]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #18863 from keszybz/cmdline-escaping
authorLennart Poettering <lennart@poettering.net>
Fri, 7 May 2021 15:29:39 +0000 (17:29 +0200)
committerGitHub <noreply@github.com>
Fri, 7 May 2021 15:29:39 +0000 (17:29 +0200)
Escape command lines properly

788 files changed:
.github/workflows/build_test.sh
.mkosi/mkosi.arch
.mkosi/mkosi.fedora
.packit.yml
README
TODO
docs/BOOT_LOADER_INTERFACE.md
docs/BOOT_LOADER_SPECIFICATION.md
docs/CONTAINER_INTERFACE.md
docs/COREDUMP_PACKAGE_METADATA.md [new file with mode: 0644]
docs/DISCOVERABLE_PARTITIONS.md
docs/ENVIRONMENT.md
docs/JOURNAL_NATIVE_PROTOCOL.md [new file with mode: 0644]
docs/PORTABLE_SERVICES.md
docs/TRANSIENT-SETTINGS.md
hwdb.d/60-autosuspend.hwdb
hwdb.d/60-keyboard.hwdb
hwdb.d/60-sensor.hwdb
hwdb.d/80-ieee1394-unit-function.hwdb [new file with mode: 0644]
hwdb.d/meson.build
hwdb.d/parse_hwdb.py
man/bootctl.xml
man/coredump.conf.xml
man/custom-entities.ent.in
man/homectl.xml
man/hostnamectl.xml
man/journald.conf.xml
man/meson.build
man/networkd.conf.xml
man/nss-myhostname.xml
man/oomd.conf.xml
man/org.freedesktop.hostname1.xml
man/org.freedesktop.login1.xml
man/org.freedesktop.portable1.xml
man/org.freedesktop.systemd1.xml
man/os-release.xml
man/portablectl.xml
man/repart.d.xml
man/resolvectl.xml
man/rules/meson.build
man/sd-id128.xml
man/sd_bus_error.xml
man/sd_bus_is_open.xml
man/sd_journal_print.xml
man/sd_login_monitor_new.xml
man/standard-specifiers.xml
man/systemd-ask-password.xml
man/systemd-boot.xml
man/systemd-coredump.xml
man/systemd-cryptenroll.xml
man/systemd-cryptsetup@.service.xml
man/systemd-detect-virt.xml
man/systemd-dissect.xml
man/systemd-firstboot.xml
man/systemd-importd.service.xml
man/systemd-journald.service.xml
man/systemd-machine-id-setup.xml
man/systemd-networkd-wait-online.service.xml
man/systemd-nspawn.xml
man/systemd-oomd.service.xml
man/systemd-repart.xml
man/systemd-resolved.service.xml
man/systemd-sysusers.xml
man/systemd-tmpfiles.xml
man/systemd-udevd.service.xml
man/systemd.dnssd.xml
man/systemd.exec.xml
man/systemd.link.xml
man/systemd.net-naming-scheme.xml
man/systemd.netdev.xml
man/systemd.network.xml
man/systemd.resource-control.xml
man/systemd.service.xml
man/systemd.special.xml
man/systemd.unit.xml
man/sysusers.d.xml
man/tmpfiles.d.xml
man/udev.conf.xml
meson.build
meson_options.txt
mkosi.build
po/ko.po
rules.d/50-udev-default.rules.in
rules.d/81-net-dhcp.rules [new file with mode: 0644]
rules.d/meson.build
shell-completion/bash/hostnamectl
shell-completion/bash/machinectl
shell-completion/bash/networkctl
shell-completion/bash/systemd-analyze
shell-completion/bash/systemd-cat
shell-completion/bash/systemd-cgls
shell-completion/bash/systemd-cgtop
shell-completion/bash/systemd-delta
shell-completion/bash/systemd-detect-virt
shell-completion/bash/systemd-id128
shell-completion/bash/systemd-nspawn
shell-completion/bash/systemd-path
shell-completion/bash/systemd-run
shell-completion/zsh/_hostnamectl
shell-completion/zsh/_localectl
shell-completion/zsh/_systemd-run
src/activate/activate.c
src/analyze/analyze.c
src/ask-password/ask-password.c
src/backlight/backlight.c
src/basic/build.h
src/basic/cgroup-util.c
src/basic/cgroup-util.h
src/basic/copy.c
src/basic/creds-util.c [new file with mode: 0644]
src/basic/creds-util.h [new file with mode: 0644]
src/basic/device-nodes.c
src/basic/efivars.c
src/basic/env-util.c
src/basic/errno-util.h
src/basic/ether-addr-util.c
src/basic/ether-addr-util.h
src/basic/fileio.c
src/basic/fileio.h
src/basic/fs-util.c
src/basic/fs-util.h
src/basic/gcrypt-util.c
src/basic/generate-af-list.sh
src/basic/generate-arphrd-list.sh
src/basic/generate-cap-list.sh
src/basic/generate-errno-list.sh
src/basic/hostname-util.h
src/basic/in-addr-util.c
src/basic/in-addr-util.h
src/basic/io-util.h
src/basic/linux/update.sh
src/basic/locale-util.c
src/basic/locale-util.h
src/basic/log.c
src/basic/log.h
src/basic/login-util.h
src/basic/meson.build
src/basic/missing_capability.h
src/basic/missing_syscall.h
src/basic/missing_syscall_def.h
src/basic/missing_syscalls.py
src/basic/mountpoint-util.c
src/basic/nss-util.h
src/basic/ordered-set.c
src/basic/ordered-set.h
src/basic/path-lookup.c
src/basic/path-util.c
src/basic/path-util.h
src/basic/proc-cmdline.c
src/basic/recovery-key.c
src/basic/selinux-util.c
src/basic/socket-util.h
src/basic/special.h
src/basic/strbuf.c
src/basic/string-util.c
src/basic/string-util.h
src/basic/syscalls-riscv64.txt [new file with mode: 0644]
src/basic/terminal-util.c
src/basic/time-util.c
src/basic/tmpfile-util.c
src/basic/unit-def.c
src/basic/unit-file.c
src/basic/unit-name.c
src/basic/unit-name.h
src/basic/user-util.c
src/basic/user-util.h
src/basic/virt.c
src/basic/virt.h
src/binfmt/binfmt.c
src/boot/bless-boot.c
src/boot/bootctl.c
src/boot/efi/boot.c
src/boot/efi/meson.build
src/boot/efi/no-undefined-symbols.sh
src/boot/efi/pe.c
src/boot/efi/stub.c
src/boot/efi/util.c
src/busctl/busctl.c
src/core/automount.c
src/core/bpf-devices.c
src/core/bpf-firewall.c
src/core/bpf-foreign.c [new file with mode: 0644]
src/core/bpf-foreign.h [new file with mode: 0644]
src/core/bpf/socket_bind/meson.build [new file with mode: 0644]
src/core/bpf/socket_bind/socket-bind-api.bpf.h [new file with mode: 0644]
src/core/bpf/socket_bind/socket-bind.bpf.c [new file with mode: 0644]
src/core/cgroup.c
src/core/cgroup.h
src/core/dbus-cgroup.c
src/core/dbus-execute.c
src/core/dbus-manager.c
src/core/dbus-manager.h
src/core/dbus-path.c
src/core/dbus-scope.c
src/core/dbus-service.c
src/core/dbus-timer.c
src/core/dbus-unit.c
src/core/dbus.c
src/core/execute.c
src/core/job.c
src/core/load-fragment-gperf.gperf.m4
src/core/load-fragment.c
src/core/load-fragment.h
src/core/main.c
src/core/manager.c
src/core/meson.build
src/core/namespace.c
src/core/namespace.h
src/core/path.c
src/core/selinux-access.c
src/core/service.c
src/core/service.h
src/core/socket-bind.c [new file with mode: 0644]
src/core/socket-bind.h [new file with mode: 0644]
src/core/system.conf.in
src/core/timer.c
src/core/unit-serialize.c
src/core/unit.c
src/core/unit.h
src/core/user.conf.in
src/coredump/coredump.c
src/coredump/coredump.conf
src/coredump/coredumpctl.c
src/coredump/stacktrace.c
src/coredump/stacktrace.h
src/cryptenroll/cryptenroll-password.c
src/cryptenroll/cryptenroll.c
src/cryptsetup/cryptsetup-fido2.c
src/cryptsetup/cryptsetup-keyfile.c
src/cryptsetup/cryptsetup-pkcs11.c
src/cryptsetup/cryptsetup.c
src/dissect/dissect.c
src/environment-d-generator/environment-d-generator.c
src/firstboot/firstboot.c
src/fstab-generator/fstab-generator.c
src/gpt-auto-generator/gpt-auto-generator.c
src/home/homectl.c
src/home/homed-bus.c
src/home/homed-home.c
src/home/homed-manager.c
src/home/homed.conf
src/home/homework-luks.c
src/home/user-record-util.c
src/hostname/hostnamectl.c
src/hostname/hostnamed.c
src/import/curl-util.c
src/import/importd.c
src/journal-remote/journal-gatewayd.c
src/journal-remote/journal-remote.c
src/journal-remote/journal-remote.conf.in
src/journal-remote/journal-upload.c
src/journal-remote/journal-upload.conf.in
src/journal/fuzz-journald-kmsg.c
src/journal/journalctl.c
src/journal/journald-kmsg.c
src/journal/journald-stream.c
src/journal/journald.conf
src/kernel-install/90-loaderentry.install
src/libsystemd-network/dhcp-internal.h
src/libsystemd-network/dhcp-network.c
src/libsystemd-network/dhcp-option.c
src/libsystemd-network/dhcp-server-internal.h
src/libsystemd-network/dhcp6-internal.h
src/libsystemd-network/dhcp6-option.c
src/libsystemd-network/fuzz-dhcp6-client.c
src/libsystemd-network/lldp-internal.h
src/libsystemd-network/lldp-neighbor.c
src/libsystemd-network/meson.build
src/libsystemd-network/ndisc-internal.h
src/libsystemd-network/ndisc-router.c
src/libsystemd-network/ndisc-router.h
src/libsystemd-network/network-common.c [new file with mode: 0644]
src/libsystemd-network/network-common.h [new file with mode: 0644]
src/libsystemd-network/network-internal.h
src/libsystemd-network/radv-internal.h
src/libsystemd-network/sd-dhcp-client.c
src/libsystemd-network/sd-dhcp-lease.c
src/libsystemd-network/sd-dhcp-server.c
src/libsystemd-network/sd-dhcp6-client.c
src/libsystemd-network/sd-dhcp6-lease.c
src/libsystemd-network/sd-ipv4acd.c
src/libsystemd-network/sd-ipv4ll.c
src/libsystemd-network/sd-lldp.c
src/libsystemd-network/sd-ndisc.c
src/libsystemd-network/sd-radv.c
src/libsystemd-network/test-dhcp-server.c
src/libsystemd-network/test-dhcp6-client.c
src/libsystemd/libsystemd.sym
src/libsystemd/meson.build
src/libsystemd/sd-bus/bus-error.c
src/libsystemd/sd-bus/sd-bus.c
src/libsystemd/sd-device/device-enumerator.c
src/libsystemd/sd-device/device-internal.h
src/libsystemd/sd-device/device-monitor.c
src/libsystemd/sd-device/device-private.c
src/libsystemd/sd-device/device-private.h
src/libsystemd/sd-device/device-util.c [new file with mode: 0644]
src/libsystemd/sd-device/device-util.h
src/libsystemd/sd-device/sd-device.c
src/libsystemd/sd-device/test-device-util.c [new file with mode: 0644]
src/libsystemd/sd-device/test-sd-device-monitor.c
src/libsystemd/sd-event/sd-event.c
src/libsystemd/sd-id128/id128-util.c
src/libsystemd/sd-id128/id128-util.h
src/libsystemd/sd-journal/compress.c
src/libsystemd/sd-journal/fsprg.c
src/libsystemd/sd-journal/generate-audit_type-list.sh
src/libsystemd/sd-journal/journal-authenticate.c
src/libsystemd/sd-journal/journal-file.c
src/libsystemd/sd-journal/journal-vacuum.c
src/libsystemd/sd-journal/sd-journal.c
src/libsystemd/sd-login/sd-login.c
src/libsystemd/sd-netlink/generic-netlink.c
src/libsystemd/sd-netlink/netlink-types.c
src/libsystemd/sd-netlink/rtnl-message.c
src/libsystemd/sd-network/network-util.c
src/libsystemd/sd-network/network-util.h
src/libsystemd/sd-network/sd-network.c
src/libudev/libudev-monitor.c
src/libudev/test-libudev.c
src/locale/keymap-util.c
src/locale/localed.c
src/login/70-uaccess.rules.m4
src/login/loginctl.c
src/login/logind-core.c
src/login/logind-dbus.c
src/login/logind-seat-dbus.c
src/login/logind-session-dbus.c
src/login/logind-session.c
src/login/logind-user-dbus.c
src/login/logind.c
src/login/logind.conf.in
src/machine-id-setup/machine-id-setup-main.c
src/machine/image-dbus.c
src/machine/machine-dbus.c
src/machine/machine.c
src/machine/machinectl.c
src/machine/machined-dbus.c
src/machine/operation.c
src/modules-load/modules-load.c
src/network/netdev/netdev-gperf.gperf
src/network/netdev/netdev.c
src/network/netdev/netdev.h
src/network/netdev/tuntap.c
src/network/netdev/wireguard.c
src/network/networkctl.c
src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-can.c
src/network/networkd-conf.c
src/network/networkd-conf.h
src/network/networkd-dhcp-common.c
src/network/networkd-dhcp-common.h
src/network/networkd-dhcp-server-bus.c
src/network/networkd-dhcp-server.c
src/network/networkd-dhcp-server.h
src/network/networkd-dhcp4.c
src/network/networkd-dhcp4.h
src/network/networkd-dhcp6.c
src/network/networkd-dhcp6.h
src/network/networkd-gperf.gperf
src/network/networkd-ipv4ll.c
src/network/networkd-link-bus.c
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-lldp-rx.c
src/network/networkd-lldp-tx.c
src/network/networkd-manager-bus.c
src/network/networkd-manager.c
src/network/networkd-manager.h
src/network/networkd-mdb.c
src/network/networkd-ndisc.c
src/network/networkd-ndisc.h
src/network/networkd-neighbor.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-nexthop.c
src/network/networkd-radv.c
src/network/networkd-radv.h
src/network/networkd-route.c
src/network/networkd-route.h
src/network/networkd-routing-policy-rule.c
src/network/networkd-state-file.c
src/network/networkd-util.c
src/network/networkd-util.h
src/network/networkd.conf
src/network/wait-online/link.c
src/network/wait-online/link.h
src/network/wait-online/manager.c
src/network/wait-online/manager.h
src/network/wait-online/wait-online.c
src/notify/notify.c
src/nspawn/nspawn-settings.h
src/nspawn/nspawn.c
src/nss-myhostname/nss-myhostname.c
src/nss-resolve/nss-resolve.c
src/nss-systemd/nss-systemd.c
src/nss-systemd/userdb-glue.c
src/oom/oomd-manager.c
src/oom/oomd-manager.h
src/oom/oomd-util.c
src/oom/oomd-util.h
src/oom/oomd.c
src/oom/oomd.conf
src/oom/test-oomd-util.c
src/partition/repart.c
src/partition/test-repart.sh
src/portable/portable.c
src/portable/portable.h
src/portable/portablectl.c
src/portable/portabled-bus.c
src/portable/portabled-image-bus.c
src/portable/portabled-operation.c
src/pstore/pstore.conf
src/random-seed/random-seed.c
src/resolve/resolved-bus.c
src/resolve/resolved-dns-answer.c
src/resolve/resolved-dns-answer.h
src/resolve/resolved-dns-cache.c
src/resolve/resolved-dns-dnssec.c
src/resolve/resolved-dns-packet.c
src/resolve/resolved-dns-packet.h
src/resolve/resolved-dns-query.c
src/resolve/resolved-dns-question.c
src/resolve/resolved-dns-question.h
src/resolve/resolved-dns-rr.h
src/resolve/resolved-dns-scope.c
src/resolve/resolved-dns-stream.c
src/resolve/resolved-dns-stub.c
src/resolve/resolved-dns-synthesize.c
src/resolve/resolved-dns-transaction.c
src/resolve/resolved-dns-transaction.h
src/resolve/resolved-dns-trust-anchor.c
src/resolve/resolved-link-bus.c
src/resolve/resolved-mdns.c
src/resolve/resolved.conf.in
src/rfkill/rfkill.c
src/rpm/macros.systemd.in
src/shared/acl-util.c
src/shared/ask-password-api.c
src/shared/ask-password-api.h
src/shared/base-filesystem.c
src/shared/bpf-link.c [new file with mode: 0644]
src/shared/bpf-link.h [new file with mode: 0644]
src/shared/bpf-program.c
src/shared/bpf-program.h
src/shared/bus-message-util.c
src/shared/bus-print-properties.c
src/shared/bus-print-properties.h
src/shared/bus-unit-util.c
src/shared/bus-wait-for-jobs.c
src/shared/clean-ipc.c
src/shared/clock-util.c
src/shared/condition.c
src/shared/condition.h
src/shared/conf-parser.c
src/shared/cryptsetup-util.h
src/shared/discover-image.c
src/shared/dissect-image.c
src/shared/dissect-image.h
src/shared/firewall-util-iptables.c
src/shared/firewall-util-private.h
src/shared/format-table.c
src/shared/generate-ip-protocol-list.sh
src/shared/generator.c
src/shared/gpt.c
src/shared/gpt.h
src/shared/install.c
src/shared/install.h
src/shared/libfido2-util.c
src/shared/local-addresses.c
src/shared/local-addresses.h
src/shared/log-link.h
src/shared/logs-show.c
src/shared/loop-util.c
src/shared/loop-util.h
src/shared/machine-id-setup.c
src/shared/meson.build
src/shared/module-util.c
src/shared/mount-util.c
src/shared/mount-util.h
src/shared/net-condition.c
src/shared/netif-naming-scheme.c
src/shared/netif-naming-scheme.h
src/shared/openssl-util.c
src/shared/pe-header.h
src/shared/pkcs11-util.c
src/shared/pkcs11-util.h
src/shared/pretty-print.c
src/shared/qrcode-util.c
src/shared/sleep-config.c
src/shared/specifier.c
src/shared/specifier.h
src/shared/tpm2-util.c
src/shared/userdb.c
src/shared/varlink.c
src/shared/wifi-util.c
src/shutdown/shutdown.c
src/sleep/sleep.c
src/sleep/sleep.conf
src/stdio-bridge/stdio-bridge.c
src/sysctl/sysctl.c
src/sysext/sysext.c
src/systemctl/systemctl-compat-halt.c
src/systemctl/systemctl-edit.c
src/systemctl/systemctl-list-units.c
src/systemctl/systemctl-logind.c
src/systemctl/systemctl-show.c
src/systemctl/systemctl-start-special.c
src/systemctl/systemctl-start-unit.c
src/systemctl/systemctl.c
src/systemctl/systemctl.h
src/systemd/sd-bus-vtable.h
src/systemd/sd-device.h
src/systemd/sd-dhcp-client.h
src/systemd/sd-dhcp-lease.h
src/systemd/sd-dhcp-server.h
src/systemd/sd-dhcp6-client.h
src/systemd/sd-id128.h
src/systemd/sd-ipv4acd.h
src/systemd/sd-ipv4ll.h
src/systemd/sd-lldp.h
src/systemd/sd-login.h
src/systemd/sd-ndisc.h
src/systemd/sd-network.h
src/systemd/sd-radv.h
src/sysusers/sysusers.c
src/sysv-generator/sysv-generator.c
src/test/meson.build
src/test/nss-test-util.c [new file with mode: 0644]
src/test/nss-test-util.h [new file with mode: 0644]
src/test/test-bpf-foreign-programs.c [new file with mode: 0644]
src/test/test-capability.c
src/test/test-cgroup-mask.c
src/test/test-cgroup-setup.c
src/test/test-cgroup-util.c
src/test/test-condition.c
src/test/test-extract-word.c
src/test/test-fileio.c
src/test/test-firewall-util.c
src/test/test-id128.c
src/test/test-install-root.c
src/test/test-local-addresses.c
src/test/test-loop-block.c
src/test/test-mount-util.c
src/test/test-namespace.c
src/test/test-ns.c
src/test/test-nss-hosts.c [moved from src/test/test-nss.c with 87% similarity]
src/test/test-nss-users.c [new file with mode: 0644]
src/test/test-ordered-set.c
src/test/test-path-util.c
src/test/test-random-util.c
src/test/test-sigbus.c
src/test/test-socket-bind.c [new file with mode: 0644]
src/test/test-string-util.c
src/test/test-udev.c
src/test/test-unit-file.c
src/test/test-unit-name.c
src/test/test-unit-serialize.c [new file with mode: 0644]
src/timedate/timedatectl.c
src/timedate/timedated.c
src/timesync/timesyncd.conf.in
src/timesync/wait-sync.c
src/tmpfiles/tmpfiles.c
src/tty-ask-password-agent/tty-ask-password-agent.c
src/udev/cdrom_id/cdrom_id.c
src/udev/dmi_memory_id/dmi_memory_id.c
src/udev/generate-keyboard-keys-gperf.sh
src/udev/generate-keyboard-keys-list.sh
src/udev/net/link-config.c
src/udev/scsi_id/scsi_id.c
src/udev/udev-builtin-net_id.c
src/udev/udev-event.c
src/udev/udev-event.h
src/udev/udev-node.c
src/udev/udev-rules.c
src/udev/udev-watch.c
src/udev/udev-watch.h
src/udev/udevadm-info.c
src/udev/udevadm-test.c
src/udev/udevadm.h
src/udev/udevd.c
src/update-utmp/update-utmp.c
src/userdb/userdbd-manager.c
src/vconsole/vconsole-setup.c
src/xdg-autostart-generator/xdg-autostart-service.c
test/TEST-01-BASIC/test.sh
test/TEST-02-UNITTESTS/test.sh
test/TEST-03-JOBS/test.sh
test/TEST-04-JOURNAL/test.sh
test/TEST-05-RLIMITS/test.sh
test/TEST-06-SELINUX/test.sh
test/TEST-07-ISSUE-1981/test.sh
test/TEST-08-ISSUE-2730/test.sh
test/TEST-09-ISSUE-2691/test.sh
test/TEST-10-ISSUE-2467/test.sh
test/TEST-11-ISSUE-3166/test.sh
test/TEST-12-ISSUE-3171/test.sh
test/TEST-13-NSPAWN-SMOKE/test.sh
test/TEST-14-MACHINE-ID/test.sh
test/TEST-15-DROPIN/test.sh
test/TEST-16-EXTEND-TIMEOUT/test.sh
test/TEST-17-UDEV/test.sh
test/TEST-18-FAILUREACTION/test.sh
test/TEST-19-DELEGATE/test.sh
test/TEST-20-MAINPIDGAMES/test.sh
test/TEST-22-TMPFILES/test.sh
test/TEST-23-TYPE-EXEC/test.sh
test/TEST-24-CRYPTSETUP/test.sh
test/TEST-25-IMPORT/test.sh
test/TEST-26-SETENV/test.sh
test/TEST-27-STDOUTFILE/test.sh
test/TEST-28-PERCENTJ-WANTEDBY/test.sh
test/TEST-29-PORTABLE/test.sh
test/TEST-30-ONCLOCKCHANGE/test.sh
test/TEST-31-DEVICE-ENUMERATION/test.sh
test/TEST-32-OOMPOLICY/test.sh
test/TEST-33-CLEAN-UNIT/test.sh
test/TEST-34-DYNAMICUSERMIGRATE/test.sh
test/TEST-36-NUMAPOLICY/test.sh
test/TEST-37-RUNTIMEDIRECTORYPRESERVE/test.sh
test/TEST-38-FREEZER/test.sh
test/TEST-39-EXECRELOAD/test.sh
test/TEST-40-EXEC-COMMAND-EX/test.sh
test/TEST-41-ONESHOT-RESTART/test.sh
test/TEST-42-EXECSTOPPOST/test.sh
test/TEST-43-PRIVATEUSER-UNPRIV/test.sh
test/TEST-44-LOG-NAMESPACE/test.sh
test/TEST-46-HOMED/test.sh
test/TEST-47-ISSUE-14566/test.sh
test/TEST-48-START-STOP-NO-RELOAD/test.sh
test/TEST-49-RUNTIME-BIND-PATHS/test.sh
test/TEST-50-DISSECT/deny-list-ubuntu-ci [deleted file]
test/TEST-50-DISSECT/test.sh
test/TEST-51-ISSUE-16115/test.sh
test/TEST-52-HONORFIRSTSHUTDOWN/Makefile [changed from file to symlink]
test/TEST-52-HONORFIRSTSHUTDOWN/fini.sh [deleted file]
test/TEST-52-HONORFIRSTSHUTDOWN/test.sh
test/TEST-53-ISSUE-16347/test.sh
test/TEST-54-CREDS/test.sh
test/TEST-55-OOMD/test.sh
test/TEST-56-EXIT-TYPE/Makefile [new symlink]
test/TEST-56-EXIT-TYPE/test.sh [new file with mode: 0755]
test/TEST-58-REPART/Makefile [new symlink]
test/TEST-58-REPART/test.sh [new file with mode: 0755]
test/TEST-59-RELOADING-RESTART/Makefile [new symlink]
test/TEST-59-RELOADING-RESTART/test.sh [new file with mode: 0755]
test/fuzz/fuzz-journald-kmsg/oss-fuzz-33881 [new file with mode: 0644]
test/fuzz/fuzz-netdev-parser/directives.netdev
test/fuzz/fuzz-network-parser/directives.network
test/fuzz/fuzz-unit-file/directives-all.service [new file with mode: 0644]
test/fuzz/fuzz-unit-file/directives.automount [new file with mode: 0644]
test/fuzz/fuzz-unit-file/directives.mount [new file with mode: 0644]
test/fuzz/fuzz-unit-file/directives.path [new file with mode: 0644]
test/fuzz/fuzz-unit-file/directives.scope
test/fuzz/fuzz-unit-file/directives.service
test/fuzz/fuzz-unit-file/directives.slice [new file with mode: 0644]
test/fuzz/fuzz-unit-file/directives.socket [new file with mode: 0644]
test/fuzz/fuzz-unit-file/directives.swap [new file with mode: 0644]
test/fuzz/fuzz-unit-file/directives.timer [new file with mode: 0644]
test/fuzz/fuzz-unit-file/github-19178 [new file with mode: 0644]
test/fuzz/fuzz-unit-file/oss-fuzz-32991 [new file with mode: 0644]
test/fuzz/fuzz-unit-file/oss-fuzz-33270 [new file with mode: 0644]
test/fuzz/fuzz-unit-file/oss-fuzz-33876 [new file with mode: 0644]
test/hwdb-test.sh
test/meson.build
test/test-execute/exec-standardoutput-append.service
test/test-execute/exec-standardoutput-file.service
test/test-execute/exec-standardoutput-truncate.service
test/test-functions
test/test-network/conf/agent-client-peer.network [new file with mode: 0644]
test/test-network/conf/agent-client.network [new file with mode: 0644]
test/test-network/conf/agent-server-peer.network [new file with mode: 0644]
test/test-network/conf/agent-server.network [new file with mode: 0644]
test/test-network/conf/agent-veth-client.netdev [new file with mode: 0644]
test/test-network/conf/agent-veth-server.netdev [new file with mode: 0644]
test/test-network/conf/dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network [new file with mode: 0644]
test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-dns-and-ntp-routes-False.conf [moved from test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-dns-routes-False.conf with 61% similarity]
test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-dns-and-ntp-routes-True.conf [moved from test/test-network/conf/dhcp-client-ipv4-use-routes-use-gateway.network.d/use-dns-routes-True.conf with 60% similarity]
test/test-network/conf/dhcp-server-timezone-router.network
test/test-network/conf/dhcp-server-with-ipv6-prefix.network [new file with mode: 0644]
test/test-network/conf/ipv6-prefix-with-delay.network [new file with mode: 0644]
test/test-network/conf/ipv6ra-prefix-client-with-static-ipv4-address.network [new file with mode: 0644]
test/test-network/conf/state-file-tests.network
test/test-network/systemd-networkd-tests.py
test/testsuite-04.units/silent-success.service [new file with mode: 0644]
test/testsuite-28.units/specifier-j-wants.service
test/testsuite-52.units/test-honor-first-shutdown.service [moved from test/units/test-honor-first-shutdown.service with 72% similarity]
test/testsuite-52.units/test-honor-first-shutdown.sh [moved from test/units/test-honor-first-shutdown.sh with 100% similarity]
test/units/testsuite-01.service
test/units/testsuite-02.sh
test/units/testsuite-03.sh
test/units/testsuite-04.sh
test/units/testsuite-05.sh
test/units/testsuite-06.sh
test/units/testsuite-07.sh
test/units/testsuite-11.sh
test/units/testsuite-12.sh
test/units/testsuite-13.sh
test/units/testsuite-14.sh
test/units/testsuite-15.sh
test/units/testsuite-16.sh
test/units/testsuite-17.01.sh
test/units/testsuite-17.02.sh
test/units/testsuite-17.03.sh
test/units/testsuite-17.04.sh
test/units/testsuite-17.05.sh
test/units/testsuite-17.06.sh [new file with mode: 0755]
test/units/testsuite-17.sh
test/units/testsuite-18.sh
test/units/testsuite-19.sh
test/units/testsuite-20.sh
test/units/testsuite-22.01.sh
test/units/testsuite-22.02.sh
test/units/testsuite-22.03.sh
test/units/testsuite-22.04.sh
test/units/testsuite-22.05.sh
test/units/testsuite-22.06.sh
test/units/testsuite-22.07.sh
test/units/testsuite-22.08.sh
test/units/testsuite-22.09.sh
test/units/testsuite-22.10.sh
test/units/testsuite-22.11.sh [new file with mode: 0755]
test/units/testsuite-22.sh
test/units/testsuite-23.sh
test/units/testsuite-25.sh
test/units/testsuite-26.sh
test/units/testsuite-27.sh
test/units/testsuite-29.sh
test/units/testsuite-30.sh
test/units/testsuite-31.sh
test/units/testsuite-32.sh
test/units/testsuite-33.sh
test/units/testsuite-34.sh
test/units/testsuite-36.sh
test/units/testsuite-37.sh
test/units/testsuite-38.sh
test/units/testsuite-39.sh
test/units/testsuite-40.sh
test/units/testsuite-41.sh
test/units/testsuite-42.sh
test/units/testsuite-43.sh
test/units/testsuite-44.sh
test/units/testsuite-46.sh
test/units/testsuite-47-repro.sh
test/units/testsuite-47.sh
test/units/testsuite-48.sh
test/units/testsuite-49.sh
test/units/testsuite-50.sh
test/units/testsuite-51.sh
test/units/testsuite-52.service [moved from test/testsuite-52.units/testsuite-52.service with 51% similarity]
test/units/testsuite-52.sh [moved from test/testsuite-52.units/testsuite-52.sh with 52% similarity]
test/units/testsuite-53.sh
test/units/testsuite-54.sh
test/units/testsuite-55-slowgrowth.sh
test/units/testsuite-55.sh
test/units/testsuite-56.service [new file with mode: 0644]
test/units/testsuite-56.sh [new file with mode: 0755]
test/units/testsuite-58.service [new file with mode: 0644]
test/units/testsuite-58.sh [new file with mode: 0755]
test/units/testsuite-59.service [new file with mode: 0644]
test/units/testsuite-59.sh [new file with mode: 0755]
tools/add-git-hook.sh
tools/build-bpf-skel.py [new file with mode: 0755]
tools/check-api-docs.sh
tools/check-directives.sh
tools/check-help.sh
tools/find-build-dir.sh
tools/find-double-newline.sh
tools/find-tabs.sh
tools/meson-apply-m4.sh
tools/meson-make-symlink.sh
tools/meson-vcs-tag.sh
tools/update-hwdb-autosuspend.sh
tools/update-hwdb.sh
tools/update-syscall-tables.sh
units/initrd-fs.target
units/initrd-usr-fs.target [new file with mode: 0644]
units/initrd.target
units/meson.build
units/system-systemd\x2dcryptsetup.slice
units/systemd-coredump.socket
units/systemd-firstboot.service
units/systemd-networkd.socket
units/systemd-repart.service.in
units/systemd-sysusers.service
units/systemd-volatile-root.service.in

index 8ad7e767909d99cebbdfbd0c9ce9207bd79a62a0..8471ea181ea672c17c1ba51bc78fb457ebd34d4e 100755 (executable)
@@ -13,6 +13,7 @@ ARGS=(
     "--optimization=3 -Db_lto=true"
     "--optimization=3 -Db_lto=false"
     "--optimization=3 -Ddns-over-tls=openssl"
+    "--optimization=3 -Dfexecve=true -Dstandalone-binaries=true -Dstatic-libsystemd=true -Dstatic-libudev=true"
     "-Db_ndebug=true"
 )
 PACKAGES=(
index 6192c191045fad737ed5b297eecd0d85233c110b..867a869e1afc015abcb0fd682ee1387c8209dedf 100644 (file)
@@ -42,6 +42,7 @@ BuildPackages=
         python
         python-lxml
         qrencode
+        rsync
         xz
         zstd
 
index e24507ad106f5984a4a246363d82f58e1bfa2d19..3f000201454bf5f28766a92d8d80c857c7dc9e7f 100644 (file)
@@ -5,7 +5,7 @@
 
 [Distribution]
 Distribution=fedora
-Release=33
+Release=34
 
 [Packages]
 BuildPackages=
@@ -52,8 +52,6 @@ BuildPackages=
         p11-kit-devel
         pam-devel
         pcre2-devel
-        perl(IPC::SysV)
-        perl(Time::HiRes)
         pkgconfig
         python3-devel
         python3-lxml
index 75f9d3abc9c3eebf93d4611a0a673e4f6cd57eab..4545e30e0867d81889333b473bcfba427e557ca9 100644 (file)
@@ -18,6 +18,8 @@ actions:
   post-upstream-clone:
     # Use the Fedora Rawhide specfile
     - "git clone https://src.fedoraproject.org/rpms/systemd .packit_rpm --depth=1"
+    # Drop the "sources" file so rebase-helper doesn't think we're a dist-git
+    - "rm -fv .packit_rpm/sources"
     # Drop backported patches from the specfile, but keep the downstream-only ones
     # - Patch0000-0499: backported patches from upstream
     # - Patch0500-9999: downstream-only patches
diff --git a/README b/README
index e0b7fbf8bf72e0af8bd5ad1465caa7a86b6b77fe..955dc11e1b0f06256e4050cc88fef78fe8f4c868 100644 (file)
--- a/README
+++ b/README
@@ -35,6 +35,10 @@ LICENSE:
 REQUIREMENTS:
         Linux kernel >= 3.13
         Linux kernel >= 4.2 for unified cgroup hierarchy support
+        Linux kernel >= 4.10 for cgroup-bpf egress and ingress hooks
+        Linux kernel >= 4.15 for cgroup-bpf device hook
+        Linux kernel >= 4.17 for cgroup-bpf socket address hooks
+        Linux kernel >= 5.3 for bounded-loops in BPF program
         Linux kernel >= 5.4 for signed Verity images support
 
         Kernel Config Options:
@@ -95,8 +99,20 @@ REQUIREMENTS:
         Required for CPUQuota= in resource control unit settings
           CONFIG_CFS_BANDWIDTH
 
-        Required for IPAddressDeny= and IPAddressAllow= in resource control
+        Required for IPAddressDeny=, IPAddressAllow=, IPIngressFilterPath=,
+        IPEgressFilterPath= in resource control unit settings
         unit settings
+          CONFIG_BPF
+          CONFIG_BPF_SYSCALL
+          CONFIG_BPF_JIT
+          CONFIG_HAVE_EBPF_JIT
+          CONFIG_CGROUP_BPF
+
+        Required for SocketBind{Allow|Deny}= in resource control unit settings
+          CONFIG_BPF
+          CONFIG_BPF_SYSCALL
+          CONFIG_BPF_JIT
+          CONFIG_HAVE_EBPF_JIT
           CONFIG_CGROUP_BPF
 
         For UEFI systems:
@@ -154,6 +170,7 @@ REQUIREMENTS:
         libcryptsetup (optional), >= 2.3.0 required for signed Verity images support
         libaudit (optional)
         libacl (optional)
+        libbpf >= 0.2.0 (optional)
         libfdisk >= 2.33 (from util-linux) (optional)
         libselinux (optional)
         liblzma (optional)
@@ -178,6 +195,8 @@ REQUIREMENTS:
         meson >= 0.46 (>= 0.49 is required to build position-independent executables)
         ninja
         gcc, awk, sed, grep, m4, and similar tools
+        clang >= 10.0, llvm >= 10.0 (optional, required to build BPF programs
+                from source code in C)
 
         During runtime, you need the following additional
         dependencies:
diff --git a/TODO b/TODO
index 451d9f34c0bd9547f0940ea427050a19b0eaa912..d2de66e9fa1bc869642148d5495408857f2f3a34 100644 (file)
--- a/TODO
+++ b/TODO
@@ -22,6 +22,44 @@ Janitorial Clean-ups:
 
 Features:
 
+* ability to insert trusted configuration and secrets into the boot parameters
+  of a kernel booting in a VM or on baremetal some way, via TPM
+  protection. idea:
+  1. pass via /proc/bootconfig
+  2. for secrets: put secrets in node of /proc/bootconfig, decrypt them via
+     TPM early on in PID 1, put them in $CREDENTIAL_PATH logic
+  3. for config: put signed data in node /proc/booconfig, validate via TPM
+     early on in PID 1, put data into /run/bootconfig/ as individual files
+  4. boot loader/stub should pick these up automatically from the boot loader
+     file systems
+
+* journald: support RFC3164 fully for the incoming syslog transport, see
+  https://github.com/systemd/systemd/issues/19251#issuecomment-816601955
+
+* nspawn: support uid mapping bind mounts, as defined available in kernel 5.12,
+  for all our disk image needs
+
+* homed: if kernel 5.12 uid mapping mounts exist, use that instead of recursive
+  chowns.
+
+* cryptsetup: tweak tpm2-device=auto logic, abort quickly if firmware tells us
+  there isn't any TPM2 device anyway. that way, we'll wait for the TPM2 device
+  to show up only if registered in LUKS header + the firmware suggests there is
+  a device worth waiting for.
+
+* systemd-sysext: optionally, run it in initrd already, before transitioning
+  into host, to open up possibility for services shipped like that.
+
+* add a new switch --auto-definitions=yes/no or so to systemd-repart. If
+  specified, synthesize a definition automatically if we can: enlarge last
+  partition on disk, but only if it is marked for growing and not read-only.
+
+* add a switch to homectl (maybe called --first-boot) where it will check if
+  any non-system users exist, and if not prompts interactively for basic user
+  info, mimicking systemd-firstboot. Then, place this in a service that runs
+  after systemd-homed, but before gdm and friends, as a simple, barebones
+  fallback logic to get a regular user created on uninitialized systems.
+
 * maybe add a tool that displays most recent journal logs as QR code to scan
   off screen and run it automatically on boot failures, emergency logs and
   such. Use DRM APIs directly, see
@@ -36,13 +74,23 @@ Features:
 * systemd-repart: read LUKS encryption key from $CREDENTIALS_PATH
 
 * introduce /dev/disk/root/* symlinks that allow referencing partitions on the
-  disk the rootfs is on in a reasonably secure way.
+  disk the rootfs is on in a reasonably secure way. (or maybe: add
+  /dev/gpt-auto-{home,srv,boot,…} similar in style to /dev/gpt-auto-root as we
+  already have it.
 
 * systemd-repart: add a switch to factory reset the partition table without
   immediately applying the new configuration again. i.e. --factory-reset=leave
   or so. (this is useful to factory reset an image, then putting it into
   another machine, ensuring that luks key is generated on new machine, not old)
 
+* systemd-repart: support setting up dm-integrity with HMAC
+
+* systemd-repart: maybe remove half-initialized image on failure. It fails
+  if the output file exists, so a repeated invocation will usually fail if
+  something goes wrong on the way.
+
+* systemd-repart: drop pager mode on normal operation?
+
 * move logind udev rules to top-level rule.d/ directory
 
 * move multiseat vid/pid matches from logind udev rule to hwdb
@@ -61,11 +109,6 @@ Features:
   With all that in place if nspawn host and container payload are up-to-date
   enough we have a very simple way to make host users available in containers.
 
-* systemd-sysusers: pick up passwords from credentials logic, so that users can
-  easily set root user pw. enable cred inheriting for root user from PID 1, so
-  that for containers we can configure the root pw automatically via nspawn's
-  --set-credential= switch. (Also do this for systemd-firstboot)
-
 * whenever we receive fds via SCM_RIGHTS make sure none got dropped due to the
   reception limit the kernel silently enforces.
 
@@ -179,22 +222,9 @@ Features:
 
 * systemd-analyze netif that explains predictable interface (or networkctl)
 
-* port selinux code from mallinfo() to mallinfo2() once added to glibc
-
 * Add service setting to run a service within the specified VRF. i.e. do the
   equivalent of "ip vrf exec".
 
-* export action of device object on sd-device, so that monitor becomes useful
-
-* add root=tmpfs that mounts a tmpfs to /sysroot (to be used in combination
-  with usr=…, for a similar effect as systemd.volatile=yes but without the
-  "hide-out" effect). Also, add root=gpt-auto-late support or so, that is like
-  root=gpt-auto but initially mounts a tmpfs to /sysroot, and then revisits
-  later after systemd-repart ran. Usecase: let's ship images with only /usr
-  partition, then on first boot create the root partition. In this case we want
-  to read the repart data from /usr before the root partition exists. Add
-  usr=gpt-auto that automatically finds a /usr partition.
-
 * change SwitchRoot() implementation in PID 1 to use pivot_root(".", "."), as
   documented in the pivot_root(2) man page, so that we can drop the /oldroot
   temporary dir.
@@ -212,8 +242,6 @@ Features:
 * when main nspawn supervisor process gets suspended due to SIGSTOP/SIGTTOU or
   so, freeze the payload too.
 
-* repart: support setting up dm-integrity with HMAC
-
 * add /etc/integritytab, to support dm-integrity setups. In particular those
   with HMAC as hash function, so that we can have a protected /home without
   encryption (leaving encryption to the individual dirs/homed).
@@ -321,15 +349,6 @@ Features:
 * busctl: maybe expose a verb "ping" for pinging a dbus service to see if it
   exists and responds.
 
-* when systemd-nspawn and suchlike dissect an OS image, and there are multiple
-  root partitions, do an strverscmp() on the partition label and boot
-  first. That is inspired how sd-boot figures out which kernel to boot, and
-  thus allows defining OS images which can be A/B updated and we default to the
-  newest version automatically, both in nspawn and in sd-boot
-
-* systemd-gpt-auto should probably set x-systemd.growfs on the mounts it
-  creates
-
 * bootctl:
   - teach it to prepare an ESP wholesale, i.e. with mkfs.vfat invocation
   - teach it to copy in unified kernel images and maybe type #1 boot loader spec entries from host
@@ -380,8 +399,6 @@ Features:
 * systemd-repart: allow sizing partitions as factor of available RAM, so that
   we can reasonably size swap partitions for hibernation.
 
-* systemd-repart: allow managing the gpt read-only partition flag + auto-mount flag
-
 * systemd-repart: allow boolean option that ensures that if existing partition
   doesn't exist within the configured size bounds the whole command fails. This
   is useful to implement ESP vs. XBOOTLDR schemes in installers: have one set
@@ -808,10 +825,6 @@ Features:
   "systemd-gdb" for attaching to the start-up of any system service in its
   natural habitat.
 
-* gpt-auto logic: related to the above, maybe support a "secondary" root
-  partition, that is mounted to / and is writable, and where the actual root's
-  /usr is mounted into.
-
 * gpt-auto logic: support encrypted swap, add kernel cmdline option to force it, and honour a gpt bit about it, plus maybe a configuration file
 
 * drop nss-myhostname in favour of nss-resolve?
@@ -848,9 +861,6 @@ Features:
 
 * journalctl: make sure -f ends when the container indicated by -M terminates
 
-* mount: automatically search for "main" partition of an image has multiple
-  partitions
-
 * in nss-systemd, if we run inside of RootDirectory= with PrivateUsers= set,
   find a way to map the User=/Group= of the service to the right name. This way
   a user/group for a service only has to exist on the host for the right
index 15a575da53131e0ba23d9ffff30fdabee49eb1d4..be3b6e401de7bdc36c9afdb67c768db4746390af 100644 (file)
@@ -130,7 +130,7 @@ names for them in UIs.
    discovered Windows installation might have the identifier `auto-windows` or
    `auto-windows-10` or so.).
 
-4. Similar, boot menu entries referring to Apple MacOS X installations should
+4. Similar, boot menu entries referring to Apple macOS installations should
    use the identifier `osx` or one that is prefixed with `osx-`. If such an
    entry is automatically discovered by the boot loader use `auto-osx` as
    identifier, or `auto-osx-` as prefix for the identifier, see above.
index 290977142cc6055acb47a0e83f577e926bf7c362..e0ac90bb9f96ae8211a154cef2b845e9ebc7dcc8 100644 (file)
@@ -208,7 +208,7 @@ On EFI, any such images shall be added to the list of valid boot entries.
 
 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).
+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.
 
index 980fce3968942f16056d6c49482cf8c92caeb7b5..ff458bd770ab37091fe339be3ce13ee9014e8872 100644 (file)
@@ -140,7 +140,7 @@ manager, please consider supporting the following interfaces.
    `$CREDENTIALS_DIRECTORY` environment variable. If the container managers
    does this, the credentials passed to the service manager can be propagated
    to services via `LoadCredential=` (see ...). The container manager can
-   choose any path, but `/run/host/credentials` is recommended."
+   choose any path, but `/run/host/credentials` is recommended.
 
 ## Advanced Integration
 
@@ -329,6 +329,19 @@ care should be taken to avoid naming conflicts. `systemd` (and in particular
    sub-directories of `/sys/` writable, but make sure to leave the root of
    `/sys/` read-only.)
 
+8. Do not pass the `CAP_AUDIT_CONTROL`, `CAP_AUDIT_READ`, `CAP_AUDIT_WRITE`
+   capabilities to the container, in particular not to those making use of user
+   namespaces. The kernel's audit subsystem is still not virtualized for
+   containers, and passing these credentials is pointless hence, given the
+   actual attempt to make use of the audit subsystem will fail. Note that
+   systemd's audit support is partially conditioned on these capabilities, thus
+   by dropping them you ensure that you get an entirely clean boot, as systemd
+   will make no attempt to use it. If you pass the capabilities to the payload
+   systemd will assume that audit is available and works, and some components
+   will subsequently fail in various ways. Note that once the kernel learnt
+   native support for container-virtualized audit, adding the capability to the
+   container description will automatically make the container payload use it.
+
 ## Fully Unprivileged Container Payload
 
 First things first, to make this clear: Linux containers are not a security
diff --git a/docs/COREDUMP_PACKAGE_METADATA.md b/docs/COREDUMP_PACKAGE_METADATA.md
new file mode 100644 (file)
index 0000000..f27f835
--- /dev/null
@@ -0,0 +1,125 @@
+---
+title: Package Metadata for Core Files
+category: Interfaces
+layout: default
+---
+
+# Package Metadata for Core Files
+
+*Intended audience: hackers working on userspace subsystems that create ELF binaries
+or parse ELF core files.*
+
+## Motivation
+
+ELF binaries get stamped with a unique, build-time generated hex string identifier called
+`build-id`, [which gets embedded as an ELF note called `.note.gnu.build-id`](https://fedoraproject.org/wiki/Releases/FeatureBuildId).
+In most cases, this allows to associate a stripped binary with its debugging information.
+It is used, for example, to dynamically fetch DWARF symbols from a debuginfo server, or
+to query the local package manager and find out the package metadata or, again, the DWARF
+symbols or program sources.
+
+However, this usage of the `build-id` requires either local metadata, usually set up by
+the package manager, or access to a remote server over the network. Both of those might
+be unavailable or forbidden.
+
+Thus it becomes desirable to add additional metadata to a binary at build time, so that
+`systemd-coredump` and other services analyzing core files are able to extract said
+metadata simply from the core file itself, without external dependencies.
+
+## Implementation
+
+This document will attempt to define a common metadata format specification, so that
+multiple implementers might use it when building packages, or core file analyzers, and
+so on.
+
+The metadata will be embedded in a single, new ELF header section, in a key-value JSON
+format. Implementers working on parsing core files should not assume a specific list of
+keys, but parse anything that is included in the section.
+Implementers working on build tools should strive to use the same key names, for
+consistency. The most common will be listed here. When corresponding to the content of
+os-release, the values should match, again for consistency.
+
+If available, the metadata should also include the debuginfod server URL that can provide
+the original executable, debuginfo and sources, to further facilitate debugging.
+
+* Section header
+
+```
+SECTION: `.note.package`
+node-id: `0xcafe1a7e`
+Owner: `FDO` (FreeDesktop.org)
+Value: a JSON string with the structure described below
+```
+
+* JSON payload
+
+```json
+{
+     "type":"rpm",          # this provides a namespace for the package+package-version fields
+     "os":"fedora",
+     "osVersion":"33",
+     "name":"coreutils",
+     "version": "4711.0815.fc13.arm32",
+     "osCpe": "cpe:/o:fedoraproject:fedora:33",          # A CPE name for the operating system, `CPE_NAME` from os-release is a good default
+     "debugInfoUrl": "https://debuginfod.fedoraproject.org/"
+}
+```
+
+A reference implementations of a [build-time tool is provided](https://github.com/systemd/package-notes)
+and can be used to generate a linker script, which can then be used at build time via
+```LDFLAGS="-Wl,-T,/path/to/generated/script"``` to include the note in the binary.
+
+Generator:
+```console
+$ ./generate-package-notes.py --rpm systemd-248~rc2-1.fc34
+SECTIONS
+{
+    .note.package : ALIGN(4) {
+        BYTE(0x04) BYTE(0x00) BYTE(0x00) BYTE(0x00) /* Length of Owner including NUL */
+        BYTE(0x64) BYTE(0x00) BYTE(0x00) BYTE(0x00) /* Length of Value including NUL */
+        BYTE(0x7e) BYTE(0x1a) BYTE(0xfe) BYTE(0xca) /* Note ID */
+        BYTE(0x46) BYTE(0x44) BYTE(0x4f) BYTE(0x00) /* Owner: 'FDO\x00' */
+        BYTE(0x7b) BYTE(0x22) BYTE(0x74) BYTE(0x79) /* Value: '{"type":"rpm","name":"systemd","version":"248~rc2-1.fc34","osCpe":"cpe:/o:fedoraproject:fedora:33"}\x00' */
+        BYTE(0x70) BYTE(0x65) BYTE(0x22) BYTE(0x3a)
+        BYTE(0x22) BYTE(0x72) BYTE(0x70) BYTE(0x6d)
+        BYTE(0x22) BYTE(0x2c) BYTE(0x22) BYTE(0x6e)
+        BYTE(0x61) BYTE(0x6d) BYTE(0x65) BYTE(0x22)
+        BYTE(0x3a) BYTE(0x22) BYTE(0x73) BYTE(0x79)
+        BYTE(0x73) BYTE(0x74) BYTE(0x65) BYTE(0x6d)
+        BYTE(0x64) BYTE(0x22) BYTE(0x2c) BYTE(0x22)
+        BYTE(0x76) BYTE(0x65) BYTE(0x72) BYTE(0x73)
+        BYTE(0x69) BYTE(0x6f) BYTE(0x6e) BYTE(0x22)
+        BYTE(0x3a) BYTE(0x22) BYTE(0x32) BYTE(0x34)
+        BYTE(0x38) BYTE(0x7e) BYTE(0x72) BYTE(0x63)
+        BYTE(0x32) BYTE(0x2d) BYTE(0x31) BYTE(0x2e)
+        BYTE(0x66) BYTE(0x63) BYTE(0x33) BYTE(0x34)
+        BYTE(0x22) BYTE(0x2c) BYTE(0x22) BYTE(0x6f)
+        BYTE(0x73) BYTE(0x43) BYTE(0x70) BYTE(0x65)
+        BYTE(0x22) BYTE(0x3a) BYTE(0x22) BYTE(0x63)
+        BYTE(0x70) BYTE(0x65) BYTE(0x3a) BYTE(0x2f)
+        BYTE(0x6f) BYTE(0x3a) BYTE(0x66) BYTE(0x65)
+        BYTE(0x64) BYTE(0x6f) BYTE(0x72) BYTE(0x61)
+        BYTE(0x70) BYTE(0x72) BYTE(0x6f) BYTE(0x6a)
+        BYTE(0x65) BYTE(0x63) BYTE(0x74) BYTE(0x3a)
+        BYTE(0x66) BYTE(0x65) BYTE(0x64) BYTE(0x6f)
+        BYTE(0x72) BYTE(0x61) BYTE(0x3a) BYTE(0x33)
+        BYTE(0x33) BYTE(0x22) BYTE(0x7d) BYTE(0x00)
+    }
+}
+INSERT AFTER .note.gnu.build-id;
+```
+
+## Well-known keys
+
+The metadata format is intentionally left open, so that vendors can add their own information.
+A set of well-known keys is defined here, and hopefully shared among all vendors.
+
+| Key name     | Key description                                                          | Example value                         |
+|--------------|--------------------------------------------------------------------------|---------------------------------------|
+| type         | The packaging type                                                       | rpm                                   |
+| os           | The OS name, typically corresponding to ID in os-release                 | fedora                                |
+| osVersion    | The OS version, typically corresponding to VERSION_ID in os-release      | 33                                    |
+| name         | The source package name                                                  | coreutils                             |
+| version      | The source package version                                               | 4711.0815.fc13.arm32                  |
+| osCpe        | A CPE name for the OS, typically corresponding to CPE_NAME in os-release | cpe:/o:fedoraproject:fedora:33        |
+| debugInfoUrl | The debuginfod server url, if available                                  | https://debuginfod.fedoraproject.org/ |
index 9ce4ebc9407f58326430a046bbf6de831cf20ff1..656a516f971f402b6f627692c1526e80484bae57 100644 (file)
@@ -62,7 +62,7 @@ Interface](https://systemd.io/BOOT_LOADER_INTERFACE).
 | `4301d2a6-4e3b-4b2a-bb94-9e0b2c4225ea` | _`/usr/` Partition (Itanium/IA-64)_ | ditto | ditto |
 | `b933fb22-5c3f-4f91-af90-e2bb0fa50702` | _`/usr/` Partition (RISC-V 32-bit)_ | ditto | ditto |
 | `beaec34b-8442-439b-a40b-984381ed097d` | _`/usr/` Partition (RISC-V 64-bit)_ | ditto | ditto |
-| `8f461b0d-14ee-4e81-9aa9-049b6fb97abd` | _`/usr/` Verity Partition (x86)_ | Any native, optionally in LUKS | Similar semantics to root Verity partition, but just for the `/usr/` partition. |
+| `8f461b0d-14ee-4e81-9aa9-049b6fb97abd` | _`/usr/` Verity Partition (x86)_ | A dm-verity superblock followed by hash data | Similar semantics to root Verity partition, but just for the `/usr/` partition. |
 | `77ff5f63-e7b6-4633-acf4-1565b864c0e6` | _`/usr/` Verity Partition (x86-64)_ | ditto | ditto |
 | `c215d751-7bcd-4649-be90-6627490a4c05` | _`/usr/` Verity Partition (32-bit ARM)_ | ditto | ditto |
 | `6e11a4e7-fbca-4ded-b9e9-e1a512bb664e` | _`/usr/` Verity Partition (64-bit ARM/AArch64)_ | ditto | ditto |
@@ -73,10 +73,10 @@ Interface](https://systemd.io/BOOT_LOADER_INTERFACE).
 | `3b8f8425-20e0-4f3b-907f-1a25a76f98e8` | _Server Data Partition_ | Any native, optionally in LUKS | The first partition with this type UUID on the disk containing the root partition is automatically mounted to `/srv/`.  If the partition is encrypted with LUKS, the device mapper file will be named `/dev/mapper/srv`. |
 | `4d21b016-b534-45c2-a9fb-5c16e091fd2d` | _Variable Data Partition_ | Any native, optionally in LUKS | The first partition with this type UUID on the disk containing the root partition is automatically mounted to `/var/` — under the condition that its partition UUID matches the first 128 bit of `HMAC-SHA256(machine-id, 0x4d21b016b53445c2a9fb5c16e091fd2d)` (i.e. the SHA256 HMAC hash of the binary type UUID keyed by the machine ID as read from [`/etc/machine-id`](https://www.freedesktop.org/software/systemd/man/machine-id.html). This special requirement is made because `/var/` (unlike the other partition types listed here) is inherently private to a specific installation and cannot possibly be shared between multiple OS installations on the same disk, and thus should be bound to a specific instance of the OS, identified by its machine ID. If the partition is encrypted with LUKS, the device mapper file will be named `/dev/mapper/var`. |
 | `7ec6f557-3bc5-4aca-b293-16ef5df639d1` | _Temporary Data Partition_ | Any native, optionally in LUKS | The first partition with this type UUID on the disk containing the root partition is automatically mounted to `/var/tmp/`.  If the partition is encrypted with LUKS, the device mapper file will be named `/dev/mapper/tmp`. Note that the intended mount point is indeed `/var/tmp/`, not `/tmp/`. The latter is typically maintained in memory via <tt>tmpfs</tt> and does not require a partition on disk. In some cases it might be desirable to make `/tmp/` persistent too, in which case it is recommended to make it a symlink or bind mount to `/var/tmp/`, thus not requiring its own partition type UUID. |
-| `0657fd6d-a4ab-43c4-84e5-0933c84b4f4f` | _Swap_ | Swap | All swap partitions on the disk containing the root partition are automatically enabled. |
+| `0657fd6d-a4ab-43c4-84e5-0933c84b4f4f` | _Swap_ | Swap | All swap partitions on the disk containing the root partition are automatically enabled. This partition type predates the Discoverable Partitions Specification. |
+| `0fc63daf-8483-4772-8e79-3d69d8477de4` | _Generic Linux Data Partitions_ | Any native, optionally in LUKS | No automatic mounting takes place for other Linux data partitions. This partition type should be used for all partitions that carry Linux file systems. The installer needs to mount them explicitly via entries in <tt>/etc/fstab</tt>. Optionally, these partitions may be encrypted with LUKS. This partition type predates the Discoverable Partitions Specification. |
 | `c12a7328-f81f-11d2-ba4b-00a0c93ec93b` | _EFI System Partition_ | VFAT | The ESP used for the current boot is automatically mounted to `/efi/` (or `/boot/` as fallback), unless a different partition is mounted there (possibly via `/etc/fstab`, or because the Extended Boot Loader Partition — see below — exists) or the directory is non-empty on the root disk.  This partition type is defined by the [UEFI Specification](http://www.uefi.org/specifications). |
 | `bc13c2ff-59e6-4262-a352-b275fd6f7172` | _Extended Boot Loader Partition_ | Typically VFAT | The Extended Boot Loader Partition (XBOOTLDR) used for the current boot is automatically mounted to <tt>/boot/</tt>, unless a different partition is mounted there (possibly via <tt>/etc/fstab</tt>) or the directory is non-empty on the root disk. This partition type is defined by the [Boot Loader Specification](https://systemd.io/BOOT_LOADER_SPECIFICATION). |
-| `0fc63daf-8483-4772-8e79-3d69d8477de4` | _Other Data Partitions_ | Any native, optionally in LUKS | No automatic mounting takes place for other Linux data partitions. This partition type should be used for all partitions that carry Linux file systems. The installer needs to mount them explicitly via entries in <tt>/etc/fstab</tt>. Optionally, these partitions may be encrypted with LUKS. |
 
 Other GPT type IDs might be used on Linux, for example to mark software RAID or
 LVM partitions. The definitions of those GPT types is outside of the scope of
@@ -94,24 +94,48 @@ localized.
 
 ## Partition Flags
 
-For the root, `/usr/`, server data, home, variable data, temporary data and swap
-partitions, the partition flag bit 63 ("*no-auto*") may be used to turn off
-auto-discovery for the specific partition.  If set, the partition will not be
-automatically mounted or enabled.
-
-For the root, `/usr/`, server data, home, variable data and temporary data
-partitions, the partition flag bit 60 ("*read-only*") may be used to mark a
-partition for read-only mounts only.  If set, the partition will be mounted
-read-only instead of read-write. Note that the variable data partition and the
-temporary data partition will generally not be able to serve their purpose if
-marked read-only, since by their very definition they are supposed to be
-mutable. (The home and server data partitions are generally assumed to be
-mutable as well, but the requirement for them is not equally strong.) Because
-of that, while the read-only flag is defined and supported, it's almost never a
-good idea to actually use it for these partitions.
-
-Note that these two flag definitions happen to map nicely to the ones used by
-Microsoft Basic Data Partitions.
+This specification defines three GPT partition flags that may be set for the
+partition types defined above:
+
+1. For the root, `/usr/`, Verity, home, server data, variable data, temporary data,
+   swap and extended boot loader partitions, the partition flag bit 63
+   ("*no-auto*") may be used to turn off auto-discovery for the specific
+   partition.  If set, the partition will not be automatically mounted or
+   enabled.
+
+2. For the root, `/usr/`, Verity, home, server data, variable data, temporary
+   data and extended boot loader partitions, the partition flag bit 60
+   ("*read-only*") may be used to mark a partition for read-only mounts only.
+   If set, the partition will be mounted read-only instead of read-write. Note
+   that the variable data partition and the temporary data partition will
+   generally not be able to serve their purpose if marked read-only, since by
+   their very definition they are supposed to be mutable. (The home and server
+   data partitions are generally assumed to be mutable as well, but the
+   requirement for them is not equally strong.) Because of that, while the
+   read-only flag is defined and supported, it's almost never a good idea to
+   actually use it for these partitions. Also note that Verity partitions are
+   by their semantics always read-only. The flag is hence of little effect for
+   them, and it is recommended to set it unconditionally for the Verity
+   partition types.
+
+3. For the root, `/usr/`, home, server data, variable data, temporary data and
+   extended boot loader partitions, the partition flag bit 59
+   ("*grow-file-system*") may be used to mark a partition for automatic growing
+   of the contained file system to the size of the partition when
+   mounted. Tools that automatically mount disk image with a GPT partition
+   table are suggested to implicitly grow the contained file system to the
+   partition size they are contained in. This flag is without effect on
+   partitions marked read-only.
+
+Note that the first two flag definitions happen to map nicely to the ones used
+by Microsoft Basic Data Partitions.
+
+All three of these flags generally affect only auto-discovery and automatic
+mounting of disk images. If partitions marked with these flags are mounted
+using low-level commands like
+[mount(8)](https://man7.org/linux/man-pages/man2/mount.8.html) or directly with
+[mount(2)](https://man7.org/linux/man-pages/man2/mount.2.html), they typically
+have no effect.
 
 ## Suggested Mode of Operation
 
@@ -162,7 +186,14 @@ partition is listed in `/etc/fstab` or with `root=` on the kernel command line,
 it _must_ take precedence over automatically discovered partitions.  If a
 `/home/`, `/usr/`, `/srv/`, `/boot/`, `/var/`, `/var/tmp/`, `/efi/` or `/boot/`
 directory is found to be populated already in the root partition, the automatic
-discovery _must not_ mount any discovered file system over it.
+discovery _must not_ mount any discovered file system over it. Optionally, in
+case of the root, `/usr/` and their Verity partitions instead of strictly
+mounting the first suitable partition an OS might choose to mount the partition
+whose label compares the highest according to `strverscmp()` or a similar
+logic, in order to implement a simple partition-based A/B versioning
+scheme. The precise rules are left for the implementation to decide, but when
+in doubt earlier partitions (by their index) should always win over later
+partitions if the label comparison is inconclusive.
 
 A *container* *manager* should automatically discover and mount the root,
 `/usr/`, `/home/`, `/srv/`, `/var/`, `/var/tmp/` partitions inside a container
index ad2d3ad84b8edef0d3bd2c41a73586bfd9c3bc4a..2cec3bdc1666d6344eb6ba39a1f18afcda9e4eb3 100644 (file)
@@ -198,11 +198,6 @@ All tools:
   prefixed with `:` in which case the kernel command line option takes
   precedence, if it is specified as well.
 
-installed systemd tests:
-
-* `$SYSTEMD_TEST_DATA` — override the location of test data. This is useful if
-  a test executable is moved to an arbitrary location.
-
 `nss-systemd`:
 
 * `$SYSTEMD_NSS_BYPASS_SYNTHETIC=1` — if set, `nss-systemd` won't synthesize
@@ -302,6 +297,14 @@ installed systemd tests:
 * `$SYSTEMD_SYSVRCND_PATH` — Controls where `systemd-sysv-generator` looks for
   SysV init script runlevel link farms.
 
+systemd tests:
+
+* `$SYSTEMD_TEST_DATA` — override the location of test data. This is useful if
+  a test executable is moved to an arbitrary location.
+
+* `$SYSTEMD_TEST_NSS_BUFSIZE` — size of scratch buffers for "reentrant"
+  functions exported by the nss modules.
+
 fuzzers:
 
 * `$SYSTEMD_FUZZ_OUTPUT` — A boolean that specifies whether to write output to
diff --git a/docs/JOURNAL_NATIVE_PROTOCOL.md b/docs/JOURNAL_NATIVE_PROTOCOL.md
new file mode 100644 (file)
index 0000000..fced459
--- /dev/null
@@ -0,0 +1,190 @@
+---
+title: Native Journal Protocol
+category: Interfaces
+layout: default
+---
+
+# Native Journal Protocol
+
+`systemd-journald.service` accepts log data via various protocols:
+
+* Classic RFC3164 BSD syslog via the `/dev/log` socket
+* STDOUT/STDERR of programs via `StandardOutput=journal` + `StandardError=journal` in service files (both of which are default settings)
+* Kernel log messages via the `/dev/kmsg` device node
+* Audit records via the kernel's audit subsystem
+* Structured log messages via `journald`'s native protocol
+
+The latter is what this document is about: if you are developing a program and
+want to pass structured log data to `journald`, it's the Journal's native
+protocol what you want to use. The systemd project provides the
+[`sd_journal_print(3)`](https://www.freedesktop.org/software/systemd/man/sd_journal_print.html)
+API that implements the client side of this protocol. This document explains
+what this interface does behind the scenes, in case you'd like to implement a
+client for it yourself, without linking to `libsystemd` — for example because
+you work in a programming language other than C or otherwise want to avoid the
+dependency.
+
+## Basics
+
+The native protocol of `journald` is spoken on the
+`/run/systemd/journal/socket` `AF_UNIX`/`SOCK_DGRAM` socket on which
+`systemd-journald.service` listens. Each datagram sent to this socket
+encapsulates one journal entry that shall be written. Since datagrams are
+subject to a size limit and we want to allow large journal entries, datagrams
+sent over this socket may come in one of two formats:
+
+* A datagram with the literal journal entry data as payload, without
+  any file descriptors attached.
+
+* A datagram with an empty payload, but with a single
+  [`memfd`](https://man7.org/linux/man-pages/man2/memfd_create.2.html)
+  file descriptor that contains the literal journal entry data.
+
+Other combinations are not permitted, i.e. datagrams with both payload and file
+descriptors, or datagrams with neither, or more than one file descriptor. Such
+datagrams are ignored. The `memfd` file descriptor should be fully sealed. The
+binary format in the datagram payload and in the `memfd` memory is
+identical. Typically a client would attempt to first send the data as datagram
+payload, but if this fails with an `EMSGSIZE` error it would immediately retry
+via the `memfd` logic.
+
+A client probably should bump up the `SO_SNDBUF` socket option of its `AF_UNIX`
+socket towards `journald` in order to delay blocking I/O as much as possible.
+
+## Data Format
+
+Each datagram should consist of a number of environment-like key/value
+assignments. Unlike environment variable assignments the value may contain NUL
+bytes however, as well as any other binary data. Keys may not include the `=`
+or newline characters (or any other control characters or non-ASCII characters)
+and may not be empty.
+
+Serialization into the datagram payload or `memfd` is straight-forward: each
+key/value pair is serialized via one of two methods:
+
+* The first method inserts a `=` character between key and value, and suffixes
+the result with `\n` (i.e. the newline character, ASCII code 10). Example: a
+key `FOO` with a value `BAR` is serialized `F`, `O`, `O`, `=`, `B`, `A`, `R`,
+`\n`.
+
+* The second method should be used if the value of a field contains a `\n`
+byte. In this case, the key name is serialized as is, followed by a `\n`
+character, followed by a (non-aligned) little-endian unsigned 64bit integer
+encoding the size of the value, followed by the literal value data, followed by
+`\n`. Example: a key `FOO` with a value `BAR` may be serialized using this
+second method as: `F`, `O`, `O`, `\n`, `\003`, `\000`, `\000`, `\000`, `\000`,
+`\000`, `\000`, `\000`, `B`, `A`, `R`, `\n`.
+
+If the value of a key/value pair contains a newline character (`\n`), it *must*
+be serialized using the second method. If it does not, either method is
+permitted. However, it is generally recommended to use the first method if
+possible for all key/value pairs where applicable since the generated datagrams
+are easily recognized and understood by the human eye this way, without any
+manual binary decoding — which improves the debugging experience a lot, in
+particular with tools such as `strace` that can show datagram content as text
+dump. After all, log messages are highly relevant for debugging programs, hence
+optimizing log traffic for readability without special tools is generally
+desirable.
+
+Note that keys that begin with `_` have special semantics in `journald`: they
+are *trusted* and implicitly appended by `journald` on the receiving
+side. Clients should not send them — if they do anyway, they will be ignored.
+
+The most important key/value pair to send is `MESSAGE=`, as that contains the
+actual log message text. Other relevant keys a client should send in most cases
+are `PRIORITY=`, `CODE_FILE=`, `CODE_LINE=`, `CODE_FUNC=`, `ERRNO=`. It's
+recommended to generate these fields implicitly on the client side. For further
+information see the [relevant documentation of these
+fields](https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html).
+
+The order in which the fields are serialized within one datagram is undefined
+and may be freely chosen by the client. The server side might or might not
+retain or reorder it when writing it to the Journal.
+
+Some programs might generate multi-line log messages (e.g. a stack unwinder
+generating log output about a stack trace, with one line for each stack
+frame). It's highly recommended to send these as a single datagram, using a
+single `MESSAGE=` field with embedded newline characters between the lines (the
+second serialization method described above must hence be used for this
+field). If possible do not split up individual events into multiple Journal
+events that might then be processed and written into the Journal as separate
+entries. The Journal toolchain is capable of handling multi-line log entries
+just fine, and it's generally preferred to have a single set of metadata fields
+associated with each multi-line message.
+
+Note that the same keys may be used multiple times within the same datagram,
+with different values. The Journal supports this and will write such entries to
+disk without complaining. This is useful for associating a single log entry
+with multiple suitable objects of the same type at once. This should only be
+used for specific Journal fields however, where this is expected. Do not use
+this for Journal fields where this is not expected and where code reasonably
+assumes per-event uniqueness of the keys. In most cases code that consumes and
+displays log entries is likely to ignore such non-unique fields or only
+consider the first of the specified values. Specifically, if a Journal entry
+contains multiple `MESSAGE=` fields, likely only the first one is
+displayed. Note that a well-written logging client library thus will not use a
+plain dictionary for accepting structured log metadata, but rather a data
+structure that allows non-unique keys, for example an array, or a dictionary
+that optionally maps to a set of values instead of a single value.
+
+## Example Datagram
+
+Here's an encoded message, with various common fields, all encoded according to
+the first serialization method, with the exception of one, where the value
+contains a newline character, and thus the second method is needed to be used.
+
+```
+PRIORITY=3\n
+SYSLOG_FACILITY=3\n
+CODE_FILE=src/foobar.c\n
+CODE_LINE=77\n
+BINARY_BLOB\n
+\004\000\000\000\000\000\000\000xx\nx\n
+CODE_FUNC=some_func\n
+SYSLOG_IDENTIFIER=footool\n
+MESSAGE=Something happened.\n
+```
+
+(Lines are broken here after each `\n` to make things more readable. C-style
+backslash escaping is used.)
+
+## Automatic Protocol Upgrading
+
+It might be wise to automatically upgrade to logging via the Journal's native
+protocol in clients that previously used the BSD syslog protocol. Behaviour in
+this case should be pretty obvious: try connecting a socket to
+`/run/systemd/journal/socket` first (on success use the native Journal
+protocol), and if that fails fall back to `/dev/log` (and use the BSD syslog
+protocol).
+
+Programs normally logging to STDERR might also choose to upgrade to native
+Journal logging in case they are invoked via systemd's service logic, where
+STDOUT and STDERR are going to the Journal anyway. By preferring the native
+protocol over STDERR-based logging, structured metadata can be passed along,
+including priority information and more — which is not available on STDERR
+based logging. If a program wants to detect automatically whether its STDERR is
+connected to the Journal's stream transport, look for the `$JOURNAL_STREAM`
+environment variable. The systemd service logic sets this variable to a
+colon-separated pair of device and inode number (formatted in decimal ASCII) of
+the STDERR file descriptor. If the `.st_dev` and `.st_ino` fields of the
+`struct stat` data returned by `fstat(STDERR_FILENO, …)` match these values a
+program can be sure its STDERR is connected to the Journal, and may then opt to
+upgrade to the native Journal protocol via an `AF_UNIX` socket of its own, and
+cease to use STDERR.
+
+Why bother with this environment variable check? A service program invoked by
+systemd might employ shell-style I/O redirection on invoked subprograms, and
+those should likely not upgrade to the native Journal protocol, but instead
+continue to use the redirected file descriptors passed to them. Thus, by
+comparing the device and inode number of the actual STDERR file descriptor with
+the one the service manager passed, one can make sure that no I/O redirection
+took place for the current program.
+
+## Alternative Implementations
+
+If you are looking for alternative implementations of this protocol (besides
+systemd's own in `sd_journal_print()`), consider
+[GLib's](https://gitlab.gnome.org/GNOME/glib/-/blob/master/glib/gmessages.c) or
+[`dbus-broker`'s](https://github.com/bus1/dbus-broker/blob/main/src/util/log.c).
+
+And that's already all there is to it.
index 8248275cedc6f097fe87cf0c2df3d9db11ffbc79..d9171c7b658fe387006f28eaa50484a3bd3fa75c 100644 (file)
@@ -59,14 +59,14 @@ 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
+main difference is that they 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
+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
+do it), but as normal processes. 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.
 
@@ -77,12 +77,12 @@ focus includes system extensions otherwise sometimes called "super-privileged
 containers".
 
 Note that portable services are only available for system services, not for
-user servicesi.e. the functionality cannot be used for the stuff
-bubblewrap/flatpak is focusing on.
+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
+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:
 
 ```
@@ -135,7 +135,7 @@ This command does the following:
 
 And that's already it.
 
-Note that the images need to stay around (and the same location) as long as the
+Note that the images need to stay around (and in 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.
@@ -144,7 +144,7 @@ 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
+Note that `portablectl 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.).
 
@@ -223,7 +223,7 @@ read-only, immutable images (e.g. squashfs images) all files and directories to
 over-mount must exist already.
 
 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
+straightforward to define images than can be made use of in a number of
 different ways. For example, by using `mkosi -b` you can trivially build a
 single, unified image that:
 
index 9f69a3162a0d8e7cb1c08a51eba8f26dee2479af..070ad5a2859ae50a13054561d0a72217c20cdda6 100644 (file)
@@ -68,6 +68,7 @@ Most generic unit settings are available for transient units.
 ✓ ConditionKernelCommandLine=
 ✓ ConditionKernelVersion=
 ✓ ConditionArchitecture=
+✓ ConditionFirmware=
 ✓ ConditionVirtualization=
 ✓ ConditionSecurity=
 ✓ ConditionCapability=
@@ -303,6 +304,7 @@ Most service unit settings are available for transient units.
 ✓ ExecStartPre=
 ✓ ExecStop=
 ✓ ExecStopPost=
+✓ ExitType=
 ✓ FileDescriptorStoreMax=
 ✓ GuessMainPID=
 ✓ NonBlocking=
index 55d3fcc3b082553e5e9bffb7fd596a7207662fcb..15dcc2f1eef0b40c3432bb83e7324d9308c6abd8 100644 (file)
@@ -55,6 +55,14 @@ usb:v0627p0001:*QEMU USB Mouse*
 usb:v0627p0001:*QEMU USB Tablet*
  ID_AUTOSUSPEND=1
 
+#########################################
+# Sierra Wireless
+#########################################
+
+# Sierra Wireless EM7345 4G LTE modem
+usb:v1199pA001*
+ ID_AUTOSUSPEND=1
+
 #########################################
 # Wacom
 #########################################
index 5485f892bb56cb4504b1e5213f7a0bbb4b014bd5..9b63f9367463d3e4ebb393bea576c4eb7e652dd3 100644 (file)
@@ -384,7 +384,7 @@ evdev:name:Dell WMI hotkeys:dmi:bvn*:bvr*:bd*:svnDell*:pnPrecision*:*
 
 # Dell Latitude privacy microphone mute
 evdev:name:Dell Privacy Driver:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*:*
- KEYBOARD_KEY_12001=f20                                 # Mic mute toggle, should be micmute
+ KEYBOARD_KEY_120001=f20                                # Mic mute toggle, should be micmute
 
 ###########################################################
 # Everex
@@ -684,6 +684,21 @@ evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*645*G4*:*
  KEYBOARD_KEY_73=slash                                  # Slash key
  KEYBOARD_KEY_f8=wlan                                   # Wireless HW switch button
 
+# HP ProBook 455 G5
+evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*455*G5*:*
+ KEYBOARD_KEY_85=unknown                                # lid close; also reported via special evdev
+ KEYBOARD_KEY_f8=wlan                                   # Wireless HW switch button
+
+# HP mt44 Mobile Thin Client
+evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*mt44*Mobile*Thin*Client*:*
+ KEYBOARD_KEY_64=calendar                               # Calendar icon (Fn + F12)
+ KEYBOARD_KEY_6d=displaytoggle                          # Display icon
+ KEYBOARD_KEY_66=connect                                # Pickup phone button → connect → XF86Go
+ KEYBOARD_KEY_65=cancel                                 # Hangup phone button → cancel → Cancel
+ KEYBOARD_KEY_81=f20                                    # Fn+F8; Microphone mute button, should be micmute
+ KEYBOARD_KEY_85=unknown                                # lid close; also reported via special evdev
+ KEYBOARD_KEY_f8=wlan                                   # Wireless HW switch button
+
 # HP Stream 7
 # The ACPI tables contains a gpio-keys entry for a non connected GPIO
 # causing spurious events, map this to unknown to disable it
@@ -1236,7 +1251,7 @@ evdev:input:b0003v1532p0200*
  KEYBOARD_KEY_c01cb=down                                # zoomout
 
 ###########################################################
-# Micro Star
+# MSI (aka "Micro Star")
 ###########################################################
 
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*:*
@@ -1275,24 +1290,19 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*PR200*:*
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnU90/U100:*
  KEYBOARD_KEY_e4=reserved
 
-# MSI Prestige15 A10SC specific keycodes. Needed for microphone and screen rotation
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*A10SC*:*
- KEYBOARD_KEY_f1=f20
- KEYBOARD_KEY_f2=f21
-
-# MSI Modern series
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-StarInternational*:pnModern*:*
- KEYBOARD_KEY_f1=f20                                    # Fn+F5 micmute
- KEYBOARD_KEY_76=f21                                    # Fn+F4 touchpad, becomes meta+ctrl+toggle
+# Keymaps MSI Prestige And MSI Modern FnKeys and Special keys
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*Prestige*:*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*Modern*:*
+ KEYBOARD_KEY_56=backslash                              # Secondary backslash key
+ KEYBOARD_KEY_f1=f20                                    # Fn+F5 Micmute
+ KEYBOARD_KEY_76=f21                                    # Fn+F4 Toggle touchpad, sends meta+ctrl+toggle
  KEYBOARD_KEY_91=prog1                                  # Fn+F7 Creation Center, sometime F7
- KEYBOARD_KEY_f2=prog2                                  # Fn+F12 screen rotation
- KEYBOARD_KEY_97=unknown                                # lid close
- KEYBOARD_KEY_98=unknown                                # lid open
-                                                        #Fn+PrntScr sends meta+shif+s
-
-###########################################################
-# MSI
-###########################################################
+ KEYBOARD_KEY_f2=prog2                                  # Fn+F12 Screen rotation
+ KEYBOARD_KEY_8d=prog3                                  # Fn+A Change True Color selections
+ KEYBOARD_KEY_8c=prog4                                  # Fn+Z Launch True Color
+ KEYBOARD_KEY_f5=fn_esc                                 # Fn+esc Toggle the behaviour of Fn keys
+ KEYBOARD_KEY_97=unknown                                # Lid close
+ KEYBOARD_KEY_98=unknown                                # Lid open
 
 evdev:name:MSI Laptop hotkeys:dmi:bvn*:bvr*:bd*:svn*:pnM[iI][cC][rR][oO]-S[tT][aA][rR]*:*
  KEYBOARD_KEY_0213=f22
index 54f6f34b7f23201a7f06616da628b1e7ed9915cd..0573e28807db79ec0b947faedc510fa1eee47314 100644 (file)
@@ -344,6 +344,14 @@ sensor:modalias:acpi:KIOX000A*:dmi:*:svnEVE*:pnEveV:*
 sensor:modalias:acpi:KIOX010A*:dmi:*:svnGEO*:pnGeoFlex*:*
  ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, 1
 
+#########################################
+# Glavey
+#########################################
+
+# Glavey TM800A550L
+sensor:modalias:acpi:KXCJ9000*:dmi:*:bvrZY-8-BI-PX4S70VTR400-X423B-005-D:*:rvnAMICorporation:rnAptioCRB:*
+ ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
+
 #########################################
 # Google Chromebooks
 #########################################
@@ -497,8 +505,7 @@ sensor:modalias:acpi:BMA250E*:dmi:bvnLENOVO:*:pvrLenovoMIIX3-1030:*
 sensor:modalias:acpi:SMO8500*:dmi:bvnLENOVO:*:pvrLenovoMIIX3-830:*
  ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
 
-# IdeaPad D330 and D330-10IGM
-sensor:modalias:acpi:BOSC0200*:dmi:*:svnLENOVO:pn81H3:*
+# IdeaPad D330-10IGM (both 81H3 and 81MD product numbers)
 sensor:modalias:acpi:BOSC0200*:dmi:*:svnLENOVO:*:cvrLenovoideapadD330-10IGM:*
  ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
 
@@ -536,6 +543,13 @@ sensor:modalias:acpi:KIOX000A*:dmi:*:svnLINX*:pnLINX12*64:*
 sensor:modalias:acpi:KIOX000A*:dmi:*:svnLINX:pnVISION004:*
  ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
 
+#########################################
+# Mediacom
+#########################################
+# Mediacom Winpad 7.0 W700
+sensor:modalias:acpi:BMA250*:dmi:*svnMEDIACOM*:pnWinPad7W10-WPW700:*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
+
 #########################################
 # Medion
 #########################################
@@ -735,6 +749,10 @@ sensor:modalias:acpi:KIOX020A*:dmi:*:svnTECLAST:pnF6Pro:*
  ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
  ACCEL_LOCATION=base
 
+# Teclast Tbook 11 (E5A6)
+sensor:modalias:acpi:KIOX000A*:dmi:*:svnTECLAST:pnTbooK11:*
+ ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
+
 # Teclast X80 Plus (H5C5)
 sensor:modalias:acpi:KIOX000A*:dmi:*:svnTECLAST:pnDefaultstring:*
  ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
@@ -767,6 +785,10 @@ sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr5.6.5:bd04/15/201
 # Toshiba
 #########################################
 
+# Toshiba Encore WT8-B tablet
+sensor:modalias:acpi:INVN6500*:dmi:*:svnTOSHIBA:pnTOSHIBAENCORE2WT8-B:* 
+ ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+
 # Toshiba Encore WT10A tablet
 sensor:modalias:acpi:INVN6500*:dmi:*:svnTOSHIBA:pnTOSHIBAWT10-A-103:*
  ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
diff --git a/hwdb.d/80-ieee1394-unit-function.hwdb b/hwdb.d/80-ieee1394-unit-function.hwdb
new file mode 100644 (file)
index 0000000..aa00711
--- /dev/null
@@ -0,0 +1,1324 @@
+# This file is part of systemd.
+
+# Description
+#
+# Each node on IEEE 1394 bus has configuration ROM with information for identification. Although the
+# typical content of configuration ROM is defined by 1394 Trading Association, many nodes have own
+# quirks. This database includes supplemental information to unit in the node.
+
+# Convention
+#
+# One entry has two keys. One is customized key to match a node. Another is for kernel alias to
+# match an unit included in the node.
+#
+# The customized key has two formats according to whether the node has model attribute:
+#  - ven0x000000mo0x000000units0x000000:0x000000
+#  - ven0x000000units0x000000:0x000000
+#
+# Even when the node has multiple units, the entry should match to one of the units. In the case,
+# the customized key should have wild pattern for units field:
+#  - ven0x000000mo0x000000units*0x000000:0x000000*
+#  - ven0x000000units*0x000000:0x000000*
+#
+# The hexadecimal digits part of the customized key should be lower-case. Linux FireWire subsystem
+# uses lower-case value for attributes of sysfs node, and systemd-hwdb parses the custom key by
+# case-sensitive way. On the other hand, it parses kernel alias by case-insensitive way.
+#
+# The entry should have some of IEEE1394_UNIT_FUNCTION_XXX environment variables to express function
+# of the unit. The variables are used to decide group owner of special file for character device
+# corresponding to node including the unit. At present, below variables are supported:
+#  - IEEE1394_UNIT_FUNCTION_MIDI
+#    - For any unit to process MIDI messages. For example, the unit includes AV/C music subunit.
+#  - IEEE1394_UNIT_FUNCTION_AUDIO
+#    - For any unit to process audio signal. For example, the unit includes AV/C audio subunit.
+#  - IEEE1394_UNIT_FUNCTION_VIDEO
+#    - For any unit to process video signal.
+#
+# Additionally, ID_VENDOR_FROM_DATABASE and ID_MODEL_FROM_DATABASE environment variables are
+# preferable.
+
+#
+# General entry for AV/C device compliant to AV/C command set generic specification:
+# * Configuration ROM for AV/C Devices 1.0 (Dec. 12, 2000, 1394 Trading Association, TA Document
+#   1999027)
+#
+
+# Just for backward compatibility. Please invalidate IEEE1394_UNIT_FUNCTION_VIDEO by adding entries
+# if it is inconvenient.
+ieee1394:node:ven*mo*units*0x00a02d:0x010001*
+ieee1394:ven*mo*sp0000A02Dver00010001
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+#
+# General entries for AV/C device with vendor unique command set:
+# * IEC 61883-1:1998
+#
+
+# Please invalidate IEEE1394_UNIT_FUNCTION_VIDEO by adding entries if it is inconvenient.
+ieee1394:node:ven*mo*units*0x00a02d:0x014000*
+ieee1394:ven*mo*sp0000A02Dver00014000
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+# Just for backward compatibility. Please invalidate IEEE1394_UNIT_FUNCTION_VIDEO by adding entries
+# if it is inconvenient.
+ieee1394:node:ven*mo*units*0x00a02d:0x014001*
+ieee1394:ven*mo*sp0000A02Dver00014001
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+#
+# General entry for:
+# * 1394-based Digital Camera Specification Version 1.04 (Aug. 9, 1996, 1394 Trading Association)
+#
+
+ieee1394:node:ven*units0x00a02d:0x000100
+ieee1394:ven*sp0000A02Dver00000100
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+#
+# General entry for:
+# * 1394-based Digital Camera Specification Version 1.20 (Jul. 23, 1998, 1394 Trading Association)
+#
+
+ieee1394:node:ven*units0x00a02d:0x000101
+ieee1394:ven*sp0000A02Dver00000101
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+#
+# General entry for:
+# * IIDC Digital Camera Control Specification Ver.1.30 (Jul. 25, 2000, 1394 Trading Association)
+# * IIDC Digital Camera Control Specification Ver.1.31 (Feb. 2, 2004, 1394 Trading Association, TA
+#   Document 2003017)
+# * IIDC Digital Camera Control Specification Ver.1.32 (Jul. 24, 2008, 1394 Trading Association,
+#   Document number 2007009)
+#
+
+ieee1394:node:ven*units0x00a02d:0x000102
+ieee1394:ven*sp0000A02Dver00000102
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+#
+# General entry for:
+# * IIDC2 Digital Camera Control Specification Ver.1.0.0 (Jan 26th, 2012, 1394 Trading Association,
+#   TS2011001)
+# * IIDC2 Digital Camera Control Specification Ver.1.1.0 (May 19th, 2015, 1394 Trading Association,
+#   TS2015001)
+#
+
+ieee1394:node:ven*units0x00a02d:0x000110
+ieee1394:ven*sp0000A02Dver00000110
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+#
+# BridgeCo. Enhancement BreakOut Box (BeBoB) for DM1000, DM1100, and DM1500 ASICs.
+#
+
+# Match to eAR Master One, Eroica, Figaro, and Ciaccona.
+ieee1394:node:ven0x000aacmo0x000002units0x00a02d:0x010001
+ieee1394:ven00000AACmo00000002sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Acoustic Reality
+ ID_MODEL_FROM_DATABASE=eAR FireWire Audio
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x0003dbmo0x01eeeeunits0x00a02d:0x010001
+ieee1394:ven000003DBmo0001EEEEsp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Apogee Electronics
+ ID_MODEL_FROM_DATABASE=Ensemble FireWire
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+# An extension card for Rosetta 200, Rosetta 800, AD16X, DA16X, DD16X, and BigBen.
+ieee1394:node:ven0x0003dbmo0x010048units0x00a02d:0x010001
+ieee1394:ven000003DBmo00010048sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Apogee Electronics
+ ID_MODEL_FROM_DATABASE=X-FireWire Card
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x001564mo0x000610units0x00a02d:0x010001
+ieee1394:ven00001564mo00000610sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Behringer
+ ID_MODEL_FROM_DATABASE=F-Control Audio 610
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x001564mo0x001616units0x00a02d:0x010001
+ieee1394:ven00001564mo00001616sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Behringer
+ ID_MODEL_FROM_DATABASE=F-Control Audio 1616
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x001564mo0x001204units0x00a02d:0x010001
+ieee1394:ven00001564mo00001204sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Behringer
+ ID_MODEL_FROM_DATABASE=XENYX UFX1204
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x001564mo0x001604units0x00a02d:0x010001
+ieee1394:ven00001564mo00001604sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Behringer
+ ID_MODEL_FROM_DATABASE=XENYX UFX1604
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+# An extension card for Behringer X32.
+ieee1394:node:ven0x001564mo0x000006units0x00a02d:0x010001
+ieee1394:ven00001564mo00000006sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Behringer
+ ID_MODEL_FROM_DATABASE=X-UF
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x00000amo0x030000units0x00a02d:0x010001
+ieee1394:ven0000000Amo00030000sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=CME
+ ID_MODEL_FROM_DATABASE=Matrix K FW
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x00a07emo0x0000a9units0x00a02d:0x014001
+ieee1394:ven0000A07Emo000000A9sp0000A02Dver00014001
+ ID_VENDOR_FROM_DATABASE=Digidesign
+ ID_MODEL_FROM_DATABASE=Mbox 2 Pro
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x0040abmo0x010048units0x00a02d:0x010001
+ieee1394:ven000040ABmo00010048sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Edirol
+ ID_MODEL_FROM_DATABASE=FA-101
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x0040abmo0x010049units0x00a02d:0x010001
+ieee1394:ven000040ABmo00010049sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Edirol
+ ID_MODEL_FROM_DATABASE=FA-66
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+# The value of model field differs depending on firmware.
+ieee1394:node:ven0x000f1bmo0x010064units0x00a02d:0x010001
+ieee1394:ven00000F1Bmo00010064sp0000A02Dver00010001
+ieee1394:node:ven0x000f1bmo0x000210units0x00a02d:0x010001
+ieee1394:ven00000F1Bmo00000210sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Ego Systems
+ ID_MODEL_FROM_DATABASE=QuataFire
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+# Match to Saffire and Saffire LE.
+ieee1394:node:ven0x00130emo0x000000units0x00a02d:0x010001
+ieee1394:ven0000130Emo00000000sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Focusrite
+ ID_MODEL_FROM_DATABASE=Saffire
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x00130emo0x000006units0x00a02d:0x010001
+ieee1394:ven0000130Emo00000006sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Focusrite
+ ID_MODEL_FROM_DATABASE=Saffire Pro 10 i/o
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x00130emo0x000003units0x00a02d:0x010001
+ieee1394:ven0000130Emo00000003sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Focusrite
+ ID_MODEL_FROM_DATABASE=Saffire Pro 26 i/o
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x01a9eemo0x000001units0x00a02d:0x010001
+ieee1394:ven0001A9EEmo00000001sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=ICON
+ ID_MODEL_FROM_DATABASE=FireXon
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000d6cmo0x010071units0x00a02d:0x014001
+ieee1394:ven00000D6Cmo00010071sp0000A02Dver00014001
+ ID_VENDOR_FROM_DATABASE=M-Audio
+ ID_MODEL_FROM_DATABASE=FW 1814
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+# Vendor is BridgeCo Co AG but M-Audio.
+ieee1394:node:ven0x0007f5mo0x010046units0x00a02d:0x014001
+ieee1394:ven000007F5mo00010046sp0000A02Dver00014001
+ ID_VENDOR_FROM_DATABASE=M-Audio
+ ID_MODEL_FROM_DATABASE=FW 410
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000d6cmo0x010060units0x00a02d:0x014001
+ieee1394:ven00000D6Cmo00010060sp0000A02Dver00014001
+ ID_VENDOR_FROM_DATABASE=M-Audio
+ ID_MODEL_FROM_DATABASE=FW Audiophile
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000d6cmo0x010062units0x00a02d:0x010001
+ieee1394:ven00000D6Cmo00010062sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=M-Audio
+ ID_MODEL_FROM_DATABASE=FW Solo
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000d6cmo0x010081units0x00a02d:0x010001
+ieee1394:ven00000D6Cmo00010081sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=M-Audio
+ ID_MODEL_FROM_DATABASE=NRV10
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000d6cmo0x00000aunits0x00a02d:0x014001
+ieee1394:ven00000D6Cmo0000000Asp0000A02Dver00014001
+ ID_VENDOR_FROM_DATABASE=M-Audio
+ ID_MODEL_FROM_DATABASE=Ozonic
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000d6cmo0x0100a1units0x00a02d:0x014001
+ieee1394:ven00000D6Cmo000100A1sp0000A02Dver00014001
+ ID_VENDOR_FROM_DATABASE=M-Audio
+ ID_MODEL_FROM_DATABASE=ProFire Lightbridge
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000d6cmo0x010091units0x00a02d:0x014001
+ieee1394:ven00000D6Cmo00010091sp0000A02Dver00014001
+ ID_VENDOR_FROM_DATABASE=M-Audio
+ ID_MODEL_FROM_DATABASE=ProjectMix I/O
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+# An extension card for Mackie Onyx 1220, 1620, and 1640.
+ieee1394:node:ven0x000ff2mo0x010065units0x00a02d:0x010001
+ieee1394:ven00000FF2mo00010065sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Loud Technologies
+ ID_MODEL_FROM_DATABASE=Mackie Onyx FireWire
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+# An extension card for Mackie d.2.
+ieee1394:node:ven0x000ff2mo0x010067units0x00a02d:0x010001
+ieee1394:ven00000FF2mo00010067sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Loud Technologies
+ ID_MODEL_FROM_DATABASE=Mackie DJ Mixer
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+# Match to FireFly 202, 302, 808, and 808 Universal.
+# Match to HelixBoard 12 mk II, 18 mk II, 24 mk II, 12 Universal, 18 Universal, and 24 Universal.
+ieee1394:node:ven0x001496mo0x000000units0x00a02d:0x010001
+ieee1394:ven00001496mo00000000sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Phonic
+ ID_MODEL_FROM_DATABASE=FireFly/Helixboard
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000a92mo0x010000units0x00a02d:0x010001
+ieee1394:ven00000A92mo00010000sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=PreSonus
+ ID_MODEL_FROM_DATABASE=FireBox
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000a92mo0x010001units0x00a02d:0x010001
+ieee1394:ven00000A92mo00010001sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=PreSonus
+ ID_MODEL_FROM_DATABASE=Inspire 1394
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x001198mo0x010048units0x00a02d:0x010001
+ieee1394:ven00001198mo00010048sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Prism Media Products
+ ID_MODEL_FROM_DATABASE=Orpheus
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000a92mo0x010066units0x00a02d:0x010001
+ieee1394:ven00000A92mo00010066sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=PreSonus
+ ID_MODEL_FROM_DATABASE=PreSonus FP10
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x001260mo0x000001units0x00a02d:0x010001
+ieee1394:ven00001260mo00000001sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Stanton Magnetics
+ ID_MODEL_FROM_DATABASE=ScratchAmp
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x010065mo0x010067units0x00a02d:0x010001
+ieee1394:ven00010065mo00010067sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Tascam
+ ID_MODEL_FROM_DATABASE=IF-FW/DM
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000aacmo0x000003units0x00a02d:0x010001
+ieee1394:ven00000AACmo00000003sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=TerraTec Electronic
+ ID_MODEL_FROM_DATABASE=PHASE 88 FW
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000aacmo0x000004units0x00a02d:0x010001
+ieee1394:ven00000AACmo00000004sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=TerraTec Electronic
+ ID_MODEL_FROM_DATABASE=PHASE 24 FW
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000aacmo0x000007units0x00a02d:0x010001
+ieee1394:ven00000AACmo00000007sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=TerraTec Electronic
+ ID_MODEL_FROM_DATABASE=PHASE X24 FW
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x002327mo0x020002units0x00a02d:0x010001
+ieee1394:ven00002327mo00020002sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=ToneWeal
+ ID_MODEL_FROM_DATABASE=FW66
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x00a0demo0x10000bunits0x00a02d:0x010001
+ieee1394:ven0000A0DEmo0010000Bsp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Yamaha
+ ID_MODEL_FROM_DATABASE=GO44
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x00a0demo0x10000cunits0x00a02d:0x010001
+ieee1394:ven0000A0DEmo0010000Csp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Yamaha
+ ID_MODEL_FROM_DATABASE=GO46
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+#
+# Fireworks board module.
+#
+# DSP model (Texus Instruments TMS320C67) and FPGA model (Xilinx Spartan XC35250E) exists.
+# Both models use Texus Instruments TSB43CB43 (IceLynx Micro, iCEM) as communication engine.
+#
+
+# Match to DSP model of AudioFire8.
+ieee1394:node:ven0x001486mo0x000af8units0x00a02d:0x010000
+ieee1394:ven00001486mo00000AF8sp0000A02Dver00010000
+ ID_VENDOR_FROM_DATABASE=Echo Digital Audio
+ ID_MODEL_FROM_DATABASE=AudioFire8
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# Match to both DSP and FPGA models of AudioFire12.
+ieee1394:node:ven0x001486mo0x00af12units0x00a02d:0x010000
+ieee1394:ven00001486mo0000AF12sp0000A02Dver00010000
+ ID_VENDOR_FROM_DATABASE=Echo Digital Audio
+ ID_MODEL_FROM_DATABASE=AudioFire12
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# DSP model.
+ieee1394:node:ven0x000ff2mo0x01200funits0x00a02d:0x010000
+ieee1394:ven00000FF2mo0001200Fsp0000A02Dver00010000
+ ID_VENDOR_FROM_DATABASE=Mackie
+ ID_MODEL_FROM_DATABASE=Onyx 1200F
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# DSP model.
+ieee1394:node:ven0x000ff2mo0x00400funits0x00a02d:0x010000
+ieee1394:ven00000FF2mo0000400Fsp0000A02Dver00010000
+ ID_VENDOR_FROM_DATABASE=Mackie
+ ID_MODEL_FROM_DATABASE=Onyx 400F
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# FPGA model.
+ieee1394:node:ven0x001486mo0x000af2units0x00a02d:0x010000
+ieee1394:ven00001486mo00000AF2sp0000A02Dver00010000
+ ID_VENDOR_FROM_DATABASE=Echo Digital Audio
+ ID_MODEL_FROM_DATABASE=AudioFire2
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# FPGA model.
+ieee1394:node:ven0x001486mo0x000af4units0x00a02d:0x010000
+ieee1394:ven00001486mo00000AF4sp0000A02Dver00010000
+ ID_VENDOR_FROM_DATABASE=Echo Digital Audio
+ ID_MODEL_FROM_DATABASE=AudioFire4
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# Match to FPGA model of AudioFire8, and AudioFirePre8.
+ieee1394:node:ven0x001486mo0x000af9units0x00a02d:0x010000
+ieee1394:ven00001486mo00000AF9sp0000A02Dver00010000
+ ID_VENDOR_FROM_DATABASE=Echo Digital Audio
+ ID_MODEL_FROM_DATABASE=AudioFire8/Pre8
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# FPGA model.
+ieee1394:node:ven0x00075bmo0x00afb2units0x00a02d:0x010000
+ieee1394:ven0000075Bmo0000AFB2sp0000A02Dver00010000
+ ID_VENDOR_FROM_DATABASE=Gibson
+ ID_MODEL_FROM_DATABASE=RIP
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+#
+# Oxford Semiconductor FW970/971.
+#
+
+ieee1394:node:ven0x0003dbmo0x01ddddunits0x00a02d:0x010001
+ieee1394:ven000003DBmo0001DDDDsp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Apogee Electronics
+ ID_MODEL_FROM_DATABASE=Duet FireWire
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x001564mo0x00fc22units0x00a02d:0x010001
+ieee1394:ven00001564mo0000FC22sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Behringer
+ ID_MODEL_FROM_DATABASE=F-Control Audio 202
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x001292mo0x00f970units0x00a02d:0x010001
+ieee1394:ven00001292mo0000F970sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Griffin Technology
+ ID_MODEL_FROM_DATABASE=Griffin FireWave
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x00d04bmo0x00f970units0x00a02d:0x010001
+ieee1394:ven0000D04Bmo0000F970sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=LaCie
+ ID_MODEL_FROM_DATABASE=LaCie FireWire Speakers
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+# Match to former models of Onyx 820i, 1220i, and 1620i.
+ieee1394:node:ven0x000ff2mo0x081216units0x00a02d:0x010001
+ieee1394:ven00000FF2mo00081216sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Loud Technologies
+ ID_MODEL_FROM_DATABASE=Mackie Onyx-i series
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000ff2mo0x001640units0x00a02d:0x010001
+ieee1394:ven00000FF2mo00001640sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Loud Technologies
+ ID_MODEL_FROM_DATABASE=Mackie Onyx 1640i
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000ff2mo0x00200funits0x00a02d:0x010001
+ieee1394:ven00000FF2mo0000200Fsp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Loud Technologies
+ ID_MODEL_FROM_DATABASE=Mackie Onyx Satellite
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x000ff2mo0x000460units0x00a02d:0x010001
+ieee1394:ven00000FF2mo00000460sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Loud Technologies
+ ID_MODEL_FROM_DATABASE=Tapco LINK.firewire 4x6
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x001260mo0x002000units0x00a02d:0x010001
+ieee1394:ven00001260mo00002000sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Stanton Magnetics
+ ID_MODEL_FROM_DATABASE=SCS.1d
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x001260mo0x001000units0x00a02d:0x010001
+ieee1394:ven00001260mo00001000sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Stanton Magnetics
+ ID_MODEL_FROM_DATABASE=SCS.1m
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+ieee1394:node:ven0x00022emo0x800007units0x00a02d:0x010001
+ieee1394:ven0000022Emo00800007sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Tascam
+ ID_MODEL_FROM_DATABASE=FireOne
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+#
+# TC Applied Technologies. Digital Interface Communication Engine (DICE).
+#
+# DICE with DICE II, TCD2210, TCD2220, and TCD3070 ASICs.
+#
+
+ieee1394:node:ven0x0004c4mo0x000000units0x0004c4:0x000001
+ieee1394:ven000004C4mo00000000sp000004C4ver00000001
+ ID_VENDOR_FROM_DATABASE=Allen and Heath
+ ID_MODEL_FROM_DATABASE=Zed R16
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# Match to iO 14, iO 26
+ieee1394:node:ven0x000595mo0x000001units0x000595:0x000001
+ieee1394:ven00000595mo00000001sp00000595ver00000001
+ ID_VENDOR_FROM_DATABASE=Alesis
+ ID_MODEL_FROM_DATABASE=iO FireWire
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000595mo0x000002units0x000595:0x000001
+ieee1394:ven00000595mo00000002sp00000595ver00000001
+ ID_VENDOR_FROM_DATABASE=Alesis
+ ID_MODEL_FROM_DATABASE=MasterControl
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# Match to Multimix 8, 12, and 16.
+ieee1394:node:ven0x000595mo0x000000units0x000595:0x000001
+ieee1394:ven00000595mo00000000sp00000595ver00000001
+ ID_VENDOR_FROM_DATABASE=Alesis
+ ID_MODEL_FROM_DATABASE=MultiMix FireWire
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00a07emo0x000004units0x00a07e:0x000001
+ieee1394:ven0000A07Emo00000004sp0000A07Ever00000001
+ ID_VENDOR_FROM_DATABASE=Avid
+ ID_MODEL_FROM_DATABASE=Mbox 3 Pro
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x001c2dmo0x000001units0x001c2d:0x000001
+ieee1394:ven00001C2Dmo00000001sp00001C2Dver00000001
+ ID_VENDOR_FROM_DATABASE=FlexRadio Systems
+ ID_MODEL_FROM_DATABASE=FLEX-5000
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x001c2dmo0x000002units0x001c2d:0x000001
+ieee1394:ven00001C2Dmo00000002sp00001C2Dver00000001
+ ID_VENDOR_FROM_DATABASE=FlexRadio Systems
+ ID_MODEL_FROM_DATABASE=FLEX-3000
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00130emo0x000006units0x00130e:0x000001
+ieee1394:ven0000130Emo00000006sp0000130Ever00000001
+ ID_VENDOR_FROM_DATABASE=Focusrite
+ ID_MODEL_FROM_DATABASE=Liquid Saffire 56
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00130emo0x000009units0x00130e:0x000001
+ieee1394:ven0000130Emo00000009sp0000130Ever00000001
+ ID_VENDOR_FROM_DATABASE=Focusrite
+ ID_MODEL_FROM_DATABASE=Saffire Pro 14
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00130emo0x000007units0x00130e:0x000001
+ieee1394:ven0000130Emo00000007sp0000130Ever00000001
+ ID_VENDOR_FROM_DATABASE=Focusrite
+ ID_MODEL_FROM_DATABASE=Saffire Pro 24
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00130emo0x000008units0x00130e:0x000001
+ieee1394:ven0000130Emo00000008sp0000130Ever00000001
+ ID_VENDOR_FROM_DATABASE=Focusrite
+ ID_MODEL_FROM_DATABASE=Saffire Pro 24 DSP
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00130emo0x000012units0x00130e:0x000001
+ieee1394:ven0000130Emo00000012sp0000130Ever00000001
+ ID_VENDOR_FROM_DATABASE=Focusrite
+ ID_MODEL_FROM_DATABASE=Saffire Pro 26
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# Revision with TCD2210.
+ieee1394:node:ven0x00130emo0x000005units0x00130e:0x000001
+ieee1394:ven0000130Emo00000005sp0000130Ever00000001
+ ID_VENDOR_FROM_DATABASE=Focusrite
+ ID_MODEL_FROM_DATABASE=Saffire Pro 40
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# Revision with TCD3070.
+ieee1394:node:ven0x00130emo0x0000deunits0x00130e:0x000001
+ieee1394:ven0000130Emo000000DEsp0000130Ever00000001
+ ID_VENDOR_FROM_DATABASE=Focusrite
+ ID_MODEL_FROM_DATABASE=Saffire Pro 40
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000fd7mo0x000001units0x000fd7:0x000001
+ieee1394:ven00000FD7mo00000001sp00000FD7ver00000001
+ ID_VENDOR_FROM_DATABASE=Harman Music Group
+ ID_MODEL_FROM_DATABASE=Lexicon I-ONIX FW810S
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000ff2mo0x000007units0x000ff2:0x000001
+ieee1394:ven00000FF2mo00000007sp00000FF2ver00000001
+ ID_VENDOR_FROM_DATABASE=Loud Technologies
+ ID_MODEL_FROM_DATABASE=Mackie Onyx Blackbird
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# Match to Onyx 1640i, and latter models of Onyx 820i, 1220i, and 1620i.
+ieee1394:node:ven0x000ff2mo0x000006units0x000ff2:0x000001
+ieee1394:ven00000FF2mo00000006sp00000FF2ver00000001
+ ID_VENDOR_FROM_DATABASE=Loud Technologies
+ ID_MODEL_FROM_DATABASE=Mackie Onyx-i series
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000d6cmo0x000011units0x000d6c:0x0100d1
+ieee1394:ven00000D6Cmo00000011sp00000D6Cver000100D1
+ ID_VENDOR_FROM_DATABASE=M-Audio
+ ID_MODEL_FROM_DATABASE=ProFire 610
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000d6cmo0x000010units0x000d6c:0x0100c1
+ieee1394:ven00000D6Cmo00000010sp00000D6Cver000100C1
+ ID_VENDOR_FROM_DATABASE=M-Audio
+ ID_MODEL_FROM_DATABASE=ProFire 2626
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x001ee8mo0x000002units0x001ee8:0x000001
+ieee1394:ven00001EE8mo00000002sp00001EE8ver00000001
+ ID_VENDOR_FROM_DATABASE=Mytek
+ ID_MODEL_FROM_DATABASE=Stereo192-DSD DAC
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x10c73fmo0x000001units0x10c73f:0x000001
+ieee1394:ven0010C73Fmo00000001sp0010C73Fver00000001
+ ID_VENDOR_FROM_DATABASE=Midas Klark Teknik
+ ID_MODEL_FROM_DATABASE=VeniceF series
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000a92mo0x000008units0x000a92:0x000001
+ieee1394:ven00000A92mo00000008sp00000A92ver00000001
+ ID_VENDOR_FROM_DATABASE=PreSonus
+ ID_MODEL_FROM_DATABASE=FireStudio
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000a92mo0x000011units0x000a92:0x000001
+ieee1394:ven00000A92mo00000011sp00000A92ver00000001
+ ID_VENDOR_FROM_DATABASE=PreSonus
+ ID_MODEL_FROM_DATABASE=FireStudio Mobile
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000a92mo0x00000bunits0x000a92:0x000001
+ieee1394:ven00000A92mo0000000Bsp00000A92ver00000001
+ ID_VENDOR_FROM_DATABASE=PreSonus
+ ID_MODEL_FROM_DATABASE=FireStudio Project
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000a92mo0x00000cunits0x000a92:0x000001
+ieee1394:ven00000A92mo0000000Csp00000A92ver00000001
+ ID_VENDOR_FROM_DATABASE=PreSonus
+ ID_MODEL_FROM_DATABASE=FireStudio Tube
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000a92mo0x000010units0x000a92:0x000001
+ieee1394:ven00000A92mo00000010sp00000A92ver00000001
+ ID_VENDOR_FROM_DATABASE=PreSonus
+ ID_MODEL_FROM_DATABASE=StudioLive 16.4.2
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000a92mo0x000012units0x000a92:0x000001
+ieee1394:ven00000A92mo00000012sp00000A92ver00000001
+ ID_VENDOR_FROM_DATABASE=PreSonus
+ ID_MODEL_FROM_DATABASE=StudioLive 24.4.2
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000a92mo0x000013units0x000a92:0x000001
+ieee1394:ven00000A92mo00000013sp00000A92ver00000001
+ ID_VENDOR_FROM_DATABASE=PreSonus
+ ID_MODEL_FROM_DATABASE=StudioLive 16.0.2
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000a92mo0x000014units0x000a92:0x000001
+ieee1394:ven00000A92mo00000014sp00000A92ver00000001
+ ID_VENDOR_FROM_DATABASE=PreSonus
+ ID_MODEL_FROM_DATABASE=StudioLive 32.4.2AI
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# Unregistered OUI. Match to Duende Classic and Duende Mini. They are differentiated by category
+# field of GUID (0x51/0x52) in TCAT specification.
+ieee1394:node:ven0x0050c2mo0x000070units0x0050c2:0x000001
+ieee1394:ven000050C2mo00000070sp000050C2ver00000001
+ ID_VENDOR_FROM_DATABASE=Solid State Logic
+ ID_MODEL_FROM_DATABASE=Duende FireWire
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000166mo0x000024units0x000166:0x000001
+ieee1394:ven00000166mo00000024sp00000166ver00000001
+ ID_VENDOR_FROM_DATABASE=TC Electronic
+ ID_MODEL_FROM_DATABASE=Desktop Konnekt 6
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000166mo0x000030units0x000166:0x000001
+ieee1394:ven00000166mo00000030sp00000166ver00000001
+ ID_VENDOR_FROM_DATABASE=TC Electronic
+ ID_MODEL_FROM_DATABASE=Digital Konnekt x32
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000166mo0x000027units0x000166:0x000001
+ieee1394:ven00000166mo00000027sp00000166ver00000001
+ ID_VENDOR_FROM_DATABASE=TC Electronic
+ ID_MODEL_FROM_DATABASE=Impact Twin
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000166mo0x000020units0x000166:0x000001
+ieee1394:ven00000166mo00000020sp00000166ver00000001
+ ID_VENDOR_FROM_DATABASE=TC Electronic
+ ID_MODEL_FROM_DATABASE=Konnekt 24D
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000166mo0x000021units0x000166:0x000001
+ieee1394:ven00000166mo00000021sp00000166ver00000001
+ ID_VENDOR_FROM_DATABASE=TC Electronic
+ ID_MODEL_FROM_DATABASE=Konnekt 8
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000166mo0x000023units0x000166:0x000001
+ieee1394:ven00000166mo00000023sp00000166ver00000001
+ ID_VENDOR_FROM_DATABASE=TC Electronic
+ ID_MODEL_FROM_DATABASE=Konnekt Live
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000166mo0x000022units0x000166:0x000001
+ieee1394:ven00000166mo00000022sp00000166ver00000001
+ ID_VENDOR_FROM_DATABASE=TC Electronic
+ ID_MODEL_FROM_DATABASE=Studio Konnekt 48
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x001c6amo0x000001units0x001c6a:0x000001
+ieee1394:ven00001C6Amo00000001sp00001C6Aver00000001
+ ID_VENDOR_FROM_DATABASE=Weiss Engineering
+ ID_MODEL_FROM_DATABASE=ADC2
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x001c6amo0x000002units0x001c6a:0x000001
+ieee1394:ven00001C6Amo00000002sp00001C6Aver00000001
+ ID_VENDOR_FROM_DATABASE=Weiss Engineering
+ ID_MODEL_FROM_DATABASE=Vesta
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x001c6amo0x000003units0x001c6a:0x000001
+ieee1394:ven00001C6Amo00000003sp00001C6Aver00000001
+ ID_VENDOR_FROM_DATABASE=Weiss Engineering
+ ID_MODEL_FROM_DATABASE=Minerva
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x001c6amo0x000004units0x001c6a:0x000001
+ieee1394:ven00001C6Amo00000004sp00001C6Aver00000001
+ ID_VENDOR_FROM_DATABASE=Weiss Engineering
+ ID_MODEL_FROM_DATABASE=AFI1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x001c6amo0x000005units0x001c6a:0x000001
+ieee1394:ven00001C6Amo00000005sp00001C6Aver00000001
+ ID_VENDOR_FROM_DATABASE=Weiss Engineering
+ ID_MODEL_FROM_DATABASE=DAC1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x001c6amo0x000006units0x001c6a:0x000001
+ieee1394:ven00001C6Amo00000006sp00001C6Aver00000001
+ ID_VENDOR_FROM_DATABASE=Weiss Engineering
+ ID_MODEL_FROM_DATABASE=INT202
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x001c6amo0x000007units0x001c6a:0x000001
+ieee1394:ven00001C6Amo00000007sp00001C6Aver00000001
+ ID_VENDOR_FROM_DATABASE=Weiss Engineering
+ ID_MODEL_FROM_DATABASE=DAC202
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+#
+# Digidesign Digi00x family.
+#
+
+ieee1394:node:ven0x00a07eunits0x0000a3:0x000001
+ieee1394:ven0000A07Emo00000001sp000000A3ver00000001
+ ID_VENDOR_FROM_DATABASE=Digidesign
+ ID_MODEL_FROM_DATABASE=Digi 002
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00a07eunits0x0000a4:0x000001
+ieee1394:ven0000A07Emo00000002sp000000A4ver00000001
+ ID_VENDOR_FROM_DATABASE=Digidesign
+ ID_MODEL_FROM_DATABASE=Digi 002Rack
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00a07eunits0x0000aa:0x000001
+ieee1394:ven0000A07Emo00000001sp000000AAver00000001
+ ID_VENDOR_FROM_DATABASE=Digidesign
+ ID_MODEL_FROM_DATABASE=Digi 003
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00a07eunits0x0000ab:0x000001
+ieee1394:ven0000A07Emo00000002sp000000ABver00000001
+ ID_VENDOR_FROM_DATABASE=Digidesign
+ ID_MODEL_FROM_DATABASE=Digi 003 Rack
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+#
+# Tascam FireWire series.
+#
+
+ieee1394:node:ven0x00022eunits0x00022e:0x800001
+ieee1394:ven0000022Emo00000000sp0000022Ever00800001
+ ID_VENDOR_FROM_DATABASE=Tascam
+ ID_MODEL_FROM_DATABASE=FE-8
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+
+ieee1394:node:ven0x00022eunits0x00022e:0x800003
+ieee1394:ven0000022Emo00000000sp0000022Ever00800003
+ ID_VENDOR_FROM_DATABASE=Tascam
+ ID_MODEL_FROM_DATABASE=FW-1082
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00022eunits0x00022e:0x800004
+ieee1394:ven0000022Emo00000000sp0000022Ever00800004
+ ID_VENDOR_FROM_DATABASE=Tascam
+ ID_MODEL_FROM_DATABASE=FW-1804
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00022eunits0x00022e:0x800000
+ieee1394:ven0000022Emo00000000sp0000022Ever00800000
+ ID_VENDOR_FROM_DATABASE=Tascam
+ ID_MODEL_FROM_DATABASE=FW-1884
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+#
+# Mark of the Unicorn FireWire series.
+#
+# The model field in unit directory should be ignored since it expresses firmware version.
+#
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x000001
+ieee1394:ven000001F2mo*sp000001F2ver00000001
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=MOTU 828
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x000002
+ieee1394:ven000001F2mo*sp000001F2ver00000002
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=MOTU 896
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x000003
+ieee1394:ven000001F2mo*sp000001F2ver00000003
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=MOTU 828 mkII
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x000005
+ieee1394:ven000001F2mo*sp000001F2ver00000005
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=MOTU 896 HD
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x000009
+ieee1394:ven000001F2mo*sp000001F2ver00000009
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=Traveler
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x00000d
+ieee1394:ven000001F2mo*sp000001F2ver0000000D
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=UltraLite
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x00000f
+ieee1394:ven000001F2mo*sp000001F2ver0000000F
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=MOTU 8pre
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x000015
+ieee1394:ven000001F2mo*sp000001F2ver00000015
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=MOTU 828 mk3 FireWire
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x000017
+ieee1394:ven000001F2mo*sp000001F2ver00000017
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=MOTU 896 mk3 FireWire
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x000019
+ieee1394:ven000001F2mo*sp000001F2ver00000019
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=UltraLite mk3 FireWire
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x00001b
+ieee1394:ven000001F2mo*sp000001F2ver0000001B
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=Traveler mk3
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x000030
+ieee1394:ven000001F2mo*sp000001F2ver00000030
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=UltraLite mk3 Hybrid
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x000033
+ieee1394:ven000001F2mo*sp000001F2ver00000033
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=Audio Express
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x000035
+ieee1394:ven000001F2mo*sp000001F2ver00000035
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=MOTU 828 mk3 Hybrid
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x0001f2units0x0001f2:0x000045
+ieee1394:ven000001F2mo*sp000001F2ver00000045
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=MOTU 4pre
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+#
+# RME Fireface series.
+#
+ieee1394:node:ven0x000a35units0x000a35:0x000001
+ieee1394:ven00000A35mo00101800sp00000A35ver00000001
+ ID_VENDOR_FROM_DATABASE=RME
+ ID_MODEL_FROM_DATABASE=Fireface 800
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000a35units0x000a35:0x000002
+ieee1394:ven00000A35mo00101800sp00000A35ver00000002
+ ID_VENDOR_FROM_DATABASE=RME
+ ID_MODEL_FROM_DATABASE=Fireface 400
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000a35units0x000a35:0x000003
+ieee1394:ven00000A35mo00101800sp00000A35ver00000003
+ ID_VENDOR_FROM_DATABASE=RME
+ ID_MODEL_FROM_DATABASE=Fireface UFX
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000a35units0x000a35:0x000004
+ieee1394:ven00000A35mo00101800sp00000A35ver00000004
+ ID_VENDOR_FROM_DATABASE=RME
+ ID_MODEL_FROM_DATABASE=Fireface UCX
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000a35units0x000a35:0x000005
+ieee1394:ven00000A35mo00101800sp00000A35ver00000005
+ ID_VENDOR_FROM_DATABASE=RME
+ ID_MODEL_FROM_DATABASE=Fireface 802
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+#
+# Yamaha mLAN 2nd generation.
+#
+# The combination of Yamaha mLAN-NC1, Yamaha mLAN-PH2, and Fujifilm PHY MD8408B.
+#
+
+ieee1394:node:ven0x000a92mo0x000000units0x00a0de:0xffffff
+ieee1394:ven00000A92mo00000000sp0000A0DEver00FFFFFF
+ ID_VENDOR_FROM_DATABASE=PreSonus
+ ID_MODEL_FROM_DATABASE=FIREStation
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00a0demo0x100005units0x00a0de:0xffffff
+ieee1394:ven0000A0DEmo00100005sp0000A0DEver00FFFFFF
+ ID_VENDOR_FROM_DATABASE=Yamaha
+ ID_MODEL_FROM_DATABASE=01X
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00a0demo0x100007units0x00a0de:0xffffff
+ieee1394:ven0000A0DEmo00100007sp0000A0DEver00FFFFFF
+ ID_VENDOR_FROM_DATABASE=Yamaha
+ ID_MODEL_FROM_DATABASE=i88X
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+#
+# Yamaha mLAN 3rd generation.
+#
+# DICE II ASIC is used with specific firmware.
+#
+
+ieee1394:node:ven0x00a0demo0x100013units0x00a02d:0x000300
+ieee1394:ven0000A0DEmo00100013sp0000A02Dver00000300
+ ID_VENDOR_FROM_DATABASE=Steinberg
+ ID_MODEL_FROM_DATABASE=MR816
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00a0demo0x100010units0x00a02d:0x000300
+ieee1394:ven0000A0DEmo00100010sp0000A02Dver00000300
+ ID_VENDOR_FROM_DATABASE=Yamaha
+ ID_MODEL_FROM_DATABASE=n8
+ IEEE1394_UNIT_FUNCTION_MIDI=1
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+#
+# Focusrite Liquid Mix series.
+#
+# OEM by Sintefex Audio lda.
+#
+
+ieee1394:node:ven0x00130eunits0x00130e:0x000700
+ieee1394:ven0000130Emo00010204sp0000130Ever00000700
+ ID_VENDOR_FROM_DATABASE=Focusrite
+ ID_MODEL_FROM_DATABASE=Liquid Mix 16
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x00130eunits0x00130e:0x000200
+ieee1394:ven0000130Emo00010200sp0000130Ever00000200
+ ID_VENDOR_FROM_DATABASE=Focusrite
+ ID_MODEL_FROM_DATABASE=Liquid Mix 32
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+#
+# TC Electronic PowerCore series.
+#
+# Consists of NXP PowerQUICC II Processor with PCI interface (XPC8245, MPC8245), Texus Instruments
+# OHCI 1.1, 1394a link layer controller (TSB43AB23). Xilinx Spartan-II FPGA (XC2S50), and some
+# NXP 24-Bit Audio Digital Signal Processor (DSP56367).
+#
+
+ieee1394:node:ven0x000166mo0x000001units0x00a02d:0x000000
+ieee1394:ven00000166mo00000001sp0000A02Dver00000000
+ ID_VENDOR_FROM_DATABASE=TC Electronic
+ ID_MODEL_FROM_DATABASE=PowerCore FireWire
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+ieee1394:node:ven0x000166mo0x000002units0x00a02d:0x014000
+ieee1394:ven00000166mo00000002sp0000A02Dver00014000
+ ID_VENDOR_FROM_DATABASE=TC Electronic
+ ID_MODEL_FROM_DATABASE=PowerCore Compact
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=0
+
+# Match to Adrenaline, Mojo, and V10.
+ieee1394:node:ven0x00a07eunits0x00a02d:0x014001
+ieee1394:ven0000A07Emo00000001sp0000A02Dver00014001
+ ID_VENDOR_FROM_DATABASE=Avid Technology
+ ID_MODEL_FROM_DATABASE=Digital Nonlinear Accelerator
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+#
+# Point Grey cameras.
+#
+
+# IIDC v1.04 compatible.
+ieee1394:node:ven0x00b09dmo*units0x00b09d:0x000100
+ieee1394:ven0000B09Dmo*spec0000B09Dver00000100
+ ID_VENDOR_FROM_DATABASE=Point Grey Research
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+# IIDC v1.20 compatible.
+ieee1394:node:ven0x00b09dmo*units0x00b09d:0x000101
+ieee1394:ven0000B09Dmo*spec0000B09Dver00000101
+ ID_VENDOR_FROM_DATABASE=Point Grey Research
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+# IIDC v1.30/v1.31/v1.32 compatible.
+ieee1394:node:ven0x00b09dmo*units0x00b09d:0x000102
+ieee1394:ven0000B09Dmo*spec0000B09Dver00000102
+ ID_VENDOR_FROM_DATABASE=Point Grey Research
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+# Unique protocol.
+ieee1394:node:ven0x00b09dmo*units0x00b09d:0x000114
+ieee1394:ven0000B09Dmo*spec0000B09Dver00000114
+ ID_VENDOR_FROM_DATABASE=Point Grey Research
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+#
+# Digital Everywhere FloppyDTV and FireDtv series.
+#
+
+ieee1394:node:ven0x001287mo0x000024units0x00a02d:0x010001
+ieee1394:ven00001287mo00000024sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Digital Everywhere
+ ID_MODEL_FROM_DATABASE=FloppyDTV S/CI
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+ieee1394:node:ven0x001287mo0x000025units0x00a02d:0x010001
+ieee1394:ven00001287mo00000025sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Digital Everywhere
+ ID_MODEL_FROM_DATABASE=FloppyDTV T/CI
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+ieee1394:node:ven0x001287mo0x000026units0x00a02d:0x010001
+ieee1394:ven00001287mo00000026sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Digital Everywhere
+ ID_MODEL_FROM_DATABASE=FloppyDTV C/CI
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+ieee1394:node:ven0x001287mo0x000034units0x00a02d:0x010001
+ieee1394:ven00001287mo00000034sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Digital Everywhere
+ ID_MODEL_FROM_DATABASE=FireDTV S/CI
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+ieee1394:node:ven0x001287mo0x000035units0x00a02d:0x010001
+ieee1394:ven00001287mo00000035sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Digital Everywhere
+ ID_MODEL_FROM_DATABASE=FireDTV T/CI
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+ieee1394:node:ven0x001287mo0x000036units0x00a02d:0x010001
+ieee1394:ven00001287mo00000036sp0000A02Dver00010001
+ ID_VENDOR_FROM_DATABASE=Digital Everywhere
+ ID_MODEL_FROM_DATABASE=FireDTV C/CI
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+#
+# Node with multiple units for several functions.
+#
+# When deciding the type of unit, please cooperate with kernel developers working for driver.
+#
+
+# Apple iSight: unit 0: IIDC v1.30 function.
+ieee1394:node:ven0x080007mo0x000008units*0x00a02d:0x000102*
+ieee1394:ven00080007mo00000008sp0000A02Dver00000102
+ ID_VENDOR_FROM_DATABASE=Apple
+ ID_MODEL_FROM_DATABASE=iSight
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+# Apple iSight: unit 1: audio function.
+ieee1394:node:ven0x080007mo0x000008units*0x000a27:0x000010*
+ieee1394:ven00080007mo00000008sp00000A27ver00000010
+ ID_VENDOR_FROM_DATABASE=Apple
+ ID_MODEL_FROM_DATABASE=iSight
+ IEEE1394_UNIT_FUNCTION_AUDIO=1
+
+# Apple iSight: unit 2: factory function.
+ieee1394:node:ven0x080007mo0x000008units*0x000a27:0x000011*
+ieee1394:ven00080007mo00000008sp00000A27ver00000011
+ ID_VENDOR_FROM_DATABASE=Apple
+ ID_MODEL_FROM_DATABASE=iSight
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+# Apple iSight: unit 3: iris diaphragm function.
+ieee1394:node:ven0x080007mo0x000008units*0x000a27:0x000012*
+ieee1394:ven00080007mo00000008sp00000A27ver00000012
+ ID_VENDOR_FROM_DATABASE=Apple
+ ID_MODEL_FROM_DATABASE=iSight
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+# MOTU V4HD: unit 0: unknown function.
+ieee1394:node:ven0x0001f2units*0x0001f2:0x000021*
+ieee1394:ven000001F2mo*sp000001F2ver00000021
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=MOTU V4HD
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+# MOTU V4HD: unit 1: unknown function.
+ieee1394:node:ven0x0001f2units*0x0001f2:0x000022*
+ieee1394:ven000001F2mo*sp000001F2ver00000022
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=MOTU V4HD
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+# MOTU V4HD: unit 2: unknown function.
+ieee1394:node:ven0x0001f2units*0x0001f2:0x000023*
+ieee1394:ven000001F2mo*sp000001F2ver00000023
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=MOTU V4HD
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
+
+# MOTU V4HD: unit 3: unknown function.
+ieee1394:node:ven0x0001f2units*0x0001f2:0x000024*
+ieee1394:ven000001F2mo*sp000001F2ver00000024
+ ID_VENDOR_FROM_DATABASE=MOTU
+ ID_MODEL_FROM_DATABASE=MOTU V4HD
+ IEEE1394_UNIT_FUNCTION_VIDEO=1
index 7221a1ae9f64bf0b5eba5df3a6f7e8ba174757bb..6a16268816bd75fb3adeac27ec6818fb9575ffd9 100644 (file)
@@ -30,6 +30,7 @@ hwdb_files_test = files('''
         70-mouse.hwdb
         70-pointingstick.hwdb
         70-touchpad.hwdb
+        80-ieee1394-unit-function.hwdb
 '''.split())
 
 if conf.get('ENABLE_HWDB') == 1
index 24964ff8d16bcadd16619688c8f7ccda146c3e18..6d88766f0b2b8bfeb862e49a948ede26678a7560 100755 (executable)
@@ -72,6 +72,7 @@ TYPES = {'mouse':    ('usb', 'bluetooth', 'ps2', '*'),
          'joystick': ('i8042', 'rmi', 'bluetooth', 'usb'),
          'keyboard': ('name', ),
          'sensor':   ('modalias', ),
+         'ieee1394-unit-function' : ('node', ),
         }
 
 # Patterns that are used to set general properties on a device
@@ -82,6 +83,7 @@ GENERAL_MATCHES = {'acpi',
                    'sdio',
                    'vmbus',
                    'OUI',
+                   'ieee1394',
                    }
 
 def upperhex_word(length):
@@ -99,7 +101,7 @@ def hwdb_grammar():
     matchline = (matchline_typed | matchline_general) + EOL
 
     propertyline = (White(' ', exact=1).suppress() +
-                    Combine(UDEV_TAG - '=' - Optional(Word(alphanums + '_=:@*.!-;, "'))
+                    Combine(UDEV_TAG - '=' - Optional(Word(alphanums + '_=:@*.!-;, "/'))
                             - Optional(pythonStyleComment)) +
                     EOL)
     propertycomment = White(' ', exact=1) + pythonStyleComment + EOL
@@ -122,6 +124,9 @@ def property_grammar():
     mount_matrix = Group(mount_matrix_row + ';' + mount_matrix_row + ';' + mount_matrix_row)('MOUNT_MATRIX')
     xkb_setting = Optional(Word(alphanums + '+-/@._'))
 
+    # Although this set doesn't cover all of characters in database entries, it's enough for test targets.
+    name_literal = Word(printables + ' ')
+
     props = (('MOUSE_DPI', Group(OneOrMore(dpi_setting))),
              ('MOUSE_WHEEL_CLICK_ANGLE', INTEGER),
              ('MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL', INTEGER),
@@ -153,6 +158,11 @@ def property_grammar():
              ('ACCEL_MOUNT_MATRIX', mount_matrix),
              ('ACCEL_LOCATION', Or(('display', 'base'))),
              ('PROXIMITY_NEAR_LEVEL', INTEGER),
+             ('IEEE1394_UNIT_FUNCTION_MIDI', Or((Literal('0'), Literal('1')))),
+             ('IEEE1394_UNIT_FUNCTION_AUDIO', Or((Literal('0'), Literal('1')))),
+             ('IEEE1394_UNIT_FUNCTION_VIDEO', Or((Literal('0'), Literal('1')))),
+             ('ID_VENDOR_FROM_DATABASE', name_literal),
+             ('ID_MODEL_FROM_DATABASE', name_literal),
             )
     fixed_props = [Literal(name)('NAME') - Suppress('=') - val('VALUE')
                    for name, val in props]
@@ -291,7 +301,7 @@ def print_summary(fname, groups):
         error('{}: no matches or props'.format(fname))
 
 if __name__ == '__main__':
-    args = sys.argv[1:] or sorted(glob.glob(os.path.dirname(sys.argv[0]) + '/[67][0-9]-*.hwdb'))
+    args = sys.argv[1:] or sorted(glob.glob(os.path.dirname(sys.argv[0]) + '/[678][0-9]-*.hwdb'))
 
     for fname in args:
         groups = parse(fname)
index 878f24742e8e3f54c28ff4cab764800254880100..5dfed110dddd8dd21052598894b1983b84158da1 100644 (file)
         cannot be written. Currently only applies to random seed operations.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--make-machine-id-directory=yes|no|auto</option></term>
+        <listitem><para>Control creation and deletion of <literal>$ESP/$MACHINE_ID</literal> during
+        <option>install</option> and <option>remove</option>, respectively.
+        <literal>auto</literal> is equivalent to to <literal>yes</literal> if <literal>/etc/machine-id</literal>
+        resides on a filesystem other than tmpfs and <literal>no</literal> otherwise.
+        Defaults to <literal>auto</literal>.</para>
+
+        <para>Overriding this may be desired to hide the machine ID from the (unencrypted) ESP,
+        configure a <citerefentry><refentrytitle>kernel-install</refentrytitle><manvolnum>8</manvolnum></citerefentry> script, or,
+        conversely, commit a machine-id that only appears transient.</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"/>
index 942a31db7454336bcf82f1b9f51d4c3fbefce9c9..5f1b4ce028cc22e0e63c045433dba21aa63de958 100644 (file)
@@ -35,7 +35,7 @@
     <citerefentry><refentrytitle>systemd-coredump</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
     a handler for core dumps invoked by the kernel. Whether <command>systemd-coredump</command> is used
     is determined by the kernel's
-    <varname>kernel.core_pattern</varname> <citerefentry project='man-pages'><refentrytitle>sysctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+    <varname>kernel.core_pattern</varname> <citerefentry project='man-pages'><refentrytitle>sysctl</refentrytitle><manvolnum>8</manvolnum></citerefentry>
     setting. See
     <citerefentry><refentrytitle>systemd-coredump</refentrytitle><manvolnum>8</manvolnum></citerefentry>
     and
@@ -86,7 +86,9 @@
         <listitem><para>The maximum size in bytes of a core
         which will be processed. Core dumps exceeding this size
         may be stored, but the backtrace will not be generated.
-        </para>
+        Like other sizes in this same config file, the usual
+        suffixes to the base of 1024 are allowed (B, K, M, 
+        G, T, P, and E.)</para>
 
         <para>Setting <varname>Storage=none</varname> and <varname>ProcessSizeMax=0</varname>
         disables all coredump handling except for a log entry.</para>
         <term><varname>JournalSizeMax=</varname></term>
 
         <listitem><para>The maximum (uncompressed) size in bytes of a
-        core to be saved.</para></listitem>
+        core to be saved. Unit suffixes are allowed just as in 
+        <option>ProcessSizeMax=</option></para></listitem>.
       </varlistentry>
 
       <varlistentry>
         <term><varname>MaxUse=</varname></term>
         <term><varname>KeepFree=</varname></term>
 
-        <listitem><para>Enforce limits on the disk space taken up by
-        externally stored core dumps. <option>MaxUse=</option> makes
+        <listitem><para>Enforce limits on the disk space, specified
+        in bytes, taken up by externally stored core dumps.
+        Unit suffixes are allowed just as in <option>ProcessSizeMax=</option>.
+        <option>MaxUse=</option> makes
         sure that old core dumps are removed as soon as the total disk
         space taken up by core dumps grows beyond this limit (defaults
         to 10% of the total disk size). <option>KeepFree=</option>
index 9963322fc9a88945000aec6eeb5609633a4d147c..8e494c7371aa813069f8a59e3b9705b27183aea7 100644 (file)
@@ -11,5 +11,5 @@
 <!ENTITY KILL_USER_PROCESSES @KILL_USER_PROCESSES_YES_NO@>
 <!ENTITY DEBUGTTY @DEBUGTTY@>
 <!ENTITY RC_LOCAL_PATH @RC_LOCAL_PATH@>
-<!ENTITY fedora_latest_version "33">
+<!ENTITY fedora_latest_version "34">
 <!ENTITY fedora_cloud_release "1.2">
index 184bdcf6fd0305271faf9e0e6d6127192bbb3923..f2858166f7babdde64d67265d4bb9ed83ab532fc 100644 (file)
     <title>Exit status</title>
 
     <para>On success, 0 is returned, a non-zero failure code otherwise.</para>
+
+    <para>When a command is invoked with <command>with</command>, the exit status of the child is
+    propagated. Effectively, <command>homectl</command> will exit without error if the command is
+    successfully invoked <emphasis>and</emphasis> finishes successfully.</para>
   </refsect1>
 
   <xi:include href="common-variables.xml" />
index 8be8972907c902568010006e7313d183b724e220..51f83d1cd63fd33ad7314dcd039fa8377a2a3218 100644 (file)
       <varlistentry>
         <term><command>status</command></term>
 
-        <listitem><para>Show current system hostname and related information. If no command is specified,
+        <listitem><para>Show system hostname and related information. If no command is specified,
         this is the implied default.</para></listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><command>set-hostname <replaceable>NAME</replaceable></command></term>
+        <term><command>hostname</command> [<replaceable>NAME</replaceable>]</term>
 
-        <listitem><para>Set the system hostname to <replaceable>NAME</replaceable>. By default, this will alter the
+        <listitem><para>If no argument is given, print the system hostname. If an
+        optional argument <replaceable>NAME</replaceable> is provided then the command changes the
+        system hostname to <replaceable>NAME</replaceable>. By default, this will alter the
         pretty, the static, and the transient hostname alike; however, if one or more of <option>--static</option>,
         <option>--transient</option>, <option>--pretty</option> are used, only the selected hostnames are changed. If
         the pretty hostname is being set, and static or transient are being set as well, the specified hostname will be
         <para>The static and transient hostnames must each be either a single DNS label (a string composed of
         7-bit ASCII lower-case characters and no spaces or dots, limited to the format allowed for DNS domain
         name labels), or a sequence of such labels separated by single dots that forms a valid DNS FQDN. The
-        hostname must be at most 64 characters, which is a Linux limitation (DNS allows longer names).</para>
-
-        <para>Pass the empty string <literal></literal> as the hostname to reset the selected hostnames to
-        their default (usually <literal>&FALLBACK_HOSTNAME;</literal>).</para></listitem>
+        hostname must be at most 64 characters, which is a Linux limitation (DNS allows longer names).</para></listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><command>set-icon-name <replaceable>NAME</replaceable></command></term>
+        <term><command>icon-name</command> [<replaceable>NAME</replaceable>]</term>
 
-        <listitem><para>Set the system icon name to
-        <replaceable>NAME</replaceable>. The icon name is used by some
+        <listitem><para>If no argument is given, print the icon name of the system. If an
+        optional argument <replaceable>NAME</replaceable> is provided then the command changes the
+        icon name to <replaceable>NAME</replaceable>. The icon name is used by some
         graphical applications to visualize this host. The icon name
         should follow the <ulink
         url="http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html">Icon
-        Naming Specification</ulink>.</para>
-
-        <para>Pass an empty string to reset the icon name to the
-        default value, which is determined from chassis type (see
-        below) and possibly other parameters.</para></listitem>
+        Naming Specification</ulink>.</para></listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><command>set-chassis <replaceable>TYPE</replaceable></command></term>
+        <term><command>chassis</command> [<replaceable>TYPE</replaceable>]</term>
 
-        <listitem><para>Set the chassis type to
-        <replaceable>TYPE</replaceable>. The chassis type is used by
-        some graphical applications to visualize the host or alter
-        user interaction. Currently, the following chassis types are
-        defined:
+        <listitem><para>If no argument is given, print the chassis type. If an
+        optional argument <replaceable>TYPE</replaceable> is provided then the command changes the
+        chassis type to <replaceable>TYPE</replaceable>. The chassis type is used by
+        some graphical applications to visualize the host or alter user interaction.
+        Currently, the following chassis types are defined:
         <literal>desktop</literal>,
         <literal>laptop</literal>,
         <literal>convertible</literal>,
         <literal>vm</literal> and
         <literal>container</literal> for virtualized systems that lack
         an immediate physical chassis.</para>
-
-        <para>Pass an empty string to reset the chassis type to the
-        default value which is determined from the firmware and
-        possibly other parameters.</para>
         </listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><command>set-deployment <replaceable>ENVIRONMENT</replaceable></command></term>
+        <term><command>deployment</command> [<replaceable>ENVIRONMENT</replaceable>]</term>
 
-        <listitem><para>Set the deployment environment description.
-        <replaceable>ENVIRONMENT</replaceable> must be a single word
-        without any control characters. One of the following is
-        suggested:
+        <listitem><para>If no argument is given, print the deployment environment. If an
+        optional argument <replaceable>ENVIRONMENT</replaceable> is provided then the command changes the
+        deployment environment to <replaceable>ENVIRONMENT</replaceable>.
+        Argument <replaceable>ENVIRONMENT</replaceable>
+        must be a single word without any control characters. One of the following is suggested:
         <literal>development</literal>,
         <literal>integration</literal>,
         <literal>staging</literal>,
         <literal>production</literal>.
         </para>
-
-        <para>Pass an empty string to reset to the default empty
-        value.</para>
         </listitem>
       </varlistentry>
 
       <varlistentry>
-        <term><command>set-location <replaceable>LOCATION</replaceable></command></term>
+        <term><command>location</command> [<replaceable>LOCATION</replaceable>]</term>
 
-        <listitem><para>Set the location string for the system, if it
-        is known. <replaceable>LOCATION</replaceable> should be a
+        <listitem><para>If no argument is given, print the location string for the system. If an
+        optional argument <replaceable>LOCATION</replaceable> is provided then the command changes the
+        location string for the system to <replaceable>LOCATION</replaceable>.
+        Argument <replaceable>LOCATION</replaceable> should be a
         human-friendly, free-form string describing the physical
         location of the system, if it is known and applicable. This
         may be as generic as <literal>Berlin, Germany</literal> or as
         specific as <literal>Left Rack, 2nd Shelf</literal>.</para>
-
-        <para>Pass an empty string to reset to the default empty
-        value.</para>
         </listitem>
       </varlistentry>
     </variablelist>
 
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
+      <xi:include href="standard-options.xml" xpointer="json" />
     </variablelist>
   </refsect1>
 
index 86137a951de82bfe6f668629e0a4663b519ab51a..06583d5ed3f42838387972608deb2d0049c076e3 100644 (file)
         the kernel log buffer, or a syslog socket will still work). Defaults to <literal>auto</literal> in
         the default journal namespace, and <literal>persistent</literal> in all others.</para>
 
+        <para>Note that journald will initially use volatile storage, until a call to 
+        <command>journalctl --flush</command> (or sending <constant>SIGUSR1</constant> to journald) will cause 
+        it to switch to persistent logging (under the conditions mentioned above). This is done automatically
+        on boot via <literal>systemd-journal-flush.service</literal>.</para>
+
         <para>Note that when this option is changed to <literal>volatile</literal>, existing persistent data
         is not removed. In the other direction,
         <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> with
index 3cae8446cda77c1194ebd61c03f598c89cd683f6..f9c4b83dc8150a839591edd9b859a92605d6920c 100644 (file)
@@ -184,17 +184,20 @@ html = custom_target(
         depends : html_pages,
         command : ['echo'])
 
-run_target(
-        'doc-sync',
-        depends : man_pages + html_pages,
-        command : ['rsync', '-rlv',
-                   '--delete-excluded',
-                   '--include=man',
-                   '--include=*.html',
-                   '--exclude=*',
-                   '--omit-dir-times',
-                   meson.current_build_dir(),
-                   get_option('www-target')])
+rsync = find_program('rsync', required : false)
+if rsync.found()
+        run_target(
+                'doc-sync',
+                depends : man_pages + html_pages,
+                command : [rsync, '-rlv',
+                           '--delete-excluded',
+                           '--include=man',
+                           '--include=*.html',
+                           '--exclude=*',
+                           '--omit-dir-times',
+                           meson.current_build_dir(),
+                           get_option('www-target')])
+endif
 
 ############################################################
 
index dcce2095edd2fb5e377852b263bdba84c7c02567..85b21ee7f98174ee918c816db1319b73d680f8cf 100644 (file)
         If <varname>SpeedMeter=no</varname>, the value is ignored. Defaults to 10sec.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>ManageForeignRoutingPolicyRules=</varname></term>
+        <listitem><para>A boolean. When true, <command>systemd-networkd</command> will remove rules
+        that are not configured in .network files (except for rules with protocol
+        <literal>kernel</literal>). When false, it will not remove any foreign rules, keeping them even
+        if they are not configured in a .network file. Defaults to yes.
+        </para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>ManageForeignRoutes=</varname></term>
-        <listitem><para>A boolean. When true, <command>systemd-networkd</command> will store any routes
-        configured by other tools in its memory. When false, <command>systemd-networkd</command> will
-        not manage the foreign routes, thus they are kept even if <varname>KeepConfiguration=</varname>
-        is false. Defaults to yes.</para></listitem>
+        <listitem><para>A boolean. When true, <command>systemd-networkd</command> will remove routes
+        that are not configured in .network files (except for routes with protocol
+        <literal>kernel</literal>, <literal>dhcp</literal> when <varname>KeepConfiguration=</varname>
+        is true or <literal>dhcp</literal>, and <literal>static</literal> when
+        <varname>KeepConfiguration=</varname> is true or <literal>static</literal>). When false, it will
+        not remove any foreign routes, keeping them even if they are not configured in a .network file.
+        Defaults to yes.</para></listitem>
       </varlistentry>
 
       <varlistentry>
   </refsect1>
 
   <refsect1>
-    <title>[DHCP] Section Options</title>
-
-    <para>This section configures the DHCP Unique Identifier (DUID) value used by DHCP
-    protocol. DHCPv6 client protocol sends the DHCP Unique Identifier and the interface
-    Identity Association Identifier (IAID) to a DHCP server when acquiring a dynamic IPv6
-    address. DHCPv4 client protocol sends IAID and DUID to the DHCP server when acquiring
-    a dynamic IPv4 address if <option>ClientIdentifier=duid</option>. IAID and DUID allows
-    a DHCP server to uniquely identify the machine and the interface requesting a DHCP IP.
-    To configure IAID and ClientIdentifier, see
+    <title>[DHCPv4] Section Options</title>
+
+    <para>This section configures the DHCP Unique Identifier (DUID) value used by DHCP protocol. DHCPv4
+    client protocol sends IAID and DUID to the DHCP server when acquiring a dynamic IPv4 address if
+    <option>ClientIdentifier=duid</option>. IAID and DUID allows a DHCP server to uniquely identify the
+    machine and the interface requesting a DHCP IP address. To configure IAID and ClientIdentifier, see
     <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
     </para>
 
@@ -176,6 +185,28 @@ DUIDRawData=00:00:ab:11:f9:2a:c2:77:29:f9:5c:00</programlisting>
     </variablelist>
   </refsect1>
 
+  <refsect1>
+    <title>[DHCPv6] Section Options</title>
+
+    <para>This section configures the DHCP Unique Identifier (DUID) value used by DHCPv6 protocol.
+    DHCPv6 client protocol sends the DHCP Unique Identifier and the interface Identity Association
+    Identifier (IAID) to a DHCPv6 server when acquiring a dynamic IPv6 address. IAID and DUID allows a
+    DHCPv6 server to uniquely identify the machine and the interface requesting a DHCP IP address. To
+    configure IAID, see
+    <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+    </para>
+
+    <para>The following options are understood:</para>
+
+    <variablelist class='network-directives'>
+      <varlistentry>
+        <term><varname>DUIDType=</varname></term>
+        <term><varname>DUIDRawData=</varname></term>
+        <listitem><para>As in the [DHCPv4] section.</para></listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
   <refsect1>
       <title>See Also</title>
       <para>
index 8d5b549c3b142798a0f3afc389f49e5d15e8bcea..8a603fb9ce4ce3e1e690c0af138c9c36f30b2958 100644 (file)
       ordered by their metric. This assigns a stable hostname to the
       current gateway, useful for referencing it independently of the
       current network configuration state.</para></listitem>
+
+      <listitem><para>The hostname <literal>_outbound</literal> is resolved to the local IPv4 and IPv6
+      addresses that are most likely used for communication with other hosts. This is determined by
+      requesting a routing decision to the configured default gateways from the kernel and then using the
+      local IP addresses selected by this decision. This hostname is only available if there is at least one
+      local default gateway configured. This assigns a stable hostname to the local outbound IP addresses,
+      useful for referencing them independently of the current network configuration state.</para></listitem>
     </itemizedlist>
 
     <para>Various software relies on an always-resolvable local
index 6156c98fbd90dc04976a888deef5bf1fbc68d6c9..27914e06999137a04cd1bd0ece21b70e878be42b 100644 (file)
@@ -52,9 +52,9 @@
 
         <listitem><para>Sets the limit for swap usage on the system before <command>systemd-oomd</command>
         will take action. If the fraction of swap used on the system is more than what is defined here,
-        <command>systemd-oomd</command> will act on eligible descendant control groups, starting from the
-        ones with the highest swap usage to the lowest swap usage. Which control groups are monitored and
-        what action gets taken depends on what the unit has configured for
+        <command>systemd-oomd</command> will act on eligible descendant control groups with swap usage greater
+        than 5% of total swap, starting from the ones with the highest swap usage. Which
+        control groups are monitored and what action gets taken depends on what the unit has configured for
         <varname>ManagedOOMSwap=</varname>.  Takes a value specified in percent (when suffixed with "%"),
         permille ("‰") or permyriad ("‱"), between 0% and 100%, inclusive. Defaults to 90%.</para></listitem>
       </varlistentry>
@@ -81,7 +81,7 @@
         <listitem><para>Sets the amount of time a unit's control group needs to have exceeded memory pressure
         limits before <command>systemd-oomd</command> will take action. Memory pressure limits are defined by
         <varname>DefaultMemoryPressureLimit=</varname> and <varname>ManagedOOMMemoryPressureLimit=</varname>.
-        Defaults to 30 seconds when this property is unset or set to 0.</para></listitem>
+        Must be set to 0, or at least 1 second. Defaults to 30 seconds when unset or 0.</para></listitem>
       </varlistentry>
 
     </variablelist>
index 3a5088ededcf2e6ca617b2bf5414ab74e6a0303e..d4af4f373743e25656741861cb758659db5cfc8c 100644 (file)
@@ -58,6 +58,7 @@ node /org/freedesktop/hostname1 {
                   in  b interactive);
       GetProductUUID(in  b interactive,
                      out ay uuid);
+      Describe(out s json);
     properties:
       readonly s Hostname = '...';
       readonly s StaticHostname = '...';
@@ -118,6 +119,8 @@ node /org/freedesktop/hostname1 {
 
     <variablelist class="dbus-method" generated="True" extra-ref="GetProductUUID()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="Describe()"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="Hostname"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="StaticHostname"/>
@@ -232,6 +235,17 @@ node /org/freedesktop/hostname1 {
     <citerefentry><refentrytitle>machine-info</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     for that. For more information on these files and syscalls see the respective man pages.</para>
 
+    <para><varname>KernelName</varname>, <varname>KernelRelease</varname>, and
+    <varname>KernelVersion</varname> expose the kernel name (e.g. <literal>Linux</literal>), release
+    (e.g. <literal>5.0.0-11</literal>), and version (i.e. the build number, e.g. <literal>#11</literal>) as
+    reported by <citerefentry project="man-pages"><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry>.
+    <varname>OperatingSystemPrettyName</varname>, <varname>OperatingSystemCPEName</varname>, and
+    <varname>HomeURL</varname> expose the <varname>PRETTY_NAME=</varname>, <varname>CPE_NAME=</varname> and
+    <varname>HOME_URL=</varname> fields from
+    <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>. The
+    purpose of those properties is to allow remote clients to access this information over D-Bus. Local
+    clients can access the information directly.</para>
+
     <refsect2>
       <title>Methods</title>
 
@@ -261,22 +275,12 @@ node /org/freedesktop/hostname1 {
       <citerefentry><refentrytitle>machine-info</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
       the semantics of those settings.</para>
 
-      <para><function>GetProductUUID()</function> returns the "product uuid" as exposed by the kernel based
+      <para><function>GetProductUUID()</function> returns the "product UUID" as exposed by the kernel based
       on DMI information in <filename>/sys/class/dmi/id/product_uuid</filename>. Reading the file directly
       requires root privileges, and this method allows access to unprivileged clients through the polkit
       framework.</para>
 
-      <para><varname>KernelName</varname>, <varname>KernelRelease</varname>, and
-      <varname>KernelVersion</varname> expose the kernel name (e.g. <literal>Linux</literal>), release
-      (e.g. <literal>5.0.0-11</literal>), and version (i.e. the build number, e.g. <literal>#11</literal>) as
-      reported by
-      <citerefentry project="man-pages"><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry>.
-      <varname>OperatingSystemPrettyName</varname>, <varname>OperatingSystemCPEName</varname>, and
-      <varname>HomeURL</varname> expose the <varname>PRETTY_NAME=</varname>, <varname>CPE_NAME=</varname> and
-      <varname>HOME_URL=</varname> fields from
-      <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>. The
-      purpose of those properties is to allow remote clients to access this information over D-Bus. Local
-      clients can access the information directly.</para>
+      <para><function>Describe()</function> returns a JSON representation of all properties in one.</para>
     </refsect2>
 
     <refsect2>
index bf7a5fa3402d843958cb35c82b2a2835106b85bd..70410fc72672e562db184f3c85aef09cb70c4042 100644 (file)
@@ -555,10 +555,13 @@ node /org/freedesktop/login1 {
       extendability, defined as follows:</para>
       <programlisting>
 #define SD_LOGIND_ROOT_CHECK_INHIBITORS  (UINT64_C(1) &lt;&lt; 0)
+#define SD_LOGIND_KEXEC_REBOOT           (UINT64_C(1) &lt;&lt; 1)
       </programlisting>
       <para> When the <varname>flags</varname> is 0 then these methods behave just like the versions
       without flags. When <constant>SD_LOGIND_ROOT_CHECK_INHIBITORS</constant> (0x01) is set, active
-      inhibitors are honoured for privileged users too.</para>
+      inhibitors are honoured for privileged users too. When <constant>SD_LOGIND_KEXEC_REBOOT</constant>
+      (0x02) is set, then <function>RebootWithFlags()</function> perform kexec reboot if kexec
+      kernel is loaded.</para>
 
       <para><function>SetRebootParameter()</function> sets a parameter for a subsequent reboot operation.
       See the description of <command>reboot</command> in
index e6d2f4f536dd510c88afa4425ccd8ae04e2cec28..53c960206ed22b34d394aa1f38e79940b73ae1c8 100644 (file)
@@ -40,7 +40,7 @@ node /org/freedesktop/portable1 {
     methods:
       GetImage(in  s image,
                out o object);
-      ListImages(out a(ssbtttso) UNNAMED);
+      ListImages(out a(ssbtttso) images);
       GetImageOSRelease(in  s image,
                         out a{ss} os_release);
       GetImageMetadata(in  s image,
@@ -48,6 +48,13 @@ node /org/freedesktop/portable1 {
                        out s image,
                        out ay os_release,
                        out a{say} units);
+      GetImageMetadataWithExtensions(in  s image,
+                                     in  as extensions,
+                                     in  as matches,
+                                     in  t flags,
+                                     out s image,
+                                     out ay os_release,
+                                     out a{say} units);
       GetImageState(in  s image,
                     out s state);
       AttachImage(in  s image,
@@ -56,9 +63,20 @@ node /org/freedesktop/portable1 {
                   in  b runtime,
                   in  s copy_mode,
                   out a(sss) changes);
+      AttachImageWithExtensions(in  s image,
+                                in  as extensions,
+                                in  as matches,
+                                in  s profile,
+                                in  s copy_mode,
+                                in  t flags,
+                                out a(sss) changes);
       DetachImage(in  s image,
                   in  b runtime,
                   out a(sss) changes);
+      DetachImageWithExtensions(in  s image,
+                                in  as extensions,
+                                in  t flags,
+                                out a(sss) changes);
       ReattachImage(in  s image,
                     in  as matches,
                     in  s profile,
@@ -66,6 +84,14 @@ node /org/freedesktop/portable1 {
                     in  s copy_mode,
                     out a(sss) changes_removed,
                     out a(sss) changes_updated);
+      ReattachImageWithExtensions(in  s image,
+                                  in  as extensions,
+                                  in  as matches,
+                                  in  s profile,
+                                  in  s copy_mode,
+                                  in  t flags,
+                                  out a(sss) changes_removed,
+                                  out a(sss) changes_updated);
       RemoveImage(in  s image);
       MarkImageReadOnly(in  s image,
                         in  b read_only);
@@ -102,14 +128,22 @@ node /org/freedesktop/portable1 {
 
     <variablelist class="dbus-method" generated="True" extra-ref="GetImageMetadata()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="GetImageMetadataWithExtensions()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="GetImageState()"/>
 
     <variablelist class="dbus-method" generated="True" extra-ref="AttachImage()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="AttachImageWithExtensions()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="DetachImage()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="DetachImageWithExtensions()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="ReattachImage()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="ReattachImageWithExtensions()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="RemoveImage()"/>
 
     <variablelist class="dbus-method" generated="True" extra-ref="MarkImageReadOnly()"/>
@@ -149,6 +183,12 @@ node /org/freedesktop/portable1 {
       and a list of portable units contained in the image, in the form of a string (unit name) and
       an array of bytes with the content.</para>
 
+      <para><function>GetImageMetadataWithExtensions()</function> retrieves metadata associated with an image.
+      This method is a superset of <function>GetImageMetadata()</function> with the addition of
+      a list of extensions as input parameter, which were overlaid on top of the main
+      image via <function>AttachImageWithExtensions()</function>.
+      The <varname>flag</varname> parameter is currently unused and reserved for future purposes.</para>
+
       <para><function>GetImageState()</function> retrieves the image state as one of the following
       strings:
       <itemizedlist>
@@ -197,6 +237,16 @@ node /org/freedesktop/portable1 {
       Note that an image cannot be attached if a unit that it contains is already present
       on the system.</para>
 
+      <para><function>AttachImageWithExtensions()</function> attaches a portable image to the system.
+      This method is a superset of <function>AttachImage()</function> with the addition of
+      a list of extensions as input parameter, which will be overlaid on top of the main
+      image. When this method is used, detaching must be done by passing the same arguments via the
+      <function>DetachImageWithExtensions()</function> method. For more details on this functionality,
+      see the <varname>MountImages=</varname> entry on
+      <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+      and <citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+      The <varname>flag</varname> parameter is currently unused and reserved for future purposes.</para>
+
       <para><function>DetachImage()</function> detaches a portable image from the system.
       This method takes an image path or name, and a boolean indicating whether the image to
       detach was attached only for the current boot session or persistently. This method
@@ -209,6 +259,12 @@ node /org/freedesktop/portable1 {
       </itemizedlist>
       Note that an image cannot be detached if a unit that it contains is running.</para>
 
+      <para><function>DetachImageWithExtensions()</function> detaches a portable image from the system.
+      This method is a superset of <function>DetachImage()</function> with the addition of
+      a list of extensions as input parameter, which were overlaid on top of the main
+      image via <function>AttachImageWithExtensions()</function>.
+      The <varname>flag</varname> parameter is currently unused and reserved for future purposes.</para>
+
       <para><function>ReattachImage()</function> combines the effects of the
       <function>AttachImage()</function> method and the <function>DetachImage()</function> method.
       The difference is that it is allowed to reattach an image while one or more of its units
@@ -218,6 +274,14 @@ node /org/freedesktop/portable1 {
       <function>DetachImage()</function> method (first array, units that were removed) and the
       <function>AttachImage()</function> method (second array, units that were updated or added).</para>
 
+      <para><function>ReattachImageWithExtensions()</function> reattaches a portable image to the system.
+      This method is a superset of <function>ReattachImage()</function> with the addition of
+      a list of extensions as input parameter, which will be overlaid on top of the main
+      image. For more details on this functionality, see the <varname>MountImages=</varname> entry on
+      <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+      and <citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+      The <varname>flag</varname> parameter is currently unused and reserved for future purposes</para>
+
       <para><function>RemoveImage()</function> removes the image with the specified name.</para>
 
       <para><function>MarkImageReadOnly()</function> toggles the read-only flag of an image.</para>
@@ -225,6 +289,15 @@ node /org/freedesktop/portable1 {
       <para><function>SetPoolLimit()</function> sets an overall quota limit on the pool of images.</para>
 
       <para><function>SetImageLimit()</function> sets a per-image quota limit.</para>
+
+      <para>The <function>AttachImageWithExtensions()</function>,
+      <function>DetachImageWithExtensions()</function> and
+      <function>ReattachImageWithExtensions()</function> methods take in options as flags instead of
+      booleans to allow for extendability, defined as follows:</para>
+
+      <programlisting>
+#define SD_SYSTEMD_PORTABLE_RUNTIME  (UINT64_C(1) &lt;&lt; 0)
+      </programlisting>
     </refsect2>
 
     <refsect2>
@@ -249,25 +322,47 @@ node /org/freedesktop/portable1 {
 node /org/freedesktop/portable1 {
   interface org.freedesktop.portable1.Image {
     methods:
-      GetOSRelease(out a{ss} UNNAMED);
+      GetOSRelease(out a{ss} os_release);
       GetMetadata(in  as matches,
                   out s image,
                   out ay os_release,
                   out a{say} units);
-      GetState(out s UNNAMED);
+      GetMetadataWithExtensions(in  as extensions,
+                                in  as matches,
+                                in  t flags,
+                                out s image,
+                                out ay os_release,
+                                out a{say} units);
+      GetState(out s state);
       Attach(in  as matches,
              in  s profile,
              in  b runtime,
              in  s copy_mode,
              out a(sss) changes);
+      AttachWithExtensions(in  as extensions,
+                           in  as matches,
+                           in  s profile,
+                           in  s copy_mode,
+                           in  t flags,
+                           out a(sss) changes);
       Detach(in  b runtime,
              out a(sss) changes);
+      DetachWithExtensions(in  as extensions,
+                           in  t flags,
+                           out a(sss) changes);
       Reattach(in  as matches,
                in  s profile,
                in  b runtime,
                in  s copy_mode,
                out a(sss) changes_removed,
                out a(sss) changes_updated);
+      ReattacheWithExtensions(in  as extensions,
+                              in  as matches,
+                              in  s profile,
+                              in  s copy_mode,
+                              in  t flags,
+                              out a(sss) changes_removed,
+                              out a(sss) changes_updated);
       Remove();
       MarkReadOnly(in  b read_only);
       SetLimit(in  t limit);
@@ -303,14 +398,22 @@ node /org/freedesktop/portable1 {
 
     <!--method GetMetadata is not documented!-->
 
+    <!--method GetMetadataWithExtensions is not documented!-->
+
     <!--method GetState is not documented!-->
 
     <!--method Attach is not documented!-->
 
+    <!--method AttachWithExtensions is not documented!-->
+
     <!--method Detach is not documented!-->
 
+    <!--method DetachWithExtensions is not documented!-->
+
     <!--method Reattach is not documented!-->
 
+    <!--method ReattacheWithExtensions is not documented!-->
+
     <!--method Remove is not documented!-->
 
     <!--method MarkReadOnly is not documented!-->
@@ -327,14 +430,22 @@ node /org/freedesktop/portable1 {
 
     <variablelist class="dbus-method" generated="True" extra-ref="GetMetadata()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="GetMetadataWithExtensions()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="GetState()"/>
 
     <variablelist class="dbus-method" generated="True" extra-ref="Attach()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="AttachWithExtensions()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="Detach()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="DetachWithExtensions()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="Reattach()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="ReattacheWithExtensions()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="Remove()"/>
 
     <variablelist class="dbus-method" generated="True" extra-ref="MarkReadOnly()"/>
@@ -377,14 +488,22 @@ node /org/freedesktop/portable1 {
 
         <listitem><para>GetMetadata()</para></listitem>
 
+        <listitem><para>GetMetadataWithExtensions()</para></listitem>
+
         <listitem><para>GetState()</para></listitem>
 
         <listitem><para>Attach()</para></listitem>
 
+        <listitem><para>AttachWithExtensions()</para></listitem>
+
         <listitem><para>Detach()</para></listitem>
 
+        <listitem><para>DetachWithExtensions()</para></listitem>
+
         <listitem><para>Reattach()</para></listitem>
 
+        <listitem><para>ReattacheWithExtensions()</para></listitem>
+
         <listitem><para>Remove()</para></listitem>
 
         <listitem><para>MarkReadOnly()</para></listitem>
index aff43217e1690703a7bcaeaafd900f3b88651668..3d6f1a39b3be35573b75acda7b0be4cb79f381ed 100644 (file)
@@ -492,6 +492,8 @@ node /org/freedesktop/systemd1 {
       readonly t TimerSlackNSec = ...;
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s DefaultOOMPolicy = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s CtrlAltDelBurstAction = '...';
   };
   interface org.freedesktop.DBus.Peer { ... };
   interface org.freedesktop.DBus.Introspectable { ... };
@@ -733,6 +735,8 @@ node /org/freedesktop/systemd1 {
 
     <!--property DefaultOOMPolicy is not documented!-->
 
+    <!--property CtrlAltDelBurstAction is not documented!-->
+
     <!--Autogenerated cross-references for systemd.directives, do not edit-->
 
     <variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.systemd1.Manager"/>
@@ -1127,6 +1131,8 @@ node /org/freedesktop/systemd1 {
 
     <variablelist class="dbus-property" generated="True" extra-ref="DefaultOOMPolicy"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="CtrlAltDelBurstAction"/>
+
     <!--End of Autogenerated section-->
 
     <refsect2>
@@ -2250,6 +2256,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s Type = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s ExitType = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s Restart = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s PIDFile = '...';
@@ -2472,6 +2480,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
       readonly u ManagedOOMMemoryPressureLimit = ...;
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
       readonly s ManagedOOMPreference = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(ss) BPFProgram = [...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(iqq) SocketBindAllow = [...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(iqq) SocketBindDeny = [...];
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly as Environment = ['...', ...];
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -2808,6 +2822,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <!--property Type is not documented!-->
 
+    <!--property ExitType is not documented!-->
+
     <!--property Restart is not documented!-->
 
     <!--property PIDFile is not documented!-->
@@ -3004,6 +3020,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <!--property ManagedOOMPreference is not documented!-->
 
+    <!--property BPFProgram is not documented!-->
+
+    <!--property SocketBindAllow is not documented!-->
+
+    <!--property SocketBindDeny is not documented!-->
+
     <!--property EnvironmentFiles is not documented!-->
 
     <!--property PassEnvironment is not documented!-->
@@ -3320,6 +3342,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <variablelist class="dbus-property" generated="True" extra-ref="Type"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="ExitType"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="Restart"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="PIDFile"/>
@@ -3560,6 +3584,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="BPFProgram"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SocketBindAllow"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SocketBindDeny"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
@@ -4245,6 +4275,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
       readonly u ManagedOOMMemoryPressureLimit = ...;
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
       readonly s ManagedOOMPreference = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(ss) BPFProgram = [...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(iqq) SocketBindAllow = [...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(iqq) SocketBindDeny = [...];
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly as Environment = ['...', ...];
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -4805,6 +4841,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
 
     <!--property ManagedOOMPreference is not documented!-->
 
+    <!--property BPFProgram is not documented!-->
+
+    <!--property SocketBindAllow is not documented!-->
+
+    <!--property SocketBindDeny is not documented!-->
+
     <!--property EnvironmentFiles is not documented!-->
 
     <!--property PassEnvironment is not documented!-->
@@ -5359,6 +5401,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
 
     <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="BPFProgram"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SocketBindAllow"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SocketBindDeny"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
@@ -5946,6 +5994,12 @@ node /org/freedesktop/systemd1/unit/home_2emount {
       readonly u ManagedOOMMemoryPressureLimit = ...;
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
       readonly s ManagedOOMPreference = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(ss) BPFProgram = [...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(iqq) SocketBindAllow = [...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(iqq) SocketBindDeny = [...];
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly as Environment = ['...', ...];
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -6434,6 +6488,12 @@ node /org/freedesktop/systemd1/unit/home_2emount {
 
     <!--property ManagedOOMPreference is not documented!-->
 
+    <!--property BPFProgram is not documented!-->
+
+    <!--property SocketBindAllow is not documented!-->
+
+    <!--property SocketBindDeny is not documented!-->
+
     <!--property EnvironmentFiles is not documented!-->
 
     <!--property PassEnvironment is not documented!-->
@@ -6906,6 +6966,12 @@ node /org/freedesktop/systemd1/unit/home_2emount {
 
     <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="BPFProgram"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SocketBindAllow"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SocketBindDeny"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
@@ -7614,6 +7680,12 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
       readonly u ManagedOOMMemoryPressureLimit = ...;
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
       readonly s ManagedOOMPreference = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(ss) BPFProgram = [...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(iqq) SocketBindAllow = [...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(iqq) SocketBindDeny = [...];
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly as Environment = ['...', ...];
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -8088,6 +8160,12 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
 
     <!--property ManagedOOMPreference is not documented!-->
 
+    <!--property BPFProgram is not documented!-->
+
+    <!--property SocketBindAllow is not documented!-->
+
+    <!--property SocketBindDeny is not documented!-->
+
     <!--property EnvironmentFiles is not documented!-->
 
     <!--property PassEnvironment is not documented!-->
@@ -8546,6 +8624,12 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
 
     <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="BPFProgram"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SocketBindAllow"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SocketBindDeny"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
@@ -9107,6 +9191,12 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
       readonly u ManagedOOMMemoryPressureLimit = ...;
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
       readonly s ManagedOOMPreference = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(ss) BPFProgram = [...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(iqq) SocketBindAllow = [...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(iqq) SocketBindDeny = [...];
   };
   interface org.freedesktop.DBus.Peer { ... };
   interface org.freedesktop.DBus.Introspectable { ... };
@@ -9245,6 +9335,12 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
 
     <!--property ManagedOOMPreference is not documented!-->
 
+    <!--property BPFProgram is not documented!-->
+
+    <!--property SocketBindAllow is not documented!-->
+
+    <!--property SocketBindDeny is not documented!-->
+
     <!--Autogenerated cross-references for systemd.directives, do not edit-->
 
     <variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.systemd1.Unit"/>
@@ -9387,6 +9483,12 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
 
     <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="BPFProgram"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SocketBindAllow"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SocketBindDeny"/>
+
     <!--End of Autogenerated section-->
 
     <refsect2>
@@ -9548,6 +9650,12 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
       readonly u ManagedOOMMemoryPressureLimit = ...;
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
       readonly s ManagedOOMPreference = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(ss) BPFProgram = [...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(iqq) SocketBindAllow = [...];
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+      readonly a(iqq) SocketBindDeny = [...];
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s KillMode = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -9702,6 +9810,12 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
 
     <!--property ManagedOOMPreference is not documented!-->
 
+    <!--property BPFProgram is not documented!-->
+
+    <!--property SocketBindAllow is not documented!-->
+
+    <!--property SocketBindDeny is not documented!-->
+
     <!--property KillMode is not documented!-->
 
     <!--property KillSignal is not documented!-->
@@ -9870,6 +9984,12 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
 
     <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="BPFProgram"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SocketBindAllow"/>
+
+    <variablelist class="dbus-property" generated="True" extra-ref="SocketBindDeny"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
index e6162bdacfb9d3add5cf6a8862e9ae88010fa43d..cda07793033e97fd5c3141179b37b393d08f9953 100644 (file)
         <literal>SYSEXT_LEVEL=15.14</literal>.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>IMAGE_ID=</varname></term>
+
+        <listitem><para> A lower-case string (no spaces or other characters outside of 0–9, a–z, ".", "_" and
+        "-"), identifying a specific image of the operating system. This is supposed to be used for
+        environments where OS images are prepared, built, shipped and updated as comprehensive, consistent OS
+        images. This field is optional and may not be implemented on all systems, in particularly not on those
+        that are not managed via images but put together and updated from individual packages and on the
+        local system. Examples: <literal>IMAGE_ID=vendorx-cashier-system</literal>,
+        <literal>IMAGE_ID=netbook-image</literal> </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>IMAGE_VERSION=</varname></term>
+
+        <listitem><para>A lower-case string (mostly numeric, no spaces or other characters outside of 0–9,
+        a–z, ".", "_" and "-") identifying the OS image version. This is supposed to be used together with
+        <varname>IMAGE_ID</varname> described above, to discern different versions of the same
+        image. Examples: <literal>IMAGE_VERSION=33</literal>,
+        <literal>IMAGE_VERSION=47.1rc1</literal> </para></listitem>
+      </varlistentry>
+
     </variablelist>
 
     <para>If you are reading this file from C code or a shell script
index 2dae537a40ab2ef3cca94d88b6a32695e7935959..d798219d459f6661f85490a5fac23bb2008bcdcc 100644 (file)
         <listitem><para>Don't block waiting for attach --now to complete.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--extension=</option><replaceable>PATH</replaceable></term>
+
+        <listitem><para>Add an additional image <replaceable>PATH</replaceable> as an overlay on
+        top of <replaceable>IMAGE</replaceable> when attaching/detaching. This argument can be specified
+        multiple times, in which case the order in which images are laid down follows the rules specified in
+        <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+        for the <varname>ExtensionImages=</varname> directive.</para>
+
+        <para>Note that the same extensions have to be specified, in the same order, when attaching
+        and detaching.</para></listitem>
+      </varlistentry>
+
       <xi:include href="user-system-options.xml" xpointer="host" />
       <xi:include href="user-system-options.xml" xpointer="machine" />
 
index 66debd336f103c9df8f3289801b5d91da6b4879c..6e3322e064b30815fe4337a3bc6a99b038001d60 100644 (file)
     partition slot greater than the highest slot number currently in use. Any existing partitions that have
     no matching partition file are left as they are.</para>
 
-    <para>Note that these definitions may only be used to created and initialize new partitions or grow
+    <para>Note that these definitions may only be used to create and initialize new partitions or to grow
     existing ones. In the latter case it will not grow the contained files systems however; separate
     mechanisms, such as
     <citerefentry><refentrytitle>systemd-growfs</refentrytitle><manvolnum>8</manvolnum></citerefentry> may be
-    used to grow the file systems inside of these partitions.</para>
+    used to grow the file systems inside of these partitions. Partitions may also be marked for automatic
+    growing via the <varname>GrowFileSystem=</varname> setting, in which case the file system is grown on
+    first mount by tools that respect this flag. See below for details.</para>
   </refsect1>
 
   <refsect1>
       <varlistentry>
         <term><varname>CopyBlocks=</varname></term>
 
-        <listitem><para>Takes a path to a regular file, block device node or directory. If specified and the
-        partition is newly created the data from the specified path is written to the newly created
-        partition, on the block level. If a directory is specified the backing block device of the file
-        system the directory is on is determined and the data read directly from that. This option is useful
-        to efficiently replicate existing file systems on the block level on a new partition, for example to
-        build a simple OS installer or OS image builder.</para>
+        <listitem><para>Takes a path to a regular file, block device node or directory, or the special value
+        <literal>auto</literal>. If specified and the partition is newly created, the data from the specified
+        path is written to the newly created partition, on the block level. If a directory is specified, the
+        backing block device of the file system the directory is on is determined, and the data read directly
+        from that. This option is useful to efficiently replicate existing file systems onto new partitions
+        on the block level — for example to build a simple OS installer or an OS image builder.</para>
+
+        <para>If the special value <literal>auto</literal> is specified, the source to copy from is
+        automatically picked up from the running system (or the image specified with
+        <option>--image=</option> — if used). A partition that matches both the configured partition type (as
+        declared with <varname>Type=</varname> above), and the currently mounted directory appropriate for
+        that partition type is determined. For example, if the partition type is set to
+        <literal>root</literal> the partition backing the root directory (<filename>/</filename>) is used as
+        source to copy from — if its partition type is set to <literal>root</literal> as well. If the
+        declared type is <literal>usr</literal> the partition backing <filename>/usr/</filename> is used as
+        source to copy blocks from — if its partition type is set to <literal>usr</literal> too. The logic is
+        capable of automatically tracking down the the backing partitions for encrypted and Verity-enabled
+        volumes. <literal>CopyBlocks=auto</literal> is useful for implementing "self-replicating" systems,
+        i.e. systems that are their own installer.</para>
 
         <para>The file specified here must have a size that is a multiple of the basic block size 512 and not
         be empty. If this option is used, the size allocation algorithm is slightly altered: the partition is
         <para>The copy operation is executed before the file system is registered in the partition table,
         thus ensuring that a file system populated this way only ever exists fully initialized.</para>
 
-        <para>This option cannot be combined with <varname>CopyBlocks=</varname>.</para></listitem>
+        <para>This option cannot be combined with <varname>CopyBlocks=</varname>.</para>
+
+        <para>When <command>systemd-repart</command> is invoked with the <option>--image=</option> or
+        <option>--root=</option> command line switches the source paths specified are taken relative to the
+        specified root directory or disk image root.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>MakeDirectories=</varname></term>
+
+        <listitem><para>akes one or more absolute paths, separated by whitespace, each declaring a directory
+        to create within the new file system. Behaviour is similar to <varname>CopyFiles=</varname>, but
+        instead of copying in a set of files this just creates the specified directories with the default
+        mode of 0755 owned by the root user and group, plus all their parent directories (with the same
+        ownership and access mode). To configure directories with different ownership or access mode, use
+        <varname>CopyFiles=</varname> and specify a source tree to copy containing appropriately
+        owned/configured directories. This option may be used more than once to create multiple
+        directories. When <varname>CopyFiles=</varname> and <varname>MakeDirectories=</varname> are used
+        together the former is applied first. If a directory listed already exists no operation is executed
+        (in particular, the ownership/access mode of the directories is left as is).</para>
+
+        <para>The primary usecase for this option is to create a minimal set of directories that may be
+        mounted over by other partitions contained in the same disk image. For example, a disk image where
+        the root file system is formatted at first boot might want to automatically pre-create
+        <filename>/usr/</filename> in it this way, so that the <literal>usr</literal> partition may
+        over-mount it.</para>
+
+        <para>Consider using
+        <citerefentry><refentrytitle>systemd-tmpfiles</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        with its <option>--image=</option> option to pre-create other, more complex directory hierarchies (as
+        well as other inodes) with fine-grained control of ownership, access modes and other file
+        attributes.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         factory reset operation. This functionality is useful to implement schemes where images can be reset
         into their original state by removing partitions and creating them anew. Defaults to off.</para></listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term><varname>Flags=</varname></term>
+
+        <listitem><para>Configures the 64bit GPT partition flags to set for the partition when creating
+        it. This option has no effect if the partition already exists. If not specified the flags values is
+        set to all zeroes, except if the partition type (as configured with <varname>Type=</varname> above)
+        refers to a Verity partition, in which case bit 60 is set (i.e. the read-only bit). This bit may also
+        be configured separately via <varname>ReadOnly=</varname>, see below. Specify the flags value in
+        hexadecimal (by prefixing it with <literal>0x</literal>), binary (prefix <literal>0b</literal>) or
+        decimal (no prefix).</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>ReadOnly=</varname></term>
+        <term><varname>GrowFileSystem=</varname></term>
+
+        <listitem><para>Configures the Read-Only and Grow-File-System partition flags (bit 60 and 59) of the
+        partition table entry, as defined by the <ulink
+        url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions Specification</ulink>. Only
+        available for partition types supported by the specification. This option is a friendly way to set bit
+        60 and 59 of the partition flags value without setting any of the other bits, and may be set via
+        <varname>Flags=</varname> too, see above.</para>
+
+        <para>If <varname>Flags=</varname> is used in conjunction with one or both of
+        <varname>ReadOnly=</varname>/<varname>GrowFileSystem=</varname> the latter control the value of the
+        relevant flags, i.e. the high-level settings
+        <varname>ReadOnly=</varname>/<varname>GrowFileSystem=</varname> override the low-level setting
+        <varname>Flags=</varname>.</para>
+
+        <para>Note that the two flags affect only automatic partition mounting, as implemented by
+        <citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        or the <option>--image=</option> option of various commands (such as
+        <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>). It
+        has no effect on explicit mounts, such as those done via <citerefentry
+        project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry> or
+        <citerefentry
+        project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry></para>
+
+        <para>If both bit 50 and 59 are set for a partition (i.e. the partition is marked both read-only and
+        marked for file system growing) the latter is typically without effect: the read-only flag takes
+        precedence in most tools reading these flags, and since growing the file system involves writing to
+        the partition it is consequently ignored.</para>
+
+        <para><varname>ReadOnly=</varname> defaults to on for Verity partition
+        types. <varname>GrowFileSystem=</varname> defaults to on for all partition types that support it,
+        except if the partition is marked read-only (and thus effectively, defaults to off for Verity
+        partitions).</para></listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
           </thead>
           <tbody>
             <xi:include href="standard-specifiers.xml" xpointer="a"/>
+            <xi:include href="standard-specifiers.xml" xpointer="A"/>
             <xi:include href="standard-specifiers.xml" xpointer="b"/>
             <xi:include href="standard-specifiers.xml" xpointer="B"/>
             <xi:include href="standard-specifiers.xml" xpointer="H"/>
             <xi:include href="standard-specifiers.xml" xpointer="l"/>
             <xi:include href="standard-specifiers.xml" xpointer="m"/>
+            <xi:include href="standard-specifiers.xml" xpointer="M"/>
             <xi:include href="standard-specifiers.xml" xpointer="o"/>
             <xi:include href="standard-specifiers.xml" xpointer="v"/>
             <xi:include href="standard-specifiers.xml" xpointer="w"/>
index 6dd467445638287721c6a98bd62e2614925243c2..bd1a636d605a3267cfc2f1e2dc9d6db77f108f0f 100644 (file)
 
         <listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
         (the default), select domains are resolved on the local system, among them
-        <literal>localhost</literal> and <literal>_gateway</literal> or entries from
-        <filename>/etc/hosts</filename>. If false these domains are not resolved locally, and either fail (in
-        case of <literal>localhost</literal> or <literal>_gateway</literal> and suchlike) or go to the
-        network via regular DNS/mDNS/LLMNR lookups (in case of <filename>/etc/hosts</filename>
-        entries).</para></listitem>
+        <literal>localhost</literal>, <literal>_gateway</literal> and <literal>_outbound</literal>, or
+        entries from <filename>/etc/hosts</filename>. If false these domains are not resolved locally, and
+        either fail (in case of <literal>localhost</literal>, <literal>_gateway</literal> or
+        <literal>_outbound</literal> and suchlike) or go to the network via regular DNS/mDNS/LLMNR lookups
+        (in case of <filename>/etc/hosts</filename> entries).</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 7ef26cb2c62a2d8e8ef87f91460456bc33af99fc..05b087db3e6921b60c933dfbe2ffa57a123ba96a 100644 (file)
@@ -119,7 +119,8 @@ manpages = [
  ['sd-hwdb', '3', [], ''],
  ['sd-id128',
   '3',
-  ['SD_ID128_CONST_STR',
+  ['SD_ID128_ALLF',
+   'SD_ID128_CONST_STR',
    'SD_ID128_FORMAT_STR',
    'SD_ID128_FORMAT_VAL',
    'SD_ID128_MAKE',
@@ -127,6 +128,10 @@ manpages = [
    'SD_ID128_NULL',
    'SD_ID128_UUID_FORMAT_STR',
    'sd_id128_equal',
+   'sd_id128_in_set',
+   'sd_id128_in_set_sentinel',
+   'sd_id128_in_setv',
+   'sd_id128_is_allf',
    'sd_id128_is_null',
    'sd_id128_t'],
   ''],
index 40a3cc59aea13a222450d7ea3fd2c0d664de998f..1890f6d6a55aa7082fb46b0f9552dd1a0b349d28 100644 (file)
 
   <refnamediv>
     <refname>sd-id128</refname>
-    <refname>sd_id128_t</refname>
+    <refname>SD_ID128_ALLF</refname>
+    <refname>SD_ID128_CONST_STR</refname>
+    <refname>SD_ID128_FORMAT_STR</refname>
+    <refname>SD_ID128_FORMAT_VAL</refname>
     <refname>SD_ID128_MAKE</refname>
     <refname>SD_ID128_MAKE_STR</refname>
     <refname>SD_ID128_NULL</refname>
-    <refname>SD_ID128_CONST_STR</refname>
-    <refname>SD_ID128_FORMAT_STR</refname>
     <refname>SD_ID128_UUID_FORMAT_STR</refname>
-    <refname>SD_ID128_FORMAT_VAL</refname>
     <refname>sd_id128_equal</refname>
+    <refname>sd_id128_in_set</refname>
+    <refname>sd_id128_in_set_sentinel</refname>
+    <refname>sd_id128_in_setv</refname>
+    <refname>sd_id128_is_allf</refname>
     <refname>sd_id128_is_null</refname>
+    <refname>sd_id128_t</refname>
     <refpurpose>APIs for processing 128-bit IDs</refpurpose>
   </refnamediv>
 
@@ -65,8 +70,8 @@
     union type:</para>
 
     <programlisting>typedef union sd_id128 {
-        uint8_t bytes[16];
-        uint64_t qwords[2];
+  uint8_t bytes[16];
+  uint64_t qwords[2];
 } sd_id128_t;</programlisting>
 
     <para>This union type allows accessing the 128-bit ID as 16
@@ -85,7 +90,7 @@
 
     <programlisting>#define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1)</programlisting>
 
-    <para><constant>SD_ID128_NULL</constant> may be used to refer to the 128bit ID consisting of only
+    <para><constant>SD_ID128_NULL</constant> may be used to refer to the 128-bit ID consisting of only
     <constant>NUL</constant> bytes.</para>
 
     <para><function>SD_ID128_MAKE_STR()</function> is similar to <function>SD_ID128_MAKE()</function>, but creates a
 #define SD_MESSAGE_COREDUMP_STR SD_ID128_MAKE_STR(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1)
 
 int main(int argc, char **argv) {
-        puts("Match for coredumps: MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR);
+  puts("Match for coredumps: MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR);
 }
     </programlisting>
 
@@ -104,7 +109,7 @@ int main(int argc, char **argv) {
     following example code will output the string
     "fc2e22bc6ee647b6b90729ab34a250b1":</para>
     <programlisting>int main(int argc, char *argv[]) {
-        puts("Match for coredumps: %s", SD_ID128_CONST_STR(SD_MESSAGE_COREDUMP));
+  puts("Match for coredumps: %s", SD_ID128_CONST_STR(SD_MESSAGE_COREDUMP));
 }</programlisting>
 
     <para><constant>SD_ID128_FORMAT_STR</constant> and <function>SD_ID128_FORMAT_VAL()</function> may
@@ -113,10 +118,10 @@ int main(int argc, char **argv) {
     format string, as shown in the following example:</para>
 
     <programlisting>int main(int argc, char *argv[]) {
-        sd_id128_t id;
-        id = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07);
-        printf("The ID encoded in this C file is " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(id));
-        return 0;
+  sd_id128_t id;
+  id = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07);
+  printf("The ID encoded in this C file is " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(id));
+  return 0;
 }</programlisting>
 
     <para><constant>SD_ID128_UUID_FORMAT_STR</constant> is similar to
@@ -127,21 +132,50 @@ int main(int argc, char **argv) {
     <para>Use <function>sd_id128_equal()</function> to compare two 128-bit IDs:</para>
 
     <programlisting>int main(int argc, char *argv[]) {
-        sd_id128_t a, b, c;
-        a = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07);
-        b = SD_ID128_MAKE(f2,28,88,9c,5f,09,44,15,9d,d7,04,77,58,cb,e7,3e);
-        c = a;
-        assert(sd_id128_equal(a, c));
-        assert(!sd_id128_equal(a, b));
-        return 0;
+  sd_id128_t a, b, c;
+  a = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07);
+  b = SD_ID128_MAKE(f2,28,88,9c,5f,09,44,15,9d,d7,04,77,58,cb,e7,3e);
+  c = a;
+  assert(sd_id128_equal(a, c));
+  assert(!sd_id128_equal(a, b));
+  return 0;
 }</programlisting>
 
-    <para>Use <function>sd_id128_is_null()</function> to check if an 128bit ID consists of only
+    <para>Use <function>sd_id128_is_null()</function> to check if an 128-bit ID consists of only
     <constant>NUL</constant> bytes:</para>
 
+    <programlisting>assert(sd_id128_is_null(SD_ID128_NULL));</programlisting>
+
+    <para>Similarly, use <function>sd_id128_is_allf()</function> to check if an 128-bit ID consists of only
+    <constant>0xFF</constant> bytes (all bits on):</para>
+
+    <programlisting>assert(sd_id128_is_allf(SD_ID128_ALLF));</programlisting>
+
+    <para>For convenience, <function>sd_id128_in_set()</function> takes a list of IDs and
+    returns true if any are equal to the first argument:</para>
+
     <programlisting>int main(int argc, char *argv[]) {
-        assert(sd_id128_is_null(SD_ID128_NULL));
-}</programlisting>
+  sd_id12_t a = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07);
+  assert(sd_id128_in_set(a, a));
+  assert(sd_id128_in_set(a, a, a));
+  assert(!sd_id128_in_set(a));
+  assert(!sd_id128_in_set(a,
+                          SD_ID128_MAKE(f2,28,88,9c,5f,09,44,15,9d,d7,04,77,58,cb,e7,3e)
+                          SD_ID128_MAKE(2f,88,28,5f,9c,44,09,9d,d7,15,77,04,bc,85,7e,e3)
+                          SD_ID128_ALLF));
+  return 0;
+}
+</programlisting>
+
+    <para><function>sd_id128_in_set()</function> is defined as a macro over
+    <function>sd_id128_in_set_sentinel()</function>, adding the <constant>SD_ID128_NULL</constant>
+    sentinel. Since <function>sd_id128_in_set_sentinel()</function> uses <constant>SD_ID128_NULL</constant>
+    as the sentinel, <constant>SD_ID128_NULL</constant> cannot be otherwise placed in the argument list.
+    </para>
+
+    <para><function>sd_id128_in_setv()</function> is similar to
+    <function>sd_id128_in_set_sentinel()</function>, but takes a <structname>struct varargs</structname>
+    argument.</para>
 
     <para>Note that new, randomized IDs may be generated with
     <citerefentry><refentrytitle>systemd-id128</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
index bfc5caf4e24b43d2f87c613c4d1a6dc7b87f49ad..bb8015de5ee7fd94067ac0a5c94b0062b2f73c74 100644 (file)
   <refsect1>
     <title>Description</title>
 
-    <para>The <structname>sd_bus_error</structname> structure carries
-    information about a D-Bus error condition. The functions described
-    below may be used to set and query fields in this structure. The
-    <structfield>name</structfield> field contains a short identifier
-    of an error. It should follow the rules for error names described
-    in the D-Bus specification, subsection <ulink
-    url="http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names">Valid
-    Names</ulink>. A number of common, standardized error names are
-    described in
-    <citerefentry><refentrytitle>sd-bus-errors</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
-    but additional domain-specific errors may be defined by
-    applications. The <structfield>message</structfield> field usually
-    contains a human-readable string describing the details, but might
-    be <constant>NULL</constant>. An unset <structname>sd_bus_error</structname> structure
-    should have both fields initialized to <constant>NULL</constant>. Set an error
-    structure to <constant>SD_BUS_ERROR_NULL</constant> in order to
-    reset both fields to <constant>NULL</constant>. When no longer necessary, resources
-    held by the <structname>sd_bus_error</structname> structure should
-    be destroyed with <function>sd_bus_error_free()</function>.</para>
-
-    <para><function>sd_bus_error_set()</function> sets an error
-    structure to the specified name and message strings. The strings
-    will be copied into internal, newly allocated memory. It is
-    essential to free the error structure again when it is not
-    required anymore (see above). The function will return an
-    <varname>errno</varname>-like negative value (see <citerefentry
+    <para>The <structname>sd_bus_error</structname> structure carries information about a D-Bus error
+    condition, or lack thereof. The functions described below may be used to set and query fields in this
+    structure.
+    <itemizedlist>
+      <listitem><para>The <structfield>name</structfield> field contains a short identifier of an error. It
+      should follow the rules for error names described in the D-Bus specification, subsection <ulink
+      url="http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names">Valid
+      Names</ulink>. A number of common, standardized error names are described in
+      <citerefentry><refentrytitle>sd-bus-errors</refentrytitle><manvolnum>3</manvolnum></citerefentry>, but
+      additional domain-specific errors may be defined by applications.</para></listitem>
+
+      <listitem><para>The <structfield>message</structfield> field usually contains a human-readable string
+      describing the details, but might be <constant>NULL</constant>.</para></listitem>
+    </itemizedlist>
+    An unset <structname>sd_bus_error</structname> structure should have both fields initialized to
+    <constant>NULL</constant>, and signifies lack of an error, i.e. success. Assign
+    <constant>SD_BUS_ERROR_NULL</constant> to the structure in order to initialize both fields to
+    <constant>NULL</constant>. When no longer necessary, resources held by the
+    <structname>sd_bus_error</structname> structure should be destroyed with
+    <function>sd_bus_error_free()</function>.</para>
+
+    <para><function>sd_bus_error_set()</function> sets an error structure to the specified name and message
+    strings. The strings will be copied into internal, newly allocated memory. It is essential to free the
+    contents again when they are not required anymore (see above). Do not use this call on error structures
+    that have already been set. If you intend to reuse an error structure, free the old data stored in it
+    with <function>sd_bus_error_free()</function> first.</para>
+
+    <para><function>sd_bus_error_set()</function> will return an <varname>errno</varname>-like value (see
+    <citerefentry
     project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>)
-    determined from the specified error name.  Various well-known
-    D-Bus errors are converted to well-known <varname>errno</varname>
-    counterparts, and the other ones to <constant>-EIO</constant>. See
-    <citerefentry><refentrytitle>sd-bus-errors</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-    for a list of well-known error names. Additional error mappings
-    may be defined with
-    <citerefentry><refentrytitle>sd_bus_error_add_map</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If
-    <parameter>e</parameter> is <constant>NULL</constant>, no error structure is initialized,
-    but the error is still converted into an
-    <varname>errno</varname>-style error. If
-    <parameter>name</parameter> is <constant>NULL</constant>, it is
-    assumed that no error occurred, and 0 is returned. This means that
-    this function may be conveniently used in a
-    <function>return</function> statement. If
-    <parameter>message</parameter> is <constant>NULL</constant>, no message is set. This
-    call can fail if no memory may be allocated for the name and
-    message strings, in which case an
-    <constant>SD_BUS_ERROR_NO_MEMORY</constant> error might be set
-    instead and -ENOMEM be returned. Do not use this call on error
-    structures that are already initialized. If you intend to reuse an
-    error structure, free the old data stored in it with
-    <function>sd_bus_error_free()</function> first.</para>
+    determined from the specified error name <parameter>name</parameter>. If <parameter>name</parameter> is
+    <constant>NULL</constant>, it is assumed that no error occurred, and <constant>0</constant> is returned.
+    If <parameter>name</parameter> is nonnull, a negative value is always returned. If
+    <parameter>e</parameter> is <constant>NULL</constant>, no error structure is initialized, but
+    <parameter>name</parameter> is still converted into an <varname>errno</varname>-style value.</para>
+
+    <para>Various well-known D-Bus errors are converted to well-known <varname>errno</varname> counterparts,
+    and the other ones to <constant>-EIO</constant>. See
+    <citerefentry><refentrytitle>sd-bus-errors</refentrytitle><manvolnum>3</manvolnum></citerefentry> for a
+    list of well-known error names. Additional error mappings may be defined with
+    <citerefentry><refentrytitle>sd_bus_error_add_map</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+    </para>
+
+    <para><function>sd_bus_error_set()</function> is designed to be conveniently used in a
+    <function>return</function> statement. If <parameter>message</parameter> is <constant>NULL</constant>, no
+    message is set. This call can fail if no memory may be allocated for the name and message strings, in
+    which case an <constant>SD_BUS_ERROR_NO_MEMORY</constant> error will be set instead and
+    <constant>-ENOMEM</constant> returned. </para>
 
     <para><function>sd_bus_error_setf()</function> is similar to
     <function>sd_bus_error_set()</function>, but takes a <citerefentry
     <structfield>message</structfield> field.</para>
 
     <para><function>sd_bus_error_set_const()</function> is similar to
-    <function>sd_bus_error_set()</function>, but the string parameters
-    are not copied internally, and must hence remain constant and
-    valid for the lifetime of <parameter>e</parameter>. Use this call
-    to avoid memory allocations when setting error structures. Since
-    this call does not allocate memory, it will not fail with an
-    out-of-memory condition as
-    <function>sd_bus_error_set()</function> can, as described
-    above. Alternatively, the
-    <constant>SD_BUS_ERROR_MAKE_CONST()</constant> macro may be used
-    to generate a literal, constant bus error structure
-    on-the-fly.</para>
-
-    <para><function>sd_bus_error_set_errno()</function> will set
-    <structfield>name</structfield> from an
-    <varname>errno</varname>-like value that is converted to a D-Bus
+    <function>sd_bus_error_set()</function>, but the string parameters are not copied internally, and must
+    hence remain constant and valid for the lifetime of <parameter>e</parameter>. Use this call to avoid
+    memory allocations when setting error structures. Since this call does not allocate memory, it will not
+    fail with an out-of-memory condition as <function>sd_bus_error_set()</function> may, as described
+    above. Alternatively, the <constant>SD_BUS_ERROR_MAKE_CONST()</constant> macro may be used to generate a
+    literal, constant bus error structure on-the-fly.</para>
+
+    <para><function>sd_bus_error_set_errno()</function> will immediately return <constant>0</constant> if the
+    specified error parameter <parameter>error</parameter> is <constant>0</constant>. Otherwise, it will set
+    <structfield>name</structfield> from an <varname>errno</varname>-like value that is converted to a D-Bus
     error. <citerefentry
-    project='die-net'><refentrytitle>strerror_r</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-    will be used to set <structfield>message</structfield>. Well-known
-    D-Bus error names will be used for <structfield>name</structfield>
-    if applicable, otherwise a name in the
-    <literal>System.Error.</literal> namespace will be generated. The
-    sign of the specified error number is ignored. The absolute value
-    is used implicitly. The call always returns a negative value, for
-    convenient usage in <function>return</function> statements. This
-    call might fail due to lack of memory, in which case an
-    <constant>SD_BUS_ERROR_NO_MEMORY</constant> error is set instead,
-    and -ENOMEM is returned.</para>
+    project='die-net'><refentrytitle>strerror_r</refentrytitle><manvolnum>3</manvolnum></citerefentry> will
+    be used to set <structfield>message</structfield>. Well-known D-Bus error names will be used for
+    <structfield>name</structfield> if applicable, otherwise a name in the <literal>System.Error.</literal>
+    namespace will be generated. The sign of the specified error number is ignored and the absolute value is
+    used implicitly. If the specified error <parameter>error</parameter> is non-zero, the call always returns
+    a negative value, for convenient usage in <function>return</function> statements. This call might fail
+    due to lack of memory, in which case an <constant>SD_BUS_ERROR_NO_MEMORY</constant> error is set instead,
+    and <constant>-ENOMEM</constant> is returned.</para>
 
     <para><function>sd_bus_error_set_errnof()</function> is similar to
     <function>sd_bus_error_set_errno()</function>, but in addition to
     project='man-pages'><refentrytitle>va_arg</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     parameter list.</para>
 
-    <para><function>sd_bus_error_get_errno()</function> converts the
-    <structfield>name</structfield> field of an error structure to an
-    <varname>errno</varname>-like (positive) value using the same
-    rules as <function>sd_bus_error_set()</function>.  If
-    <parameter>e</parameter> is <constant>NULL</constant>, 0 will be
-    returned.</para>
-
-    <para><function>sd_bus_error_copy()</function> will initialize
-    <parameter>dst</parameter> using the values in
-    <parameter>e</parameter>. If the strings in
-    <parameter>e</parameter> were set using
-    <function>sd_bus_error_set_const()</function>, they will be shared.
-    Otherwise, they will be copied. Returns a converted
-    <varname>errno</varname>-like, negative error code.</para>
-
-    <para><function>sd_bus_error_move()</function> is similar to <function>sd_bus_error_copy()</function>, but will
-    move any error information from <parameter>e</parameter> into <parameter>dst</parameter>, resetting the
-    former. This function cannot fail, as no new memory is allocated. Note that if <parameter>e</parameter> is not set
-    (or <constant>NULL</constant>) <parameter>dst</parameter> is initializated to
-    <constant>SD_BUS_ERROR_NULL</constant>. Moreover, if <parameter>dst</parameter> is <constant>NULL</constant> no
-    operation is executed on it and resources held by <parameter>e</parameter> are freed and reset. Returns a
-    converted <varname>errno</varname>-like, negative error code.</para>
+    <para><function>sd_bus_error_get_errno()</function> converts the <structfield>name</structfield> field of
+    an error structure to an <varname>errno</varname>-like (positive) value using the same rules as
+    <function>sd_bus_error_set()</function>.  If <parameter>e</parameter> is <constant>NULL</constant>,
+    <constant>0</constant> will be returned.</para>
+
+    <para><function>sd_bus_error_copy()</function> will initialize <parameter>dst</parameter> using the
+    values in <parameter>e</parameter>, if <parameter>e</parameter> has been set with an error value before.
+    Otherwise, it will return immediately. If the strings in <parameter>e</parameter> were set using
+    <function>sd_bus_error_set_const()</function>, they will be shared. Otherwise, they will be
+    copied. Returns a converted <varname>errno</varname>-like, negative error code or <constant>0</constant>.
+    Before this call, <parameter>dst</parameter> must be unset, i.e. either freshly initialized with
+    <constant>NULL</constant> or reset using <function>sd_bus_error_free()</function>.</para>
+
+    <para><function>sd_bus_error_move()</function> is similar to <function>sd_bus_error_copy()</function>,
+    but will move any error information from <parameter>e</parameter> into <parameter>dst</parameter>,
+    resetting the former. This function cannot fail, as no new memory is allocated. Note that if
+    <parameter>e</parameter> is not set, <parameter>dst</parameter> is initializated to
+    <constant>SD_BUS_ERROR_NULL</constant>. Moreover, if <parameter>dst</parameter> is
+    <constant>NULL</constant> no operation is executed on it and resources held by <parameter>e</parameter>
+    are freed and reset. Returns a converted <varname>errno</varname>-like, non-positive error value.</para>
 
     <para><function>sd_bus_error_is_set()</function> will return a
     non-zero value if <parameter>e</parameter> is
   <refsect1>
     <title>Return Value</title>
 
-    <para>The functions <function>sd_bus_error_set()</function>,
-    <function>sd_bus_error_setf()</function>, and
-    <function>sd_bus_error_set_const()</function>, when successful,
-    return the negative errno value corresponding to the
-    <parameter>name</parameter> parameter. The functions
-    <function>sd_bus_error_set_errno()</function>,
-    <function>sd_bus_error_set_errnof()</function> and
-    <function>sd_bus_error_set_errnofv()</function>, when successful,
-    return the negative value of the <parameter>error</parameter>
-    parameter. If an error occurs, one of the negative error values
-    listed below will be returned.</para>
+    <para>The functions <function>sd_bus_error_set()</function>, <function>sd_bus_error_setf()</function>,
+    and <function>sd_bus_error_set_const()</function> always return <constant>0</constant> when the specified
+    error value is <constant>NULL</constant>, and a negative errno-like value corresponding to the
+    <parameter>name</parameter> parameter otherwise. The functions
+    <function>sd_bus_error_set_errno()</function>, <function>sd_bus_error_set_errnof()</function> and
+    <function>sd_bus_error_set_errnofv()</function>, return <constant>0</constant> when the specified error
+    value is <constant>0</constant>, and a a negative errno-like value corresponding to the
+    <parameter>error</parameter> parameter otherwise. If an error occurs internally, one of the negative
+    error values listed below will be returned.</para>
 
     <para><function>sd_bus_error_get_errno()</function> returns
     <constant>false</constant> when <parameter>e</parameter> is
     <constant>NULL</constant>, and a positive errno value mapped from
     <parameter>e-&gt;name</parameter> otherwise.</para>
 
-    <para><function>sd_bus_error_copy()</function> and <function>sd_bus_error_move()</function> return 0 or a positive
-    integer on success, and a negative error value converted from the error name otherwise.</para>
+    <para><function>sd_bus_error_copy()</function> and <function>sd_bus_error_move()</function> return a
+    negative error value converted from the source error, and zero if the error has not been set.</para>
 
     <para><function>sd_bus_error_is_set()</function> returns a
     non-zero value when <parameter>e</parameter> and the
index 8e0aed29b3319c6768a1d99f703507215cb6eecd..621ed272bb8eba1b990f4f28551c58b90d4d29f1 100644 (file)
@@ -57,6 +57,9 @@
     zero outside of this state, and positive otherwise. Effectively, this function returns positive while regular
     messages can be sent or received on the connection.</para>
 
+    <para>The <parameter>bus</parameter> argument may be <constant>NULL</constant>, zero is also returned in
+    that case.</para>
+
     <para>To be notified when the connection is fully established, use
     <citerefentry><refentrytitle>sd_bus_set_connected_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry> and
     install a match for the <function>Connected()</function> signal on the
@@ -68,8 +71,8 @@
   <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>
+    <para>Those functions return 0 if the bus is <emphasis>not</emphasis> in the given state, and a positive
+    integer when it is. On failure, a negative errno-style error code is returned.</para>
 
     <refsect2>
       <title>Errors</title>
index 68a4a0a5c0e4b6afa9ad7523daba8d1b7dc22bc4..f7a70e9b0f836dc91b474d6b0626578abeaf1cc5 100644 (file)
@@ -218,6 +218,9 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(
     <function>sd_journal_send()</function>. Using
     <function>syslog()</function> has the benefit of being
     more portable.</para>
+
+    <para>These functions implement a client to the <ulink
+    url="https://systemd.io/JOURNAL_NATIVE_PROTOCOL">Native Journal Protocol</ulink>.</para>
   </refsect1>
 
   <refsect1>
index 57d22f9f6524b75a4223990e021ef83b14b25f9d..081796249d0a3680751ef9515f280e6b8f6f6270 100644 (file)
   __attribute__((cleanup(sd_login_monitor_unrefp))) sd_login_monitor *m = NULL;
   int r;
   …
-  r = sd_login_monitor_default(&amp;m);
+  r = sd_login_monitor_new(NULL, &amp;m);
   if (r &lt; 0)
     fprintf(stderr, "Failed to allocate login monitor object: %s\n", strerror(-r));
   …
index 40bb6cc3ea00a57f23e59e346741cc9f0fd23390..f1666365b9c19ba7a9129067215f94e22e969600 100644 (file)
@@ -4,16 +4,21 @@
 <!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
 
 <tbody>
-  <row id='b'>
-    <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 id='a'>
     <entry><literal>%a</literal></entry>
     <entry>Architecture</entry>
     <entry>A short string identifying the architecture of the local system. A string such as <constant>x86</constant>, <constant>x86-64</constant> or <constant>arm64</constant>. See the architectures defined for <varname>ConditionArchitecture=</varname> in <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for a full list.</entry>
   </row>
+  <row id='A'>
+    <entry><literal>%A</literal></entry>
+    <entry>Operating system image version</entry>
+    <entry>The operating system image version identifier of the running system, as read from the <varname>IMAGE_VERSION=</varname> field of <filename>/etc/os-release</filename>. If not set, resolves to an empty string. See <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more information.</entry>
+  </row>
+  <row id='b'>
+    <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 id='B'>
     <entry><literal>%B</literal></entry>
     <entry>Operating system build ID</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 id='M'>
+    <entry><literal>%M</literal></entry>
+    <entry>Operating system image identifier</entry>
+    <entry>The operating system image identifier of the running system, as read from the <varname>IMAGE_ID=</varname> field of <filename>/etc/os-release</filename>. If not set, resolves to an empty string. See <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more information.</entry>
+  </row>
   <row id='o'>
     <entry><literal>%o</literal></entry>
     <entry>Operating system ID</entry>
index 433260475dc2d9bf39cc42b316405fbbea829e2c..f241064d8bbefef7a393272193a9b3cb47451fe9 100644 (file)
         directly. Example: <literal>--keyname=cryptsetup</literal></para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--credential=</option></term>
+        <listitem><para>Configure a credential to read the password from – if it exists. This may be used in
+        conjunction with the <varname>LoadCredential=</varname> and <varname>SetCredential=</varname>
+        settings in unit files. See
+        <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+        details. If not specified, defaults to <literal>password</literal>. This option has no effect if no
+        credentials directory is passed to the program (i.e. <varname>$CREDENTIALS_DIRECTORY</varname> is not
+        set) or if the no credential of the specified name exists.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--timeout=</option></term>
 
index 09f2854d83a2a7d3931d92a2e46ab18e440aa7d7..139f79fa6b7d56ef9450315b48053ea09397812c 100644 (file)
@@ -51,7 +51,7 @@
 
       <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 Apple macOS boot manager, if installed</para></listitem>
 
       <listitem><para>The EFI Shell binary, if installed</para></listitem>
 
 
       <varlistentry>
         <term><keycap>a</keycap></term>
-        <listitem><para>OS X</para></listitem>
+        <listitem><para>macOS</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 117b9eb6d08711e8d437d40094ea273d07749ab0..8719ddaae9fe51c1d860f68d3b4e471e46c6fdcc 100644 (file)
@@ -352,6 +352,20 @@ flags:   ...
         </para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>COREDUMP_PACKAGE_NAME=</varname></term>
+        <term><varname>COREDUMP_PACKAGE_VERSION=</varname></term>
+        <term><varname>COREDUMP_PACKAGE_JSON=</varname></term>
+
+        <listitem><para>If the executable contained .package metadata ELF notes, they will be
+        parsed and attached. The <varname>package</varname> and <varname>packageVersion</varname>
+        of the 'main' ELF module (ie: the executable) will be appended individually. The
+        JSON-formatted content of all modules will be appended as a single JSON object, each with
+        the module name as the key. For more information about this metadata format and content, see
+        <ulink url="https://systemd.io/COREDUMP_PACKAGE_METADATA/">the coredump metadata spec</ulink>.</para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>MESSAGE=</varname></term>
 
index 93acdd02a5bfbc35b19a9d21e629614466d52c15..9751444e50860353c0307ff612da81f0abff9afb 100644 (file)
 
               <row>
                 <entry>8</entry>
-                <entry><citerefentry><refentrytitle>sd-boot</refentrytitle><manvolnum>8</manvolnum></citerefentry> measures the kernel command line in this PCR.</entry>
+                <entry><citerefentry><refentrytitle>sd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures the kernel command line in this PCR.</entry>
               </row>
             </tbody>
           </tgroup>
index c70d6a9d3ed3b0f6dc15c8879f901ee2fcf4f3b2..668208a01d35a8828ee1e3b3fccbedf6317226f8 100644 (file)
 
   <refnamediv>
     <refname>systemd-cryptsetup@.service</refname>
+    <!-- <refname>system-systemd\x2dcryptsetup.slice</refname> — this causes meson to go haywire because it
+         thinks this is a (windows) path. Let's just not create the alias for this name, and only include it
+         in the synopsis. -->
     <refname>systemd-cryptsetup</refname>
     <refpurpose>Full disk decryption logic</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
     <para><filename>systemd-cryptsetup@.service</filename></para>
+    <para><filename>system-systemd\x2dcryptsetup.slice</filename></para>
     <para><filename>/usr/lib/systemd/systemd-cryptsetup</filename></para>
   </refsynopsisdiv>
 
   <refsect1>
     <title>Description</title>
 
-    <para><filename>systemd-cryptsetup@.service</filename> is a
-    service responsible for setting up encrypted block devices. It is
-    instantiated for each device that requires decryption for
-    access.</para>
+    <para><filename>systemd-cryptsetup@.service</filename> is a service responsible for setting up encrypted
+    block devices. It is instantiated for each device that requires decryption for access.</para>
+
+    <para><filename>systemd-cryptsetup@.service</filename> instances are part of the
+    <filename>system-systemd\x2dcryptsetup.slice</filename> slice, which is destroyed only very late in the
+    shutdown procedure. This allows the encrypted devices to remain up until filesystems have been unmounted.
+    </para>
 
     <para><filename>systemd-cryptsetup@.service</filename> will ask
     for hard disk passwords via the <ulink
index 654cf9b84c441f5c5f1c2838a01a3e1bbd4a6468..14bfd19b6220c82c1da8b7b9282f53726990d073 100644 (file)
 
           <row>
             <entry><varname>kvm</varname></entry>
-            <entry>Linux KVM kernel virtual machine, with whatever software, except Oracle Virtualbox</entry>
+            <entry>Linux KVM kernel virtual machine, in combination with QEMU. Not used for other virtualizers using the KVM interfaces, such as Oracle VirtualBox or Amazon EC2 Nitro, see below.</entry>
+          </row>
+
+          <row>
+            <entry><varname>amazon</varname></entry>
+            <entry>Amazon EC2 Nitro using Linux KVM</entry>
           </row>
 
           <row>
index caaf68dcae8bc99f3efb293754b3edbbfafef08d..4cdac2b013fb757b57c74ebac47e30d109a4bd69 100644 (file)
         <term><option>--fsck=no</option></term>
 
         <listitem><para>Turn off automatic file system checking. By default when an image is accessed for
-        writing (by <option>--mount</option> or <option>--add</option>) the file systems contained in the OS
-        image are automatically checked using the appropriate <citerefentry
+        writing (by <option>--mount</option> or <option>--copy-to</option>) the file systems contained in the
+        OS image are automatically checked using the appropriate <citerefentry
         project='man-pages'><refentrytitle>fsck</refentrytitle><manvolnum>8</manvolnum></citerefentry>
         command, in automatic fixing mode. This behavior may be switched off using
         <option>--fsck=no</option>.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--growfs=no</option></term>
+
+        <listitem><para>Turn off automatic growing of accessed file systems to their partition size, if
+        marked for that in the GPT partition table. By default when an image is accessed for writing (by
+        <option>--mount</option> or <option>--copy-to</option>) the file systems contained in the OS image
+        are automatically grown to their partition sizes, if bit 59 in the GPT partition flags is set for
+        partition types that are defined by the <ulink
+        url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions Specification</ulink>. This
+        behavior may be switched off using <option>--growfs=no</option>. File systems are grown automatically
+        on access if all of the following conditions are met:</para>
+        <orderedlist>
+          <listitem><para>The file system is mounted writable</para></listitem>
+          <listitem><para>The file system currently is smaller than the partition it is contained in (and thus can be grown)</para></listitem>
+          <listitem><para>The image contains a GPT partition table</para></listitem>
+          <listitem><para>The file system is stored on a partition defined by the Discoverable Partitions Specification</para></listitem>
+          <listitem><para>Bit 59 of the GPT partition flags for this partition is set, as per specification</para></listitem>
+          <listitem><para>The <option>--growfs=no</option> option is not passed.</para></listitem>
+        </orderedlist>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--mkdir</option></term>
 
index 100192490230d8caea9dd8844489d63a8b771fc9..46fe0a0682cea690e80d61c50ad62ed2185f81d7 100644 (file)
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
     </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Credentials</title>
+
+    <para><command>systemd-firstboot</command> supports the service credentials logic as implemented by
+    <varname>LoadCredential=</varname>/<varname>SetCredential=</varname> (see
+    <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+    details). The following credentials are used when passed in:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term><literal>passwd.hashed-password.root</literal></term>
+        <term><literal>passwd.plaintext-password.root</literal></term>
+
+        <listitem><para>A hashed or plaintext version of the root password to use, in place of prompting the
+        user. These credentials are equivalent to the same ones defined for the
+        <citerefentry><refentrytitle>systemd-sysusers.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        service.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><literal>passwd.shell.root</literal></term>
+
+        <listitem><para>Specifies the shell binary to use for the the specified account when creating
+        it. Equivalent to the credential of the same name defined for the
+        <citerefentry><refentrytitle>systemd-sysusers.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        service.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><literal>firstboot.locale</literal></term>
+        <term><literal>firstboot.locale-messages</literal></term>
+
+        <listitem><para>These credentials specify the locale settings to set during first boot, in place of
+        prompting the user.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><literal>firstboot.keymap</literal></term>
+
+        <listitem><para>This credential specifies the keyboard setting to set during first boot, in place of
+        prompting the user.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><literal>firstboot.timezone</literal></term>
+
+        <listitem><para>This credential specifies the system timezone setting to set during first boot, in
+        place of prompting the user.</para></listitem>
+      </varlistentry>
+    </variablelist>
+
+    <para>Note that by default the <filename>systemd-firstboot.service</filename> unit file is set up to
+    inherit the listed credentials
+    from the service manager. Thus, when invoking a container with an unpopulated <filename>/etc/</filename>
+    for the first time it is possible to configure the root user's password to be <literal>systemd</literal>
+    like this:</para>
+
+    <para><programlisting># systemd-nspawn --image=… --set-credential=firstboot.locale:de_DE.UTF-8 …</programlisting></para>
 
+    <para>Note that these credentials are only read and applied during the first boot process. Once they are
+    applied they remain applied for subsequent boots, and the credentials are not considered anymore.</para>
   </refsect1>
 
   <refsect1>
index 19cc69f1a53d590cb3f380df71a46fac61253e3a..1e3c17bce0f8289ef2c3792051d2cdb2e33fc2d2 100644 (file)
@@ -34,7 +34,7 @@
     <citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>, and provides the implementation for
     <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
     <command>pull-raw</command>, <command>pull-tar</command>, <command>import-raw</command>,
-    <command>import-tar</command>, <command>export-raw</command>, and <command>export-tar</command> commands.</para>
+    <command>import-tar</command>, <command>import-fs</command>, <command>export-raw</command>, and <command>export-tar</command> commands.</para>
 
     <para>See
     <citerefentry><refentrytitle>org.freedesktop.import1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
index 35cfbde86c8b94e728657ad7f8aa3f64c6e5b5cc..b66e6ea8ebcdf3214a083e3e5dc33fff800a1927 100644 (file)
       project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
       call</para></listitem>
 
-      <listitem><para>Structured system log messages via the native
-      Journal API, see
-      <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry></para></listitem>
+      <listitem><para>Structured system log messages via the native Journal API, see
+      <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+      and <ulink url="https://systemd.io/JOURNAL_NATIVE_PROTOCOL">Native Journal
+      Protocol</ulink></para></listitem>
 
       <listitem><para>Standard output and standard error of service units. For further details see
       below.</para></listitem>
     <citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> to configure
     where log data is placed, independently of the existence of <filename>/var/log/journal/</filename>.</para>
 
+    <para>Note that journald will initially use volatile storage, until a call to 
+    <command>journalctl --flush</command> (or sending <constant>SIGUSR1</constant> to journald) will cause 
+    it to switch to persistent logging (under the conditions mentioned above). This is done automatically
+    on boot via <literal>systemd-journal-flush.service</literal>.</para>
+
     <para>On systems where <filename>/var/log/journal/</filename> does not exist yet but where persistent logging is
     desired (and the default <filename>journald.conf</filename> is used), it is sufficient to create the directory, and
     ensure it has the correct access modes and ownership:</para>
index 2c2a0964932b7325758d9dd3772da3061a7dbb30..a9c52d842c54bb9c16c800a35090832ededa14cb 100644 (file)
     <variablelist>
 
       <varlistentry>
-        <term><option>--root=<replaceable>root</replaceable></option></term>
-        <listitem><para>Takes a directory path as argument. All paths
-        operated will be prefixed with the given alternate
-        <replaceable>root</replaceable> path, including the path for
+        <term><option>--root=<replaceable>path</replaceable></option></term>
+        <listitem><para>Takes a directory path as argument. All paths operated on will be prefixed with the
+        given alternate <replaceable>root</replaceable> path, including the path for
         <filename>/etc/machine-id</filename> itself.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--image=<replaceable>path</replaceable></option></term>
+        <listitem><para>Takes a path to a device node or refular file as argument. This is similar to
+        <option>--root=</option> as described above, but operates on a disk image instead of a directory
+        tree.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--commit</option></term>
         <listitem><para>Commit a transient machine ID to disk. This
index 6d2c71d8c7bf3f001e92478806d501b3a82bb8d5..31aa02218af8334e318fa9165445993cc669b7f1 100644 (file)
         </para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>-4</option></term>
+        <term><option>--ipv4</option></term>
+
+        <listitem><para>Waiting for an IPv4 address of each network interface to be configured. If this
+        option is specified with <option>--any</option>, then
+        <command>systemd-networkd-wait-online</command> exits with success when at least one interface
+        becomes online and has an IPv4 address. The option is applied only for the operational state
+        <literal>degraded</literal> or above. If neither <option>--ipv4</option> nor
+        <option>--ipv6</option> is specified, then the value from
+        <varname>RequiredFamilyForOnline=</varname> in the corresponding <filename>.network</filename>
+        file is used if present.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>-6</option></term>
+        <term><option>--ipv6</option></term>
+
+        <listitem><para>Waiting for an IPv6 address of each network interface to be configured. If this
+        option is specified with <option>--any</option>, then
+        <command>systemd-networkd-wait-online</command> exits with success when at least one interface
+        becomes online and has an IPv6 address. The option is applied only for the operational state
+        <literal>degraded</literal> or above. If neither <option>--ipv4</option> nor
+        <option>--ipv6</option> is specified, then the value from
+        <varname>RequiredFamilyForOnline=</varname> in the corresponding <filename>.network</filename>
+        file is used if present.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--any</option></term>
 
index 6a27bab1e30639c793644dfb150d40fe5ac8265e..c4732507df0b23e013392478674a1525f807bdc0 100644 (file)
@@ -1487,7 +1487,31 @@ After=sys-subsystem-net-devices-ens1.device</programlisting>
         <para>In order to embed binary data into the credential data for <option>--set-credential=</option>
         use C-style escaping (i.e. <literal>\n</literal> to embed a newline, or <literal>\x00</literal> to
         embed a <constant>NUL</constant> byte. Note that the invoking shell might already apply unescaping
-        once, hence this might require double escaping!).</para></listitem>
+        once, hence this might require double escaping!).</para>
+
+        <para>The
+        <citerefentry><refentrytitle>systemd-sysusers.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        and
+        <citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+        services read credentials configured this way for the purpose of configuring the container's root
+        user's password and shell, as well as system locale, keymap and timezone during the first boot
+        process of the container. This is particularly useful in combination with
+        <option>--volatile=yes</option> where every single boot appears as first boot, since configuration
+        applied to <filename>/etc/</filename> is lost on container reboot cycles. See the respective man
+        pages for details. Example:</para>
+
+        <programlisting># systemd-nspawn -i image.raw \
+        --volatile=yes \
+        --set-credential=firstboot.locale:de_DE.UTF-8 \
+        --set-credential=passwd.hashed-password.root:'$y$j9T$yAuRJu1o5HioZAGDYPU5d.$F64ni6J2y2nNQve90M/p0ZP0ECP/qqzipNyaY9fjGpC' \
+        -b</programlisting>
+
+        <para>The above command line will invoke the specified image file <filename>image.raw</filename> in
+        volatile mode, i.e with an empty <filename>/etc/</filename> and <filename>/var/</filename>, so that
+        the container's payload recognizes this as first boot condition, and will invoke
+        <filename>systemd-firstboot.service</filename>, which then read the two passed credentials to
+        configure the system's initial locale and root password.</para>
+        </listitem>
         </varlistentry>
 
     </variablelist>
index ebd2467ee2323cce3e62c932fa684388fc02fe48..86c47e5b572c39373af9da33afe941ec4cb616de 100644 (file)
     <title>Setup Information</title>
 
     <para>The system must be running systemd with a full unified cgroup hierarchy for the expected cgroups-v2 features.
-    Furthermore, resource accounting must be turned on for all units monitored by <command>systemd-oomd</command>.
-    The easiest way to turn on resource accounting is by ensuring the values for <varname>DefaultCPUAccounting</varname>,
-    <varname>DefaultIOAccounting</varname>, <varname>DefaultMemoryAccounting</varname>, and
-    <varname>DefaultTasksAccounting</varname> are set to <constant>true</constant> in
+    Furthermore, memory accounting must be turned on for all units monitored by <command>systemd-oomd</command>.
+    The easiest way to turn on memory accounting is by ensuring the value for <varname>DefaultMemoryAccounting=</varname>
+    is set to <constant>true</constant> in
     <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
 
     <para>You will need a kernel compiled with PSI support. This is available in Linux 4.20 and above.</para>
index a5a0890c526c174f48ecb36fc324cabe06ed46dd..380ba57884a3da0e03230c2b4713f7d6c1e932f2 100644 (file)
     <citerefentry><refentrytitle>repart.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
     </para>
 
-    <para>If invoked with no arguments, it operates on the block device backing the root file system partition
-    of the OS, thus growing and adding partitions of the booted OS image itself. When called in the initial
-    RAM disk it operates on the block device backing <filename>/sysroot/</filename> instead, i.e. on the
-    block device the system will soon transition into. The <filename>systemd-repart.service</filename>
-    service is generally run at boot in the initial RAM disk, in order to augment the partition table of the
-    OS before its partitions are mounted. <command>systemd-repart</command> (mostly) operates in a purely
-    incremental mode: it only grows existing and adds new partitions; it does not shrink, delete or move
-    existing partitions. The service is intended to be run on every boot, but when it detects that the
-    partition table already matches the installed <filename>repart.d/*.conf</filename> configuration
-    files, it executes no operation.</para>
+    <para>If invoked with no arguments, it operates on the block device backing the root file system
+    partition of the running OS, thus growing and adding partitions of the booted OS image itself. If
+    <varname>--image=</varname> is used it will operate on the specified image file. When called in the
+    <literal>initrd</literal> it operates on the block device backing <filename>/sysroot/</filename> instead,
+    i.e. on the block device the system will soon transition into. The
+    <filename>systemd-repart.service</filename> service is generally run at boot in the initial RAM disk, in
+    order to augment the partition table of the OS before its partitions are
+    mounted. <command>systemd-repart</command> (mostly) operates in a purely incremental mode: it only grows
+    existing and adds new partitions; it does not shrink, delete or move existing partitions. The service is
+    intended to be run on every boot, but when it detects that the partition table already matches the
+    installed <filename>repart.d/*.conf</filename> configuration files, it executes no operation.</para>
 
     <para><command>systemd-repart</command> is intended to be used when deploying OS images, to automatically
     adjust them to the system they are running on, during first boot. This way the deployed image can be
         <term><option>--root=</option></term>
 
         <listitem><para>Takes a path to a directory to use as root file system when searching for
-        <filename>repart.d/*.conf</filename> files and for the machine ID file to use as seed. By default
-        when invoked on the regular system this defaults to the host's root file system
+        <filename>repart.d/*.conf</filename> files, for the machine ID file to use as seed and for the
+        <varname>CopyFiles=</varname> and <varname>CopyBlocks=</varname> source files and directories. By
+        default when invoked on the regular system this defaults to the host's root file system
         <filename>/</filename>. If invoked from the initial RAM disk this defaults to
         <filename>/sysroot/</filename>, so that the tool operates on the configuration and machine ID stored
         in the root file system later transitioned into itself.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--image=</option></term>
+
+        <listitem><para>Takes a path to a disk image file or device to mount and use in a similar fashion to
+        <option>--root=</option>, see above.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--seed=</option></term>
 
index ed6214cd625b23362fac6c86726cdeaf50955bf9..9c7c482549d4a9cc728461838e6368db42f09f55 100644 (file)
       gateway addresses, ordered by their metric. This assigns a stable hostname to the current gateway,
       useful for referencing it independently of the current network configuration state.</para></listitem>
 
+      <listitem><para>The hostname <literal>_outbound</literal> is resolved to the local IPv4 and IPv6
+      addresses that are most likely used for communication with other hosts. This is determined by
+      requesting a routing decision to the configured default gateways from the kernel and then using the
+      local IP addresses selected by this decision. This hostname is only available if there is at least one
+      local default gateway configured. This assigns a stable hostname to the local outbound IP addresses,
+      useful for referencing them independently of the current network configuration state.</para></listitem>
+
       <listitem><para>The mappings defined in <filename>/etc/hosts</filename> are resolved to their
       configured addresses and back, but they will not affect lookups for non-address types (like MX).
       Support for <filename>/etc/hosts</filename> may be disabled with <varname>ReadEtcHosts=no</varname>,
index 950a8b4499bbb9e306cbacd2bf94468929b9026c..466a4601514fffcaffef13e12c80af9f00774868 100644 (file)
       <xi:include href="standard-options.xml" xpointer="help" />
       <xi:include href="standard-options.xml" xpointer="version" />
     </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Credentials</title>
+
+    <para><command>systemd-sysusers</command> supports the service credentials logic as implemented by
+    <varname>LoadCredential=</varname>/<varname>SetCredential=</varname> (see
+    <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+    details). The following credentials are used when passed in:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term><literal>passwd.hashed-password.<replaceable>user</replaceable></literal></term>
+        <listitem><para>A UNIX hashed password string to use for the specified user, when creating an entry
+        for it. This is particularly useful for the <literal>root</literal> user as it allows provisioning
+        the default root password to use via a unit file drop-in or from a container manager passing in this
+        credential. Note that setting this credential has no effect if the specified user account already
+        exists. This credential is hence primarily useful in first boot scenarios or systems that are fully
+        stateless and come up with an empty <filename>/etc/</filename> on every boot.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><literal>passwd.plaintext-password.<replaceable>user</replaceable></literal></term>
+
+        <listitem><para>Similar to <literal>passwd.hashed-password.<replaceable>user</replaceable></literal>
+        but expect a literal, plaintext password, which is then automatically hashed before used for the user
+        account. If both the hashed and the plaintext credential are specified for the same user the
+        former takes precedence. It's generally recommended to specify the hashed version; however in test
+        environments with weaker requirements on security it might be easier to pass passwords in plaintext
+        instead.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><literal>passwd.shell.<replaceable>user</replaceable></literal></term>
+
+        <listitem><para>Specifies the shell binary to use for the the specified account when creating it.</para></listitem>
+      </varlistentry>
+    </variablelist>
+
+    <para>Note that by default the <filename>systemd-sysusers.service</filename> unit file is set up to
+    inherit the <literal>passwd.hashed-password.root</literal>,
+    <literal>passwd.plaintext-password.root</literal> and <literal>passwd.shell.root</literal> credentials
+    from the service manager. Thus, when invoking a container with an unpopulated <filename>/etc/</filename>
+    for the first time it is possible to configure the root user's password to be <literal>systemd</literal>
+    like this:</para>
+
+    <para><programlisting># systemd-nspawn --image=… --set-credential=password.hashed-password.root:'$y$j9T$yAuRJu1o5HioZAGDYPU5d.$F64ni6J2y2nNQve90M/p0ZP0ECP/qqzipNyaY9fjGpC' …</programlisting></para>
+
+    <para>Note again that the data specified in these credentials is consulted only when creating an account
+    for the first time, it may not be used for changing the password or shell of an account that already
+    exists.</para>
 
+    <para>Use <citerefentry><refentrytitle>mkpasswd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+    for generating UNIX password hashes from the command line.</para>
   </refsect1>
 
   <refsect1>
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>sysusers.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
-      <ulink url="https://systemd.io/UIDS-GIDS">Users, Groups, UIDs and GIDs on systemd systems</ulink>
+      <ulink url="https://systemd.io/UIDS-GIDS">Users, Groups, UIDs and GIDs on systemd systems</ulink>,
+      <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>mkpasswd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
     </para>
   </refsect1>
 
index 5f97e37025f3b530de4c56efd7d3e91a96c5dcbb..15bc1ea889b830d5c029513611e82dd79899f5fa 100644 (file)
   <refsect1>
     <title>Exit status</title>
 
-    <para>On success, 0 is returned. If the configuration was syntactically invalid (syntax errors,
-    missing arguments, …), so some lines had to be ignored, but no other errors occurred,
-    <constant>65</constant> is returned (<constant>EX_DATAERR</constant> from
-    <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_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>
+    <para>On success, 0 is returned. If the configuration was syntactically invalid (syntax errors, missing
+    arguments, …), so some lines had to be ignored, but no other errors occurred, <constant>65</constant> is
+    returned (<constant>EX_DATAERR</constant> from <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_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>
+
+    <para>Note: when creating items, if the target already exists, but is of the wrong type or otherwise does
+    not match the requested state, and forced operation has not been requested with <literal>+</literal>,
+    a message is emitted, but the failure is otherwise ignored.</para>
   </refsect1>
 
   <refsect1>
index 5df4cd6a223ef98018c6883cc7ef82335c4f1ee5..32cb82bac304d1a5b04f824cd4e8b31dffa29ac4 100644 (file)
@@ -88,8 +88,8 @@
         <term><option>-e</option></term>
         <term><option>--exec-delay=</option></term>
         <listitem>
-          <para>Delay the execution of <varname>RUN</varname>
-          instructions by the given number of seconds. This option
+          <para>Delay the execution of each <varname>RUN{<replaceable>program</replaceable>}</varname>
+          parameter by the given number of seconds. This option
           might be useful when debugging system crashes during
           coldplug caused by loading non-working kernel
           modules.</para>
         <term><varname>udev.exec_delay=</varname></term>
         <term><varname>rd.udev.exec_delay=</varname></term>
         <listitem>
-          <para>Delay the execution of <varname>RUN</varname> instructions by the given
+          <para>Delay the execution of each <varname>RUN{<replaceable>program</replaceable>}</varname> parameter by the given
           number of seconds. This option might be useful when
           debugging system crashes during coldplug caused by loading
           non-working kernel modules.</para>
index 96a14b1ba542063cc7e21878092e42c2f6d1bda5..be2e873efb3a10ae8bc36623eaca6a73b777920e 100644 (file)
                 </thead>
                 <tbody>
                   <xi:include href="standard-specifiers.xml" xpointer="a"/>
+                  <xi:include href="standard-specifiers.xml" xpointer="A"/>
                   <xi:include href="standard-specifiers.xml" xpointer="b"/>
                   <xi:include href="standard-specifiers.xml" xpointer="B"/>
                   <xi:include href="standard-specifiers.xml" xpointer="H"/>
                   <xi:include href="standard-specifiers.xml" xpointer="m"/>
+                  <xi:include href="standard-specifiers.xml" xpointer="M"/>
                   <xi:include href="standard-specifiers.xml" xpointer="o"/>
                   <xi:include href="standard-specifiers.xml" xpointer="v"/>
                   <xi:include href="standard-specifiers.xml" xpointer="w"/>
index 5bb9af3e7da63682a8dd0affde0b04590d7fb6ea..b2fbb3b64417f42a8edc71b03e4d50ff6c45af31 100644 (file)
@@ -1777,11 +1777,13 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
         <term><varname>RestrictAddressFamilies=</varname></term>
 
         <listitem><para>Restricts the set of socket address families accessible to the processes of this
-        unit. Takes a space-separated list of address family names to allow-list, such as
-        <constant>AF_UNIX</constant>, <constant>AF_INET</constant> or <constant>AF_INET6</constant>. When
-        prefixed with <constant>~</constant> the listed address families will be applied as deny list,
-        otherwise as allow list.  Note that this restricts access to the <citerefentry
-        project='man-pages'><refentrytitle>socket</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+        unit. Takes <literal>none</literal>, or a space-separated list of address family names to
+        allow-list, such as <constant>AF_UNIX</constant>, <constant>AF_INET</constant> or
+        <constant>AF_INET6</constant>. When <literal>none</literal> is specified, then all address
+        families will be denied. When prefixed with <literal>~</literal> the listed address
+        families will be applied as deny list, otherwise as allow list. Note that this restricts access
+        to the
+        <citerefentry project='man-pages'><refentrytitle>socket</refentrytitle><manvolnum>2</manvolnum></citerefentry>
         system call only. Sockets passed into the process by other means (for example, by using socket
         activation with socket units, see
         <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
@@ -2651,7 +2653,8 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
         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 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
+        of the processes belonging to this unit, as well as any log messages written by the system manager process
+        (PID 1) in reference 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
         subsystem. For example, <varname>MaxLevelStore=</varname> configured in
@@ -2821,7 +2824,7 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
     <variablelist class='unit-directives'>
 
       <varlistentry>
-        <term><varname>LoadCredential=</varname><replaceable>ID</replaceable>:<replaceable>PATH</replaceable></term>
+        <term><varname>LoadCredential=</varname><replaceable>ID</replaceable><optional>:<replaceable>PATH</replaceable></optional></term>
 
         <listitem><para>Pass a credential to the unit. Credentials are limited-size binary or textual objects
         that may be passed to unit processes. They are primarily used for passing cryptographic keys (both
@@ -2834,19 +2837,21 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
         environment variable to the unit's processes.</para>
 
         <para>The <varname>LoadCredential=</varname> setting takes a textual ID to use as name for a
-        credential plus a file system path. The ID must be a short ASCII string suitable as filename in the
-        filesystem, and may be chosen freely by the user. If the specified path is absolute it is opened as
-        regular file and the credential data is read from it. If the absolute path refers to an
-        <constant>AF_UNIX</constant> stream socket in the file system a connection is made to it (only once
-        at unit start-up) and the credential data read from the connection, providing an easy IPC integration
-        point for dynamically providing credentials from other services. If the specified path is not
-        absolute and itself qualifies as valid credential identifier it is understood to refer to a
-        credential that the service manager itself received via the <varname>$CREDENTIALS_DIRECTORY</varname>
-        environment variable, which may be used to propagate credentials from an invoking environment (e.g. a
-        container manager that invoked the service manager) into a service. The contents of the file/socket
-        may be arbitrary binary or textual data, including newline characters and <constant>NUL</constant>
-        bytes. This option may be used multiple times, each time defining an additional credential to pass to
-        the unit.</para>
+        credential plus a file system path, separated by a colon. The ID must be a short ASCII string
+        suitable as filename in the filesystem, and may be chosen freely by the user. If the specified path
+        is absolute it is opened as regular file and the credential data is read from it. If the absolute
+        path refers to an <constant>AF_UNIX</constant> stream socket in the file system a connection is made
+        to it (only once at unit start-up) and the credential data read from the connection, providing an
+        easy IPC integration point for dynamically providing credentials from other services. If the
+        specified path is not absolute and itself qualifies as valid credential identifier it is understood
+        to refer to a credential that the service manager itself received via the
+        <varname>$CREDENTIALS_DIRECTORY</varname> environment variable, which may be used to propagate
+        credentials from an invoking environment (e.g. a container manager that invoked the service manager)
+        into a service. The contents of the file/socket may be arbitrary binary or textual data, including
+        newline characters and <constant>NUL</constant> bytes. If the file system path is omitted it is
+        chosen identical to the credential name, i.e. this is a terse way do declare credentials to inherit
+        from the service manager into a service. This option may be used multiple times, each time defining
+        an additional credential to pass to the unit.</para>
 
         <para>The credential files/IPC sockets must be accessible to the service manager, but don't have to
         be directly accessible to the unit's processes: the credential data is read and copied into separate,
index 5918a32189810c54190d92e19aa6343ce3ad519a..6be115026bb55596f0806fd99f3c40ffd7feb46d 100644 (file)
           </para>
         </listitem>
       </varlistentry>
+
+      <varlistentry id='firmware'>
+        <term><varname>Firmware=</varname></term>
+        <listitem>
+          <para>Checks whether the system is running on a machine with the specified firmware. See
+          <varname>ConditionFirmware=</varname> in
+          <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+          for details. When prefixed with an exclamation mark (<literal>!</literal>), the result is negated.
+          If an empty string is assigned, then previously assigned value is cleared.
+          </para>
+        </listitem>
+      </varlistentry>
     </variablelist>
 
   </refsect1>
index 646dd3e561108b1a9f32cb32dd763ed3920e08f7..bc1ff7876d90b40a290fe3b67b1755c2de10b85b 100644 (file)
           property.</para></listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><constant>v249</constant></term>
+
+          <listitem><para>PCI hotplug slot names for the s390 PCI driver are a hexadecimal representation
+          of the <filename>function_id</filename> device attribute. This attribute is now used to build the
+          <varname>ID_NET_NAME_SLOT</varname>. Before that, all slot names were parsed as decimal
+          numbers, which could either result in an incorrect value of the <varname>ID_NET_NAME_SLOT</varname>
+          property or none at all.</para>
+
+          <para>Some firmware and hypervisor implementations report unreasonable high numbers for the onboard
+          index. To prevent the generation of bogus onbard interface names, index numbers greater than 16381
+          (2^14-1) were ignored. For s390 PCI devices index values up to 65535 (2^16-1) are valid. To account
+          for that, the limit is increased to now 65535.</para></listitem>
+        </varlistentry>
+
       </variablelist>
 
     <para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this
index c1b1980bac50f9124f35e119f0bb4c2bc719c222..d93ee8bb30cc4761a7098ff73c4b8f020fb49045 100644 (file)
           </para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>Firmware=</varname></term>
+        <listitem>
+          <para>Checks whether the system is running on a machine with the specified firmware. See
+          <literal>ConditionFirmware=</literal> in
+          <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+          for details. When prefixed with an exclamation mark (<literal>!</literal>), the result is negated.
+          If an empty string is assigned, then previously assigned value is cleared.
+          </para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
index cec2f96f26c8196862be0b4b33b349f1cd7741d3..7f137db2231cd10dddcf1efa29234e8289643dee 100644 (file)
           if <literal>RequiredForOnline=no</literal>.</para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>RequiredFamilyForOnline=</varname></term>
+        <listitem>
+          <para>Specifies an address family. When specified,
+          <command>systemd-networkd-wait-online</command> waits for at least one routable or link-local
+          IP address in the family should be configured on the link. Takes one of
+          <literal>ipv4</literal>, <literal>ipv6</literal>, <literal>both</literal>, or
+          <literal>any</literal>. Defaults to <literal>any</literal>. Note that this will be used only
+          when <varname>RequiredForOnline=</varname> is true, or its minimum operational state is
+          <literal>degraded</literal> or above. Otherwise, it will be ignored.</para>
+        </listitem>
+      </varlistentry>
       <varlistentry>
         <term><varname>ActivationPolicy=</varname></term>
         <listitem>
@@ -1087,6 +1099,15 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
             Defaults to <literal>global</literal>.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>RouteMetric=</varname></term>
+          <listitem>
+            <para>The metric of the prefix route, which is pointing to the subnet of the configured IP
+            address, taking the configured prefix length into account. Takes an unsigned integer in the
+            range 0…4294967295. When unset or set to 0, the kernel's default value is used. This
+            setting will be ignored when <varname>AddPrefixRoute=</varname> is false.</para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><varname>HomeAddress=</varname></term>
           <listitem>
@@ -1409,7 +1430,8 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
         <varlistentry>
           <term><varname>Metric=</varname></term>
           <listitem>
-            <para>The metric of the route (an unsigned integer).</para>
+            <para>The metric of the route. Takes an unsigned integer in the range 0…4294967295.
+            Defaluts to unset, and the kernel's default will be used.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
@@ -1609,7 +1631,7 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
           <listitem>
             <para>When true, the routes to the DNS servers received from the DHCP server will be
             configured. When <varname>UseDNS=</varname> is disabled, this setting is ignored.
-            Defaults to false.</para>
+            Defaults to true.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
@@ -1619,6 +1641,14 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
             <filename>systemd-timesyncd.service</filename>.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>RoutesToNTP=</varname></term>
+          <listitem>
+            <para>When true, the routes to the NTP servers received from the DHCP server will be
+            configured. When <varname>UseNTP=</varname> is disabled, this setting is ignored.
+            Defaults to true.</para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><varname>UseSIP=</varname></term>
           <listitem>
@@ -1639,26 +1669,24 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
         <varlistentry>
           <term><varname>Anonymize=</varname></term>
           <listitem>
-            <para>Takes a boolean. When true, the options sent to the DHCP server will
-            follow the <ulink url="https://tools.ietf.org/html/rfc7844">RFC 7844</ulink>
-            (Anonymity Profiles for DHCP Clients) to minimize disclosure of identifying information.
-            Defaults to false.</para>
+            <para>Takes a boolean. When true, the options sent to the DHCP server will follow the
+            <ulink url="https://tools.ietf.org/html/rfc7844">RFC 7844</ulink> (Anonymity Profiles for
+            DHCP Clients) to minimize disclosure of identifying information. Defaults to false.</para>
 
-            <para>This option should only be set to true when
-            <varname>MACAddressPolicy=</varname> is set to <literal>random</literal>
-            (see <citerefentry
-            project='man-pages'><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>).</para>
+            <para>This option should only be set to true when <varname>MACAddressPolicy=</varname> is
+            set to <literal>random</literal> (see
+            <citerefentry project='man-pages'><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
+            </para>
 
-            <para>Note that this configuration will overwrite others.
-            In concrete, the following variables will be ignored:
-            <varname>SendHostname=</varname>, <varname>ClientIdentifier=</varname>,
-            <varname>UseRoutes=</varname>, <varname>UseMTU=</varname>,
-            <varname>VendorClassIdentifier=</varname>, <varname>UseTimezone=</varname>.</para>
+            <para>When true, <varname>SendHostname=</varname>, <varname>ClientIdentifier=</varname>,
+            <varname>VendorClassIdentifier=</varname>, <varname>UserClass=</varname>,
+            <varname>RequestOptions=</varname>, <varname>SendOption=</varname>,
+            <varname>SendVendorOption=</varname>, and <varname>MUDURL=</varname> are ignored.</para>
 
-            <para>With this option enabled DHCP requests will mimic those generated by Microsoft Windows, in
-            order to reduce the ability to fingerprint and recognize installations. This means DHCP request
-            sizes will grow and lease data will be more comprehensive than normally, though most of the
-            requested data is not actually used.</para>
+            <para>With this option enabled DHCP requests will mimic those generated by Microsoft
+            Windows, in order to reduce the ability to fingerprint and recognize installations. This
+            means DHCP request sizes will grow and lease data will be more comprehensive than normally,
+            though most of the requested data is not actually used.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
@@ -1827,7 +1855,8 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
         <varlistentry>
           <term><varname>RouteMetric=</varname></term>
           <listitem>
-            <para>Set the routing metric for routes specified by the DHCP server. Defaults to 1024.</para>
+            <para>Set the routing metric for routes specified by the DHCP server. Takes an unsigned
+            integer in the range 0…4294967295. Defaults to 1024.</para>
           </listitem>
         </varlistentry>
 
@@ -1961,18 +1990,15 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
           <term><varname>UseDNS=</varname></term>
           <term><varname>UseNTP=</varname></term>
           <term><varname>UseHostname=</varname></term>
+          <term><varname>UseDomains=</varname></term>
+          <term><varname>IAID=</varname></term>
+          <term><varname>DUIDType=</varname></term>
+          <term><varname>DUIDRawData=</varname></term>
           <listitem>
             <para>As in the [DHCPv4] section.</para>
           </listitem>
         </varlistentry>
 
-        <varlistentry>
-          <term><varname>RouteMetric=</varname></term>
-          <listitem>
-            <para>Set the routing metric for routes specified by the DHCP server. Defaults to 1024.</para>
-          </listitem>
-        </varlistentry>
-
         <varlistentry>
           <term><varname>RapidCommit=</varname></term>
           <listitem>
@@ -2147,6 +2173,14 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
           <para>As in the [Address] section, but defaults to true.</para>
         </listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term><varname>RouteMetric=</varname></term>
+        <listitem>
+          <para>The metric of the route to the delegated prefix subnet. Takes an unsigned integer in
+          the range 0…4294967295. When unset or set to 0, the kernel's default value is used.</para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
@@ -2196,6 +2230,14 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>RouteMetric=</varname></term>
+          <listitem>
+            <para>Set the routing metric for the routes received in the Router Advertisement. Takes an
+            unsigned integer in the range 0…4294967295. Defaults to 1024.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term><varname>UseAutonomousPrefix=</varname></term>
           <listitem>
@@ -2283,6 +2325,17 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
 
     <variablelist class='network-directives'>
 
+      <varlistentry>
+        <term><varname>RelayTarget=</varname></term>
+        <listitem>
+          <para>Takes an IPv4 address, which must be in the format
+          described in
+          <citerefentry project='man-pages'><refentrytitle>inet_pton</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+          Turns this DHCP server into a DHCP relay agent. See <ulink url="https://tools.ietf.org/html/rfc1542">RFC 1542</ulink>.
+          The address is the address of DHCP server or another relay agent to forward DHCP messages to and from.</para>
+          Check also BindToInterface= option. Turning it off is required for relaying messages outside.
+        </listitem>
+      </varlistentry>
       <varlistentry>
         <term><varname>PoolOffset=</varname></term>
         <term><varname>PoolSize=</varname></term>
@@ -2406,6 +2459,13 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
           then all options specified earlier are cleared. Defaults to unset.</para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>BindToInterface=</varname></term>
+        <listitem>Takes a boolean value. When <literal>yes</literal>, DHCP server socket will be bound
+        to its network interface and all socket communication will be restricted to this interface.
+        Defaults to <literal>yes</literal>.
+        </listitem>
+      </varlistentry>
 
     </variablelist>
   </refsect1>
@@ -2535,6 +2595,15 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
         <listitem><para>Takes a boolean. When true, adds an address from the prefix. Default to false.
         </para></listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term><varname>RouteMetric=</varname></term>
+        <listitem>
+          <para>The metric of the prefix route. Takes an unsigned integer in the range 0…4294967295.
+          When unset or set to 0, the kernel's default value is used. This setting is ignored when
+          <varname>Assign=</varname> is false.</para>
+        </listitem>
+      </varlistentry>
     </variablelist>
     </refsect1>
 
index 1bc45a9f007acb0c5bda6670246c2ff5ce2f9c3d..d9b570e232cac4efc903a91dcc1be576ba1e14fc 100644 (file)
           <para>If these settings are used multiple times in the same unit all the specified programs are attached. If an
           empty string is assigned to these settings the program list is reset and all previous specified programs ignored.</para>
 
+          <para>If the path <replaceable>BPF_FS_PROGRAM_PATH</replaceable> in <varname>IPIngressFilterPath=</varname> assignment
+          is already being handled by <varname>BPFProgram=</varname> ingress hook, e.g.
+          <varname>BPFProgram=</varname><constant>ingress</constant>:<replaceable>BPF_FS_PROGRAM_PATH</replaceable>,
+          the assignment will be still considered valid and the program will be attached to a cgroup. Same for
+          <varname>IPEgressFilterPath=</varname> path and <constant>egress</constant> hook.</para>
+
           <para>Note that for socket-activated services, the IP filter programs configured on the socket unit apply to
           all sockets associated with it directly, but not to any sockets created by the ultimately activated services
           for it. Conversely, the IP filter programs configured for the service are not applied to any sockets passed into
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>BPFProgram=<replaceable>type</replaceable><constant>:</constant><replaceable>program-path</replaceable></varname></term>
+        <listitem>
+          <para>Add a custom cgroup BPF program.</para>
+
+          <para><varname>BPFProgram=</varname> allows attaching BPF hooks to the cgroup of a systemd unit.
+          (This generalizes the functionality exposed via <varname>IPEgressFilterPath=</varname> for egress and
+          <varname>IPIngressFilterPath=</varname> for ingress.)
+          Cgroup-bpf hooks in the form of BPF programs loaded to the BPF filesystem are attached with cgroup-bpf attach
+          flags determined by the unit. For details about attachment types and flags see <ulink
+          url="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/include/uapi/linux/bpf.h"/>.
+          For general BPF documentation please refer to <ulink url="https://www.kernel.org/doc/html/latest/bpf/index.html"/>.</para>
+
+          <para>The specification of BPF program consists of a <replaceable>type</replaceable> followed by a
+          <replaceable>program-path</replaceable> with <literal>:</literal> as the separator:
+          <replaceable>type</replaceable><constant>:</constant><replaceable>program-path</replaceable>.</para>
+
+          <para><replaceable>type</replaceable> is the string name of BPF attach type also used in
+          <command>bpftool</command>. <replaceable>type</replaceable> can be one of <constant>egress</constant>,
+          <constant>ingress</constant>, <constant>sock_create</constant>, <constant>sock_ops</constant>,
+          <constant>device</constant>, <constant>bind4</constant>, <constant>bind6</constant>,
+          <constant>connect4</constant>, <constant>connect6</constant>, <constant>post_bind4</constant>,
+          <constant>post_bind6</constant>, <constant>sendmsg4</constant>, <constant>sendmsg6</constant>,
+          <constant>sysctl</constant>, <constant>recvmsg4</constant>, <constant>recvmsg6</constant>,
+          <constant>getsockopt</constant>, <constant>setsockopt</constant>.</para>
+
+          <para>Setting <varname>BPFProgram=</varname> to an empty value makes previous assignments ineffective.</para>
+          <para>Multiple assignments of the same <replaceable>type</replaceable>:<replaceable>program-path</replaceable>
+          value have the same effect as a single assignment: the program with the path <replaceable>program-path</replaceable>
+          will be attached to cgroup hook <replaceable>type</replaceable> just once.</para>
+          <para>If BPF <constant>egress</constant> pinned to <replaceable>program-path</replaceable> path is already being
+          handled by <varname>IPEgressFilterPath=</varname>, <varname>BPFProgram=</varname>
+          assignment will be considered valid and <varname>BPFProgram=</varname> will be attached to a cgroup.
+          Similarly for <constant>ingress</constant> hook and <varname>IPIngressFilterPath=</varname> assignment.</para>
+
+          <para>BPF programs passed with <varname>BPFProgram=</varname> are attached to the cgroup of a unit with BPF
+          attach flag <constant>multi</constant>, that allows further attachments of the same
+          <replaceable>type</replaceable> within cgroup hierarchy topped by the unit cgroup.</para>
+
+          <para>Examples:<programlisting>
+BPFProgram=egress:/sys/fs/bpf/egress-hook
+BPFProgram=bind6:/sys/fs/bpf/sock-addr-hook
+</programlisting></para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>SocketBindAllow=<replaceable>bind-rule</replaceable></varname></term>
+        <term><varname>SocketBindDeny=<replaceable>bind-rule</replaceable></varname></term>
+
+        <listitem>
+          <para>Allow or deny binding a socket address to a socket by matching it with the <replaceable>bind-rule</replaceable> and
+          applying a corresponding action if there is a match.</para>
+
+          <para><replaceable>bind-rule</replaceable> describes socket properties such as <replaceable>address-family</replaceable>
+          and <replaceable>ip-ports</replaceable>.</para>
+
+          <para><replaceable>bind-rule</replaceable> := [<replaceable>address-family</replaceable><constant>:</constant>]<replaceable>ip-ports</replaceable></para>
+
+          <para><replaceable>address-family</replaceable> := { <constant>IPv4</constant> | <constant>IPv6</constant> }</para>
+
+          <para><replaceable>ip-ports</replaceable> := { <replaceable>ip-port</replaceable> | <replaceable>ip-port-range</replaceable> |
+          <constant>any</constant> }</para>
+
+          <para>An optional <replaceable>address-family</replaceable> expects <constant>IPv4</constant> or <constant>IPv6</constant> values.
+          If not specified, a rule will be matched for both IPv4 and IPv6 addresses and applied depending on other socket fields, e.g.
+          <replaceable>ip-port</replaceable>.</para>
+
+          <para><replaceable>ip-port</replaceable> value must lie within 1…65535 interval inclusively, i.e.
+          dynamic port <constant>0</constant> is not allowed. A range of sequential ports is described by
+          <replaceable>ip-port-range</replaceable> := <replaceable>ip-port-low</replaceable><constant>-</constant><replaceable>ip-port-high</replaceable>,
+          where <replaceable>ip-port-low</replaceable> is smaller than or equal to <replaceable>ip-port-high</replaceable>
+          and both are within 1…65535 inclusively. A special value <constant>any</constant>
+          should be used to apply a rule to any port with a positive value.</para>
+
+          <para>To allow multiple rules assign <varname>SocketBindAllow=</varname> or <varname>SocketBindDeny=</varname> multiple times.
+          To clear the existing assignments pass an empty <varname>SocketBindAllow=</varname> or <varname>SocketBindDeny=</varname>
+          assignment.</para>
+
+          <para>For each of <varname>SocketBindAllow=</varname> and <varname>SocketBindDeny=</varname>, maximum allowed number of assignments is
+          <constant>128</constant>.</para>
+
+          <itemizedlist>
+            <listitem><para>Binding to a socket is allowed when a socket address matches an entry in the
+            <varname>SocketBindAllow=</varname> list.</para></listitem>
+
+            <listitem><para>Otherwise, binding is denied when the socket address matches an entry in the
+            <varname>SocketBindDeny=</varname> list.</para></listitem>
+
+            <listitem><para>Otherwise, binding is allowed.</para></listitem>
+          </itemizedlist>
+
+          <para>The feature is implemented with <constant>cgroup/bind4</constant> and <constant>cgroup/bind6</constant> cgroup-bpf hooks.</para>
+          <para>Examples:<programlisting>…
+# Allow binding IPv6 socket addresses with a port greater than or equal to 10000.
+[Service]
+SocketBindAllow=IPv6:10000-65535
+SocketBindDeny=any
+…
+# Allow binding IPv4 and IPv6 socket addresses with 1234 and 4321 ports.
+[Service]
+SocketBindAllow=1234
+SocketBindAllow=4321
+SocketBindDeny=any
+…
+# Deny binding IPv6 socket addresses.
+[Service]
+SocketBindDeny=IPv6:any
+…
+# Deny binding IPv4 and IPv6 socket addresses.
+[Service]
+SocketBindDeny=any
+…</programlisting></para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>DeviceAllow=</varname></term>
 
index 350bc5f8e5bca5054c2702ed046ab9bfbe2d65f4..50d1a1d85d638f2404c2b943df6226bb48924a76 100644 (file)
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>ExitType=</varname></term>
+
+        <listitem>
+          <para>Configures the process exit type for this service unit. One of <option>main</option> or
+          <option>cgroup</option>:</para>
+
+          <itemizedlist>
+            <listitem><para>If set to <option>main</option> (the default), the service manager
+            will consider the unit stopped when the main process, which is determined according to the `Type`, exits.
+            </para></listitem>
+
+            <listitem><para>The <option>cgroup</option> exit type is meant for applications whose forking model is not
+            known ahead of time and which might not have a specific main process. The service will stay running as long
+            as at least one process in the cgroup is running. The exit status of the service is that of the last
+            process in the cgroup to exit.</para></listitem>
+          </itemizedlist>
+
+          <para>It is generally recommended to use <varname>ExitType=</varname><option>main</option> when a service has
+          a known forking model and a main process can reliably be determined. <varname>ExitType=</varname>
+          <option>cgroup</option> is well suited for transient or automatically generated services, such as graphical
+          applications inside of a desktop environment.</para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>RemainAfterExit=</varname></term>
 
index c9f320935dcc1eeb9fbc5bcc6f800e5d008c6005..b09c4e9fa2ee48fa59f3a36057934574b7f64967 100644 (file)
@@ -46,6 +46,7 @@
     <filename>initrd-fs.target</filename>,
     <filename>initrd-root-device.target</filename>,
     <filename>initrd-root-fs.target</filename>,
+    <filename>initrd-usr-fs.target</filename>,
     <filename>kbrequest.target</filename>,
     <filename>kexec.target</filename>,
     <filename>local-fs-pre.target</filename>,
           <term><filename>initrd-fs.target</filename></term>
           <listitem>
             <para><citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-            automatically adds dependencies of type
-            <varname>Before=</varname> to
-            <filename>sysroot-usr.mount</filename> and all mount points
-            found in <filename>/etc/fstab</filename> that have
-            <option>x-initrd.mount</option> and not have
-            <option>noauto</option> mount options set.</para>
+            automatically adds dependencies of type <varname>Before=</varname> to
+            <filename>sysroot-usr.mount</filename> and all mount points found in
+            <filename>/etc/fstab</filename> that have the <option>x-initrd.mount</option> mount option set
+            and do not have the <option>noauto</option> mount option set. It is also indirectly ordered after
+            <filename>sysroot.mount</filename>. Thus, once this target is reached the
+            <filename>/sysroot/</filename> hierarchy is fully set up, in preparation for the transition to
+            the host OS.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
           <term><filename>initrd-root-fs.target</filename></term>
           <listitem>
             <para><citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-            automatically adds dependencies of type
-            <varname>Before=</varname> to the
-            <filename>sysroot.mount</filename> unit, which is generated
-            from the kernel command line.
-            </para>
+            automatically adds dependencies of type <varname>Before=</varname> to the
+            <filename>sysroot.mount</filename> unit, which is generated from the kernel command line's
+            <varname>root=</varname> setting (or equivalent).</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><filename>initrd-usr-fs.target</filename></term>
+          <listitem>
+            <para><citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+            automatically adds dependencies of type <varname>Before=</varname> to the
+            <filename>sysusr-usr.mount</filename> unit, which is generated from the kernel command line's
+            <varname>usr=</varname> switch. Services may order themselves after this target unit in order to
+            run once the <filename>/sysusr/</filename> hierarchy becomes available, on systems that come up
+            initially without a root file system, but with an initialized <filename>/usr/</filename> and need
+            to access that before setting up the root file system to ultimately switch to. On systems where
+            <varname>usr=</varname> is not used this target is ordered after
+            <filename>sysroot.mount</filename> and thus mostly equivalent to
+            <filename>initrd-root-fs.target</filename>. In effect on any system once this target is reached
+            the file system backing <filename>/usr/</filename> is mounted, though possibly at two different
+            locations, either below the <filename>/sysusr/</filename> or the <filename>/sysroot/</filename>
+            hierarchies.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
index 42dcbac72ca3e19a4cb71ed9583158c18d0f6383..b7a5ec0362e2229a1ec09081da162f71fa6d9375 100644 (file)
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>ConditionFirmware=</varname></term>
+
+          <listitem><para>Check whether the system's firmware is of a certain type. Possible values are:
+          <literal>uefi</literal> (for systems with EFI),
+          <literal>device-tree</literal> (for systems with a device tree) and
+          <literal>device-tree-compatible(xyz)</literal> (for systems with a device tree that is compatible to <literal>xyz</literal>).</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term><varname>ConditionVirtualization=</varname></term>
 
           <literal>container</literal> to test against a generic type of virtualization solution, or one of
           <literal>qemu</literal>,
           <literal>kvm</literal>,
+          <literal>amazon</literal>,
           <literal>zvm</literal>,
           <literal>vmware</literal>,
           <literal>microsoft</literal>,
             <entry>Architecture</entry>
             <entry>A short string identifying the architecture of the local system. A string such as <constant>x86</constant>, <constant>x86-64</constant> or <constant>arm64</constant>. See the architectures defined for <varname>ConditionArchitecture=</varname> above for a full list.</entry>
           </row>
+          <xi:include href="standard-specifiers.xml" xpointer="A"/>
           <xi:include href="standard-specifiers.xml" xpointer="b"/>
           <xi:include href="standard-specifiers.xml" xpointer="B"/>
           <row>
@@ -1944,6 +1956,7 @@ Note that this setting is <emphasis>not</emphasis> influenced by the <varname>Us
             <entry>This is either <filename>/var/log</filename> (for the system manager) or the path <literal>$XDG_CONFIG_HOME</literal> resolves to with <filename index="false">/log</filename> appended (for user managers).</entry>
           </row>
           <xi:include href="standard-specifiers.xml" xpointer="m"/>
+          <xi:include href="standard-specifiers.xml" xpointer="M"/>
           <row>
             <entry><literal>%n</literal></entry>
             <entry>Full unit name</entry>
index e15c1b2eee5778d22170d8551e974dd14473f6bb..fd67c1f078e20b4f03fd4b30dd7d043455acadd2 100644 (file)
@@ -259,11 +259,13 @@ r     -        500-900
         </thead>
         <tbody>
           <xi:include href="standard-specifiers.xml" xpointer="a"/>
+          <xi:include href="standard-specifiers.xml" xpointer="A"/>
           <xi:include href="standard-specifiers.xml" xpointer="b"/>
           <xi:include href="standard-specifiers.xml" xpointer="B"/>
           <xi:include href="standard-specifiers.xml" xpointer="H"/>
           <xi:include href="standard-specifiers.xml" xpointer="l"/>
           <xi:include href="standard-specifiers.xml" xpointer="m"/>
+          <xi:include href="standard-specifiers.xml" xpointer="M"/>
           <xi:include href="standard-specifiers.xml" xpointer="o"/>
           <xi:include href="standard-specifiers.xml" xpointer="T"/>
           <xi:include href="standard-specifiers.xml" xpointer="v"/>
index 4adbf6bb0a611703c8cb5c2ac3246c7e22ab1be7..35b762ca3f7c7d3b6d2d79cc844f64e4275e9d41 100644 (file)
@@ -58,8 +58,8 @@ c+    /dev/char-device-to-[re]create           mode user group -           major
 b     /dev/block-device-to-create              mode user group -           major:minor
 b+    /dev/block-device-to-[re]create          mode user group -           major:minor
 C     /target/to/create                        -    -    -     -           /source/to/copy
-x     /path-or-glob/to/ignore                  -    -    -     -           -
-X     /path-or-glob/to/ignore/recursively      -    -    -     -           -
+x     /path-or-glob/to/ignore/recursively      -    -    -     -           -
+X     /path-or-glob/to/ignore                  -    -    -     -           -
 r     /empty/dir/to/remove                     -    -    -     -           -
 R     /dir/to/remove/recursively               -    -    -     -           -
 z     /path-or-glob/to/adjust/mode             mode user group -           -
@@ -635,6 +635,7 @@ w- /proc/sys/vm/swappiness - - - - 10</programlisting></para>
           </thead>
           <tbody>
             <xi:include href="standard-specifiers.xml" xpointer="a"/>
+            <xi:include href="standard-specifiers.xml" xpointer="A"/>
             <xi:include href="standard-specifiers.xml" xpointer="b"/>
             <xi:include href="standard-specifiers.xml" xpointer="B"/>
             <row>
@@ -665,6 +666,7 @@ w- /proc/sys/vm/swappiness - - - - 10</programlisting></para>
               <entry>In <option>--user</option> mode, this is the same as <varname>$XDG_CONFIG_HOME</varname> with <filename index="false">/log</filename> appended, and <filename>/var/log</filename> otherwise.</entry>
             </row>
             <xi:include href="standard-specifiers.xml" xpointer="m"/>
+            <xi:include href="standard-specifiers.xml" xpointer="M"/>
             <xi:include href="standard-specifiers.xml" xpointer="o"/>
             <row>
               <entry><literal>%S</literal></entry>
index df0a70c9fb0d6c1c529b63bcacbc8088981089e5..0f51a1aaefe98b123a93f5a7712d4c5fba97a8b1 100644 (file)
@@ -63,8 +63,8 @@
         <term><varname>exec_delay=</varname></term>
 
         <listitem>
-          <para>An integer. Delay the execution of <varname>RUN</varname>
-          instructions by the given number of seconds. This option
+          <para>An integer. Delay the execution of each <varname>RUN{<replaceable>program</replaceable>}</varname>
+          parameter by the given number of seconds. This option
           might be useful when debugging system crashes during
           coldplug caused by loading non-working kernel
           modules.</para>
index 6a474afdac33a284350f96f48bb7526e4bb49d9b..ee94d5c354d347c32772d089309111b61e817277 100644 (file)
@@ -38,8 +38,8 @@ relative_source_path = run_command('realpath',
                                    project_source_root).stdout().strip()
 conf.set_quoted('RELATIVE_SOURCE_PATH', relative_source_path)
 
-conf.set('BUILD_MODE', 'BUILD_MODE_' + get_option('mode').to_upper(),
-         description : 'tailor build to development or release builds')
+conf.set10('BUILD_MODE_DEVELOPER', get_option('mode') == 'developer',
+           description : 'tailor build to development or release builds')
 
 want_ossfuzz = get_option('oss-fuzz')
 want_libfuzzer = get_option('llvm-fuzz')
@@ -395,10 +395,6 @@ possible_cc_flags = [
         '-Wno-error=#warnings',  # clang
         '-Wno-string-plus-int',  # clang
 
-        # Disable -Wmaybe-uninitialized, since it's noisy on gcc 8 with
-        # optimizations enabled, producing essentially false positives.
-        '-Wno-maybe-uninitialized',
-
         '-ffast-math',
         '-fno-common',
         '-fdiagnostics-show-option',
@@ -409,6 +405,15 @@ possible_cc_flags = [
         '--param=ssp-buffer-size=4',
 ]
 
+# Disable -Wmaybe-unitialized when compiling with -Os/-O1/-O3/etc. There are
+# too many false positives with gcc >= 8. Effectively, we only test with -O0
+# and -O2; this should be enough to catch most important cases without too much
+# busywork. See https://github.com/systemd/systemd/pull/19226.
+if cc.get_id() == 'gcc' and (not '02'.contains(get_option('optimization')) or
+                             cc.version().version_compare('<10'))
+        possible_cc_flags += '-Wno-maybe-uninitialized'
+endif
+
 # --as-needed and --no-undefined are provided by meson by default,
 # run mesonconf to see what is enabled
 possible_link_flags = [
@@ -475,11 +480,14 @@ conf.set('SIZEOF_RLIM_T', cc.sizeof('rlim_t', prefix : '#include <sys/resource.h
 
 decl_headers = '''
 #include <uchar.h>
+#include <sys/mount.h>
 #include <sys/stat.h>
+#include <linux/fs.h>
 '''
 
 foreach decl : ['char16_t',
                 'char32_t',
+                'struct mount_attr',
                 'struct statx',
                ]
 
@@ -547,9 +555,13 @@ foreach ident : [
                                  #include <signal.h>
                                  #include <sys/wait.h>'''],
         ['mallinfo',          '''#include <malloc.h>'''],
+        ['mallinfo2',         '''#include <malloc.h>'''],
         ['execveat',          '''#include <unistd.h>'''],
         ['close_range',       '''#include <unistd.h>'''],
         ['epoll_pwait2',      '''#include <sys/epoll.h>'''],
+        ['mount_setattr',     '''#include <sys/mount.h>'''],
+        ['move_mount',        '''#include <sys/mount.h>'''],
+        ['open_tree',         '''#include <sys/mount.h>'''],
 ]
 
         have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE')
@@ -710,7 +722,7 @@ if time_epoch == -1
         if time_epoch == '' and git.found() and run_command('test', '-e', '.git').returncode() == 0
                 # If we're in a git repository, use the creation time of the latest git tag.
                 latest_tag = run_command('git', 'describe', '--abbrev=0', '--tags').stdout().strip()
-                time_epoch = run_command('git', 'log', '-1', '--format=%at', latest_tag).stdout()
+                time_epoch = run_command('git', 'log', '--no-show-signature', '-1', '--format=%at', latest_tag).stdout()
         endif
         if time_epoch == ''
                 NEWS = files('NEWS')
@@ -797,7 +809,7 @@ if not meson.is_cross_build()
                 id = id_result.stdout().to_int()
                 if id != 65534
                         warning('\n' +
-                                'The local group with the configured group name "@0@" of the nobody group does not have UID 65534 (it has @1@).\n'.format(nobody_group, id) +
+                                'The local group with the configured group name "@0@" of the nobody group does not have GID 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
@@ -932,6 +944,25 @@ if not libcap.found()
         libcap = cc.find_library('cap')
 endif
 
+want_bpf_framework = get_option('bpf-framework')
+bpf_framework_required = want_bpf_framework == 'true'
+
+libbpf = dependency('libbpf', required : bpf_framework_required, version : '>= 0.2')
+conf.set10('HAVE_LIBBPF', libbpf.found())
+
+if want_bpf_framework == 'false'
+        conf.set10('BPF_FRAMEWORK', 0)
+else
+        clang = find_program('clang', required : bpf_framework_required)
+        llvm_strip = find_program('llvm-strip', required : bpf_framework_required)
+        bpftool = find_program('bpftool', required : bpf_framework_required)
+        bpf_arches = ['x86_64']
+        deps_found = libbpf.found() and clang.found() and llvm_strip.found() and bpftool.found()
+        # Can build BPF program from source code in restricted C
+        conf.set10('BPF_FRAMEWORK',
+                bpf_arches.contains(host_machine.cpu_family()) and deps_found)
+endif
+
 libmount = dependency('mount',
                       version : fuzzer_build ? '>= 0' : '>= 2.30')
 
@@ -1112,7 +1143,7 @@ else
         libcurl = []
 endif
 conf.set10('HAVE_LIBCURL', have)
-conf.set10('CURL_NO_OLDIES', get_option('mode') == 'developer')
+conf.set10('CURL_NO_OLDIES', conf.get('BUILD_MODE_DEVELOPER') == 1)
 
 want_libidn = get_option('libidn')
 want_libidn2 = get_option('libidn2')
@@ -1227,7 +1258,7 @@ conf.set10('HAVE_LIBFIDO2', have)
 want_tpm2 = get_option('tpm2')
 if want_tpm2 != 'false' and not skip_deps
         tpm2 = dependency('tss2-esys tss2-rc tss2-mu',
-                              required : want_tpm2 == 'true')
+                          required : want_tpm2 == 'true')
         have = tpm2.found()
 else
         have = false
@@ -1580,6 +1611,9 @@ if get_option('efi')
         elif efi_arch == 'aarch64'
                 EFI_MACHINE_TYPE_NAME = 'aa64'
                 gnu_efi_arch = 'aarch64'
+        elif efi_arch == 'riscv64'
+                EFI_MACHINE_TYPE_NAME = 'riscv64'
+                gnu_efi_arch = 'riscv64'
         else
                 EFI_MACHINE_TYPE_NAME = ''
                 gnu_efi_arch = ''
@@ -1596,6 +1630,7 @@ conf.set10('ENABLE_EFI', have)
 
 ############################################################
 
+build_bpf_skel_py = find_program('tools/build-bpf-skel.py')
 generate_gperfs = find_program('tools/generate-gperfs.py')
 make_autosuspend_rules_py = find_program('tools/make-autosuspend-rules.py')
 make_directive_index_py = find_program('tools/make-directive-index.py')
@@ -1688,6 +1723,7 @@ install_libsystemd_static = static_library(
                         libxz,
                         libzstd,
                         liblz4,
+                        libbpf,
                         libcap,
                         libblkid,
                         libmount,
@@ -2324,7 +2360,7 @@ if conf.get('ENABLE_HOMED') == 1
 endif
 
 foreach alias : (['halt', 'poweroff', 'reboot', 'shutdown'] +
-                (conf.get('HAVE_SYSV_COMPAT') == 1 ? ['runlevel', 'telinit'] : []))
+                 (conf.get('HAVE_SYSV_COMPAT') == 1 ? ['runlevel', 'telinit'] : []))
         meson.add_install_script(meson_make_symlink,
                                  join_paths(rootbindir, 'systemctl'),
                                  join_paths(rootsbindir, alias))
@@ -2745,14 +2781,14 @@ if conf.get('ENABLE_OOMD') == 1
                    install_dir : rootlibexecdir)
 
         public_programs += executable(
-                   'oomctl',
-                   oomctl_sources,
-                   include_directories : includes,
-                   link_with : [libshared],
-                   dependencies : [],
-                   install_rpath : rootlibexecdir,
-                   install : true,
-                   install_dir : rootbindir)
+                'oomctl',
+                oomctl_sources,
+                include_directories : includes,
+                link_with : [libshared],
+                dependencies : [],
+                install_rpath : rootlibexecdir,
+                install : true,
+                install_dir : rootbindir)
 endif
 
 if conf.get('ENABLE_BINFMT') == 1
@@ -3139,7 +3175,7 @@ if conf.get('ENABLE_TMPFILES') == 1
 endif
 
 if conf.get('ENABLE_HWDB') == 1
-        public_programs += executable(
+        systemd_hwdb = executable(
                 'systemd-hwdb',
                 'src/hwdb/hwdb.c',
                 include_directories : includes,
@@ -3147,6 +3183,14 @@ if conf.get('ENABLE_HWDB') == 1
                 install_rpath : udev_rpath,
                 install : true,
                 install_dir : rootbindir)
+        public_programs += systemd_hwdb
+
+        if want_tests != 'false'
+                test('hwdb-test',
+                     hwdb_test_sh,
+                     args : [systemd_hwdb.full_path()],
+                     timeout : 90)
+        endif
 endif
 
 if conf.get('ENABLE_QUOTACHECK') == 1
@@ -3308,11 +3352,20 @@ custom_target(
         'systemd-runtest.env',
         output : 'systemd-runtest.env',
         command : ['sh', '-c', '{ ' +
-                   'echo SYSTEMD_TEST_DATA=@0@; '.format(join_paths(project_source_root, 'test')) +
-                   'echo SYSTEMD_CATALOG_DIR=@0@; '.format(join_paths(project_build_root, 'catalog')) +
-                   '} >@OUTPUT@'],
+                               'echo SYSTEMD_TEST_DATA=@0@; '.format(join_paths(project_source_root, 'test')) +
+                               'echo SYSTEMD_CATALOG_DIR=@0@; '.format(join_paths(project_build_root, 'catalog')) +
+                               '} >@OUTPUT@'],
         build_by_default : true)
 
+test_cflags = ['-DTEST_CODE=1']
+# We intentionally do not do inline initializations with definitions for a
+# bunch of _cleanup_ variables in tests, to ensure valgrind is triggered if we
+# use the variable unexpectedly. This triggers a lot of maybe-uninitialized
+# false positives when the combination of -O2 and -flto is used. Suppress them.
+if '-O2' in get_option('c_args') and '-flto=auto' in get_option('c_args')
+        test_cflags += cc.first_supported_argument('-Wno-maybe-uninitialized')
+endif
+
 foreach tuple : tests
         sources = tuple[0]
         link_with = tuple.length() > 1 and tuple[1].length() > 0 ? tuple[1] : [libshared]
@@ -3321,6 +3374,7 @@ foreach tuple : tests
         condition = tuple.length() > 4 ? tuple[4] : ''
         type = tuple.length() > 5 ? tuple[5] : ''
         defs = tuple.length() > 6 ? tuple[6] : []
+        defs += test_cflags
         parallel = tuple.length() > 7 ? tuple[7] : true
         timeout = 30
 
@@ -3388,7 +3442,7 @@ exe = executable(
         'test-libudev-sym',
         test_libudev_sym_c,
         include_directories : libudev_includes,
-        c_args : '-Wno-deprecated-declarations',
+        c_args : ['-Wno-deprecated-declarations'] + test_cflags,
         link_with : [libudev],
         build_by_default : want_tests != 'false',
         install : install_tests,
@@ -3401,7 +3455,7 @@ exe = executable(
         'test-libudev-static-sym',
         test_libudev_sym_c,
         include_directories : libudev_includes,
-        c_args : '-Wno-deprecated-declarations',
+        c_args : ['-Wno-deprecated-declarations'] + test_cflags,
         link_with : [install_libudev_static],
         build_by_default : want_tests != 'false' and static_libudev_pic,
         install : install_tests and static_libudev_pic,
@@ -3442,7 +3496,7 @@ foreach tuple : fuzzers
                 include_directories : [incs, include_directories('src/fuzz')],
                 link_with : link_with,
                 dependencies : dependencies,
-                c_args : defs,
+                c_args : defs + test_cflags,
                 link_args: link_args,
                 install : false,
                 build_by_default : fuzz_tests or fuzzer_build)
@@ -3515,7 +3569,7 @@ check_directives_sh = find_program('tools/check-directives.sh')
 if want_tests != 'false'
         test('check-directives',
              check_directives_sh,
-             args : project_source_root)
+             args : [project_source_root, project_build_root])
 endif
 
 ############################################################
@@ -3629,7 +3683,7 @@ if dbus_docs.length() > 0
                            '@INPUT@'],
                 input : dbus_docs)
 
-        if conf.get('BUILD_MODE') == 'BUILD_MODE_DEVELOPER'
+        if conf.get('BUILD_MODE_DEVELOPER') == 1
                 test('dbus-docs-fresh',
                      update_dbus_docs_py,
                      args : ['--build-dir=@0@'.format(project_build_root),
@@ -3713,10 +3767,6 @@ alt_time_epoch = run_command('date', '-Is', '-u', '-d',
 status += [
         'time epoch:                        @0@ (@1@)'.format(time_epoch, alt_time_epoch)]
 
-status += [
-        'static libsystemd:                 @0@'.format(static_libsystemd),
-        'static libudev:                    @0@'.format(static_libudev)]
-
 # TODO:
 # CFLAGS:   ${OUR_CFLAGS} ${CFLAGS}
 # CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
@@ -3739,107 +3789,114 @@ found = []
 missing = []
 
 foreach tuple : [
-        ['libcryptsetup'],
-        ['PAM'],
-        ['pwquality'],
-        ['libfdisk'],
-        ['p11kit'],
-        ['libfido2'],
-        ['tpm2'],
+        # dependencies
+        ['ACL'],
         ['AUDIT'],
-        ['IMA'],
         ['AppArmor'],
-        ['SELinux'],
+        ['IMA'],
+        ['PAM'],
         ['SECCOMP'],
+        ['SELinux'],
         ['SMACK'],
-        ['zlib'],
-        ['xz'],
-        ['zstd'],
-        ['lz4'],
-        ['bzip2'],
-        ['ACL'],
+        ['blkid'],
+        ['elfutils'],
         ['gcrypt'],
-        ['qrencode'],
-        ['microhttpd'],
         ['gnutls'],
-        ['openssl'],
+        ['libbpf'],
+        ['libcryptsetup'],
         ['libcurl'],
-        ['idn'],
-        ['initrd'],
-        ['compat-mutable-uid-boundaries'],
-        ['nscd'],
-        ['libidn2'],
+        ['libfdisk'],
+        ['libfido2'],
         ['libidn'],
+        ['libidn2'],
         ['libiptc'],
-        ['elfutils'],
+        ['microhttpd'],
+        ['openssl'],
+        ['p11kit'],
+        ['pcre2'],
+        ['pwquality'],
+        ['qrencode'],
+        ['tpm2'],
+        ['xkbcommon'],
+
+        # compression libs
+        ['zstd'],
+        ['lz4'],
+        ['xz'],
+        ['zlib'],
+        ['bzip2'],
+
+        # components
+        ['backlight'],
         ['binfmt'],
-        ['repart'],
-        ['vconsole'],
-        ['quotacheck'],
-        ['tmpfiles'],
+        ['bpf-framework',         conf.get('BPF_FRAMEWORK') == 1],
+        ['coredump'],
         ['environment.d'],
-        ['sysusers'],
+        ['efi'],
+        ['gnu-efi',               have_gnu_efi],
         ['firstboot'],
-        ['randomseed'],
-        ['backlight'],
-        ['rfkill'],
-        ['xdg-autostart'],
+        ['hibernate'],
+        ['homed'],
+        ['hostnamed'],
+        ['hwdb'],
+        ['importd'],
+        ['initrd'],
+        ['kernel-install',        get_option('kernel-install')],
+        ['localed'],
         ['logind'],
         ['machined'],
+        ['networkd'],
+        ['nss-myhostname'],
+        ['nss-mymachines'],
+        ['nss-resolve'],
+        ['nss-systemd'],
+        ['oomd'],
         ['portabled'],
+        ['pstore'],
+        ['quotacheck'],
+        ['randomseed'],
+        ['repart'],
+        ['resolve'],
+        ['rfkill'],
         ['sysext'],
-        ['userdb'],
-        ['homed'],
-        ['importd'],
-        ['hostnamed'],
+        ['systemd-analyze',       conf.get('ENABLE_ANALYZE') == 1],
+        ['sysusers'],
         ['timedated'],
         ['timesyncd'],
-        ['localed'],
-        ['networkd'],
-        ['resolve'],
-        ['DNS-over-TLS(gnutls)',  conf.get('DNS_OVER_TLS_USE_GNUTLS') == 1],
-        ['DNS-over-TLS(openssl)', conf.get('DNS_OVER_TLS_USE_OPENSSL') == 1],
-        ['coredump'],
-        ['pstore'],
-        ['oomd'],
+        ['tmpfiles'],
+        ['userdb'],
+        ['vconsole'],
+        ['xdg-autostart'],
+
+        # optional features
+        ['idn'],
         ['polkit'],
-        ['legacy pkla',      install_polkit_pkla],
-        ['efi'],
-        ['gnu-efi',          have_gnu_efi],
+        ['nscd'],
+        ['legacy-pkla',           install_polkit_pkla],
         ['kmod'],
-        ['xkbcommon'],
-        ['pcre2'],
-        ['blkid'],
         ['dbus'],
         ['glib'],
-        ['nss-myhostname'],
-        ['nss-mymachines'],
-        ['nss-resolve'],
-        ['nss-systemd'],
-        ['hwdb'],
         ['tpm'],
-        ['man pages',        want_man],
-        ['html pages',       want_html],
-        ['man page indices', want_man and have_lxml],
+        ['man pages',             want_man],
+        ['html pages',            want_html],
+        ['man page indices',      want_man and have_lxml],
         ['SysV compat'],
+        ['compat-mutable-uid-boundaries'],
         ['utmp'],
         ['ldconfig'],
-        ['hibernate'],
-        ['adm group',        get_option('adm-group')],
-        ['wheel group',      get_option('wheel-group')],
+        ['adm group',             get_option('adm-group')],
+        ['wheel group',           get_option('wheel-group')],
         ['gshadow'],
         ['debug hashmap'],
         ['debug mmap cache'],
         ['debug siphash'],
-        ['valgrind',         conf.get('VALGRIND') == 1],
-        ['trace logging',    conf.get('LOG_TRACE') == 1],
-        ['install tests',    install_tests],
+        ['valgrind',              conf.get('VALGRIND') == 1],
+        ['trace logging',         conf.get('LOG_TRACE') == 1],
+        ['install tests',         install_tests],
         ['link-udev-shared',      get_option('link-udev-shared')],
         ['link-systemctl-shared', get_option('link-systemctl-shared')],
         ['link-networkd-shared',  get_option('link-networkd-shared')],
         ['link-timesyncd-shared', get_option('link-timesyncd-shared')],
-        ['kernel-install',        get_option('kernel-install')],
-        ['systemd-analyze',  conf.get('ENABLE_ANALYZE') == 1],
         ['fexecve'],
         ['standalone-binaries',   get_option('standalone-binaries')],
 ]
@@ -3858,6 +3915,26 @@ foreach tuple : [
         endif
 endforeach
 
+if static_libsystemd == 'false'
+        missing += 'static-libsystemd'
+else
+        found += 'static-libsystemd(@0@)'.format(static_libsystemd)
+endif
+
+if static_libudev == 'false'
+        missing += 'static-libudev'
+else
+        found += 'static-libudev(@0@)'.format(static_libudev)
+endif
+
+if conf.get('DNS_OVER_TLS_USE_GNUTLS') == 1
+        found += 'DNS-over-TLS(gnutls)'
+elif conf.get('DNS_OVER_TLS_USE_OPENSSL') == 1
+        found += 'DNS-over-TLS(openssl)'
+else
+        missing += 'DNS-over-TLS'
+endif
+
 status += [
         '',
         'enabled features: @0@'.format(', '.join(found)),
index d96d4e3f047c859832ea384d75f054d4d1feccc6..ad7174cf69eff19bb87bbd68ea3a8e2ce7079ab6 100644 (file)
@@ -269,7 +269,7 @@ option('dns-over-tls', type : 'combo', choices : ['auto', 'gnutls', 'openssl', '
        description : 'DNS-over-TLS support')
 option('dns-servers', type : 'string',
        description : 'space-separated list of default DNS servers',
-       value : '1.1.1.1 8.8.8.8 1.0.0.1 8.8.4.4 2606:4700:4700::1111 2001:4860:4860::8888 2606:4700:4700::1001 2001:4860:4860::8844')
+       value : '1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google 1.0.0.1#cloudflare-dns.com 8.8.4.4#dns.google 2606:4700:4700::1111#cloudflare-dns.com 2001:4860:4860::8888#dns.google 2606:4700:4700::1001#cloudflare-dns.com 2001:4860:4860::8844#dns.google')
 option('ntp-servers', type : 'string',
        description : 'space-separated list of default NTP servers',
        value : 'time1.google.com time2.google.com time3.google.com time4.google.com')
@@ -403,3 +403,6 @@ option('kernel-install', type: 'boolean', value: 'true',
        description : 'install kernel-install and associated files')
 option('analyze', type: 'boolean', value: 'true',
        description : 'install systemd-analyze')
+
+option('bpf-framework', type : 'combo', choices : ['auto', 'true', 'false'],
+    description: 'build BPF programs from source code in restricted C')
index a74fc196be5b3630536b8cf7b01f38c087ac5c95..ff339b440c29f1950878dd02dcbd3fc146241f36 100755 (executable)
@@ -14,6 +14,18 @@ if ! mountpoint -q "$SRCDIR"; then
         umask 022
 fi
 
+# On Fedora "ld" is (unfortunately — if you ask me) managed via
+# "alternatives". Since we'd like to support building images in environments
+# with only /usr/ around (e.g. mkosi's UsrOnly=1 option), we have the problem
+# that /usr/bin/ld is a symlink that points to a non-existing file in
+# /etc/alternative/ in this mode. Let's work around this for now by manually
+# redirect "ld" to "ld.bfd", i.e. circumventing the /usr/bin/ld symlink.
+if [ ! -x /usr/bin/ld -a -x /usr/bin/ld.bfd ] ; then
+        mkdir -p "$HOME"/bin
+        ln -s /usr/bin/ld.bfd "$HOME"/bin/ld
+        PATH="$HOME/bin:$PATH"
+fi
+
 # 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
index 3713b161ecfe9865ca03528279969ce1ff0bde84..a7177e99e3ee207adf8ed48459acb90fa0acbbe2 100644 (file)
--- a/po/ko.po
+++ b/po/ko.po
@@ -9,7 +9,7 @@ msgstr ""
 "Project-Id-Version: systemd\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2021-01-08 17:48+0100\n"
-"PO-Revision-Date: 2021-03-25 03:01+0000\n"
+"PO-Revision-Date: 2021-04-15 10:01+0000\n"
 "Last-Translator: simmon <simmon@nplob.com>\n"
 "Language-Team: Korean <https://translate.fedoraproject.org/projects/systemd/"
 "master/ko/>\n"
@@ -18,7 +18,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.5.1\n"
+"X-Generator: Weblate 4.5.3\n"
 "X-Poedit-SourceCharset: UTF-8\n"
 
 #: src/core/org.freedesktop.systemd1.policy.in:22
@@ -54,9 +54,7 @@ msgstr "시스템 및 서비스 관리자 환경 변수 설정 또는 설정 해
 msgid ""
 "Authentication is required to set or unset system and service manager "
 "environment variables."
-msgstr ""
-"시스템 및 서비스 관리자 환경 변수를 설정하거나 설정 해제하려면 인증이 필요합"
-"니다."
+msgstr "시스템 및 서비스 관리자 환경 변수를 설정하거나 설정 또는 해제하려면 인증이 필요합니다."
 
 #: src/core/org.freedesktop.systemd1.policy.in:64
 msgid "Reload the systemd state"
@@ -132,7 +130,7 @@ msgstr "정적 호스트 이름 설정"
 msgid ""
 "Authentication is required to set the statically configured local hostname, "
 "as well as the pretty hostname."
-msgstr "로컬호스트 이름을 모양새를 갖춘 호스트이름 처럼 정적으로 설정하려면 인증이 필요합니다."
+msgstr "로컬호스트 이름을 지정 호스트이름 처럼 정적으로 설정하려면 인증이 필요합니다."
 
 #: src/hostname/org.freedesktop.hostname1.policy:41
 msgid "Set machine information"
index edfa8bb107e5d5a3c5a75afd616f0eb56c3319e5..3304e32bb627b1b852b3f7a1027b2e79e1eaed9b 100644 (file)
@@ -49,10 +49,15 @@ SUBSYSTEM=="sound", GROUP="audio", \
 
 SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0664"
 
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*", GROUP="video"
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", GROUP="video"
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", GROUP="video"
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", GROUP="video"
+SUBSYSTEM=="firewire", TEST=="units", TEST=="model", \
+  IMPORT{builtin}="hwdb 'ieee1394:node:ven$attr{vendor}mo$attr{model}units$attr{units}'"
+
+SUBSYSTEM=="firewire", TEST=="units", TEST!="model", \
+  IMPORT{builtin}="hwdb 'ieee1394:node:ven$attr{vendor}units$attr{units}'"
+
+SUBSYSTEM=="firewire", TEST=="units", ENV{IEEE1394_UNIT_FUNCTION_MIDI}=="1", GROUP="audio"
+SUBSYSTEM=="firewire", TEST=="units", ENV{IEEE1394_UNIT_FUNCTION_AUDIO}=="1", GROUP="audio"
+SUBSYSTEM=="firewire", TEST=="units", ENV{IEEE1394_UNIT_FUNCTION_VIDEO}=="1", GROUP="video"
 
 KERNEL=="parport[0-9]*", GROUP="lp"
 SUBSYSTEM=="printer", KERNEL=="lp*", GROUP="lp"
@@ -86,6 +91,8 @@ KERNEL=="fuse", MODE="0666", OPTIONS+="static_node=fuse"
 # The static_node is required on s390x and ppc (they are using MODULE_ALIAS)
 KERNEL=="kvm", GROUP="kvm", MODE="@DEV_KVM_MODE@", OPTIONS+="static_node=kvm"
 
+KERNEL=="vfio", MODE="0666", OPTIONS+="static_node=vfio/vfio"
+
 KERNEL=="vsock", MODE="0666"
 KERNEL=="vhost-vsock", GROUP="kvm", MODE="@DEV_KVM_MODE@", OPTIONS+="static_node=vhost-vsock"
 
diff --git a/rules.d/81-net-dhcp.rules b/rules.d/81-net-dhcp.rules
new file mode 100644 (file)
index 0000000..2ef25ba
--- /dev/null
@@ -0,0 +1,14 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="net_dhcp_end"
+SUBSYSTEM!="net", GOTO="net_dhcp_end"
+
+# Network interfaces requiring DHCPOFFER messages to be broadcast
+# must set ID_NET_DHCP_BROADCAST to "1". This property will be
+# checked by the networkd DHCP4 client to set the DHCP option
+
+# s390 ccwgroup interfaces in layer3 mode need broadcast DHCPOFFER
+# using the link driver to detect this condition
+ENV{ID_NET_DRIVER}=="qeth_l3", ENV{ID_NET_DHCP_BROADCAST}="1"
+
+LABEL="net_dhcp_end"
index 42fa451c6bac73102697dfb71e90dfa4fa6fb87b..4bbba09fd544000080a5d23d45ceab9585a2086e 100644 (file)
@@ -26,6 +26,7 @@ rules = files('''
         75-probe_mtd.rules
         78-sound-card.rules
         80-net-setup-link.rules
+        81-net-dhcp.rules
 '''.split())
 
 if conf.get('HAVE_KMOD') == 1
index e3765c315cbf0785af137ae8981c3c0532ec7678..5c8d3975d77fd8bce2e67e8e6502a4ea1e3030ce 100644 (file)
@@ -38,9 +38,9 @@ _hostnamectl() {
 
     local -A VERBS=(
         [STANDALONE]='status'
-        [ICONS]='set-icon-name'
-        [NAME]='set-hostname set-deployment set-location'
-        [CHASSIS]='set-chassis'
+        [ICONS]='icon-name'
+        [NAME]='hostname deployment location'
+        [CHASSIS]='chassis'
     )
 
     for ((i=0; i < COMP_CWORD; i++)); do
index cd16e47721350060ac4a21617d6c5cd520c0e5d8..bc3a7889b3882e1b0fb880ae1721c49b286a40d9 100644 (file)
@@ -30,7 +30,7 @@ __get_machines() {
 }
 
 _machinectl() {
-    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
     local i verb comps
 
     local -A OPTS=(
index 9282ee873773cabcf429d031529b8408087d0a86..ab2a5f7015ef6f1786f94e565e7a851e0f585992 100644 (file)
@@ -30,7 +30,7 @@ __get_links() {
 
 _networkctl() {
     local i verb comps
-    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
     local -A OPTS=(
         [STANDALONE]='-a --all -h --help --version --no-pager --no-legend -s --stats -l --full'
         [ARG]='-n --lines'
index 92f81a60fc718261a1489546bf9381c9c7980ea2..eded49b50e7d769029c7c1e1eca62e3ab7c7c2d9 100644 (file)
@@ -46,7 +46,7 @@ __get_syscall_sets() {
 
 _systemd_analyze() {
     local i verb comps mode
-    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
 
     local -A OPTS=(
         [STANDALONE]='-h --help --version --system --user --global --order --require --no-pager
index 9413b6fa70ab00ca72a687eef46b214b13c93e82..737f33981bb5a30ff255be6c73c2caa39c473206 100644 (file)
@@ -25,7 +25,7 @@ __contains_word() {
 }
 
 _systemd_cat() {
-    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
     local i verb comps
 
     local -A OPTS=(
index 7caaf89ddb903a34f32f2a6b2dddfc990283767d..0b6a8fda0d28319715f1d9c2c06a9270e80b67f8 100644 (file)
@@ -37,7 +37,7 @@ __get_units_have_cgroup() {
 }
 
 _systemd_cgls() {
-    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
     local i verb comps
 
     local -A OPTS=(
index b186f1bd537ca37018ac113a5789309a98c3c2f7..2c59b6c9f69d36bce9a0d9554193338b18be1e05 100644 (file)
@@ -29,7 +29,7 @@ __get_machines() {
 }
 
 _systemd_cgtop() {
-    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
     local comps
 
     local -A OPTS=(
index baf86b081343d64822ce70dcbada1dc1863f0071..f97b6dd5b2eabbc0d22769c76c4faed5d288f34d 100644 (file)
@@ -24,7 +24,7 @@ __contains_word() {
 }
 
 _systemd-delta() {
-    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
     local comps
 
     local -A OPTS=(
index fb35efaadb9648faff181d340649cbbc00c66214..0c9da3a22e1ad0adfd4f8e3dc7ab35498373511b 100644 (file)
@@ -24,7 +24,7 @@ __contains_word() {
 }
 
 _systemd_detect_virt() {
-    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
     local i verb comps
 
     local -A OPTS=(
index 937556154a8593e42f815adacb05528aca861653..25110d13091948c1d92e50a6bbf22c515f8e3aad 100644 (file)
@@ -26,7 +26,7 @@ __contains_word () {
 
 _systemd_id128() {
     local i verb comps
-    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
     local -A OPTS=(
         [STANDALONE]='-h --help --version -p --pretty'
         [ARG]='-a --app-specific'
index ebd97a9de1b683205050814a8e54c53453ad2276..ed1296a87883cba8e3c47a0cf4c4415372011a45 100644 (file)
@@ -58,7 +58,7 @@ __get_rlimit() {
 }
 
 _systemd_nspawn() {
-    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
     local i verb comps
 
     local -A OPTS=(
index cae4ac1b3093f4e04c667f7705e296feb5bcf619..4330c3e05b32d81fc555019fb846abe7ff1a57f2 100644 (file)
@@ -30,7 +30,7 @@ __get_names() {
 
 _systemd_path() {
     local comps
-    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+    local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
     local -A OPTS=(
         [STANDALONE]='-h --help --version'
         [ARG]='--suffix'
index 76b9700f79fd5e8dd0dbc4d7cee1459810e52eae..c5db8b77bd8f3dbee88a07494fdd47a8360e2ff0 100644 (file)
@@ -78,7 +78,7 @@ _systemd_run() {
         -p|--property)
             local comps='CPUAccounting= MemoryAccounting= BlockIOAccounting= SendSIGHUP=
                          SendSIGKILL= MemoryLimit= CPUShares= BlockIOWeight= User= Group=
-                         DevicePolicy= KillMode= DeviceAllow= BlockIOReadBandwidth=
+                         DevicePolicy= KillMode= ExitType= DeviceAllow= BlockIOReadBandwidth=
                          BlockIOWriteBandwidth= BlockIODeviceWeight= Nice= Environment=
                          KillSignal= RestartKillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA=
                          LimitSTACK= LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC=
index d05c46bd43645e8338bdbe99e5047c2eb17eed2d..2a6bf4d125c4f0c9b4c70696498112e7c55b6e44 100644 (file)
@@ -1,8 +1,8 @@
 #compdef hostnamectl                    -*- shell-script -*-
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
-(( $+functions[_hostnamectl_set-hostname] )) ||
-_hostnamectl_set-hostname() {
+(( $+functions[_hostnamectl_hostname] )) ||
+_hostnamectl_hostname() {
     if (( CURRENT <= 3 )); then
         _message "new hostname"
     else
@@ -10,8 +10,8 @@ _hostnamectl_set-hostname() {
     fi
 }
 
-(( $+functions[_hostnamectl_set-icon-name] )) ||
-_hostnamectl_set-icon-name() {
+(( $+functions[_hostnamectl_icon-name] )) ||
+_hostnamectl_icon-name() {
     if (( CURRENT <= 3 )); then
         _message "new icon name"
     else
@@ -19,8 +19,8 @@ _hostnamectl_set-icon-name() {
     fi
 }
 
-(( $+functions[_hostnamectl_set-chassis] )) ||
-_hostnamectl_set-chassis() {
+(( $+functions[_hostnamectl_chassis] )) ||
+_hostnamectl_chassis() {
     if (( CURRENT <= 3 )); then
         _chassis=( desktop laptop convertible server tablet handset watch embedded vm container )
         _describe chassis _chassis
@@ -29,8 +29,8 @@ _hostnamectl_set-chassis() {
     fi
 }
 
-(( $+functions[_hostnamectl_set-deployment] )) ||
-_hostnamectl_set-deployment() {
+(( $+functions[_hostnamectl_deployment] )) ||
+_hostnamectl_deployment() {
     if (( CURRENT <= 3 )); then
         _message "new environment"
     else
@@ -38,8 +38,8 @@ _hostnamectl_set-deployment() {
     fi
 }
 
-(( $+functions[_hostnamectl_set-location] )) ||
-_hostnamectl_set-location() {
+(( $+functions[_hostnamectl_location] )) ||
+_hostnamectl_location() {
     if (( CURRENT <= 3 )); then
         _message "new location"
     else
@@ -52,11 +52,11 @@ _hostnamectl_commands() {
     local -a _hostnamectl_cmds
     _hostnamectl_cmds=(
         "status:Show current hostname settings"
-        "set-hostname:Set system hostname"
-        "set-icon-name:Set icon name for host"
-        "set-chassis:Set chassis type for host"
-        "set-deployment:Set deployment environment for host"
-        "set-location:Set location for host"
+        "hostname:Get/set system hostname"
+        "icon-name:Get/set icon name for host"
+        "chassis:Get/set chassis type for host"
+        "deployment:Get/set deployment environment for host"
+        "location:Get/set location for host"
     )
     if (( CURRENT == 1 )); then
         _describe -t commands 'hostnamectl commands' _hostnamectl_cmds || compadd "$@"
index 1c7ac82b65967731f6a845135ae2fa3c626de307..851ac8253b0342aef1c3d290985e59ac1e67f9ea 100644 (file)
@@ -39,7 +39,7 @@ _localectl_set-x11-keymap() {
         local -a _file _layout _model _variant _options
         local _xorg_lst
         _xorg_lst=${"$($commands[pkg-config] xkeyboard-config --variable=xkb_base)"}
-        _file=( ${(ps:\n\!:)"$(<$_xorg_lst/rules/xorg.lst)"} )
+        _file=( ${(ps:\n\!:)"$(<$_xorg_lst/rules/base.lst)"} )
         _layout=( ${${${(M)${(f)_file[2]}:#  *}#  }%% *} )
         _model=( ${${${(M)${(f)_file[1]}:#  *}#  }%% *} )
         _variant=( ${${${(M)${(f)_file[3]}:#  *}#  }%% *} )
index bd70c13ba38c4505005cb156dc1ecb7b2fdc009b..d7af226105e7ad86180ec4f4b179373e2923e7b2 100644 (file)
@@ -45,7 +45,7 @@ _arguments \
     {-p+,--property=}'[Set unit property]:NAME=VALUE:(( \
                 CPUAccounting= MemoryAccounting= BlockIOAccounting= SendSIGHUP= \
                 SendSIGKILL= MemoryLimit= CPUShares= BlockIOWeight= User= Group= \
-                DevicePolicy= KillMode= DeviceAllow= BlockIOReadBandwidth= \
+                DevicePolicy= KillMode= ExitType= DeviceAllow= BlockIOReadBandwidth= \
                 BlockIOWriteBandwidth= BlockIODeviceWeight= Nice= Environment= \
                 KillSignal= RestartKillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA= \
                 LimitSTACK= LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC= \
index f298b1d49100f9a925df0922b4e5a88307054467..8c61c3ca7fc2eb091bfd30e6215343bf3fa921b7 100644 (file)
@@ -151,7 +151,7 @@ static int exec_process(const char *name, char **argv, char **env, int start_fd,
 
                         envp[n_env++] = k;
                 } else {
-                        _cleanup_free_ char *p;
+                        _cleanup_free_ char *p = NULL;
                         const char *n;
 
                         p = strjoin(*s, "=");
@@ -421,7 +421,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_FDNAME: {
-                        _cleanup_strv_free_ char **names;
+                        _cleanup_strv_free_ char **names = NULL;
                         char **s;
 
                         names = strv_split(optarg, ":");
@@ -430,7 +430,7 @@ static int parse_argv(int argc, char *argv[]) {
 
                         STRV_FOREACH(s, names)
                                 if (!fdname_is_valid(*s)) {
-                                        _cleanup_free_ char *esc;
+                                        _cleanup_free_ char *esc = NULL;
 
                                         esc = cescape(*s);
                                         log_warning("File descriptor name \"%s\" is not valid.", esc);
index 1a38d878a36a0defc0cc2531905f56316a13f116..1ad373185263af47ac99f1861c9b03911fddd759 100644 (file)
@@ -15,7 +15,6 @@
 #include "analyze-condition.h"
 #include "analyze-security.h"
 #include "analyze-verify.h"
-#include "build.h"
 #include "bus-error.h"
 #include "bus-locator.h"
 #include "bus-map-properties.h"
@@ -53,6 +52,7 @@
 #include "unit-name.h"
 #include "util.h"
 #include "verbs.h"
+#include "version.h"
 
 #define SCALE_X (0.1 / 1000.0) /* pixels per us */
 #define SCALE_Y (20.0)
index 6b89f57e1b71a8ebc9b5a4d71b62a85a71f8e518..09bcefbe66d4e95be0b9e5ab98a8574157266f14 100644 (file)
 #include "main-func.h"
 #include "pretty-print.h"
 #include "strv.h"
+#include "terminal-util.h"
 
 static const char *arg_icon = NULL;
-static const char *arg_id = NULL;
-static const char *arg_keyname = NULL;
+static const char *arg_id = NULL;               /* identifier for 'ask-password' protocol */
+static const char *arg_key_name = NULL;         /* name in kernel keyring */
+static const char *arg_credential_name = NULL;  /* name in $CREDENTIALS_DIRECTORY directory */
 static char *arg_message = NULL;
 static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
 static bool arg_multiple = false;
@@ -32,21 +34,26 @@ static int help(void) {
         if (r < 0)
                 return log_oom();
 
-        printf("%s [OPTIONS...] MESSAGE\n\n"
-               "Query the user for a system passphrase, via the TTY or an UI agent.\n\n"
+        printf("%1$s [OPTIONS...] MESSAGE\n\n"
+               "%3$sQuery the user for a system passphrase, via the TTY or an UI agent.%4$s\n\n"
                "  -h --help           Show this help\n"
                "     --icon=NAME      Icon name\n"
                "     --id=ID          Query identifier (e.g. \"cryptsetup:/dev/sda5\")\n"
                "     --keyname=NAME   Kernel key name for caching passwords (e.g. \"cryptsetup\")\n"
+               "     --credential=NAME\n"
+               "                      Credential name for LoadCredential=/SetCredential=\n"
+               "                      credentials\n"
                "     --timeout=SEC    Timeout in seconds\n"
                "     --echo           Do not mask input (useful for usernames)\n"
                "     --no-tty         Ask question via agent even on TTY\n"
                "     --accept-cached  Accept cached passwords\n"
                "     --multiple       List multiple passwords if available\n"
                "     --no-output      Do not print password to standard output\n"
-               "\nSee the %s for details.\n",
+               "\nSee the %2$s for details.\n",
                program_invocation_short_name,
-               link);
+               link,
+               ansi_highlight(),
+               ansi_normal());
 
         return 0;
 }
@@ -64,6 +71,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_KEYNAME,
                 ARG_NO_OUTPUT,
                 ARG_VERSION,
+                ARG_CREDENTIAL,
         };
 
         static const struct option options[] = {
@@ -78,6 +86,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "id",            required_argument, NULL, ARG_ID            },
                 { "keyname",       required_argument, NULL, ARG_KEYNAME       },
                 { "no-output",     no_argument,       NULL, ARG_NO_OUTPUT     },
+                { "credential",    required_argument, NULL, ARG_CREDENTIAL    },
                 {}
         };
 
@@ -128,13 +137,17 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_KEYNAME:
-                        arg_keyname = optarg;
+                        arg_key_name = optarg;
                         break;
 
                 case ARG_NO_OUTPUT:
                         arg_no_output = true;
                         break;
 
+                case ARG_CREDENTIAL:
+                        arg_credential_name = optarg;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -170,7 +183,7 @@ static int run(int argc, char *argv[]) {
         else
                 timeout = 0;
 
-        r = ask_password_auto(arg_message, arg_icon, arg_id, arg_keyname, timeout, arg_flags, &l);
+        r = ask_password_auto(arg_message, arg_icon, arg_id, arg_key_name, arg_credential_name ?: "password", timeout, arg_flags, &l);
         if (r < 0)
                 return log_error_errno(r, "Failed to query password: %m");
 
index 86927be62e98cd61eb541446f86f8e5a435863cb..7c0970a60c24502a587784fd52ce05ce609934b7 100644 (file)
@@ -226,26 +226,20 @@ static int validate_device(sd_device *device) {
 }
 
 static int get_max_brightness(sd_device *device, unsigned *ret) {
-        const char *max_brightness_str;
-        unsigned max_brightness;
+        const char *s;
         int r;
 
         assert(device);
         assert(ret);
 
-        r = sd_device_get_sysattr_value(device, "max_brightness", &max_brightness_str);
+        r = sd_device_get_sysattr_value(device, "max_brightness", &s);
         if (r < 0)
                 return log_device_warning_errno(device, r, "Failed to read 'max_brightness' attribute: %m");
 
-        r = safe_atou(max_brightness_str, &max_brightness);
+        r = safe_atou(s, ret);
         if (r < 0)
-                return log_device_warning_errno(device, r, "Failed to parse 'max_brightness' \"%s\": %m", max_brightness_str);
-
-        if (max_brightness <= 0)
-                return log_device_warning_errno(device, SYNTHETIC_ERRNO(EINVAL), "Maximum brightness is 0, ignoring device.");
+                return log_device_warning_errno(device, r, "Failed to parse 'max_brightness' \"%s\": %m", s);
 
-        log_device_debug(device, "Maximum brightness is %u", max_brightness);
-        *ret = max_brightness;
         return 0;
 }
 
@@ -409,6 +403,13 @@ static int run(int argc, char *argv[]) {
         if (get_max_brightness(device, &max_brightness) < 0)
                 return 0;
 
+        if (max_brightness == 0) {
+                log_device_warning(device, "Maximum brightness is 0, ignoring device.");
+                return 0;
+        }
+
+        log_device_debug(device, "Maximum brightness is %u", max_brightness);
+
         escaped_ss = cescape(ss);
         if (!escaped_ss)
                 return log_oom();
index 3de0d36cc9ff8a98b9baaeb7d80f1cb14a69c0df..87276bf686b426e9b17394ebe0a122982b9907c5 100644 (file)
@@ -4,8 +4,3 @@
 #include "version.h"
 
 extern const char* const systemd_features;
-
-enum {
-        BUILD_MODE_DEVELOPER,
-        BUILD_MODE_RELEASE,
-};
index 8dd3f8cd95018b46a9cef8800e3835e665b908da..b790df6dbeb17d07e4ea311cffbfa796666659ea 100644 (file)
@@ -660,7 +660,7 @@ int cg_remove_xattr(const char *controller, const char *path, const char *name)
 
 int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) {
         _cleanup_fclose_ FILE *f = NULL;
-        const char *fs, *controller_str;
+        const char *fs, *controller_str = NULL;  /* avoid false maybe-uninitialized warning */
         int unified, r;
 
         assert(pid >= 0);
@@ -720,6 +720,7 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) {
                                 continue;
                         *e = 0;
 
+                        assert(controller_str);
                         r = string_contains_word(l, ",", controller_str);
                         if (r < 0)
                                 return r;
@@ -2162,6 +2163,8 @@ static const char *const cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = {
         [CGROUP_CONTROLLER_PIDS] = "pids",
         [CGROUP_CONTROLLER_BPF_FIREWALL] = "bpf-firewall",
         [CGROUP_CONTROLLER_BPF_DEVICES] = "bpf-devices",
+        [CGROUP_CONTROLLER_BPF_FOREIGN] = "bpf-foreign",
+        [CGROUP_CONTROLLER_BPF_SOCKET_BIND] = "bpf-socket-bind",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(cgroup_controller, CGroupController);
index f79e384147d11712e229d0c6c0fd56e123b04865..ce2f4c6589bddbd8998c3884fec05c9ce853a3e0 100644 (file)
@@ -30,6 +30,8 @@ typedef enum CGroupController {
         /* BPF-based pseudo-controllers, v2 only */
         CGROUP_CONTROLLER_BPF_FIREWALL,
         CGROUP_CONTROLLER_BPF_DEVICES,
+        CGROUP_CONTROLLER_BPF_FOREIGN,
+        CGROUP_CONTROLLER_BPF_SOCKET_BIND,
 
         _CGROUP_CONTROLLER_MAX,
         _CGROUP_CONTROLLER_INVALID = -EINVAL,
@@ -49,6 +51,8 @@ typedef enum CGroupMask {
         CGROUP_MASK_PIDS = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_PIDS),
         CGROUP_MASK_BPF_FIREWALL = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BPF_FIREWALL),
         CGROUP_MASK_BPF_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BPF_DEVICES),
+        CGROUP_MASK_BPF_FOREIGN = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BPF_FOREIGN),
+        CGROUP_MASK_BPF_SOCKET_BIND = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BPF_SOCKET_BIND),
 
         /* All real cgroup v1 controllers */
         CGROUP_MASK_V1 = CGROUP_MASK_CPU|CGROUP_MASK_CPUACCT|CGROUP_MASK_BLKIO|CGROUP_MASK_MEMORY|CGROUP_MASK_DEVICES|CGROUP_MASK_PIDS,
@@ -57,7 +61,7 @@ typedef enum CGroupMask {
         CGROUP_MASK_V2 = CGROUP_MASK_CPU|CGROUP_MASK_CPUSET|CGROUP_MASK_IO|CGROUP_MASK_MEMORY|CGROUP_MASK_PIDS,
 
         /* All cgroup v2 BPF pseudo-controllers */
-        CGROUP_MASK_BPF = CGROUP_MASK_BPF_FIREWALL|CGROUP_MASK_BPF_DEVICES,
+        CGROUP_MASK_BPF = CGROUP_MASK_BPF_FIREWALL|CGROUP_MASK_BPF_DEVICES|CGROUP_MASK_BPF_FOREIGN|CGROUP_MASK_BPF_SOCKET_BIND,
 
         _CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1
 } CGroupMask;
index d25777cc4b47a030b03014ab1b55aea20d323a43..af9ac842a1150250f4f046b1e2d28e3043cbdb48 100644 (file)
@@ -1072,7 +1072,7 @@ int copy_file_full(
 
         _cleanup_close_ int fdf = -1;
         struct stat st;
-        int fdt = -1, r;
+        int r, fdt = -1;  /* avoid false maybe-uninitialized warning */
 
         assert(from);
         assert(to);
diff --git a/src/basic/creds-util.c b/src/basic/creds-util.c
new file mode 100644 (file)
index 0000000..5807670
--- /dev/null
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "creds-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "path-util.h"
+
+bool credential_name_valid(const char *s) {
+        /* We want that credential names are both valid in filenames (since that's our primary way to pass
+         * them around) and as fdnames (which is how we might want to pass them around eventually) */
+        return filename_is_valid(s) && fdname_is_valid(s);
+}
+
+int get_credentials_dir(const char **ret) {
+        const char *e;
+
+        assert(ret);
+
+        e = secure_getenv("CREDENTIALS_DIRECTORY");
+        if (!e)
+                return -ENXIO;
+
+        if (!path_is_absolute(e) || !path_is_normalized(e))
+                return -EINVAL;
+
+        *ret = e;
+        return 0;
+}
+
+int read_credential(const char *name, void **ret, size_t *ret_size) {
+        _cleanup_free_ char *fn = NULL;
+        const char *d;
+        int r;
+
+        assert(ret);
+
+        if (!credential_name_valid(name))
+                return -EINVAL;
+
+        r = get_credentials_dir(&d);
+        if (r < 0)
+                return r;
+
+        fn = path_join(d, name);
+        if (!fn)
+                return -ENOMEM;
+
+        return read_full_file_full(
+                        AT_FDCWD, fn,
+                        UINT64_MAX, SIZE_MAX,
+                        READ_FULL_FILE_SECURE,
+                        NULL,
+                        (char**) ret, ret_size);
+}
diff --git a/src/basic/creds-util.h b/src/basic/creds-util.h
new file mode 100644 (file)
index 0000000..5e33ca3
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <sys/types.h>
+
+bool credential_name_valid(const char *s);
+
+int get_credentials_dir(const char **ret);
+
+int read_credential(const char *name, void **ret, size_t *ret_size);
index 158ab738e839c0a14a0b0705c5f5f5866d9398cb..ec5613ac583da10485e5736b2b243fbd7fde6365 100644 (file)
@@ -8,15 +8,12 @@
 #include "utf8.h"
 
 int allow_listed_char_for_devnode(char c, const char *white) {
-
-        if ((c >= '0' && c <= '9') ||
-            (c >= 'A' && c <= 'Z') ||
-            (c >= 'a' && c <= 'z') ||
-            strchr("#+-.:=@_", c) != NULL ||
-            (white != NULL && strchr(white, c) != NULL))
-                return 1;
-
-        return 0;
+        return
+                (c >= '0' && c <= '9') ||
+                (c >= 'A' && c <= 'Z') ||
+                (c >= 'a' && c <= 'z') ||
+                strchr("#+-.:=@_", c) ||
+                (white && strchr(white, c));
 }
 
 int encode_devnode_name(const char *str, char *str_enc, size_t len) {
@@ -31,7 +28,7 @@ int encode_devnode_name(const char *str, char *str_enc, size_t len) {
                 seqlen = utf8_encoded_valid_unichar(str + i, SIZE_MAX);
                 if (seqlen > 1) {
 
-                        if (len-j < (size_t)seqlen)
+                        if (len-j < (size_t) seqlen)
                                 return -EINVAL;
 
                         memcpy(&str_enc[j], &str[i], seqlen);
index 26d34bb94f8ab46a8a326f818c325aebaebaa316..7e1e9e60476570faca59eac0fffdc9ca7b4aa714 100644 (file)
@@ -63,7 +63,7 @@ int efi_get_variable(
         _cleanup_free_ char *p = NULL;
         _cleanup_free_ void *buf = NULL;
         struct stat st;
-        usec_t begin;
+        usec_t begin = 0; /* Unnecessary initialization to appease gcc */
         uint32_t a;
         ssize_t n;
 
@@ -350,7 +350,7 @@ int cache_efi_options_variable(void) {
          * (NB: For testing purposes, we still check the $SYSTEMD_EFI_OPTIONS env var before accessing this
          * cache, even when in SecureBoot mode.) */
         if (is_efi_secure_boot()) {
-                _cleanup_free_ char *k;
+                _cleanup_free_ char *k = NULL;
 
                 k = efi_variable_path(EFI_VENDOR_SYSTEMD, "SystemdOptions");
                 if (!k)
index c110a750a55dd49bd70b1f66c9968b4502a4a032..0e8c2878d61a17574142c0c9c3ee18fa98c47388 100644 (file)
@@ -515,10 +515,10 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
                 ALTERNATE_VALUE,
         } state = WORD;
 
-        const char *e, *word = format, *test_value;
+        const char *e, *word = format, *test_value = NULL; /* test_value is initialized to appease gcc */
         char *k;
         _cleanup_free_ char *r = NULL;
-        size_t i, len;
+        size_t i, len = 0; /* len is initialized to appease gcc */
         int nest = 0;
 
         assert(format);
@@ -581,13 +581,12 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
                                 word = e+1;
                                 state = WORD;
                         } else if (*e == ':') {
-                                if (!(flags & REPLACE_ENV_ALLOW_EXTENDED))
+                                if (flags & REPLACE_ENV_ALLOW_EXTENDED) {
+                                        len = e - word - 2;
+                                        state = TEST;
+                                } else
                                         /* Treat this as unsupported syntax, i.e. do no replacement */
                                         state = WORD;
-                                else {
-                                        len = e-word-2;
-                                        state = TEST;
-                                }
                         }
                         break;
 
index 5609820b882f528a0ab756f1e15a4756391e3ab2..3f2d0af56d9524bcda780741a034044f09d57931 100644 (file)
@@ -33,7 +33,7 @@ static inline int negative_errno(void) {
 
 static inline const char *strerror_safe(int error) {
         /* 'safe' here does NOT mean thread safety. */
-        return strerror(abs(error));
+        return strerror(abs(error)); /* lgtm [cpp/potentially-dangerous-function] */
 }
 
 static inline int errno_or_else(int fallback) {
index c8094b6e45ecf6269dce7a290e3fc4ed8adf54c1..4bb655738454f7dcfd785529748dcf16ae09b5a1 100644 (file)
@@ -43,6 +43,22 @@ char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR
         return buffer;
 }
 
+int ether_addr_to_string_alloc(const struct ether_addr *addr, char **ret) {
+        char *buf;
+
+        assert(addr);
+        assert(ret);
+
+        buf = new(char, ETHER_ADDR_TO_STRING_MAX);
+        if (!buf)
+                return -ENOMEM;
+
+        ether_addr_to_string(addr, buf);
+
+        *ret = buf;
+        return 0;
+}
+
 int ether_addr_compare(const struct ether_addr *a, const struct ether_addr *b) {
         return memcmp(a, b, ETH_ALEN);
 }
index 942ce55621e16fe56140c42965c252e4051064bf..712c9277964829a05d22603a031c2b9e4e962a55 100644 (file)
@@ -35,6 +35,7 @@ char* hw_addr_to_string(const hw_addr_data *addr, char buffer[HW_ADDR_TO_STRING_
 
 #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]);
+int ether_addr_to_string_alloc(const struct ether_addr *addr, char **ret);
 
 int ether_addr_compare(const struct ether_addr *a, const struct ether_addr *b);
 static inline bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
index 024eb29bb9f944f94a6f1c6a06e28c53b0f0b662..93d8547b32e8c11237dc69d09e1e7bb50a738906 100644 (file)
@@ -57,7 +57,7 @@ int fdopen_unlocked(int fd, const char *options, FILE **ret) {
 }
 
 int take_fdopen_unlocked(int *fd, const char *options, FILE **ret) {
-        int     r;
+        int r;
 
         assert(fd);
 
@@ -121,7 +121,7 @@ int write_string_stream_ts(
                 const struct timespec *ts) {
 
         bool needs_nl;
-        int r, fd;
+        int r, fd = -1;
 
         assert(f);
         assert(line);
@@ -140,8 +140,8 @@ int write_string_stream_ts(
         needs_nl = !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n");
 
         if (needs_nl && (flags & WRITE_STRING_FILE_DISABLE_BUFFER)) {
-                /* If STDIO buffering was disabled, then let's append the newline character to the string itself, so
-                 * that the write goes out in one go, instead of two */
+                /* If STDIO buffering was disabled, then let's append the newline character to the string
+                 * itself, so that the write goes out in one go, instead of two */
 
                 line = strjoina(line, "\n");
                 needs_nl = false;
@@ -164,6 +164,7 @@ int write_string_stream_ts(
         if (ts) {
                 const struct timespec twice[2] = {*ts, *ts};
 
+                assert(fd >= 0);
                 if (futimens(fd, twice) < 0)
                         return -errno;
         }
@@ -285,7 +286,7 @@ fail:
         /* OK, the operation failed, but let's see if the right
          * contents in place already. If so, eat up the error. */
 
-        q = verify_file(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+        q = verify_file(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) || (flags & WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE));
         if (q <= 0)
                 return r;
 
@@ -931,12 +932,19 @@ int xfopenat(int dir_fd, const char *path, const char *mode, int flags, FILE **r
         return 0;
 }
 
-static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
+static int search_and_fopen_internal(
+                const char *path,
+                const char *mode,
+                const char *root,
+                char **search,
+                FILE **ret,
+                char **ret_path) {
+
         char **i;
 
         assert(path);
         assert(mode);
-        assert(_f);
+        assert(ret);
 
         if (!path_strv_resolve_uniq(search, root))
                 return -ENOMEM;
@@ -951,7 +959,10 @@ static int search_and_fopen_internal(const char *path, const char *mode, const c
 
                 f = fopen(p, mode);
                 if (f) {
-                        *_f = f;
+                        if (ret_path)
+                                *ret_path = path_simplify(TAKE_PTR(p), true);
+
+                        *ret = f;
                         return 0;
                 }
 
@@ -962,52 +973,84 @@ static int search_and_fopen_internal(const char *path, const char *mode, const c
         return -ENOENT;
 }
 
-int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
+int search_and_fopen(
+                const char *filename,
+                const char *mode,
+                const char *root,
+                const char **search,
+                FILE **ret,
+                char **ret_path) {
+
         _cleanup_strv_free_ char **copy = NULL;
 
-        assert(path);
+        assert(filename);
         assert(mode);
-        assert(_f);
+        assert(ret);
 
-        if (path_is_absolute(path)) {
-                FILE *f;
+        if (path_is_absolute(filename)) {
+                _cleanup_fclose_ FILE *f = NULL;
 
-                f = fopen(path, mode);
-                if (f) {
-                        *_f = f;
-                        return 0;
+                f = fopen(filename, mode);
+                if (!f)
+                        return -errno;
+
+                if (ret_path) {
+                        char *p;
+
+                        p = strdup(filename);
+                        if (!p)
+                                return -ENOMEM;
+
+                        *ret_path = path_simplify(p, true);
                 }
 
-                return -errno;
+                *ret = TAKE_PTR(f);
+                return 0;
         }
 
         copy = strv_copy((char**) search);
         if (!copy)
                 return -ENOMEM;
 
-        return search_and_fopen_internal(path, mode, root, copy, _f);
+        return search_and_fopen_internal(filename, mode, root, copy, ret, ret_path);
 }
 
-int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
+int search_and_fopen_nulstr(
+                const char *filename,
+                const char *mode,
+                const char *root,
+                const char *search,
+                FILE **ret,
+                char **ret_path) {
+
         _cleanup_strv_free_ char **s = NULL;
 
-        if (path_is_absolute(path)) {
-                FILE *f;
+        if (path_is_absolute(filename)) {
+                _cleanup_fclose_ FILE *f = NULL;
 
-                f = fopen(path, mode);
-                if (f) {
-                        *_f = f;
-                        return 0;
+                f = fopen(filename, mode);
+                if (!f)
+                        return -errno;
+
+                if (ret_path) {
+                        char *p;
+
+                        p = strdup(filename);
+                        if (!p)
+                                return -ENOMEM;
+
+                        *ret_path = path_simplify(p, true);
                 }
 
-                return -errno;
+                *ret = TAKE_PTR(f);
+                return 0;
         }
 
         s = strv_split_nulstr(search);
         if (!s)
                 return -ENOMEM;
 
-        return search_and_fopen_internal(path, mode, root, s, _f);
+        return search_and_fopen_internal(filename, mode, root, s, ret, ret_path);
 }
 
 int chase_symlinks_and_fopen_unlocked(
@@ -1021,7 +1064,6 @@ int chase_symlinks_and_fopen_unlocked(
         _cleanup_close_ int fd = -1;
         _cleanup_free_ char *final_path = NULL;
         int mode_flags, r;
-        FILE *f;
 
         assert(path);
         assert(open_flags);
@@ -1035,12 +1077,10 @@ int chase_symlinks_and_fopen_unlocked(
         if (fd < 0)
                 return fd;
 
-        r = fdopen_unlocked(fd, open_flags, &f);
+        r = take_fdopen_unlocked(&fd, open_flags, ret_file);
         if (r < 0)
                 return r;
-        TAKE_FD(fd);
 
-        *ret_file = f;
         if (ret_path)
                 *ret_path = TAKE_PTR(final_path);
         return 0;
index 2a6eef3790d7212bae657679311eb1304453b203..c28b17fef52691c79fe54f10f545ee3225882694 100644 (file)
 #define LONG_LINE_MAX (1U*1024U*1024U)
 
 typedef enum {
-        WRITE_STRING_FILE_CREATE            = 1 << 0,
-        WRITE_STRING_FILE_TRUNCATE          = 1 << 1,
-        WRITE_STRING_FILE_ATOMIC            = 1 << 2,
-        WRITE_STRING_FILE_AVOID_NEWLINE     = 1 << 3,
-        WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1 << 4,
-        WRITE_STRING_FILE_SYNC              = 1 << 5,
-        WRITE_STRING_FILE_DISABLE_BUFFER    = 1 << 6,
-        WRITE_STRING_FILE_NOFOLLOW          = 1 << 7,
-        WRITE_STRING_FILE_MKDIR_0755        = 1 << 8,
-        WRITE_STRING_FILE_MODE_0600         = 1 << 9,
+        WRITE_STRING_FILE_CREATE                = 1 << 0,
+        WRITE_STRING_FILE_TRUNCATE              = 1 << 1,
+        WRITE_STRING_FILE_ATOMIC                = 1 << 2,
+        WRITE_STRING_FILE_AVOID_NEWLINE         = 1 << 3,
+        WRITE_STRING_FILE_VERIFY_ON_FAILURE     = 1 << 4,
+        WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE = 1 << 5,
+        WRITE_STRING_FILE_SYNC                  = 1 << 6,
+        WRITE_STRING_FILE_DISABLE_BUFFER        = 1 << 7,
+        WRITE_STRING_FILE_NOFOLLOW              = 1 << 8,
+        WRITE_STRING_FILE_MKDIR_0755            = 1 << 9,
+        WRITE_STRING_FILE_MODE_0600             = 1 << 10,
 
         /* 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()
@@ -84,8 +85,8 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin
 DIR *xopendirat(int dirfd, const char *name, int flags);
 int xfopenat(int dir_fd, const char *path, const char *mode, int flags, FILE **ret);
 
-int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
-int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);
+int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **ret, char **ret_path);
+int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **ret, char **ret_path);
 
 int chase_symlinks_and_fopen_unlocked(
                 const char *path,
index b2a4e8036f8d3653a7e69e61e769f5bfc36f5f35..46d6f7780e18941b08487dfdd252d580afcb2e47 100644 (file)
@@ -24,6 +24,7 @@
 #include "path-util.h"
 #include "process-util.h"
 #include "random-util.h"
+#include "ratelimit.h"
 #include "stat-util.h"
 #include "stdio-util.h"
 #include "string-util.h"
@@ -1715,3 +1716,23 @@ do_rename:
 
         return 1;
 }
+
+int posix_fallocate_loop(int fd, uint64_t offset, uint64_t size) {
+        RateLimit rl;
+        int r;
+
+        r = posix_fallocate(fd, offset, size); /* returns positive errnos on error */
+        if (r != EINTR)
+                return -r; /* Let's return negative errnos, like common in our codebase */
+
+        /* On EINTR try a couple of times more, but protect against busy looping
+         * (not more than 16 times per 10s) */
+        rl = (RateLimit) { 10 * USEC_PER_SEC, 16 };
+        while (ratelimit_below(&rl)) {
+                r = posix_fallocate(fd, offset, size);
+                if (r != EINTR)
+                        return -r;
+        }
+
+        return -EINTR;
+}
index 45115fd3db18581fc2dbb6863ab7b7f452b91da2..027037f7a724ac22d482b5595a1fee40cff2bebc 100644 (file)
@@ -146,3 +146,5 @@ int conservative_renameat(int olddirfd, const char *oldpath, int newdirfd, const
 static inline int conservative_rename(const char *oldpath, const char *newpath) {
         return conservative_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath);
 }
+
+int posix_fallocate_loop(int fd, uint64_t offset, uint64_t size);
index bf0d2106f8d54218e6f000e675e1661760afc455..cdc308aca3349a221d9e683cea0969a256f2ec1b 100644 (file)
@@ -20,6 +20,7 @@ void initialize_libgcrypt(bool secmem) {
 
 int string_hashsum(const char *s, size_t len, int md_algorithm, char **out) {
         _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
+        gcry_error_t err;
         size_t hash_size;
         void *hash;
         char *enc;
@@ -29,8 +30,8 @@ int string_hashsum(const char *s, size_t len, int md_algorithm, char **out) {
         hash_size = gcry_md_get_algo_dlen(md_algorithm);
         assert(hash_size > 0);
 
-        gcry_md_open(&md, md_algorithm, 0);
-        if (!md)
+        err = gcry_md_open(&md, md_algorithm, 0);
+        if (gcry_err_code(err) != GPG_ERR_NO_ERROR || !md)
                 return -EIO;
 
         gcry_md_write(md, s, len);
index 0a5c5c4cd7673e0ef95581a31dd1b1b5df7baf6c..f747e0d0659681538e51a43430eac884a178f70d 100755 (executable)
@@ -1,7 +1,8 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
+set -o pipefail
 
-$1 -E -dM -include sys/socket.h -include "$2" -include "$3" - </dev/null | \
-    grep -Ev 'AF_UNSPEC|AF_MAX' | \
-    awk '/^#define[ \t]+AF_[^ \t]+[ \t]+[AP]F_[^ \t]/ { print $2; }'
+${1:?} -E -dM -include sys/socket.h -include "${2:?}" -include "${3:?}" - </dev/null | \
+       grep -Ev 'AF_UNSPEC|AF_MAX' | \
+       awk '/^#define[ \t]+AF_[^ \t]+[ \t]+[AP]F_[^ \t]/ { print $2; }'
index 9a2661b4d8fbdae83398c60a156506b8525eb62d..8a8c276d5fa83b9bb60bf49a478ab7d1f5ade11c 100755 (executable)
@@ -1,7 +1,8 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
+set -o pipefail
 
-$1 -dM -include linux/if_arp.h -include "$2" - </dev/null | \
-    awk '/^#define[ \t]+ARPHRD_[^ \t]+[ \t]+[^ \t]/ { print $2; }' | \
-    sed -e 's/ARPHRD_//'
+${1:?} -dM -include linux/if_arp.h -include "${2:?}" - </dev/null | \
+       awk '/^#define[ \t]+ARPHRD_[^ \t]+[ \t]+[^ \t]/ { print $2; }' | \
+       sed -e 's/ARPHRD_//'
index 89d5bb03d9d96d153c1988d9bac09c5e329e19dc..eb1357efa212ea3b3fb5db9100572e0a70345cc6 100755 (executable)
@@ -1,7 +1,8 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
+set -o pipefail
 
-$1 -dM -include linux/capability.h -include "$2" -include "$3" - </dev/null | \
-    awk '/^#define[ \t]+CAP_[A-Z_]+[ \t]+/ { print $2; }' | \
-    grep -v CAP_LAST_CAP
+${1:?} -dM -include linux/capability.h -include "${2:?}" -include "${3:?}" - </dev/null | \
+       awk '/^#define[ \t]+CAP_[A-Z_]+[ \t]+/ { print $2; }' | \
+       grep -v CAP_LAST_CAP
index 4c13b3157daa52c27a8baa71d44b7eed50ac3bae..dceeba415c76b04ad6ffb24fd55a308e116d4fec 100755 (executable)
@@ -1,6 +1,7 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
+set -o pipefail
 
-$1 -dM -include errno.h - </dev/null | \
-    awk '/^#define[ \t]+E[^ _]+[ \t]+/ { print $2; }'
+${1:?} -dM -include errno.h - </dev/null | \
+       awk '/^#define[ \t]+E[^ _]+[ \t]+/ { print $2; }'
index 576ca083e011ef879f4d7b551c6c3a1a1e434354..c3fc6752cbae43369ebfdbfcb64274da817bd358 100644 (file)
@@ -28,3 +28,8 @@ static inline bool is_gateway_hostname(const char *hostname) {
         /* This tries to identify the valid syntaxes for the our synthetic "gateway" host. */
         return STRCASE_IN_SET(hostname, "_gateway", "_gateway.");
 }
+
+static inline bool is_outbound_hostname(const char *hostname) {
+        /* This tries to identify the valid syntaxes for the our synthetic "outbound" host. */
+        return STRCASE_IN_SET(hostname, "_outbound", "_outbound.");
+}
index f7a7252f1af4d5f9e0722b0c424d6299b8279e8f..9d7e51f8fd758e30913fe9cb5ce7d4a24c56e104 100644 (file)
@@ -51,7 +51,7 @@ bool in4_addr_is_link_local(const struct in_addr *a) {
 bool in6_addr_is_link_local(const struct in6_addr *a) {
         assert(a);
 
-        return IN6_IS_ADDR_LINKLOCAL(a);
+        return IN6_IS_ADDR_LINKLOCAL(a); /* lgtm [cpp/potentially-dangerous-function] */
 }
 
 int in_addr_is_link_local(int family, const union in_addr_union *u) {
@@ -116,7 +116,7 @@ int in_addr_is_localhost(int family, const union in_addr_union *u) {
                 return in4_addr_is_localhost(&u->in);
 
         if (family == AF_INET6)
-                return IN6_IS_ADDR_LOOPBACK(&u->in6);
+                return IN6_IS_ADDR_LOOPBACK(&u->in6); /* lgtm [cpp/potentially-dangerous-function] */
 
         return -EAFNOSUPPORT;
 }
@@ -803,6 +803,9 @@ int in_addr_prefix_from_string_auto_internal(
 }
 
 static void in_addr_data_hash_func(const struct in_addr_data *a, struct siphash *state) {
+        assert(a);
+        assert(state);
+
         siphash24_compress(&a->family, sizeof(a->family), state);
         siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state);
 }
@@ -810,6 +813,9 @@ static void in_addr_data_hash_func(const struct in_addr_data *a, struct siphash
 static int in_addr_data_compare_func(const struct in_addr_data *x, const struct in_addr_data *y) {
         int r;
 
+        assert(x);
+        assert(y);
+
         r = CMP(x->family, y->family);
         if (r != 0)
                 return r;
@@ -819,13 +825,46 @@ static int in_addr_data_compare_func(const struct in_addr_data *x, const struct
 
 DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func);
 
+static void in_addr_prefix_hash_func(const struct in_addr_prefix *a, struct siphash *state) {
+        assert(a);
+        assert(state);
+
+        siphash24_compress(&a->family, sizeof(a->family), state);
+        siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state);
+        siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state);
+}
+
+static int in_addr_prefix_compare_func(const struct in_addr_prefix *x, const struct in_addr_prefix *y) {
+        int r;
+
+        assert(x);
+        assert(y);
+
+        r = CMP(x->family, y->family);
+        if (r != 0)
+                return r;
+
+        r = CMP(x->prefixlen, y->prefixlen);
+        if (r != 0)
+                return r;
+
+        return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
+}
+
+DEFINE_HASH_OPS(in_addr_prefix_hash_ops, struct in_addr_prefix, in_addr_prefix_hash_func, in_addr_prefix_compare_func);
+DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(in_addr_prefix_hash_ops_free, struct in_addr_prefix, in_addr_prefix_hash_func, in_addr_prefix_compare_func, free);
+
 void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) {
         assert(addr);
+        assert(state);
 
         siphash24_compress(addr, sizeof(*addr), state);
 }
 
 int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) {
+        assert(a);
+        assert(b);
+
         return memcmp(a, b, sizeof(*a));
 }
 
index 519ee53b3a48126d3e2a2f3c24defeb768dc8775..d5caf662ab500a850f1e26bbcdc572a84d5ea80e 100644 (file)
@@ -20,6 +20,12 @@ struct in_addr_data {
         union in_addr_union address;
 };
 
+struct in_addr_prefix {
+        int family;
+        uint8_t prefixlen;
+        union in_addr_union address;
+};
+
 bool in4_addr_is_null(const struct in_addr *a);
 static inline bool in4_addr_is_set(const struct in_addr *a) {
         return !in4_addr_is_null(a);
@@ -111,4 +117,6 @@ void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state);
 int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b);
 
 extern const struct hash_ops in_addr_data_hash_ops;
+extern const struct hash_ops in_addr_prefix_hash_ops;
+extern const struct hash_ops in_addr_prefix_hash_ops_free;
 extern const struct hash_ops in6_addr_hash_ops;
index d98817f760955104a6b655a27d79de05d31b9051..ce54ca228bf8558e0e0b6a26ac296f0ad26d2cc4 100644 (file)
@@ -25,22 +25,25 @@ 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, size_t n) {
-        size_t j, r = 0;
+        size_t r = 0;
 
-        for (j = 0; j < n; j++)
+        for (size_t j = 0; j < n; j++)
                 r += i[j].iov_len;
 
         return r;
 }
 
-static inline size_t IOVEC_INCREMENT(struct iovec *i, size_t n, size_t k) {
-        size_t j;
+static inline bool IOVEC_INCREMENT(struct iovec *i, size_t n, size_t k) {
+        /* Returns true if there is nothing else to send (bytes written cover all of the iovec),
+         * false if there's still work to do. */
 
-        for (j = 0; j < n; j++) {
+        for (size_t j = 0; j < n; j++) {
                 size_t sub;
 
-                if (_unlikely_(k <= 0))
-                        break;
+                if (i[j].iov_len == 0)
+                        continue;
+                if (k == 0)
+                        return false;
 
                 sub = MIN(i[j].iov_len, k);
                 i[j].iov_len -= sub;
@@ -48,7 +51,9 @@ static inline size_t IOVEC_INCREMENT(struct iovec *i, size_t n, size_t k) {
                 k -= sub;
         }
 
-        return k;
+        assert(k == 0); /* Anything else would mean that we wrote more bytes than available,
+                         * or the kernel reported writing more bytes than sent. */
+        return true;
 }
 
 static inline bool FILE_SIZE_VALID(uint64_t l) {
index ca0b9ec07770bb9b45dcb28067593470aebacdbf..1ada894f09872473ff2959c38605859ed6b0c4bf 100755 (executable)
@@ -1,13 +1,14 @@
 #!/usr/bin/env bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
+set -o pipefail
 
 for i in *.h */*.h; do
-    if [[ $i == 'loadavg.h' ]]; then
-        curl --fail https://raw.githubusercontent.com/torvalds/linux/master/include/linux/sched/$i -o $i
+    if [[ "$i" == "loadavg.h" ]]; then
+        curl --fail "https://raw.githubusercontent.com/torvalds/linux/master/include/linux/sched/$i" -o "$i"
     else
-        curl --fail https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/$i -o $i
+        curl --fail "https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/$i" -o "$i"
     fi
 
-    sed -i -e 's/__user //g' -e '/^#include <linux\/compiler.h>/ d' $i
+    sed -i -e 's/__user //g' -e '/^#include <linux\/compiler.h>/ d' "$i"
 done
index 93261e675e2ff4009c3569af30027db001341f7d..b818078158bd2af87b4883f3a1c88989d8046121 100644 (file)
@@ -427,8 +427,10 @@ const char *special_glyph(SpecialGlyph code) {
                 },
         };
 
-        assert(code < _SPECIAL_GLYPH_MAX);
+        if (code < 0)
+                return NULL;
 
+        assert(code < _SPECIAL_GLYPH_MAX);
         return draw_table[code >= _SPECIAL_GLYPH_FIRST_EMOJI ? emoji_enabled() : is_locale_utf8()][code];
 }
 
index 558c5a898bb5c9f7ae659f9d9993639c8d53c5f9..df259d1bbd9f169907e45382d0800dca67a3d6eb 100644 (file)
@@ -39,7 +39,7 @@ void init_gettext(void);
 
 bool is_locale_utf8(void);
 
-typedef enum {
+typedef enum SpecialGlyph {
         SPECIAL_GLYPH_TREE_VERTICAL,
         SPECIAL_GLYPH_TREE_BRANCH,
         SPECIAL_GLYPH_TREE_RIGHT,
@@ -70,6 +70,7 @@ typedef enum {
         SPECIAL_GLYPH_LOCK_AND_KEY,
         SPECIAL_GLYPH_TOUCH,
         _SPECIAL_GLYPH_MAX,
+        _SPECIAL_GLYPH_INVALID = -EINVAL,
 } SpecialGlyph;
 
 const char *special_glyph(SpecialGlyph code) _const_;
index 595db0c395ac44ebc51bbdf4144741a7097df713..fb183ea9e752b62ec81aa66acffd1714e1101a3c 100644 (file)
@@ -452,11 +452,6 @@ static int write_to_syslog(
         char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
              header_time[64],
              header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
-        struct iovec iovec[5] = {};
-        struct msghdr msghdr = {
-                .msg_iov = iovec,
-                .msg_iovlen = ELEMENTSOF(iovec),
-        };
         time_t t;
         struct tm tm;
 
@@ -474,15 +469,21 @@ static int write_to_syslog(
 
         xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
 
-        iovec[0] = IOVEC_MAKE_STRING(header_priority);
-        iovec[1] = IOVEC_MAKE_STRING(header_time);
-        iovec[2] = IOVEC_MAKE_STRING(program_invocation_short_name);
-        iovec[3] = IOVEC_MAKE_STRING(header_pid);
-        iovec[4] = IOVEC_MAKE_STRING(buffer);
+        struct iovec iovec[] = {
+                IOVEC_MAKE_STRING(header_priority),
+                IOVEC_MAKE_STRING(header_time),
+                IOVEC_MAKE_STRING(program_invocation_short_name),
+                IOVEC_MAKE_STRING(header_pid),
+                IOVEC_MAKE_STRING(buffer),
+        };
+        struct msghdr msghdr = {
+                .msg_iov = iovec,
+                .msg_iovlen = ELEMENTSOF(iovec),
+        };
 
         /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
         if (syslog_is_stream)
-                iovec[4].iov_len++;
+                iovec[ELEMENTSOF(iovec) - 1].iov_len++;
 
         for (;;) {
                 ssize_t n;
@@ -491,11 +492,11 @@ static int write_to_syslog(
                 if (n < 0)
                         return -errno;
 
-                if (!syslog_is_stream ||
-                    (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
+                if (!syslog_is_stream)
                         break;
 
-                IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
+                if (IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n))
+                        break;
         }
 
         return 1;
@@ -520,7 +521,6 @@ static int write_to_kmsg(
 
         char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
              header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
-        struct iovec iovec[5] = {};
 
         if (kmsg_fd < 0)
                 return 0;
@@ -531,11 +531,13 @@ static int write_to_kmsg(
         xsprintf(header_priority, "<%i>", level);
         xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
 
-        iovec[0] = IOVEC_MAKE_STRING(header_priority);
-        iovec[1] = IOVEC_MAKE_STRING(program_invocation_short_name);
-        iovec[2] = IOVEC_MAKE_STRING(header_pid);
-        iovec[3] = IOVEC_MAKE_STRING(buffer);
-        iovec[4] = IOVEC_MAKE_STRING("\n");
+        const struct iovec iovec[] = {
+                IOVEC_MAKE_STRING(header_priority),
+                IOVEC_MAKE_STRING(program_invocation_short_name),
+                IOVEC_MAKE_STRING(header_pid),
+                IOVEC_MAKE_STRING(buffer),
+                IOVEC_MAKE_STRING("\n"),
+        };
 
         if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
                 return -errno;
@@ -959,7 +961,7 @@ int log_struct_internal(
                 if (journal_fd >= 0) {
                         char header[LINE_MAX];
                         struct iovec iovec[17] = {};
-                        size_t n = 0, i;
+                        size_t n = 0;
                         int r;
                         struct msghdr mh = {
                                 .msg_iov = iovec,
@@ -981,7 +983,7 @@ int log_struct_internal(
                         }
 
                         va_end(ap);
-                        for (i = 1; i < n; i += 2)
+                        for (size_t i = 1; i < n; i += 2)
                                 free(iovec[i].iov_base);
 
                         if (!fallback) {
@@ -1429,10 +1431,9 @@ int log_syntax_invalid_utf8_internal(
         if (rvalue)
                 p = utf8_escape_invalid(rvalue);
 
-        log_syntax_internal(unit, level, config_file, config_line, 0, file, line, func,
-                            "String is not UTF-8 clean, ignoring assignment: %s", strna(p));
-
-        return -EINVAL;
+        return log_syntax_internal(unit, level, config_file, config_line,
+                                   SYNTHETIC_ERRNO(EINVAL), file, line, func,
+                                   "String is not UTF-8 clean, ignoring assignment: %s", strna(p));
 }
 
 void log_set_upgrade_syslog_to_journal(bool b) {
index b3d32abfc84f9b992b491ac4edbd7dbc8cb5d73a..51ba3d8fde788e99b759c2b50d3e1adeda87551c 100644 (file)
@@ -4,6 +4,7 @@
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdlib.h>
+#include <string.h>
 #include <syslog.h>
 
 #include "macro.h"
@@ -188,20 +189,39 @@ void log_assert_failed_return(
         log_dispatch_internal(level, error, PROJECT_FILE, __LINE__, __func__, NULL, NULL, NULL, NULL, buffer)
 
 /* Logging with level */
-#define log_full_errno(level, error, ...)                               \
+#define log_full_errno_zerook(level, error, ...)                        \
         ({                                                              \
                 int _level = (level), _e = (error);                     \
-                (log_get_max_level() >= LOG_PRI(_level))                \
+                _e = (log_get_max_level() >= LOG_PRI(_level))           \
                         ? log_internal(_level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
                         : -ERRNO_VALUE(_e);                             \
+                _e < 0 ? _e : -ESTRPIPE;                                \
+        })
+
+#if BUILD_MODE_DEVELOPER && !defined(TEST_CODE)
+#  define ASSERT_NON_ZERO(x) assert((x) != 0)
+#else
+#  define ASSERT_NON_ZERO(x)
+#endif
+
+#define log_full_errno(level, error, ...)                               \
+        ({                                                              \
+                int _error = (error);                                   \
+                ASSERT_NON_ZERO(_error);                                \
+                log_full_errno_zerook(level, _error, __VA_ARGS__);      \
         })
 
-#define log_full(level, ...) (void) log_full_errno((level), 0, __VA_ARGS__)
+#define log_full(level, fmt, ...)                                      \
+        ({                                                             \
+                if (BUILD_MODE_DEVELOPER)                              \
+                        assert(!strstr(fmt, "%m"));                    \
+                (void) log_full_errno_zerook(level, 0, fmt, ##__VA_ARGS__); \
+        })
 
 int log_emergency_level(void);
 
 /* Normal logging */
-#define log_debug(...)     log_full_errno(LOG_DEBUG, 0, __VA_ARGS__)
+#define log_debug(...)     log_full(LOG_DEBUG,   __VA_ARGS__)
 #define log_info(...)      log_full(LOG_INFO,    __VA_ARGS__)
 #define log_notice(...)    log_full(LOG_NOTICE,  __VA_ARGS__)
 #define log_warning(...)   log_full(LOG_WARNING, __VA_ARGS__)
index dff87697a64c0dd830a67f08d3eaacdd10c755a3..841fd324f1606cd541738c15e33cc1ab72f70918 100644 (file)
@@ -5,12 +5,13 @@
 #include <unistd.h>
 
 #define SD_LOGIND_ROOT_CHECK_INHIBITORS           (UINT64_C(1) << 0)
+#define SD_LOGIND_REBOOT_VIA_KEXEC                (UINT64_C(1) << 1)
 
 /* For internal use only */
 #define SD_LOGIND_INTERACTIVE                     (UINT64_C(1) << 63)
 
-#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC (SD_LOGIND_ROOT_CHECK_INHIBITORS)
-#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_ALL    (SD_LOGIND_ROOT_CHECK_INHIBITORS|SD_LOGIND_INTERACTIVE)
+#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC (SD_LOGIND_ROOT_CHECK_INHIBITORS|SD_LOGIND_REBOOT_VIA_KEXEC)
+#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_ALL    (SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC|SD_LOGIND_INTERACTIVE)
 
 bool session_id_valid(const char *id);
 
index 60ef801a253037097a03ef49bc784ef136f8f531..18084875bdf07146cb847b6cd6a43942dad84c9e 100644 (file)
@@ -35,6 +35,8 @@ basic_sources = files('''
         conf-files.h
         copy.c
         copy.h
+        creds-util.c
+        creds-util.h
         def.h
         device-nodes.c
         device-nodes.h
@@ -356,6 +358,7 @@ arch_list = [
         'mipso32',
         'powerpc',
         'powerpc64',
+        'riscv64',
         's390',
         's390x',
         'sparc',
index 4cf31cb839a6ce12980534ab7b6256a570d0609d..5adda554e59aa539e0206024fcb99d24308f02af 100644 (file)
@@ -27,7 +27,7 @@
 
 #ifdef CAP_LAST_CAP
 #  if CAP_LAST_CAP > SYSTEMD_CAP_LAST_CAP
-#    if BUILD_MODE == BUILD_MODE_DEVELOPER && defined(TEST_CAPABILITY_C)
+#    if BUILD_MODE_DEVELOPER && defined(TEST_CAPABILITY_C)
 #      warning "The capability list here is outdated"
 #    endif
 #  else
index 13843248045a9eda3773dd725fc019ecae405908..9e3a165857d8490290982da9bfd4a5a5de1ea3bc 100644 (file)
@@ -425,3 +425,98 @@ static inline int missing_epoll_pwait2(
 
 #  define epoll_pwait2 missing_epoll_pwait2
 #endif
+
+/* ======================================================================= */
+
+#if !HAVE_MOUNT_SETATTR
+
+#if !HAVE_STRUCT_MOUNT_ATTR
+struct mount_attr {
+        uint64_t attr_set;
+        uint64_t attr_clr;
+        uint64_t propagation;
+        uint64_t userns_fd;
+};
+#else
+struct mount_attr;
+#endif
+
+#ifndef MOUNT_ATTR_IDMAP
+#define MOUNT_ATTR_IDMAP 0x00100000
+#endif
+
+#ifndef AT_RECURSIVE
+#define AT_RECURSIVE 0x8000
+#endif
+
+static inline int missing_mount_setattr(
+                int dfd,
+                const char *path,
+                unsigned flags,
+                struct mount_attr *attr,
+                size_t size) {
+
+#  if defined __NR_mount_setattr && __NR_mount_setattr >= 0
+        return syscall(__NR_mount_setattr, dfd, path, flags, attr, size);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+
+#  define mount_setattr missing_mount_setattr
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_OPEN_TREE
+
+#ifndef OPEN_TREE_CLONE
+#define OPEN_TREE_CLONE 1
+#endif
+
+#ifndef OPEN_TREE_CLOEXEC
+#define OPEN_TREE_CLOEXEC O_CLOEXEC
+#endif
+
+static inline int missing_open_tree(
+                int dfd,
+                const char *filename,
+                unsigned flags) {
+
+#  if defined __NR_open_tree && __NR_open_tree >= 0
+        return syscall(__NR_open_tree, dfd, filename, flags);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+
+#  define open_tree missing_open_tree
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_MOVE_MOUNT
+
+#ifndef MOVE_MOUNT_F_EMPTY_PATH
+#define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */
+#endif
+
+static inline int missing_move_mount(
+                int from_dfd,
+                const char *from_pathname,
+                int to_dfd,
+                const char *to_pathname,
+                unsigned flags) {
+
+#  if defined __NR_move_mount && __NR_move_mount >= 0
+        return syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd, to_pathname, flags);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+
+#  define move_mount missing_move_mount
+#endif
index a66977cfec54183a38322515215a110210fb1dfe..84b79ecc092ad9b2f827f0932510df6537e3d5d5 100644 (file)
@@ -1,5 +1,38 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later
- * This file is generated. Do not edit! */
+ * This file is generated by src/basic/missing_syscalls.py. Do not edit!
+ *
+ * Use 'ninja -C build update-syscall-tables' to download new syscall tables,
+ * and 'ninja -C build update-syscall-header' to regenerate this file.
+ */
+
+/* Note: if this code looks strange, this is because it is derived from the same
+ * template as the per-syscall blocks below. */
+#  if defined(__aarch64__)
+#  elif defined(__alpha__)
+#  elif defined(__arc__) || defined(__tilegx__)
+#  elif defined(__arm__)
+#  elif defined(__i386__)
+#  elif defined(__ia64__)
+#  elif defined(__m68k__)
+#  elif defined(_MIPS_SIM)
+#    if _MIPS_SIM == _MIPS_SIM_ABI32
+#    elif _MIPS_SIM == _MIPS_SIM_NABI32
+#    elif _MIPS_SIM == _MIPS_SIM_ABI64
+#    else
+#      error "Unknown MIPS ABI"
+#    endif
+#  elif defined(__powerpc__)
+#  elif defined(__riscv) && defined(__LP64__)
+#  elif defined(__s390__)
+#  elif defined(__sparc__)
+#  elif defined(__x86_64__)
+#    if defined(__ILP32__)
+#    else
+#    endif
+#  elif !defined(missing_arch_template)
+#    warning "Current architecture is missing from the template"
+#    define missing_arch_template 1
+#  endif
 
 #ifndef __IGNORE_bpf
 #  if defined(__aarch64__)
@@ -28,6 +61,8 @@
 #    endif
 #  elif defined(__powerpc__)
 #    define systemd_NR_bpf 361
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_bpf 280
 #  elif defined(__s390__)
 #    define systemd_NR_bpf 351
 #  elif defined(__sparc__)
@@ -38,7 +73,7 @@
 #    else
 #      define systemd_NR_bpf 321
 #    endif
-#  else
+#  elif !defined(missing_arch_template)
 #    warning "bpf() syscall number is unknown for your architecture"
 #  endif
 
@@ -84,6 +119,8 @@ assert_cc(__NR_bpf == systemd_NR_bpf);
 #    endif
 #  elif defined(__powerpc__)
 #    define systemd_NR_close_range 436
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_close_range 436
 #  elif defined(__s390__)
 #    define systemd_NR_close_range 436
 #  elif defined(__sparc__)
@@ -94,7 +131,7 @@ assert_cc(__NR_bpf == systemd_NR_bpf);
 #    else
 #      define systemd_NR_close_range 436
 #    endif
-#  else
+#  elif !defined(missing_arch_template)
 #    warning "close_range() syscall number is unknown for your architecture"
 #  endif
 
@@ -140,6 +177,8 @@ assert_cc(__NR_close_range == systemd_NR_close_range);
 #    endif
 #  elif defined(__powerpc__)
 #    define systemd_NR_copy_file_range 379
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_copy_file_range 285
 #  elif defined(__s390__)
 #    define systemd_NR_copy_file_range 375
 #  elif defined(__sparc__)
@@ -150,7 +189,7 @@ assert_cc(__NR_close_range == systemd_NR_close_range);
 #    else
 #      define systemd_NR_copy_file_range 326
 #    endif
-#  else
+#  elif !defined(missing_arch_template)
 #    warning "copy_file_range() syscall number is unknown for your architecture"
 #  endif
 
@@ -169,6 +208,64 @@ assert_cc(__NR_copy_file_range == systemd_NR_copy_file_range);
 #  endif
 #endif
 
+#ifndef __IGNORE_epoll_pwait2
+#  if defined(__aarch64__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__alpha__)
+#    define systemd_NR_epoll_pwait2 551
+#  elif defined(__arc__) || defined(__tilegx__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__arm__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__i386__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__ia64__)
+#    define systemd_NR_epoll_pwait2 1465
+#  elif defined(__m68k__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(_MIPS_SIM)
+#    if _MIPS_SIM == _MIPS_SIM_ABI32
+#      define systemd_NR_epoll_pwait2 4441
+#    elif _MIPS_SIM == _MIPS_SIM_NABI32
+#      define systemd_NR_epoll_pwait2 6441
+#    elif _MIPS_SIM == _MIPS_SIM_ABI64
+#      define systemd_NR_epoll_pwait2 5441
+#    else
+#      error "Unknown MIPS ABI"
+#    endif
+#  elif defined(__powerpc__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__s390__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__sparc__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__x86_64__)
+#    if defined(__ILP32__)
+#      define systemd_NR_epoll_pwait2 (441 | /* __X32_SYSCALL_BIT */ 0x40000000)
+#    else
+#      define systemd_NR_epoll_pwait2 441
+#    endif
+#  elif !defined(missing_arch_template)
+#    warning "epoll_pwait2() syscall number is unknown for your architecture"
+#  endif
+
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
+#  if defined __NR_epoll_pwait2 && __NR_epoll_pwait2 >= 0
+#    if defined systemd_NR_epoll_pwait2
+assert_cc(__NR_epoll_pwait2 == systemd_NR_epoll_pwait2);
+#    endif
+#  else
+#    if defined __NR_epoll_pwait2
+#      undef __NR_epoll_pwait2
+#    endif
+#    if defined systemd_NR_epoll_pwait2 && systemd_NR_epoll_pwait2 >= 0
+#      define __NR_epoll_pwait2 systemd_NR_epoll_pwait2
+#    endif
+#  endif
+#endif
+
 #ifndef __IGNORE_getrandom
 #  if defined(__aarch64__)
 #    define systemd_NR_getrandom 278
@@ -196,6 +293,8 @@ assert_cc(__NR_copy_file_range == systemd_NR_copy_file_range);
 #    endif
 #  elif defined(__powerpc__)
 #    define systemd_NR_getrandom 359
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_getrandom 278
 #  elif defined(__s390__)
 #    define systemd_NR_getrandom 349
 #  elif defined(__sparc__)
@@ -206,7 +305,7 @@ assert_cc(__NR_copy_file_range == systemd_NR_copy_file_range);
 #    else
 #      define systemd_NR_getrandom 318
 #    endif
-#  else
+#  elif !defined(missing_arch_template)
 #    warning "getrandom() syscall number is unknown for your architecture"
 #  endif
 
@@ -252,6 +351,8 @@ assert_cc(__NR_getrandom == systemd_NR_getrandom);
 #    endif
 #  elif defined(__powerpc__)
 #    define systemd_NR_memfd_create 360
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_memfd_create 279
 #  elif defined(__s390__)
 #    define systemd_NR_memfd_create 350
 #  elif defined(__sparc__)
@@ -262,7 +363,7 @@ assert_cc(__NR_getrandom == systemd_NR_getrandom);
 #    else
 #      define systemd_NR_memfd_create 319
 #    endif
-#  else
+#  elif !defined(missing_arch_template)
 #    warning "memfd_create() syscall number is unknown for your architecture"
 #  endif
 
@@ -281,6 +382,122 @@ assert_cc(__NR_memfd_create == systemd_NR_memfd_create);
 #  endif
 #endif
 
+#ifndef __IGNORE_mount_setattr
+#  if defined(__aarch64__)
+#    define systemd_NR_mount_setattr 442
+#  elif defined(__alpha__)
+#    define systemd_NR_mount_setattr 552
+#  elif defined(__arc__) || defined(__tilegx__)
+#    define systemd_NR_mount_setattr 442
+#  elif defined(__arm__)
+#    define systemd_NR_mount_setattr 442
+#  elif defined(__i386__)
+#    define systemd_NR_mount_setattr 442
+#  elif defined(__ia64__)
+#    define systemd_NR_mount_setattr 1466
+#  elif defined(__m68k__)
+#    define systemd_NR_mount_setattr 442
+#  elif defined(_MIPS_SIM)
+#    if _MIPS_SIM == _MIPS_SIM_ABI32
+#      define systemd_NR_mount_setattr 4442
+#    elif _MIPS_SIM == _MIPS_SIM_NABI32
+#      define systemd_NR_mount_setattr 6442
+#    elif _MIPS_SIM == _MIPS_SIM_ABI64
+#      define systemd_NR_mount_setattr 5442
+#    else
+#      error "Unknown MIPS ABI"
+#    endif
+#  elif defined(__powerpc__)
+#    define systemd_NR_mount_setattr 442
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_mount_setattr 442
+#  elif defined(__s390__)
+#    define systemd_NR_mount_setattr 442
+#  elif defined(__sparc__)
+#    define systemd_NR_mount_setattr 442
+#  elif defined(__x86_64__)
+#    if defined(__ILP32__)
+#      define systemd_NR_mount_setattr (442 | /* __X32_SYSCALL_BIT */ 0x40000000)
+#    else
+#      define systemd_NR_mount_setattr 442
+#    endif
+#  elif !defined(missing_arch_template)
+#    warning "mount_setattr() syscall number is unknown for your architecture"
+#  endif
+
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
+#  if defined __NR_mount_setattr && __NR_mount_setattr >= 0
+#    if defined systemd_NR_mount_setattr
+assert_cc(__NR_mount_setattr == systemd_NR_mount_setattr);
+#    endif
+#  else
+#    if defined __NR_mount_setattr
+#      undef __NR_mount_setattr
+#    endif
+#    if defined systemd_NR_mount_setattr && systemd_NR_mount_setattr >= 0
+#      define __NR_mount_setattr systemd_NR_mount_setattr
+#    endif
+#  endif
+#endif
+
+#ifndef __IGNORE_move_mount
+#  if defined(__aarch64__)
+#    define systemd_NR_move_mount 429
+#  elif defined(__alpha__)
+#    define systemd_NR_move_mount 539
+#  elif defined(__arc__) || defined(__tilegx__)
+#    define systemd_NR_move_mount 429
+#  elif defined(__arm__)
+#    define systemd_NR_move_mount 429
+#  elif defined(__i386__)
+#    define systemd_NR_move_mount 429
+#  elif defined(__ia64__)
+#    define systemd_NR_move_mount 1453
+#  elif defined(__m68k__)
+#    define systemd_NR_move_mount 429
+#  elif defined(_MIPS_SIM)
+#    if _MIPS_SIM == _MIPS_SIM_ABI32
+#      define systemd_NR_move_mount 4429
+#    elif _MIPS_SIM == _MIPS_SIM_NABI32
+#      define systemd_NR_move_mount 6429
+#    elif _MIPS_SIM == _MIPS_SIM_ABI64
+#      define systemd_NR_move_mount 5429
+#    else
+#      error "Unknown MIPS ABI"
+#    endif
+#  elif defined(__powerpc__)
+#    define systemd_NR_move_mount 429
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_move_mount 429
+#  elif defined(__s390__)
+#    define systemd_NR_move_mount 429
+#  elif defined(__sparc__)
+#    define systemd_NR_move_mount 429
+#  elif defined(__x86_64__)
+#    if defined(__ILP32__)
+#      define systemd_NR_move_mount (429 | /* __X32_SYSCALL_BIT */ 0x40000000)
+#    else
+#      define systemd_NR_move_mount 429
+#    endif
+#  elif !defined(missing_arch_template)
+#    warning "move_mount() syscall number is unknown for your architecture"
+#  endif
+
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
+#  if defined __NR_move_mount && __NR_move_mount >= 0
+#    if defined systemd_NR_move_mount
+assert_cc(__NR_move_mount == systemd_NR_move_mount);
+#    endif
+#  else
+#    if defined __NR_move_mount
+#      undef __NR_move_mount
+#    endif
+#    if defined systemd_NR_move_mount && systemd_NR_move_mount >= 0
+#      define __NR_move_mount systemd_NR_move_mount
+#    endif
+#  endif
+#endif
+
 #ifndef __IGNORE_name_to_handle_at
 #  if defined(__aarch64__)
 #    define systemd_NR_name_to_handle_at 264
@@ -308,6 +525,8 @@ assert_cc(__NR_memfd_create == systemd_NR_memfd_create);
 #    endif
 #  elif defined(__powerpc__)
 #    define systemd_NR_name_to_handle_at 345
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_name_to_handle_at 264
 #  elif defined(__s390__)
 #    define systemd_NR_name_to_handle_at 335
 #  elif defined(__sparc__)
@@ -318,7 +537,7 @@ assert_cc(__NR_memfd_create == systemd_NR_memfd_create);
 #    else
 #      define systemd_NR_name_to_handle_at 303
 #    endif
-#  else
+#  elif !defined(missing_arch_template)
 #    warning "name_to_handle_at() syscall number is unknown for your architecture"
 #  endif
 
@@ -337,6 +556,64 @@ assert_cc(__NR_name_to_handle_at == systemd_NR_name_to_handle_at);
 #  endif
 #endif
 
+#ifndef __IGNORE_open_tree
+#  if defined(__aarch64__)
+#    define systemd_NR_open_tree 428
+#  elif defined(__alpha__)
+#    define systemd_NR_open_tree 538
+#  elif defined(__arc__) || defined(__tilegx__)
+#    define systemd_NR_open_tree 428
+#  elif defined(__arm__)
+#    define systemd_NR_open_tree 428
+#  elif defined(__i386__)
+#    define systemd_NR_open_tree 428
+#  elif defined(__ia64__)
+#    define systemd_NR_open_tree 1452
+#  elif defined(__m68k__)
+#    define systemd_NR_open_tree 428
+#  elif defined(_MIPS_SIM)
+#    if _MIPS_SIM == _MIPS_SIM_ABI32
+#      define systemd_NR_open_tree 4428
+#    elif _MIPS_SIM == _MIPS_SIM_NABI32
+#      define systemd_NR_open_tree 6428
+#    elif _MIPS_SIM == _MIPS_SIM_ABI64
+#      define systemd_NR_open_tree 5428
+#    else
+#      error "Unknown MIPS ABI"
+#    endif
+#  elif defined(__powerpc__)
+#    define systemd_NR_open_tree 428
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_open_tree 428
+#  elif defined(__s390__)
+#    define systemd_NR_open_tree 428
+#  elif defined(__sparc__)
+#    define systemd_NR_open_tree 428
+#  elif defined(__x86_64__)
+#    if defined(__ILP32__)
+#      define systemd_NR_open_tree (428 | /* __X32_SYSCALL_BIT */ 0x40000000)
+#    else
+#      define systemd_NR_open_tree 428
+#    endif
+#  elif !defined(missing_arch_template)
+#    warning "open_tree() syscall number is unknown for your architecture"
+#  endif
+
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
+#  if defined __NR_open_tree && __NR_open_tree >= 0
+#    if defined systemd_NR_open_tree
+assert_cc(__NR_open_tree == systemd_NR_open_tree);
+#    endif
+#  else
+#    if defined __NR_open_tree
+#      undef __NR_open_tree
+#    endif
+#    if defined systemd_NR_open_tree && systemd_NR_open_tree >= 0
+#      define __NR_open_tree systemd_NR_open_tree
+#    endif
+#  endif
+#endif
+
 #ifndef __IGNORE_pidfd_open
 #  if defined(__aarch64__)
 #    define systemd_NR_pidfd_open 434
@@ -364,6 +641,8 @@ assert_cc(__NR_name_to_handle_at == systemd_NR_name_to_handle_at);
 #    endif
 #  elif defined(__powerpc__)
 #    define systemd_NR_pidfd_open 434
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_pidfd_open 434
 #  elif defined(__s390__)
 #    define systemd_NR_pidfd_open 434
 #  elif defined(__sparc__)
@@ -374,7 +653,7 @@ assert_cc(__NR_name_to_handle_at == systemd_NR_name_to_handle_at);
 #    else
 #      define systemd_NR_pidfd_open 434
 #    endif
-#  else
+#  elif !defined(missing_arch_template)
 #    warning "pidfd_open() syscall number is unknown for your architecture"
 #  endif
 
@@ -420,6 +699,8 @@ assert_cc(__NR_pidfd_open == systemd_NR_pidfd_open);
 #    endif
 #  elif defined(__powerpc__)
 #    define systemd_NR_pidfd_send_signal 424
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_pidfd_send_signal 424
 #  elif defined(__s390__)
 #    define systemd_NR_pidfd_send_signal 424
 #  elif defined(__sparc__)
@@ -430,7 +711,7 @@ assert_cc(__NR_pidfd_open == systemd_NR_pidfd_open);
 #    else
 #      define systemd_NR_pidfd_send_signal 424
 #    endif
-#  else
+#  elif !defined(missing_arch_template)
 #    warning "pidfd_send_signal() syscall number is unknown for your architecture"
 #  endif
 
@@ -476,6 +757,8 @@ assert_cc(__NR_pidfd_send_signal == systemd_NR_pidfd_send_signal);
 #    endif
 #  elif defined(__powerpc__)
 #    define systemd_NR_pkey_mprotect 386
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_pkey_mprotect 288
 #  elif defined(__s390__)
 #    define systemd_NR_pkey_mprotect 384
 #  elif defined(__sparc__)
@@ -486,7 +769,7 @@ assert_cc(__NR_pidfd_send_signal == systemd_NR_pidfd_send_signal);
 #    else
 #      define systemd_NR_pkey_mprotect 329
 #    endif
-#  else
+#  elif !defined(missing_arch_template)
 #    warning "pkey_mprotect() syscall number is unknown for your architecture"
 #  endif
 
@@ -532,6 +815,8 @@ assert_cc(__NR_pkey_mprotect == systemd_NR_pkey_mprotect);
 #    endif
 #  elif defined(__powerpc__)
 #    define systemd_NR_renameat2 357
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_renameat2 276
 #  elif defined(__s390__)
 #    define systemd_NR_renameat2 347
 #  elif defined(__sparc__)
@@ -542,7 +827,7 @@ assert_cc(__NR_pkey_mprotect == systemd_NR_pkey_mprotect);
 #    else
 #      define systemd_NR_renameat2 316
 #    endif
-#  else
+#  elif !defined(missing_arch_template)
 #    warning "renameat2() syscall number is unknown for your architecture"
 #  endif
 
@@ -588,6 +873,8 @@ assert_cc(__NR_renameat2 == systemd_NR_renameat2);
 #    endif
 #  elif defined(__powerpc__)
 #    define systemd_NR_setns 350
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_setns 268
 #  elif defined(__s390__)
 #    define systemd_NR_setns 339
 #  elif defined(__sparc__)
@@ -598,7 +885,7 @@ assert_cc(__NR_renameat2 == systemd_NR_renameat2);
 #    else
 #      define systemd_NR_setns 308
 #    endif
-#  else
+#  elif !defined(missing_arch_template)
 #    warning "setns() syscall number is unknown for your architecture"
 #  endif
 
@@ -644,6 +931,8 @@ assert_cc(__NR_setns == systemd_NR_setns);
 #    endif
 #  elif defined(__powerpc__)
 #    define systemd_NR_statx 383
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_statx 291
 #  elif defined(__s390__)
 #    define systemd_NR_statx 379
 #  elif defined(__sparc__)
@@ -654,7 +943,7 @@ assert_cc(__NR_setns == systemd_NR_setns);
 #    else
 #      define systemd_NR_statx 332
 #    endif
-#  else
+#  elif !defined(missing_arch_template)
 #    warning "statx() syscall number is unknown for your architecture"
 #  endif
 
@@ -672,59 +961,3 @@ assert_cc(__NR_statx == systemd_NR_statx);
 #    endif
 #  endif
 #endif
-
-#ifndef __IGNORE_epoll_pwait2
-#  if defined(__aarch64__)
-#    define systemd_NR_epoll_pwait2 441
-#  elif defined(__alpha__)
-#    define systemd_NR_epoll_pwait2 551
-#  elif defined(__arc__) || defined(__tilegx__)
-#    define systemd_NR_epoll_pwait2 441
-#  elif defined(__arm__)
-#    define systemd_NR_epoll_pwait2 441
-#  elif defined(__i386__)
-#    define systemd_NR_epoll_pwait2 441
-#  elif defined(__ia64__)
-#    define systemd_NR_epoll_pwait2 1465
-#  elif defined(__m68k__)
-#    define systemd_NR_epoll_pwait2 441
-#  elif defined(_MIPS_SIM)
-#    if _MIPS_SIM == _MIPS_SIM_ABI32
-#      define systemd_NR_epoll_pwait2 4441
-#    elif _MIPS_SIM == _MIPS_SIM_NABI32
-#      define systemd_NR_epoll_pwait2 6441
-#    elif _MIPS_SIM == _MIPS_SIM_ABI64
-#      define systemd_NR_epoll_pwait2 5441
-#    else
-#      error "Unknown MIPS ABI"
-#    endif
-#  elif defined(__powerpc__)
-#    define systemd_NR_epoll_pwait2 441
-#  elif defined(__s390__)
-#    define systemd_NR_epoll_pwait2 441
-#  elif defined(__sparc__)
-#    define systemd_NR_epoll_pwait2 441
-#  elif defined(__x86_64__)
-#    if defined(__ILP32__)
-#      define systemd_NR_epoll_pwait2 (441 | /* __X32_SYSCALL_BIT */ 0x40000000)
-#    else
-#      define systemd_NR_epoll_pwait2 441
-#    endif
-#  else
-#    warning "epoll_pwait2() syscall number is unknown for your architecture"
-#  endif
-
-/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
-#  if defined __NR_epoll_pwait2 && __NR_epoll_pwait2 >= 0
-#    if defined systemd_NR_epoll_pwait2
-assert_cc(__NR_epoll_pwait2 == systemd_NR_epoll_pwait2);
-#    endif
-#  else
-#    if defined __NR_epoll_pwait2
-#      undef __NR_epoll_pwait2
-#    endif
-#    if defined systemd_NR_epoll_pwait2 && systemd_NR_epoll_pwait2 >= 0
-#      define __NR_epoll_pwait2 systemd_NR_epoll_pwait2
-#    endif
-#  endif
-#endif
index 550be48cf4d0d0d918c7a0c9281c7e3d16f7bd03..d3c68dc067d8727d5bc96b25be9c24bf33ded223 100644 (file)
@@ -9,16 +9,20 @@ SYSCALLS = [
     'bpf',
     'close_range',
     'copy_file_range',
+    'epoll_pwait2',
     'getrandom',
     'memfd_create',
+    'mount_setattr',
+    'move_mount',
     'name_to_handle_at',
+    'open_tree',
     'pidfd_open',
     'pidfd_send_signal',
     'pkey_mprotect',
     'renameat2',
     'setns',
     'statx',
-    'epoll_pwait2']
+]
 
 def dictify(f):
     def wrap(*args, **kwargs):
@@ -37,8 +41,12 @@ def parse_syscall_tables(filenames):
     return {filename.split('-')[-1][:-4]: parse_syscall_table(filename)
             for filename in filenames}
 
-DEF_TEMPLATE = '''
+DEF_TEMPLATE_A = '''\
+
 #ifndef __IGNORE_{syscall}
+'''
+
+DEF_TEMPLATE_B = '''\
 #  if defined(__aarch64__)
 #    define systemd_NR_{syscall} {nr_arm64}
 #  elif defined(__alpha__)
@@ -65,6 +73,8 @@ DEF_TEMPLATE = '''
 #    endif
 #  elif defined(__powerpc__)
 #    define systemd_NR_{syscall} {nr_powerpc}
+#  elif defined(__riscv) && defined(__LP64__)
+#    define systemd_NR_{syscall} {nr_riscv64}
 #  elif defined(__s390__)
 #    define systemd_NR_{syscall} {nr_s390}
 #  elif defined(__sparc__)
@@ -75,9 +85,12 @@ DEF_TEMPLATE = '''
 #    else
 #      define systemd_NR_{syscall} {nr_x86_64}
 #    endif
-#  else
-#    warning "{syscall}() syscall number is unknown for your architecture"
+#  elif !defined(missing_arch_template)
+%s
 #  endif
+'''
+
+DEF_TEMPLATE_C = '''\
 
 /* may be an (invalid) negative number due to libseccomp, see PR 13319 */
 #  if defined __NR_{syscall} && __NR_{syscall} >= 0
@@ -92,20 +105,37 @@ assert_cc(__NR_{syscall} == systemd_NR_{syscall});
 #      define __NR_{syscall} systemd_NR_{syscall}
 #    endif
 #  endif
-#endif
-'''
+#endif'''
+
+DEF_TEMPLATE = (DEF_TEMPLATE_A +
+                DEF_TEMPLATE_B % '#    warning "{syscall}() syscall number is unknown for your architecture"' +
+                DEF_TEMPLATE_C)
+
+ARCH_CHECK = '''\
+/* Note: if this code looks strange, this is because it is derived from the same
+ * template as the per-syscall blocks below. */
+''' + '\n'.join(line for line in DEF_TEMPLATE_B.splitlines()
+                       if ' define ' not in line) % '''\
+#    warning "Current architecture is missing from the template"
+#    define missing_arch_template 1'''
 
 def print_syscall_def(syscall, tables, out):
     mappings = {f'nr_{arch}':t.get(syscall, -1)
                 for arch, t in tables.items()}
     print(DEF_TEMPLATE.format(syscall=syscall, **mappings),
-          file=out, end='')
+          file=out)
 
 def print_syscall_defs(syscalls, tables, out):
     print('''\
 /* SPDX-License-Identifier: LGPL-2.1-or-later
- * This file is generated. Do not edit! */
-''' , file=out, end='')
+ * This file is generated by src/basic/missing_syscalls.py. Do not edit!
+ *
+ * Use 'ninja -C build update-syscall-tables' to download new syscall tables,
+ * and 'ninja -C build update-syscall-header' to regenerate this file.
+ */
+''',
+          file=out)
+    print(ARCH_CHECK, file=out)
     for syscall in syscalls:
         print_syscall_def(syscall, tables, out)
 
index c8f6675eb8676b88855c70115f86ba52ffffcc0d..1d617e87b276a97946230feb350e157bf5163ea4 100644 (file)
@@ -196,13 +196,15 @@ int fd_is_mount_point(int fd, const char *filename, int flags) {
 
         if (statx(fd, filename, (FLAGS_SET(flags, AT_SYMLINK_FOLLOW) ? 0 : AT_SYMLINK_NOFOLLOW) |
                                 (flags & AT_EMPTY_PATH) |
-                                AT_NO_AUTOMOUNT, 0, &sx) < 0) {
+                                AT_NO_AUTOMOUNT, STATX_TYPE, &sx) < 0) {
                 if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
                         return -errno;
 
                 /* If statx() is not available or forbidden, fall back to name_to_handle_at() below */
         } else if (FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT)) /* yay! */
                 return FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT);
+        else if (FLAGS_SET(sx.stx_mask, STATX_TYPE) && S_ISLNK(sx.stx_mode))
+                return false; /* symlinks are never mount points */
 
         r = name_to_handle_at_loop(fd, filename, &h, &mount_id, flags);
         if (IN_SET(r, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL))
@@ -231,16 +233,13 @@ int fd_is_mount_point(int fd, const char *filename, int flags) {
         } else if (r < 0)
                 return r;
 
-        /* The parent can do name_to_handle_at() but the
-         * directory we are interested in can't? If so, it
-         * must be a mount point. */
+        /* The parent can do name_to_handle_at() but the directory we are interested in can't? If so, it must
+         * be a mount point. */
         if (nosupp)
                 return 1;
 
-        /* If the file handle for the directory we are
-         * interested in and its parent are identical, we
-         * assume this is the root directory, which is a mount
-         * point. */
+        /* If the file handle for the directory we are interested in and its parent are identical, we assume
+         * this is the root directory, which is a mount point. */
 
         if (h->handle_bytes == h_parent->handle_bytes &&
             h->handle_type == h_parent->handle_type &&
@@ -263,23 +262,22 @@ fallback_fdinfo:
         if (mount_id != mount_id_parent)
                 return 1;
 
-        /* Hmm, so, the mount ids are the same. This leaves one
-         * special case though for the root file system. For that,
-         * let's see if the parent directory has the same inode as we
-         * are interested in. Hence, let's also do fstat() checks now,
-         * too, but avoid the st_dev comparisons, since they aren't
-         * that useful on unionfs mounts. */
+        /* Hmm, so, the mount ids are the same. This leaves one special case though for the root file
+         * system. For that, let's see if the parent directory has the same inode as we are interested
+         * in. Hence, let's also do fstat() checks now, too, but avoid the st_dev comparisons, since they
+         * aren't that useful on unionfs mounts. */
         check_st_dev = false;
 
 fallback_fstat:
-        /* yay for fstatat() taking a different set of flags than the other
-         * _at() above */
+        /* yay for fstatat() taking a different set of flags than the other _at() above */
         if (flags & AT_SYMLINK_FOLLOW)
                 flags &= ~AT_SYMLINK_FOLLOW;
         else
                 flags |= AT_SYMLINK_NOFOLLOW;
         if (fstatat(fd, filename, &a, flags) < 0)
                 return -errno;
+        if (S_ISLNK(a.st_mode)) /* Symlinks are never mount points */
+                return false;
 
         if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
                 return -errno;
index dfc0d3fb200e64bd4e06d59d1eeed4f09348d385..3c59dcc03c363b5106c4a8624c9b3d9aef65171b 100644 (file)
@@ -213,3 +213,25 @@ typedef enum nss_status (*_nss_gethostbyaddr_r_t)(
                 struct hostent *host,
                 char *buffer, size_t buflen,
                 int *errnop, int *h_errnop);
+
+typedef enum nss_status (*_nss_getpwnam_r_t)(
+                const char *name,
+                struct passwd *pwd,
+                char *buffer, size_t buflen,
+                int *errnop);
+typedef enum nss_status (*_nss_getpwuid_r_t)(
+                uid_t uid,
+                struct passwd *pwd,
+                char *buffer, size_t buflen,
+                int *errnop);
+
+typedef enum nss_status (*_nss_getgrnam_r_t)(
+                const char *name,
+                struct group *gr,
+                char *buffer, size_t buflen,
+                int *errnop);
+typedef enum nss_status (*_nss_getgrgid_r_t)(
+                gid_t gid,
+                struct group *gr,
+                char *buffer, size_t buflen,
+                int *errnop);
index 58fa8af1b7371c68035fe3eaf0086e8dbb317da6..0a76f0456165b46a48aaeabda7d4c2396c19cf95 100644 (file)
@@ -35,30 +35,33 @@ int ordered_set_consume(OrderedSet *s, void *p) {
         return r;
 }
 
-int ordered_set_put_strdup(OrderedSet *s, const char *p) {
+int _ordered_set_put_strdup(OrderedSet **s, const char *p  HASHMAP_DEBUG_PARAMS) {
         char *c;
         int r;
 
         assert(s);
         assert(p);
 
+        r = _ordered_set_ensure_allocated(s, &string_hash_ops_free  HASHMAP_DEBUG_PASS_ARGS);
+        if (r < 0)
+                return r;
+
+        if (ordered_set_contains(*s, p))
+                return 0;
+
         c = strdup(p);
         if (!c)
                 return -ENOMEM;
 
-        r = ordered_set_consume(s, c);
-        if (r == -EEXIST)
-                return 0;
-
-        return r;
+        return ordered_set_consume(*s, c);
 }
 
-int ordered_set_put_strdupv(OrderedSet *s, char **l) {
+int _ordered_set_put_strdupv(OrderedSet **s, char **l  HASHMAP_DEBUG_PARAMS) {
         int n = 0, r;
         char **i;
 
         STRV_FOREACH(i, l) {
-                r = ordered_set_put_strdup(s, *i);
+                r = _ordered_set_put_strdup(s, *i  HASHMAP_DEBUG_PASS_ARGS);
                 if (r < 0)
                         return r;
 
@@ -68,7 +71,7 @@ int ordered_set_put_strdupv(OrderedSet *s, char **l) {
         return n;
 }
 
-int ordered_set_put_string_set(OrderedSet *s, OrderedSet *l) {
+int ordered_set_put_string_set(OrderedSet **s, OrderedSet *l) {
         int n = 0, r;
         char *p;
 
index baf82020887517d827e3b1e516ac5862c2f333c1..a377f20b1f254c8705486a0b56beb60ee10173eb 100644 (file)
@@ -26,6 +26,10 @@ static inline OrderedSet* ordered_set_free_free(OrderedSet *s) {
         return (OrderedSet*) ordered_hashmap_free_free((OrderedHashmap*) s);
 }
 
+static inline int ordered_set_contains(OrderedSet *s, const void *p) {
+        return ordered_hashmap_contains((OrderedHashmap*) s, p);
+}
+
 static inline int ordered_set_put(OrderedSet *s, void *p) {
         return ordered_hashmap_put((OrderedHashmap*) s, p, p);
 }
@@ -59,9 +63,11 @@ static inline char** ordered_set_get_strv(OrderedSet *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);
-int ordered_set_put_string_set(OrderedSet *s, OrderedSet *l);
+int _ordered_set_put_strdup(OrderedSet **s, const char *p  HASHMAP_DEBUG_PARAMS);
+#define ordered_set_put_strdup(s, p) _ordered_set_put_strdup(s, p  HASHMAP_DEBUG_SRC_ARGS)
+int _ordered_set_put_strdupv(OrderedSet **s, char **l  HASHMAP_DEBUG_PARAMS);
+#define ordered_set_put_strdupv(s, l) _ordered_set_put_strdupv(s, l  HASHMAP_DEBUG_SRC_ARGS)
+int ordered_set_put_string_set(OrderedSet **s, OrderedSet *l);
 void ordered_set_print(FILE *f, const char *field, OrderedSet *s);
 
 #define _ORDERED_SET_FOREACH(e, s, i) \
index 96b82170d06d93b5ff2e360ae938dd4e692fbe8a..e53c2302b12722c2c3617d63ffc2fcefdb02b5cc 100644 (file)
@@ -772,7 +772,7 @@ void lookup_paths_log(LookupPaths *p) {
                 log_debug("Ignoring unit files.");
                 p->search_path = strv_free(p->search_path);
         } else {
-                _cleanup_free_ char *t;
+                _cleanup_free_ char *t = NULL;
 
                 t = strv_join(p->search_path, "\n\t");
                 log_debug("Looking for unit files in (higher priority first):\n\t%s", strna(t));
index 50ba44492e502bd8ad624243959d9be1a1afa0e7..f98859939cddad1994d4a73504bbfcb8dcf9edb2 100644 (file)
@@ -527,6 +527,27 @@ bool path_equal_or_files_same(const char *a, const char *b, int flags) {
         return path_equal(a, b) || files_same(a, b, flags) > 0;
 }
 
+bool path_equal_filename(const char *a, const char *b) {
+        _cleanup_free_ char *a_basename = NULL, *b_basename = NULL;
+        int r;
+
+        assert(a);
+        assert(b);
+
+        r = path_extract_filename(a, &a_basename);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to parse basename of %s: %m", a);
+                return false;
+        }
+        r = path_extract_filename(b, &b_basename);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to parse basename of %s: %m", b);
+                return false;
+        }
+
+        return path_equal(a_basename, b_basename);
+}
+
 char* path_join_internal(const char *first, ...) {
         char *joined, *q;
         const char *p;
@@ -1190,9 +1211,3 @@ bool prefixed_path_strv_contains(char **l, const char *path) {
 
         return false;
 }
-
-bool credential_name_valid(const char *s) {
-        /* We want that credential names are both valid in filenames (since that's our primary way to pass
-         * them around) and as fdnames (which is how we might want to pass them around eventually) */
-        return filename_is_valid(s) && fdname_is_valid(s);
-}
index 74ee6362eacb9147c24ae5c6a012b46b9a139325..f82d935dc5c739d8d76afae6cbcaf6fee61ba568 100644 (file)
@@ -61,6 +61,8 @@ 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);
+/* Compares only the last portion of the input paths, ie: the filenames */
+bool path_equal_filename(const char *a, const char *b);
 char* path_join_internal(const char *first, ...);
 #define path_join(x, ...) path_join_internal(x, __VA_ARGS__, POINTER_MAX)
 
@@ -183,5 +185,3 @@ static inline const char *empty_to_root(const char *path) {
 
 bool path_strv_contains(char **l, const char *path);
 bool prefixed_path_strv_contains(char **l, const char *path);
-
-bool credential_name_valid(const char *s);
index 0b6fb137bdc304e3921aed759b56a4871d6e92f6..410b8a3eb5de67e7d1defd0a5377bf8441520102 100644 (file)
@@ -47,7 +47,7 @@ static int proc_cmdline_extract_first(const char **p, char **ret_word, ProcCmdli
                 _cleanup_free_ char *word = NULL;
                 const char *c;
 
-                r = extract_first_word(&q, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX);
+                r = extract_first_word(&q, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
                 if (r < 0)
                         return r;
                 if (r == 0)
index a3c4500dff4537fb6c4ccc27446035c62fd49aed..cad639a023b97fe5098b5968114d7c909a647c98 100644 (file)
@@ -74,6 +74,7 @@ int normalize_recovery_key(const char *password, char **ret) {
 int make_recovery_key(char **ret) {
         _cleanup_(erase_and_freep) char *formatted = NULL;
         _cleanup_(erase_and_freep) uint8_t *key = NULL;
+        size_t j = 0;
         int r;
 
         assert(ret);
@@ -91,7 +92,7 @@ int make_recovery_key(char **ret) {
         if (!formatted)
                 return -ENOMEM;
 
-        for (size_t i = 0, j = 0; i < RECOVERY_KEY_MODHEX_RAW_LENGTH; i++) {
+        for (size_t i = 0; i < RECOVERY_KEY_MODHEX_RAW_LENGTH; i++) {
                 formatted[j++] = modhex_alphabet[key[i] >> 4];
                 formatted[j++] = modhex_alphabet[key[i] & 0xF];
 
@@ -99,7 +100,9 @@ int make_recovery_key(char **ret) {
                         formatted[j++] = '-';
         }
 
-        formatted[RECOVERY_KEY_MODHEX_FORMATTED_LENGTH-1] = 0;
+        assert(j == RECOVERY_KEY_MODHEX_FORMATTED_LENGTH);
+        assert(formatted[RECOVERY_KEY_MODHEX_FORMATTED_LENGTH-1] == '-');
+        formatted[RECOVERY_KEY_MODHEX_FORMATTED_LENGTH-1] = 0; /* replace final dash with a NUL */
 
         *ret = TAKE_PTR(formatted);
         return 0;
index ee9e34ed47cb676fba1fc92449fecd9ec3aadca8..8c5544d46bbbda4efe954c4a1d9f5bb05ae0842a 100644 (file)
@@ -84,15 +84,24 @@ void mac_selinux_retest(void) {
 }
 
 #if HAVE_SELINUX
-#  if HAVE_MALLINFO
-static struct mallinfo mallinfo_nowarn(void) {
-        /* glibc has deprecated mallinfo(), but the replacement malloc_info() returns an XML blob ;=[ */
+#  if HAVE_MALLINFO2
+#    define HAVE_GENERIC_MALLINFO 1
+typedef struct mallinfo2 generic_mallinfo;
+static generic_mallinfo generic_mallinfo_get(void) {
+        return mallinfo2();
+}
+#  elif HAVE_MALLINFO
+#    define HAVE_GENERIC_MALLINFO 1
+typedef struct mallinfo generic_mallinfo;
+static generic_mallinfo generic_mallinfo_get(void) {
+        /* glibc has deprecated mallinfo(), let's suppress the deprecation warning if mallinfo2() doesn't
+         * exist yet. */
 DISABLE_WARNING_DEPRECATED_DECLARATIONS
         return mallinfo();
 REENABLE_WARNING
 }
 #  else
-#    warning "mallinfo() is missing, add mallinfo2() supported instead."
+#    define HAVE_GENERIC_MALLINFO 0
 #  endif
 
 static int open_label_db(void) {
@@ -100,8 +109,8 @@ static int open_label_db(void) {
         usec_t before_timestamp, after_timestamp;
         char timespan[FORMAT_TIMESPAN_MAX];
 
-#  if HAVE_MALLINFO
-        struct mallinfo before_mallinfo = mallinfo_nowarn();
+#  if HAVE_GENERIC_MALLINFO
+        generic_mallinfo before_mallinfo = generic_mallinfo_get();
 #  endif
         before_timestamp = now(CLOCK_MONOTONIC);
 
@@ -110,10 +119,10 @@ static int open_label_db(void) {
                 return log_enforcing_errno(errno, "Failed to initialize SELinux labeling handle: %m");
 
         after_timestamp = now(CLOCK_MONOTONIC);
-#  if HAVE_MALLINFO
-        struct mallinfo after_mallinfo = mallinfo_nowarn();
-        int l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0;
-        log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.",
+#  if HAVE_GENERIC_MALLINFO
+        generic_mallinfo after_mallinfo = generic_mallinfo_get();
+        size_t l = LESS_BY((size_t) after_mallinfo.uordblks, (size_t) before_mallinfo.uordblks);
+        log_debug("Successfully loaded SELinux database in %s, size on heap is %zuK.",
                   format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0),
                   DIV_ROUND_UP(l, 1024));
 #  else
index 507a599d7cfa072833b1364d2e55f4ff45ca5abf..e0b959f5da550cc1bd60c430bc64bee179fe5561 100644 (file)
@@ -14,6 +14,7 @@
 #include <sys/types.h>
 #include <sys/un.h>
 
+#include "errno-util.h"
 #include "macro.h"
 #include "missing_network.h"
 #include "missing_socket.h"
@@ -264,7 +265,7 @@ static inline int getsockopt_int(int fd, int level, int optname, int *ret) {
         socklen_t sl = sizeof(v);
 
         if (getsockopt(fd, level, optname, &v, &sl) < 0)
-                return -errno;
+                return negative_errno();
         if (sl != sizeof(v))
                 return -EIO;
 
index b9b7be7a7dda98c0b0840bacabcda882c75ed150..78f22f1ac918d4ef844a2230d5b85911ff1b0751 100644 (file)
@@ -37,6 +37,7 @@
 #define SPECIAL_INITRD_FS_TARGET "initrd-fs.target"
 #define SPECIAL_INITRD_ROOT_DEVICE_TARGET "initrd-root-device.target"
 #define SPECIAL_INITRD_ROOT_FS_TARGET "initrd-root-fs.target"
+#define SPECIAL_INITRD_USR_FS_TARGET "initrd-usr-fs.target"
 #define SPECIAL_REMOTE_FS_TARGET "remote-fs.target"       /* LSB's $remote_fs */
 #define SPECIAL_REMOTE_FS_PRE_TARGET "remote-fs-pre.target"
 #define SPECIAL_SWAP_TARGET "swap.target"
@@ -79,6 +80,7 @@
 /* Magic early boot services */
 #define SPECIAL_FSCK_SERVICE "systemd-fsck@.service"
 #define SPECIAL_FSCK_ROOT_SERVICE "systemd-fsck-root.service"
+#define SPECIAL_FSCK_USR_SERVICE "systemd-fsck-usr.service"
 #define SPECIAL_QUOTACHECK_SERVICE "systemd-quotacheck.service"
 #define SPECIAL_QUOTAON_SERVICE "quotaon.service"
 #define SPECIAL_REMOUNT_FS_SERVICE "systemd-remount-fs.service"
index 212b561fa645bb2fbcca76271d1f04402feb6576..0617acc8d215308b58af4cab8101cc6d3e76c2cf 100644 (file)
@@ -107,11 +107,9 @@ static void bubbleinsert(struct strbuf_node *node,
 /* add string, return the index/offset into the buffer */
 ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
         uint8_t c;
-        struct strbuf_node *node;
-        size_t depth;
         char *buf_new;
         struct strbuf_child_entry *child;
-        struct strbuf_node *node_child;
+        struct strbuf_node *node;
         ssize_t off;
 
         if (!str->root)
@@ -127,7 +125,7 @@ ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
         str->in_len += len;
 
         node = str->root;
-        for (depth = 0; depth <= len; depth++) {
+        for (size_t depth = 0; depth <= len; depth++) {
                 struct strbuf_child_entry search;
 
                 /* match against current node */
@@ -159,6 +157,8 @@ ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
         str->buf[str->len++] = '\0';
 
         /* new node */
+        _cleanup_free_ struct strbuf_node *node_child = NULL;
+
         node_child = new(struct strbuf_node, 1);
         if (!node_child)
                 return -ENOMEM;
@@ -169,15 +169,13 @@ ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
 
         /* extend array, add new entry, sort for bisection */
         child = reallocarray(node->children, node->children_count + 1, sizeof(struct strbuf_child_entry));
-        if (!child) {
-                free(node_child);
+        if (!child)
                 return -ENOMEM;
-        }
 
         str->nodes_count++;
 
         node->children = child;
-        bubbleinsert(node, c, node_child);
+        bubbleinsert(node, c, TAKE_PTR(node_child));
 
         return off;
 }
index bcf39cd3ecb30b356ff415f0e42a35261f764a9c..c1f368dbd89b333e2e19082d6cec63dac377fdaa 100644 (file)
@@ -790,6 +790,87 @@ char *strextend_with_separator_internal(char **x, const char *separator, ...) {
         return p;
 }
 
+int strextendf(char **x, const char *format, ...) {
+        size_t m, a;
+        va_list ap;
+        int l;
+
+        /* Appends a formatted string to the specified string. Don't use this in inner loops, since then
+         * we'll spend a tonload of time in determining the length of the string passed in, over and over
+         * again. */
+
+        assert(x);
+        assert(format);
+
+        /* Let's try to use the allocated buffer, if there's room at the end still. Otherwise let's extend by 64 chars. */
+        if (*x) {
+                m = strlen(*x);
+                a = malloc_usable_size(*x);
+                assert(a >= m + 1);
+        } else
+                m = a = 0;
+
+        if (a - m < 17) { /* if there's less than 16 chars space, then enlarge the buffer first */
+                char *n;
+
+                if (_unlikely_(m > SIZE_MAX - 64)) /* overflow check */
+                        return -ENOMEM;
+
+                n = realloc(*x, m + 64);
+                if (!n)
+                        return -ENOMEM;
+
+                *x = n;
+                a = malloc_usable_size(*x);
+        }
+
+        /* Now, let's try to format the string into it */
+        va_start(ap, format);
+        l = vsnprintf(*x + m, a - m, format, ap);
+        va_end(ap);
+
+        assert(l >= 0);
+
+        if ((size_t) l < a - m) {
+                char *n;
+
+                /* Nice! This worked. We are done. But first, let's return the extra space we don't
+                 * need. This should be a cheap operation, since we only lower the allocation size here,
+                 * never increase. */
+                n = realloc(*x, m + (size_t) l + 1);
+                if (n)
+                        *x = n;
+        } else {
+                char *n;
+
+                /* Wasn't enough. Then let's allocate exactly what we need. */
+
+                if (_unlikely_((size_t) l > SIZE_MAX - 1)) /* overflow check #1 */
+                        goto oom;
+                if (_unlikely_(m > SIZE_MAX - ((size_t) l + 1))) /* overflow check #2 */
+                        goto oom;
+
+                a = m + (size_t) l + 1;
+                n = realloc(*x, a);
+                if (!n)
+                        goto oom;
+                *x = n;
+
+                va_start(ap, format);
+                l = vsnprintf(*x + m, a - m, format, ap);
+                va_end(ap);
+
+                assert((size_t) l < a - m);
+        }
+
+        return 0;
+
+oom:
+        /* truncate the bytes added after the first vsnprintf() attempt again */
+        (*x)[m] = 0;
+        return -ENOMEM;
+}
+
 char *strrep(const char *s, unsigned n) {
         char *r, *p;
         size_t l;
index 1bc131f15b0a735d8fc58a37b19216020d9aadd1..116dbd4583e256b2b00d1da2b946a051758ceaab 100644 (file)
@@ -155,6 +155,8 @@ char *strextend_with_separator_internal(char **x, const char *separator, ...) _s
 #define strextend_with_separator(x, separator, ...) strextend_with_separator_internal(x, separator, __VA_ARGS__, NULL)
 #define strextend(x, ...) strextend_with_separator_internal(x, NULL, __VA_ARGS__, NULL)
 
+int strextendf(char **x, const char *format, ...) _printf_(2,3);
+
 char *strrep(const char *s, unsigned n);
 
 int split_pair(const char *s, const char *sep, char **l, char **r);
diff --git a/src/basic/syscalls-riscv64.txt b/src/basic/syscalls-riscv64.txt
new file mode 100644 (file)
index 0000000..60445d0
--- /dev/null
@@ -0,0 +1,594 @@
+_llseek
+_newselect
+_sysctl
+accept 202
+accept4        242
+access
+acct   89
+add_key        217
+adjtimex       171
+alarm
+arc_gettls
+arc_settls
+arc_usr_cmpxchg
+arch_prctl
+arm_fadvise64_64
+atomic_barrier
+atomic_cmpxchg_32
+bdflush
+bind   200
+bpf    280
+brk    214
+cachectl
+cacheflush
+capget 90
+capset 91
+chdir  49
+chmod
+chown
+chown32
+chroot 51
+clock_adjtime  266
+clock_adjtime64
+clock_getres   114
+clock_getres_time64
+clock_gettime  113
+clock_gettime64
+clock_nanosleep        115
+clock_nanosleep_time64
+clock_settime  112
+clock_settime64
+clone  220
+clone2
+clone3 435
+close  57
+close_range    436
+connect        203
+copy_file_range        285
+creat
+create_module
+delete_module  106
+dipc
+dup    23
+dup2
+dup3   24
+epoll_create
+epoll_create1  20
+epoll_ctl      21
+epoll_ctl_old
+epoll_pwait    22
+epoll_pwait2   441
+epoll_wait
+epoll_wait_old
+eventfd
+eventfd2       19
+exec_with_loader
+execv
+execve 221
+execveat       281
+exit   93
+exit_group     94
+faccessat      48
+faccessat2     439
+fadvise64      223
+fadvise64_64
+fallocate      47
+fanotify_init  262
+fanotify_mark  263
+fchdir 50
+fchmod 52
+fchmodat       53
+fchown 55
+fchown32
+fchownat       54
+fcntl  25
+fcntl64
+fdatasync      83
+fgetxattr      10
+finit_module   273
+flistxattr     13
+flock  32
+fork
+fp_udfiex_crtl
+fremovexattr   16
+fsconfig       431
+fsetxattr      7
+fsmount        432
+fsopen 430
+fspick 433
+fstat  80
+fstat64
+fstatat64
+fstatfs        44
+fstatfs64
+fsync  82
+ftruncate      46
+ftruncate64
+futex  98
+futex_time64
+futimesat
+get_kernel_syms
+get_mempolicy  236
+get_robust_list        100
+get_thread_area
+getcpu 168
+getcwd 17
+getdents
+getdents64     61
+getdomainname
+getdtablesize
+getegid        177
+getegid32
+geteuid        175
+geteuid32
+getgid 176
+getgid32
+getgroups      158
+getgroups32
+gethostname
+getitimer      102
+getpagesize
+getpeername    205
+getpgid        155
+getpgrp
+getpid 172
+getpmsg
+getppid        173
+getpriority    141
+getrandom      278
+getresgid      150
+getresgid32
+getresuid      148
+getresuid32
+getrlimit      163
+getrusage      165
+getsid 156
+getsockname    204
+getsockopt     209
+gettid 178
+gettimeofday   169
+getuid 174
+getuid32
+getunwind
+getxattr       8
+getxgid
+getxpid
+getxuid
+idle
+init_module    105
+inotify_add_watch      27
+inotify_init
+inotify_init1  26
+inotify_rm_watch       28
+io_cancel      3
+io_destroy     1
+io_getevents   4
+io_pgetevents  292
+io_pgetevents_time64
+io_setup       0
+io_submit      2
+io_uring_enter 426
+io_uring_register      427
+io_uring_setup 425
+ioctl  29
+ioperm
+iopl
+ioprio_get     31
+ioprio_set     30
+ipc
+kcmp   272
+kern_features
+kexec_file_load        294
+kexec_load     104
+keyctl 219
+kill   129
+lchown
+lchown32
+lgetxattr      9
+link
+linkat 37
+listen 201
+listxattr      11
+llistxattr     12
+lookup_dcookie 18
+lremovexattr   15
+lseek  62
+lsetxattr      6
+lstat
+lstat64
+madvise        233
+mbind  235
+membarrier     283
+memfd_create   279
+memory_ordering
+migrate_pages  238
+mincore        232
+mkdir
+mkdirat        34
+mknod
+mknodat        33
+mlock  228
+mlock2 284
+mlockall       230
+mmap   222
+mmap2
+modify_ldt
+mount  40
+mount_setattr  442
+move_mount     429
+move_pages     239
+mprotect       226
+mq_getsetattr  185
+mq_notify      184
+mq_open        180
+mq_timedreceive        183
+mq_timedreceive_time64
+mq_timedsend   182
+mq_timedsend_time64
+mq_unlink      181
+mremap 216
+msgctl 187
+msgget 186
+msgrcv 188
+msgsnd 189
+msync  227
+multiplexer
+munlock        229
+munlockall     231
+munmap 215
+name_to_handle_at      264
+nanosleep      101
+newfstatat     79
+nfsservctl     42
+nice
+old_adjtimex
+old_getpagesize
+oldfstat
+oldlstat
+oldolduname
+oldstat
+oldumount
+olduname
+open
+open_by_handle_at      265
+open_tree      428
+openat 56
+openat2        437
+or1k_atomic
+osf_adjtime
+osf_afs_syscall
+osf_alt_plock
+osf_alt_setsid
+osf_alt_sigpending
+osf_asynch_daemon
+osf_audcntl
+osf_audgen
+osf_chflags
+osf_execve
+osf_exportfs
+osf_fchflags
+osf_fdatasync
+osf_fpathconf
+osf_fstat
+osf_fstatfs
+osf_fstatfs64
+osf_fuser
+osf_getaddressconf
+osf_getdirentries
+osf_getdomainname
+osf_getfh
+osf_getfsstat
+osf_gethostid
+osf_getitimer
+osf_getlogin
+osf_getmnt
+osf_getrusage
+osf_getsysinfo
+osf_gettimeofday
+osf_kloadcall
+osf_kmodcall
+osf_lstat
+osf_memcntl
+osf_mincore
+osf_mount
+osf_mremap
+osf_msfs_syscall
+osf_msleep
+osf_mvalid
+osf_mwakeup
+osf_naccept
+osf_nfssvc
+osf_ngetpeername
+osf_ngetsockname
+osf_nrecvfrom
+osf_nrecvmsg
+osf_nsendmsg
+osf_ntp_adjtime
+osf_ntp_gettime
+osf_old_creat
+osf_old_fstat
+osf_old_getpgrp
+osf_old_killpg
+osf_old_lstat
+osf_old_open
+osf_old_sigaction
+osf_old_sigblock
+osf_old_sigreturn
+osf_old_sigsetmask
+osf_old_sigvec
+osf_old_stat
+osf_old_vadvise
+osf_old_vtrace
+osf_old_wait
+osf_oldquota
+osf_pathconf
+osf_pid_block
+osf_pid_unblock
+osf_plock
+osf_priocntlset
+osf_profil
+osf_proplist_syscall
+osf_reboot
+osf_revoke
+osf_sbrk
+osf_security
+osf_select
+osf_set_program_attributes
+osf_set_speculative
+osf_sethostid
+osf_setitimer
+osf_setlogin
+osf_setsysinfo
+osf_settimeofday
+osf_shmat
+osf_signal
+osf_sigprocmask
+osf_sigsendset
+osf_sigstack
+osf_sigwaitprim
+osf_sstk
+osf_stat
+osf_statfs
+osf_statfs64
+osf_subsys_info
+osf_swapctl
+osf_swapon
+osf_syscall
+osf_sysinfo
+osf_table
+osf_uadmin
+osf_usleep_thread
+osf_uswitch
+osf_utc_adjtime
+osf_utc_gettime
+osf_utimes
+osf_utsname
+osf_wait4
+osf_waitid
+pause
+pciconfig_iobase
+pciconfig_read
+pciconfig_write
+perf_event_open        241
+perfctr
+perfmonctl
+personality    92
+pidfd_getfd    438
+pidfd_open     434
+pidfd_send_signal      424
+pipe
+pipe2  59
+pivot_root     41
+pkey_alloc     289
+pkey_free      290
+pkey_mprotect  288
+poll
+ppoll  73
+ppoll_time64
+prctl  167
+pread64        67
+preadv 69
+preadv2        286
+prlimit64      261
+process_madvise        440
+process_vm_readv       270
+process_vm_writev      271
+pselect6       72
+pselect6_time64
+ptrace 117
+pwrite64       68
+pwritev        70
+pwritev2       287
+query_module
+quotactl       60
+read   63
+readahead      213
+readdir
+readlink
+readlinkat     78
+readv  65
+reboot 142
+recv
+recvfrom       207
+recvmmsg       243
+recvmmsg_time64
+recvmsg        212
+remap_file_pages       234
+removexattr    14
+rename
+renameat
+renameat2      276
+request_key    218
+restart_syscall        128
+riscv_flush_icache     259
+rmdir
+rseq   293
+rt_sigaction   134
+rt_sigpending  136
+rt_sigprocmask 135
+rt_sigqueueinfo        138
+rt_sigreturn   139
+rt_sigsuspend  133
+rt_sigtimedwait        137
+rt_sigtimedwait_time64
+rt_tgsigqueueinfo      240
+rtas
+s390_guarded_storage
+s390_pci_mmio_read
+s390_pci_mmio_write
+s390_runtime_instr
+s390_sthyi
+sched_get_affinity
+sched_get_priority_max 125
+sched_get_priority_min 126
+sched_getaffinity      123
+sched_getattr  275
+sched_getparam 121
+sched_getscheduler     120
+sched_rr_get_interval  127
+sched_rr_get_interval_time64
+sched_set_affinity
+sched_setaffinity      122
+sched_setattr  274
+sched_setparam 118
+sched_setscheduler     119
+sched_yield    124
+seccomp        277
+select
+semctl 191
+semget 190
+semop  193
+semtimedop     192
+semtimedop_time64
+send
+sendfile       71
+sendfile64
+sendmmsg       269
+sendmsg        211
+sendto 206
+set_mempolicy  237
+set_robust_list        99
+set_thread_area
+set_tid_address        96
+setdomainname  162
+setfsgid       152
+setfsgid32
+setfsuid       151
+setfsuid32
+setgid 144
+setgid32
+setgroups      159
+setgroups32
+sethae
+sethostname    161
+setitimer      103
+setns  268
+setpgid        154
+setpgrp
+setpriority    140
+setregid       143
+setregid32
+setresgid      149
+setresgid32
+setresuid      147
+setresuid32
+setreuid       145
+setreuid32
+setrlimit      164
+setsid 157
+setsockopt     208
+settimeofday   170
+setuid 146
+setuid32
+setxattr       5
+sgetmask
+shmat  196
+shmctl 195
+shmdt  197
+shmget 194
+shutdown       210
+sigaction
+sigaltstack    132
+signal
+signalfd
+signalfd4      74
+sigpending
+sigprocmask
+sigreturn
+sigsuspend
+socket 198
+socketcall
+socketpair     199
+splice 76
+spu_create
+spu_run
+ssetmask
+stat
+stat64
+statfs 43
+statfs64
+statx  291
+stime
+subpage_prot
+swapcontext
+swapoff        225
+swapon 224
+switch_endian
+symlink
+symlinkat      36
+sync   81
+sync_file_range        84
+sync_file_range2
+syncfs 267
+sys_debug_setcontext
+syscall
+sysfs
+sysinfo        179
+syslog 116
+sysmips
+tee    77
+tgkill 131
+time
+timer_create   107
+timer_delete   111
+timer_getoverrun       109
+timer_gettime  108
+timer_gettime64
+timer_settime  110
+timer_settime64
+timerfd
+timerfd_create 85
+timerfd_gettime        87
+timerfd_gettime64
+timerfd_settime        86
+timerfd_settime64
+times  153
+tkill  130
+truncate       45
+truncate64
+ugetrlimit
+umask  166
+umount
+umount2        39
+uname  160
+unlink
+unlinkat       35
+unshare        97
+uselib
+userfaultfd    282
+ustat
+utime
+utimensat      88
+utimensat_time64
+utimes
+utrap_install
+vfork
+vhangup        58
+vm86
+vm86old
+vmsplice       75
+wait4  260
+waitid 95
+waitpid
+write  64
+writev 66
index 1a3f9ccb33cd782ac773ca404b4c234580c13a7a..fafdaaa090e94274943e31d19074426433082691 100644 (file)
@@ -52,7 +52,7 @@ static volatile int cached_color_mode = _COLOR_INVALID;
 static volatile int cached_underline_enabled = -1;
 
 int chvt(int vt) {
-        _cleanup_close_ int fd;
+        _cleanup_close_ int fd = -1;
 
         /* Switch to the specified vt number. If the VT is specified <= 0 switch to the VT the kernel log messages go,
          * if that's configured. */
@@ -514,7 +514,7 @@ int terminal_vhangup_fd(int fd) {
 }
 
 int terminal_vhangup(const char *name) {
-        _cleanup_close_ int fd;
+        _cleanup_close_ int fd = -1;
 
         fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
         if (fd < 0)
index 3c2b25bd2a72039f14516457618b20c6c8eb7ea7..6b3b42254d504c55f03d04fe766c9ffb12e4e8c6 100644 (file)
@@ -1278,8 +1278,8 @@ int get_timezones(char ***ret) {
         f = fopen("/usr/share/zoneinfo/zone1970.tab", "re");
         if (f) {
                 for (;;) {
-                        _cleanup_free_ char *line = NULL;
-                        char *p, *w;
+                        _cleanup_free_ char *line = NULL, *w = NULL;
+                        char *p;
                         size_t k;
 
                         r = read_line(f, LONG_LINE_MAX, &line);
@@ -1310,12 +1310,10 @@ int get_timezones(char ***ret) {
                         if (!w)
                                 return -ENOMEM;
 
-                        if (!GREEDY_REALLOC(zones, n_allocated, n_zones + 2)) {
-                                free(w);
+                        if (!GREEDY_REALLOC(zones, n_allocated, n_zones + 2))
                                 return -ENOMEM;
-                        }
 
-                        zones[n_zones++] = w;
+                        zones[n_zones++] = TAKE_PTR(w);
                         zones[n_zones] = NULL;
                 }
 
@@ -1547,7 +1545,7 @@ int time_change_fd(void) {
                 .it_value.tv_sec = TIME_T_MAX,
         };
 
-        _cleanup_close_ int fd;
+        _cleanup_close_ int fd = -1;
 
         assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
 
index 5ee71d015887aa8441e57498bb13aa19a77945ff..c5ae92f985fb5f6db862ea37bb459fbcc175c4b4 100644 (file)
@@ -65,7 +65,7 @@ int fopen_temporary(const char *path, FILE **ret_f, char **ret_temp_path) {
 
 /* This is much like mkostemp() but is subject to umask(). */
 int mkostemp_safe(char *pattern) {
-        int fd = -1; /* avoid false maybe-uninitialized warning */
+        int fd = -1;  /* avoid false maybe-uninitialized warning */
 
         assert(pattern);
 
index 6fbb947f096dab7146b7517cd2cb9f43c0f8529b..5cfabca83fb08fcae548ce83943483c1b564ef66 100644 (file)
@@ -296,22 +296,19 @@ static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = {
 DEFINE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess);
 
 SpecialGlyph unit_active_state_to_glyph(UnitActiveState state) {
-        switch (state) {
-                case UNIT_ACTIVE:
-                    return SPECIAL_GLYPH_BLACK_CIRCLE;
-                case UNIT_RELOADING:
-                    return SPECIAL_GLYPH_CIRCLE_ARROW;
-                case UNIT_INACTIVE:
-                    return SPECIAL_GLYPH_WHITE_CIRCLE;
-                case UNIT_FAILED:
-                    return SPECIAL_GLYPH_MULTIPLICATION_SIGN;
-                case UNIT_ACTIVATING:
-                case UNIT_DEACTIVATING:
-                    return SPECIAL_GLYPH_BLACK_CIRCLE;
-                case UNIT_MAINTENANCE:
-                    return SPECIAL_GLYPH_WHITE_CIRCLE;
-
-                default:
-                    return SPECIAL_GLYPH_BLACK_CIRCLE;
-            }
+        static const SpecialGlyph map[_UNIT_ACTIVE_STATE_MAX] = {
+                [UNIT_ACTIVE]       = SPECIAL_GLYPH_BLACK_CIRCLE,
+                [UNIT_RELOADING]    = SPECIAL_GLYPH_CIRCLE_ARROW,
+                [UNIT_INACTIVE]     = SPECIAL_GLYPH_WHITE_CIRCLE,
+                [UNIT_FAILED]       = SPECIAL_GLYPH_MULTIPLICATION_SIGN,
+                [UNIT_ACTIVATING]   = SPECIAL_GLYPH_BLACK_CIRCLE,
+                [UNIT_DEACTIVATING] = SPECIAL_GLYPH_BLACK_CIRCLE,
+                [UNIT_MAINTENANCE]  = SPECIAL_GLYPH_WHITE_CIRCLE,
+        };
+
+        if (state < 0)
+                return _SPECIAL_GLYPH_INVALID;
+
+        assert(state < _UNIT_ACTIVE_STATE_MAX);
+        return map[state];
 }
index 50e6eccbf70ddbeb4007a4d829f1d78dcb5c106c..fab63b6dcece9f1d55b0ffda1f9862c56b82f3e4 100644 (file)
@@ -72,7 +72,7 @@ int unit_validate_alias_symlink_and_warn(const char *filename, const char *targe
         const char *src, *dst;
         _cleanup_free_ char *src_instance = NULL, *dst_instance = NULL;
         UnitType src_unit_type, dst_unit_type;
-        int src_name_type, dst_name_type;
+        UnitNameFlags src_name_type, dst_name_type;
 
         /* Check if the *alias* symlink is valid. This applies to symlinks like
          * /etc/systemd/system/dbus.service → dbus-broker.service, but not to .wants or .requires symlinks
@@ -284,7 +284,7 @@ int unit_file_build_name_map(
                         continue;
                 }
 
-                FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) {
+                FOREACH_DIRENT(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) {
                         char *filename;
                         _cleanup_free_ char *_filename_free = NULL, *simplified = NULL;
                         const char *suffix, *dst = NULL;
@@ -403,6 +403,7 @@ int unit_file_build_name_map(
         /* Let's also put the names in the reverse db. */
         const char *dummy, *src;
         HASHMAP_FOREACH_KEY(dummy, src, ids) {
+                _cleanup_free_ char *inst = NULL, *dst_inst = NULL;
                 const char *dst;
 
                 r = unit_ids_map_get(ids, src, &dst);
@@ -412,15 +413,31 @@ int unit_file_build_name_map(
                 if (null_or_empty_path(dst) != 0)
                         continue;
 
-                /* Do not treat instance symlinks that point to the template as aliases */
-                if (unit_name_is_valid(basename(dst), UNIT_NAME_TEMPLATE) &&
-                    unit_name_is_valid(src, UNIT_NAME_INSTANCE))
-                        continue;
+                dst = basename(dst);
+
+                /* If we have an symlink from an instance name to a template name, it is an alias just for
+                 * this specific instance, foo@id.service ↔ template@id.service. */
+                if (unit_name_is_valid(dst, UNIT_NAME_TEMPLATE)) {
+                        UnitNameFlags t = unit_name_to_instance(src, &inst);
+                        if (t < 0)
+                                return log_error_errno(t, "Failed to extract instance part from %s: %m", src);
+                        if (t == UNIT_NAME_INSTANCE) {
+                                r = unit_name_replace_instance(dst, inst, &dst_inst);
+                                if (r < 0) {
+                                        /* This might happen e.g. if the combined length is too large.
+                                         * Let's not make too much of a fuss. */
+                                        log_debug_errno(r, "Failed to build alias name (%s + %s), ignoring: %m",
+                                                        dst, inst);
+                                        continue;
+                                }
 
-                r = string_strv_hashmap_put(&names, basename(dst), src);
+                                dst = dst_inst;
+                        }
+                }
+
+                r = string_strv_hashmap_put(&names, dst, src);
                 if (r < 0)
-                        return log_warning_errno(r, "Failed to add entry to hashmap (%s→%s): %m",
-                                                 basename(dst), src);
+                        return log_warning_errno(r, "Failed to add entry to hashmap (%s→%s): %m", dst, src);
         }
 
         if (cache_timestamp_hash)
@@ -434,6 +451,88 @@ int unit_file_build_name_map(
         return 1;
 }
 
+static int add_name(
+                const char *unit_name,
+                Set **names,
+                const char *name) {
+        int r;
+
+        assert(names);
+        assert(name);
+
+        r = set_put_strdup(names, name);
+        if (r < 0)
+                return r;
+        if (r > 0 && !streq(unit_name, name))
+                log_debug("Unit %s has alias %s.", unit_name, name);
+        return r;
+}
+
+static int add_names(
+                Hashmap *unit_ids_map,
+                Hashmap *unit_name_map,
+                const char *unit_name,
+                const char *fragment_basename,  /* Only set when adding additional names based on fragment path */
+                UnitNameFlags name_type,
+                const char *instance,
+                Set **names,
+                const char *name) {
+
+        char **aliases, **alias;
+        int r;
+
+        assert(name_type == UNIT_NAME_PLAIN || instance);
+
+        /* The unit has its own name if it's not a template. If we're looking at a fragment, the fragment
+         * name (possibly with instance inserted), is also always one of the unit names. */
+        if (name_type != UNIT_NAME_TEMPLATE) {
+                r = add_name(unit_name, names, name);
+                if (r < 0)
+                        return r;
+        }
+
+        /* Add any aliases of the name to the set of names.
+         *
+         * We don't even need to know which fragment we will use. The unit_name_map should return the same
+         * set of names for any of the aliases. */
+        aliases = hashmap_get(unit_name_map, name);
+        STRV_FOREACH(alias, aliases) {
+                if (name_type == UNIT_NAME_INSTANCE && unit_name_is_valid(*alias, UNIT_NAME_TEMPLATE)) {
+                        _cleanup_free_ char *inst = NULL;
+                        const char *inst_fragment = NULL;
+
+                        r = unit_name_replace_instance(*alias, instance, &inst);
+                        if (r < 0)
+                                return log_debug_errno(r, "Cannot build instance name %s + %s: %m",
+                                                       *alias, instance);
+
+                        /* Exclude any aliases that point in some other direction.
+                         *
+                         * See https://github.com/systemd/systemd/pull/13119#discussion_r308145418. */
+                        r = unit_ids_map_get(unit_ids_map, inst, &inst_fragment);
+                        if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO))
+                                return log_debug_errno(r, "Cannot find instance fragment %s: %m", inst);
+
+                        if (inst_fragment &&
+                            !streq(basename(inst_fragment), fragment_basename)) {
+                                log_debug("Instance %s has fragment %s and is not an alias of %s.",
+                                          inst, inst_fragment, unit_name);
+                                continue;
+                        }
+
+                        r = set_consume(*names, TAKE_PTR(inst));
+                        if (r > 0)
+                                log_debug("Unit %s has alias %s.", unit_name, inst);
+                } else
+                        r = add_name(unit_name, names, *alias);
+
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
 int unit_file_find_fragment(
                 Hashmap *unit_ids_map,
                 Hashmap *unit_name_map,
@@ -443,9 +542,8 @@ int unit_file_find_fragment(
 
         const char *fragment = NULL;
         _cleanup_free_ char *template = NULL, *instance = NULL;
-        _cleanup_set_free_free_ Set *names = NULL;
-        char **t, **nnn;
-        int r, name_type;
+        _cleanup_set_free_ Set *names = NULL;
+        int r;
 
         /* Finds a fragment path, and returns the set of names:
          * if we have …/foo.service and …/foo-alias.service→foo.service,
@@ -461,53 +559,19 @@ int unit_file_find_fragment(
          * foo-alias@inst.service → …/foo@inst.service, {foo@inst.service, foo-alias@inst.service}.
          */
 
-        name_type = unit_name_to_instance(unit_name, &instance);
+        UnitNameFlags name_type = unit_name_to_instance(unit_name, &instance);
         if (name_type < 0)
                 return name_type;
 
-        names = set_new(&string_hash_ops);
-        if (!names)
-                return -ENOMEM;
-
-        /* The unit always has its own name if it's not a template. */
-        if (IN_SET(name_type, UNIT_NAME_PLAIN, UNIT_NAME_INSTANCE)) {
-                r = set_put_strdup(&names, unit_name);
-                if (r < 0)
-                        return r;
-        }
+        r = add_names(unit_ids_map, unit_name_map, unit_name, NULL, name_type, instance, &names, unit_name);
+        if (r < 0)
+                return r;
 
         /* First try to load fragment under the original name */
         r = unit_ids_map_get(unit_ids_map, unit_name, &fragment);
         if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO))
                 return log_debug_errno(r, "Cannot load unit %s: %m", unit_name);
 
-        if (fragment) {
-                /* Add any aliases of the original name to the set of names */
-                nnn = hashmap_get(unit_name_map, basename(fragment));
-                STRV_FOREACH(t, nnn) {
-                        if (name_type == UNIT_NAME_INSTANCE && unit_name_is_valid(*t, UNIT_NAME_TEMPLATE)) {
-                                char *inst;
-
-                                r = unit_name_replace_instance(*t, instance, &inst);
-                                if (r < 0)
-                                        return log_debug_errno(r, "Cannot build instance name %s+%s: %m", *t, instance);
-
-                                if (!streq(unit_name, inst))
-                                        log_debug("%s: %s has alias %s", __func__, unit_name, inst);
-
-                                log_info("%s: %s+%s → %s", __func__, *t, instance, inst);
-                                r = set_consume(names, inst);
-                        } else {
-                                if (!streq(unit_name, *t))
-                                        log_debug("%s: %s has alias %s", __func__, unit_name, *t);
-
-                                r = set_put_strdup(&names, *t);
-                        }
-                        if (r < 0)
-                                return r;
-                }
-        }
-
         if (!fragment && name_type == UNIT_NAME_INSTANCE) {
                 /* Look for a fragment under the template name */
 
@@ -518,43 +582,22 @@ int unit_file_find_fragment(
                 r = unit_ids_map_get(unit_ids_map, template, &fragment);
                 if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO))
                         return log_debug_errno(r, "Cannot load template %s: %m", template);
+        }
 
-                if (fragment) {
-                        /* Add any aliases of the original name to the set of names */
-                        nnn = hashmap_get(unit_name_map, basename(fragment));
-                        STRV_FOREACH(t, nnn) {
-                                _cleanup_free_ char *inst = NULL;
-                                const char *inst_fragment = NULL;
-
-                                r = unit_name_replace_instance(*t, instance, &inst);
-                                if (r < 0)
-                                        return log_debug_errno(r, "Cannot build instance name %s+%s: %m", template, instance);
-
-                                /* Exclude any aliases that point in some other direction. */
-                                r = unit_ids_map_get(unit_ids_map, inst, &inst_fragment);
-                                if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO))
-                                        return log_debug_errno(r, "Cannot find instance fragment %s: %m", inst);
-
-                                if (inst_fragment &&
-                                    !streq(basename(inst_fragment), basename(fragment))) {
-                                        log_debug("Instance %s has fragment %s and is not an alias of %s.",
-                                                  inst, inst_fragment, unit_name);
-                                        continue;
-                                }
+        if (fragment) {
+                const char *fragment_basename = basename(fragment);
 
-                                if (!streq(unit_name, inst))
-                                        log_debug("%s: %s has alias %s", __func__, unit_name, inst);
-                                r = set_consume(names, TAKE_PTR(inst));
-                                if (r < 0)
-                                        return r;
-                        }
+                if (!streq(fragment_basename, unit_name)) {
+                        /* Add names based on the fragment name to the set of names */
+                        r = add_names(unit_ids_map, unit_name_map, unit_name, fragment_basename, name_type, instance, &names, fragment_basename);
+                        if (r < 0)
+                                return r;
                 }
         }
 
         *ret_fragment_path = fragment;
         *ret_names = TAKE_PTR(names);
 
-        // FIXME: if instance, consider any unit names with different template name
         return 0;
 }
 
index 532f8fa048c1c5c32ae81754898fb44b75238410..dbc9f5baa26886cd320b4e61824cd7a12573796b 100644 (file)
@@ -139,7 +139,7 @@ int unit_name_to_prefix(const char *n, char **ret) {
         return 0;
 }
 
-int unit_name_to_instance(const char *n, char **ret) {
+UnitNameFlags unit_name_to_instance(const char *n, char **ret) {
         const char *p, *d;
 
         assert(n);
index 19d70abea8cc6b93c4d1a3089da1af3b424a1e63..f6af01c9bd8e8a3a1b4088d1c14a0c0efb685eea 100644 (file)
@@ -22,8 +22,8 @@ bool unit_instance_is_valid(const char *i) _pure_;
 bool unit_suffix_is_valid(const char *s) _pure_;
 
 int unit_name_to_prefix(const char *n, char **ret);
-int unit_name_to_instance(const char *n, char **ret);
-static inline int unit_name_classify(const char *n) {
+UnitNameFlags unit_name_to_instance(const char *n, char **ret);
+static inline UnitNameFlags unit_name_classify(const char *n) {
         return unit_name_to_instance(n, NULL);
 }
 int unit_name_to_prefix_and_instance(const char *n, char **ret);
index 0ea4e409fac5991e8b5f37ced3e04fde43a66808..3756e80c30d799742b8d8cf20e55cdfefa8c2768 100644 (file)
@@ -1072,3 +1072,16 @@ int fgetsgent_sane(FILE *stream, struct sgrp **sg) {
         return !!s;
 }
 #endif
+
+int is_this_me(const char *username) {
+        uid_t uid;
+        int r;
+
+        /* Checks if the specified username is our current one. Passed string might be a UID or a user name. */
+
+        r = get_user_creds(&username, &uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING);
+        if (r < 0)
+                return r;
+
+        return uid == getuid();
+}
index 20ff415e2e9befc896ebe1f837d66ed066d5db21..fd00b47b7665c55ced366dd2e57d259bdc6302e2 100644 (file)
@@ -109,3 +109,14 @@ int putsgent_sane(const struct sgrp *sg, FILE *stream);
 #endif
 
 bool is_nologin_shell(const char *shell);
+
+int is_this_me(const char *username);
+
+/* A locked *and* invalid password for "struct spwd"'s .sp_pwdp and "struct passwd"'s .pw_passwd field */
+#define PASSWORD_LOCKED_AND_INVALID "!*"
+
+/* A password indicating "look in shadow file, please!" for "struct passwd"'s .pw_passwd */
+#define PASSWORD_SEE_SHADOW "x"
+
+/* A password indicating "hey, no password required for login" */
+#define PASSWORD_NONE ""
index 335f59d6fc60c8c9de3e973c03d84ac7142c2c6c..9b8518bd084065e798c328c9927930abb5f3d417 100644 (file)
 #include "string-util.h"
 #include "virt.h"
 
+enum {
+      SMBIOS_VM_BIT_SET,
+      SMBIOS_VM_BIT_UNSET,
+      SMBIOS_VM_BIT_UNKNOWN,
+};
+
 #if defined(__i386__) || defined(__x86_64__)
 static const char *const vm_table[_VIRTUALIZATION_MAX] = {
         [VIRTUALIZATION_XEN]       = "XenVMMXenVMM",
@@ -134,9 +140,8 @@ static int detect_vm_device_tree(void) {
 #endif
 }
 
-static int detect_vm_dmi(void) {
 #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
-
+static int detect_vm_dmi_vendor(void) {
         static const char *const dmi_vendors[] = {
                 "/sys/class/dmi/id/product_name", /* Test this before sys_vendor to detect KVM over QEMU */
                 "/sys/class/dmi/id/sys_vendor",
@@ -149,6 +154,7 @@ static int detect_vm_dmi(void) {
                 int id;
         } dmi_vendor_table[] = {
                 { "KVM",                 VIRTUALIZATION_KVM       },
+                { "Amazon EC2",          VIRTUALIZATION_AMAZON    },
                 { "QEMU",                VIRTUALIZATION_QEMU      },
                 { "VMware",              VIRTUALIZATION_VMWARE    }, /* https://kb.vmware.com/s/article/1009458 */
                 { "VMW",                 VIRTUALIZATION_VMWARE    },
@@ -180,11 +186,63 @@ static int detect_vm_dmi(void) {
                                 return dmi_vendor_table[j].id;
                         }
         }
-#endif
+        return VIRTUALIZATION_NONE;
+}
+
+static int detect_vm_smbios(void) {
+        /* The SMBIOS BIOS Charateristics Extension Byte 2 (Section 2.1.2.2 of
+         * https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.4.0.pdf), specifies that
+         * the 4th bit being set indicates a VM. The BIOS Characteristics table is exposed via the kernel in
+         * /sys/firmware/dmi/entries/0-0. Note that in the general case, this bit being unset should not
+         * imply that the system is running on bare-metal.  For example, QEMU 3.1.0 (with or without KVM)
+         * with SeaBIOS does not set this bit. */
+        _cleanup_free_ char *s = NULL;
+        size_t readsize;
+        int r;
+
+        r = read_full_virtual_file("/sys/firmware/dmi/entries/0-0/raw", &s, &readsize);
+        if (r < 0) {
+                log_debug_errno(r, "Unable to read /sys/firmware/dmi/entries/0-0/raw, ignoring: %m");
+                return SMBIOS_VM_BIT_UNKNOWN;
+        }
+        if (readsize < 20 || s[1] < 20) {
+                /* The spec indicates that byte 1 contains the size of the table, 0x12 + the number of
+                 * extension bytes. The data we're interested in is in extension byte 2, which would be at
+                 * 0x13. If we didn't read that much data, or if the BIOS indicates that we don't have that
+                 * much data, we don't infer anything from the SMBIOS. */
+                log_debug("Only read %zu bytes from /sys/firmware/dmi/entries/0-0/raw (expected 20)", readsize);
+                return SMBIOS_VM_BIT_UNKNOWN;
+        }
 
-        log_debug("No virtualization found in DMI");
+        uint8_t byte = (uint8_t) s[19];
+        if (byte & (1U<<4)) {
+                log_debug("DMI BIOS Extension table indicates virtualization");
+                return SMBIOS_VM_BIT_SET;
+        }
+        log_debug("DMI BIOS Extension table does not indicate virtualization");
+        return SMBIOS_VM_BIT_UNSET;
+}
+#endif /* defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) */
+
+static int detect_vm_dmi(void) {
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
+
+        int r;
+        r = detect_vm_dmi_vendor();
 
+        /* The DMI vendor tables in /sys/class/dmi/id don't help us distinguish between Amazon EC2
+         * virtual machines and bare-metal instances, so we need to look at SMBIOS. */
+        if (r == VIRTUALIZATION_AMAZON && detect_vm_smbios() == SMBIOS_VM_BIT_UNSET)
+                return VIRTUALIZATION_NONE;
+
+        /* If we haven't identified a VM, but the firmware indicates that there is one, indicate as much. We
+         * have no further information about what it is. */
+        if (r == VIRTUALIZATION_NONE && detect_vm_smbios() == SMBIOS_VM_BIT_SET)
+                return VIRTUALIZATION_VM_OTHER;
+        return r;
+#else
         return VIRTUALIZATION_NONE;
+#endif
 }
 
 static int detect_vm_xen(void) {
@@ -344,8 +402,9 @@ int detect_vm(void) {
 
         /* We have to use the correct order here:
          *
-         * → First, try to detect Oracle Virtualbox, even if it uses KVM, as well as Xen even if it cloaks as Microsoft
-         *   Hyper-V. Attempt to detect uml at this stage also since it runs as a user-process nested inside other VMs.
+         * → First, try to detect Oracle Virtualbox and Amazon EC2 Nitro, even if they use KVM, as well as Xen even if
+         *   it cloaks as Microsoft Hyper-V. Attempt to detect uml at this stage also since it runs as a user-process
+         *   nested inside other VMs.
          *
          * → Second, try to detect from CPUID, this will report KVM for whatever software is used even if info in DMI is
          *   overwritten.
@@ -353,7 +412,7 @@ int detect_vm(void) {
          * → Third, try to detect from DMI. */
 
         dmi = detect_vm_dmi();
-        if (IN_SET(dmi, VIRTUALIZATION_ORACLE, VIRTUALIZATION_XEN)) {
+        if (IN_SET(dmi, VIRTUALIZATION_ORACLE, VIRTUALIZATION_XEN, VIRTUALIZATION_AMAZON)) {
                 r = dmi;
                 goto finish;
         }
@@ -914,6 +973,7 @@ bool has_cpu_with_flag(const char *flag) {
 static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
         [VIRTUALIZATION_NONE] = "none",
         [VIRTUALIZATION_KVM] = "kvm",
+        [VIRTUALIZATION_AMAZON] = "amazon",
         [VIRTUALIZATION_QEMU] = "qemu",
         [VIRTUALIZATION_BOCHS] = "bochs",
         [VIRTUALIZATION_XEN] = "xen",
index 378c7c4d232a5b84ec8f2e4ea9baa944e04d1f42..1eafbe2cbecfc92bbc730430f39b5a6423a8a581 100644 (file)
@@ -10,6 +10,7 @@ enum {
 
         VIRTUALIZATION_VM_FIRST,
         VIRTUALIZATION_KVM = VIRTUALIZATION_VM_FIRST,
+        VIRTUALIZATION_AMAZON,
         VIRTUALIZATION_QEMU,
         VIRTUALIZATION_BOCHS,
         VIRTUALIZATION_XEN,
index f6b72e0bae865f3402716938f4298583aa4545e0..29530bb691c6c22c398a3067836ea6c4c7a0a0ed 100644 (file)
@@ -65,11 +65,12 @@ static int apply_rule(const char *rule) {
 
 static int apply_file(const char *path, bool ignore_enoent) {
         _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_free_ char *pp = NULL;
         int r;
 
         assert(path);
 
-        r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f);
+        r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f, &pp);
         if (r < 0) {
                 if (ignore_enoent && r == -ENOENT)
                         return 0;
@@ -77,7 +78,7 @@ static int apply_file(const char *path, bool ignore_enoent) {
                 return log_error_errno(r, "Failed to open file '%s': %m", path);
         }
 
-        log_debug("apply: %s", path);
+        log_debug("apply: %s", pp);
         for (;;) {
                 _cleanup_free_ char *line = NULL;
                 char *p;
@@ -85,7 +86,7 @@ static int apply_file(const char *path, bool ignore_enoent) {
 
                 k = read_line(f, LONG_LINE_MAX, &line);
                 if (k < 0)
-                        return log_error_errno(k, "Failed to read file '%s': %m", path);
+                        return log_error_errno(k, "Failed to read file '%s': %m", pp);
                 if (k == 0)
                         break;
 
index bd6f64915d3353bf9053aa6c78a800a69d150a1a..97ad1e0cb5016124e27681fe7b6919da52b3b366 100644 (file)
@@ -126,7 +126,7 @@ static int acquire_path(void) {
         strv_free_and_replace(arg_path, a);
 
         if (DEBUG_LOGGING) {
-                _cleanup_free_ char *j;
+                _cleanup_free_ char *j = NULL;
 
                 j = strv_join(arg_path, ":");
                 log_debug("Using %s as boot loader drop-in search path.", j);
index 04cc7664e512bc2657f0e1a1cb1cf98724ba8f7d..34f0c14b44af3e15889187ff2888905c8d6ff3f3 100644 (file)
@@ -29,6 +29,7 @@
 #include "main-func.h"
 #include "mkdir.h"
 #include "pager.h"
+#include "parse-argument.h"
 #include "parse-util.h"
 #include "pretty-print.h"
 #include "random-util.h"
@@ -52,6 +53,7 @@ static bool arg_print_dollar_boot_path = false;
 static bool arg_touch_variables = true;
 static PagerFlags arg_pager_flags = 0;
 static bool arg_graceful = false;
+static int arg_make_machine_id_directory = -1;
 
 STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep);
@@ -112,6 +114,19 @@ static int acquire_xbootldr(bool unprivileged_mode, sd_id128_t *ret_uuid) {
         return 1;
 }
 
+static void settle_make_machine_id_directory(void) {
+        int r;
+
+        if (arg_make_machine_id_directory >= 0)
+                return;
+
+        r = path_is_temporary_fs("/etc/machine-id");
+        if (r < 0)
+                log_debug_errno(r, "Couldn't determine whether /etc/machine-id is on a temporary file system, assuming so.");
+
+        arg_make_machine_id_directory = r == 0;
+}
+
 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
 static int get_file_version(int fd, char **v) {
         struct stat st;
@@ -312,7 +327,7 @@ static int status_variables(void) {
 }
 
 static int boot_entry_file_check(const char *root, const char *p) {
-        _cleanup_free_ char *path;
+        _cleanup_free_ char *path = NULL;
 
         path = path_join(root, p);
         if (!path)
@@ -888,6 +903,24 @@ static int remove_subdirs(const char *root, const char *const *subdirs) {
         return r < 0 ? r : q;
 }
 
+static int remove_machine_id_directory(const char *root) {
+        sd_id128_t machine_id;
+        char buf[SD_ID128_STRING_MAX];
+        int r;
+
+        assert(root);
+        assert(arg_make_machine_id_directory >= 0);
+
+        if (!arg_make_machine_id_directory)
+                return 0;
+
+        r = sd_id128_get_machine(&machine_id);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get machine id: %m");
+
+        return rmdir_one(root, sd_id128_to_string(machine_id, buf));
+}
+
 static int remove_binaries(const char *esp_path) {
         const char *p;
         int r, q;
@@ -974,9 +1007,13 @@ static int install_loader_config(const char *esp_path) {
         _cleanup_(unlink_and_freep) char *t = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_close_ int fd = -1;
+        sd_id128_t machine_id;
+        char machine_string[SD_ID128_STRING_MAX];
         const char *p;
         int r;
 
+        assert(arg_make_machine_id_directory >= 0);
+
         p = prefix_roota(esp_path, "/loader/loader.conf");
         if (access(p, F_OK) >= 0) /* Silently skip creation if the file already exists (early check) */
                 return 0;
@@ -991,6 +1028,13 @@ static int install_loader_config(const char *esp_path) {
 
         fprintf(f, "#timeout 3\n"
                    "#console-mode keep\n");
+        if (arg_make_machine_id_directory) {
+                r = sd_id128_get_machine(&machine_id);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to get machine id: %m");
+
+                fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string));
+        }
 
         r = fflush_sync_and_check(f);
         if (r < 0)
@@ -1006,6 +1050,24 @@ static int install_loader_config(const char *esp_path) {
         return 1;
 }
 
+static int install_machine_id_directory(const char *root) {
+        sd_id128_t machine_id;
+        char buf[SD_ID128_STRING_MAX];
+        int r;
+
+        assert(root);
+        assert(arg_make_machine_id_directory >= 0);
+
+        if (!arg_make_machine_id_directory)
+                return 0;
+
+        r = sd_id128_get_machine(&machine_id);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get machine id: %m");
+
+        return mkdir_one(root, sd_id128_to_string(machine_id, buf));
+}
+
 static int help(int argc, char *argv[], void *userdata) {
         _cleanup_free_ char *link = NULL;
         int r;
@@ -1043,6 +1105,8 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --no-pager        Do not pipe output into a pager\n"
                "     --graceful        Don't fail when the ESP cannot be found or EFI\n"
                "                       variables cannot be written\n"
+               "     --make-machine-id-directory=yes|no|auto\n"
+               "                       Create $BOOT/$MACHINE_ID\n"
                "\nSee the %2$s for details.\n",
                program_invocation_short_name,
                link,
@@ -1062,24 +1126,27 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_NO_VARIABLES,
                 ARG_NO_PAGER,
                 ARG_GRACEFUL,
+                ARG_MAKE_MACHINE_ID_DIRECTORY,
         };
 
         static const struct option options[] = {
-                { "help",            no_argument,       NULL, 'h'                 },
-                { "version",         no_argument,       NULL, ARG_VERSION         },
-                { "esp-path",        required_argument, NULL, ARG_ESP_PATH        },
-                { "path",            required_argument, NULL, ARG_ESP_PATH        }, /* Compatibility alias */
-                { "boot-path",       required_argument, NULL, ARG_BOOT_PATH       },
-                { "print-esp-path",  no_argument,       NULL, 'p'                 },
-                { "print-path",      no_argument,       NULL, 'p'                 }, /* Compatibility alias */
-                { "print-boot-path", no_argument,       NULL, 'x'                 },
-                { "no-variables",    no_argument,       NULL, ARG_NO_VARIABLES    },
-                { "no-pager",        no_argument,       NULL, ARG_NO_PAGER        },
-                { "graceful",        no_argument,       NULL, ARG_GRACEFUL        },
+                { "help",                      no_argument,       NULL, 'h'                           },
+                { "version",                   no_argument,       NULL, ARG_VERSION                   },
+                { "esp-path",                  required_argument, NULL, ARG_ESP_PATH                  },
+                { "path",                      required_argument, NULL, ARG_ESP_PATH                  }, /* Compatibility alias */
+                { "boot-path",                 required_argument, NULL, ARG_BOOT_PATH                 },
+                { "print-esp-path",            no_argument,       NULL, 'p'                           },
+                { "print-path",                no_argument,       NULL, 'p'                           }, /* Compatibility alias */
+                { "print-boot-path",           no_argument,       NULL, 'x'                           },
+                { "no-variables",              no_argument,       NULL, ARG_NO_VARIABLES              },
+                { "no-pager",                  no_argument,       NULL, ARG_NO_PAGER                  },
+                { "graceful",                  no_argument,       NULL, ARG_GRACEFUL                  },
+                { "make-machine-id-directory", required_argument, NULL, ARG_MAKE_MACHINE_ID_DIRECTORY },
                 {}
         };
 
         int c, r;
+        bool b;
 
         assert(argc >= 0);
         assert(argv);
@@ -1132,6 +1199,17 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_graceful = true;
                         break;
 
+                case ARG_MAKE_MACHINE_ID_DIRECTORY:
+                        if (streq(optarg, "auto"))
+                                arg_make_machine_id_directory = -1;  /* default */
+                        else {
+                                r = parse_boolean_argument("--make-machine-id-directory=", optarg, &b);
+                                if (r < 0)
+                                        return r;
+                                arg_make_machine_id_directory = b;
+                        }
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -1530,6 +1608,8 @@ static int verb_install(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
+        settle_make_machine_id_directory();
+
         install = streq(argv[0], "install");
 
         RUN_WITH_UMASK(0002) {
@@ -1555,6 +1635,10 @@ static int verb_install(int argc, char *argv[], void *userdata) {
                         if (r < 0)
                                 return r;
 
+                        r = install_machine_id_directory(arg_dollar_boot_path());
+                        if (r < 0)
+                                return r;
+
                         r = install_random_seed(arg_esp_path);
                         if (r < 0)
                                 return r;
@@ -1584,6 +1668,8 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
+        settle_make_machine_id_directory();
+
         r = remove_binaries(arg_esp_path);
 
         q = remove_file(arg_esp_path, "/loader/loader.conf");
@@ -1602,11 +1688,19 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
         if (q < 0 && r >= 0)
                 r = q;
 
+        q = remove_machine_id_directory(arg_esp_path);
+        if (q < 0 && r >= 0)
+                r = 1;
+
         if (arg_xbootldr_path) {
                 /* Remove the latter two also in the XBOOTLDR partition if it exists */
                 q = remove_subdirs(arg_xbootldr_path, dollar_boot_subdirs);
                 if (q < 0 && r >= 0)
                         r = q;
+
+                q = remove_machine_id_directory(arg_xbootldr_path);
+                if (q < 0 && r >= 0)
+                        r = q;
         }
 
         (void) sync_everything();
index 35248db009bf48cfd46c04fac961d7890c27bcc1..24efe5de1dbc61fac8969841b77401c0a83efa7f 100644 (file)
@@ -456,7 +456,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
 
                         device_path = DevicePathFromHandle(entry->device);
                         if (device_path) {
-                                _cleanup_freepool_ CHAR16 *str;
+                                _cleanup_freepool_ CHAR16 *str = NULL;
 
                                 str = DevicePathToStr(device_path);
                                 Print(L"device handle           '%s'\n", str);
index 2a37b0a9ac69f96689610ccb833882f6315b1564..47768931082f049818d57eb4aa85653b011106ee 100644 (file)
@@ -190,9 +190,9 @@ if have_gnu_efi
                        '-znocombreloc',
                        '-L', efi_libdir,
                        efi_crt0]
-        if efi_arch == 'aarch64' or efi_arch == 'arm'
-                # Aarch64 and ARM32 don't have an EFI capable objcopy. Use 'binary'
-                # instead, and add required symbols manually.
+        if ['aarch64', 'arm', 'riscv64'].contains(efi_arch)
+                # Aarch64, ARM32 and 64bit RISC-V don't have an EFI capable objcopy.
+                # Use 'binary' instead, and add required symbols manually.
                 efi_ldflags += ['--defsym=EFI_SUBSYSTEM=0xa']
                 efi_format = ['-O', 'binary']
         else
index b9541c31266ab6b68b000ade59353fc1f42bf844..8bdb16accf2d966d52f25a271efea9e2f319fbc2 100755 (executable)
@@ -1,8 +1,9 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
+set -o pipefail
 
-if nm -D -u "$1" | grep ' U '; then
+if nm -D -u "${1:?}" | grep ' U '; then
     echo "Undefined symbols detected!"
     exit 1
 fi
index cb3583807211d9fce7c0954e39aa9bd9a94a41dc..e65701734307a56e12b6b6143609e87d6192d3f1 100644 (file)
@@ -31,6 +31,8 @@ struct DosFileHeader {
 #define PE_HEADER_MACHINE_I386          0x014c
 #define PE_HEADER_MACHINE_X64           0x8664
 #define PE_HEADER_MACHINE_ARM64         0xaa64
+#define PE_HEADER_MACHINE_ARM           0x01c2
+#define PE_HEADER_MACHINE_RISCV64       0x5064
 struct PeFileHeader {
         UINT16  Machine;
         UINT16  NumberOfSections;
@@ -76,7 +78,9 @@ EFI_STATUS pe_memory_locate_sections(CHAR8 *base, CHAR8 **sections, UINTN *addrs
         /* PE32+ Subsystem type */
         if (pe->FileHeader.Machine != PE_HEADER_MACHINE_X64 &&
             pe->FileHeader.Machine != PE_HEADER_MACHINE_ARM64 &&
-            pe->FileHeader.Machine != PE_HEADER_MACHINE_I386)
+            pe->FileHeader.Machine != PE_HEADER_MACHINE_I386 &&
+            pe->FileHeader.Machine != PE_HEADER_MACHINE_ARM &&
+            pe->FileHeader.Machine != PE_HEADER_MACHINE_RISCV64)
                 return EFI_LOAD_ERROR;
 
         if (pe->FileHeader.NumberOfSections > 96)
index 1d9a5f07ab1ee61500afdebbf7bca13fa083a5e1..082fe91c9e5fd56599119d8a9e8f1a3980f2e86b 100644 (file)
@@ -92,7 +92,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
          * is non-NULL explicitly.) */
         if (efivar_get_raw(LOADER_GUID, L"LoaderImageIdentifier", NULL, NULL) != EFI_SUCCESS &&
             loaded_image->FilePath) {
-                _cleanup_freepool_ CHAR16 *s;
+                _cleanup_freepool_ CHAR16 *s = NULL;
 
                 s = DevicePathToStr(loaded_image->FilePath);
                 efivar_set(LOADER_GUID, L"LoaderImageIdentifier", s, 0);
@@ -100,7 +100,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
 
         /* if LoaderFirmwareInfo is not set, let's set it */
         if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) {
-                _cleanup_freepool_ CHAR16 *s;
+                _cleanup_freepool_ CHAR16 *s = NULL;
 
                 s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
                 efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", s, 0);
@@ -108,7 +108,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
 
         /* ditto for LoaderFirmwareType */
         if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) {
-                _cleanup_freepool_ CHAR16 *s;
+                _cleanup_freepool_ CHAR16 *s = NULL;
 
                 s = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
                 efivar_set(LOADER_GUID, L"LoaderFirmwareType", s, 0);
index 06fbd500e579c2db250301d70f2262c4abefe678..0061e03eba2eda2b593abc26cc4787cdaa22a8c1 100644 (file)
@@ -379,7 +379,7 @@ EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN s
                 return err;
 
         if (size == 0) {
-                _cleanup_freepool_ EFI_FILE_INFO *info;
+                _cleanup_freepool_ EFI_FILE_INFO *info = NULL;
 
                 info = LibFileInfo(handle);
                 if (!info)
index cbc24bc2517f32300916551fc5f7e6b1a9a244ab..f081e98ae02e5589df817c3f4f8fdbddaf10a188 100644 (file)
@@ -797,7 +797,7 @@ static Set* member_set_free(Set *s) {
 DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, member_set_free);
 
 static int on_interface(const char *interface, uint64_t flags, void *userdata) {
-        _cleanup_(member_freep) Member *m;
+        _cleanup_(member_freep) Member *m = NULL;
         Set *members = userdata;
         int r;
 
@@ -828,7 +828,7 @@ static int on_interface(const char *interface, uint64_t flags, void *userdata) {
 }
 
 static int on_method(const char *interface, const char *name, const char *signature, const char *result, uint64_t flags, void *userdata) {
-        _cleanup_(member_freep) Member *m;
+        _cleanup_(member_freep) Member *m = NULL;
         Set *members = userdata;
         int r;
 
@@ -871,7 +871,7 @@ static int on_method(const char *interface, const char *name, const char *signat
 }
 
 static int on_signal(const char *interface, const char *name, const char *signature, uint64_t flags, void *userdata) {
-        _cleanup_(member_freep) Member *m;
+        _cleanup_(member_freep) Member *m = NULL;
         Set *members = userdata;
         int r;
 
@@ -910,7 +910,7 @@ static int on_signal(const char *interface, const char *name, const char *signat
 }
 
 static int on_property(const char *interface, const char *name, const char *signature, bool writable, uint64_t flags, void *userdata) {
-        _cleanup_(member_freep) Member *m;
+        _cleanup_(member_freep) Member *m = NULL;
         Set *members = userdata;
         int r;
 
index f0fa5c8ca987ea5cc1fbe33c120f43030708a2f6..dc92f9c0e4456f0411affc27985081bb288f6fb9 100644 (file)
@@ -651,7 +651,7 @@ fail:
 
 static void *expire_thread(void *p) {
         struct autofs_dev_ioctl param;
-        _cleanup_(expire_data_freep) struct expire_data *data = (struct expire_data*)p;
+        _cleanup_(expire_data_freep) struct expire_data *data = p;
         int r;
 
         assert(data->dev_autofs_fd >= 0);
index 1ad7ade3065d0a469d2b61730ce45b286a68efb5..8a345a44981cba862f8f386c7449068ab5c00191 100644 (file)
@@ -216,7 +216,7 @@ int bpf_devices_apply_policy(
         _cleanup_free_ char *controller_path = NULL;
         int r;
 
-        /* This will assign *keep_program if everything goes well. */
+        /* This will assign *prog_installed if everything goes well. */
 
         if (!prog)
                 goto finish;
index 0f588b6ca5fce2e64aa23f04ff6bdacc2068b376..02e33399c3e36615f9b0932bfbdd0e7363608221 100644 (file)
@@ -698,8 +698,7 @@ int bpf_firewall_install(Unit *u) {
         if (r < 0)
                 return log_unit_error_errno(u, r, "Failed to determine cgroup path: %m");
 
-        flags = (supported == BPF_FIREWALL_SUPPORTED_WITH_MULTI &&
-                 (u->type == UNIT_SLICE || unit_cgroup_delegate(u))) ? BPF_F_ALLOW_MULTI : 0;
+        flags = supported == BPF_FIREWALL_SUPPORTED_WITH_MULTI ? BPF_F_ALLOW_MULTI : 0;
 
         /* Unref the old BPF program (which will implicitly detach it) right before attaching the new program, to
          * minimize the time window when we don't account for IP traffic. */
@@ -707,8 +706,7 @@ int bpf_firewall_install(Unit *u) {
         u->ip_bpf_ingress_installed = bpf_program_unref(u->ip_bpf_ingress_installed);
 
         if (u->ip_bpf_egress) {
-                r = bpf_program_cgroup_attach(u->ip_bpf_egress, BPF_CGROUP_INET_EGRESS, path,
-                                              flags | (set_isempty(u->ip_bpf_custom_egress) ? 0 : BPF_F_ALLOW_MULTI));
+                r = bpf_program_cgroup_attach(u->ip_bpf_egress, BPF_CGROUP_INET_EGRESS, path, flags);
                 if (r < 0)
                         return log_unit_error_errno(u, r, "Attaching egress BPF program to cgroup %s failed: %m", path);
 
@@ -717,8 +715,7 @@ int bpf_firewall_install(Unit *u) {
         }
 
         if (u->ip_bpf_ingress) {
-                r = bpf_program_cgroup_attach(u->ip_bpf_ingress, BPF_CGROUP_INET_INGRESS, path,
-                                              flags | (set_isempty(u->ip_bpf_custom_ingress) ? 0 : BPF_F_ALLOW_MULTI));
+                r = bpf_program_cgroup_attach(u->ip_bpf_ingress, BPF_CGROUP_INET_INGRESS, path, flags);
                 if (r < 0)
                         return log_unit_error_errno(u, r, "Attaching ingress BPF program to cgroup %s failed: %m", path);
 
diff --git a/src/core/bpf-foreign.c b/src/core/bpf-foreign.c
new file mode 100644 (file)
index 0000000..98655bd
--- /dev/null
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bpf-foreign.h"
+#include "bpf-program.h"
+#include "cgroup.h"
+#include "memory-util.h"
+#include "mountpoint-util.h"
+#include "set.h"
+
+typedef struct BPFForeignKey BPFForeignKey;
+struct BPFForeignKey {
+        uint32_t prog_id;
+        uint32_t attach_type;
+};
+
+static int bpf_foreign_key_new(uint32_t prog_id,
+                enum bpf_attach_type attach_type,
+                BPFForeignKey **ret) {
+        _cleanup_free_ BPFForeignKey *p = NULL;
+
+        assert(ret);
+
+        p = new(BPFForeignKey, 1);
+        if (!p)
+                return log_oom();
+
+        *p = (BPFForeignKey) {
+                .prog_id = prog_id,
+                .attach_type = attach_type,
+        };
+
+        *ret = TAKE_PTR(p);
+
+        return 0;
+}
+
+static int bpf_foreign_key_compare_func(const BPFForeignKey *a, const BPFForeignKey *b) {
+        int r = CMP(a->prog_id, b->prog_id);
+        if (r != 0)
+                return r;
+
+        return CMP(a->attach_type, b->attach_type);
+}
+
+static void bpf_foreign_key_hash_func(const BPFForeignKey *p, struct siphash *h) {
+        siphash24_compress(&p->prog_id, sizeof(p->prog_id), h);
+        siphash24_compress(&p->attach_type, sizeof(p->attach_type), h);
+}
+
+DEFINE_PRIVATE_HASH_OPS_FULL(bpf_foreign_by_key_hash_ops,
+                BPFForeignKey, bpf_foreign_key_hash_func, bpf_foreign_key_compare_func, free,
+                BPFProgram, bpf_program_unref);
+
+static int attach_programs(Unit *u, const char *path, Hashmap* foreign_by_key, uint32_t attach_flags) {
+        const BPFForeignKey *key;
+        BPFProgram *prog;
+        int r;
+
+        assert(u);
+
+        HASHMAP_FOREACH_KEY(prog, key, foreign_by_key) {
+                r = bpf_program_cgroup_attach(prog, key->attach_type, path, attach_flags);
+                if (r < 0)
+                        return log_unit_error_errno(u, r, "Attaching foreign BPF program to cgroup %s failed: %m", path);
+        }
+
+        return 0;
+}
+
+/*
+ * Prepare foreign BPF program for installation:
+ * - Load the program from BPF filesystem to the kernel;
+ * - Store program FD identified by program ID and attach type in the unit.
+ */
+static int bpf_foreign_prepare(
+                Unit *u,
+                enum bpf_attach_type attach_type,
+                const char *bpffs_path) {
+        _cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL;
+        _cleanup_free_ BPFForeignKey *key = NULL;
+        uint32_t prog_id;
+        int r;
+
+        assert(u);
+        assert(bpffs_path);
+
+        r = bpf_program_new_from_bpffs_path(bpffs_path, &prog);
+        if (r < 0)
+                return log_unit_error_errno(u, r, "Failed to create foreign BPFProgram: %m");
+
+        r = bpf_program_get_id_by_fd(prog->kernel_fd, &prog_id);
+        if (r < 0)
+                return log_unit_error_errno(u, r, "Failed to get BPF program id by fd: %m");
+
+        r = bpf_foreign_key_new(prog_id, attach_type, &key);
+        if (r < 0)
+                return log_unit_error_errno(u, r,
+                                "Failed to create foreign BPF program key from path '%s': %m", bpffs_path);
+
+        r = hashmap_ensure_put(&u->bpf_foreign_by_key, &bpf_foreign_by_key_hash_ops, key, prog);
+        if (r == -EEXIST) {
+                log_unit_warning_errno(u, r, "Foreign BPF program already exists, ignoring: %m");
+                return 0;
+        }
+        if (r < 0)
+                return log_unit_error_errno(u, r, "Failed to put foreign BPFProgram into map: %m");
+
+        TAKE_PTR(key);
+        TAKE_PTR(prog);
+
+        return 0;
+}
+
+int bpf_foreign_supported(void) {
+        int r;
+
+        r = cg_all_unified();
+        if (r <= 0)
+                return r;
+
+        return path_is_mount_point("/sys/fs/bpf", NULL, 0);
+}
+
+int bpf_foreign_install(Unit *u) {
+        _cleanup_free_ char *cgroup_path = NULL;
+        CGroupBPFForeignProgram *p;
+        CGroupContext *cc;
+        int r;
+
+        assert(u);
+
+        cc = unit_get_cgroup_context(u);
+        if (!cc)
+                return 0;
+
+        r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &cgroup_path);
+        if (r < 0)
+                return log_unit_error_errno(u, r, "Failed to get cgroup path: %m");
+
+        LIST_FOREACH(programs, p, cc->bpf_foreign_programs) {
+                r = bpf_foreign_prepare(u, p->attach_type, p->bpffs_path);
+                if (r < 0)
+                        return log_unit_error_errno(u, r, "Failed to prepare foreign BPF hashmap: %m");
+        }
+
+        r = attach_programs(u, cgroup_path, u->bpf_foreign_by_key, BPF_F_ALLOW_MULTI);
+        if (r < 0)
+                  return log_unit_error_errno(u, r, "Failed to install foreign BPF programs: %m");
+
+        return 0;
+}
diff --git a/src/core/bpf-foreign.h b/src/core/bpf-foreign.h
new file mode 100644 (file)
index 0000000..7704986
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#pragma once
+
+#include "unit.h"
+
+int bpf_foreign_supported(void);
+/*
+ * Attach cgroup-bpf programs foreign to systemd, i.e. loaded to the kernel by an entity
+ * external to systemd.
+ */
+int bpf_foreign_install(Unit *u);
diff --git a/src/core/bpf/socket_bind/meson.build b/src/core/bpf/socket_bind/meson.build
new file mode 100644 (file)
index 0000000..0ea8e57
--- /dev/null
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+if conf.get('BPF_FRAMEWORK') == 1
+        socket_bind_skel_h = custom_target(
+                'socket-bind.skel.h',
+                input : 'socket-bind.bpf.c',
+                output : 'socket-bind.skel.h',
+                command : [build_bpf_skel_py,
+                           '--clang_exec', clang.path(),
+                           '--llvm_strip_exec', llvm_strip.path(),
+                           '--bpftool_exec', bpftool.path(),
+                           '--arch', host_machine.cpu_family(),
+                           '@INPUT@', '@OUTPUT@'])
+endif
diff --git a/src/core/bpf/socket_bind/socket-bind-api.bpf.h b/src/core/bpf/socket_bind/socket-bind-api.bpf.h
new file mode 100644 (file)
index 0000000..4188899
--- /dev/null
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+/* The SPDX header above is actually correct in claiming this was
+ * LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
+ * compatible with GPL we will claim this to be GPL however, which should be
+ * fine given that LGPL-2.1-or-later downgrades to GPL if needed.
+ */
+
+#include <linux/types.h>
+
+/*
+ * Bind rule is matched with socket fields accessible to cgroup/bind{4,6} hook
+ * through bpf_sock_addr struct.
+ * address_family is expected to be one of AF_UNSPEC, AF_INET or AF_INET6.
+ * Matching by family is bypassed for rules with AF_UNSPEC set, which makes the
+ * rest of a rule applicable for both IPv4 and IPv6 addresses.
+ * If matching by family is either successful or bypassed, a rule and a socket
+ * are matched by ports.
+ * nr_ports and port_min fields specify a set of ports to match a user port
+ * with.
+ * If nr_ports is 0, matching by port is bypassed, making that rule applicable
+ * for all possible ports, e.g. [1, 65535] range. Thus a rule with
+ * address_family and nr_ports equal to AF_UNSPEC and 0 correspondingly forms
+ * 'allow any' or 'deny any' cases.
+ * For positive nr_ports, a user_port lying in a range from port_min to
+ * port_min + nr_ports exclusively is considered to be a match. nr_ports
+ * equalling to 1 forms a rule for a single port.
+ * Ports are in host order.
+ *
+ * Examples:
+ * AF_UNSPEC, 1, 7777: match IPv4 and IPv6 addresses with 7777 user port;
+ *
+ * AF_INET, 1023, 1: match IPv4 addresses with user port in [1, 1023]
+ * range inclusively;
+ *
+ * AF_INET6, 0, 0: match IPv6 addresses;
+ *
+ * AF_UNSPEC, 0, 0: match IPv4 and IPv6 addresses.
+ */
+
+struct socket_bind_rule {
+        __u32 address_family;
+        __u16 nr_ports;
+        __u16 port_min;
+};
+
+#define SOCKET_BIND_MAX_RULES 128
diff --git a/src/core/bpf/socket_bind/socket-bind.bpf.c b/src/core/bpf/socket_bind/socket-bind.bpf.c
new file mode 100644 (file)
index 0000000..474808d
--- /dev/null
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+/* The SPDX header above is actually correct in claiming this was
+ * LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
+ * compatible with GPL we will claim this to be GPL however, which should be
+ * fine given that LGPL-2.1-or-later downgrades to GPL if needed.
+ */
+
+#include "socket-bind-api.bpf.h"
+/* <linux/types.h> must precede <bpf/bpf_helpers.h> due to
+ * <bpf/bpf_helpers.h> does not depend from type header by design.
+ */
+#include <linux/types.h>
+#include <bpf/bpf_endian.h>
+#include <bpf/bpf_helpers.h>
+#include <linux/bpf.h>
+#include <netinet/in.h>
+#include <stdbool.h>
+
+/*
+ * max_entries is set from user space with bpf_map__resize helper.
+ */
+struct socket_bind_map_t {
+        __uint(type, BPF_MAP_TYPE_ARRAY);
+        __type(key, __u32);
+        __type(value, struct socket_bind_rule);
+};
+
+enum socket_bind_action {
+        SOCKET_BIND_DENY = 0,
+        SOCKET_BIND_ALLOW = 1,
+};
+
+struct socket_bind_map_t sd_bind_allow SEC(".maps");
+struct socket_bind_map_t sd_bind_deny SEC(".maps");
+
+static __always_inline bool match_af(
+                __u8 address_family, const struct socket_bind_rule *r) {
+        return r->address_family == AF_UNSPEC || address_family == r->address_family;
+}
+
+static __always_inline bool match_user_port(
+                __u16 port, const struct socket_bind_rule *r) {
+        return r->nr_ports == 0 ||
+                (port >= r->port_min && port < r->port_min + (__u32) r->nr_ports);
+}
+
+static __always_inline bool match(
+                __u8 address_family,
+                __u16 port,
+                const struct socket_bind_rule *r) {
+        return match_af(address_family, r) && match_user_port(port, r);
+}
+
+static __always_inline bool match_rules(
+                struct bpf_sock_addr *ctx,
+                struct socket_bind_map_t *rules) {
+        volatile __u32 user_port = ctx->user_port;
+        __u16 port = (__u16)bpf_ntohs(user_port);
+
+        for (__u32 i = 0; i < SOCKET_BIND_MAX_RULES; ++i) {
+                const __u32 key = i;
+                const struct socket_bind_rule *rule = bpf_map_lookup_elem(rules, &key);
+
+                /* Lookup returns NULL if iterator is advanced past the last
+                 * element put in the map. */
+                if (!rule)
+                        break;
+
+                if (match(ctx->user_family, port, rule))
+                        return true;
+        }
+
+        return false;
+}
+
+static __always_inline int bind_socket(struct bpf_sock_addr *ctx) {
+        if (match_rules(ctx, &sd_bind_allow))
+                return SOCKET_BIND_ALLOW;
+
+        if (match_rules(ctx, &sd_bind_deny))
+                return SOCKET_BIND_DENY;
+
+        return SOCKET_BIND_ALLOW;
+}
+
+SEC("cgroup/bind4")
+int sd_bind4(struct bpf_sock_addr *ctx) {
+        if (ctx->user_family != AF_INET || ctx->family != AF_INET)
+                return SOCKET_BIND_ALLOW;
+
+        return bind_socket(ctx);
+}
+
+SEC("cgroup/bind6")
+int sd_bind6(struct bpf_sock_addr *ctx) {
+        if (ctx->user_family != AF_INET6 || ctx->family != AF_INET6)
+                return SOCKET_BIND_ALLOW;
+
+        return bind_socket(ctx);
+}
+
+char _license[] SEC("license") = "GPL";
index 96073b108b2e7674e88bd4b4936cf64bb0967a3a..a44cf9368c71a49a9a8d648b06da54e6059f1c37 100644 (file)
@@ -8,6 +8,7 @@
 #include "blockdev-util.h"
 #include "bpf-devices.h"
 #include "bpf-firewall.h"
+#include "bpf-foreign.h"
 #include "btrfs-util.h"
 #include "bus-error.h"
 #include "cgroup-setup.h"
@@ -24,6 +25,7 @@
 #include "percent-util.h"
 #include "process-util.h"
 #include "procfs-util.h"
+#include "socket-bind.h"
 #include "special.h"
 #include "stat-util.h"
 #include "stdio-util.h"
@@ -190,6 +192,27 @@ void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockI
         free(b);
 }
 
+void cgroup_context_remove_bpf_foreign_program(CGroupContext *c, CGroupBPFForeignProgram *p) {
+        assert(c);
+        assert(p);
+
+        LIST_REMOVE(programs, c->bpf_foreign_programs, p);
+        free(p->bpffs_path);
+        free(p);
+}
+
+void cgroup_context_remove_socket_bind(CGroupSocketBindItem **head) {
+        CGroupSocketBindItem *h;
+
+        assert(head);
+
+        while (*head) {
+                h = *head;
+                LIST_REMOVE(socket_bind_items, *head, h);
+                free(h);
+        }
+}
+
 void cgroup_context_done(CGroupContext *c) {
         assert(c);
 
@@ -211,12 +234,18 @@ void cgroup_context_done(CGroupContext *c) {
         while (c->device_allow)
                 cgroup_context_free_device_allow(c, c->device_allow);
 
+        cgroup_context_remove_socket_bind(&c->socket_bind_allow);
+        cgroup_context_remove_socket_bind(&c->socket_bind_deny);
+
         c->ip_address_allow = ip_address_access_free_all(c->ip_address_allow);
         c->ip_address_deny = ip_address_access_free_all(c->ip_address_deny);
 
         c->ip_filters_ingress = strv_free(c->ip_filters_ingress);
         c->ip_filters_egress = strv_free(c->ip_filters_egress);
 
+        while (c->bpf_foreign_programs)
+                cgroup_context_remove_bpf_foreign_program(c, c->bpf_foreign_programs);
+
         cpu_set_reset(&c->cpuset_cpus);
         cpu_set_reset(&c->cpuset_mems);
 }
@@ -276,8 +305,7 @@ static int unit_compare_memory_limit(Unit *u, const char *property_name, uint64_
         if (!FLAGS_SET(m, CGROUP_MASK_MEMORY))
                 return -ENODATA;
 
-        c = unit_get_cgroup_context(u);
-        assert(c);
+        assert_se(c = unit_get_cgroup_context(u));
 
         if (streq(property_name, "MemoryLow")) {
                 unit_value = unit_get_ancestor_memory_low(u);
@@ -360,8 +388,10 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
         CGroupIODeviceLatency *l;
         CGroupBlockIODeviceBandwidth *b;
         CGroupBlockIODeviceWeight *w;
+        CGroupBPFForeignProgram *p;
         CGroupDeviceAllow *a;
         CGroupContext *c;
+        CGroupSocketBindItem *bi;
         IPAddressAccessItem *iaai;
         char **path;
         char q[FORMAT_TIMESPAN_MAX];
@@ -376,8 +406,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
         assert(u);
         assert(f);
 
-        c = unit_get_cgroup_context(u);
-        assert(c);
+        assert_se(c = unit_get_cgroup_context(u));
 
         prefix = strempty(prefix);
 
@@ -420,7 +449,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
                 "%sManagedOOMSwap: %s\n"
                 "%sManagedOOMMemoryPressure: %s\n"
                 "%sManagedOOMMemoryPressureLimit: " PERMYRIAD_AS_PERCENT_FORMAT_STR "\n"
-                "%sManagedOOMPreference: %s%%\n",
+                "%sManagedOOMPreference: %s\n",
                 prefix, yes_no(c->cpu_accounting),
                 prefix, yes_no(c->io_accounting),
                 prefix, yes_no(c->blockio_accounting),
@@ -544,6 +573,38 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
 
         STRV_FOREACH(path, c->ip_filters_egress)
                 fprintf(f, "%sIPEgressFilterPath: %s\n", prefix, *path);
+
+        LIST_FOREACH(programs, p, c->bpf_foreign_programs)
+                fprintf(f, "%sBPFProgram: %s:%s",
+                        prefix, bpf_cgroup_attach_type_to_string(p->attach_type), p->bpffs_path);
+
+        if (c->socket_bind_allow) {
+                fprintf(f, "%sSocketBindAllow:", prefix);
+                LIST_FOREACH(socket_bind_items, bi, c->socket_bind_allow)
+                        cgroup_context_dump_socket_bind_item(bi, f);
+                fputc('\n', f);
+        }
+
+        if (c->socket_bind_deny) {
+                fprintf(f, "%sSocketBindDeny:", prefix);
+                LIST_FOREACH(socket_bind_items, bi, c->socket_bind_deny)
+                        cgroup_context_dump_socket_bind_item(bi, f);
+                fputc('\n', f);
+        }
+}
+
+void cgroup_context_dump_socket_bind_item(const CGroupSocketBindItem *item, FILE *f) {
+        const char *family = item->address_family == AF_INET ? "IPv4:" :
+                item->address_family == AF_INET6 ? "IPv6:" : "";
+
+        if (item->nr_ports == 0)
+                fprintf(f, " %sany", family);
+        else if (item->nr_ports == 1)
+                fprintf(f, " %s%" PRIu16, family, item->port_min);
+        else {
+                uint16_t port_max = item->port_min + item->nr_ports - 1;
+                fprintf(f, " %s%" PRIu16 "-%" PRIu16, family, item->port_min, port_max);
+        }
 }
 
 int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode) {
@@ -575,6 +636,34 @@ int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode)
         return 0;
 }
 
+int cgroup_add_bpf_foreign_program(CGroupContext *c, uint32_t attach_type, const char *bpffs_path) {
+        CGroupBPFForeignProgram *p;
+        _cleanup_free_ char *d = NULL;
+
+        assert(c);
+        assert(bpffs_path);
+
+        if (!path_is_normalized(bpffs_path) || !path_is_absolute(bpffs_path))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Path is not normalized: %m");
+
+        d = strdup(bpffs_path);
+        if (!d)
+                return log_oom();
+
+        p = new(CGroupBPFForeignProgram, 1);
+        if (!p)
+                return log_oom();
+
+        *p = (CGroupBPFForeignProgram) {
+                .attach_type = attach_type,
+                .bpffs_path = TAKE_PTR(d),
+        };
+
+        LIST_PREPEND(programs, c->bpf_foreign_programs, TAKE_PTR(p));
+
+        return 0;
+}
+
 #define UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(entry)                       \
         uint64_t unit_get_ancestor_##entry(Unit *u) {                   \
                 CGroupContext *c;                                       \
@@ -937,17 +1026,14 @@ static void cgroup_apply_io_device_latency(Unit *u, const char *dev_path, usec_t
 }
 
 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;
+        char limit_bufs[_CGROUP_IO_LIMIT_TYPE_MAX][DECIMAL_STR_MAX(uint64_t)],
+             buf[DECIMAL_STR_MAX(dev_t)*2+2+(6+DECIMAL_STR_MAX(uint64_t)+1)*4];
         dev_t dev;
-        int r;
 
-        r = lookup_block_device(dev_path, &dev);
-        if (r < 0)
+        if (lookup_block_device(dev_path, &dev) < 0)
                 return;
 
-        for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
+        for (CGroupIOLimitType type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
                 if (limits[type] != cgroup_io_limit_defaults[type])
                         xsprintf(limit_bufs[type], "%" PRIu64, limits[type]);
                 else
@@ -962,10 +1048,8 @@ static void cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t
 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;
-        int r;
 
-        r = lookup_block_device(dev_path, &dev);
-        if (r < 0)
+        if (lookup_block_device(dev_path, &dev) < 0)
                 return;
 
         sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), rbps);
@@ -980,8 +1064,7 @@ static bool unit_has_unified_memory_config(Unit *u) {
 
         assert(u);
 
-        c = unit_get_cgroup_context(u);
-        assert(c);
+        assert_se(c = unit_get_cgroup_context(u));
 
         return unit_get_ancestor_memory_min(u) > 0 || unit_get_ancestor_memory_low(u) > 0 ||
                c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX ||
@@ -1009,6 +1092,12 @@ static void cgroup_apply_firewall(Unit *u) {
         (void) bpf_firewall_install(u);
 }
 
+static void cgroup_apply_socket_bind(Unit *u) {
+        assert(u);
+
+        (void) socket_bind_install(u);
+}
+
 static int cgroup_apply_devices(Unit *u) {
         _cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL;
         const char *path;
@@ -1115,6 +1204,12 @@ static void set_io_weight(Unit *u, const char *controller, uint64_t weight) {
         (void) set_attribute_and_warn(u, controller, p, buf);
 }
 
+static void cgroup_apply_bpf_foreign_program(Unit *u) {
+        assert(u);
+
+        (void) bpf_foreign_install(u);
+}
+
 static void cgroup_context_apply(
                 Unit *u,
                 CGroupMask apply_mask,
@@ -1428,6 +1523,12 @@ static void cgroup_context_apply(
 
         if (apply_mask & CGROUP_MASK_BPF_FIREWALL)
                 cgroup_apply_firewall(u);
+
+        if (apply_mask & CGROUP_MASK_BPF_FOREIGN)
+                cgroup_apply_bpf_foreign_program(u);
+
+        if (apply_mask & CGROUP_MASK_BPF_SOCKET_BIND)
+                cgroup_apply_socket_bind(u);
 }
 
 static bool unit_get_needs_bpf_firewall(Unit *u) {
@@ -1460,15 +1561,35 @@ static bool unit_get_needs_bpf_firewall(Unit *u) {
         return false;
 }
 
-static CGroupMask unit_get_cgroup_mask(Unit *u) {
-        CGroupMask mask = 0;
+static bool unit_get_needs_bpf_foreign_program(Unit *u) {
         CGroupContext *c;
+        assert(u);
 
+        c = unit_get_cgroup_context(u);
+        if (!c)
+                return false;
+
+        return !LIST_IS_EMPTY(c->bpf_foreign_programs);
+}
+
+static bool unit_get_needs_socket_bind(Unit *u) {
+        CGroupContext *c;
         assert(u);
 
         c = unit_get_cgroup_context(u);
+        if (!c)
+                return false;
 
-        assert(c);
+        return c->socket_bind_allow != NULL || c->socket_bind_deny != NULL;
+}
+
+static CGroupMask unit_get_cgroup_mask(Unit *u) {
+        CGroupMask mask = 0;
+        CGroupContext *c;
+
+        assert(u);
+
+        assert_se(c = unit_get_cgroup_context(u));
 
         /* Figure out which controllers we need, based on the cgroup context object */
 
@@ -1511,6 +1632,12 @@ static CGroupMask unit_get_bpf_mask(Unit *u) {
         if (unit_get_needs_bpf_firewall(u))
                 mask |= CGROUP_MASK_BPF_FIREWALL;
 
+        if (unit_get_needs_bpf_foreign_program(u))
+                mask |= CGROUP_MASK_BPF_FOREIGN;
+
+        if (unit_get_needs_socket_bind(u))
+                mask |= CGROUP_MASK_BPF_SOCKET_BIND;
+
         return mask;
 }
 
@@ -2786,11 +2913,10 @@ int unit_check_oomd_kill(Unit *u) {
                 return 0;
 
         if (n > 0)
-                log_struct(LOG_NOTICE,
-                           "MESSAGE_ID=" SD_MESSAGE_UNIT_OOMD_KILL_STR,
-                           LOG_UNIT_ID(u),
-                           LOG_UNIT_INVOCATION_ID(u),
-                           LOG_UNIT_MESSAGE(u, "systemd-oomd killed %"PRIu64" process(es) in this unit.", n));
+                log_unit_struct(u, LOG_NOTICE,
+                                "MESSAGE_ID=" SD_MESSAGE_UNIT_OOMD_KILL_STR,
+                                LOG_UNIT_INVOCATION_ID(u),
+                                LOG_UNIT_MESSAGE(u, "systemd-oomd killed %"PRIu64" process(es) in this unit.", n));
 
         return 1;
 }
@@ -2818,11 +2944,10 @@ int unit_check_oom(Unit *u) {
         if (!increased)
                 return 0;
 
-        log_struct(LOG_NOTICE,
-                   "MESSAGE_ID=" SD_MESSAGE_UNIT_OUT_OF_MEMORY_STR,
-                   LOG_UNIT_ID(u),
-                   LOG_UNIT_INVOCATION_ID(u),
-                   LOG_UNIT_MESSAGE(u, "A process of this unit has been killed by the OOM killer."));
+        log_unit_struct(u, LOG_NOTICE,
+                        "MESSAGE_ID=" SD_MESSAGE_UNIT_OUT_OF_MEMORY_STR,
+                        LOG_UNIT_INVOCATION_ID(u),
+                        LOG_UNIT_MESSAGE(u, "A process of this unit has been killed by the OOM killer."));
 
         if (UNIT_VTABLE(u)->notify_cgroup_oom)
                 UNIT_VTABLE(u)->notify_cgroup_oom(u);
@@ -2989,6 +3114,16 @@ static int cg_bpf_mask_supported(CGroupMask *ret) {
         if (r > 0)
                 mask |= CGROUP_MASK_BPF_DEVICES;
 
+        /* BPF pinned prog */
+        r = bpf_foreign_supported();
+        if (r > 0)
+                mask |= CGROUP_MASK_BPF_FOREIGN;
+
+        /* BPF-based bind{4|6} hooks */
+        r = socket_bind_supported();
+        if (r > 0)
+                mask |= CGROUP_MASK_BPF_SOCKET_BIND;
+
         *ret = mask;
         return 0;
 }
index fa79ba15239e80407e3158343ce112f0c2bd039e..1ad5dd38389886b3aed94b6b21e2c78b66e219f4 100644 (file)
@@ -31,6 +31,8 @@ typedef struct CGroupIODeviceLimit CGroupIODeviceLimit;
 typedef struct CGroupIODeviceLatency CGroupIODeviceLatency;
 typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight;
 typedef struct CGroupBlockIODeviceBandwidth CGroupBlockIODeviceBandwidth;
+typedef struct CGroupBPFForeignProgram CGroupBPFForeignProgram;
+typedef struct CGroupSocketBindItem CGroupSocketBindItem;
 
 typedef enum CGroupDevicePolicy {
         /* When devices listed, will allow those, plus built-in ones, if none are listed will allow
@@ -94,6 +96,19 @@ struct CGroupBlockIODeviceBandwidth {
         uint64_t wbps;
 };
 
+struct CGroupBPFForeignProgram {
+        LIST_FIELDS(CGroupBPFForeignProgram, programs);
+        uint32_t attach_type;
+        char *bpffs_path;
+};
+
+struct CGroupSocketBindItem {
+        LIST_FIELDS(CGroupSocketBindItem, socket_bind_items);
+        int address_family;
+        uint16_t nr_ports;
+        uint16_t port_min;
+};
+
 struct CGroupContext {
         bool cpu_accounting;
         bool io_accounting;
@@ -142,6 +157,7 @@ struct CGroupContext {
 
         char **ip_filters_ingress;
         char **ip_filters_egress;
+        LIST_HEAD(CGroupBPFForeignProgram, bpf_foreign_programs);
 
         /* For legacy hierarchies */
         uint64_t cpu_shares;
@@ -157,6 +173,9 @@ struct CGroupContext {
         CGroupDevicePolicy device_policy;
         LIST_HEAD(CGroupDeviceAllow, device_allow);
 
+        LIST_HEAD(CGroupSocketBindItem, socket_bind_allow);
+        LIST_HEAD(CGroupSocketBindItem, socket_bind_deny);
+
         /* Common */
         TasksMax tasks_max;
 
@@ -195,6 +214,7 @@ usec_t cgroup_cpu_adjust_period(usec_t period, usec_t quota, usec_t resolution,
 void cgroup_context_init(CGroupContext *c);
 void cgroup_context_done(CGroupContext *c);
 void cgroup_context_dump(Unit *u, FILE* f, const char *prefix);
+void cgroup_context_dump_socket_bind_item(const CGroupSocketBindItem *item, FILE *f);
 
 void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a);
 void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight *w);
@@ -202,8 +222,11 @@ void cgroup_context_free_io_device_limit(CGroupContext *c, CGroupIODeviceLimit *
 void cgroup_context_free_io_device_latency(CGroupContext *c, CGroupIODeviceLatency *l);
 void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w);
 void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b);
+void cgroup_context_remove_bpf_foreign_program(CGroupContext *c, CGroupBPFForeignProgram *p);
+void cgroup_context_remove_socket_bind(CGroupSocketBindItem **head);
 
 int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode);
+int cgroup_add_bpf_foreign_program(CGroupContext *c, uint32_t attach_type, const char *path);
 
 void cgroup_oomd_xattr_apply(Unit *u, const char *cgroup_path);
 
index 04d2ba34f30f6e9a1fbf7db93ad4bf3d7d7eb41c..d7f03d0cfdb492e2807cbb8acdb3812db4e603bf 100644 (file)
@@ -5,6 +5,7 @@
 #include "af-list.h"
 #include "alloc-util.h"
 #include "bpf-firewall.h"
+#include "bpf-foreign.h"
 #include "bus-get-properties.h"
 #include "cgroup-util.h"
 #include "cgroup.h"
@@ -15,6 +16,7 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "limits-util.h"
+#include "parse-util.h"
 #include "path-util.h"
 #include "percent-util.h"
 
@@ -347,6 +349,59 @@ static int property_get_ip_address_access(
         return sd_bus_message_close_container(reply);
 }
 
+static int property_get_bpf_foreign_program(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+        CGroupContext *c = userdata;
+        CGroupBPFForeignProgram *p;
+        int r;
+
+        r = sd_bus_message_open_container(reply, 'a', "(ss)");
+        if (r < 0)
+                return r;
+
+        LIST_FOREACH(programs, p, c->bpf_foreign_programs) {
+                const char *attach_type = bpf_cgroup_attach_type_to_string(p->attach_type);
+
+                r = sd_bus_message_append(reply, "(ss)", attach_type, p->bpffs_path);
+                if (r < 0)
+                        return r;
+        }
+
+        return sd_bus_message_close_container(reply);
+}
+
+static int property_get_socket_bind(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+        CGroupSocketBindItem **items = userdata, *i;
+        int r;
+
+        assert(items);
+
+        r = sd_bus_message_open_container(reply, 'a', "(iqq)");
+        if (r < 0)
+                return r;
+
+        LIST_FOREACH(socket_bind_items, i, *items) {
+                r = sd_bus_message_append(reply, "(iqq)", i->address_family, i->nr_ports, i->port_min);
+                if (r < 0)
+                        return r;
+        }
+
+        return sd_bus_message_close_container(reply);
+}
+
 const sd_bus_vtable bus_cgroup_vtable[] = {
         SD_BUS_VTABLE_START(0),
         SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
@@ -398,6 +453,9 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
         SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_mem_pressure), 0),
         SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimit", "u", NULL, offsetof(CGroupContext, moom_mem_pressure_limit), 0),
         SD_BUS_PROPERTY("ManagedOOMPreference", "s", property_get_managed_oom_preference, offsetof(CGroupContext, moom_preference), 0),
+        SD_BUS_PROPERTY("BPFProgram", "a(ss)", property_get_bpf_foreign_program, 0, 0),
+        SD_BUS_PROPERTY("SocketBindAllow", "a(iqq)", property_get_socket_bind, offsetof(CGroupContext, socket_bind_allow), 0),
+        SD_BUS_PROPERTY("SocketBindDeny", "a(iqq)", property_get_socket_bind, offsetof(CGroupContext, socket_bind_deny), 0),
         SD_BUS_VTABLE_END
 };
 
@@ -422,7 +480,7 @@ static int bus_cgroup_set_transient_property(
                 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");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
 
                 r = sd_bus_message_read(message, "b", &b);
                 if (r < 0)
@@ -441,7 +499,7 @@ static int bus_cgroup_set_transient_property(
                 CGroupMask mask = 0;
 
                 if (streq(name, "DelegateControllers") && !UNIT_VTABLE(u)->can_delegate)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
 
                 r = sd_bus_message_enter_container(message, 'a', "s");
                 if (r < 0)
@@ -570,6 +628,85 @@ static int bus_cgroup_set_transient_property(
                         }
                 }
 
+                return 1;
+        } else if (streq(name, "BPFProgram")) {
+                const char *a, *p;
+                size_t n = 0;
+
+                r = sd_bus_message_enter_container(message, 'a', "(ss)");
+                if (r < 0)
+                        return r;
+
+                while ((r = sd_bus_message_read(message, "(ss)", &a, &p)) > 0) {
+                        int attach_type = bpf_cgroup_attach_type_from_string(a);
+                        if (attach_type < 0)
+                                return sd_bus_error_setf(
+                                                error,
+                                                SD_BUS_ERROR_INVALID_ARGS,
+                                                "%s expects a valid BPF attach type, got '%s'.",
+                                                name, a);
+
+                        if (!path_is_normalized(p) || !path_is_absolute(p))
+                                return sd_bus_error_setf(
+                                                error,
+                                                SD_BUS_ERROR_INVALID_ARGS,
+                                                "%s= expects a normalized absolute path.",
+                                                name);
+
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+                                r = cgroup_add_bpf_foreign_program(c, attach_type, p);
+                                if (r < 0)
+                                        return r;
+                        }
+                        n++;
+                }
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_exit_container(message);
+                if (r < 0)
+                        return r;
+
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+                        _cleanup_free_ char *buf = NULL;
+                        _cleanup_fclose_ FILE *f = NULL;
+                        CGroupBPFForeignProgram *fp;
+                        size_t size = 0;
+
+                        if (n == 0)
+                                while (c->bpf_foreign_programs)
+                                        cgroup_context_remove_bpf_foreign_program(c, c->bpf_foreign_programs);
+
+                        f = open_memstream_unlocked(&buf, &size);
+                        if (!f)
+                                return -ENOMEM;
+
+                        fputs(name, f);
+                        fputs("=\n", f);
+
+                        LIST_FOREACH(programs, fp, c->bpf_foreign_programs)
+                                fprintf(f, "%s=%s:%s\n", name,
+                                                bpf_cgroup_attach_type_to_string(fp->attach_type),
+                                                fp->bpffs_path);
+
+                        r = fflush_and_check(f);
+                        if (r < 0)
+                                return r;
+
+                        unit_write_setting(u, flags, name, buf);
+
+                        if (!LIST_IS_EMPTY(c->bpf_foreign_programs)) {
+                                r = bpf_foreign_supported();
+                                if (r < 0)
+                                        return r;
+                                if (r == 0)
+                                        log_full(LOG_DEBUG,
+                                                 "Transient unit %s configures a BPF program pinned to BPF "
+                                                 "filesystem, but the local system does not support that.\n"
+                                                 "Starting this unit will fail!", u->id);
+                        }
+                }
+
                 return 1;
         }
 
@@ -944,7 +1081,7 @@ int bus_cgroup_set_property(
                         return r;
 
                 if (u64 <= 0)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "CPUQuotaPerSecUSec= value out of range");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "CPUQuotaPerSecUSec= value out of range");
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->cpu_quota_per_sec_usec = u64;
@@ -1122,7 +1259,7 @@ int bus_cgroup_set_property(
                                 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");
+                                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "IODeviceWeight= value out of range");
 
                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 CGroupIODeviceWeight *a = NULL, *b;
@@ -1380,7 +1517,7 @@ int bus_cgroup_set_property(
                                 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");
+                                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIODeviceWeight= out of range");
 
                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 CGroupBlockIODeviceWeight *a = NULL, *b;
@@ -1476,12 +1613,12 @@ int bus_cgroup_set_property(
                 while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
 
                         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");
+                                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node or pattern");
 
                         if (isempty(rwm))
                                 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");
+                                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
 
                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 CGroupDeviceAllow *a = NULL, *b;
@@ -1741,6 +1878,89 @@ int bus_cgroup_set_property(
 
                 return 1;
         }
+        if (STR_IN_SET(name, "SocketBindAllow", "SocketBindDeny")) {
+                CGroupSocketBindItem **list;
+                uint16_t nr_ports, port_min;
+                size_t n = 0;
+                int family;
+
+                list = streq(name, "SocketBindAllow") ? &c->socket_bind_allow : &c->socket_bind_deny;
+
+                r = sd_bus_message_enter_container(message, 'a', "(iqq)");
+                if (r < 0)
+                        return r;
+
+                while ((r = sd_bus_message_read(message, "(iqq)", &family, &nr_ports, &port_min)) > 0) {
+
+                        if (!IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6))
+                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects INET or INET6 family, if specified.", name);
+
+                        if (port_min + (uint32_t) nr_ports > (1 << 16))
+                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects maximum port value lesser than 65536.", name);
+
+                        if (port_min == 0 && nr_ports != 0)
+                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects port range starting with positive value.", name);
+
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+                                _cleanup_free_ CGroupSocketBindItem *item = NULL;
+
+                                item = new(CGroupSocketBindItem, 1);
+                                if (!item)
+                                        return log_oom();
+
+                                *item = (CGroupSocketBindItem) {
+                                        .address_family = family,
+                                        .nr_ports = nr_ports,
+                                        .port_min = port_min
+                                };
+
+                                LIST_PREPEND(socket_bind_items, *list, TAKE_PTR(item));
+                        }
+                        n++;
+                }
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_exit_container(message);
+                if (r < 0)
+                        return r;
+
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+                        _cleanup_free_ char *buf = NULL;
+                        _cleanup_fclose_ FILE *f = NULL;
+                        CGroupSocketBindItem *item;
+                        size_t size = 0;
+
+                        if (n == 0)
+                                cgroup_context_remove_socket_bind(list);
+                        else {
+                                if ((u->manager->cgroup_supported & CGROUP_MASK_BPF_SOCKET_BIND) == 0)
+                                        log_full(LOG_DEBUG,
+                                                 "Unit %s configures source compiled BPF programs "
+                                                 "but the local system does not support that.\n"
+                                                 "Starting this unit will fail!", u->id);
+                        }
+
+                        f = open_memstream_unlocked(&buf, &size);
+                        if (!f)
+                                return -ENOMEM;
+
+                        fprintf(f, "%s:", name);
+
+                        LIST_FOREACH(socket_bind_items, item, *list)
+                                cgroup_context_dump_socket_bind_item(item, f);
+
+                        fputc('\n', f);
+
+                        r = fflush_and_check(f);
+                        if (r < 0)
+                                return r;
+
+                        unit_write_setting(u, flags, name, buf);
+                }
+
+                return 1;
+        }
 
         if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB))
                 return bus_cgroup_set_transient_property(u, c, name, message, flags, error);
index 4a1585f663313d3025f1ebb87e12606ca80ccb73..9c141d73b1052dc7a768ee51e3cd564657737214 100644 (file)
@@ -13,6 +13,7 @@
 #include "cap-list.h"
 #include "capability-util.h"
 #include "cpu-set-util.h"
+#include "creds-util.h"
 #include "dbus-execute.h"
 #include "dbus-util.h"
 #include "env-util.h"
@@ -1626,7 +1627,7 @@ int bus_exec_context_set_transient_property(
 
                                 unit_write_settingf(u, flags, name, "RootHash=");
                         } else {
-                                _cleanup_free_ void *p;
+                                _cleanup_free_ void *p = NULL;
 
                                 encoded = hexmem(roothash_decoded, roothash_decoded_size);
                                 if (!encoded)
@@ -1672,7 +1673,7 @@ int bus_exec_context_set_transient_property(
 
                                 unit_write_settingf(u, flags, name, "RootHashSignature=");
                         } else {
-                                _cleanup_free_ void *p;
+                                _cleanup_free_ void *p = NULL;
                                 ssize_t len;
 
                                 len = base64mem(roothash_sig_decoded, roothash_sig_decoded_size, &encoded);
@@ -2059,7 +2060,7 @@ int bus_exec_context_set_transient_property(
                         return r;
 
                 if (!log_level_is_valid(level))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
@@ -2076,7 +2077,7 @@ int bus_exec_context_set_transient_property(
                         return r;
 
                 if (!log_facility_unshifted_is_valid(facility))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
@@ -2093,7 +2094,7 @@ int bus_exec_context_set_transient_property(
                         return r;
 
                 if (!isempty(n) && !log_namespace_name_valid(n))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log namespace name not valid");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Log namespace name not valid");
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
 
@@ -2139,13 +2140,13 @@ int bus_exec_context_set_transient_property(
                                 break;
 
                         if (memchr(p, 0, sz))
-                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains zero byte");
+                                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains zero byte");
 
                         eq = memchr(p, '=', sz);
                         if (!eq)
-                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains no '=' character");
+                                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains no '=' character");
                         if (!journal_field_valid(p, eq - (const char*) p, false))
-                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field invalid");
+                                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field invalid");
 
                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 t = reallocarray(c->log_extra_fields, c->n_log_extra_fields+1, sizeof(struct iovec));
@@ -2162,7 +2163,7 @@ int bus_exec_context_set_transient_property(
                         ((uint8_t*) copy)[sz] = 0;
 
                         if (!utf8_is_valid(copy))
-                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field is not valid UTF-8");
+                                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field is not valid UTF-8");
 
                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 c->log_extra_fields[c->n_log_extra_fields++] = IOVEC_MAKE(copy, sz);
@@ -2378,8 +2379,8 @@ int bus_exec_context_set_transient_property(
                 return 1;
 
         } else if (streq(name, "RestrictAddressFamilies")) {
-                int allow_list;
                 _cleanup_strv_free_ char **l = NULL;
+                int allow_list;
 
                 r = sd_bus_message_enter_container(message, 'r', "bas");
                 if (r < 0)
@@ -2402,10 +2403,11 @@ int bus_exec_context_set_transient_property(
                         char **s;
 
                         if (strv_isempty(l)) {
-                                c->address_families_allow_list = false;
+                                c->address_families_allow_list = allow_list;
                                 c->address_families = set_free(c->address_families);
 
-                                unit_write_settingf(u, flags, name, "RestrictAddressFamilies=");
+                                unit_write_settingf(u, flags, name, "RestrictAddressFamilies=%s",
+                                                    allow_list ? "none" : "");
                                 return 1;
                         }
 
@@ -2429,7 +2431,7 @@ int bus_exec_context_set_transient_property(
                                         if (r < 0)
                                                 return r;
                                 } else
-                                        (void) set_remove(c->address_families, INT_TO_PTR(af));
+                                        set_remove(c->address_families, INT_TO_PTR(af));
                         }
 
                         joined = strv_join(l, " ");
@@ -2648,7 +2650,7 @@ int bus_exec_context_set_transient_property(
                         missing_ok = false;
 
                 if (!isempty(s) && !streq(s, "~") && !path_is_absolute(s))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (streq(s, "~")) {
@@ -2677,7 +2679,7 @@ int bus_exec_context_set_transient_property(
                         return r;
 
                 if (!isempty(s) && !fdname_is_valid(s))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name");
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
 
@@ -2829,7 +2831,7 @@ int bus_exec_context_set_transient_property(
                         return r;
 
                 if (!strv_env_is_valid(l))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (strv_isempty(l)) {
@@ -2863,7 +2865,7 @@ int bus_exec_context_set_transient_property(
                         return r;
 
                 if (!strv_env_name_or_assignment_is_valid(l))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UnsetEnvironment= list.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UnsetEnvironment= list.");
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (strv_isempty(l)) {
@@ -2896,7 +2898,7 @@ int bus_exec_context_set_transient_property(
                         return r;
 
                 if (!oom_score_adjust_is_valid(oa))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->oom_score_adjust = oa;
@@ -3017,7 +3019,7 @@ int bus_exec_context_set_transient_property(
                         return r;
 
                 if (!strv_env_name_is_valid(l))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment= block.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment= block.");
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (strv_isempty(l)) {
@@ -3192,7 +3194,7 @@ int bus_exec_context_set_transient_property(
                         if (!path_is_absolute(destination))
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination);
                         if (!IN_SET(mount_flags, 0, MS_REC))
-                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount flags.");
+                                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount flags.");
 
                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts,
index e33896f9763f49a3f1293a0f67b460c6a0d24b19..128d7778f55e8249aa915dc859483f064a9f2475 100644 (file)
@@ -48,6 +48,7 @@ static UnitFileFlags unit_file_bools_to_flags(bool runtime, bool force) {
 }
 
 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_oom_policy, oom_policy, OOMPolicy);
+BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_emergency_action, emergency_action, EmergencyAction);
 
 static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_version, "s", GIT_VERSION);
 static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_features, "s", systemd_features);
@@ -380,7 +381,7 @@ static int bus_get_unit_by_name(Manager *m, sd_bus_message *message, const char
 
                 u = manager_get_unit_by_pid(m, pid);
                 if (!u)
-                        return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client not member of any unit.");
+                        return sd_bus_error_set(error, BUS_ERROR_NO_SUCH_UNIT, "Client not member of any unit.");
         } else {
                 u = manager_get_unit(m, name);
                 if (!u)
@@ -504,7 +505,7 @@ static int method_get_unit_by_invocation_id(sd_bus_message *message, void *userd
         else if (sz == 16)
                 memcpy(&id, a, sz);
         else
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid invocation ID");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid invocation ID");
 
         if (sd_id128_is_null(id)) {
                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
@@ -1235,7 +1236,7 @@ static int method_subscribe(sd_bus_message *message, void *userdata, sd_bus_erro
                 if (r < 0)
                         return r;
                 if (r == 0)
-                        return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
+                        return sd_bus_error_set(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
         }
 
         return sd_bus_reply_method_return(message, NULL);
@@ -1259,7 +1260,7 @@ static int method_unsubscribe(sd_bus_message *message, void *userdata, sd_bus_er
                 if (r < 0)
                         return r;
                 if (r == 0)
-                        return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
+                        return sd_bus_error_set(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
         }
 
         return sd_bus_reply_method_return(message, NULL);
@@ -1309,7 +1310,7 @@ static int method_dump_by_fd(sd_bus_message *message, void *userdata, sd_bus_err
 }
 
 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.");
+        return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for snapshots has been removed.");
 }
 
 static int verify_run_space(const char *message, sd_bus_error *error) {
@@ -1624,7 +1625,7 @@ static int method_set_environment(sd_bus_message *message, void *userdata, sd_bu
         if (r < 0)
                 return r;
         if (!strv_env_is_valid(plus))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
 
         r = bus_verify_set_environment_async(m, message, error);
         if (r < 0)
@@ -1729,7 +1730,7 @@ static int method_set_exit_code(sd_bus_message *message, void *userdata, sd_bus_
                 return r;
 
         if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "ExitCode can only be set for user service managers or in containers.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "ExitCode can only be set for user service managers or in containers.");
 
         m->return_value = code;
 
@@ -2723,6 +2724,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
         SD_BUS_PROPERTY("DefaultTasksMax", "t", bus_property_get_tasks_max, offsetof(Manager, default_tasks_max), 0),
         SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultOOMPolicy", "s", bus_property_get_oom_policy, offsetof(Manager, default_oom_policy), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("CtrlAltDelBurstAction", "s", bus_property_get_emergency_action, offsetof(Manager, cad_burst_action), SD_BUS_VTABLE_PROPERTY_CONST),
 
         SD_BUS_METHOD_WITH_NAMES("GetUnit",
                                  "s",
index f3862fca83c37ee37fe2ea152518d1738b8aa14e..9b050801a71468117c63d12cef25d9ba19645df5 100644 (file)
@@ -15,3 +15,4 @@ void bus_manager_send_change_signal(Manager *m);
 int verify_run_space_and_log(const char *message);
 
 int bus_property_get_oom_policy(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);
+int bus_property_get_emergency_action(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);
index 14e77d783dd929b25a17560907c4dcc48d2ae34f..e132cd2b3cf94f021b5f7223a1914bb4af007951 100644 (file)
@@ -96,7 +96,7 @@ static int bus_path_set_transient_property(
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in %s is not absolute: %s", type_name, path);
 
                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-                                _cleanup_free_ char *k;
+                                _cleanup_free_ char *k = NULL;
                                 PathSpec *s;
 
                                 k = strdup(path);
index 1bcb4836f63e9790a59c92a8dea5f4c8b33edf97..90ec6a686cdf46c3ff5095cc6c8fad453970c40b 100644 (file)
@@ -133,7 +133,7 @@ static int bus_scope_set_transient_property(
                 /* We can't support direct connections with this, as direct connections know no service or unique name
                  * concept, but the Controller field stores exactly that. */
                 if (sd_bus_message_get_bus(message) != u->manager->api_bus)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Sorry, Controller= logic only supported via the bus.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Sorry, Controller= logic only supported via the bus.");
 
                 r = sd_bus_message_read(message, "s", &controller);
                 if (r < 0)
index f7cdb51eba883c83b8472173dc01342f47326788..4dea8d5aec1f333e0d214f18a4b16b658e797543 100644 (file)
@@ -27,6 +27,7 @@
 #include "unit.h"
 
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exit_type, service_exit_type, ServiceExitType);
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
@@ -108,7 +109,7 @@ static int bus_service_method_mount(sd_bus_message *message, void *userdata, sd_
         assert(u);
 
         if (!MANAGER_IS_SYSTEM(u->manager))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Adding bind mounts at runtime is only supported for system managers.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Adding bind mounts at runtime is only supported for system managers.");
 
         r = mac_selinux_unit_access_check(u, message, "start", error);
         if (r < 0)
@@ -119,12 +120,12 @@ static int bus_service_method_mount(sd_bus_message *message, void *userdata, sd_
                 return r;
 
         if (!path_is_absolute(src) || !path_is_normalized(src))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and normalized.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and normalized.");
 
         if (!is_image && isempty(dest))
                 dest = src;
         else if (!path_is_absolute(dest) || !path_is_normalized(dest))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and normalized.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and normalized.");
 
         if (is_image) {
                 r = bus_read_mount_options(message, error, &options, NULL, "");
@@ -146,23 +147,23 @@ static int bus_service_method_mount(sd_bus_message *message, void *userdata, sd_
                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
 
         if (u->type != UNIT_SERVICE)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not of type .service");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not of type .service");
 
         /* If it would be dropped at startup time, return an error. The context should always be available, but
          * there's an assert in exec_needs_mount_namespace, so double-check just in case. */
         c = unit_get_exec_context(u);
         if (!c)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot access unit execution context");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot access unit execution context");
         if (path_startswith_strv(dest, c->inaccessible_paths))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s is not accessible to this unit", dest);
 
         /* Ensure that the unit was started in a private mount namespace */
         if (!exec_needs_mount_namespace(c, NULL, unit_get_exec_runtime(u)))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit not running in private mount namespace, cannot activate bind mount");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unit not running in private mount namespace, cannot activate bind mount");
 
         unit_pid = unit_main_pid(u);
         if (unit_pid == 0 || !UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u)))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not running");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not running");
 
         propagate_directory = strjoina("/run/systemd/propagate/", u->id);
         if (is_image)
@@ -192,6 +193,7 @@ int bus_service_method_mount_image(sd_bus_message *message, void *userdata, sd_b
 const sd_bus_vtable bus_service_vtable[] = {
         SD_BUS_VTABLE_START(0),
         SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("ExitType", "s", property_get_exit_type, offsetof(Service, exit_type), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -377,6 +379,7 @@ static int bus_set_transient_std_fd(
 }
 static BUS_DEFINE_SET_TRANSIENT_PARSE(notify_access, NotifyAccess, notify_access_from_string);
 static BUS_DEFINE_SET_TRANSIENT_PARSE(service_type, ServiceType, service_type_from_string);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(service_exit_type, ServiceExitType, service_exit_type_from_string);
 static BUS_DEFINE_SET_TRANSIENT_PARSE(service_restart, ServiceRestart, service_restart_from_string);
 static BUS_DEFINE_SET_TRANSIENT_PARSE(oom_policy, OOMPolicy, oom_policy_from_string);
 static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, sd_bus_service_name_is_valid);
@@ -414,6 +417,9 @@ static int bus_service_set_transient_property(
         if (streq(name, "Type"))
                 return bus_set_transient_service_type(u, name, &s->type, message, flags, error);
 
+        if (streq(name, "ExitType"))
+                return bus_set_transient_service_exit_type(u, name, &s->exit_type, message, flags, error);
+
         if (streq(name, "OOMPolicy"))
                 return bus_set_transient_oom_policy(u, name, &s->oom_policy, message, flags, error);
 
index 88b2f2cacf58647482d199875c8121a64fb772f9..e54c473d1101c2a16f572dd3596534b8266fa273 100644 (file)
@@ -183,7 +183,7 @@ static int timer_add_one_calendar_spec(
 
         r = calendar_spec_from_string(str, &c);
         if (r == -EINVAL)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid calendar spec");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid calendar spec");
         if (r < 0)
                 return r;
 
index 53397e8cbf1bc1ee8f57c69e4dca55ad79aab0f0..a83648d9687c01cd18875aa52d0e6647e6d69a7c 100644 (file)
@@ -10,6 +10,7 @@
 #include "cgroup-util.h"
 #include "condition.h"
 #include "dbus-job.h"
+#include "dbus-manager.h"
 #include "dbus-unit.h"
 #include "dbus-util.h"
 #include "dbus.h"
@@ -43,7 +44,6 @@ static bool unit_can_isolate_refuse_manual(Unit *u) {
 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_GET2(property_get_freezer_state, "s", Unit, unit_freezer_state, freezer_state_to_string);
@@ -527,7 +527,7 @@ int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *
         }
 
         if (!SIGNAL_VALID(signo))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
 
         r = bus_verify_manage_units_async_full(
                         u,
@@ -653,7 +653,7 @@ int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error
 
         r = bus_unit_track_remove_sender(u, message);
         if (r == -EUNATCH)
-                return sd_bus_error_setf(error, BUS_ERROR_NOT_REFERENCED, "Unit has not been referenced yet.");
+                return sd_bus_error_set(error, BUS_ERROR_NOT_REFERENCED, "Unit has not been referenced yet.");
         if (r < 0)
                 return r;
 
@@ -719,9 +719,9 @@ int bus_unit_method_clean(sd_bus_message *message, void *userdata, sd_bus_error
         if (r == -EOPNOTSUPP)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Unit '%s' does not supporting cleaning.", u->id);
         if (r == -EUNATCH)
-                return sd_bus_error_setf(error, BUS_ERROR_NOTHING_TO_CLEAN, "No matching resources found.");
+                return sd_bus_error_set(error, BUS_ERROR_NOTHING_TO_CLEAN, "No matching resources found.");
         if (r == -EBUSY)
-                return sd_bus_error_setf(error, BUS_ERROR_UNIT_BUSY, "Unit is not inactive or has pending job.");
+                return sd_bus_error_set(error, BUS_ERROR_UNIT_BUSY, "Unit is not inactive or has pending job.");
         if (r < 0)
                 return r;
 
@@ -768,9 +768,9 @@ static int bus_unit_method_freezer_generic(sd_bus_message *message, void *userda
         if (r == -EOPNOTSUPP)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Unit '%s' does not support freezing.", u->id);
         if (r == -EBUSY)
-                return sd_bus_error_setf(error, BUS_ERROR_UNIT_BUSY, "Unit has a pending job.");
+                return sd_bus_error_set(error, BUS_ERROR_UNIT_BUSY, "Unit has a pending job.");
         if (r == -EHOSTDOWN)
-                return sd_bus_error_setf(error, BUS_ERROR_UNIT_INACTIVE, "Unit is inactive.");
+                return sd_bus_error_set(error, BUS_ERROR_UNIT_INACTIVE, "Unit is inactive.");
         if (r == -EALREADY)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Previously requested freezer operation for unit '%s' is still in progress.", u->id);
         if (r < 0)
@@ -899,7 +899,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
         SD_BUS_PROPERTY("Markers", "as", property_get_markers, offsetof(Unit, markers), 0),
         SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("JobRunningTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_running_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_emergency_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("JobTimeoutAction", "s", bus_property_get_emergency_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
@@ -912,10 +912,10 @@ const sd_bus_vtable bus_unit_vtable[] = {
         SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("StartLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_ratelimit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("StartLimitAction", "s", bus_property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("FailureAction", "s", bus_property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("FailureActionExitStatus", "i", bus_property_get_int, offsetof(Unit, failure_action_exit_status), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("SuccessAction", "s", property_get_emergency_action, offsetof(Unit, success_action), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("SuccessAction", "s", bus_property_get_emergency_action, offsetof(Unit, success_action), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("SuccessActionExitStatus", "i", bus_property_get_int, offsetof(Unit, success_action_exit_status), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
@@ -1444,10 +1444,10 @@ int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd
         }
 
         if (!unit_cgroup_delegate(u))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Process migration not available on non-delegated units.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Process migration not available on non-delegated units.");
 
         if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not active, refusing.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not active, refusing.");
 
         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
         if (r < 0)
@@ -1932,7 +1932,7 @@ static int bus_unit_set_live_property(
                         return r;
 
                 if (some_plus_minus && some_absolute)
-                        return sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING, "Bad marker syntax.");
+                        return sd_bus_error_set(error, BUS_ERROR_BAD_UNIT_SETTING, "Bad marker syntax.");
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (some_absolute)
@@ -2001,7 +2001,7 @@ static int bus_set_transient_exit_status(
                 return r;
 
         if (k > 255)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Exit status must be in range 0…255 or negative.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Exit status must be in range 0…255 or negative.");
 
         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                 *p = k < 0 ? -1 : k;
@@ -2207,11 +2207,11 @@ static int bus_unit_set_transient_property(
                 const char *s;
 
                 if (!UNIT_HAS_CGROUP_CONTEXT(u))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "The slice property is only available for units with control groups.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "The slice property is only available for units with control groups.");
                 if (u->type == UNIT_SLICE)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Slice may not be set for slice units.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Slice may not be set for slice units.");
                 if (unit_has_name(u, SPECIAL_INIT_SCOPE))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set slice for init.scope");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set slice for init.scope");
 
                 r = sd_bus_message_read(message, "s", &s);
                 if (r < 0)
index 5db484b8de64531da0a9c5a0dc126d0d813b6dd7..26e34ac4d0f93be186c2b02f2de73676478de5c2 100644 (file)
@@ -164,7 +164,7 @@ static int signal_activation_request(sd_bus_message *message, void *userdata, sd
 
         if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
             manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
-                r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
+                r = sd_bus_error_set(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
                 goto failed;
         }
 
index 35aea2f83015ca01d0d2501f655e4b3331a15989..6a1e6c842974b2b8fc7414d7d007c518e002bae5 100644 (file)
@@ -2564,6 +2564,7 @@ static int acquire_credentials(
                 ReadFullFileFlags flags = READ_FULL_FILE_SECURE;
                 _cleanup_(erase_and_freep) char *data = NULL;
                 _cleanup_free_ char *j = NULL, *bindname = NULL;
+                bool missing_ok = true;
                 const char *source;
                 size_t size, add;
 
@@ -2577,6 +2578,8 @@ static int acquire_credentials(
                         if (asprintf(&bindname, "@%" PRIx64"/unit/%s/%s", random_u64(), unit, *id) < 0)
                                 return -ENOMEM;
 
+                        missing_ok = false;
+
                 } else if (params->received_credentials) {
                         /* If this is a relative path, take it relative to the credentials we received
                          * ourselves. We don't support the AF_UNIX stuff in this mode, since we are operating
@@ -2589,16 +2592,23 @@ static int acquire_credentials(
                 } else
                         source = NULL;
 
-
                 if (source)
                         r = read_full_file_full(AT_FDCWD, source, UINT64_MAX, SIZE_MAX, flags, bindname, &data, &size);
                 else
                         r = -ENOENT;
-                if (r == -ENOENT &&
-                    faccessat(dfd, *id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) /* If the source file doesn't exist, but we already acquired the key otherwise, then don't fail */
+                if (r == -ENOENT && (missing_ok || faccessat(dfd, *id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)) {
+                        /* Make a missing inherited credential non-fatal, let's just continue. After all apps
+                         * will get clear errors if we don't pass such a missing credential on as they
+                         * themselves will get ENOENT when trying to read them, which should not be much
+                         * worse than when we handle the error here and make it fatal.
+                         *
+                         * Also, if the source file doesn't exist, but we already acquired the key otherwise,
+                         * then don't fail either. */
+                        log_debug_errno(r, "Couldn't read inherited credential '%s', skipping: %m", *fn);
                         continue;
+                }
                 if (r < 0)
-                        return r;
+                        return log_debug_errno(r, "Failed to read credential '%s': %m", *fn);
 
                 add = strlen(*id) + size;
                 if (add > left)
@@ -3247,7 +3257,6 @@ static int apply_mount_namespace(
                             propagate_dir,
                             incoming_dir,
                             root_dir || root_image ? params->notify_socket : NULL,
-                            DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
                             error_path);
 
         /* If we couldn't set up the namespace this is probably due to a missing capability. setup_namespace() reports
@@ -4309,24 +4318,23 @@ static int exec_child(
         r = find_executable_full(command->path, false, &executable, &executable_fd);
         if (r < 0) {
                 if (r != -ENOMEM && (command->flags & EXEC_COMMAND_IGNORE_FAILURE)) {
-                        log_struct_errno(LOG_INFO, r,
-                                         "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);
+                        log_unit_struct_errno(unit, LOG_INFO, r,
+                                              "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
+                                              LOG_UNIT_INVOCATION_ID(unit),
+                                              LOG_UNIT_MESSAGE(unit, "Executable %s missing, skipping: %m",
+                                                               command->path),
+                                              "EXECUTABLE=%s", command->path);
                         return 0;
                 }
 
                 *exit_status = EXIT_EXEC;
-                return log_struct_errno(LOG_INFO, r,
-                                        "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
-                                        LOG_UNIT_ID(unit),
-                                        LOG_UNIT_INVOCATION_ID(unit),
-                                        LOG_UNIT_MESSAGE(unit, "Failed to locate executable %s: %m",
-                                                         command->path),
-                                        "EXECUTABLE=%s", command->path);
+
+                return log_unit_struct_errno(unit, LOG_INFO, r,
+                                             "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
+                                             LOG_UNIT_INVOCATION_ID(unit),
+                                             LOG_UNIT_MESSAGE(unit, "Failed to locate executable %s: %m",
+                                                              command->path),
+                                             "EXECUTABLE=%s", command->path);
         }
 
         r = add_shifted_fd(keep_fds, ELEMENTSOF(keep_fds), &n_keep_fds, executable_fd, &executable_fd);
@@ -4630,15 +4638,14 @@ static int exec_child(
                 final_argv = command->argv;
 
         if (DEBUG_LOGGING) {
-                _cleanup_free_ char *line;
+                _cleanup_free_ char *line = NULL;
 
                 line = exec_command_line(final_argv);
                 if (line)
-                        log_struct(LOG_DEBUG,
-                                   "EXECUTABLE=%s", executable,
-                                   LOG_UNIT_MESSAGE(unit, "Executing: %s", line),
-                                   LOG_UNIT_ID(unit),
-                                   LOG_UNIT_INVOCATION_ID(unit));
+                        log_unit_struct(unit, LOG_DEBUG,
+                                        "EXECUTABLE=%s", executable,
+                                        LOG_UNIT_MESSAGE(unit, "Executing: %s", line),
+                                        LOG_UNIT_INVOCATION_ID(unit));
         }
 
         if (exec_fd >= 0) {
@@ -4730,14 +4737,13 @@ int exec_spawn(Unit *unit,
            and, until the next SELinux policy changes, we save further reloads in future children. */
         mac_selinux_maybe_reload();
 
-        log_struct(LOG_DEBUG,
-                   LOG_UNIT_MESSAGE(unit, "About to execute %s", line),
-                   "EXECUTABLE=%s", command->path, /* We won't know the real executable path until we create
-                                                      the mount namespace in the child, but we want to log
-                                                      from the parent, so we need to use the (possibly
-                                                      inaccurate) path here. */
-                   LOG_UNIT_ID(unit),
-                   LOG_UNIT_INVOCATION_ID(unit));
+        log_unit_struct(unit, LOG_DEBUG,
+                        LOG_UNIT_MESSAGE(unit, "About to execute %s", line),
+                        "EXECUTABLE=%s", command->path, /* We won't know the real executable path until we create
+                                                           the mount namespace in the child, but we want to log
+                                                           from the parent, so we need to use the (possibly
+                                                           inaccurate) path here. */
+                        LOG_UNIT_INVOCATION_ID(unit));
 
         if (params->cgroup_path) {
                 r = exec_parameters_get_cgroup_path(params, &subcgroup_path);
@@ -4781,13 +4787,12 @@ int exec_spawn(Unit *unit,
                                 exit_status_to_string(exit_status,
                                                       EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD);
 
-                        log_struct_errno(LOG_ERR, r,
-                                         "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
-                                         LOG_UNIT_ID(unit),
-                                         LOG_UNIT_INVOCATION_ID(unit),
-                                         LOG_UNIT_MESSAGE(unit, "Failed at step %s spawning %s: %m",
-                                                          status, command->path),
-                                         "EXECUTABLE=%s", command->path);
+                        log_unit_struct_errno(unit, LOG_ERR, r,
+                                              "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
+                                              LOG_UNIT_INVOCATION_ID(unit),
+                                              LOG_UNIT_MESSAGE(unit, "Failed at step %s spawning %s: %m",
+                                                               status, command->path),
+                                              "EXECUTABLE=%s", command->path);
                 }
 
                 _exit(exit_status);
@@ -4907,6 +4912,7 @@ void exec_context_done(ExecContext *c) {
         c->stdin_data_size = 0;
 
         c->network_namespace_path = mfree(c->network_namespace_path);
+        c->ipc_namespace_path = mfree(c->ipc_namespace_path);
 
         c->log_namespace = mfree(c->log_namespace);
 
@@ -4923,7 +4929,7 @@ int exec_context_destroy_runtime_directory(const ExecContext *c, const char *run
                 return 0;
 
         STRV_FOREACH(i, c->directories[EXEC_DIRECTORY_RUNTIME].paths) {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 if (exec_directory_is_private(c, EXEC_DIRECTORY_RUNTIME))
                         p = path_join(runtime_prefix, "private", *i);
@@ -5225,7 +5231,7 @@ static void strv_dump(FILE* f, const char *prefix, const char *name, char **strv
         assert(name);
 
         if (!strv_isempty(strv)) {
-                fprintf(f, "%s%s:", name, prefix);
+                fprintf(f, "%s%s:", prefix, name);
                 strv_fprintf(f, strv);
                 fputs("\n", f);
         }
index 639dc352a6c0db44080d8a9d9cc1f9a708f830e5..57829d185a059012f18e947caf86f3302aac12c2 100644 (file)
@@ -557,6 +557,9 @@ static void job_log_begin_status_message(Unit *u, uint32_t job_id, JobType t) {
         if (!IN_SET(t, JOB_START, JOB_STOP, JOB_RELOAD))
                 return;
 
+        if (!unit_log_level_test(u, LOG_INFO))
+                return;
+
         if (log_on_console()) /* Skip this if it would only go on the console anyway */
                 return;
 
@@ -578,13 +581,12 @@ static void job_log_begin_status_message(Unit *u, uint32_t job_id, JobType t) {
          * which is supposed the highest level, friendliest output
          * possible, which means we should avoid the low-level unit
          * name. */
-        log_struct(LOG_INFO,
-                   LOG_MESSAGE("%s", buf),
-                   "JOB_ID=%" PRIu32, job_id,
-                   "JOB_TYPE=%s", job_type_to_string(t),
-                   LOG_UNIT_ID(u),
-                   LOG_UNIT_INVOCATION_ID(u),
-                   mid);
+        log_unit_struct(u, LOG_INFO,
+                        LOG_MESSAGE("%s", buf),
+                        "JOB_ID=%" PRIu32, job_id,
+                        "JOB_TYPE=%s", job_type_to_string(t),
+                        LOG_UNIT_INVOCATION_ID(u),
+                        mid);
 }
 
 static void job_emit_begin_status_message(Unit *u, uint32_t job_id, JobType t) {
@@ -844,7 +846,7 @@ static void job_print_done_status_message(Unit *u, JobType t, JobResult result)
         REENABLE_WARNING;
 
         if (t == JOB_START && result == JOB_FAILED) {
-                _cleanup_free_ char *quoted;
+                _cleanup_free_ char *quoted = NULL;
 
                 quoted = shell_maybe_quote(u->id, 0);
                 manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, "See 'systemctl status %s' for details.", strna(quoted));
@@ -879,18 +881,20 @@ static void job_log_done_status_message(Unit *u, uint32_t job_id, JobType t, Job
 
         /* Show condition check message if the job did not actually do anything due to failed condition. */
         if (t == JOB_START && result == JOB_DONE && !u->condition_result) {
-                log_struct(LOG_INFO,
-                           "MESSAGE=Condition check resulted in %s being skipped.", unit_status_string(u),
-                           "JOB_ID=%" PRIu32, job_id,
-                           "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),
-                           "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTED_STR);
+                log_unit_struct(u, LOG_INFO,
+                                "MESSAGE=Condition check resulted in %s being skipped.", unit_status_string(u),
+                                "JOB_ID=%" PRIu32, job_id,
+                                "JOB_TYPE=%s", job_type_to_string(t),
+                                "JOB_RESULT=%s", job_result_to_string(result),
+                                LOG_UNIT_INVOCATION_ID(u),
+                                "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTED_STR);
 
                 return;
         }
 
+        if (!unit_log_level_test(u, job_result_log_level[result]))
+                return;
+
         format = job_get_done_status_message_format(u, t, result);
         if (!format)
                 return;
@@ -922,24 +926,22 @@ static void job_log_done_status_message(Unit *u, uint32_t job_id, JobType t, Job
                 break;
 
         default:
-                log_struct(job_result_log_level[result],
-                           LOG_MESSAGE("%s", buf),
-                           "JOB_ID=%" PRIu32, job_id,
-                           "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));
+                log_unit_struct(u, job_result_log_level[result],
+                                LOG_MESSAGE("%s", buf),
+                                "JOB_ID=%" PRIu32, job_id,
+                                "JOB_TYPE=%s", job_type_to_string(t),
+                                "JOB_RESULT=%s", job_result_to_string(result),
+                                LOG_UNIT_INVOCATION_ID(u));
                 return;
         }
 
-        log_struct(job_result_log_level[result],
-                   LOG_MESSAGE("%s", buf),
-                   "JOB_ID=%" PRIu32, job_id,
-                   "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),
-                   mid);
+        log_unit_struct(u, job_result_log_level[result],
+                        LOG_MESSAGE("%s", buf),
+                        "JOB_ID=%" PRIu32, job_id,
+                        "JOB_TYPE=%s", job_type_to_string(t),
+                        "JOB_RESULT=%s", job_result_to_string(result),
+                        LOG_UNIT_INVOCATION_ID(u),
+                        mid);
 }
 
 static void job_emit_done_status_message(Unit *u, uint32_t job_id, JobType t, JobResult result) {
@@ -1048,14 +1050,13 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr
          * this context. And JOB_FAILURE is already handled by the
          * unit itself. */
         if (IN_SET(result, JOB_TIMEOUT, JOB_DEPENDENCY)) {
-                log_struct(LOG_NOTICE,
-                           "JOB_TYPE=%s", job_type_to_string(t),
-                           "JOB_RESULT=%s", job_result_to_string(result),
-                           LOG_UNIT_ID(u),
-                           LOG_UNIT_MESSAGE(u, "Job %s/%s failed with result '%s'.",
-                                            u->id,
-                                            job_type_to_string(t),
-                                            job_result_to_string(result)));
+                log_unit_struct(u, LOG_NOTICE,
+                                "JOB_TYPE=%s", job_type_to_string(t),
+                                "JOB_RESULT=%s", job_result_to_string(result),
+                                LOG_UNIT_MESSAGE(u, "Job %s/%s failed with result '%s'.",
+                                                 u->id,
+                                                 job_type_to_string(t),
+                                                 job_result_to_string(result)));
 
                 unit_start_on_failure(u);
         }
index 21bbcffe41af6d84ecbcc4f31c287a318b4dc579..7c3c1c9095af37a2d721ed43c5216f91e4e423c2 100644 (file)
@@ -234,7 +234,10 @@ $1.ManagedOOMSwap,                       config_parse_managed_oom_mode,
 $1.ManagedOOMMemoryPressure,             config_parse_managed_oom_mode,               0,                                  offsetof($1, cgroup_context.moom_mem_pressure)
 $1.ManagedOOMMemoryPressureLimit,        config_parse_managed_oom_mem_pressure_limit, 0,                                  offsetof($1, cgroup_context.moom_mem_pressure_limit)
 $1.ManagedOOMPreference,                 config_parse_managed_oom_preference,         0,                                  offsetof($1, cgroup_context.moom_preference)
-$1.NetClass,                             config_parse_warn_compat,                    DISABLED_LEGACY,                    0'
+$1.NetClass,                             config_parse_warn_compat,                    DISABLED_LEGACY,                    0
+$1.BPFProgram,                           config_parse_bpf_foreign_program,            0,                                  offsetof($1, cgroup_context)
+$1.SocketBindAllow,                      config_parse_cgroup_socket_bind,             0,                                  offsetof($1, cgroup_context.socket_bind_allow)
+$1.SocketBindDeny,                       config_parse_cgroup_socket_bind,             0,                                  offsetof($1, cgroup_context.socket_bind_deny)'
 )m4_dnl
 Unit.Description,                        config_parse_unit_string_printf,             0,                                  offsetof(Unit, description)
 Unit.Documentation,                      config_parse_documentation,                  0,                                  offsetof(Unit, documentation)
@@ -294,6 +297,7 @@ Unit.ConditionFileIsExecutable,          config_parse_unit_condition_path,
 Unit.ConditionNeedsUpdate,               config_parse_unit_condition_path,            CONDITION_NEEDS_UPDATE,             offsetof(Unit, conditions)
 Unit.ConditionFirstBoot,                 config_parse_unit_condition_string,          CONDITION_FIRST_BOOT,               offsetof(Unit, conditions)
 Unit.ConditionArchitecture,              config_parse_unit_condition_string,          CONDITION_ARCHITECTURE,             offsetof(Unit, conditions)
+Unit.ConditionFirmware,                  config_parse_unit_condition_string,          CONDITION_FIRMWARE,                 offsetof(Unit, conditions)
 Unit.ConditionVirtualization,            config_parse_unit_condition_string,          CONDITION_VIRTUALIZATION,           offsetof(Unit, conditions)
 Unit.ConditionHost,                      config_parse_unit_condition_string,          CONDITION_HOST,                     offsetof(Unit, conditions)
 Unit.ConditionKernelCommandLine,         config_parse_unit_condition_string,          CONDITION_KERNEL_COMMAND_LINE,      offsetof(Unit, conditions)
@@ -359,6 +363,7 @@ Service.StartLimitAction,                config_parse_emergency_action,
 Service.FailureAction,                   config_parse_emergency_action,               0,                                  offsetof(Unit, failure_action)
 Service.RebootArgument,                  config_parse_unit_string_printf,             0,                                  offsetof(Unit, reboot_arg)
 Service.Type,                            config_parse_service_type,                   0,                                  offsetof(Service, type)
+Service.ExitType,                        config_parse_service_exit_type,              0,                                  offsetof(Service, exit_type)
 Service.Restart,                         config_parse_service_restart,                0,                                  offsetof(Service, restart)
 Service.PermissionsStartOnly,            config_parse_bool,                           0,                                  offsetof(Service, permissions_start_only)
 Service.RootDirectoryStartOnly,          config_parse_bool,                           0,                                  offsetof(Service, root_directory_start_only)
index c6fc4fe083f989f74956979430c0ee69f2bf1222..2399089492e6a6f12bc079137a7ead1f7e393b4d 100644 (file)
 #include "sd-messages.h"
 
 #include "af-list.h"
-#include "alloc-util.h"
 #include "all-units.h"
+#include "alloc-util.h"
 #include "bpf-firewall.h"
+#include "bpf-program.h"
 #include "bus-error.h"
 #include "bus-internal.h"
 #include "bus-util.h"
@@ -28,6 +29,7 @@
 #include "conf-parser.h"
 #include "core-varlink.h"
 #include "cpu-set-util.h"
+#include "creds-util.h"
 #include "env-util.h"
 #include "errno-list.h"
 #include "escape.h"
@@ -53,6 +55,7 @@
 #endif
 #include "securebits-util.h"
 #include "signal-util.h"
+#include "socket-bind.h"
 #include "socket-netlink.h"
 #include "stat-util.h"
 #include "string-util.h"
@@ -130,6 +133,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_home, protect_home, ProtectHome, "
 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_exit_type, service_exit_type, ServiceExitType, "Failed to parse service exit type");
 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_timeout_failure_mode, service_timeout_failure_mode, ServiceTimeoutFailureMode, "Failed to parse timeout failure mode");
 DEFINE_CONFIG_PARSE_ENUM(config_parse_socket_bind, socket_address_bind_ipv6_only_or_bool, SocketAddressBindIPv6Only, "Failed to parse bind IPv6 only value");
@@ -1695,6 +1699,8 @@ int config_parse_exec_cpu_affinity(
                 void *userdata) {
 
         ExecContext *c = data;
+        const Unit *u = userdata;
+        _cleanup_free_ char *k = NULL;
         int r;
 
         assert(filename);
@@ -1709,7 +1715,15 @@ int config_parse_exec_cpu_affinity(
                 return 0;
         }
 
-        r = parse_cpu_set_extend(rvalue, &c->cpu_set, true, unit, filename, line, lvalue);
+        r = unit_full_printf(u, rvalue, &k);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to resolve unit specifiers in '%s', ignoring: %m",
+                           rvalue);
+                return 0;
+        }
+
+        r = parse_cpu_set_extend(k, &c->cpu_set, true, unit, filename, line, lvalue);
         if (r >= 0)
                 c->cpu_affinity_from_numa = false;
 
@@ -2002,7 +2016,7 @@ int config_parse_trigger_unit(
         assert(rvalue);
         assert(data);
 
-        if (!hashmap_isempty(u->dependencies[UNIT_TRIGGERS])) {
+        if (UNIT_TRIGGER(u)) {
                 log_syntax(unit, LOG_WARNING, filename, line, 0, "Multiple units to trigger specified, ignoring: %s", rvalue);
                 return 0;
         }
@@ -2199,14 +2213,14 @@ int config_parse_service_sockets(
                 _cleanup_free_ char *word = NULL, *k = NULL;
 
                 r = extract_first_word(&p, &word, NULL, 0);
-                if (r == 0)
-                        return 0;
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0) {
                         log_syntax(unit, LOG_WARNING, filename, line, r, "Trailing garbage in sockets, ignoring: %s", rvalue);
                         return 0;
                 }
+                if (r == 0)
+                        return 0;
 
                 r = unit_name_printf(UNIT(s), word, &k);
                 if (r < 0) {
@@ -2474,14 +2488,14 @@ int config_parse_user_group_strv_compat(
                 _cleanup_free_ char *word = NULL, *k = NULL;
 
                 r = extract_first_word(&p, &word, NULL, 0);
-                if (r == 0)
-                        return 0;
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0) {
                         log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax: %s", rvalue);
                         return -ENOEXEC;
                 }
+                if (r == 0)
+                        return 0;
 
                 r = unit_full_printf(u, word, &k);
                 if (r < 0) {
@@ -2640,8 +2654,6 @@ int config_parse_environ(
                 _cleanup_free_ char *word = NULL, *resolved = NULL;
 
                 r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
-                if (r == 0)
-                        return 0;
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0) {
@@ -2649,6 +2661,8 @@ int config_parse_environ(
                                    "Invalid syntax, ignoring: %s", rvalue);
                         return 0;
                 }
+                if (r == 0)
+                        return 0;
 
                 if (u) {
                         r = unit_full_printf(u, word, &resolved);
@@ -2705,8 +2719,6 @@ int config_parse_pass_environ(
                 _cleanup_free_ char *word = NULL, *k = NULL;
 
                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
-                if (r == 0)
-                        break;
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0) {
@@ -2714,6 +2726,8 @@ int config_parse_pass_environ(
                                    "Trailing garbage in %s, ignoring: %s", lvalue, rvalue);
                         break;
                 }
+                if (r == 0)
+                        break;
 
                 if (u) {
                         r = unit_full_printf(u, word, &k);
@@ -2780,8 +2794,6 @@ int config_parse_unset_environ(
                 _cleanup_free_ char *word = NULL, *k = NULL;
 
                 r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
-                if (r == 0)
-                        break;
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0) {
@@ -2789,6 +2801,8 @@ int config_parse_unset_environ(
                                    "Trailing garbage in %s, ignoring: %s", lvalue, rvalue);
                         break;
                 }
+                if (r == 0)
+                        break;
 
                 if (u) {
                         r = unit_full_printf(u, word, &k);
@@ -2854,14 +2868,14 @@ int config_parse_log_extra_fields(
                 const char *eq;
 
                 r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
-                if (r == 0)
-                        return 0;
                 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)
+                        return 0;
 
                 r = unit_full_printf(u, word, &k);
                 if (r < 0) {
@@ -3066,8 +3080,6 @@ int config_parse_unit_requires_mounts_for(
                 _cleanup_free_ char *word = NULL, *resolved = NULL;
 
                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
-                if (r == 0)
-                        return 0;
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0) {
@@ -3075,6 +3087,8 @@ int config_parse_unit_requires_mounts_for(
                                    "Invalid syntax, ignoring: %s", rvalue);
                         return 0;
                 }
+                if (r == 0)
+                        return 0;
 
                 r = unit_full_printf(u, word, &resolved);
                 if (r < 0) {
@@ -3204,8 +3218,6 @@ int config_parse_syscall_filter(
                 int num;
 
                 r = extract_first_word(&p, &word, NULL, 0);
-                if (r == 0)
-                        return 0;
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0) {
@@ -3213,6 +3225,8 @@ int config_parse_syscall_filter(
                                    "Invalid syntax, ignoring: %s", rvalue);
                         return 0;
                 }
+                if (r == 0)
+                        return 0;
 
                 r = parse_syscall_and_errno(word, &name, &num);
                 if (r < 0) {
@@ -3290,14 +3304,14 @@ int config_parse_syscall_log(
                 _cleanup_free_ char *word = NULL;
 
                 r = extract_first_word(&p, &word, NULL, 0);
-                if (r == 0)
-                        return 0;
                 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)
+                        return 0;
 
                 r = seccomp_parse_syscall_filter(
                                 word, -1, c->syscall_log,
@@ -3335,8 +3349,6 @@ int config_parse_syscall_archs(
                 uint32_t a;
 
                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
-                if (r == 0)
-                        return 0;
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0) {
@@ -3344,6 +3356,8 @@ int config_parse_syscall_archs(
                                    "Invalid syntax, ignoring: %s", rvalue);
                         return 0;
                 }
+                if (r == 0)
+                        return 0;
 
                 r = seccomp_arch_from_string(word, &a);
                 if (r < 0) {
@@ -3424,6 +3438,13 @@ int config_parse_address_families(
                 return 0;
         }
 
+        if (streq(rvalue, "none")) {
+                /* Forbid all address families. */
+                c->address_families = set_free(c->address_families);
+                c->address_families_allow_list = true;
+                return 0;
+        }
+
         if (rvalue[0] == '~') {
                 invert = true;
                 rvalue++;
@@ -3442,8 +3463,6 @@ int config_parse_address_families(
                 int af;
 
                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
-                if (r == 0)
-                        return 0;
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0) {
@@ -3451,6 +3470,8 @@ int config_parse_address_families(
                                    "Invalid syntax, ignoring: %s", rvalue);
                         return 0;
                 }
+                if (r == 0)
+                        return 0;
 
                 af = af_from_name(word);
                 if (af < 0) {
@@ -3800,14 +3821,14 @@ int config_parse_delegate(
                         CGroupController cc;
 
                         r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
-                        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;
                         }
+                        if (r == 0)
+                                break;
 
                         cc = cgroup_controller_from_string(word);
                         if (cc < 0) {
@@ -3933,13 +3954,8 @@ int config_parse_device_allow(
         r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
         if (r == -ENOMEM)
                 return log_oom();
-        if (r < 0) {
+        if (r <= 0) {
                 log_syntax(unit, LOG_WARNING, filename, line, r,
-                           "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;
         }
@@ -4004,13 +4020,8 @@ int config_parse_io_device_weight(
         r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
         if (r == -ENOMEM)
                 return log_oom();
-        if (r < 0) {
+        if (r <= 0 || isempty(p)) {
                 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;
         }
@@ -4078,13 +4089,8 @@ int config_parse_io_device_latency(
         r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
         if (r == -ENOMEM)
                 return log_oom();
-        if (r < 0) {
+        if (r <= 0 || isempty(p)) {
                 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 latency from '%s', ignoring.", rvalue);
                 return 0;
         }
@@ -4153,13 +4159,8 @@ int config_parse_io_limit(
         r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
         if (r == -ENOMEM)
                 return log_oom();
-        if (r < 0) {
+        if (r <= 0 || isempty(p)) {
                 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;
         }
@@ -4244,13 +4245,8 @@ int config_parse_blockio_device_weight(
         r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
         if (r == -ENOMEM)
                 return log_oom();
-        if (r < 0) {
+        if (r <= 0 || isempty(p)) {
                 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;
         }
@@ -4322,13 +4318,8 @@ int config_parse_blockio_bandwidth(
         r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
         if (r == -ENOMEM)
                 return log_oom();
-        if (r < 0) {
+        if (r <= 0 || isempty(p)) {
                 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;
         }
@@ -4606,14 +4597,23 @@ int config_parse_load_credential(
                 log_syntax(unit, LOG_WARNING, filename, line, 0, "Credential name \"%s\" not valid, ignoring.", k);
                 return 0;
         }
-        r = unit_full_printf(u, p, &q);
-        if (r < 0) {
-                log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", p);
-                return 0;
-        }
-        if (path_is_absolute(q) ? !path_is_normalized(q) : !credential_name_valid(q)) {
-                log_syntax(unit, LOG_WARNING, filename, line, r, "Credential source \"%s\" not valid, ignoring.", q);
-                return 0;
+
+        if (isempty(p)) {
+                /* If only one field field is specified take it as shortcut for inheriting a credential named
+                 * the same way from our parent */
+                q = strdup(k);
+                if (!q)
+                        return log_oom();
+        } else {
+                r = unit_full_printf(u, p, &q);
+                if (r < 0) {
+                        log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", p);
+                        return 0;
+                }
+                if (path_is_absolute(q) ? !path_is_normalized(q) : !credential_name_valid(q)) {
+                        log_syntax(unit, LOG_WARNING, filename, line, r, "Credential source \"%s\" not valid, ignoring.", q);
+                        return 0;
+                }
         }
 
         r = strv_consume_pair(&context->load_credentials, TAKE_PTR(k), TAKE_PTR(q));
@@ -4721,14 +4721,14 @@ int config_parse_namespace_path_strv(
                 bool ignore_enoent = false, shall_prefix = false;
 
                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
-                if (r == 0)
-                        break;
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0) {
                         log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue);
                         return 0;
                 }
+                if (r == 0)
+                        break;
 
                 w = word;
                 if (startswith(w, "-")) {
@@ -4798,14 +4798,14 @@ int config_parse_temporary_filesystems(
                 const char *w;
 
                 r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
-                if (r == 0)
-                        return 0;
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0) {
                         log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue);
                         return 0;
                 }
+                if (r == 0)
+                        return 0;
 
                 w = word;
                 r = extract_first_word(&w, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
@@ -4872,14 +4872,14 @@ int config_parse_bind_paths(
                 bool rbind = true, ignore_enoent = false;
 
                 r = extract_first_word(&p, &source, ":" WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS);
-                if (r == 0)
-                        break;
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0) {
                         log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue);
                         return 0;
                 }
+                if (r == 0)
+                        break;
 
                 r = unit_full_printf(u, source, &sresolved);
                 if (r < 0) {
@@ -5570,6 +5570,142 @@ int config_parse_ip_filter_bpf_progs(
         return 0;
 }
 
+int config_parse_bpf_foreign_program(
+                const char *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_free_ char *resolved = NULL, *word = NULL;
+        CGroupContext *c = data;
+        Unit *u = userdata;
+        int attach_type, r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                while (c->bpf_foreign_programs)
+                        cgroup_context_remove_bpf_foreign_program(c, c->bpf_foreign_programs);
+
+                return 0;
+        }
+
+        r = extract_first_word(&rvalue, &word, ":", 0);
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r <= 0 || isempty(rvalue)) {
+                log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse foreign BPF program, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        attach_type = bpf_cgroup_attach_type_from_string(word);
+        if (attach_type < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown BPF attach type=%s, ignoring: %s", word, rvalue);
+                return 0;
+        }
+
+        r = unit_full_printf(u, rvalue, &resolved);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
+                return 0;
+        }
+
+        r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+        if (r < 0)
+                return 0;
+
+        r = cgroup_add_bpf_foreign_program(c, attach_type, resolved);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add foreign BPF program to cgroup context: %m");
+
+        return 0;
+}
+
+int config_parse_cgroup_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) {
+        _cleanup_free_ CGroupSocketBindItem *item = NULL;
+        const char *user_port;
+        uint16_t nr_ports = 0, port_min = 0;
+        CGroupSocketBindItem **head = data;
+        _cleanup_free_ char *word = NULL;
+        int af, r;
+
+        if (isempty(rvalue)) {
+                cgroup_context_remove_socket_bind(head);
+                return 0;
+        }
+
+        r = extract_first_word(&rvalue, &word, ":", 0);
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r <= 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Unable to parse %s= assignment, ignoring: %s", lvalue, rvalue);
+                return 0;
+        }
+
+        if (rvalue) {
+                if (streq(word, "IPv4"))
+                        af = AF_INET;
+                else if (streq(word, "IPv6"))
+                        af = AF_INET6;
+                else {
+                        log_syntax(unit, LOG_WARNING, filename, line, 0,
+                                   "Only IPv4 and IPv6 protocols are supported, ignoring.");
+                        return 0;
+                }
+
+                user_port = rvalue;
+        } else {
+                af = AF_UNSPEC;
+                user_port = word;
+        }
+
+        if (!streq(user_port, "any")) {
+                uint16_t port_max;
+
+                r = parse_ip_port_range(user_port, &port_min, &port_max);
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_WARNING, filename, line, r,
+                                   "Invalid port or port range, ignoring: %m");
+                        return 0;
+                }
+
+                nr_ports = 1 + port_max - port_min;
+        }
+
+        item = new(CGroupSocketBindItem, 1);
+        if (!item)
+                return log_oom();
+        *item = (CGroupSocketBindItem) {
+                .address_family = af,
+                .nr_ports = nr_ports,
+                .port_min = port_min,
+        };
+
+        LIST_PREPEND(socket_bind_items, *head, TAKE_PTR(item));
+
+        return 0;
+}
+
 static int merge_by_names(Unit **u, Set *names, const char *id) {
         char *k;
         int r;
@@ -5748,6 +5884,7 @@ void unit_dump_config_items(FILE *f) {
                 { config_parse_unit_deps,             "UNIT [...]" },
                 { config_parse_exec,                  "PATH [ARGUMENT [...]]" },
                 { config_parse_service_type,          "SERVICETYPE" },
+                { config_parse_service_exit_type,     "SERVICEEXITTYPE" },
                 { config_parse_service_restart,       "SERVICERESTART" },
                 { config_parse_service_timeout_failure_mode, "TIMEOUTMODE" },
                 { config_parse_kill_mode,             "KILLMODE" },
index b8a6d5feadc57fed460cfea1bf516c8e6c1af75e..d722041f962363981cd2fd397e71f05d17b4b03f 100644 (file)
@@ -32,6 +32,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout);
 CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout_abort);
 CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout_failure_mode);
 CONFIG_PARSER_PROTOTYPE(config_parse_service_type);
+CONFIG_PARSER_PROTOTYPE(config_parse_service_exit_type);
 CONFIG_PARSER_PROTOTYPE(config_parse_service_restart);
 CONFIG_PARSER_PROTOTYPE(config_parse_socket_bindtodevice);
 CONFIG_PARSER_PROTOTYPE(config_parse_exec_output);
@@ -139,6 +140,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_swap_priority);
 CONFIG_PARSER_PROTOTYPE(config_parse_mount_images);
 CONFIG_PARSER_PROTOTYPE(config_parse_socket_timestamping);
 CONFIG_PARSER_PROTOTYPE(config_parse_extension_images);
+CONFIG_PARSER_PROTOTYPE(config_parse_bpf_foreign_program);
+CONFIG_PARSER_PROTOTYPE(config_parse_cgroup_socket_bind);
 
 /* gperf prototypes */
 const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
index 0ddd6298513cba22f08be59d99ed3c85b5e9a550..12948ca964c6f082f3cf21f4aeebd1e2456d9280 100644 (file)
@@ -1198,8 +1198,8 @@ static void bump_file_max_and_nr_open(void) {
 #endif
 
 #if BUMP_PROC_SYS_FS_FILE_MAX
-        /* The maximum the kernel allows for this since 5.2 is LONG_MAX, use that. (Previously thing where
-         * different but the operation would fail silently.) */
+        /* The maximum the kernel allows for this since 5.2 is LONG_MAX, use that. (Previously things were
+         * different, but the operation would fail silently.) */
         r = sysctl_writef("fs/file-max", "%li\n", LONG_MAX);
         if (r < 0)
                 log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to bump fs.file-max, ignoring: %m");
@@ -1367,7 +1367,7 @@ static int status_welcome(void) {
 
 static int write_container_id(void) {
         const char *c;
-        int r;
+        int r = 0;  /* avoid false maybe-uninitialized warning */
 
         c = getenv("container");
         if (isempty(c))
@@ -2036,7 +2036,7 @@ static void log_execution_mode(bool *ret_first_boot) {
                 }
         } else {
                 if (DEBUG_LOGGING) {
-                        _cleanup_free_ char *t;
+                        _cleanup_free_ char *t = NULL;
 
                         t = uid_to_name(getuid());
                         log_debug("systemd " GIT_VERSION " running in %suser mode for user " UID_FMT "/%s. (%s)",
@@ -2549,18 +2549,16 @@ static void setup_console_terminal(bool skip_setup) {
 
 static bool early_skip_setup_check(int argc, char *argv[]) {
         bool found_deserialize = false;
-        int i;
 
         /* Determine if this is a reexecution or normal bootup. We do the full command line parsing much later, so
          * let's just have a quick peek here. Note that if we have switched root, do all the special setup things
          * anyway, even if in that case we also do deserialization. */
 
-        for (i = 1; i < argc; i++) {
+        for (int 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"))
                         found_deserialize = true;
-        }
 
         return found_deserialize; /* When we are deserializing, then we are reexecuting, hence avoid the extensive setup */
 }
index 629966ea60edef121b4afb36b6448c123293996b..30aadb0944d2cb45e3cef2676ce8378932f3f7a3 100644 (file)
@@ -30,6 +30,7 @@
 #include "clean-ipc.h"
 #include "clock-util.h"
 #include "core-varlink.h"
+#include "creds-util.h"
 #include "dbus-job.h"
 #include "dbus-manager.h"
 #include "dbus-unit.h"
@@ -49,8 +50,8 @@
 #include "install.h"
 #include "io-util.h"
 #include "label.h"
-#include "locale-setup.h"
 #include "load-fragment.h"
+#include "locale-setup.h"
 #include "log.h"
 #include "macro.h"
 #include "manager.h"
@@ -247,7 +248,7 @@ static void manager_print_jobs_in_progress(Manager *m) {
 }
 
 static int have_ask_password(void) {
-        _cleanup_closedir_ DIR *dir;
+        _cleanup_closedir_ DIR *dir = NULL;
         struct dirent *de;
 
         dir = opendir("/run/systemd/ask-password");
@@ -687,7 +688,8 @@ static int manager_setup_prefix(Manager *m) {
         for (ExecDirectoryType i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++) {
                 r = sd_path_lookup(p[i].type, p[i].suffix, &m->prefix[i]);
                 if (r < 0)
-                        return r;
+                        return log_warning_errno(r, "Failed to lookup %s path: %m",
+                                                 exec_directory_type_to_string(i));
         }
 
         return 0;
@@ -852,8 +854,8 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager
         if (r < 0)
                 return r;
 
-        e = secure_getenv("CREDENTIALS_DIRECTORY");
-        if (e) {
+        r = get_credentials_dir(&e);
+        if (r >= 0) {
                 m->received_credentials = strdup(e);
                 if (!m->received_credentials)
                         return -ENOMEM;
@@ -1280,7 +1282,6 @@ static unsigned manager_dispatch_stop_when_unneeded_queue(Manager *m) {
 
         while ((u = m->stop_when_unneeded_queue)) {
                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-                assert(m->stop_when_unneeded_queue);
 
                 assert(u->in_stop_when_unneeded_queue);
                 LIST_REMOVE(stop_when_unneeded_queue, m->stop_when_unneeded_queue, u);
@@ -1731,13 +1732,13 @@ int manager_add_job(
         assert(mode < _JOB_MODE_MAX);
 
         if (mode == JOB_ISOLATE && type != JOB_START)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
 
         if (mode == JOB_ISOLATE && !unit->allow_isolate)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
+                return sd_bus_error_set(error, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
 
         if (mode == JOB_TRIGGERING && type != JOB_STOP)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "--job-mode=triggering is only valid for stop.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "--job-mode=triggering is only valid for stop.");
 
         log_unit_debug(unit, "Trying to enqueue job %s/%s/%s", unit->id, job_type_to_string(type), job_mode_to_string(mode));
 
index a389c906b368609084a171fd8cd9235a56ef8110..c5c9e8cbe81ac9b661d82c4255fb222426a74701 100644 (file)
@@ -11,6 +11,8 @@ libcore_sources = '''
         bpf-devices.h
         bpf-firewall.c
         bpf-firewall.h
+        bpf-foreign.c
+        bpf-foreign.h
         cgroup.c
         cgroup.h
         core-varlink.c
@@ -103,6 +105,8 @@ libcore_sources = '''
         slice.h
         smack-setup.c
         smack-setup.h
+        socket-bind.c
+        socket-bind.h
         socket.c
         socket.h
         swap.c
@@ -121,6 +125,11 @@ libcore_sources = '''
         unit.h
 '''.split()
 
+subdir('bpf/socket_bind')
+if conf.get('BPF_FRAMEWORK') == 1
+        libcore_sources += [socket_bind_skel_h]
+endif
+
 load_fragment_gperf_gperf = custom_target(
         'load-fragment-gperf.gperf',
         input : 'load-fragment-gperf.gperf.m4',
@@ -150,6 +159,7 @@ libcore = static_library(
         include_directories : includes,
         dependencies : [versiondep,
                         threads,
+                        libbpf,
                         librt,
                         libseccomp,
                         libpam,
index d47531408baac5f5ab8723433716e7de85d634c7..acf8d14b67f295ede18dd43cd91153e0ab93b0f4 100644 (file)
@@ -1802,7 +1802,6 @@ int setup_namespace(
                 const char *propagate_dir,
                 const char *incoming_dir,
                 const char *notify_socket,
-                DissectImageFlags dissect_image_flags,
                 char **error_path) {
 
         _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
@@ -1813,6 +1812,14 @@ int setup_namespace(
         MountEntry *m = NULL, *mounts = NULL;
         bool require_prefix = false, setup_propagate = false;
         const char *root, *extension_dir = "/run/systemd/unit-extensions";
+        DissectImageFlags dissect_image_flags =
+                DISSECT_IMAGE_GENERIC_ROOT |
+                DISSECT_IMAGE_REQUIRE_ROOT |
+                DISSECT_IMAGE_DISCARD_ON_LOOP |
+                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                DISSECT_IMAGE_FSCK |
+                DISSECT_IMAGE_USR_NO_ROOT |
+                DISSECT_IMAGE_GROWFS;
         size_t n_mounts;
         int r;
 
@@ -1825,8 +1832,6 @@ int setup_namespace(
                 mount_flags = MS_SHARED;
 
         if (root_image) {
-                dissect_image_flags |= DISSECT_IMAGE_REQUIRE_ROOT;
-
                 /* Make the whole image read-only if we can determine that we only access it in a read-only fashion. */
                 if (root_read_only(read_only_paths,
                                    ns_info->protect_system) &&
@@ -1849,7 +1854,7 @@ int setup_namespace(
 
                 r = loop_device_make_by_path(
                                 root_image,
-                                FLAGS_SET(dissect_image_flags, DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : -1 /* < 0 means writable if possible, read-only as fallback */,
+                                FLAGS_SET(dissect_image_flags, DISSECT_IMAGE_DEVICE_READ_ONLY) ? O_RDONLY : -1 /* < 0 means writable if possible, read-only as fallback */,
                                 FLAGS_SET(dissect_image_flags, DISSECT_IMAGE_NO_PARTITION_TABLE) ? 0 : LO_FLAGS_PARTSCAN,
                                 &loop_device);
                 if (r < 0)
@@ -1859,6 +1864,8 @@ int setup_namespace(
                                 loop_device->fd,
                                 &verity,
                                 root_image_options,
+                                loop_device->uevent_seqnum_not_before,
+                                loop_device->timestamp_not_before,
                                 dissect_image_flags,
                                 &dissected_image);
                 if (r < 0)
@@ -2088,7 +2095,7 @@ int setup_namespace(
                 }
 
                 if (log_namespace) {
-                        _cleanup_free_ char *q;
+                        _cleanup_free_ char *q = NULL;
 
                         q = strjoin("/run/systemd/journal.", log_namespace);
                         if (!q) {
@@ -2327,7 +2334,7 @@ int mount_image_add(MountImage **m, size_t *n, const MountImage *item) {
         }
 
         LIST_FOREACH(mount_options, i, item->mount_options) {
-                _cleanup_(mount_options_free_allp) MountOptions *o;
+                _cleanup_(mount_options_free_allp) MountOptions *o = NULL;
 
                 o = new(MountOptions, 1);
                 if (!o)
index 2806db8fd1bf0aace57b52a8d4628f39f77ace16..737d6eae8b1e5d25d66fdc4d9e280bb971b4d94f 100644 (file)
@@ -143,7 +143,6 @@ int setup_namespace(
                 const char *propagate_dir,
                 const char *incoming_dir,
                 const char *notify_socket,
-                DissectImageFlags dissected_image_flags,
                 char **error_path);
 
 #define RUN_SYSTEMD_EMPTY "/run/systemd/empty"
index b954ee1f47d30f33d84e05db5e08f792f1380bda..04084bf63e412727c37475f136e4ad23a6246902 100644 (file)
@@ -316,7 +316,7 @@ static int path_add_trigger_dependencies(Path *p) {
 
         assert(p);
 
-        if (!hashmap_isempty(UNIT(p)->dependencies[UNIT_TRIGGERS]))
+        if (UNIT_TRIGGER(UNIT(p)))
                 return 0;
 
         r = unit_load_related_unit(UNIT(p), ".service", &x);
index 18f6fb59bc0a0a75b17799032dcc887940937c99..cdb82dd8947ad33d46f2bcc52773aa0d7581d4ca 100644 (file)
@@ -250,7 +250,7 @@ int mac_selinux_generic_access_check(
                         if (!enforce)
                                 return 0;
 
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
                 }
 
                 tclass = "system";
@@ -270,11 +270,12 @@ int mac_selinux_generic_access_check(
                 r = errno_or_else(EPERM);
 
                 if (enforce)
-                        sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
+                        sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
         }
 
-        log_debug_errno(r, "SELinux access check scon=%s tcon=%s tclass=%s perm=%s state=%s path=%s cmdline=%s: %m",
-                        scon, fcon, tclass, permission, enforce ? "enforcing" : "permissive", path, cl);
+        log_full_errno_zerook(LOG_DEBUG, r,
+                              "SELinux access check scon=%s tcon=%s tclass=%s perm=%s state=%s path=%s cmdline=%s: %m",
+                              scon, fcon, tclass, permission, enforce ? "enforcing" : "permissive", path, cl);
         return enforce ? r : 0;
 }
 
index df3ed05cfc6e8e6114af3b6f52dd0c45816dd858..1cce15eb76626884dd692d06c42e2e2f9922ab92 100644 (file)
@@ -1621,18 +1621,25 @@ static int control_pid_good(Service *s) {
         return s->control_pid > 0;
 }
 
-static int cgroup_good(Service *s) {
-        int r;
-
+static int cgroup_empty(Service *s) {
         assert(s);
 
-        /* Returns 0 if the cgroup is empty or doesn't exist, > 0 if it is exists and is populated, < 0 if we can't
-         * figure it out */
+        /* Returns 0 if there is no cgroup, > 0 if is empty or doesn't exist, < 0 if we can't figure it out */
 
         if (!UNIT(s)->cgroup_path)
                 return 0;
 
-        r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path);
+        return cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path);
+}
+
+
+static int cgroup_good(Service *s) {
+        int r;
+
+        /* Returns 0 if the cgroup is empty or doesn't exist, > 0 if it is exists and is populated, < 0 if we can't
+         * figure it out */
+
+        r = cgroup_empty(s);
         if (r < 0)
                 return r;
 
@@ -2270,12 +2277,11 @@ static void service_enter_restart(Service *s) {
         s->n_restarts ++;
         s->flush_n_restarts = false;
 
-        log_struct(LOG_INFO,
-                   "MESSAGE_ID=" SD_MESSAGE_UNIT_RESTART_SCHEDULED_STR,
-                   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);
+        log_unit_struct(UNIT(s), LOG_INFO,
+                        "MESSAGE_ID=" SD_MESSAGE_UNIT_RESTART_SCHEDULED_STR,
+                        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);
 
         /* Notify clients about changed restart counter */
         unit_add_to_dbus_queue(UNIT(s));
@@ -2718,7 +2724,7 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
         return 0;
 }
 
-static int service_deserialize_exec_command(
+int service_deserialize_exec_command(
                 Unit *u,
                 const char *key,
                 const char *value) {
@@ -2776,9 +2782,6 @@ static int service_deserialize_exec_command(
                 case STATE_EXEC_COMMAND_PATH:
                         path = TAKE_PTR(arg);
                         state = STATE_EXEC_COMMAND_ARGS;
-
-                        if (!path_is_absolute(path))
-                                return -EINVAL;
                         break;
                 case STATE_EXEC_COMMAND_ARGS:
                         r = strv_extend(&argv, arg);
@@ -2786,13 +2789,14 @@ static int service_deserialize_exec_command(
                                 return -ENOMEM;
                         break;
                 default:
-                        assert_not_reached("Unknown error at deserialization of exec command");
-                        break;
+                        assert_not_reached("Logic error in exec command deserialization");
                 }
         }
 
         if (state != STATE_EXEC_COMMAND_ARGS)
                 return -EINVAL;
+        if (strv_isempty(argv))
+                return -EINVAL; /* At least argv[0] must be always present. */
 
         /* Let's check whether exec command on given offset matches data that we just deserialized */
         for (command = s->exec_command[id], i = 0; command; command = command->command_next, i++) {
@@ -3398,7 +3402,14 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         else
                 assert_not_reached("Unknown code");
 
-        if (s->main_pid == pid) {
+        /* Services with ExitType=cgroup ignore the main PID for purposes of exit status */
+        if (s->exit_type == SERVICE_EXIT_CGROUP && s->main_pid == pid) {
+                service_unwatch_main_pid(s);
+                s->main_pid_known = false;
+        }
+
+        if ((s->exit_type == SERVICE_EXIT_MAIN && s->main_pid == pid) ||
+            (s->exit_type == SERVICE_EXIT_CGROUP && cgroup_empty(s) && !control_pid_good(s))) {
                 /* Forking services may occasionally move to a new PID.
                  * As long as they update the PID file before exiting the old
                  * PID, they're fine. */
@@ -3431,7 +3442,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 
                 unit_log_process_exit(
                                 u,
-                                "Main process",
+                                s->exit_type == SERVICE_EXIT_CGROUP ? "Last process" : "Main process",
                                 service_exec_command_to_string(SERVICE_EXEC_START),
                                 f == SERVICE_SUCCESS,
                                 code, status);
@@ -3460,6 +3471,15 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 
                         case SERVICE_START_POST:
                         case SERVICE_RELOAD:
+                                /* If neither main nor control processes are running then
+                                 * the current state can never exit cleanly, hence immediately
+                                 * terminate the service. */
+                                if (control_pid_good(s) <= 0)
+                                        service_enter_stop(s, f);
+
+                                /* Otherwise need to wait until the operation is done. */
+                                break;
+
                         case SERVICE_STOP:
                                 /* Need to wait until the operation is
                                  * done */
@@ -4255,7 +4275,7 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context
         if (getpeername_pretty(fd, true, &peer) >= 0) {
 
                 if (UNIT(s)->description) {
-                        _cleanup_free_ char *a;
+                        _cleanup_free_ char *a = NULL;
 
                         a = strjoin(UNIT(s)->description, " (", peer, ")");
                         if (!a)
@@ -4448,6 +4468,13 @@ static const char* const service_type_table[_SERVICE_TYPE_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType);
 
+static const char* const service_exit_type_table[_SERVICE_EXIT_TYPE_MAX] = {
+        [SERVICE_EXIT_MAIN] = "main",
+        [SERVICE_EXIT_CGROUP] = "cgroup",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(service_exit_type, ServiceExitType);
+
 static const char* const service_exec_command_table[_SERVICE_EXEC_COMMAND_MAX] = {
         [SERVICE_EXEC_CONDITION] = "ExecCondition",
         [SERVICE_EXEC_START_PRE] = "ExecStartPre",
index af474aa40e90a0ebe6d7aac8a47cfafb987702b9..0d51fc31535acabcf919799ef999b068ef18aa25 100644 (file)
@@ -35,6 +35,13 @@ typedef enum ServiceType {
         _SERVICE_TYPE_INVALID = -EINVAL,
 } ServiceType;
 
+typedef enum ServiceExitType {
+        SERVICE_EXIT_MAIN,    /* we consider the main PID when deciding if the service exited */
+        SERVICE_EXIT_CGROUP,  /* we wait for the last process in the cgroup to exit */
+        _SERVICE_EXIT_TYPE_MAX,
+        _SERVICE_EXIT_TYPE_INVALID = -EINVAL,
+} ServiceExitType;
+
 typedef enum ServiceExecCommand {
         SERVICE_EXEC_CONDITION,
         SERVICE_EXEC_START_PRE,
@@ -97,6 +104,7 @@ struct Service {
         Unit meta;
 
         ServiceType type;
+        ServiceExitType exit_type;
         ServiceRestart restart;
         ExitStatusSet restart_prevent_status;
         ExitStatusSet restart_force_status;
@@ -226,6 +234,9 @@ ServiceRestart service_restart_from_string(const char *s) _pure_;
 const char* service_type_to_string(ServiceType i) _const_;
 ServiceType service_type_from_string(const char *s) _pure_;
 
+const char* service_exit_type_to_string(ServiceExitType i) _const_;
+ServiceExitType service_exit_type_from_string(const char *s) _pure_;
+
 const char* service_exec_command_to_string(ServiceExecCommand i) _const_;
 ServiceExecCommand service_exec_command_from_string(const char *s) _pure_;
 
@@ -244,3 +255,6 @@ ServiceTimeoutFailureMode service_timeout_failure_mode_from_string(const char *s
 DEFINE_CAST(SERVICE, Service);
 
 #define STATUS_TEXT_MAX (16U*1024U)
+
+/* Only exported for unit tests */
+int service_deserialize_exec_command(Unit *u, const char *key, const char *value);
diff --git a/src/core/socket-bind.c b/src/core/socket-bind.c
new file mode 100644 (file)
index 0000000..ed6c36c
--- /dev/null
@@ -0,0 +1,238 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#if BPF_FRAMEWORK
+#include <bpf/bpf.h>
+#endif
+
+#include "fd-util.h"
+#include "socket-bind.h"
+
+#if BPF_FRAMEWORK
+/* libbpf, clang, llvm and bpftool compile time dependencies are satisfied */
+#include "bpf-link.h"
+#include "bpf/socket_bind/socket-bind.skel.h"
+#include "bpf/socket_bind/socket-bind-api.bpf.h"
+
+static struct socket_bind_bpf *socket_bind_bpf_free(struct socket_bind_bpf *obj) {
+        /* socket_bind_bpf__destroy handles object == NULL case */
+        (void) socket_bind_bpf__destroy(obj);
+
+        return NULL;
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct socket_bind_bpf *, socket_bind_bpf_free);
+
+static int update_rules_map(
+                int map_fd, CGroupSocketBindItem *head) {
+        CGroupSocketBindItem *item;
+        uint32_t i = 0;
+
+        assert(map_fd >= 0);
+
+        LIST_FOREACH(socket_bind_items, item, head) {
+                const uint32_t key = i++;
+                struct socket_bind_rule val = {
+                        .address_family = (uint32_t) item->address_family,
+                        .nr_ports = item->nr_ports,
+                        .port_min = item->port_min,
+                };
+
+                if (bpf_map_update_elem(map_fd, &key, &val, BPF_ANY) != 0)
+                        return -errno;
+        }
+
+        return 0;
+}
+
+static int prepare_socket_bind_bpf(
+                Unit *u, CGroupSocketBindItem *allow, CGroupSocketBindItem *deny, struct socket_bind_bpf **ret_obj) {
+        _cleanup_(socket_bind_bpf_freep) struct socket_bind_bpf *obj = 0;
+        uint32_t allow_count = 0, deny_count = 0;
+        int allow_map_fd, deny_map_fd, r;
+        CGroupSocketBindItem *item;
+
+        assert(ret_obj);
+
+        LIST_FOREACH(socket_bind_items, item,  allow)
+                allow_count++;
+
+        LIST_FOREACH(socket_bind_items, item, deny)
+                deny_count++;
+
+        if (allow_count > SOCKET_BIND_MAX_RULES)
+                return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL),
+                                "Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES);
+
+        if (deny_count > SOCKET_BIND_MAX_RULES)
+                return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL),
+                                "Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES);
+
+        obj = socket_bind_bpf__open();
+        if (!obj)
+                return log_unit_error_errno(u, SYNTHETIC_ERRNO(ENOMEM), "Failed to open BPF object");
+
+        if (bpf_map__resize(obj->maps.sd_bind_allow, MAX(allow_count, 1u)) != 0)
+                return log_unit_error_errno(u, errno,
+                                "Failed to resize BPF map '%s': %m", bpf_map__name(obj->maps.sd_bind_allow));
+
+        if (bpf_map__resize(obj->maps.sd_bind_deny, MAX(deny_count, 1u)) != 0)
+                return log_unit_error_errno(u, errno,
+                                "Failed to resize BPF map '%s': %m", bpf_map__name(obj->maps.sd_bind_deny));
+
+        if (socket_bind_bpf__load(obj) != 0)
+                return log_unit_error_errno(u, errno, "Failed to load BPF object");
+
+        allow_map_fd = bpf_map__fd(obj->maps.sd_bind_allow);
+        assert(allow_map_fd >= 0);
+
+        r = update_rules_map(allow_map_fd, allow);
+        if (r < 0)
+                return log_unit_error_errno(
+                                u, r, "Failed to put socket bind allow rules into BPF map '%s'",
+                                bpf_map__name(obj->maps.sd_bind_allow));
+
+        deny_map_fd = bpf_map__fd(obj->maps.sd_bind_deny);
+        assert(deny_map_fd >= 0);
+
+        r = update_rules_map(deny_map_fd, deny);
+        if (r < 0)
+                return log_unit_error_errno(
+                                u, r, "Failed to put socket bind deny rules into BPF map '%s'",
+                                bpf_map__name(obj->maps.sd_bind_deny));
+
+        *ret_obj = TAKE_PTR(obj);
+        return 0;
+}
+
+int socket_bind_supported(void) {
+        _cleanup_(socket_bind_bpf_freep) struct socket_bind_bpf *obj = NULL;
+
+        int r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
+        if (r < 0)
+                return log_error_errno(r, "Can't determine whether the unified hierarchy is used: %m");
+
+        if (r == 0) {
+                log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+                                "Not running with unified cgroup hierarchy, BPF is not supported");
+                return 0;
+        }
+
+        if (!bpf_probe_prog_type(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, /*ifindex=*/0)) {
+                log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+                                "BPF program type cgroup_sock_addr is not supported");
+                return 0;
+        }
+
+        r = prepare_socket_bind_bpf(/*unit=*/NULL, /*allow_rules=*/NULL, /*deny_rules=*/NULL, &obj);
+        if (r < 0) {
+                log_debug_errno(r, "BPF based socket_bind is not supported: %m");
+                return 0;
+        }
+
+        return can_link_bpf_program(obj->progs.sd_bind4);
+}
+
+int socket_bind_add_initial_link_fd(Unit *u, int fd) {
+        int r;
+
+        assert(u);
+
+        if (!u->initial_socket_bind_link_fds) {
+                u->initial_socket_bind_link_fds = fdset_new();
+                if (!u->initial_socket_bind_link_fds)
+                        return log_oom();
+        }
+
+        r = fdset_put(u->initial_socket_bind_link_fds, fd);
+        if (r < 0)
+                return log_unit_error_errno(u, r, "Failed to put socket-bind BPF link fd %d to initial fdset", fd);
+
+        return 0;
+}
+
+static int socket_bind_install_impl(Unit *u) {
+        _cleanup_(bpf_link_freep) struct bpf_link *ipv4 = NULL, *ipv6 = NULL;
+        _cleanup_(socket_bind_bpf_freep) struct socket_bind_bpf *obj = NULL;
+        _cleanup_free_ char *cgroup_path = NULL;
+        _cleanup_close_ int cgroup_fd = -1;
+        CGroupContext *cc;
+        int r;
+
+        cc = unit_get_cgroup_context(u);
+        if (!cc)
+                return 0;
+
+        r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &cgroup_path);
+        if (r < 0)
+                return log_unit_error_errno(u, r, "Failed to get cgroup path: %m");
+
+        if (!cc->socket_bind_allow && !cc->socket_bind_deny)
+                return 0;
+
+        r = prepare_socket_bind_bpf(u, cc->socket_bind_allow, cc->socket_bind_deny, &obj);
+        if (r < 0)
+                return log_unit_error_errno(u, r, "Failed to load BPF object: %m");
+
+        cgroup_fd = open(cgroup_path, O_RDONLY | O_CLOEXEC, 0);
+        if (cgroup_fd < 0)
+                return log_unit_error_errno(
+                                u, errno, "Failed to open cgroup=%s for reading", cgroup_path);
+
+        ipv4 = bpf_program__attach_cgroup(obj->progs.sd_bind4, cgroup_fd);
+        r = libbpf_get_error(ipv4);
+        if (r != 0)
+                return log_unit_error_errno(u, r, "Failed to link '%s' cgroup-bpf program",
+                                bpf_program__name(obj->progs.sd_bind4));
+
+        ipv6 = bpf_program__attach_cgroup(obj->progs.sd_bind6, cgroup_fd);
+        r = libbpf_get_error(ipv6);
+        if (r != 0)
+                return log_unit_error_errno(u, r, "Failed to link '%s' cgroup-bpf program",
+                                bpf_program__name(obj->progs.sd_bind6));
+
+        u->ipv4_socket_bind_link = TAKE_PTR(ipv4);
+        u->ipv6_socket_bind_link = TAKE_PTR(ipv6);
+
+        return 0;
+}
+
+int socket_bind_install(Unit *u) {
+        int r = socket_bind_install_impl(u);
+        if (r == -ENOMEM)
+                return r;
+
+        fdset_close(u->initial_socket_bind_link_fds);
+
+        return r;
+}
+
+int serialize_socket_bind(Unit *u, FILE *f, FDSet *fds) {
+        int r;
+
+        assert(u);
+
+        r = serialize_bpf_link(f, fds, "ipv4-socket-bind-bpf-link", u->ipv4_socket_bind_link);
+        if (r < 0)
+                return r;
+
+        return serialize_bpf_link(f, fds, "ipv6-socket-bind-bpf-link", u->ipv6_socket_bind_link);
+}
+
+#else /* ! BPF_FRAMEWORK */
+int socket_bind_supported(void) {
+        return 0;
+}
+
+int socket_bind_add_initial_link_fd(Unit *u, int fd) {
+        return 0;
+}
+
+int socket_bind_install(Unit *u) {
+        log_unit_debug(u, "Failed to install socket bind: BPF framework is not supported");
+        return 0;
+}
+
+int serialize_socket_bind(Unit *u, FILE *f, FDSet *fds) {
+        return 0;
+}
+#endif
diff --git a/src/core/socket-bind.h b/src/core/socket-bind.h
new file mode 100644 (file)
index 0000000..2a6e71a
--- /dev/null
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "fdset.h"
+#include "unit.h"
+
+int socket_bind_supported(void);
+
+/* Add BPF link fd created before daemon-reload or daemon-reexec.
+ * FDs will be closed at the end of socket_bind_install. */
+int socket_bind_add_initial_link_fd(Unit *u, int fd);
+
+int socket_bind_install(Unit *u);
+
+int serialize_socket_bind(Unit *u, FILE *f, FDSet *fds);
index fa6fb690c7806a11348de5573089e1469e62f253..97325d1811bdfb7b4ecd0ccbc2fa20969f1da3ed 100644 (file)
@@ -31,7 +31,6 @@
 #NUMAMask=
 #RuntimeWatchdogSec=0
 #RebootWatchdogSec=10min
-#ShutdownWatchdogSec=10min
 #KExecWatchdogSec=0
 #WatchdogDevice=
 #CapabilityBoundingSet=
@@ -72,3 +71,4 @@
 #DefaultLimitNICE=
 #DefaultLimitRTPRIO=
 #DefaultLimitRTTIME=
+#DefaultOOMPolicy=stop
index 32abdb74d76c52abdff304864da205cd31864dde..b0caaf385041a9cbc680200fdb0fdd57badae518 100644 (file)
@@ -124,7 +124,7 @@ static int timer_add_trigger_dependencies(Timer *t) {
 
         assert(t);
 
-        if (!hashmap_isempty(UNIT(t)->dependencies[UNIT_TRIGGERS]))
+        if (UNIT_TRIGGER(UNIT(t)))
                 return 0;
 
         r = unit_load_related_unit(UNIT(t), ".service", &x);
index 3f099248ce680e7d9d2e7251d9703bc3c8fbbe3a..509210ad5e228eecca7809d663cbae7390ae07d6 100644 (file)
@@ -7,6 +7,7 @@
 #include "format-util.h"
 #include "parse-util.h"
 #include "serialize.h"
+#include "socket-bind.h"
 #include "string-table.h"
 #include "unit-serialize.h"
 #include "user-util.h"
@@ -151,6 +152,8 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
         (void) serialize_cgroup_mask(f, "cgroup-enabled-mask", u->cgroup_enabled_mask);
         (void) serialize_cgroup_mask(f, "cgroup-invalidated-mask", u->cgroup_invalidated_mask);
 
+        (void) serialize_socket_bind(u, f, fds);
+
         if (uid_is_valid(u->ref_uid))
                 (void) serialize_item_format(f, "ref-uid", UID_FMT, u->ref_uid);
         if (gid_is_valid(u->ref_gid))
@@ -362,6 +365,23 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
                 else if (MATCH_DESERIALIZE_IMMEDIATE("cgroup-invalidated-mask", l, v, cg_mask_from_string, u->cgroup_invalidated_mask))
                         continue;
 
+                else if (STR_IN_SET(l, "ipv4-socket-bind-bpf-link-fd", "ipv6-socket-bind-bpf-link-fd")) {
+                        int fd;
+
+                        if (safe_atoi(v, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
+                                log_unit_debug(u, "Failed to parse %s value: %s, ignoring.", l, v);
+                        else {
+                                if (fdset_remove(fds, fd) < 0) {
+                                        log_unit_debug(u, "Failed to remove %s value=%d from fdset", l, fd);
+
+                                        continue;
+                                }
+
+                                (void) socket_bind_add_initial_link_fd(u, fd);
+                        }
+                        continue;
+                }
+
                 else if (streq(l, "ref-uid")) {
                         uid_t uid;
 
index 2c5dc54379a77e0e86f2816ba79c58a91ee6e6d3..67d811d7dd9d8dbaf610b96fcf8703e8d24966ef 100644 (file)
@@ -11,6 +11,7 @@
 #include "all-units.h"
 #include "alloc-util.h"
 #include "bpf-firewall.h"
+#include "bpf-foreign.h"
 #include "bus-common-errors.h"
 #include "bus-util.h"
 #include "cgroup-setup.h"
@@ -40,6 +41,7 @@
 #include "rm-rf.h"
 #include "set.h"
 #include "signal-util.h"
+#include "socket-bind.h"
 #include "sparse-endian.h"
 #include "special.h"
 #include "specifier.h"
@@ -55,6 +57,9 @@
 #include "unit.h"
 #include "user-util.h"
 #include "virt.h"
+#if BPF_FRAMEWORK
+#include "bpf-link.h"
+#endif
 
 /* Thresholds for logging at INFO level about resource consumption */
 #define MENTIONWORTHY_CPU_NSEC (1 * NSEC_PER_SEC)
@@ -556,7 +561,7 @@ static void unit_free_requires_mounts_for(Unit *u) {
         assert(u);
 
         for (;;) {
-                _cleanup_free_ char *path;
+                _cleanup_free_ char *path = NULL;
 
                 path = hashmap_steal_first_key(u->requires_mounts_for);
                 if (!path)
@@ -662,6 +667,13 @@ Unit* unit_free(Unit *u) {
         if (u->on_console)
                 manager_unref_console(u->manager);
 
+
+        fdset_free(u->initial_socket_bind_link_fds);
+#if BPF_FRAMEWORK
+        bpf_link_free(u->ipv4_socket_bind_link);
+        bpf_link_free(u->ipv6_socket_bind_link);
+#endif
+
         unit_release_cgroup(u);
 
         if (!MANAGER_IS_RELOADING(u->manager))
@@ -723,6 +735,8 @@ Unit* unit_free(Unit *u) {
         set_free(u->ip_bpf_custom_ingress_installed);
         set_free(u->ip_bpf_custom_egress_installed);
 
+        hashmap_free(u->bpf_foreign_by_key);
+
         bpf_program_unref(u->bpf_device_control_installed);
 
         condition_free_list(u->conditions);
@@ -1060,7 +1074,7 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
 
                 char **dp;
                 STRV_FOREACH(dp, c->directories[dt].paths) {
-                        _cleanup_free_ char *p;
+                        _cleanup_free_ char *p = NULL;
 
                         p = path_join(u->manager->prefix[dt], *dp);
                         if (!p)
@@ -1449,6 +1463,9 @@ static int log_unit_internal(void *userdata, int level, int error, const char *f
         va_list ap;
         int r;
 
+        if (u && !unit_log_level_test(u, level))
+                return -ERRNO_VALUE(error);
+
         va_start(ap, format);
         if (u)
                 r = log_object_internalv(level, error, file, line, func,
@@ -2152,6 +2169,13 @@ static int unit_log_resources(Unit *u) {
                                                 value > NOTICEWORTHY_IP_BYTES);
         }
 
+        /* This check is here because it is the earliest point following all possible log_level assignments. If
+         * log_level is assigned anywhere after this point, move this check. */
+        if (!unit_log_level_test(u, log_level)) {
+                r = 0;
+                goto finish;
+        }
+
         if (have_ip_accounting) {
                 if (any_traffic) {
                         if (igress)
@@ -2181,7 +2205,7 @@ static int unit_log_resources(Unit *u) {
         if (n_message_parts == 0)
                 t = strjoina("MESSAGE=", u->id, ": Completed.");
         else {
-                _cleanup_free_ char *joined;
+                _cleanup_free_ char *joined = NULL;
 
                 message_parts[n_message_parts] = NULL;
 
@@ -2206,7 +2230,7 @@ static int unit_log_resources(Unit *u) {
         t = strjoina(u->manager->invocation_log_field, u->invocation_id_string);
         iovec[n_iovec + 3] = IOVEC_MAKE_STRING(t);
 
-        log_struct_iovec(log_level, iovec, n_iovec + 4);
+        log_unit_struct_iovec(u, log_level, iovec, n_iovec + 4);
         r = 0;
 
 finish:
@@ -3866,7 +3890,7 @@ int unit_patch_contexts(Unit *u) {
         return 0;
 }
 
-ExecContext *unit_get_exec_context(Unit *u) {
+ExecContext *unit_get_exec_context(const Unit *u) {
         size_t offset;
         assert(u);
 
@@ -4478,6 +4502,9 @@ void unit_warn_if_dir_nonempty(Unit *u, const char* where) {
         assert(u);
         assert(where);
 
+        if (!unit_log_level_test(u, LOG_NOTICE))
+                return;
+
         r = dir_is_empty(where);
         if (r > 0 || r == -ENOTDIR)
                 return;
@@ -4486,12 +4513,11 @@ void unit_warn_if_dir_nonempty(Unit *u, const char* where) {
                 return;
         }
 
-        log_struct(LOG_NOTICE,
-                   "MESSAGE_ID=" SD_MESSAGE_OVERMOUNTING_STR,
-                   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);
+        log_unit_struct(u, LOG_NOTICE,
+                        "MESSAGE_ID=" SD_MESSAGE_OVERMOUNTING_STR,
+                        LOG_UNIT_INVOCATION_ID(u),
+                        LOG_UNIT_MESSAGE(u, "Directory %s to mount over is not empty, mounting anyway.", where),
+                        "WHERE=%s", where);
 }
 
 int unit_fail_if_noncanonical(Unit *u, const char* where) {
@@ -4512,12 +4538,11 @@ int unit_fail_if_noncanonical(Unit *u, const char* where) {
                 return 0;
 
         /* No need to mention "." or "..", they would already have been rejected by unit_name_from_path() */
-        log_struct(LOG_ERR,
-                   "MESSAGE_ID=" SD_MESSAGE_OVERMOUNTING_STR,
-                   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);
+        log_unit_struct(u, LOG_ERR,
+                        "MESSAGE_ID=" SD_MESSAGE_OVERMOUNTING_STR,
+                        LOG_UNIT_INVOCATION_ID(u),
+                        LOG_UNIT_MESSAGE(u, "Mount path %s is not canonical (contains a symlink).", where),
+                        "WHERE=%s", where);
 
         return -ELOOP;
 }
@@ -5296,35 +5321,32 @@ int unit_pid_attachable(Unit *u, pid_t pid, sd_bus_error *error) {
 void unit_log_success(Unit *u) {
         assert(u);
 
-        log_struct(LOG_INFO,
-                   "MESSAGE_ID=" SD_MESSAGE_UNIT_SUCCESS_STR,
-                   LOG_UNIT_ID(u),
-                   LOG_UNIT_INVOCATION_ID(u),
-                   LOG_UNIT_MESSAGE(u, "Deactivated successfully."));
+        log_unit_struct(u, LOG_INFO,
+                        "MESSAGE_ID=" SD_MESSAGE_UNIT_SUCCESS_STR,
+                        LOG_UNIT_INVOCATION_ID(u),
+                        LOG_UNIT_MESSAGE(u, "Deactivated successfully."));
 }
 
 void unit_log_failure(Unit *u, const char *result) {
         assert(u);
         assert(result);
 
-        log_struct(LOG_WARNING,
-                   "MESSAGE_ID=" SD_MESSAGE_UNIT_FAILURE_RESULT_STR,
-                   LOG_UNIT_ID(u),
-                   LOG_UNIT_INVOCATION_ID(u),
-                   LOG_UNIT_MESSAGE(u, "Failed with result '%s'.", result),
-                   "UNIT_RESULT=%s", result);
+        log_unit_struct(u, LOG_WARNING,
+                        "MESSAGE_ID=" SD_MESSAGE_UNIT_FAILURE_RESULT_STR,
+                        LOG_UNIT_INVOCATION_ID(u),
+                        LOG_UNIT_MESSAGE(u, "Failed with result '%s'.", result),
+                        "UNIT_RESULT=%s", result);
 }
 
 void unit_log_skip(Unit *u, const char *result) {
         assert(u);
         assert(result);
 
-        log_struct(LOG_INFO,
-                   "MESSAGE_ID=" SD_MESSAGE_UNIT_SKIPPED_STR,
-                   LOG_UNIT_ID(u),
-                   LOG_UNIT_INVOCATION_ID(u),
-                   LOG_UNIT_MESSAGE(u, "Skipped due to '%s'.", result),
-                   "UNIT_RESULT=%s", result);
+        log_unit_struct(u, LOG_INFO,
+                        "MESSAGE_ID=" SD_MESSAGE_UNIT_SKIPPED_STR,
+                        LOG_UNIT_INVOCATION_ID(u),
+                        LOG_UNIT_MESSAGE(u, "Skipped due to '%s'.", result),
+                        "UNIT_RESULT=%s", result);
 }
 
 void unit_log_process_exit(
@@ -5351,19 +5373,18 @@ void unit_log_process_exit(
         else
                 level = LOG_WARNING;
 
-        log_struct(level,
-                   "MESSAGE_ID=" SD_MESSAGE_UNIT_PROCESS_EXIT_STR,
-                   LOG_UNIT_MESSAGE(u, "%s exited, code=%s, status=%i/%s",
-                                    kind,
-                                    sigchld_code_to_string(code), status,
-                                    strna(code == CLD_EXITED
-                                          ? exit_status_to_string(status, EXIT_STATUS_FULL)
-                                          : signal_to_string(status))),
-                   "EXIT_CODE=%s", sigchld_code_to_string(code),
-                   "EXIT_STATUS=%i", status,
-                   "COMMAND=%s", strna(command),
-                   LOG_UNIT_ID(u),
-                   LOG_UNIT_INVOCATION_ID(u));
+        log_unit_struct(u, level,
+                        "MESSAGE_ID=" SD_MESSAGE_UNIT_PROCESS_EXIT_STR,
+                        LOG_UNIT_MESSAGE(u, "%s exited, code=%s, status=%i/%s",
+                                         kind,
+                                         sigchld_code_to_string(code), status,
+                                         strna(code == CLD_EXITED
+                                               ? exit_status_to_string(status, EXIT_STATUS_FULL)
+                                               : signal_to_string(status))),
+                        "EXIT_CODE=%s", sigchld_code_to_string(code),
+                        "EXIT_STATUS=%i", status,
+                        "COMMAND=%s", strna(command),
+                        LOG_UNIT_INVOCATION_ID(u));
 }
 
 int unit_exit_status(Unit *u) {
index 6d38e6668031112855e81e66f88d18549f982758..abd8aecc1a05a6d4469684d8bdd25cb0d088559a 100644 (file)
@@ -305,6 +305,19 @@ typedef struct Unit {
         Set *ip_bpf_custom_egress;
         Set *ip_bpf_custom_egress_installed;
 
+        /* BPF programs managed (e.g. loaded to kernel) by an entity external to systemd,
+         * attached to unit cgroup by provided program fd and attach type. */
+        Hashmap *bpf_foreign_by_key;
+
+        FDSet *initial_socket_bind_link_fds;
+#if BPF_FRAMEWORK
+        /* BPF links to BPF programs attached to cgroup/bind{4|6} hooks and
+         * responsible for allowing or denying a unit to bind(2) to a socket
+         * address. */
+        struct bpf_link *ipv4_socket_bind_link;
+        struct bpf_link *ipv6_socket_bind_link;
+#endif
+
         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
@@ -645,7 +658,7 @@ typedef struct UnitVTable {
 
 extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX];
 
-static inline const UnitVTable* UNIT_VTABLE(Unit *u) {
+static inline const UnitVTable* UNIT_VTABLE(const Unit *u) {
         return unit_vtable[u->type];
 }
 
@@ -808,7 +821,7 @@ void unit_ref_unset(UnitRef *ref);
 
 int unit_patch_contexts(Unit *u);
 
-ExecContext *unit_get_exec_context(Unit *u) _pure_;
+ExecContext *unit_get_exec_context(const Unit *u) _pure_;
 KillContext *unit_get_kill_context(Unit *u) _pure_;
 CGroupContext *unit_get_cgroup_context(Unit *u) _pure_;
 
@@ -879,6 +892,11 @@ static inline bool unit_has_job_type(Unit *u, JobType type) {
         return u && u->job && u->job->type == type;
 }
 
+static inline bool unit_log_level_test(const Unit *u, int level) {
+        ExecContext *ec = unit_get_exec_context(u);
+        return !ec || ec->log_level_max < 0 || ec->log_level_max >= LOG_PRI(level);
+}
+
 /* unit_log_skip is for cases like ExecCondition= where a unit is considered "done"
  * after some execution, rather than succeeded or failed. */
 void unit_log_skip(Unit *u, const char *result);
@@ -915,17 +933,25 @@ int unit_thaw_vtable_common(Unit *u);
 
 /* Macros which append UNIT= or USER_UNIT= to the message */
 
-#define log_unit_full_errno(unit, level, error, ...)                    \
+#define log_unit_full_errno_zerook(unit, level, error, ...)             \
         ({                                                              \
                 const Unit *_u = (unit);                                \
-                (log_get_max_level() < LOG_PRI(level)) ? -ERRNO_VALUE(error) : \
-                        _u ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, _u->manager->unit_log_field, _u->id, _u->manager->invocation_log_field, _u->invocation_id_string, ##__VA_ARGS__) : \
-                                log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
+                const int _l = (level);                                 \
+                (log_get_max_level() < LOG_PRI(_l) || (_u && !unit_log_level_test(_u, _l))) ? -ERRNO_VALUE(error) : \
+                        _u ? log_object_internal(_l, error, PROJECT_FILE, __LINE__, __func__, _u->manager->unit_log_field, _u->id, _u->manager->invocation_log_field, _u->invocation_id_string, ##__VA_ARGS__) : \
+                                log_internal(_l, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
+        })
+
+#define log_unit_full_errno(unit, level, error, ...) \
+        ({                                                              \
+                int _error = (error);                                   \
+                ASSERT_NON_ZERO(_error);                                \
+                log_unit_full_errno_zerook(unit, level, _error, ##__VA_ARGS__); \
         })
 
-#define log_unit_full(unit, level, ...) (void) log_unit_full_errno(unit, level, 0, __VA_ARGS__)
+#define log_unit_full(unit, level, ...) (void) log_unit_full_errno_zerook(unit, level, 0, __VA_ARGS__)
 
-#define log_unit_debug(unit, ...)   log_unit_full_errno(unit, LOG_DEBUG, 0, __VA_ARGS__)
+#define log_unit_debug(unit, ...)   log_unit_full(unit, LOG_DEBUG, __VA_ARGS__)
 #define log_unit_info(unit, ...)    log_unit_full(unit, LOG_INFO, __VA_ARGS__)
 #define log_unit_notice(unit, ...)  log_unit_full(unit, LOG_NOTICE, __VA_ARGS__)
 #define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, __VA_ARGS__)
@@ -937,6 +963,27 @@ int unit_thaw_vtable_common(Unit *u);
 #define log_unit_warning_errno(unit, error, ...) log_unit_full_errno(unit, LOG_WARNING, error, __VA_ARGS__)
 #define log_unit_error_errno(unit, error, ...)   log_unit_full_errno(unit, LOG_ERR, error, __VA_ARGS__)
 
+#define log_unit_struct_errno(unit, level, error, ...)                  \
+        ({                                                              \
+                const Unit *_u = (unit);                                \
+                const int _l = (level);                                 \
+                unit_log_level_test(_u, _l) ?                           \
+                        log_struct_errno(_l, error, __VA_ARGS__, LOG_UNIT_ID(_u)) : \
+                        -ERRNO_VALUE(error);                            \
+        })
+
+#define log_unit_struct(unit, level, ...) log_unit_struct_errno(unit, level, 0, __VA_ARGS__)
+
+#define log_unit_struct_iovec_errno(unit, level, error, iovec, n_iovec) \
+        ({                                                              \
+                const int _l = (level);                                 \
+                unit_log_level_test(unit, _l) ?                         \
+                        log_struct_iovec_errno(_l, error, iovec, n_iovec) : \
+                        -ERRNO_VALUE(error);                            \
+        })
+
+#define log_unit_struct_iovec(unit, level, iovec, n_iovec) log_unit_struct_iovec_errno(unit, level, 0, iovec, n_iovec)
+
 #define LOG_UNIT_MESSAGE(unit, fmt, ...) "MESSAGE=%s: " fmt, (unit)->id, ##__VA_ARGS__
 #define LOG_UNIT_ID(unit) (unit)->manager->unit_log_format_string, (unit)->id
 #define LOG_UNIT_INVOCATION_ID(unit) (unit)->manager->invocation_log_format_string, (unit)->invocation_id_string
index d3887e1c876be4ff0b1f886a8a9fd2b7849f1fb6..5f0ca4cb0256fd6684aa621388b821701c066078 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Entries in this file show the compile time defaults. Local configuration
 # should be created by either modifying this file, or by creating "drop-ins" in
-# the system.conf.d/ subdirectory. The latter is generally recommended.
+# the user.conf.d/ subdirectory. The latter is generally recommended.
 # Defaults can be restored by simply deleting this file and all drop-ins.
 #
 # See systemd-user.conf(5) for details.
index a16be3c44832cf14f3995e634e26914995bddc2c..b75a7c39ce684ec085e540c854d59b44156debe3 100644 (file)
@@ -588,7 +588,7 @@ static int compose_open_fds(pid_t pid, char **open_fds) {
 static int get_process_ns(pid_t pid, const char *namespace, ino_t *ns) {
         const char *p;
         struct stat stbuf;
-        _cleanup_close_ int proc_ns_dir_fd;
+        _cleanup_close_ int proc_ns_dir_fd = -1;
 
         p = procfs_file_alloca(pid, "ns");
 
@@ -703,14 +703,16 @@ static int submit_coredump(
                 struct iovec_wrapper *iovw,
                 int input_fd) {
 
+        _cleanup_(json_variant_unrefp) JsonVariant *json_metadata = NULL;
         _cleanup_close_ int coredump_fd = -1, coredump_node_fd = -1;
         _cleanup_free_ char *filename = NULL, *coredump_data = NULL;
         _cleanup_free_ char *stacktrace = NULL;
         char *core_message;
+        const char *module_name;
         uint64_t coredump_size = UINT64_MAX;
         bool truncated = false;
+        JsonVariant *module_json;
         int r;
-
         assert(context);
         assert(iovw);
         assert(input_fd >= 0);
@@ -757,7 +759,7 @@ static int submit_coredump(
                           "than %"PRIu64" (the configured maximum)",
                           coredump_size, arg_process_size_max);
         } else
-                coredump_make_stack_trace(coredump_fd, context->meta[META_EXE], &stacktrace);
+                coredump_parse_core(coredump_fd, context->meta[META_EXE], &stacktrace, &json_metadata);
 #endif
 
 log:
@@ -781,6 +783,34 @@ log:
         if (truncated)
                 (void) iovw_put_string_field(iovw, "COREDUMP_TRUNCATED=", "1");
 
+        /* If we managed to parse any ELF metadata (build-id, ELF package meta),
+         * attach it as journal metadata. */
+        if (json_metadata) {
+                _cleanup_free_ char *formatted_json = NULL;
+
+                r = json_variant_format(json_metadata, 0, &formatted_json);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to format JSON package metadata: %m");
+
+                (void) iovw_put_string_field(iovw, "COREDUMP_PACKAGE_JSON=", formatted_json);
+        }
+
+        JSON_VARIANT_OBJECT_FOREACH(module_name, module_json, json_metadata) {
+                JsonVariant *package_name, *package_version;
+
+                /* We only add structured fields for the 'main' ELF module */
+                if (!path_equal_filename(module_name, context->meta[META_EXE]))
+                        continue;
+
+                package_name = json_variant_by_key(module_json, "name");
+                if (package_name)
+                        (void) iovw_put_string_field(iovw, "COREDUMP_PACKAGE_NAME=", json_variant_string(package_name));
+
+                package_version = json_variant_by_key(module_json, "version");
+                if (package_version)
+                        (void) iovw_put_string_field(iovw, "COREDUMP_PACKAGE_VERSION=", json_variant_string(package_version));
+        }
+
         /* Optionally store the entire coredump in the journal */
         if (arg_storage == COREDUMP_STORAGE_JOURNAL) {
                 if (coredump_size <= arg_journal_size_max) {
index 56c100824524185386bc7c40de63286e06e309d8..1f75d48d336f9084e053ce95f1d3e6b28df1cf60 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Entries in this file show the compile time defaults. Local configuration
 # should be created by either modifying this file, or by creating "drop-ins" in
-# the system.conf.d/ subdirectory. The latter is generally recommended.
+# the coredump.conf.d/ subdirectory. The latter is generally recommended.
 # Defaults can be restored by simply deleting this file and all drop-ins.
 #
 # Use 'systemd-analyze cat-config systemd/coredump.conf' to display the full config.
index 0c4ef2e123486216213435956539b90482b4454c..9a577d47c8b7227120fea466b50bab436385ad78 100644 (file)
@@ -139,7 +139,7 @@ static int acquire_journal(sd_journal **ret, char **matches) {
                 return r;
 
         if (DEBUG_LOGGING) {
-                _cleanup_free_ char *filter;
+                _cleanup_free_ char *filter = NULL;
 
                 filter = journal_make_match_string(j);
                 log_debug("Journal filter: %s", filter);
@@ -545,7 +545,8 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) {
                 *boot_id = NULL, *machine_id = NULL, *hostname = NULL,
                 *slice = NULL, *cgroup = NULL, *owner_uid = NULL,
                 *message = NULL, *timestamp = NULL, *filename = NULL,
-                *truncated = NULL, *coredump = NULL;
+                *truncated = NULL, *coredump = NULL,
+                *pkgmeta_name = NULL, *pkgmeta_version = NULL, *pkgmeta_json = NULL;
         const void *d;
         size_t l;
         bool normal_coredump;
@@ -574,6 +575,9 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) {
                 RETRIEVE(d, l, "COREDUMP_FILENAME", filename);
                 RETRIEVE(d, l, "COREDUMP_TRUNCATED", truncated);
                 RETRIEVE(d, l, "COREDUMP", coredump);
+                RETRIEVE(d, l, "COREDUMP_PACKAGE_NAME", pkgmeta_name);
+                RETRIEVE(d, l, "COREDUMP_PACKAGE_VERSION", pkgmeta_version);
+                RETRIEVE(d, l, "COREDUMP_PACKAGE_JSON", pkgmeta_json);
                 RETRIEVE(d, l, "_BOOT_ID", boot_id);
                 RETRIEVE(d, l, "_MACHINE_ID", machine_id);
                 RETRIEVE(d, l, "MESSAGE", message);
@@ -716,6 +720,37 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) {
         else
                 fprintf(file, "       Storage: none\n");
 
+        if (pkgmeta_name && pkgmeta_version)
+                fprintf(file, "       Package: %s/%s\n", pkgmeta_name, pkgmeta_version);
+
+        /* Print out the build-id of the 'main' ELF module, by matching the JSON key
+         * with the 'exe' field. */
+        if (exe && pkgmeta_json) {
+                _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+
+                r = json_parse(pkgmeta_json, 0, &v, NULL, NULL);
+                if (r < 0)
+                        log_warning_errno(r, "json_parse on %s failed, ignoring: %m", pkgmeta_json);
+                else {
+                        const char *module_name;
+                        JsonVariant *module_json;
+
+                        JSON_VARIANT_OBJECT_FOREACH(module_name, module_json, v) {
+                                JsonVariant *build_id;
+
+                                /* We only print the build-id for the 'main' ELF module */
+                                if (!path_equal_filename(module_name, exe))
+                                        continue;
+
+                                build_id = json_variant_by_key(module_json, "buildId");
+                                if (build_id)
+                                        fprintf(file, "      build-id: %s\n", json_variant_string(build_id));
+
+                                break;
+                        }
+                }
+        }
+
         if (message) {
                 _cleanup_free_ char *m = NULL;
 
@@ -944,7 +979,7 @@ static int save_core(sd_journal *j, FILE *file, char **path, bool *unlink_temp)
 
         if (filename) {
 #if HAVE_COMPRESSION
-                _cleanup_close_ int fdf;
+                _cleanup_close_ int fdf = -1;
 
                 fdf = open(filename, O_RDONLY | O_CLOEXEC);
                 if (fdf < 0) {
index a29ab1211c2feae5a5f4e6f59301639a0abf8df6..102ad2e65beb51ec0f8ff402b49ecc1590fa4621 100644 (file)
@@ -1,7 +1,9 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <dwarf.h>
+#include <elfutils/libdwelf.h>
 #include <elfutils/libdwfl.h>
+#include <libelf.h>
 #include <sys/types.h>
 #include <unistd.h>
 
@@ -9,6 +11,7 @@
 #include "fileio.h"
 #include "fd-util.h"
 #include "format-util.h"
+#include "hexdecoct.h"
 #include "macro.h"
 #include "stacktrace.h"
 #include "string-util.h"
@@ -16,6 +19,7 @@
 
 #define FRAMES_MAX 64
 #define THREADS_MAX 64
+#define ELF_PACKAGE_METADATA_ID 0xcafe1a7e
 
 struct stack_context {
         FILE *f;
@@ -23,6 +27,8 @@ struct stack_context {
         Elf *elf;
         unsigned n_thread;
         unsigned n_frame;
+        JsonVariant **package_metadata;
+        Set **modules;
 };
 
 static int frame_callback(Dwfl_Frame *frame, void *userdata) {
@@ -111,14 +117,212 @@ static int thread_callback(Dwfl_Thread *thread, void *userdata) {
         return DWARF_CB_OK;
 }
 
-static int make_stack_trace(int fd, const char *executable, char **ret) {
+static int parse_package_metadata(const char *name, JsonVariant *id_json, Elf *elf, struct stack_context *c) {
+        size_t n_program_headers;
+        int r;
+
+        assert(name);
+        assert(elf);
+        assert(c);
+
+        /* When iterating over PT_LOAD we will visit modules more than once */
+        if (set_contains(*c->modules, name))
+                return DWARF_CB_OK;
+
+        r = elf_getphdrnum(elf, &n_program_headers);
+        if (r < 0) /* Not the handle we are looking for - that's ok, skip it */
+                return DWARF_CB_OK;
+
+        /* Iterate over all program headers in that ELF object. These will have been copied by
+         * the kernel verbatim when the core file is generated. */
+        for (size_t i = 0; i < n_program_headers; ++i) {
+                size_t note_offset = 0, name_offset, desc_offset;
+                GElf_Phdr mem, *program_header;
+                GElf_Nhdr note_header;
+                Elf_Data *data;
+
+                /* Package metadata is in PT_NOTE headers. */
+                program_header = gelf_getphdr(elf, i, &mem);
+                if (!program_header || program_header->p_type != PT_NOTE)
+                        continue;
+
+                /* Fortunately there is an iterator we can use to walk over the
+                 * elements of a PT_NOTE program header. We are interested in the
+                 * note with type. */
+                data = elf_getdata_rawchunk(elf,
+                                            program_header->p_offset,
+                                            program_header->p_filesz,
+                                            ELF_T_NHDR);
+
+                while (note_offset < data->d_size &&
+                       (note_offset = gelf_getnote(data, note_offset, &note_header, &name_offset, &desc_offset)) > 0) {
+                        const char *note_name = (const char *)data->d_buf + name_offset;
+                        const char *payload = (const char *)data->d_buf + desc_offset;
+
+                        if (note_header.n_namesz == 0 || note_header.n_descsz == 0)
+                                continue;
+
+                        /* Package metadata might have different owners, but the
+                         * magic ID is always the same. */
+                        if (note_header.n_type == ELF_PACKAGE_METADATA_ID) {
+                                _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *w = NULL;
+
+                                r = json_parse(payload, 0, &v, NULL, NULL);
+                                if (r < 0) {
+                                        log_error_errno(r, "json_parse on %s failed: %m", payload);
+                                        return DWARF_CB_ABORT;
+                                }
+
+                                /* First pretty-print to the buffer, so that the metadata goes as
+                                 * plaintext in the journal. */
+                                fprintf(c->f, "Metadata for module %s owned by %s found: ",
+                                        name, note_name);
+                                json_variant_dump(v, JSON_FORMAT_NEWLINE|JSON_FORMAT_PRETTY, c->f, NULL);
+                                fputc('\n', c->f);
+
+                                /* Secondly, if we have a build-id, merge it in the same JSON object
+                                 * so that it appears all nicely together in the logs/metadata. */
+                                if (id_json) {
+                                        r = json_variant_merge(&v, id_json);
+                                        if (r < 0) {
+                                                log_error_errno(r, "json_variant_merge of package meta with buildid failed: %m");
+                                                return DWARF_CB_ABORT;
+                                        }
+                                }
+
+                                /* Then we build a new object using the module name as the key, and merge it
+                                 * with the previous parses, so that in the end it all fits together in a single
+                                 * JSON blob. */
+                                r = json_build(&w, JSON_BUILD_OBJECT(JSON_BUILD_PAIR(name, JSON_BUILD_VARIANT(v))));
+                                if (r < 0) {
+                                        log_error_errno(r, "Failed to build JSON object: %m");
+                                        return DWARF_CB_ABORT;
+                                }
+                                r = json_variant_merge(c->package_metadata, w);
+                                if (r < 0) {
+                                        log_error_errno(r, "json_variant_merge of package meta with buildid failed: %m");
+                                        return DWARF_CB_ABORT;
+                                }
+
+                                /* Finally stash the name, so we avoid double visits. */
+                                r = set_put_strdup(c->modules, name);
+                                if (r < 0) {
+                                        log_error_errno(r, "set_put_strdup failed: %m");
+                                        return DWARF_CB_ABORT;
+                                }
+
+                                return DWARF_CB_OK;
+                        }
+                }
+        }
+
+        /* Didn't find package metadata for this module - that's ok, just go to the next. */
+        return DWARF_CB_OK;
+}
+
+static int module_callback(Dwfl_Module *mod, void **userdata, const char *name, Dwarf_Addr start, void *arg) {
+        _cleanup_(json_variant_unrefp) JsonVariant *id_json = NULL;
+        struct stack_context *c = arg;
+        size_t n_program_headers;
+        GElf_Addr id_vaddr, bias;
+        const unsigned char *id;
+        int id_len, r;
+        Elf *elf;
+
+        assert(mod);
+        assert(c);
+
+        if (!name)
+                name = "(unnamed)"; /* For logging purposes */
+
+        /* We are iterating on each "module", which is what dwfl calls ELF objects contained in the
+         * core file, and extracting the build-id first and then the package metadata.
+         * We proceed in a best-effort fashion - not all ELF objects might contain both or either.
+         * The build-id is easy, as libdwfl parses it during the dwfl_core_file_report() call and
+         * stores it separately in an internal library struct. */
+        id_len = dwfl_module_build_id(mod, &id, &id_vaddr);
+        if (id_len <= 0)
+                /* If we don't find a build-id, note it in the journal message, and try
+                 * anyway to find the package metadata. It's unlikely to have the latter
+                 * without the former, but there's no hard rule. */
+                fprintf(c->f, "Found module %s without build-id.\n", name);
+        else {
+                JsonVariant *build_id;
+
+                /* We will later parse package metadata json and pass it to our caller. Prepare the
+                * build-id in json format too, so that it can be appended and parsed cleanly. It
+                * will then be added as metadata to the journal message with the stack trace. */
+                r = json_build(&id_json, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("buildId", JSON_BUILD_HEX(id, id_len))));
+                if (r < 0) {
+                        log_error_errno(r, "json_build on build-id failed: %m");
+                        return DWARF_CB_ABORT;
+                }
+
+                build_id = json_variant_by_key(id_json, "buildId");
+                assert_se(build_id);
+                fprintf(c->f, "Found module %s with build-id: %s\n", name, json_variant_string(build_id));
+        }
+
+        /* The .note.package metadata is more difficult. From the module, we need to get a reference
+         * to the ELF object first. We might be lucky and just get it from elfutils. */
+        elf = dwfl_module_getelf(mod, &bias);
+        if (elf)
+                return parse_package_metadata(name, id_json, elf, c);
+
+        /* We did not get the ELF object. That is likely because we didn't get direct
+         * access to the executable, and the version of elfutils does not yet support
+         * parsing it out of the core file directly.
+         * So fallback to manual extraction - get the PT_LOAD section from the core,
+         * and if it's the right one we can interpret it as an Elf object, and parse
+         * its notes manually. */
+
+        r = elf_getphdrnum(c->elf, &n_program_headers);
+        if (r < 0) {
+                log_warning("Could not parse number of program headers from core file: %s",
+                            elf_errmsg(-1)); /* -1 retrieves the most recent error */
+                return DWARF_CB_OK;
+        }
+
+        for (size_t i = 0; i < n_program_headers; ++i) {
+                GElf_Phdr mem, *program_header;
+                Elf_Data *data;
+
+                /* The core file stores the ELF files in the PT_LOAD segment .*/
+                program_header = gelf_getphdr(c->elf, i, &mem);
+                if (!program_header || program_header->p_type != PT_LOAD)
+                        continue;
+
+                /* Now get a usable Elf reference, and parse the notes from it. */
+                data = elf_getdata_rawchunk(c->elf,
+                                            program_header->p_offset,
+                                            program_header->p_filesz,
+                                            ELF_T_NHDR);
+
+                Elf *memelf = elf_memory(data->d_buf, data->d_size);
+                if (!memelf)
+                        continue;
+                r = parse_package_metadata(name, id_json, memelf, c);
+                if (r != DWARF_CB_OK)
+                        return r;
+        }
+
+        return DWARF_CB_OK;
+}
+
+static int parse_core(int fd, const char *executable, char **ret, JsonVariant **ret_package_metadata) {
 
         static const Dwfl_Callbacks callbacks = {
                 .find_elf = dwfl_build_id_find_elf,
+                .section_address = dwfl_offline_section_address,
                 .find_debuginfo = dwfl_standard_find_debuginfo,
         };
 
-        struct stack_context c = {};
+        _cleanup_(json_variant_unrefp) JsonVariant *package_metadata = NULL;
+        _cleanup_(set_freep) Set *modules = NULL;
+        struct stack_context c = {
+                .package_metadata = &package_metadata,
+                .modules = &modules,
+        };
         char *buf = NULL;
         size_t sz = 0;
         int r;
@@ -157,6 +361,11 @@ static int make_stack_trace(int fd, const char *executable, char **ret) {
                 goto finish;
         }
 
+        if (dwfl_getmodules(c.dwfl, &module_callback, &c, 0) < 0) {
+                r = -EINVAL;
+                goto finish;
+        }
+
         if (dwfl_core_file_attach(c.dwfl, c.elf) < 0) {
                 r = -EINVAL;
                 goto finish;
@@ -170,6 +379,8 @@ static int make_stack_trace(int fd, const char *executable, char **ret) {
         c.f = safe_fclose(c.f);
 
         *ret = TAKE_PTR(buf);
+        if (ret_package_metadata)
+                *ret_package_metadata = TAKE_PTR(package_metadata);
 
         r = 0;
 
@@ -187,10 +398,10 @@ finish:
         return r;
 }
 
-void coredump_make_stack_trace(int fd, const char *executable, char **ret) {
+void coredump_parse_core(int fd, const char *executable, char **ret, JsonVariant **ret_package_metadata) {
         int r;
 
-        r = make_stack_trace(fd, executable, ret);
+        r = parse_core(fd, executable, ret, ret_package_metadata);
         if (r == -EINVAL)
                 log_warning("Failed to generate stack trace: %s", dwfl_errmsg(dwfl_errno()));
         else if (r < 0)
index b93574840424e5161366382d4da2a6a90c6f64ad..5039b934dda4ca30a51515f8bcb067b1b4f503fe 100644 (file)
@@ -1,4 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
-void coredump_make_stack_trace(int fd, const char *executable, char **ret);
+#include "json.h"
+
+void coredump_parse_core(int fd, const char *executable, char **ret, JsonVariant **ret_package_metadata);
index e08f564d3faff5c1abb774c17fde40438c1c5c9d..0314831174be1ea6cb996b99d9ef7260f52cc78f 100644 (file)
@@ -57,7 +57,7 @@ int enroll_password(
                         if (!question)
                                 return log_oom();
 
-                        r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", USEC_INFINITY, 0, &passwords);
+                        r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", "cryptenroll.new-passphrase", USEC_INFINITY, 0, &passwords);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to query password: %m");
 
@@ -68,7 +68,7 @@ int enroll_password(
                         if (!question)
                                 return log_oom();
 
-                        r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", USEC_INFINITY, 0, &passwords2);
+                        r = ask_password_auto(question, "drive-harddisk", id, "cryptenroll", "cryptenroll.new-passphrase", USEC_INFINITY, 0, &passwords2);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to query password: %m");
 
index a137a41c9d7cfda6d75696671b48008c886e0b3c..7d12c427b3099f6feaf2e9f2e471b2a7767e627a 100644 (file)
@@ -417,7 +417,7 @@ static int prepare_luks(
                                                        "Too many attempts, giving up:");
 
                         r = ask_password_auto(
-                                        question, "drive-harddisk", id, "cryptenroll", USEC_INFINITY,
+                                        question, "drive-harddisk", id, "cryptenroll", "cryptenroll.passphrase", USEC_INFINITY,
                                         ask_password_flags,
                                         &passwords);
                         if (r < 0)
index dfdb964360a7998e9cecfc527726641dc3c35b6e..82b83ee47705ecbce7f0b7d89c9b1e2999a23817 100644 (file)
@@ -88,7 +88,7 @@ int acquire_fido2_key(
 
                 pins = strv_free_erase(pins);
 
-                r = ask_password_auto("Please enter security token PIN:", "drive-harddisk", NULL, "fido2-pin", until, flags, &pins);
+                r = ask_password_auto("Please enter security token PIN:", "drive-harddisk", NULL, "fido2-pin", "cryptsetup.fido2-pin", until, flags, &pins);
                 if (r < 0)
                         return log_error_errno(r, "Failed to ask for user password: %m");
 
index a6281fbdeeeafb616c4c75af4f8b0f39fce26ed3..55c1442ed6e7fb1d54b9ccd31f1cc3dd40507418 100644 (file)
@@ -33,7 +33,7 @@ int find_key_file(
         }
 
         STRV_FOREACH(i, search_path) {
-                _cleanup_free_ char *joined;
+                _cleanup_free_ char *joined = NULL;
 
                 joined = path_join(*i, key_file);
                 if (!joined)
index 8d7d74fb75b1294725db55248dfaa8be9d88bc57..6d7b01176cbe0960706efee68997b16903ed1525 100644 (file)
@@ -70,6 +70,7 @@ static int pkcs11_callback(
                         data->friendly_name,
                         "drive-harddisk",
                         "pkcs11-pin",
+                        "cryptsetup.pkcs11-pin",
                         data->until,
                         NULL);
         if (r < 0)
index dba26a54a3f15faa45c1d82e557bb31f5e52088b..c9cebb46378e9d227ab4cffd38fea881e40c4bad 100644 (file)
@@ -545,7 +545,7 @@ static int get_password(
 
         id = strjoina("cryptsetup:", disk_path);
 
-        r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", until,
+        r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", "cryptsetup.passphrase", until,
                               ASK_PASSWORD_PUSH_CACHE | (accept_cached*ASK_PASSWORD_ACCEPT_CACHED),
                               &passwords);
         if (r < 0)
@@ -561,7 +561,7 @@ static int get_password(
 
                 id = strjoina("cryptsetup-verification:", disk_path);
 
-                r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", until, ASK_PASSWORD_PUSH_CACHE, &passwords2);
+                r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", "cryptsetup.passphrase", until, ASK_PASSWORD_PUSH_CACHE, &passwords2);
                 if (r < 0)
                         return log_error_errno(r, "Failed to query verification password: %m");
 
@@ -1008,7 +1008,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         _cleanup_free_ char *friendly = NULL;
         int keyslot = arg_key_slot, r;
-        size_t decrypted_key_size;
+        size_t decrypted_key_size = 0;  /* avoid false maybe-uninitialized warning */
 
         assert(cd);
         assert(name);
@@ -1058,15 +1058,12 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                                                 &policy_hash, &policy_hash_size,
                                                 &keyslot,
                                                 &token);
-                                if (r == -ENXIO) {
+                                if (r == -ENXIO)
                                         /* No further TPM2 tokens found in the LUKS2 header.*/
-                                        if (found_some)
-                                                return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
-                                                                       "No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking.");
-                                        else
-                                                return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
-                                                                       "No TPM2 metadata enrolled in LUKS2 header, falling back to traditional unlocking.");
-                                }
+                                        return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
+                                                               found_some
+                                                               ? "No TPM2 metadata matching the current system state found in LUKS2 header, falling back to traditional unlocking."
+                                                               : "No TPM2 metadata enrolled in LUKS2 header, falling back to traditional unlocking.");
                                 if (r < 0)
                                         return r;
 
@@ -1091,6 +1088,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                         if (r != -EAGAIN) /* EAGAIN means: no tpm2 chip found */
                                 return r;
                 }
+                assert(decrypted_key);
 
                 if (!monitor) {
                         /* We didn't find the TPM2 device. In this case, watch for it via udev. Let's create
index cb96a57abee41b6987c1f0c7ef0a022307bc2a05..ef11faaf425a9525a41cd31ae0a7135f1c8a1b93 100644 (file)
@@ -44,7 +44,13 @@ static const char *arg_image = NULL;
 static const char *arg_path = NULL;
 static const char *arg_source = NULL;
 static const char *arg_target = NULL;
-static DissectImageFlags arg_flags = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK;
+static DissectImageFlags arg_flags =
+        DISSECT_IMAGE_GENERIC_ROOT |
+        DISSECT_IMAGE_DISCARD_ON_LOOP |
+        DISSECT_IMAGE_RELAX_VAR_CHECK |
+        DISSECT_IMAGE_FSCK |
+        DISSECT_IMAGE_USR_NO_ROOT |
+        DISSECT_IMAGE_GROWFS;
 static VeritySettings arg_verity_settings = VERITY_SETTINGS_DEFAULT;
 static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
 static PagerFlags arg_pager_flags = 0;
@@ -70,6 +76,7 @@ static int help(void) {
                "     --no-legend          Do not show the headers and footers\n"
                "  -r --read-only          Mount read-only\n"
                "     --fsck=BOOL          Run fsck before mounting\n"
+               "     --growfs=BOOL        Grow file system to partition size, if marked\n"
                "     --mkdir              Make mount directory before mounting, if missing\n"
                "     --discard=MODE       Choose 'discard' mode (disabled, loop, all, crypto)\n"
                "     --root-hash=HASH     Specify root hash for verity\n"
@@ -107,6 +114,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_NO_LEGEND,
                 ARG_DISCARD,
                 ARG_FSCK,
+                ARG_GROWFS,
                 ARG_ROOT_HASH,
                 ARG_ROOT_HASH_SIG,
                 ARG_VERITY_DATA,
@@ -123,6 +131,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "read-only",     no_argument,       NULL, 'r'               },
                 { "discard",       required_argument, NULL, ARG_DISCARD       },
                 { "fsck",          required_argument, NULL, ARG_FSCK          },
+                { "growfs",        required_argument, NULL, ARG_GROWFS        },
                 { "root-hash",     required_argument, NULL, ARG_ROOT_HASH     },
                 { "root-hash-sig", required_argument, NULL, ARG_ROOT_HASH_SIG },
                 { "verity-data",   required_argument, NULL, ARG_VERITY_DATA   },
@@ -259,6 +268,14 @@ static int parse_argv(int argc, char *argv[]) {
                         SET_FLAG(arg_flags, DISSECT_IMAGE_FSCK, r);
                         break;
 
+                case ARG_GROWFS:
+                        r = parse_boolean(optarg);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse --growfs= parameter: %s", optarg);
+
+                        SET_FLAG(arg_flags, DISSECT_IMAGE_GROWFS, r);
+                        break;
+
                 case ARG_JSON:
                         r = parse_json_argument(optarg, &arg_json_format_flags);
                         if (r <= 0)
@@ -293,6 +310,7 @@ static int parse_argv(int argc, char *argv[]) {
 
                 arg_image = argv[optind];
                 arg_path = argv[optind + 1];
+                arg_flags |= DISSECT_IMAGE_REQUIRE_ROOT;
                 break;
 
         case ACTION_COPY_FROM:
@@ -304,7 +322,7 @@ static int parse_argv(int argc, char *argv[]) {
                 arg_source = argv[optind + 1];
                 arg_target = argc > optind + 2 ? argv[optind + 2] : "-" /* this means stdout */ ;
 
-                arg_flags |= DISSECT_IMAGE_READ_ONLY;
+                arg_flags |= DISSECT_IMAGE_READ_ONLY | DISSECT_IMAGE_REQUIRE_ROOT;
                 break;
 
         case ACTION_COPY_TO:
@@ -322,6 +340,7 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_target = argv[optind + 1];
                 }
 
+                arg_flags |= DISSECT_IMAGE_REQUIRE_ROOT;
                 break;
 
         default:
@@ -460,7 +479,7 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
                         return log_oom();
         }
 
-        t = table_new("rw", "designator", "partition uuid", "fstype", "architecture", "verity", "node", "partno");
+        t = table_new("rw", "designator", "partition uuid", "partition label", "fstype", "architecture", "verity", "growfs", "node", "partno");
         if (!t)
                 return log_oom();
 
@@ -489,6 +508,7 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
 
                 r = table_add_many(
                                 t,
+                                TABLE_STRING, p->label,
                                 TABLE_STRING, p->fstype,
                                 TABLE_STRING, architecture_to_string(p->architecture));
                 if (r < 0)
@@ -503,6 +523,10 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
                 if (r < 0)
                         return table_log_add_error(r);
 
+                r = table_add_many(t, TABLE_BOOLEAN, (int) p->growfs);
+                if (r < 0)
+                        return table_log_add_error(r);
+
                 if (p->partno < 0) /* no partition table, naked file system */ {
                         r = table_add_cell(t, NULL, TABLE_STRING, arg_image);
                         if (r < 0)
@@ -762,17 +786,19 @@ static int run(int argc, char *argv[]) {
 
         r = loop_device_make_by_path(
                         arg_image,
-                        FLAGS_SET(arg_flags, DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : O_RDWR,
+                        FLAGS_SET(arg_flags, DISSECT_IMAGE_DEVICE_READ_ONLY) ? O_RDONLY : O_RDWR,
                         FLAGS_SET(arg_flags, DISSECT_IMAGE_NO_PARTITION_TABLE) ? 0 : LO_FLAGS_PARTSCAN,
                         &d);
         if (r < 0)
-                return log_error_errno(r, "Failed to set up loopback device: %m");
+                return log_error_errno(r, "Failed to set up loopback device for %s: %m", arg_image);
 
         r = dissect_image_and_warn(
                         d->fd,
                         arg_image,
                         &arg_verity_settings,
                         NULL,
+                        d->uevent_seqnum_not_before,
+                        d->timestamp_not_before,
                         arg_flags,
                         &m);
         if (r < 0)
index 5372f6cec28bbd21c3ea522241a163b31e08e1a2..1171fdc29093515db75943ec6e80990c778c6b4a 100644 (file)
@@ -29,7 +29,7 @@ static int environment_dirs(char ***ret) {
                 return r;
 
         if (DEBUG_LOGGING) {
-                _cleanup_free_ char *t;
+                _cleanup_free_ char *t = NULL;
 
                 t = strv_join(dirs, "\n\t");
                 log_debug("Looking for environment.d files in (higher priority first):\n\t%s", strna(t));
index 8e3028717e79dbccc4d07acb3e93d9e331befabb..2cb4f80d5d5d9a00398a2f6a0023908811b3ebfb 100644 (file)
@@ -10,6 +10,7 @@
 #include "alloc-util.h"
 #include "ask-password-api.h"
 #include "copy.h"
+#include "creds-util.h"
 #include "dissect-image.h"
 #include "env-file.h"
 #include "fd-util.h"
@@ -43,8 +44,8 @@
 static char *arg_root = NULL;
 static char *arg_image = NULL;
 static char *arg_locale = NULL;  /* $LANG */
-static char *arg_keymap = NULL;
 static char *arg_locale_messages = NULL; /* $LC_MESSAGES */
+static char *arg_keymap = NULL;
 static char *arg_timezone = NULL;
 static char *arg_hostname = NULL;
 static sd_id128_t arg_machine_id = {};
@@ -232,11 +233,29 @@ static bool locale_is_ok(const char *name) {
 
 static int prompt_locale(void) {
         _cleanup_strv_free_ char **locales = NULL;
+        bool acquired_from_creds = false;
         int r;
 
         if (arg_locale || arg_locale_messages)
                 return 0;
 
+        r = read_credential("firstboot.locale", (void**) &arg_locale, NULL);
+        if (r < 0)
+                log_debug_errno(r, "Failed to read credential firstboot.locale, ignoring: %m");
+        else
+                acquired_from_creds = true;
+
+        r = read_credential("firstboot.locale-messages", (void**) &arg_locale_messages, NULL);
+        if (r < 0)
+                log_debug_errno(r, "Failed to read credential firstboot.locale-message, ignoring: %m");
+        else
+                acquired_from_creds = true;
+
+        if (acquired_from_creds) {
+                log_debug("Acquired locale from credentials.");
+                return 0;
+        }
+
         if (!arg_prompt_locale)
                 return 0;
 
@@ -336,6 +355,14 @@ static int prompt_keymap(void) {
         if (arg_keymap)
                 return 0;
 
+        r = read_credential("firstboot.keymap", (void**) &arg_keymap, NULL);
+        if (r < 0)
+                log_debug_errno(r, "Failed to read credential firstboot.keymap, ignoring: %m");
+        else {
+                log_debug("Acquired keymap from credential.");
+                return 0;
+        }
+
         if (!arg_prompt_keymap)
                 return 0;
 
@@ -407,6 +434,14 @@ static int prompt_timezone(void) {
         if (arg_timezone)
                 return 0;
 
+        r = read_credential("firstboot.timezone", (void**) &arg_timezone, NULL);
+        if (r < 0)
+                log_debug_errno(r, "Failed to read credential firstboot.timezone, ignoring: %m");
+        else {
+                log_debug("Acquired timezone from credential.");
+                return 0;
+        }
+
         if (!arg_prompt_timezone)
                 return 0;
 
@@ -558,6 +593,22 @@ static int prompt_root_password(void) {
         if (arg_root_password)
                 return 0;
 
+        r = read_credential("passwd.hashed-password.root", (void**) &arg_root_password, NULL);
+        if (r == -ENOENT) {
+                r = read_credential("passwd.plaintext-password.root", (void**) &arg_root_password, NULL);
+                if (r < 0)
+                        log_debug_errno(r, "Couldn't read credential 'passwd.{hashed|plaintext}-password.root', ignoring: %m");
+                else {
+                        arg_root_password_is_hashed = false;
+                        return 0;
+                }
+        } else if (r < 0)
+                log_debug_errno(r, "Couldn't read credential 'passwd.hashed-password.root', ignoring: %m");
+        else {
+                arg_root_password_is_hashed = true;
+                return 0;
+        }
+
         if (!arg_prompt_root_password)
                 return 0;
 
@@ -631,7 +682,18 @@ static int find_shell(const char *path, const char *root) {
 static int prompt_root_shell(void) {
         int r;
 
-        if (arg_root_shell || !arg_prompt_root_shell)
+        if (arg_root_shell)
+                return 0;
+
+        r = read_credential("passwd.shell.root", (void**) &arg_root_shell, NULL);
+        if (r < 0)
+                log_debug_errno(r, "Failed to read credential passwd.shell.root, ignoring: %m");
+        else {
+                log_debug("Acquired root shell from credential.");
+                return 0;
+        }
+
+        if (!arg_prompt_root_shell)
                 return 0;
 
         print_welcome();
@@ -860,20 +922,20 @@ static int process_root_args(void) {
                 return r;
 
         if (arg_root_password && arg_root_password_is_hashed) {
-                password = "x";
+                password = PASSWORD_SEE_SHADOW;
                 hashed_password = arg_root_password;
         } else if (arg_root_password) {
                 r = hash_password(arg_root_password, &_hashed_password);
                 if (r < 0)
                         return log_error_errno(r, "Failed to hash password: %m");
 
-                password = "x";
+                password = PASSWORD_SEE_SHADOW;
                 hashed_password = _hashed_password;
 
         } else if (arg_delete_root_password)
-                password = hashed_password = "";
+                password = hashed_password = PASSWORD_NONE;
         else
-                password = hashed_password = "!";
+                password = hashed_password = PASSWORD_LOCKED_AND_INVALID;
 
         r = write_root_passwd(etc_passwd, password, arg_root_shell);
         if (r < 0)
@@ -1291,7 +1353,12 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
-                                DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_VALIDATE_OS |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                DISSECT_IMAGE_FSCK |
+                                DISSECT_IMAGE_GROWFS,
                                 &unlink_dir,
                                 &loop_device,
                                 &decrypted_image);
index 8c1087a9a33b1d0fe9800ff869dd3e52e42bc574..c0ded48d9788dd3bd4f6ac19de080354337fd1c3 100644 (file)
 #include "virt.h"
 #include "volatile-util.h"
 
-typedef enum MountpointFlags {
-        NOAUTO    = 1 << 0,
-        NOFAIL    = 1 << 1,
-        AUTOMOUNT = 1 << 2,
-        MAKEFS    = 1 << 3,
-        GROWFS    = 1 << 4,
-        RWONLY    = 1 << 5,
-} MountpointFlags;
+typedef enum MountPointFlags {
+        MOUNT_NOAUTO    = 1 << 0,
+        MOUNT_NOFAIL    = 1 << 1,
+        MOUNT_AUTOMOUNT = 1 << 2,
+        MOUNT_MAKEFS    = 1 << 3,
+        MOUNT_GROWFS    = 1 << 4,
+        MOUNT_RW_ONLY   = 1 << 5,
+} MountPointFlags;
 
 static const char *arg_dest = NULL;
 static const char *arg_dest_late = NULL;
@@ -91,7 +91,7 @@ static int write_what(FILE *f, const char *what) {
 static int add_swap(
                 const char *what,
                 struct mntent *me,
-                MountpointFlags flags) {
+                MountPointFlags flags) {
 
         _cleanup_free_ char *name = NULL;
         _cleanup_fclose_ FILE *f = NULL;
@@ -154,19 +154,19 @@ static int add_swap(
         if (r < 0)
                 return r;
 
-        if (flags & MAKEFS) {
+        if (flags & MOUNT_MAKEFS) {
                 r = generator_hook_up_mkswap(arg_dest, what);
                 if (r < 0)
                         return r;
         }
 
-        if (flags & GROWFS)
+        if (flags & MOUNT_GROWFS)
                 /* TODO: swap devices must be wiped and recreated */
                 log_warning("%s: growing swap devices is currently unsupported.", what);
 
-        if (!(flags & NOAUTO)) {
+        if (!(flags & MOUNT_NOAUTO)) {
                 r = generator_add_symlink(arg_dest, SPECIAL_SWAP_TARGET,
-                                          (flags & NOFAIL) ? "wants" : "requires", name);
+                                          (flags & MOUNT_NOFAIL) ? "wants" : "requires", name);
                 if (r < 0)
                         return r;
         }
@@ -345,7 +345,7 @@ static int add_mount(
                 const char *fstype,
                 const char *opts,
                 int passno,
-                MountpointFlags flags,
+                MountPointFlags flags,
                 const char *post,
                 const char *source) {
 
@@ -385,20 +385,20 @@ static int add_mount(
                 return r;
 
         if (path_equal(where, "/")) {
-                if (flags & NOAUTO)
-                        log_warning("Ignoring \"noauto\" for root device");
-                if (flags & NOFAIL)
-                        log_warning("Ignoring \"nofail\" for root device");
-                if (flags & AUTOMOUNT)
-                        log_warning("Ignoring automount option for root device");
+                if (flags & MOUNT_NOAUTO)
+                        log_warning("Ignoring \"noauto\" option for root device");
+                if (flags & MOUNT_NOFAIL)
+                        log_warning("Ignoring \"nofail\" option for root device");
+                if (flags & MOUNT_AUTOMOUNT)
+                        log_warning("Ignoring \"automount\" option for root device");
                 if (!strv_isempty(wanted_by))
-                        log_warning("Ignoring \"x-systemd.wanted-by=\" for root device");
+                        log_warning("Ignoring \"x-systemd.wanted-by=\" option for root device");
                 if (!strv_isempty(required_by))
-                        log_warning("Ignoring \"x-systemd.required-by=\" for root device");
+                        log_warning("Ignoring \"x-systemd.required-by=\" option for root device");
 
                 required_by = strv_free(required_by);
                 wanted_by = strv_free(wanted_by);
-                SET_FLAG(flags, NOAUTO | NOFAIL | AUTOMOUNT, false);
+                SET_FLAG(flags, MOUNT_NOAUTO | MOUNT_NOFAIL | MOUNT_AUTOMOUNT, false);
         }
 
         r = unit_name_from_path(where, ".mount", &name);
@@ -415,7 +415,7 @@ static int add_mount(
                 "SourcePath=%s\n",
                 source);
 
-        if (STRPTR_IN_SET(fstype, "nfs", "nfs4") && !(flags & AUTOMOUNT) &&
+        if (STRPTR_IN_SET(fstype, "nfs", "nfs4") && !(flags & MOUNT_AUTOMOUNT) &&
             fstab_test_yes_no_option(opts, "bg\0" "fg\0")) {
                 /* The default retry timeout that mount.nfs uses for 'bg' mounts
                  * is 10000 minutes, where as it uses 2 minutes for 'fg' mounts.
@@ -426,13 +426,18 @@ static int add_mount(
                  * By placing these options first, they can be overridden by
                  * settings in /etc/fstab. */
                 opts = strjoina("x-systemd.mount-timeout=infinity,retry=10000,nofail,", opts, ",fg");
-                SET_FLAG(flags, NOFAIL, true);
+                SET_FLAG(flags, MOUNT_NOFAIL, true);
         }
 
         r = write_extra_dependencies(f, opts);
         if (r < 0)
                 return r;
 
+        /* Order the mount unit we generate relative to the post unit, so that DefaultDependencies= on the
+         * target unit won't affect us. */
+        if (post && !FLAGS_SET(flags, MOUNT_AUTOMOUNT) && !FLAGS_SET(flags, MOUNT_NOAUTO))
+                fprintf(f, "Before=%s\n", post);
+
         if (passno != 0) {
                 r = generator_write_fsck_deps(f, dest, what, where, fstype);
                 if (r < 0)
@@ -460,7 +465,7 @@ static int add_mount(
                 return r;
 
         if (!isempty(fstype) && !streq(fstype, "auto")) {
-                _cleanup_free_ char *t;
+                _cleanup_free_ char *t = NULL;
 
                 t = specifier_escape(fstype);
                 if (!t)
@@ -485,29 +490,29 @@ static int add_mount(
         if (r < 0)
                 return r;
 
-        if (flags & RWONLY)
+        if (flags & MOUNT_RW_ONLY)
                 fprintf(f, "ReadWriteOnly=yes\n");
 
         r = fflush_and_check(f);
         if (r < 0)
                 return log_error_errno(r, "Failed to write unit file %s: %m", name);
 
-        if (flags & MAKEFS) {
+        if (flags & MOUNT_MAKEFS) {
                 r = generator_hook_up_mkfs(dest, what, where, fstype);
                 if (r < 0)
                         return r;
         }
 
-        if (flags & GROWFS) {
+        if (flags & MOUNT_GROWFS) {
                 r = generator_hook_up_growfs(dest, where, post);
                 if (r < 0)
                         return r;
         }
 
-        if (!FLAGS_SET(flags, AUTOMOUNT)) {
-                if (!FLAGS_SET(flags, NOAUTO) && strv_isempty(wanted_by) && strv_isempty(required_by)) {
+        if (!FLAGS_SET(flags, MOUNT_AUTOMOUNT)) {
+                if (!FLAGS_SET(flags, MOUNT_NOAUTO) && strv_isempty(wanted_by) && strv_isempty(required_by)) {
                         r = generator_add_symlink(dest, post,
-                                                  (flags & NOFAIL) ? "wants" : "requires", name);
+                                                  (flags & MOUNT_NOFAIL) ? "wants" : "requires", name);
                         if (r < 0)
                                 return r;
                 } else {
@@ -557,7 +562,7 @@ static int add_mount(
                         return log_error_errno(r, "Failed to write unit file %s: %m", automount_name);
 
                 r = generator_add_symlink(dest, post,
-                                          (flags & NOFAIL) ? "wants" : "requires", automount_name);
+                                          (flags & MOUNT_NOFAIL) ? "wants" : "requires", automount_name);
                 if (r < 0)
                         return r;
         }
@@ -584,7 +589,8 @@ static int parse_fstab(bool initrd) {
 
         while ((me = getmntent(f))) {
                 _cleanup_free_ char *where = NULL, *what = NULL, *canonical_where = NULL;
-                bool makefs, growfs, noauto, nofail, rwonly;
+                bool makefs, growfs, noauto, nofail;
+                MountPointFlags flags;
                 int k;
 
                 if (initrd && !mount_in_initrd(me))
@@ -624,7 +630,6 @@ static int parse_fstab(bool initrd) {
 
                 makefs = fstab_test_option(me->mnt_opts, "x-systemd.makefs\0");
                 growfs = fstab_test_option(me->mnt_opts, "x-systemd.growfs\0");
-                rwonly = fstab_test_option(me->mnt_opts, "x-systemd.rw-only\0");
                 noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0");
                 nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0");
 
@@ -633,16 +638,25 @@ static int parse_fstab(bool initrd) {
                           yes_no(makefs), yes_no(growfs),
                           yes_no(noauto), yes_no(nofail));
 
+                flags = makefs * MOUNT_MAKEFS |
+                        growfs * MOUNT_GROWFS |
+                        noauto * MOUNT_NOAUTO |
+                        nofail * MOUNT_NOFAIL;
+
                 if (streq(me->mnt_type, "swap"))
-                        k = add_swap(what, me,
-                                     makefs*MAKEFS | growfs*GROWFS | noauto*NOAUTO | nofail*NOFAIL);
+                        k = add_swap(what, me, flags);
                 else {
-                        bool automount;
+                        bool rw_only, automount;
                         const char *post;
 
+                        rw_only = fstab_test_option(me->mnt_opts, "x-systemd.rw-only\0");
                         automount = fstab_test_option(me->mnt_opts,
                                                       "comment=systemd.automount\0"
                                                       "x-systemd.automount\0");
+
+                        flags |= rw_only * MOUNT_RW_ONLY |
+                                 automount * MOUNT_AUTOMOUNT;
+
                         if (initrd)
                                 post = SPECIAL_INITRD_FS_TARGET;
                         else if (mount_is_network(me))
@@ -657,7 +671,7 @@ static int parse_fstab(bool initrd) {
                                       me->mnt_type,
                                       me->mnt_opts,
                                       me->mnt_passno,
-                                      makefs*MAKEFS | growfs*GROWFS | noauto*NOAUTO | nofail*NOFAIL | automount*AUTOMOUNT | rwonly*RWONLY,
+                                      flags,
                                       post,
                                       fstab);
                 }
@@ -721,7 +735,7 @@ static int add_sysroot_mount(void) {
         else
                 opts = arg_root_options;
 
-        log_debug("Found entry what=%s where=/sysroot type=%s", what, strna(arg_root_fstype));
+        log_debug("Found entry what=%s where=/sysroot type=%s opts=%s", what, strna(arg_root_fstype), strempty(opts));
 
         if (is_device_path(what)) {
                 r = generator_write_initrd_root_device_deps(arg_dest, what);
@@ -744,6 +758,10 @@ static int add_sysroot_mount(void) {
 static int add_sysroot_usr_mount(void) {
         _cleanup_free_ char *what = NULL;
         const char *opts;
+        int r;
+
+        /* Returns 0 if we didn't do anything, > 0 if we either generated a unit for the /usr/ mount, or we
+         * know for sure something else did */
 
         if (!arg_usr_what && !arg_usr_fstype && !arg_usr_options)
                 return 0;
@@ -767,8 +785,23 @@ static int add_sysroot_usr_mount(void) {
                         return log_oom();
         }
 
-        if (!arg_usr_what)
+        if (isempty(arg_usr_what)) {
+                log_debug("Could not find a usr= entry on the kernel command line.");
                 return 0;
+        }
+
+        if (streq(arg_usr_what, "gpt-auto")) {
+                /* This is handled by the gpt-auto generator */
+                log_debug("Skipping /usr/ directory handling, as gpt-auto was requested.");
+                return 1; /* systemd-gpt-auto-generator will generate a unit for this, hence report that a
+                           * unit file is being created for the host /usr/ mount. */
+        }
+
+        if (path_equal(arg_usr_what, "/dev/nfs")) {
+                /* This is handled by the initrd (if at all supported, that is) */
+                log_debug("Skipping /usr/ directory handling, as /dev/nfs was requested.");
+                return 1; /* As above, report that NFS code will create the unit */
+        }
 
         what = fstab_node_to_udev_node(arg_usr_what);
         if (!what)
@@ -781,17 +814,62 @@ static int add_sysroot_usr_mount(void) {
         else
                 opts = arg_usr_options;
 
-        log_debug("Found entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype));
-        return add_mount(arg_dest,
-                         what,
-                         "/sysroot/usr",
-                         NULL,
-                         arg_usr_fstype,
-                         opts,
-                         is_device_path(what) ? 1 : 0, /* passno */
-                         0,
-                         SPECIAL_INITRD_FS_TARGET,
-                         "/proc/cmdline");
+        /* When mounting /usr from the initrd, we add an extra level of indirection: we first mount the /usr/
+         * partition to /sysusr/usr/, and then afterwards bind mount that to /sysroot/usr/. We do this so
+         * that we can cover for systems that initially only have a /usr/ around and where the root fs needs
+         * to be synthesized, based on configuration included in /usr/, e.g. systemd-repart. Software like
+         * this should order itself after initrd-usr-fs.target and before initrd-fs.target; and it should
+         * look into both /sysusr/ and /sysroot/ for the configuration data to apply. */
+
+        log_debug("Found entry what=%s where=/sysusr/usr type=%s opts=%s", what, strna(arg_usr_fstype), strempty(opts));
+
+        r = add_mount(arg_dest,
+                      what,
+                      "/sysusr/usr",
+                      NULL,
+                      arg_usr_fstype,
+                      opts,
+                      is_device_path(what) ? 1 : 0, /* passno */
+                      0,
+                      SPECIAL_INITRD_USR_FS_TARGET,
+                      "/proc/cmdline");
+        if (r < 0)
+                return r;
+
+        log_debug("Synthesizing entry what=/sysusr/usr where=/sysrootr/usr opts=bind");
+
+        r = add_mount(arg_dest,
+                      "/sysusr/usr",
+                      "/sysroot/usr",
+                      NULL,
+                      NULL,
+                      "bind",
+                      0,
+                      0,
+                      SPECIAL_INITRD_FS_TARGET,
+                      "/proc/cmdline");
+        if (r < 0)
+                return r;
+
+        return 1;
+}
+
+static int add_sysroot_usr_mount_or_fallback(void) {
+        int r;
+
+        r = add_sysroot_usr_mount();
+        if (r != 0)
+                return r;
+
+        /* OK, so we didn't write anything out for /sysusr/usr/ nor /sysroot/usr/. In this case, let's make
+         * sure that initrd-usr-fs.target is at least ordered after sysroot.mount so that services that order
+         * themselves get the guarantee that /usr/ is definitely mounted somewhere. */
+
+        return generator_add_symlink(
+                        arg_dest,
+                        SPECIAL_INITRD_USR_FS_TARGET,
+                        "requires",
+                        "sysroot.mount");
 }
 
 static int add_volatile_root(void) {
@@ -953,7 +1031,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
         if (in_initrd()) {
                 r = add_sysroot_mount();
 
-                r2 = add_sysroot_usr_mount();
+                r2 = add_sysroot_usr_mount_or_fallback();
 
                 r3 = add_volatile_root();
         } else
index f9d0ca54214749a2ce6f94ad6c43d04158d16c77..705e138b8d25eb66ea347e4e3172dc2e7619923c 100644 (file)
@@ -105,6 +105,7 @@ static int open_parent_block_device(dev_t devnum, int *ret_fd) {
 }
 
 static int add_cryptsetup(const char *id, const char *what, bool rw, bool require, char **device) {
+#if HAVE_LIBCRYPTSETUP
         _cleanup_free_ char *e = NULL, *n = NULL, *d = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         int r;
@@ -182,6 +183,9 @@ static int add_cryptsetup(const char *id, const char *what, bool rw, bool requir
         }
 
         return 0;
+#else
+        return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Partition is encrypted, but the project was compiled without libcryptsetup support");
+#endif
 }
 
 static int add_mount(
@@ -190,6 +194,7 @@ static int add_mount(
                 const char *where,
                 const char *fstype,
                 bool rw,
+                bool growfs,
                 const char *options,
                 const char *description,
                 const char *post) {
@@ -267,8 +272,18 @@ static int add_mount(
         if (r < 0)
                 return log_error_errno(r, "Failed to write unit file %s: %m", p);
 
-        if (post)
-                return generator_add_symlink(arg_dest, post, "requires", unit);
+        if (growfs) {
+                r = generator_hook_up_growfs(arg_dest, where, post);
+                if (r < 0)
+                        return r;
+        }
+
+        if (post) {
+                r = generator_add_symlink(arg_dest, post, "requires", unit);
+                if (r < 0)
+                        return r;
+        }
+
         return 0;
 }
 
@@ -317,6 +332,7 @@ static int add_partition_mount(
                         where,
                         p->fstype,
                         p->rw,
+                        p->growfs,
                         NULL,
                         description,
                         SPECIAL_LOCAL_FS_TARGET);
@@ -381,6 +397,7 @@ static int add_automount(
                 const char *where,
                 const char *fstype,
                 bool rw,
+                bool growfs,
                 const char *options,
                 const char *description,
                 usec_t timeout) {
@@ -402,6 +419,7 @@ static int add_automount(
                       where,
                       fstype,
                       rw,
+                      growfs,
                       opt,
                       description,
                       NULL);
@@ -477,7 +495,8 @@ static int add_xbootldr(DissectedPartition *p) {
                              p->node,
                              "/boot",
                              p->fstype,
-                             true,
+                             /* rw= */ true,
+                             /* growfs= */ false,
                              esp_or_xbootldr_options(p),
                              "Boot Loader Partition",
                              120 * USEC_PER_SEC);
@@ -551,7 +570,8 @@ static int add_esp(DissectedPartition *p, bool has_xbootldr) {
                              p->node,
                              esp_path,
                              p->fstype,
-                             true,
+                             /* rw= */ true,
+                             /* growfs= */ false,
                              esp_or_xbootldr_options(p),
                              "EFI System Partition Automount",
                              120 * USEC_PER_SEC);
@@ -647,7 +667,8 @@ static int add_root_mount(void) {
                         "/dev/gpt-auto-root",
                         in_initrd() ? "/sysroot" : "/",
                         NULL,
-                        arg_root_rw > 0,
+                        /* rw= */ arg_root_rw > 0,
+                        /* growfs= */ false,
                         NULL,
                         "Root Partition",
                         in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
@@ -665,7 +686,15 @@ static int enumerate_partitions(dev_t devnum) {
         if (r <= 0)
                 return r;
 
-        r = dissect_image(fd, NULL, NULL, DISSECT_IMAGE_GPT_ONLY|DISSECT_IMAGE_NO_UDEV, &m);
+        r = dissect_image(
+                        fd,
+                        NULL, NULL,
+                        UINT64_MAX,
+                        USEC_INFINITY,
+                        DISSECT_IMAGE_GPT_ONLY|
+                        DISSECT_IMAGE_NO_UDEV|
+                        DISSECT_IMAGE_USR_NO_ROOT,
+                        &m);
         if (r == -ENOPKG) {
                 log_debug_errno(r, "No suitable partition table found, ignoring.");
                 return 0;
index 9d12b9abae528ff5d36d4d26cf6704a83d6e18a2..09d424734783f1ede7237666843c228b7b1daf75 100644 (file)
@@ -190,7 +190,12 @@ static int list_homes(int argc, char *argv[], void *userdata) {
         return 0;
 }
 
-static int acquire_existing_password(const char *user_name, UserRecord *hr, bool emphasize_current) {
+static int acquire_existing_password(
+                const char *user_name,
+                UserRecord *hr,
+                bool emphasize_current,
+                AskPasswordFlags flags) {
+
         _cleanup_(strv_free_erasep) char **password = NULL;
         _cleanup_free_ char *question = NULL;
         char *e;
@@ -212,16 +217,32 @@ static int acquire_existing_password(const char *user_name, UserRecord *hr, bool
                 string_erase(e);
                 assert_se(unsetenv("PASSWORD") == 0);
 
-                return 0;
+                return 1;
         }
 
+        /* If this is not our own user, then don't use the password cache */
+        if (is_this_me(user_name) <= 0)
+                SET_FLAG(flags, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, false);
+
         if (asprintf(&question, emphasize_current ?
                      "Please enter current password for user %s:" :
                      "Please enter password for user %s:",
                      user_name) < 0)
                 return log_oom();
 
-        r = ask_password_auto(question, "user-home", NULL, "home-password", USEC_INFINITY, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, &password);
+        r = ask_password_auto(question,
+                              /* icon= */ "user-home",
+                              NULL,
+                              /* key_name= */ "home-password",
+                              /* credential_name= */ "home.password",
+                              USEC_INFINITY,
+                              flags,
+                              &password);
+        if (r == -EUNATCH) { /* EUNATCH is returned if no password was found and asking interactively was
+                              * disabled via the flags. Not an error for us. */
+                log_debug_errno(r, "No passwords acquired.");
+                return 0;
+        }
         if (r < 0)
                 return log_error_errno(r, "Failed to acquire password: %m");
 
@@ -229,10 +250,14 @@ static int acquire_existing_password(const char *user_name, UserRecord *hr, bool
         if (r < 0)
                 return log_error_errno(r, "Failed to store password: %m");
 
-        return 0;
+        return 1;
 }
 
-static int acquire_token_pin(const char *user_name, UserRecord *hr) {
+static int acquire_token_pin(
+                const char *user_name,
+                UserRecord *hr,
+                AskPasswordFlags flags) {
+
         _cleanup_(strv_free_erasep) char **pin = NULL;
         _cleanup_free_ char *question = NULL;
         char *e;
@@ -250,14 +275,30 @@ static int acquire_token_pin(const char *user_name, UserRecord *hr) {
                 string_erase(e);
                 assert_se(unsetenv("PIN") == 0);
 
-                return 0;
+                return 1;
         }
 
+        /* If this is not our own user, then don't use the password cache */
+        if (is_this_me(user_name) <= 0)
+                SET_FLAG(flags, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, false);
+
         if (asprintf(&question, "Please enter security token PIN for user %s:", user_name) < 0)
                 return log_oom();
 
-        /* We never cache or use cached PINs, since usually there are only very few attempts allowed before the PIN is blocked */
-        r = ask_password_auto(question, "user-home", NULL, "token-pin", USEC_INFINITY, 0, &pin);
+        r = ask_password_auto(
+                        question,
+                        /* icon= */ "user-home",
+                        NULL,
+                        /* key_name= */ "token-pin",
+                        /* credential_name= */ "home.token-pin",
+                        USEC_INFINITY,
+                        flags,
+                        &pin);
+        if (r == -EUNATCH) { /* EUNATCH is returned if no PIN was found and asking interactively was disabled
+                              * via the flags. Not an error for us. */
+                log_debug_errno(r, "No security token PINs acquired.");
+                return 0;
+        }
         if (r < 0)
                 return log_error_errno(r, "Failed to acquire security token PIN: %m");
 
@@ -265,7 +306,7 @@ static int acquire_token_pin(const char *user_name, UserRecord *hr) {
         if (r < 0)
                 return log_error_errno(r, "Failed to store security token PIN: %m");
 
-        return 0;
+        return 1;
 }
 
 static int handle_generic_user_record_error(
@@ -292,7 +333,13 @@ static int handle_generic_user_record_error(
                 if (!strv_isempty(hr->password))
                         log_notice("Password incorrect or not sufficient, please try again.");
 
-                r = acquire_existing_password(user_name, hr, emphasize_current_password);
+                /* Don't consume cache entries or credentials here, we already tried that unsuccessfully. But
+                 * let's push what we acquire here into the cache */
+                r = acquire_existing_password(
+                                user_name,
+                                hr,
+                                emphasize_current_password,
+                                ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_NO_CREDENTIAL);
                 if (r < 0)
                         return r;
 
@@ -303,13 +350,21 @@ static int handle_generic_user_record_error(
                 else
                         log_notice("Password incorrect or not sufficient, and configured security token not inserted, please try again.");
 
-                r = acquire_existing_password(user_name, hr, emphasize_current_password);
+                r = acquire_existing_password(
+                                user_name,
+                                hr,
+                                emphasize_current_password,
+                                ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_NO_CREDENTIAL);
                 if (r < 0)
                         return r;
 
         } else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_PIN_NEEDED)) {
 
-                r = acquire_token_pin(user_name, hr);
+                /* First time the PIN is requested, let's accept cached data, and allow using credential store */
+                r = acquire_token_pin(
+                                user_name,
+                                hr,
+                                ASK_PASSWORD_ACCEPT_CACHED | ASK_PASSWORD_PUSH_CACHE);
                 if (r < 0)
                         return r;
 
@@ -340,7 +395,11 @@ static int handle_generic_user_record_error(
 
                 log_notice("Security token PIN incorrect, please try again.");
 
-                r = acquire_token_pin(user_name, hr);
+                /* If the previous PIN was wrong don't accept cached info anymore, but add to cache. Also, don't use the credential data */
+                r = acquire_token_pin(
+                                user_name,
+                                hr,
+                                ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_NO_CREDENTIAL);
                 if (r < 0)
                         return r;
 
@@ -348,7 +407,10 @@ static int handle_generic_user_record_error(
 
                 log_notice("Security token PIN incorrect, please try again (only a few tries left!).");
 
-                r = acquire_token_pin(user_name, hr);
+                r = acquire_token_pin(
+                                user_name,
+                                hr,
+                                ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_NO_CREDENTIAL);
                 if (r < 0)
                         return r;
 
@@ -356,7 +418,10 @@ static int handle_generic_user_record_error(
 
                 log_notice("Security token PIN incorrect, please try again (only one try left!).");
 
-                r = acquire_token_pin(user_name, hr);
+                r = acquire_token_pin(
+                                user_name,
+                                hr,
+                                ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_NO_CREDENTIAL);
                 if (r < 0)
                         return r;
         } else
@@ -365,6 +430,39 @@ static int handle_generic_user_record_error(
         return 0;
 }
 
+static int acquire_passed_secrets(const char *user_name, UserRecord **ret) {
+        _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
+        int r;
+
+        assert(ret);
+
+        /* Generates an initial secret objects that contains passwords supplied via $PASSWORD, the password
+         * cache or the credentials subsystem, but excluding any interactive stuff. If nothing is passed,
+         * returns an empty secret object. */
+
+        secret = user_record_new();
+        if (!secret)
+                return log_oom();
+
+        r = acquire_existing_password(
+                        user_name,
+                        secret,
+                        /* emphasize_current_password = */ false,
+                        ASK_PASSWORD_ACCEPT_CACHED | ASK_PASSWORD_NO_TTY | ASK_PASSWORD_NO_AGENT);
+        if (r < 0)
+                return r;
+
+        r = acquire_token_pin(
+                        user_name,
+                        secret,
+                        ASK_PASSWORD_ACCEPT_CACHED | ASK_PASSWORD_NO_TTY | ASK_PASSWORD_NO_AGENT);
+        if (r < 0)
+                return r;
+
+        *ret = TAKE_PTR(secret);
+        return 0;
+}
+
 static int activate_home(int argc, char *argv[], void *userdata) {
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r, ret = 0;
@@ -377,9 +475,9 @@ static int activate_home(int argc, char *argv[], void *userdata) {
         STRV_FOREACH(i, strv_skip(argv, 1)) {
                 _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
 
-                secret = user_record_new();
-                if (!secret)
-                        return log_oom();
+                r = acquire_passed_secrets(*i, &secret);
+                if (r < 0)
+                        return r;
 
                 for (;;) {
                         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -399,7 +497,7 @@ static int activate_home(int argc, char *argv[], void *userdata) {
 
                         r = sd_bus_call(bus, m, HOME_SLOW_BUS_CALL_TIMEOUT_USEC, &error, NULL);
                         if (r < 0) {
-                                r = handle_generic_user_record_error(*i, secret, &error, r, false);
+                                r = handle_generic_user_record_error(*i, secret, &error, r, /* emphasize_current_password= */ false);
                                 if (r < 0) {
                                         if (ret == 0)
                                                 ret = r;
@@ -603,9 +701,9 @@ static int authenticate_home(int argc, char *argv[], void *userdata) {
         STRV_FOREACH(i, items) {
                 _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
 
-                secret = user_record_new();
-                if (!secret)
-                        return log_oom();
+                r = acquire_passed_secrets(*i, &secret);
+                if (r < 0)
+                        return r;
 
                 for (;;) {
                         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -1010,7 +1108,15 @@ static int acquire_new_password(
                 if (asprintf(&question, "Please enter new password for user %s:", user_name) < 0)
                         return log_oom();
 
-                r = ask_password_auto(question, "user-home", NULL, "home-password", USEC_INFINITY, 0, &first);
+                r = ask_password_auto(
+                                question,
+                                /* icon= */ "user-home",
+                                NULL,
+                                /* key_name= */ "home-password",
+                                /* credential_name= */ "home.new-password",
+                                USEC_INFINITY,
+                                0, /* no caching, we want to collect a new password here after all */
+                                &first);
                 if (r < 0)
                         return log_error_errno(r, "Failed to acquire password: %m");
 
@@ -1018,7 +1124,15 @@ static int acquire_new_password(
                 if (asprintf(&question, "Please enter new password for user %s (repeat):", user_name) < 0)
                         return log_oom();
 
-                r = ask_password_auto(question, "user-home", NULL, "home-password", USEC_INFINITY, 0, &second);
+                r = ask_password_auto(
+                                question,
+                                /* icon= */ "user-home",
+                                NULL,
+                                /* key_name= */ "home-password",
+                                /* credential_name= */ "home.new-password",
+                                USEC_INFINITY,
+                                0, /* no caching */
+                                &second);
                 if (r < 0)
                         return log_error_errno(r, "Failed to acquire password: %m");
 
@@ -1106,7 +1220,11 @@ static int create_home(int argc, char *argv[], void *userdata) {
                                 return log_error_errno(r, "Failed to hash password: %m");
                 } else {
                         /* There's a hash password set in the record, acquire the unhashed version of it. */
-                        r = acquire_existing_password(hr->user_name, hr, /* emphasize_current= */ false);
+                        r = acquire_existing_password(
+                                        hr->user_name,
+                                        hr,
+                                        /* emphasize_current= */ false,
+                                        ASK_PASSWORD_ACCEPT_CACHED | ASK_PASSWORD_PUSH_CACHE);
                         if (r < 0)
                                 return r;
                 }
@@ -1585,9 +1703,9 @@ static int resize_home(int argc, char *argv[], void *userdata) {
                 ds = arg_disk_size;
         }
 
-        secret = user_record_new();
-        if (!secret)
-                return log_oom();
+        r = acquire_passed_secrets(argv[1], &secret);
+        if (r < 0)
+                return r;
 
         for (;;) {
                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -1661,9 +1779,9 @@ static int unlock_home(int argc, char *argv[], void *userdata) {
         STRV_FOREACH(i, strv_skip(argv, 1)) {
                 _cleanup_(user_record_unrefp) UserRecord *secret = NULL;
 
-                secret = user_record_new();
-                if (!secret)
-                        return log_oom();
+                r = acquire_passed_secrets(*i, &secret);
+                if (r < 0)
+                        return r;
 
                 for (;;) {
                         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -1727,9 +1845,9 @@ static int with_home(int argc, char *argv[], void *userdata) {
         if (!cmdline)
                 return log_oom();
 
-        secret = user_record_new();
-        if (!secret)
-                return log_oom();
+        r = acquire_passed_secrets(argv[1], &secret);
+        if (r < 0)
+                return r;
 
         for (;;) {
                 r = bus_message_new_method_call(bus, &m, bus_mgr, "AcquireHome");
@@ -3362,4 +3480,4 @@ static int run(int argc, char *argv[]) {
         return dispatch_verb(argc, argv, verbs, NULL);
 }
 
-DEFINE_MAIN_FUNCTION(run);
+DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
index d70fda5f4403e5d13b99db230cb8217b9ac811fb..8f7a646d4a7efdaa548d175103280dffd3af2052 100644 (file)
@@ -59,7 +59,7 @@ int bus_message_read_home_record(sd_bus_message *m, UserRecordLoadFlags flags, U
 
         r = user_record_load(hr, v, flags);
         if (r < 0)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "JSON data is not a valid identity record");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "JSON data is not a valid identity record");
 
         *ret = TAKE_PTR(hr);
         return 0;
index b0c5ce4232a6b6429f443b7910a707d773316c70..dc9a446c71474ffed9751607cb11e6daaa807fe1 100644 (file)
@@ -437,19 +437,19 @@ static int convert_worker_errno(Home *h, int e, sd_bus_error *error) {
         switch (e) {
 
         case -EMSGSIZE:
-                return sd_bus_error_setf(error, BUS_ERROR_BAD_HOME_SIZE, "File systems of this type cannot be shrunk");
+                return sd_bus_error_set(error, BUS_ERROR_BAD_HOME_SIZE, "File systems of this type cannot be shrunk");
         case -ETXTBSY:
-                return sd_bus_error_setf(error, BUS_ERROR_BAD_HOME_SIZE, "File systems of this type can only be shrunk offline");
+                return sd_bus_error_set(error, BUS_ERROR_BAD_HOME_SIZE, "File systems of this type can only be shrunk offline");
         case -ERANGE:
-                return sd_bus_error_setf(error, BUS_ERROR_BAD_HOME_SIZE, "File system size too small");
+                return sd_bus_error_set(error, BUS_ERROR_BAD_HOME_SIZE, "File system size too small");
         case -ENOLINK:
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "System does not support selected storage backend");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "System does not support selected storage backend");
         case -EPROTONOSUPPORT:
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "System does not support selected file system");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "System does not support selected file system");
         case -ENOTTY:
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Operation not supported on storage backend");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Operation not supported on storage backend");
         case -ESOCKTNOSUPPORT:
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Operation not supported on file system");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Operation not supported on file system");
         case -ENOKEY:
                 return sd_bus_error_setf(error, BUS_ERROR_BAD_PASSWORD, "Password for home %s is incorrect or not sufficient for authentication.", h->user_name);
         case -EBADSLT:
@@ -457,21 +457,21 @@ static int convert_worker_errno(Home *h, int e, sd_bus_error *error) {
         case -EREMOTEIO:
                 return sd_bus_error_setf(error, BUS_ERROR_BAD_RECOVERY_KEY, "Recovery key for home %s is incorrect or not sufficient for authentication.", h->user_name);
         case -ENOANO:
-                return sd_bus_error_setf(error, BUS_ERROR_TOKEN_PIN_NEEDED, "PIN for security token required.");
+                return sd_bus_error_set(error, BUS_ERROR_TOKEN_PIN_NEEDED, "PIN for security token required.");
         case -ERFKILL:
-                return sd_bus_error_setf(error, BUS_ERROR_TOKEN_PROTECTED_AUTHENTICATION_PATH_NEEDED, "Security token requires protected authentication path.");
+                return sd_bus_error_set(error, BUS_ERROR_TOKEN_PROTECTED_AUTHENTICATION_PATH_NEEDED, "Security token requires protected authentication path.");
         case -EMEDIUMTYPE:
-                return sd_bus_error_setf(error, BUS_ERROR_TOKEN_USER_PRESENCE_NEEDED, "Security token requires user presence.");
+                return sd_bus_error_set(error, BUS_ERROR_TOKEN_USER_PRESENCE_NEEDED, "Security token requires user presence.");
         case -ENOSTR:
-                return sd_bus_error_setf(error, BUS_ERROR_TOKEN_ACTION_TIMEOUT, "Token action timeout. (User was supposed to verify presence or similar, by interacting with the token, and didn't do that in time.)");
+                return sd_bus_error_set(error, BUS_ERROR_TOKEN_ACTION_TIMEOUT, "Token action timeout. (User was supposed to verify presence or similar, by interacting with the token, and didn't do that in time.)");
         case -EOWNERDEAD:
-                return sd_bus_error_setf(error, BUS_ERROR_TOKEN_PIN_LOCKED, "PIN of security token locked.");
+                return sd_bus_error_set(error, BUS_ERROR_TOKEN_PIN_LOCKED, "PIN of security token locked.");
         case -ENOLCK:
-                return sd_bus_error_setf(error, BUS_ERROR_TOKEN_BAD_PIN, "Bad PIN of security token.");
+                return sd_bus_error_set(error, BUS_ERROR_TOKEN_BAD_PIN, "Bad PIN of security token.");
         case -ETOOMANYREFS:
-                return sd_bus_error_setf(error, BUS_ERROR_TOKEN_BAD_PIN_FEW_TRIES_LEFT, "Bad PIN of security token, and only a few tries left.");
+                return sd_bus_error_set(error, BUS_ERROR_TOKEN_BAD_PIN_FEW_TRIES_LEFT, "Bad PIN of security token, and only a few tries left.");
         case -EUCLEAN:
-                return sd_bus_error_setf(error, BUS_ERROR_TOKEN_BAD_PIN_ONE_TRY_LEFT, "Bad PIN of security token, and only one try left.");
+                return sd_bus_error_set(error, BUS_ERROR_TOKEN_BAD_PIN_ONE_TRY_LEFT, "Bad PIN of security token, and only one try left.");
         case -EBUSY:
                 return sd_bus_error_setf(error, BUS_ERROR_HOME_BUSY, "Home %s is currently being used, or an operation on home %s is currently being executed.", h->user_name, h->user_name);
         case -ENOEXEC:
@@ -1104,7 +1104,7 @@ static int home_ratelimit(Home *h, sd_bus_error *error) {
                         return sd_bus_error_setf(error, BUS_ERROR_AUTHENTICATION_LIMIT_HIT, "Too many login attempts, please try again in %s!",
                                                  format_timespan(buf, sizeof(buf), t - n, USEC_PER_SEC));
 
-                return sd_bus_error_setf(error, BUS_ERROR_AUTHENTICATION_LIMIT_HIT, "Too many login attempts, please try again later.");
+                return sd_bus_error_set(error, BUS_ERROR_AUTHENTICATION_LIMIT_HIT, "Too many login attempts, please try again later.");
         }
 
         return 0;
@@ -1402,10 +1402,10 @@ static int home_update_internal(
         assert(hr);
 
         if (!user_record_compatible(hr, h->record))
-                return sd_bus_error_setf(error, BUS_ERROR_HOME_RECORD_MISMATCH, "Updated user record is not compatible with existing one.");
+                return sd_bus_error_set(error, BUS_ERROR_HOME_RECORD_MISMATCH, "Updated user record is not compatible with existing one.");
         c = user_record_compare_last_change(hr, h->record); /* refuse downgrades */
         if (c < 0)
-                return sd_bus_error_setf(error, BUS_ERROR_HOME_RECORD_DOWNGRADE, "Refusing to update to older home record.");
+                return sd_bus_error_set(error, BUS_ERROR_HOME_RECORD_DOWNGRADE, "Refusing to update to older home record.");
 
         if (!secret && FLAGS_SET(hr->mask, USER_RECORD_SECRET)) {
                 r = user_record_clone(hr, USER_RECORD_EXTRACT_SECRET, &saved_secret);
@@ -1454,7 +1454,7 @@ static int home_update_internal(
                 if (r < 0)
                         return r;
                 if (r == 0)
-                        return sd_bus_error_setf(error, BUS_ERROR_HOME_RECORD_MISMATCH, "Home record different but timestamp remained the same, refusing.");
+                        return sd_bus_error_set(error, BUS_ERROR_HOME_RECORD_MISMATCH, "Home record different but timestamp remained the same, refusing.");
         }
 
         r = home_start_work(h, verb, new_hr, secret);
@@ -1528,7 +1528,7 @@ int home_resize(Home *h, uint64_t disk_size, UserRecord *secret, sd_bus_error *e
 
         if (disk_size == UINT64_MAX || disk_size == h->record->disk_size) {
                 if (h->record->disk_size == UINT64_MAX)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "No disk size to resize to specified.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "No disk size to resize to specified.");
 
                 c = user_record_ref(h->record); /* Shortcut if size is unspecified or matches the record */
         } else {
@@ -2349,6 +2349,8 @@ static int home_dispatch_acquire(Home *h, Operation *o) {
         assert(o);
         assert(o->type == OPERATION_ACQUIRE);
 
+        assert(!h->current_operation);
+
         switch (home_get_state(h)) {
 
         case HOME_UNFIXATED:
@@ -2357,8 +2359,9 @@ static int home_dispatch_acquire(Home *h, Operation *o) {
                 break;
 
         case HOME_ABSENT:
-                r = sd_bus_error_setf(&error, BUS_ERROR_HOME_ABSENT, "Home %s is currently missing or not plugged in.", h->user_name);
-                break;
+                r = sd_bus_error_setf(&error, BUS_ERROR_HOME_ABSENT,
+                                      "Home %s is currently missing or not plugged in.", h->user_name);
+                goto check;
 
         case HOME_INACTIVE:
         case HOME_DIRTY:
@@ -2382,14 +2385,11 @@ static int home_dispatch_acquire(Home *h, Operation *o) {
                 return 0;
         }
 
-        assert(!h->current_operation);
-
-        if (call) {
-                r = home_ratelimit(h, &error);
-                if (r >= 0)
-                        r = call(h, o->secret, for_state, &error);
-        }
+        r = home_ratelimit(h, &error);
+        if (r >= 0)
+                r = call(h, o->secret, for_state, &error);
 
+ check:
         if (r != 0) /* failure or completed */
                 operation_result(o, r, &error);
         else /* ongoing */
@@ -2660,7 +2660,7 @@ int home_schedule_operation(Home *h, Operation *o, sd_bus_error *error) {
 
         if (o) {
                 if (ordered_set_size(h->pending_operations) >= PENDING_OPERATIONS_MAX)
-                        return sd_bus_error_setf(error, BUS_ERROR_TOO_MANY_OPERATIONS, "Too many client operations requested");
+                        return sd_bus_error_set(error, BUS_ERROR_TOO_MANY_OPERATIONS, "Too many client operations requested");
 
                 r = ordered_set_ensure_put(&h->pending_operations, &operation_hash_ops, o);
                 if (r < 0)
index 85fdc88962c6c8a0772044fe176e6d9b189a1085..f8dfa272b93101099d202fc6dff6cca43afa5469 100644 (file)
@@ -1327,7 +1327,7 @@ static int manager_load_key_pair(Manager *m) {
                 m->private_key = NULL;
         }
 
-        r = search_and_fopen_nulstr("local.private", "re", NULL, KEY_PATHS_NULSTR, &f);
+        r = search_and_fopen_nulstr("local.private", "re", NULL, KEY_PATHS_NULSTR, &f, NULL);
         if (r == -ENOENT)
                 return 0;
         if (r < 0)
@@ -1457,7 +1457,7 @@ int manager_sign_user_record(Manager *m, UserRecord *u, UserRecord **ret, sd_bus
         if (r < 0)
                 return r;
         if (r == 0)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_KEY, "Can't sign without local key.");
+                return sd_bus_error_set(error, BUS_ERROR_NO_PRIVATE_KEY, "Can't sign without local key.");
 
         return user_record_sign(u, m->private_key, ret);
 }
index ba854641df78f5b3e6d50ebcd6be07ece3fead1d..d3a685e81649fb96491c99a85af8942b43f9cc16 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Entries in this file show the compile time defaults. Local configuration
 # should be created by either modifying this file, or by creating "drop-ins" in
-# the system.conf.d/ subdirectory. The latter is generally recommended.
+# the homed.conf.d/ subdirectory. The latter is generally recommended.
 # Defaults can be restored by simply deleting this file and all drop-ins.
 #
 # Use 'systemd-analyze cat-config systemd/homed.conf' to display the full config.
index 07d5bcfdb6136eb79fd9f6f4708f6f4bdadb74ac..543195914fb3632c7ddb603a6eeebf054cd9d58c 100644 (file)
@@ -1870,7 +1870,8 @@ int home_create_luks(
                 UserRecord **ret_home) {
 
         _cleanup_free_ char *dm_name = NULL, *dm_node = NULL, *subdir = NULL, *disk_uuid_path = NULL, *temporary_image_path = NULL;
-        uint64_t host_size, encrypted_size, partition_offset, partition_size;
+        uint64_t encrypted_size,
+                host_size = 0, partition_offset = 0, partition_size = 0; /* Unnecessary initialization to appease gcc */
         bool image_created = false, dm_activated = false, mounted = false;
         _cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
         sd_id128_t partition_uuid, fs_uuid, luks_uuid, disk_uuid;
index b8f59c55ecbd7795825ceab206001e510733ffa2..e244ba5772a106baf574d6c853ab8d6d6b4c644b 100644 (file)
@@ -1351,16 +1351,16 @@ int user_record_is_supported(UserRecord *hr, sd_bus_error *error) {
         assert(hr);
 
         if (hr->disposition >= 0 && hr->disposition != USER_REGULAR)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot manage anything but regular users.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot manage anything but regular users.");
 
         if (hr->storage >= 0 && !IN_SET(hr->storage, USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT, USER_CIFS))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User record has storage type this service cannot manage.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "User record has storage type this service cannot manage.");
 
         if (gid_is_valid(hr->gid) && hr->uid != (uid_t) hr->gid)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User record has to have matching UID/GID fields.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "User record has to have matching UID/GID fields.");
 
         if (hr->service && !streq(hr->service, "io.systemd.Home"))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not accepted with service not matching io.systemd.Home.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Not accepted with service not matching io.systemd.Home.");
 
         return 0;
 }
index e7cb015ef2dc71559187791e495e78a7f4905925..283038c7cbaf55e5dc3d96122400df543803588c 100644 (file)
@@ -17,7 +17,9 @@
 #include "format-table.h"
 #include "hostname-setup.h"
 #include "hostname-util.h"
+#include "json.h"
 #include "main-func.h"
+#include "parse-argument.h"
 #include "pretty-print.h"
 #include "spawn-polkit-agent.h"
 #include "terminal-util.h"
@@ -30,6 +32,7 @@ static char *arg_host = NULL;
 static bool arg_transient = false;
 static bool arg_pretty = false;
 static bool arg_static = false;
+static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
 
 typedef struct StatusInfo {
         const char *hostname;
@@ -155,17 +158,10 @@ static int print_status_info(StatusInfo *i) {
         }
 
         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;
-                }
-
                 r = table_add_many(table,
                                    TABLE_STRING, "Operating System:",
-                                   TABLE_STRING, t);
+                                   TABLE_STRING, i->os_pretty_name,
+                                   TABLE_SET_URL, i->home_url);
                 if (r < 0)
                         return table_log_add_error(r);
         }
@@ -315,25 +311,60 @@ static int show_all_names(sd_bus *bus) {
         return print_status_info(&info);
 }
 
+static int get_hostname_based_on_flag(sd_bus *bus) {
+        const char *attr;
+
+        if (!!arg_static + !!arg_pretty + !!arg_transient > 1)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "Cannot query more than one name type at a time");
+
+        attr = arg_pretty ? "PrettyHostname" :
+                arg_static ? "StaticHostname" : "Hostname";
+
+        return get_one_name(bus, attr, NULL);
+}
+
 static int show_status(int argc, char **argv, void *userdata) {
         sd_bus *bus = userdata;
+        int r;
 
-        if (arg_pretty || arg_static || arg_transient) {
-                const char *attr;
+        if (arg_json_format_flags != JSON_FORMAT_OFF) {
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+                _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+                const char *text = NULL;
+
+                r = sd_bus_call_method(
+                                bus,
+                                "org.freedesktop.hostname1",
+                                "/org/freedesktop/hostname1",
+                                "org.freedesktop.hostname1",
+                                "Describe",
+                                &error,
+                                &reply,
+                                NULL);
+                if (r < 0)
+                        return log_error_errno(r, "Could not get description: %s", bus_error_message(&error, r));
 
-                if (!!arg_static + !!arg_pretty + !!arg_transient > 1)
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                               "Cannot query more than one name type at a time");
+                r = sd_bus_message_read(reply, "s", &text);
+                if (r < 0)
+                        return bus_log_parse_error(r);
 
-                attr = arg_pretty ? "PrettyHostname" :
-                        arg_static ? "StaticHostname" : "Hostname";
+                r = json_parse(text, 0, &v, NULL, NULL);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse JSON: %m");
 
-                return get_one_name(bus, attr, NULL);
+                json_variant_dump(v, arg_json_format_flags, NULL, NULL);
+                return 0;
         }
 
+        if (arg_pretty || arg_static || arg_transient)
+                return get_hostname_based_on_flag(bus);
+
         return show_all_names(bus);
 }
 
+
 static int set_simple_string_internal(sd_bus *bus, sd_bus_error *error, const char *target, const char *method, const char *value) {
         _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
         int r;
@@ -447,20 +478,29 @@ static int set_hostname(int argc, char **argv, void *userdata) {
         return ret;
 }
 
-static int set_icon_name(int argc, char **argv, void *userdata) {
-        return set_simple_string(userdata, "icon", "SetIconName", argv[1]);
+static int get_or_set_hostname(int argc, char **argv, void *userdata) {
+        return argc == 1 ? get_hostname_based_on_flag(userdata) :
+                           set_hostname(argc, argv, userdata);
+}
+
+static int get_or_set_icon_name(int argc, char **argv, void *userdata) {
+        return argc == 1 ? get_one_name(userdata, "IconName", NULL) :
+                           set_simple_string(userdata, "icon", "SetIconName", argv[1]);
 }
 
-static int set_chassis(int argc, char **argv, void *userdata) {
-        return set_simple_string(userdata, "chassis", "SetChassis", argv[1]);
+static int get_or_set_chassis(int argc, char **argv, void *userdata) {
+        return argc == 1 ? get_one_name(userdata, "Chassis", NULL) :
+                           set_simple_string(userdata, "chassis", "SetChassis", argv[1]);
 }
 
-static int set_deployment(int argc, char **argv, void *userdata) {
-        return set_simple_string(userdata, "deployment", "SetDeployment", argv[1]);
+static int get_or_set_deployment(int argc, char **argv, void *userdata) {
+        return argc == 1 ? get_one_name(userdata, "Deployment", NULL) :
+                           set_simple_string(userdata, "deployment", "SetDeployment", argv[1]);
 }
 
-static int set_location(int argc, char **argv, void *userdata) {
-        return set_simple_string(userdata, "location", "SetLocation", argv[1]);
+static int get_or_set_location(int argc, char **argv, void *userdata) {
+        return argc == 1 ? get_one_name(userdata, "Location", NULL) :
+                           set_simple_string(userdata, "location", "SetLocation", argv[1]);
 }
 
 static int help(void) {
@@ -475,11 +515,11 @@ static int help(void) {
                "%sQuery or change system hostname.%s\n"
                "\nCommands:\n"
                "  status                 Show current hostname settings\n"
-               "  set-hostname NAME      Set system hostname\n"
-               "  set-icon-name NAME     Set icon name for host\n"
-               "  set-chassis NAME       Set chassis type for host\n"
-               "  set-deployment NAME    Set deployment environment for host\n"
-               "  set-location NAME      Set location for host\n"
+               "  hostname [NAME]        Get/set system hostname\n"
+               "  icon-name [NAME]       Get/set icon name for host\n"
+               "  chassis [NAME]         Get/set chassis type for host\n"
+               "  deployment [NAME]      Get/set deployment environment for host\n"
+               "  location [NAME]        Get/set location for host\n"
                "\nOptions:\n"
                "  -h --help              Show this help\n"
                "     --version           Show package version\n"
@@ -489,6 +529,8 @@ static int help(void) {
                "     --transient         Only set transient hostname\n"
                "     --static            Only set static hostname\n"
                "     --pretty            Only set pretty hostname\n"
+               "     --json=pretty|short|off\n"
+               "                         Generate JSON output\n"
                "\nSee the %s for details.\n",
                program_invocation_short_name,
                ansi_highlight(),
@@ -509,7 +551,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_NO_ASK_PASSWORD,
                 ARG_TRANSIENT,
                 ARG_STATIC,
-                ARG_PRETTY
+                ARG_PRETTY,
+                ARG_JSON,
         };
 
         static const struct option options[] = {
@@ -521,10 +564,11 @@ static int parse_argv(int argc, char *argv[]) {
                 { "host",            required_argument, NULL, 'H'                 },
                 { "machine",         required_argument, NULL, 'M'                 },
                 { "no-ask-password", no_argument,       NULL, ARG_NO_ASK_PASSWORD },
+                { "json",            required_argument, NULL, ARG_JSON            },
                 {}
         };
 
-        int c;
+        int c, r;
 
         assert(argc >= 0);
         assert(argv);
@@ -565,6 +609,13 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_ask_password = false;
                         break;
 
+                case ARG_JSON:
+                        r = parse_json_argument(optarg, &arg_json_format_flags);
+                        if (r <= 0)
+                                return r;
+
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -578,13 +629,18 @@ static int parse_argv(int argc, char *argv[]) {
 static int hostnamectl_main(sd_bus *bus, int argc, char *argv[]) {
 
         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. */
+                { "status",         VERB_ANY, 1,        VERB_DEFAULT, show_status           },
+                { "hostname",       VERB_ANY, 2,        0,            get_or_set_hostname   },
+                { "set-hostname",   2,        2,        0,            get_or_set_hostname   }, /* obsolete */
+                { "icon-name",      VERB_ANY, 2,        0,            get_or_set_icon_name  },
+                { "set-icon-name",  2,        2,        0,            get_or_set_icon_name  }, /* obsolete */
+                { "chassis",        VERB_ANY, 2,        0,            get_or_set_chassis    },
+                { "set-chassis",    2,        2,        0,            get_or_set_chassis    }, /* obsolete */
+                { "deployment",     VERB_ANY, 2,        0,            get_or_set_deployment },
+                { "set-deployment", 2,        2,        0,            get_or_set_deployment }, /* obsolete */
+                { "location",       VERB_ANY, 2,        0,            get_or_set_location   },
+                { "set-location",   2,        2,        0,            get_or_set_location   }, /* obsolete */
+                { "help",           VERB_ANY, VERB_ANY, 0,            verb_help             }, /* Not documented, but supported since it is created. */
                 {}
         };
 
index 2ece8b2fbd9bbf0f8ab697ae45f9f3811bd4b676..bd535ddc4d8042a88427dee9795a7674031d96ce 100644 (file)
@@ -20,6 +20,7 @@
 #include "hostname-setup.h"
 #include "hostname-util.h"
 #include "id128-util.h"
+#include "json.h"
 #include "main-func.h"
 #include "missing_capability.h"
 #include "nscd-flush.h"
@@ -40,6 +41,8 @@
 
 #define VALID_DEPLOYMENT_CHARS (DIGITS LETTERS "-.:")
 
+/* Properties we cache are indexed by an enum, to make invalidation easy and systematic (as we can iterate
+ * through them all, and they are uniformly strings). */
 enum {
         /* Read from /etc/hostname */
         PROP_STATIC_HOSTNAME,
@@ -51,9 +54,6 @@ enum {
         PROP_DEPLOYMENT,
         PROP_LOCATION,
 
-        PROP_HARDWARE_VENDOR,
-        PROP_HARDWARE_MODEL,
-
         /* Read from /etc/os-release (or /usr/lib/os-release) */
         PROP_OS_PRETTY_NAME,
         PROP_OS_CPE_NAME,
@@ -449,6 +449,41 @@ static int context_write_data_machine_info(Context *c) {
         return 0;
 }
 
+static int get_dmi_data(const char *database_key, const char *regular_key, char **ret) {
+        _cleanup_(sd_device_unrefp) sd_device *device = NULL;
+        _cleanup_free_ char *b = NULL;
+        const char *s = NULL;
+        int r;
+
+        r = sd_device_new_from_syspath(&device, "/sys/class/dmi/id");
+        if (r < 0)
+                return log_debug_errno(r, "Failed to open /sys/class/dmi/id device, ignoring: %m");
+
+        if (database_key)
+                (void) sd_device_get_property_value(device, database_key, &s);
+        if (!s && regular_key)
+                (void) sd_device_get_property_value(device, regular_key, &s);
+
+        if (s) {
+                b = strdup(s);
+                if (!b)
+                        return -ENOMEM;
+        }
+
+        if (ret)
+                *ret = TAKE_PTR(b);
+
+        return !!s;
+}
+
+static int get_hardware_vendor(char **ret) {
+        return get_dmi_data("ID_VENDOR_FROM_DATABASE", "ID_VENDOR", ret);
+}
+
+static int get_hardware_model(char **ret) {
+        return get_dmi_data("ID_MODEL_FROM_DATABASE", "ID_MODEL", ret);
+}
+
 static int property_get_hardware_vendor(
                 sd_bus *bus,
                 const char *path,
@@ -457,20 +492,11 @@ static int property_get_hardware_vendor(
                 sd_bus_message *reply,
                 void *userdata,
                 sd_bus_error *error) {
-        _cleanup_(sd_device_unrefp) sd_device *device = NULL;
-        const char *hardware_vendor = NULL;
-        int r;
 
-        r = sd_device_new_from_syspath(&device, "/sys/class/dmi/id");
-        if (r < 0) {
-                log_warning_errno(r, "Failed to open /sys/class/dmi/id device, ignoring: %m");
-                return sd_bus_message_append(reply, "s", NULL);
-        }
+        _cleanup_free_ char *vendor = NULL;
 
-        if (sd_device_get_property_value(device, "ID_VENDOR_FROM_DATABASE", &hardware_vendor) < 0)
-                (void) sd_device_get_property_value(device, "ID_VENDOR", &hardware_vendor);
-
-        return sd_bus_message_append(reply, "s", hardware_vendor);
+        (void) get_hardware_vendor(&vendor);
+        return sd_bus_message_append(reply, "s", vendor);
 }
 
 static int property_get_hardware_model(
@@ -481,20 +507,11 @@ static int property_get_hardware_model(
                 sd_bus_message *reply,
                 void *userdata,
                 sd_bus_error *error) {
-        _cleanup_(sd_device_unrefp) sd_device *device = NULL;
-        const char *hardware_model = NULL;
-        int r;
-
-        r = sd_device_new_from_syspath(&device, "/sys/class/dmi/id");
-        if (r < 0) {
-                log_warning_errno(r, "Failed to open /sys/class/dmi/id device, ignoring: %m");
-                return sd_bus_message_append(reply, "s", NULL);
-        }
 
-        if (sd_device_get_property_value(device, "ID_MODEL_FROM_DATABASE", &hardware_model) < 0)
-                (void) sd_device_get_property_value(device, "ID_MODEL", &hardware_model);
+        _cleanup_free_ char *model = NULL;
 
-        return sd_bus_message_append(reply, "s", hardware_model);
+        (void) get_hardware_model(&model);
+        return sd_bus_message_append(reply, "s", model);
 }
 
 static int property_get_hostname(
@@ -548,13 +565,46 @@ static int property_get_default_hostname(
                 void *userdata,
                 sd_bus_error *error) {
 
-        _cleanup_free_ char *hn = get_default_hostname();
+        _cleanup_free_ char *hn = NULL;
+
+        hn = get_default_hostname();
         if (!hn)
                 return log_oom();
 
         return sd_bus_message_append(reply, "s", hn);
 }
 
+static void context_determine_hostname_source(Context *c) {
+        char hostname[HOST_NAME_MAX + 1] = {};
+        _cleanup_free_ char *fallback = NULL;
+        int r;
+
+        assert(c);
+
+        if (c->hostname_source >= 0)
+                return;
+
+        (void) get_hostname_filtered(hostname);
+
+        if (streq_ptr(hostname, c->data[PROP_STATIC_HOSTNAME]))
+                c->hostname_source = HOSTNAME_STATIC;
+        else {
+                /* If the hostname was not set by us, try to figure out where it came from. If we set it to
+                 * the default hostname, the file will tell us. We compare the string because it is possible
+                 * that the hostname was set by an older version that had a different fallback, in the
+                 * initramfs or before we reexecuted. */
+
+                r = read_one_line_file("/run/systemd/default-hostname", &fallback);
+                if (r < 0 && r != -ENOENT)
+                        log_warning_errno(r, "Failed to read /run/systemd/default-hostname, ignoring: %m");
+
+                if (streq_ptr(fallback, hostname))
+                        c->hostname_source = HOSTNAME_DEFAULT;
+                else
+                        c->hostname_source = HOSTNAME_TRANSIENT;
+        }
+}
+
 static int property_get_hostname_source(
                 sd_bus *bus,
                 const char *path,
@@ -565,36 +615,10 @@ static int property_get_hostname_source(
                 sd_bus_error *error) {
 
         Context *c = userdata;
-        int r;
         assert(c);
 
         context_read_etc_hostname(c);
-
-        if (c->hostname_source < 0) {
-                char hostname[HOST_NAME_MAX + 1] = {};
-                _cleanup_free_ char *fallback = NULL;
-
-                (void) get_hostname_filtered(hostname);
-
-                if (streq_ptr(hostname, c->data[PROP_STATIC_HOSTNAME]))
-                        c->hostname_source = HOSTNAME_STATIC;
-
-                else {
-                        /* If the hostname was not set by us, try to figure out where it came from. If we set
-                         * it to the default hostname, the file will tell us. We compare the string because
-                         * it is possible that the hostname was set by an older version that had a different
-                         * fallback, in the initramfs or before we reexecuted. */
-
-                        r = read_one_line_file("/run/systemd/default-hostname", &fallback);
-                        if (r < 0 && r != -ENOENT)
-                                log_warning_errno(r, "Failed to read /run/systemd/default-hostname, ignoring: %m");
-
-                        if (streq_ptr(fallback, hostname))
-                                c->hostname_source = HOSTNAME_DEFAULT;
-                        else
-                                c->hostname_source = HOSTNAME_TRANSIENT;
-                }
-        }
+        context_determine_hostname_source(c);
 
         return sd_bus_message_append(reply, "s", hostname_source_to_string(c->hostname_source));
 }
@@ -932,28 +956,12 @@ static int method_set_location(sd_bus_message *m, void *userdata, sd_bus_error *
 static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_error *error) {
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         Context *c = userdata;
-        bool has_uuid = false;
         int interactive, r;
         sd_id128_t uuid;
 
         assert(m);
         assert(c);
 
-        r = id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, &uuid);
-        if (r == -ENOENT)
-                r = id128_read("/sys/firmware/devicetree/base/vm,uuid", ID128_UUID, &uuid);
-        if (r < 0)
-                log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
-                               "Failed to read product UUID, ignoring: %m");
-        else if (sd_id128_is_null(uuid) || sd_id128_is_allf(uuid))
-                log_debug("DMI product UUID " SD_ID128_FORMAT_STR " is all 0x00 or all 0xFF, ignoring.", SD_ID128_FORMAT_VAL(uuid));
-        else
-                has_uuid = true;
-
-        if (!has_uuid)
-                return sd_bus_error_set(error, BUS_ERROR_NO_PRODUCT_UUID,
-                                        "Failed to read product UUID from firmware.");
-
         r = sd_bus_message_read(m, "b", &interactive);
         if (r < 0)
                 return r;
@@ -972,11 +980,125 @@ static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_err
         if (r == 0)
                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
 
+        r = id128_get_product(&uuid);
+        if (r < 0) {
+                if (r == -EADDRNOTAVAIL)
+                        log_debug_errno(r, "DMI product UUID is all 0x00 or all 0xFF, ignoring.");
+                else
+                        log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+                                       "Failed to read product UUID, ignoring: %m");
+
+                return sd_bus_error_set(error, BUS_ERROR_NO_PRODUCT_UUID,
+                                        "Failed to read product UUID from firmware.");
+        }
+
+        r = sd_bus_message_new_method_return(m, &reply);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append_array(reply, 'y', uuid.bytes, sizeof(uuid.bytes));
+        if (r < 0)
+                return r;
+
+        return sd_bus_send(NULL, reply, NULL);
+}
+
+static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+        _cleanup_free_ char *hn = NULL, *dhn = NULL, *in = NULL, *text = NULL, *vendor = NULL, *model = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+        sd_id128_t product_uuid = SD_ID128_NULL;
+        const char *chassis = NULL;
+        Context *c = userdata;
+        bool privileged;
+        struct utsname u;
+        int r;
+
+        assert(m);
+        assert(c);
+
+        r = bus_verify_polkit_async(
+                        m,
+                        CAP_SYS_ADMIN,
+                        "org.freedesktop.hostname1.get-product-uuid",
+                        NULL,
+                        false,
+                        UID_INVALID,
+                        &c->polkit_registry,
+                        NULL);
+        if (r == 0)
+                return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+
+        /* We ignore all authentication errors here, since most data is unprivileged, the one exception being
+         * the product ID which we'll check explicitly. */
+        privileged = r > 0;
+
+        context_read_etc_hostname(c);
+        context_read_machine_info(c);
+        context_read_os_release(c);
+        context_determine_hostname_source(c);
+
+        r = gethostname_strict(&hn);
+        if (r < 0) {
+                if (r != -ENXIO)
+                        return log_error_errno(r, "Failed to read local host name: %m");
+
+                hn = get_default_hostname();
+                if (!hn)
+                        return log_oom();
+        }
+
+        dhn = get_default_hostname();
+        if (!dhn)
+                return log_oom();
+
+        if (isempty(c->data[PROP_ICON_NAME]))
+                in = context_fallback_icon_name(c);
+
+        if (isempty(c->data[PROP_CHASSIS]))
+                chassis = fallback_chassis();
+
+        assert_se(uname(&u) >= 0);
+
+        (void) get_hardware_vendor(&vendor);
+        (void) get_hardware_model(&model);
+
+        if (privileged) /* The product UUID is only available to privileged clients */
+                id128_get_product(&product_uuid);
+
+        r = json_build(&v, JSON_BUILD_OBJECT(
+                                       JSON_BUILD_PAIR("Hostname", JSON_BUILD_STRING(hn)),
+                                       JSON_BUILD_PAIR("StaticHostname", JSON_BUILD_STRING(c->data[PROP_STATIC_HOSTNAME])),
+                                       JSON_BUILD_PAIR("PrettyHostname", JSON_BUILD_STRING(c->data[PROP_PRETTY_HOSTNAME])),
+                                       JSON_BUILD_PAIR("DefaultHostname", JSON_BUILD_STRING(dhn)),
+                                       JSON_BUILD_PAIR("HostnameSource", JSON_BUILD_STRING(hostname_source_to_string(c->hostname_source))),
+                                       JSON_BUILD_PAIR("IconName", JSON_BUILD_STRING(in ?: c->data[PROP_ICON_NAME])),
+                                       JSON_BUILD_PAIR("Chassis", JSON_BUILD_STRING(chassis ?: c->data[PROP_CHASSIS])),
+                                       JSON_BUILD_PAIR("Deployment", JSON_BUILD_STRING(c->data[PROP_DEPLOYMENT])),
+                                       JSON_BUILD_PAIR("Location", JSON_BUILD_STRING(c->data[PROP_LOCATION])),
+                                       JSON_BUILD_PAIR("KernelName", JSON_BUILD_STRING(u.sysname)),
+                                       JSON_BUILD_PAIR("KernelRelease", JSON_BUILD_STRING(u.release)),
+                                       JSON_BUILD_PAIR("KernelVersion", JSON_BUILD_STRING(u.version)),
+                                       JSON_BUILD_PAIR("OperatingSystemPrettyName", JSON_BUILD_STRING(c->data[PROP_OS_PRETTY_NAME])),
+                                       JSON_BUILD_PAIR("OperatingSystemCPEName", JSON_BUILD_STRING(c->data[PROP_OS_CPE_NAME])),
+                                       JSON_BUILD_PAIR("OperatingSystemHomeURL", JSON_BUILD_STRING(c->data[PROP_OS_HOME_URL])),
+                                       JSON_BUILD_PAIR("HardwareVendor", JSON_BUILD_STRING(vendor)),
+                                       JSON_BUILD_PAIR("HardwareModel", JSON_BUILD_STRING(model)),
+                                       JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(product_uuid), "ProductUUID", JSON_BUILD_ID128(product_uuid)),
+                                       JSON_BUILD_PAIR_CONDITION(sd_id128_is_null(product_uuid), "ProductUUID", JSON_BUILD_NULL)));
+
+        if (r < 0)
+                return log_error_errno(r, "Failed to build JSON data: %m");
+
+        r = json_variant_format(v, 0, &text);
+        if (r < 0)
+                return log_error_errno(r, "Failed to format JSON data: %m");
+
         r = sd_bus_message_new_method_return(m, &reply);
         if (r < 0)
                 return r;
 
-        r = sd_bus_message_append_array(reply, 'y', &uuid, sizeof(uuid));
+        r = sd_bus_message_append(reply, "s", text);
         if (r < 0)
                 return r;
 
@@ -1059,6 +1181,11 @@ static const sd_bus_vtable hostname_vtable[] = {
                                  SD_BUS_PARAM(uuid),
                                  method_get_product_uuid,
                                  SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("Describe",
+                                SD_BUS_NO_ARGS,
+                                SD_BUS_RESULT("s", json),
+                                method_describe,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
 
         SD_BUS_VTABLE_END,
 };
index e6db8106355c38c7306eaa70e9a3a260997b9195..ed2ac0a654a69c3a832ee15bf34a5e775f63b9c0 100644 (file)
@@ -3,11 +3,11 @@
 #include <fcntl.h>
 
 #include "alloc-util.h"
-#include "build.h"
 #include "curl-util.h"
 #include "fd-util.h"
 #include "locale-util.h"
 #include "string-util.h"
+#include "version.h"
 
 static void curl_glue_check_finished(CurlGlue *g) {
         CURLMsg *msg;
index fa8ff68a461bd2c8994d4dbc23dfdf18f873df8e..f0f61ca7848e62153b5dad7f5bcb450615147c6e 100644 (file)
@@ -1080,7 +1080,7 @@ static int method_cancel_transfer(sd_bus_message *msg, void *userdata, sd_bus_er
         if (r < 0)
                 return r;
         if (id <= 0)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid transfer id");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid transfer id");
 
         t = hashmap_get(m->transfers, UINT32_TO_PTR(id));
         if (!t)
index 4cefe3918c9d60dc4180dc7cbd9fa3c8f0d28a07..a2f166a881ba57ba6c132a3d222915ae1842f5ce 100644 (file)
@@ -311,7 +311,7 @@ static int request_parse_range(
 
                 colon2 = strchr(colon + 1, ':');
                 if (colon2) {
-                        _cleanup_free_ char *t;
+                        _cleanup_free_ char *t = NULL;
 
                         t = strndup(colon + 1, colon2 - colon - 1);
                         if (!t)
index 6f71248aaf31cf754652aa04d05d31b5c0fa73ab..9600e5f732475f26f2c37ccd2791bf2ab1d95569 100644 (file)
@@ -40,7 +40,7 @@ static int open_output(RemoteServer *s, Writer *w, const char* host) {
                 break;
 
         case JOURNAL_WRITE_SPLIT_HOST: {
-                _cleanup_free_ char *name;
+                _cleanup_free_ char *name = NULL;
 
                 assert(host);
 
index 1e4c3b9710fe0027e0c09cb0ec51edb1acf109a9..4c1b78ebc17311da70d02239d39daf56e86e264e 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Entries in this file show the compile time defaults. Local configuration
 # should be created by either modifying this file, or by creating "drop-ins" in
-# the system.conf.d/ subdirectory. The latter is generally recommended.
+# the journal-remote.conf.d/ subdirectory. The latter is generally recommended.
 # Defaults can be restored by simply deleting this file and all drop-ins.
 #
 # See journal-remote.conf(5) for details.
index a8f1f7e5115b4793605d291b34019ad6c9a246eb..d7e45364a6e8a19a4f578729b35ff942c3bad963 100644 (file)
@@ -9,7 +9,6 @@
 #include "sd-daemon.h"
 
 #include "alloc-util.h"
-#include "build.h"
 #include "conf-parser.h"
 #include "daemon-util.h"
 #include "def.h"
@@ -34,6 +33,7 @@
 #include "strv.h"
 #include "tmpfile-util.h"
 #include "util.h"
+#include "version.h"
 
 #define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-upload.pem"
 #define CERT_FILE     CERTIFICATE_ROOT "/certs/journal-upload.pem"
index 7d2bdc75018f2bf4da84827e0bbabd81e2e98652..29b623bdfa4d79321ea008f6f9cbf2045bdad115 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Entries in this file show the compile time defaults. Local configuration
 # should be created by either modifying this file, or by creating "drop-ins" in
-# the system.conf.d/ subdirectory. The latter is generally recommended.
+# the journal-upload.conf.d/ subdirectory. The latter is generally recommended.
 # Defaults can be restored by simply deleting this file and all drop-ins.
 #
 # See journal-upload.conf(5) for details.
index 1b423d5cba275bea35b6b452aa9a53c291d6e04c..ec22f14ccb1ab76387aa3e300cc4506db8c62ec3 100644 (file)
@@ -10,6 +10,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         if (size == 0)
                 return 0;
 
+        /* We don't want to fill the logs with assert warnings.
+         * Disable most logging if not running standalone */
+        if (!getenv("SYSTEMD_LOG_LEVEL"))
+                log_set_max_level(LOG_CRIT);
+
         dummy_server_init(&s, data, size);
         dev_kmsg_record(&s, s.buffer, size);
         server_done(&s);
index 6b06320d78285fd53119cd3fc2be9225a0e26be3..c8fb726d420f00b50f57ebe66c77d701f5b323a0 100644 (file)
@@ -1158,7 +1158,7 @@ static int add_matches(sd_journal *j, char **args) {
 
                         if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
                                 if (executable_is_script(p, &interpreter) > 0) {
-                                        _cleanup_free_ char *comm;
+                                        _cleanup_free_ char *comm = NULL;
 
                                         comm = strndup(basename(p), 15);
                                         if (!comm)
@@ -1537,7 +1537,7 @@ static int get_possible_units(
                 char **patterns,
                 Set **units) {
 
-        _cleanup_set_free_free_ Set *found;
+        _cleanup_set_free_free_ Set *found = NULL;
         const char *field;
         int r;
 
@@ -2150,8 +2150,11 @@ int main(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
-                                DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|
-                                (arg_action == ACTION_UPDATE_CATALOG ? DISSECT_IMAGE_FSCK : DISSECT_IMAGE_READ_ONLY),
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_VALIDATE_OS |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                (arg_action == ACTION_UPDATE_CATALOG ? DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS : DISSECT_IMAGE_READ_ONLY),
                                 &unlink_dir,
                                 &loop_device,
                                 &decrypted_image);
@@ -2179,7 +2182,7 @@ int main(int argc, char *argv[]) {
         case ACTION_LIST_CATALOG:
         case ACTION_DUMP_CATALOG:
         case ACTION_UPDATE_CATALOG: {
-                _cleanup_free_ char *database;
+                _cleanup_free_ char *database = NULL;
 
                 database = path_join(arg_root, CATALOG_DATABASE);
                 if (!database) {
@@ -2433,7 +2436,7 @@ int main(int argc, char *argv[]) {
                 goto finish;
 
         if (DEBUG_LOGGING) {
-                _cleanup_free_ char *filter;
+                _cleanup_free_ char *filter = NULL;
 
                 filter = journal_make_match_string(j);
                 if (!filter)
index e7255b0355b702821f7608038a379effb5217dd4..c96b84e61f841c8d7314d1a61b41a7d70e9a3692 100644 (file)
@@ -14,6 +14,7 @@
 #include "escape.h"
 #include "fd-util.h"
 #include "format-util.h"
+#include "fs-util.h"
 #include "io-util.h"
 #include "journald-kmsg.h"
 #include "journald-server.h"
@@ -376,8 +377,8 @@ int server_open_dev_kmsg(Server *s) {
 
         s->dev_kmsg_fd = open("/dev/kmsg", mode);
         if (s->dev_kmsg_fd < 0) {
-                log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
-                         "Failed to open /dev/kmsg, ignoring: %m");
+                log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
+                               errno, "Failed to open /dev/kmsg, ignoring: %m");
                 return 0;
         }
 
@@ -436,8 +437,8 @@ int server_open_kernel_seqnum(Server *s) {
                 return 0;
         }
 
-        r = posix_fallocate(fd, 0, sizeof(uint64_t));
-        if (r != 0) {
+        r = posix_fallocate_loop(fd, 0, sizeof(uint64_t));
+        if (r < 0) {
                 log_error_errno(r, "Failed to allocate sequential number file, ignoring: %m");
                 return 0;
         }
index 7bc26097f3a2a20b84b7e1a6bae2b02ffca3fe80..85723f5b30fcc0de9fbb2e4e073e3eaf55c3a871 100644 (file)
 
 #define STDOUT_STREAMS_MAX 4096
 
+/* During the "setup" protocol phase of the stream logic let's define a different maximum line length than
+ * during the actual operational phase. We want to allow users to specify very short line lengths after all,
+ * but the unit name we embed in the setup protocol might be longer than that. Hence, during the setup phase
+ * let's enforce a line length matching the maximum unit name length (255) */
+#define STDOUT_STREAM_SETUP_PROTOCOL_LINE_MAX (UNIT_NAME_MAX-1U)
+
 typedef enum StdoutStreamState {
         STDOUT_STREAM_IDENTIFIER,
         STDOUT_STREAM_UNIT_ID,
@@ -47,7 +53,7 @@ typedef enum StdoutStreamState {
         STDOUT_STREAM_FORWARD_TO_SYSLOG,
         STDOUT_STREAM_FORWARD_TO_KMSG,
         STDOUT_STREAM_FORWARD_TO_CONSOLE,
-        STDOUT_STREAM_RUNNING
+        STDOUT_STREAM_RUNNING,
 } StdoutStreamState;
 
 /* The different types of log record terminators: a real \n was read, a NUL character was read, the maximum line length
@@ -189,7 +195,7 @@ static int stdout_stream_save(StdoutStream *s) {
                 s->id_field + STRLEN("_STREAM_ID="));
 
         if (!isempty(s->identifier)) {
-                _cleanup_free_ char *escaped;
+                _cleanup_free_ char *escaped = NULL;
 
                 escaped = cescape(s->identifier);
                 if (!escaped) {
@@ -201,7 +207,7 @@ static int stdout_stream_save(StdoutStream *s) {
         }
 
         if (!isempty(s->unit_id)) {
-                _cleanup_free_ char *escaped;
+                _cleanup_free_ char *escaped = NULL;
 
                 escaped = cescape(s->unit_id);
                 if (!escaped) {
@@ -468,6 +474,18 @@ static int stdout_stream_found(
         return r;
 }
 
+static size_t stdout_stream_line_max(StdoutStream *s) {
+        assert(s);
+
+        /* During the "setup" phase of our protocol, let's ensure we use a line length where a full unit name
+         * can fit in */
+        if (s->state != STDOUT_STREAM_RUNNING)
+                return STDOUT_STREAM_SETUP_PROTOCOL_LINE_MAX;
+
+        /* After the protocol's "setup" phase is complete, let's use whatever the user configured */
+        return s->server->line_max;
+}
+
 static int stdout_stream_scan(
                 StdoutStream *s,
                 char *p,
@@ -475,19 +493,22 @@ static int stdout_stream_scan(
                 LineBreak force_flush,
                 size_t *ret_consumed) {
 
-        size_t consumed = 0;
+        size_t consumed = 0, line_max;
         int r;
 
         assert(s);
         assert(p);
 
+        line_max = stdout_stream_line_max(s);
+
         for (;;) {
                 LineBreak line_break;
                 size_t skip, found;
                 char *end1, *end2;
+                size_t tmp_remaining = MIN(remaining, line_max);
 
-                end1 = memchr(p, '\n', remaining);
-                end2 = memchr(p, 0, end1 ? (size_t) (end1 - p) : remaining);
+                end1 = memchr(p, '\n', tmp_remaining);
+                end2 = memchr(p, 0, end1 ? (size_t) (end1 - p) : tmp_remaining);
 
                 if (end2) {
                         /* We found a NUL terminator */
@@ -499,9 +520,9 @@ static int stdout_stream_scan(
                         found = end1 - p;
                         skip = found + 1;
                         line_break = LINE_BREAK_NEWLINE;
-                } else if (remaining >= s->server->line_max) {
+                } else if (remaining >= line_max) {
                         /* Force a line break after the maximum line length */
-                        found = skip = s->server->line_max;
+                        found = skip = line_max;
                         line_break = LINE_BREAK_LINE_MAX;
                 } else
                         break;
@@ -563,7 +584,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
 
         /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also,
          * always leave room for a terminating NUL we might need to add. */
-        limit = MIN(s->allocated - 1, s->server->line_max);
+        limit = MIN(s->allocated - 1, MAX(s->server->line_max, STDOUT_STREAM_SETUP_PROTOCOL_LINE_MAX));
         assert(s->length <= limit);
         iovec = IOVEC_MAKE(s->buffer + s->length, limit - s->length);
 
index 18d6b30773bad40962631dc8b50c727ff01382f6..5a60a9d39c59f4db643cbaf2c028d260e85c0455 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Entries in this file show the compile time defaults. Local configuration
 # should be created by either modifying this file, or by creating "drop-ins" in
-# the system.conf.d/ subdirectory. The latter is generally recommended.
+# the journald.conf.d/ subdirectory. The latter is generally recommended.
 # Defaults can be restored by simply deleting this file and all drop-ins.
 #
 # Use 'systemd-analyze cat-config systemd/journald.conf' to display the full config.
index e6c7e99e650e975b9151174619120a47ef2e6f46..75218d0deea87010eaaf1cf7809efec6a1e06e4c 100644 (file)
@@ -36,7 +36,11 @@ MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID
 
 BOOT_ROOT=${ENTRY_DIR_ABS%/$MACHINE_ID/$KERNEL_VERSION}
 BOOT_MNT=$(stat -c %m $BOOT_ROOT)
-ENTRY_DIR=${ENTRY_DIR_ABS#$BOOT_MNT}
+if [[ $BOOT_MNT == '/' ]]; then
+    ENTRY_DIR=$ENTRY_DIR_ABS
+else
+    ENTRY_DIR=${ENTRY_DIR_ABS#$BOOT_MNT}
+fi
 
 if [[ $COMMAND == remove ]]; then
     rm -f "$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION.conf"
index 40e6b1f26f7a3c7e4d38f352f23dc9f23647e804..e5be7c5a63b5dab09b6895feb5af6c0fabd64788 100644 (file)
@@ -12,6 +12,7 @@
 #include "sd-dhcp-client.h"
 
 #include "dhcp-protocol.h"
+#include "log-link.h"
 #include "socket-util.h"
 
 typedef struct sd_dhcp_option {
@@ -65,5 +66,13 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, ui
 #define DHCP_CLIENT_DONT_DESTROY(client) \
         _cleanup_(sd_dhcp_client_unrefp) _unused_ sd_dhcp_client *_dont_destroy_##client = sd_dhcp_client_ref(client)
 
-#define log_dhcp_client_errno(client, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "DHCP CLIENT (0x%x): " fmt, client->xid, ##__VA_ARGS__)
-#define log_dhcp_client(client, fmt, ...) log_dhcp_client_errno(client, 0, fmt, ##__VA_ARGS__)
+#define log_dhcp_client_errno(client, error, fmt, ...)          \
+        log_interface_prefix_full_errno(                        \
+                "DHCPv4 client: ",                              \
+                sd_dhcp_client_get_ifname(client),              \
+                error, fmt, ##__VA_ARGS__)
+#define log_dhcp_client(client, fmt, ...)                       \
+        log_interface_prefix_full_errno_zerook(                 \
+                "DHCPv4 client: ",                              \
+                sd_dhcp_client_get_ifname(client),              \
+                0, fmt, ##__VA_ARGS__)
index 656482bf83810a82f8d34f01639f7e5f39d45714..85059102b1c64955184f947d4dc5d066a68ff142 100644 (file)
@@ -186,15 +186,18 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int
                         return r;
         }
 
-        if (address == INADDR_ANY) {
-                r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
-                if (r < 0)
-                        return r;
-
+        if (port == DHCP_PORT_SERVER) {
                 r = setsockopt_int(s, SOL_SOCKET, SO_BROADCAST, true);
                 if (r < 0)
                         return r;
-
+                if (address == INADDR_ANY) {
+                        /* IP_PKTINFO filter should not be applied when packets are
+                           allowed to enter/leave through the interface other than
+                           DHCP server sits on(BindToInterface option). */
+                        r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
+                        if (r < 0)
+                                return r;
+                }
         } else {
                 r = setsockopt_int(s, IPPROTO_IP, IP_FREEBIND, true);
                 if (r < 0)
index faa075cbd71e20dd7c4ff128535b95e2ef05876d..8899e8a55239db3db2c32335f6b4152a70e1a4fd 100644 (file)
@@ -17,6 +17,7 @@
 static int option_append(uint8_t options[], size_t size, size_t *offset,
                          uint8_t code, size_t optlen, const void *optval) {
         assert(options);
+        assert(size > 0);
         assert(offset);
 
         if (code != SD_DHCP_OPTION_END)
@@ -165,7 +166,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
                         } else if (r == -ENOBUFS && use_sname) {
                                 /* did not fit, but we have more buffers to try
                                    close the file array and move the offset to its end */
-                                r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
+                                r = option_append(message->file, sizeof(message->file), &file_offset, SD_DHCP_OPTION_END, 0, NULL);
                                 if (r < 0)
                                         return r;
 
index b5293c3ed66996913223a5c7738c6d270e78f541..3628223ae9ac47cd78d76a444fbec7ab4674b788 100644 (file)
@@ -10,7 +10,7 @@
 
 #include "dhcp-internal.h"
 #include "ordered-set.h"
-#include "log.h"
+#include "log-link.h"
 #include "time-util.h"
 
 typedef enum DHCPRawOption {
@@ -39,15 +39,20 @@ typedef struct DHCPLease {
 } DHCPLease;
 
 struct sd_dhcp_server {
+        struct in_addr relay_target;
         unsigned n_ref;
 
         sd_event *event;
         int event_priority;
         sd_event_source *receive_message;
+        sd_event_source *receive_broadcast;
         int fd;
         int fd_raw;
+        int fd_broadcast;
 
         int ifindex;
+        char *ifname;
+        bool bind_to_interface;
         be32_t address;
         be32_t netmask;
         be32_t subnet;
@@ -85,9 +90,6 @@ typedef struct DHCPRequest {
         uint32_t lifetime;
 } DHCPRequest;
 
-#define log_dhcp_server(client, fmt, ...) log_internal(LOG_DEBUG, 0, PROJECT_FILE, __LINE__, __func__, "DHCP SERVER: " fmt, ##__VA_ARGS__)
-#define log_dhcp_server_errno(client, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "DHCP SERVER: " fmt, ##__VA_ARGS__)
-
 int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
                                size_t length);
 int dhcp_server_send_packet(sd_dhcp_server *server,
@@ -96,3 +98,14 @@ int dhcp_server_send_packet(sd_dhcp_server *server,
 
 void client_id_hash_func(const DHCPClientId *p, struct siphash *state);
 int client_id_compare_func(const DHCPClientId *a, const DHCPClientId *b);
+
+#define log_dhcp_server_errno(server, error, fmt, ...)          \
+        log_interface_prefix_full_errno(                        \
+                "DHCPv4 server: ",                              \
+                sd_dhcp_server_get_ifname(server),              \
+                error, fmt, ##__VA_ARGS__)
+#define log_dhcp_server(server, fmt, ...)                       \
+        log_interface_prefix_full_errno_zerook(                 \
+                "DHCPv4 server: ",                              \
+                sd_dhcp_server_get_ifname(server),              \
+                0, fmt, ##__VA_ARGS__)
index 681c462315587cfea3cbc0b1ff32db791983716f..1e5a6b0e3779be0cf250bfc8f00c0c80e6c19d85 100644 (file)
@@ -9,9 +9,11 @@
 #include <netinet/in.h>
 
 #include "sd-event.h"
+#include "sd-dhcp6-client.h"
 
-#include "list.h"
 #include "hashmap.h"
+#include "list.h"
+#include "log-link.h"
 #include "macro.h"
 #include "sparse-endian.h"
 
@@ -78,7 +80,7 @@ struct ia_ta {
         be32_t id;
 } _packed_;
 
-struct DHCP6IA {
+typedef struct DHCP6IA {
         uint16_t type;
         union {
                 struct ia_na ia_na;
@@ -87,12 +89,7 @@ struct DHCP6IA {
         };
 
         LIST_HEAD(DHCP6Address, addresses);
-};
-
-typedef struct DHCP6IA DHCP6IA;
-
-#define log_dhcp6_client_errno(p, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__)
-#define log_dhcp6_client(p, fmt, ...) log_dhcp6_client_errno(p, 0, fmt, ##__VA_ARGS__)
+} DHCP6IA;
 
 int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
                         size_t optlen, const void *optval);
@@ -105,7 +102,7 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHash
 int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
                        size_t *optlen, uint8_t **optvalue);
 int dhcp6_option_parse_status(DHCP6Option *option, size_t len);
-int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code);
+int dhcp6_option_parse_ia(sd_dhcp6_client *client, DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code);
 int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
                                 struct in6_addr **addrs, size_t count,
                                 size_t *allocated);
@@ -121,3 +118,14 @@ const char *dhcp6_message_type_to_string(int s) _const_;
 int dhcp6_message_type_from_string(const char *s) _pure_;
 const char *dhcp6_message_status_to_string(int s) _const_;
 int dhcp6_message_status_from_string(const char *s) _pure_;
+
+#define log_dhcp6_client_errno(client, error, fmt, ...)         \
+        log_interface_prefix_full_errno(                        \
+                "DHCPv6 client: ",                              \
+                sd_dhcp6_client_get_ifname(client),             \
+                error, fmt, ##__VA_ARGS__)
+#define log_dhcp6_client(client, fmt, ...)                      \
+        log_interface_prefix_full_errno_zerook(                 \
+                "DHCPv6 client: ",                              \
+                sd_dhcp6_client_get_ifname(client),             \
+                0, fmt, ##__VA_ARGS__)
index 91162d636bf75ca7ddd22a1dfd057a2f535f0eac..6aca898d336756fc69784830bd499c719be7e802 100644 (file)
@@ -425,7 +425,7 @@ int dhcp6_option_parse_status(DHCP6Option *option, size_t len) {
         return be16toh(statusopt->status);
 }
 
-static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia, uint32_t *ret_lifetime_valid) {
+static int dhcp6_option_parse_address(sd_dhcp6_client *client, DHCP6Option *option, DHCP6IA *ia, uint32_t *ret_lifetime_valid) {
         DHCP6AddressOption *addr_option = (DHCP6AddressOption *)option;
         DHCP6Address *addr;
         uint32_t lt_valid, lt_pref;
@@ -437,23 +437,20 @@ static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia, uint32_t
         lt_valid = be32toh(addr_option->iaaddr.lifetime_valid);
         lt_pref = be32toh(addr_option->iaaddr.lifetime_preferred);
 
-        if (lt_valid == 0 || lt_pref > lt_valid) {
-                log_dhcp6_client(client,
-                                 "Valid lifetime of an IA address is zero or "
-                                 "preferred lifetime %"PRIu32" > valid lifetime %"PRIu32,
-                                 lt_pref, lt_valid);
-                return -EINVAL;
-        }
+        if (lt_valid == 0 || lt_pref > lt_valid)
+                return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+                                              "Valid lifetime of an IA address is zero or "
+                                              "preferred lifetime %"PRIu32" > valid lifetime %"PRIu32,
+                                              lt_pref, lt_valid);
 
         if (be16toh(option->len) + offsetof(DHCP6Option, data) > sizeof(*addr_option)) {
                 r = dhcp6_option_parse_status((DHCP6Option *)addr_option->options, be16toh(option->len) + offsetof(DHCP6Option, data) - sizeof(*addr_option));
                 if (r < 0)
                         return r;
-                if (r > 0) {
-                        log_dhcp6_client(client, "Non-zero status code '%s' for address is received",
-                                         dhcp6_message_status_to_string(r));
-                        return -EINVAL;
-                }
+                if (r > 0)
+                        return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+                                                      "Non-zero status code '%s' for address is received",
+                                                      dhcp6_message_status_to_string(r));
         }
 
         addr = new0(DHCP6Address, 1);
@@ -470,7 +467,7 @@ static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia, uint32_t
         return 0;
 }
 
-static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia, uint32_t *ret_lifetime_valid) {
+static int dhcp6_option_parse_pdprefix(sd_dhcp6_client *client, DHCP6Option *option, DHCP6IA *ia, uint32_t *ret_lifetime_valid) {
         DHCP6PDPrefixOption *pdprefix_option = (DHCP6PDPrefixOption *)option;
         DHCP6Address *prefix;
         uint32_t lt_valid, lt_pref;
@@ -482,23 +479,20 @@ static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia, uint32_
         lt_valid = be32toh(pdprefix_option->iapdprefix.lifetime_valid);
         lt_pref = be32toh(pdprefix_option->iapdprefix.lifetime_preferred);
 
-        if (lt_valid == 0 || lt_pref > lt_valid) {
-                log_dhcp6_client(client,
-                                 "Valid lifetieme of a PD prefix is zero or "
-                                 "preferred lifetime %"PRIu32" > valid lifetime %"PRIu32,
-                                 lt_pref, lt_valid);
-                return -EINVAL;
-        }
+        if (lt_valid == 0 || lt_pref > lt_valid)
+                return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+                                              "Valid lifetieme of a PD prefix is zero or "
+                                              "preferred lifetime %"PRIu32" > valid lifetime %"PRIu32,
+                                              lt_pref, lt_valid);
 
         if (be16toh(option->len) + offsetof(DHCP6Option, data) > sizeof(*pdprefix_option)) {
                 r = dhcp6_option_parse_status((DHCP6Option *)pdprefix_option->options, be16toh(option->len) + offsetof(DHCP6Option, data) - sizeof(*pdprefix_option));
                 if (r < 0)
                         return r;
-                if (r > 0) {
-                        log_dhcp6_client(client, "Non-zero status code '%s' for PD prefix is received",
-                                         dhcp6_message_status_to_string(r));
-                        return -EINVAL;
-                }
+                if (r > 0)
+                        return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+                                                      "Non-zero status code '%s' for PD prefix is received",
+                                                      dhcp6_message_status_to_string(r));
         }
 
         prefix = new0(DHCP6Address, 1);
@@ -515,7 +509,7 @@ static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia, uint32_
         return 0;
 }
 
-int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code) {
+int dhcp6_option_parse_ia(sd_dhcp6_client *client, DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code) {
         uint32_t lt_t1, lt_t2, lt_valid = 0, lt_min = UINT32_MAX;
         uint16_t iatype, optlen;
         size_t iaaddr_offset;
@@ -541,10 +535,10 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat
                 lt_t1 = be32toh(ia->ia_na.lifetime_t1);
                 lt_t2 = be32toh(ia->ia_na.lifetime_t2);
 
-                if (lt_t1 && lt_t2 && lt_t1 > lt_t2) {
-                        log_dhcp6_client(client, "IA NA T1 %"PRIu32"sec > T2 %"PRIu32"sec", lt_t1, lt_t2);
-                        return -EINVAL;
-                }
+                if (lt_t1 > lt_t2)
+                        return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+                                                      "IA NA T1 %"PRIu32"sec > T2 %"PRIu32"sec",
+                                                      lt_t1, lt_t2);
 
                 break;
 
@@ -559,10 +553,10 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat
                 lt_t1 = be32toh(ia->ia_pd.lifetime_t1);
                 lt_t2 = be32toh(ia->ia_pd.lifetime_t2);
 
-                if (lt_t1 && lt_t2 && lt_t1 > lt_t2) {
-                        log_dhcp6_client(client, "IA PD T1 %"PRIu32"sec > T2 %"PRIu32"sec", lt_t1, lt_t2);
-                        return -EINVAL;
-                }
+                if (lt_t1 > lt_t2)
+                        return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+                                                      "IA PD T1 %"PRIu32"sec > T2 %"PRIu32"sec",
+                                                      lt_t1, lt_t2);
 
                 break;
 
@@ -594,12 +588,11 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat
                 switch (opt) {
                 case SD_DHCP6_OPTION_IAADDR:
 
-                        if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_NA, SD_DHCP6_OPTION_IA_TA)) {
-                                log_dhcp6_client(client, "IA Address option not in IA NA or TA option");
-                                return -EINVAL;
-                        }
+                        if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_NA, SD_DHCP6_OPTION_IA_TA))
+                                return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+                                                              "IA Address option not in IA NA or TA option");
 
-                        r = dhcp6_option_parse_address(option, ia, &lt_valid);
+                        r = dhcp6_option_parse_address(client, option, ia, &lt_valid);
                         if (r < 0 && r != -EINVAL)
                                 return r;
                         if (r >= 0 && lt_valid < lt_min)
@@ -609,12 +602,11 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat
 
                 case SD_DHCP6_OPTION_IA_PD_PREFIX:
 
-                        if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_PD)) {
-                                log_dhcp6_client(client, "IA PD Prefix option not in IA PD option");
-                                return -EINVAL;
-                        }
+                        if (ia->type != SD_DHCP6_OPTION_IA_PD)
+                                return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+                                                              "IA PD Prefix option not in IA PD option");
 
-                        r = dhcp6_option_parse_pdprefix(option, ia, &lt_valid);
+                        r = dhcp6_option_parse_pdprefix(client, option, ia, &lt_valid);
                         if (r < 0 && r != -EINVAL)
                                 return r;
                         if (r >= 0 && lt_valid < lt_min)
@@ -650,7 +642,7 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat
 
         switch(iatype) {
         case SD_DHCP6_OPTION_IA_NA:
-                if (!ia->ia_na.lifetime_t1 && !ia->ia_na.lifetime_t2 && lt_min != UINT32_MAX) {
+                if (ia->ia_na.lifetime_t1 == 0 && ia->ia_na.lifetime_t2 == 0 && lt_min != UINT32_MAX) {
                         lt_t1 = lt_min / 2;
                         lt_t2 = lt_min / 10 * 8;
                         ia->ia_na.lifetime_t1 = htobe32(lt_t1);
@@ -663,7 +655,7 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat
                 break;
 
         case SD_DHCP6_OPTION_IA_PD:
-                if (!ia->ia_pd.lifetime_t1 && !ia->ia_pd.lifetime_t2 && lt_min != UINT32_MAX) {
+                if (ia->ia_pd.lifetime_t1 == 0 && ia->ia_pd.lifetime_t2 == 0 && lt_min != UINT32_MAX) {
                         lt_t1 = lt_min / 2;
                         lt_t2 = lt_min / 10 * 8;
                         ia->ia_pd.lifetime_t1 = htobe32(lt_t1);
index acb8d9b98ca0d5eeabced8f0f233b765b5edf4d5..7ebe01286da57a97e189e1225805c0ee4bfbbe33 100644 (file)
@@ -23,7 +23,7 @@ int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
 }
 
 static void fuzz_client(const uint8_t *data, size_t size, bool is_information_request_enabled) {
-        _cleanup_(sd_event_unrefp) sd_event *e;
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
         _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
         struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
 
index daedbb088fbb767eb6567b9fd4a8e6a880c7f8c4..cf0578c5c2958a5b45a0450554c6c8562c2c3254 100644 (file)
@@ -5,13 +5,14 @@
 #include "sd-lldp.h"
 
 #include "hashmap.h"
-#include "log.h"
+#include "log-link.h"
 #include "prioq.h"
 
 struct sd_lldp {
         unsigned n_ref;
 
         int ifindex;
+        char *ifname;
         int fd;
 
         sd_event *event;
@@ -32,8 +33,16 @@ struct sd_lldp {
         struct ether_addr filter_address;
 };
 
-#define log_lldp_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__)
-#define log_lldp(fmt, ...) log_lldp_errno(0, fmt, ##__VA_ARGS__)
-
 const char* lldp_event_to_string(sd_lldp_event_t e) _const_;
 sd_lldp_event_t lldp_event_from_string(const char *s) _pure_;
+
+#define log_lldp_errno(lldp, error, fmt, ...)           \
+        log_interface_prefix_full_errno(                \
+                "LLDP: ",                               \
+                sd_lldp_get_ifname(lldp),               \
+                error, fmt, ##__VA_ARGS__)
+#define log_lldp(lldp, fmt, ...)                        \
+        log_interface_prefix_full_errno_zerook(         \
+                "LLDP: ",                               \
+                sd_lldp_get_ifname(lldp),               \
+                0, fmt, ##__VA_ARGS__)
index 546ae1c980fa167f4f35d4d4f15b6bb1f31cfff8..3bd775158efdbb6c3ea8858f5f9241f415ea0b9c 100644 (file)
@@ -112,7 +112,7 @@ sd_lldp_neighbor *lldp_neighbor_new(size_t raw_size) {
         return n;
 }
 
-static int parse_string(char **s, const void *q, size_t n) {
+static int parse_string(sd_lldp *lldp, char **s, const void *q, size_t n) {
         const char *p = q;
         char *k;
 
@@ -120,7 +120,7 @@ static int parse_string(char **s, const void *q, size_t n) {
         assert(p || n == 0);
 
         if (*s) {
-                log_lldp("Found duplicate string, ignoring field.");
+                log_lldp(lldp, "Found duplicate string, ignoring field.");
                 return 0;
         }
 
@@ -133,14 +133,14 @@ static int parse_string(char **s, const void *q, size_t n) {
 
         /* Look for inner NULs */
         if (memchr(p, 0, n)) {
-                log_lldp("Found inner NUL in string, ignoring field.");
+                log_lldp(lldp, "Found inner NUL in string, ignoring field.");
                 return 0;
         }
 
         /* Let's escape weird chars, for security reasons */
         k = cescape_length(p, n);
         if (!k)
-                return -ENOMEM;
+                return log_oom_debug();
 
         free(*s);
         *s = k;
@@ -156,27 +156,24 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
 
         assert(n);
 
-        if (n->raw_size < sizeof(struct ether_header)) {
-                log_lldp("Received truncated packet, ignoring.");
-                return -EBADMSG;
-        }
+        if (n->raw_size < sizeof(struct ether_header))
+                return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                      "Received truncated packet, ignoring.");
 
         memcpy(&h, LLDP_NEIGHBOR_RAW(n), sizeof(h));
 
-        if (h.ether_type != htobe16(ETHERTYPE_LLDP)) {
-                log_lldp("Received packet with wrong type, ignoring.");
-                return -EBADMSG;
-        }
+        if (h.ether_type != htobe16(ETHERTYPE_LLDP))
+                return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                      "Received packet with wrong type, ignoring.");
 
         if (h.ether_dhost[0] != 0x01 ||
             h.ether_dhost[1] != 0x80 ||
             h.ether_dhost[2] != 0xc2 ||
             h.ether_dhost[3] != 0x00 ||
             h.ether_dhost[4] != 0x00 ||
-            !IN_SET(h.ether_dhost[5], 0x00, 0x03, 0x0e)) {
-                log_lldp("Received packet with wrong destination address, ignoring.");
-                return -EBADMSG;
-        }
+            !IN_SET(h.ether_dhost[5], 0x00, 0x03, 0x0e))
+                return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                      "Received packet with wrong destination address, ignoring.");
 
         memcpy(&n->source_address, h.ether_shost, sizeof(struct ether_addr));
         memcpy(&n->destination_address, h.ether_dhost, sizeof(struct ether_addr));
@@ -188,27 +185,24 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
                 uint8_t type;
                 uint16_t length;
 
-                if (left < 2) {
-                        log_lldp("TLV lacks header, ignoring.");
-                        return -EBADMSG;
-                }
+                if (left < 2)
+                        return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                              "TLV lacks header, ignoring.");
 
                 type = p[0] >> 1;
                 length = p[1] + (((uint16_t) (p[0] & 1)) << 8);
                 p += 2, left -= 2;
 
-                if (left < length) {
-                        log_lldp("TLV truncated, ignoring datagram.");
-                        return -EBADMSG;
-                }
+                if (left < length)
+                        return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                              "TLV truncated, ignoring datagram.");
 
                 switch (type) {
 
                 case SD_LLDP_TYPE_END:
-                        if (length != 0) {
-                                log_lldp("End marker TLV not zero-sized, ignoring datagram.");
-                                return -EBADMSG;
-                        }
+                        if (length != 0)
+                                return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                                      "End marker TLV not zero-sized, ignoring datagram.");
 
                         /* Note that after processing the SD_LLDP_TYPE_END left could still be > 0
                          * as the message may contain padding (see IEEE 802.1AB-2016, sec. 8.5.12) */
@@ -216,98 +210,93 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
                         goto end_marker;
 
                 case SD_LLDP_TYPE_CHASSIS_ID:
-                        if (length < 2 || length > 256) { /* includes the chassis subtype, hence one extra byte */
-                                log_lldp("Chassis ID field size out of range, ignoring datagram.");
-                                return -EBADMSG;
-                        }
-                        if (n->id.chassis_id) {
-                                log_lldp("Duplicate chassis ID field, ignoring datagram.");
-                                return -EBADMSG;
-                        }
+                        if (length < 2 || length > 256)
+                                /* includes the chassis subtype, hence one extra byte */
+                                return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                                      "Chassis ID field size out of range, ignoring datagram.");
+
+                        if (n->id.chassis_id)
+                                return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                                      "Duplicate chassis ID field, ignoring datagram.");
 
                         n->id.chassis_id = memdup(p, length);
                         if (!n->id.chassis_id)
-                                return -ENOMEM;
+                                return log_oom_debug();
 
                         n->id.chassis_id_size = length;
                         break;
 
                 case SD_LLDP_TYPE_PORT_ID:
-                        if (length < 2 || length > 256) { /* includes the port subtype, hence one extra byte */
-                                log_lldp("Port ID field size out of range, ignoring datagram.");
-                                return -EBADMSG;
-                        }
-                        if (n->id.port_id) {
-                                log_lldp("Duplicate port ID field, ignoring datagram.");
-                                return -EBADMSG;
-                        }
+                        if (length < 2 || length > 256)
+                                /* includes the port subtype, hence one extra byte */
+                                return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                                      "Port ID field size out of range, ignoring datagram.");
+
+                        if (n->id.port_id)
+                                return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                                      "Duplicate port ID field, ignoring datagram.");
 
                         n->id.port_id = memdup(p, length);
                         if (!n->id.port_id)
-                                return -ENOMEM;
+                                return log_oom_debug();
 
                         n->id.port_id_size = length;
                         break;
 
                 case SD_LLDP_TYPE_TTL:
-                        if (length != 2) {
-                                log_lldp("TTL field has wrong size, ignoring datagram.");
-                                return -EBADMSG;
-                        }
+                        if (length != 2)
+                                return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                                      "TTL field has wrong size, ignoring datagram.");
 
-                        if (n->has_ttl) {
-                                log_lldp("Duplicate TTL field, ignoring datagram.");
-                                return -EBADMSG;
-                        }
+                        if (n->has_ttl)
+                                return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                                      "Duplicate TTL field, ignoring datagram.");
 
                         n->ttl = unaligned_read_be16(p);
                         n->has_ttl = true;
                         break;
 
                 case SD_LLDP_TYPE_PORT_DESCRIPTION:
-                        r = parse_string(&n->port_description, p, length);
+                        r = parse_string(n->lldp, &n->port_description, p, length);
                         if (r < 0)
                                 return r;
                         break;
 
                 case SD_LLDP_TYPE_SYSTEM_NAME:
-                        r = parse_string(&n->system_name, p, length);
+                        r = parse_string(n->lldp, &n->system_name, p, length);
                         if (r < 0)
                                 return r;
                         break;
 
                 case SD_LLDP_TYPE_SYSTEM_DESCRIPTION:
-                        r = parse_string(&n->system_description, p, length);
+                        r = parse_string(n->lldp, &n->system_description, p, length);
                         if (r < 0)
                                 return r;
                         break;
 
                 case SD_LLDP_TYPE_SYSTEM_CAPABILITIES:
                         if (length != 4)
-                                log_lldp("System capabilities field has wrong size, ignoring.");
-                        else {
-                                n->system_capabilities = unaligned_read_be16(p);
-                                n->enabled_capabilities = unaligned_read_be16(p + 2);
-                                n->has_capabilities = true;
-                        }
+                                return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                                      "System capabilities field has wrong size.");
 
+                        n->system_capabilities = unaligned_read_be16(p);
+                        n->enabled_capabilities = unaligned_read_be16(p + 2);
+                        n->has_capabilities = true;
                         break;
 
-                case SD_LLDP_TYPE_PRIVATE: {
+                case SD_LLDP_TYPE_PRIVATE:
                         if (length < 4)
-                                log_lldp("Found private TLV that is too short, ignoring.");
-                        else {
-                                /* RFC 8520: MUD URL */
-                                if (memcmp(p, SD_LLDP_OUI_MUD, sizeof(SD_LLDP_OUI_MUD)) == 0 &&
-                                    p[sizeof(SD_LLDP_OUI_MUD)] == SD_LLDP_OUI_SUBTYPE_MUD_USAGE_DESCRIPTION) {
-                                        r = parse_string(&n->mud_url, p + sizeof(SD_LLDP_OUI_MUD) + 1,
-                                                         length - 1 - sizeof(SD_LLDP_OUI_MUD));
-                                        if (r < 0)
-                                                return r;
-                                }
+                                return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                                      "Found private TLV that is too short, ignoring.");
+
+                        /* RFC 8520: MUD URL */
+                        if (memcmp(p, SD_LLDP_OUI_MUD, sizeof(SD_LLDP_OUI_MUD)) == 0 &&
+                            p[sizeof(SD_LLDP_OUI_MUD)] == SD_LLDP_OUI_SUBTYPE_MUD_USAGE_DESCRIPTION) {
+                                r = parse_string(n->lldp, &n->mud_url, p + sizeof(SD_LLDP_OUI_MUD) + 1,
+                                                 length - 1 - sizeof(SD_LLDP_OUI_MUD));
+                                if (r < 0)
+                                        return r;
                         }
-                }
-
                         break;
                 }
 
@@ -315,11 +304,9 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
         }
 
 end_marker:
-        if (!n->id.chassis_id || !n->id.port_id || !n->has_ttl) {
-                log_lldp("One or more mandatory TLV missing in datagram. Ignoring.");
-                return -EBADMSG;
-
-        }
+        if (!n->id.chassis_id || !n->id.port_id || !n->has_ttl)
+                return log_lldp_errno(n->lldp, SYNTHETIC_ERRNO(EBADMSG),
+                                      "One or more mandatory TLV missing in datagram. Ignoring.");
 
         n->rindex = sizeof(struct ether_header);
 
index 6bc4a3f54b56a632735fbf97b038455e9f9c9a1b..ca3393eff367425d4908f56cb35b92c7a9c7f653 100644 (file)
@@ -16,6 +16,8 @@ sources = files('''
         sd-ipv4acd.c
         arp-util.h
         arp-util.c
+        network-common.c
+        network-common.h
         network-internal.c
         network-internal.h
         sd-ndisc.c
index 70b254867bbf81bd5ec9c63989d4f55688430e57..d43b5753526cf3f6957e0766365dcb8bccc1fa78 100644 (file)
@@ -5,11 +5,11 @@
   Copyright © 2014 Intel Corporation. All rights reserved.
 ***/
 
-#include "log.h"
-#include "time-util.h"
-
 #include "sd-ndisc.h"
 
+#include "log-link.h"
+#include "time-util.h"
+
 #define NDISC_ROUTER_SOLICITATION_INTERVAL (4U * USEC_PER_SEC)
 #define NDISC_MAX_ROUTER_SOLICITATION_INTERVAL (3600U * USEC_PER_SEC)
 #define NDISC_MAX_ROUTER_SOLICITATIONS 3U
@@ -18,6 +18,7 @@ struct sd_ndisc {
         unsigned n_ref;
 
         int ifindex;
+        char *ifname;
         int fd;
 
         sd_event *event;
@@ -37,8 +38,16 @@ struct sd_ndisc {
         void *userdata;
 };
 
-#define log_ndisc_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "NDISC: " fmt, ##__VA_ARGS__)
-#define log_ndisc(fmt, ...) log_ndisc_errno(0, fmt, ##__VA_ARGS__)
-
 const char* ndisc_event_to_string(sd_ndisc_event_t e) _const_;
 sd_ndisc_event_t ndisc_event_from_string(const char *s) _pure_;
+
+#define log_ndisc_errno(ndisc, error, fmt, ...)         \
+        log_interface_prefix_full_errno(                \
+                "NDISC: ",                              \
+                sd_ndisc_get_ifname(ndisc),             \
+                error, fmt, ##__VA_ARGS__)
+#define log_ndisc(ndisc, fmt, ...)                      \
+        log_interface_prefix_full_errno_zerook(         \
+                "NDISC: ",                              \
+                sd_ndisc_get_ifname(ndisc),             \
+                0, fmt, ##__VA_ARGS__)
index c88293a9239cf5b3d05b8cf3973f2e5c70e94c4b..46f30332bbf8ffbeb82b2e2d62760bfb39047e6e 100644 (file)
@@ -43,7 +43,7 @@ _public_ int sd_ndisc_router_from_raw(sd_ndisc_router **ret, const void *raw, si
                 return -ENOMEM;
 
         memcpy(NDISC_ROUTER_RAW(rt), raw, raw_size);
-        r = ndisc_router_parse(rt);
+        r = ndisc_router_parse(NULL, rt);
         if (r < 0)
                 return r;
 
@@ -87,7 +87,7 @@ _public_ int sd_ndisc_router_get_raw(sd_ndisc_router *rt, const void **ret, size
         return 0;
 }
 
-int ndisc_router_parse(sd_ndisc_router *rt) {
+int ndisc_router_parse(sd_ndisc *nd, sd_ndisc_router *rt) {
         struct nd_router_advert *a;
         const uint8_t *p;
         bool has_mtu = false, has_flag_extension = false;
@@ -95,23 +95,20 @@ int ndisc_router_parse(sd_ndisc_router *rt) {
 
         assert(rt);
 
-        if (rt->raw_size < sizeof(struct nd_router_advert)) {
-                log_ndisc("Too small to be a router advertisement, ignoring.");
-                return -EBADMSG;
-        }
+        if (rt->raw_size < sizeof(struct nd_router_advert))
+                return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+                                       "Too small to be a router advertisement, ignoring.");
 
         /* Router advertisement packets are neatly aligned to 64bit boundaries, hence we can access them directly */
         a = NDISC_ROUTER_RAW(rt);
 
-        if (a->nd_ra_type != ND_ROUTER_ADVERT) {
-                log_ndisc("Received ND packet that is not a router advertisement, ignoring.");
-                return -EBADMSG;
-        }
+        if (a->nd_ra_type != ND_ROUTER_ADVERT)
+                return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+                                       "Received ND packet that is not a router advertisement, ignoring.");
 
-        if (a->nd_ra_code != 0) {
-                log_ndisc("Received ND packet with wrong RA code, ignoring.");
-                return -EBADMSG;
-        }
+        if (a->nd_ra_code != 0)
+                return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+                                       "Received ND packet with wrong RA code, ignoring.");
 
         rt->hop_limit = a->nd_ra_curhoplimit;
         rt->flags = a->nd_ra_flags_reserved; /* the first 8bit */
@@ -131,36 +128,31 @@ int ndisc_router_parse(sd_ndisc_router *rt) {
                 if (left == 0)
                         break;
 
-                if (left < 2) {
-                        log_ndisc("Option lacks header, ignoring datagram.");
-                        return -EBADMSG;
-                }
+                if (left < 2)
+                        return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+                                               "Option lacks header, ignoring datagram.");
 
                 type = p[0];
                 length = p[1] * 8;
 
-                if (length == 0) {
-                        log_ndisc("Zero-length option, ignoring datagram.");
-                        return -EBADMSG;
-                }
-                if (left < length) {
-                        log_ndisc("Option truncated, ignoring datagram.");
-                        return -EBADMSG;
-                }
+                if (length == 0)
+                        return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+                                               "Zero-length option, ignoring datagram.");
+                if (left < length)
+                        return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+                                               "Option truncated, ignoring datagram.");
 
                 switch (type) {
 
                 case SD_NDISC_OPTION_PREFIX_INFORMATION:
 
-                        if (length != 4*8) {
-                                log_ndisc("Prefix option of invalid size, ignoring datagram.");
-                                return -EBADMSG;
-                        }
+                        if (length != 4*8)
+                                return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+                                                       "Prefix option of invalid size, ignoring datagram.");
 
-                        if (p[2] > 128) {
-                                log_ndisc("Bad prefix length, ignoring datagram.");
-                                return -EBADMSG;
-                        }
+                        if (p[2] > 128)
+                                return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+                                                       "Bad prefix length, ignoring datagram.");
 
                         break;
 
@@ -168,14 +160,13 @@ int ndisc_router_parse(sd_ndisc_router *rt) {
                         uint32_t m;
 
                         if (has_mtu) {
-                                log_ndisc("MTU option specified twice, ignoring.");
+                                log_ndisc(nd, "MTU option specified twice, ignoring.");
                                 break;
                         }
 
-                        if (length != 8) {
-                                log_ndisc("MTU option of invalid size, ignoring datagram.");
-                                return -EBADMSG;
-                        }
+                        if (length != 8)
+                                return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+                                                       "MTU option of invalid size, ignoring datagram.");
 
                         m = be32toh(*(uint32_t*) (p + 4));
                         if (m >= IPV6_MIN_MTU) /* ignore invalidly small MTUs */
@@ -186,37 +177,32 @@ int ndisc_router_parse(sd_ndisc_router *rt) {
                 }
 
                 case SD_NDISC_OPTION_ROUTE_INFORMATION:
-                        if (length < 1*8 || length > 3*8) {
-                                log_ndisc("Route information option of invalid size, ignoring datagram.");
-                                return -EBADMSG;
-                        }
+                        if (length < 1*8 || length > 3*8)
+                                return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+                                                       "Route information option of invalid size, ignoring datagram.");
 
-                        if (p[2] > 128) {
-                                log_ndisc("Bad route prefix length, ignoring datagram.");
-                                return -EBADMSG;
-                        }
+                        if (p[2] > 128)
+                                return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+                                                       "Bad route prefix length, ignoring datagram.");
 
                         break;
 
                 case SD_NDISC_OPTION_RDNSS:
-                        if (length < 3*8 || (length % (2*8)) != 1*8) {
-                                log_ndisc("RDNSS option has invalid size.");
-                                return -EBADMSG;
-                        }
+                        if (length < 3*8 || (length % (2*8)) != 1*8)
+                                return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG), "RDNSS option has invalid size.");
 
                         break;
 
                 case SD_NDISC_OPTION_FLAGS_EXTENSION:
 
                         if (has_flag_extension) {
-                                log_ndisc("Flags extension option specified twice, ignoring.");
+                                log_ndisc(nd, "Flags extension option specified twice, ignoring.");
                                 break;
                         }
 
-                        if (length < 1*8) {
-                                log_ndisc("Flags extension option has invalid size.");
-                                return -EBADMSG;
-                        }
+                        if (length < 1*8)
+                                return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+                                                       "Flags extension option has invalid size.");
 
                         /* Add in the additional flags bits */
                         rt->flags |=
@@ -231,10 +217,9 @@ int ndisc_router_parse(sd_ndisc_router *rt) {
                         break;
 
                 case SD_NDISC_OPTION_DNSSL:
-                        if (length < 2*8) {
-                                log_ndisc("DNSSL option has invalid size.");
-                                return -EBADMSG;
-                        }
+                        if (length < 2*8)
+                                return log_ndisc_errno(nd, SYNTHETIC_ERRNO(EBADMSG),
+                                                       "DNSSL option has invalid size.");
 
                         break;
                 }
@@ -437,7 +422,7 @@ _public_ int sd_ndisc_router_prefix_get_flags(sd_ndisc_router *rt, uint8_t *ret)
         flags = pi->nd_opt_pi_flags_reserved;
 
         if ((flags & ND_OPT_PI_FLAG_AUTO) && (pi->nd_opt_pi_prefix_len != 64)) {
-                log_ndisc("Invalid prefix length, ignoring prefix for stateless autoconfiguration.");
+                log_ndisc(NULL, "Invalid prefix length, ignoring prefix for stateless autoconfiguration.");
                 flags &= ~ND_OPT_PI_FLAG_AUTO;
         }
 
index cb3a56452be69f7ad3a2b45225ed19ad6b3ff377..f5293c96e01df8d4c0eebc7e05a4079b3610cf33 100644 (file)
@@ -45,4 +45,4 @@ static inline size_t NDISC_ROUTER_OPTION_LENGTH(const sd_ndisc_router *rt) {
 }
 
 sd_ndisc_router *ndisc_router_new(size_t raw_size);
-int ndisc_router_parse(sd_ndisc_router *rt);
+int ndisc_router_parse(sd_ndisc *nd, sd_ndisc_router *rt);
diff --git a/src/libsystemd-network/network-common.c b/src/libsystemd-network/network-common.c
new file mode 100644 (file)
index 0000000..9bc0da9
--- /dev/null
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "format-util.h"
+#include "network-common.h"
+#include "string-util.h"
+
+const char *get_ifname(int ifindex, char **ifname) {
+        char buf[IF_NAMESIZE + 1];
+
+        assert(ifname);
+
+        /* This sets ifname only when it is not set yet. */
+
+        if (*ifname)
+                return *ifname;
+
+        if (ifindex <= 0)
+                return NULL;
+
+        if (!format_ifname(ifindex, buf))
+                return NULL;
+
+        return *ifname = strdup(buf);
+}
diff --git a/src/libsystemd-network/network-common.h b/src/libsystemd-network/network-common.h
new file mode 100644 (file)
index 0000000..76a6c4a
--- /dev/null
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+const char *get_ifname(int ifindex, char **ifname);
index e5b853c0cd7acec6a8924e79dedc9353b75ed34b..9e7a67cbe360ed6a03291f73e1e419bb967b62bf 100644 (file)
@@ -27,5 +27,5 @@ int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t
 /* 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 dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
+int dhcp_lease_save(const sd_dhcp_lease *lease, const char *lease_file);
 int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
index 3dbeffe0c65a5a3e147f7bcee04a0786b49af33b..209425548baac1a5f6dbfcdbcbc0e21cd76f1412 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "sd-radv.h"
 
-#include "log.h"
+#include "log-link.h"
 #include "list.h"
 #include "sparse-endian.h"
 
@@ -41,6 +41,7 @@ struct sd_radv {
         RAdvState state;
 
         int ifindex;
+        char *ifname;
 
         sd_event *event;
         int event_priority;
@@ -124,6 +125,13 @@ struct sd_radv_route_prefix {
         LIST_FIELDS(struct sd_radv_route_prefix, prefix);
 };
 
-#define log_radv_full(level, error, fmt, ...) log_internal(level, error, PROJECT_FILE, __LINE__, __func__, "RADV: " fmt, ##__VA_ARGS__)
-#define log_radv_errno(error, fmt, ...) log_radv_full(LOG_DEBUG, error, fmt, ##__VA_ARGS__)
-#define log_radv(fmt, ...) log_radv_errno(0, fmt, ##__VA_ARGS__)
+#define log_radv_errno(radv, error, fmt, ...)           \
+        log_interface_prefix_full_errno(                \
+                "RADV: ",                               \
+                sd_radv_get_ifname(radv),               \
+                error, fmt, ##__VA_ARGS__)
+#define log_radv(radv, fmt, ...)                        \
+        log_interface_prefix_full_errno_zerook(         \
+                "RADV: ",                               \
+                sd_radv_get_ifname(radv),               \
+                0, fmt, ##__VA_ARGS__)
index fb94fdc88289ace602f0f5e552498245de141175..11492bca97f85b9e36f1961bf3b99316f9b42390 100644 (file)
@@ -24,6 +24,7 @@
 #include "hostname-util.h"
 #include "io-util.h"
 #include "memory-util.h"
+#include "network-common.h"
 #include "random-util.h"
 #include "set.h"
 #include "sort-util.h"
@@ -76,6 +77,7 @@ struct sd_dhcp_client {
         int event_priority;
         sd_event_source *timeout_resend;
         int ifindex;
+        char *ifname;
         int fd;
         uint16_t port;
         union sockaddr_union link;
@@ -282,6 +284,23 @@ int sd_dhcp_client_set_ifindex(sd_dhcp_client *client, int ifindex) {
         return 0;
 }
 
+int sd_dhcp_client_set_ifname(sd_dhcp_client *client, const char *ifname) {
+        assert_return(client, -EINVAL);
+        assert_return(ifname, -EINVAL);
+
+        if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
+                return -EINVAL;
+
+        return free_and_strdup(&client->ifname, ifname);
+}
+
+const char *sd_dhcp_client_get_ifname(sd_dhcp_client *client) {
+        if (!client)
+                return NULL;
+
+        return get_ifname(client->ifindex, &client->ifname);
+}
+
 int sd_dhcp_client_set_mac(
                 sd_dhcp_client *client,
                 const uint8_t *addr,
@@ -2033,6 +2052,13 @@ int sd_dhcp_client_send_renew(sd_dhcp_client *client) {
         return client_initialize_time_events(client);
 }
 
+int sd_dhcp_client_is_running(const sd_dhcp_client *client) {
+        if (!client)
+                return 0;
+
+        return !IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED);
+}
+
 int sd_dhcp_client_start(sd_dhcp_client *client) {
         int r;
 
@@ -2205,6 +2231,7 @@ static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) {
         client->user_class = strv_free(client->user_class);
         ordered_hashmap_free(client->extra_options);
         ordered_hashmap_free(client->vendor_options);
+        free(client->ifname);
         return mfree(client);
 }
 
index 6d88c88e6bb794c6ac3e9360c80f4b0bdec65653..37e37ef780931cd46c939e126c3b8d0970410c9d 100644 (file)
@@ -31,7 +31,7 @@
 #include "tmpfile-util.h"
 #include "unaligned.h"
 
-int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
+int sd_dhcp_lease_get_address(const sd_dhcp_lease *lease, struct in_addr *addr) {
         assert_return(lease, -EINVAL);
         assert_return(addr, -EINVAL);
 
@@ -42,7 +42,7 @@ int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
         return 0;
 }
 
-int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr) {
+int sd_dhcp_lease_get_broadcast(const sd_dhcp_lease *lease, struct in_addr *addr) {
         assert_return(lease, -EINVAL);
         assert_return(addr, -EINVAL);
 
@@ -53,7 +53,7 @@ int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr) {
         return 0;
 }
 
-int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) {
+int sd_dhcp_lease_get_lifetime(const sd_dhcp_lease *lease, uint32_t *lifetime) {
         assert_return(lease, -EINVAL);
         assert_return(lifetime, -EINVAL);
 
@@ -64,7 +64,7 @@ int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) {
         return 0;
 }
 
-int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1) {
+int sd_dhcp_lease_get_t1(const sd_dhcp_lease *lease, uint32_t *t1) {
         assert_return(lease, -EINVAL);
         assert_return(t1, -EINVAL);
 
@@ -75,7 +75,7 @@ int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1) {
         return 0;
 }
 
-int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2) {
+int sd_dhcp_lease_get_t2(const sd_dhcp_lease *lease, uint32_t *t2) {
         assert_return(lease, -EINVAL);
         assert_return(t2, -EINVAL);
 
@@ -86,7 +86,7 @@ int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2) {
         return 0;
 }
 
-int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) {
+int sd_dhcp_lease_get_mtu(const sd_dhcp_lease *lease, uint16_t *mtu) {
         assert_return(lease, -EINVAL);
         assert_return(mtu, -EINVAL);
 
@@ -98,7 +98,7 @@ int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) {
 }
 
 int sd_dhcp_lease_get_servers(
-                sd_dhcp_lease *lease,
+                const sd_dhcp_lease *lease,
                 sd_dhcp_lease_server_type_t what,
                 const struct in_addr **addr) {
 
@@ -114,26 +114,26 @@ int sd_dhcp_lease_get_servers(
         return (int) lease->servers[what].size;
 }
 
-int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) {
+int sd_dhcp_lease_get_dns(const sd_dhcp_lease *lease, const struct in_addr **addr) {
         return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_DNS, addr);
 }
-int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) {
+int sd_dhcp_lease_get_ntp(const sd_dhcp_lease *lease, const struct in_addr **addr) {
         return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_NTP, addr);
 }
-int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) {
+int sd_dhcp_lease_get_sip(const sd_dhcp_lease *lease, const struct in_addr **addr) {
         return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SIP, addr);
 }
-int sd_dhcp_lease_get_pop3(sd_dhcp_lease *lease, const struct in_addr **addr) {
+int sd_dhcp_lease_get_pop3(const sd_dhcp_lease *lease, const struct in_addr **addr) {
         return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_POP3, addr);
 }
-int sd_dhcp_lease_get_smtp(sd_dhcp_lease *lease, const struct in_addr **addr) {
+int sd_dhcp_lease_get_smtp(const sd_dhcp_lease *lease, const struct in_addr **addr) {
         return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SMTP, addr);
 }
-int sd_dhcp_lease_get_lpr(sd_dhcp_lease *lease, const struct in_addr **addr) {
+int sd_dhcp_lease_get_lpr(const sd_dhcp_lease *lease, const struct in_addr **addr) {
         return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_LPR, addr);
 }
 
-int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
+int sd_dhcp_lease_get_domainname(const sd_dhcp_lease *lease, const char **domainname) {
         assert_return(lease, -EINVAL);
         assert_return(domainname, -EINVAL);
 
@@ -144,7 +144,7 @@ int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname)
         return 0;
 }
 
-int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) {
+int sd_dhcp_lease_get_hostname(const sd_dhcp_lease *lease, const char **hostname) {
         assert_return(lease, -EINVAL);
         assert_return(hostname, -EINVAL);
 
@@ -155,7 +155,7 @@ int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) {
         return 0;
 }
 
-int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) {
+int sd_dhcp_lease_get_root_path(const sd_dhcp_lease *lease, const char **root_path) {
         assert_return(lease, -EINVAL);
         assert_return(root_path, -EINVAL);
 
@@ -166,7 +166,7 @@ int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) {
         return 0;
 }
 
-int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr) {
+int sd_dhcp_lease_get_router(const sd_dhcp_lease *lease, const struct in_addr **addr) {
         assert_return(lease, -EINVAL);
         assert_return(addr, -EINVAL);
 
@@ -177,7 +177,7 @@ int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr)
         return (int) lease->router_size;
 }
 
-int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {
+int sd_dhcp_lease_get_netmask(const sd_dhcp_lease *lease, struct in_addr *addr) {
         assert_return(lease, -EINVAL);
         assert_return(addr, -EINVAL);
 
@@ -188,7 +188,7 @@ int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {
         return 0;
 }
 
-int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr) {
+int sd_dhcp_lease_get_server_identifier(const sd_dhcp_lease *lease, struct in_addr *addr) {
         assert_return(lease, -EINVAL);
         assert_return(addr, -EINVAL);
 
@@ -199,7 +199,7 @@ int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *ad
         return 0;
 }
 
-int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) {
+int sd_dhcp_lease_get_next_server(const sd_dhcp_lease *lease, struct in_addr *addr) {
         assert_return(lease, -EINVAL);
         assert_return(addr, -EINVAL);
 
@@ -214,7 +214,7 @@ int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) {
  * The returned routes array must be freed by the caller.
  * Route objects have the same lifetime of the lease and must not be freed.
  */
-int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) {
+int sd_dhcp_lease_get_routes(const sd_dhcp_lease *lease, sd_dhcp_route ***routes) {
         sd_dhcp_route **ret;
         unsigned i;
 
@@ -235,7 +235,7 @@ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) {
         return (int) lease->static_route_size;
 }
 
-int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) {
+int sd_dhcp_lease_get_search_domains(const sd_dhcp_lease *lease, char ***domains) {
         size_t r;
 
         assert_return(lease, -EINVAL);
@@ -250,7 +250,7 @@ int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) {
         return -ENODATA;
 }
 
-int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len) {
+int sd_dhcp_lease_get_vendor_specific(const sd_dhcp_lease *lease, const void **data, size_t *data_len) {
         assert_return(lease, -EINVAL);
         assert_return(data, -EINVAL);
         assert_return(data_len, -EINVAL);
@@ -868,7 +868,7 @@ int dhcp_lease_new(sd_dhcp_lease **ret) {
         return 0;
 }
 
-int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
+int dhcp_lease_save(const sd_dhcp_lease *lease, const char *lease_file) {
         _cleanup_(unlink_and_freep) char *temp_path = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         struct sd_dhcp_raw_option *option;
@@ -1313,7 +1313,7 @@ int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) {
         return 0;
 }
 
-int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len) {
+int sd_dhcp_lease_get_client_id(const sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len) {
         assert_return(lease, -EINVAL);
         assert_return(client_id, -EINVAL);
         assert_return(client_id_len, -EINVAL);
@@ -1348,7 +1348,7 @@ int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t
         return 0;
 }
 
-int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **tz) {
+int sd_dhcp_lease_get_timezone(const sd_dhcp_lease *lease, const char **tz) {
         assert_return(lease, -EINVAL);
         assert_return(tz, -EINVAL);
 
@@ -1359,7 +1359,7 @@ int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **tz) {
         return 0;
 }
 
-int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination) {
+int sd_dhcp_route_get_destination(const sd_dhcp_route *route, struct in_addr *destination) {
         assert_return(route, -EINVAL);
         assert_return(destination, -EINVAL);
 
@@ -1367,7 +1367,7 @@ int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destinat
         return 0;
 }
 
-int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length) {
+int sd_dhcp_route_get_destination_prefix_length(const sd_dhcp_route *route, uint8_t *length) {
         assert_return(route, -EINVAL);
         assert_return(length, -EINVAL);
 
@@ -1375,7 +1375,7 @@ int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *l
         return 0;
 }
 
-int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway) {
+int sd_dhcp_route_get_gateway(const sd_dhcp_route *route, struct in_addr *gateway) {
         assert_return(route, -EINVAL);
         assert_return(gateway, -EINVAL);
 
@@ -1383,7 +1383,7 @@ int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway) {
         return 0;
 }
 
-int sd_dhcp_route_get_option(sd_dhcp_route *route) {
+int sd_dhcp_route_get_option(const sd_dhcp_route *route) {
         assert_return(route, -EINVAL);
 
         return route->option;
index 2b1384cff085ae78785ebd63a92289debf1b1029..e2ad99ebcbdec265069b384efe5c39ff41be5903 100644 (file)
@@ -15,6 +15,7 @@
 #include "fd-util.h"
 #include "in-addr-util.h"
 #include "io-util.h"
+#include "network-common.h"
 #include "ordered-set.h"
 #include "siphash24.h"
 #include "string-util.h"
@@ -113,6 +114,12 @@ int sd_dhcp_server_is_running(sd_dhcp_server *server) {
         return !!server->receive_message;
 }
 
+int sd_dhcp_server_is_in_relay_mode(sd_dhcp_server *server) {
+        assert_return(server, -EINVAL);
+
+        return in4_addr_is_set(&server->relay_target);
+}
+
 void client_id_hash_func(const DHCPClientId *id, struct siphash *state) {
         assert(id);
         assert(id->length);
@@ -158,6 +165,8 @@ static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) {
         ordered_set_free(server->vendor_options);
 
         free(server->bound_leases);
+
+        free(server->ifname);
         return mfree(server);
 }
 
@@ -169,29 +178,49 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
         assert_return(ret, -EINVAL);
         assert_return(ifindex > 0, -EINVAL);
 
-        server = new0(sd_dhcp_server, 1);
+        server = new(sd_dhcp_server, 1);
         if (!server)
                 return -ENOMEM;
 
-        server->n_ref = 1;
-        server->fd_raw = -1;
-        server->fd = -1;
-        server->address = htobe32(INADDR_ANY);
-        server->netmask = htobe32(INADDR_ANY);
-        server->ifindex = ifindex;
+        *server = (sd_dhcp_server) {
+                .n_ref = 1,
+                .fd_raw = -1,
+                .fd = -1,
+                .fd_broadcast = -1,
+                .address = htobe32(INADDR_ANY),
+                .netmask = htobe32(INADDR_ANY),
+                .ifindex = ifindex,
+                .bind_to_interface = true,
+                .default_lease_time = DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC, USEC_PER_SEC),
+                .max_lease_time = DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC, USEC_PER_SEC),
+        };
 
         server->leases_by_client_id = hashmap_new(&dhcp_lease_hash_ops);
         if (!server->leases_by_client_id)
                 return -ENOMEM;
 
-        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 = TAKE_PTR(server);
 
         return 0;
 }
 
+int sd_dhcp_server_set_ifname(sd_dhcp_server *server, const char *ifname) {
+        assert_return(server, -EINVAL);
+        assert_return(ifname, -EINVAL);
+
+        if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
+                return -EINVAL;
+
+        return free_and_strdup(&server->ifname, ifname);
+}
+
+const char *sd_dhcp_server_get_ifname(sd_dhcp_server *server) {
+        if (!server)
+                return NULL;
+
+        return get_ifname(server->ifindex, &server->ifname);
+}
+
 int sd_dhcp_server_attach_event(sd_dhcp_server *server, sd_event *event, int64_t priority) {
         int r;
 
@@ -229,11 +258,12 @@ int sd_dhcp_server_stop(sd_dhcp_server *server) {
         if (!server)
                 return 0;
 
-        server->receive_message =
-                sd_event_source_unref(server->receive_message);
+        server->receive_message = sd_event_source_unref(server->receive_message);
+        server->receive_broadcast = sd_event_source_unref(server->receive_broadcast);
 
         server->fd_raw = safe_close(server->fd_raw);
         server->fd = safe_close(server->fd);
+        server->fd_broadcast = safe_close(server->fd_broadcast);
 
         log_dhcp_server(server, "STOPPED");
 
@@ -282,8 +312,6 @@ static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
                 .msg_namelen = sizeof(dest.in),
                 .msg_iov = &iov,
                 .msg_iovlen = 1,
-                .msg_control = &control,
-                .msg_controllen = sizeof(control),
         };
         struct cmsghdr *cmsg;
         struct in_pktinfo *pktinfo;
@@ -293,22 +321,27 @@ static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
         assert(message);
         assert(len > sizeof(DHCPMessage));
 
-        cmsg = CMSG_FIRSTHDR(&msg);
-        assert(cmsg);
+        if (server->bind_to_interface) {
+                msg.msg_control = &control;
+                msg.msg_controllen = sizeof(control);
 
-        cmsg->cmsg_level = IPPROTO_IP;
-        cmsg->cmsg_type = IP_PKTINFO;
-        cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+                cmsg = CMSG_FIRSTHDR(&msg);
+                assert(cmsg);
 
-        /* we attach source interface and address info to the message
-           rather than binding the socket. This will be mostly useful
-           when we gain support for arbitrary number of server addresses
-         */
-        pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg);
-        assert(pktinfo);
+                cmsg->cmsg_level = IPPROTO_IP;
+                cmsg->cmsg_type = IP_PKTINFO;
+                cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
 
-        pktinfo->ipi_ifindex = server->ifindex;
-        pktinfo->ipi_spec_dst.s_addr = server->address;
+                /* we attach source interface and address info to the message
+                   rather than binding the socket. This will be mostly useful
+                   when we gain support for arbitrary number of server addresses
+                 */
+                pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg);
+                assert(pktinfo);
+
+                pktinfo->ipi_ifindex = server->ifindex;
+                pktinfo->ipi_spec_dst.s_addr = server->address;
+        }
 
         if (sendmsg(server->fd, &msg, 0) < 0)
                 return -errno;
@@ -316,10 +349,27 @@ static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
         return 0;
 }
 
-static bool requested_broadcast(DHCPRequest *req) {
-        assert(req);
+static bool requested_broadcast(DHCPMessage *message) {
+        assert(message);
+        return message->flags & htobe16(0x8000);
+}
 
-        return req->message->flags & htobe16(0x8000);
+static int dhcp_server_send(sd_dhcp_server *server, be32_t destination, uint16_t destination_port,
+                            DHCPPacket *packet, size_t optoffset, bool l2_broadcast) {
+        if (destination != INADDR_ANY)
+                return dhcp_server_send_udp(server, destination,
+                                            destination_port, &packet->dhcp,
+                                            sizeof(DHCPMessage) + optoffset);
+        else if (l2_broadcast)
+                return dhcp_server_send_udp(server, INADDR_BROADCAST,
+                                            destination_port, &packet->dhcp,
+                                            sizeof(DHCPMessage) + optoffset);
+        else
+                /* we cannot send UDP packet to specific MAC address when the
+                   address is not yet configured, so must fall back to raw
+                   packets */
+                return dhcp_server_send_unicast_raw(server, packet,
+                                                    sizeof(DHCPPacket) + optoffset);
 }
 
 int dhcp_server_send_packet(sd_dhcp_server *server,
@@ -377,20 +427,8 @@ int dhcp_server_send_packet(sd_dhcp_server *server,
         } else if (req->message->ciaddr && type != DHCP_NAK)
                 destination = req->message->ciaddr;
 
-        if (destination != INADDR_ANY)
-                return dhcp_server_send_udp(server, destination,
-                                            destination_port, &packet->dhcp,
-                                            sizeof(DHCPMessage) + optoffset);
-        else if (requested_broadcast(req) || type == DHCP_NAK)
-                return dhcp_server_send_udp(server, INADDR_BROADCAST,
-                                            destination_port, &packet->dhcp,
-                                            sizeof(DHCPMessage) + optoffset);
-        else
-                /* we cannot send UDP packet to specific MAC address when the
-                   address is not yet configured, so must fall back to raw
-                   packets */
-                return dhcp_server_send_unicast_raw(server, packet,
-                                                    sizeof(DHCPPacket) + optoffset);
+        bool l2_broadcast = requested_broadcast(req->message) || type == DHCP_NAK;
+        return dhcp_server_send(server, destination, destination_port, packet, optoffset, l2_broadcast);
 }
 
 static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret,
@@ -674,6 +712,47 @@ static int get_pool_offset(sd_dhcp_server *server, be32_t requested_ip) {
         return be32toh(requested_ip & ~server->netmask) - server->pool_offset;
 }
 
+static int dhcp_server_relay_message(sd_dhcp_server *server, DHCPMessage *message, size_t opt_length) {
+        _cleanup_free_ DHCPPacket *packet = NULL;
+
+        assert(server);
+        assert(message);
+        assert(sd_dhcp_server_is_in_relay_mode(server));
+
+        if (message->op == BOOTREQUEST) {
+                log_dhcp_server(server, "(relay agent) BOOTREQUEST (0x%x)", be32toh(message->xid));
+                if (message->hops >= 16)
+                        return -ETIME;
+                message->hops++;
+
+                /* https://tools.ietf.org/html/rfc1542#section-4.1.1 */
+                if (message->giaddr == 0)
+                        message->giaddr = server->address;
+
+                return dhcp_server_send_udp(server, server->relay_target.s_addr, DHCP_PORT_SERVER, message, sizeof(DHCPMessage) + opt_length);
+        } else if (message->op == BOOTREPLY) {
+                log_dhcp_server(server, "(relay agent) BOOTREPLY (0x%x)", be32toh(message->xid));
+                if (message->giaddr != server->address) {
+                        return log_dhcp_server_errno(server, SYNTHETIC_ERRNO(EBADMSG),
+                                                     "(relay agent)  BOOTREPLY giaddr mismatch, discarding");
+                }
+
+                int message_type = dhcp_option_parse(message, sizeof(DHCPMessage) + opt_length, NULL, NULL, NULL);
+                if (message_type < 0)
+                        return message_type;
+
+                packet = malloc0(sizeof(DHCPPacket) + opt_length);
+                if (!packet)
+                        return -ENOMEM;
+                memcpy(&packet->dhcp, message, sizeof(DHCPMessage) + opt_length);
+
+                bool l2_broadcast = requested_broadcast(message) || message_type == DHCP_NAK;
+                const be32_t destination = message_type == DHCP_NAK ? INADDR_ANY : message->ciaddr;
+                return dhcp_server_send(server, destination, DHCP_PORT_CLIENT, packet, opt_length, l2_broadcast);
+        }
+        return -EBADMSG;
+}
+
 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
 
 int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
@@ -972,10 +1051,15 @@ static int server_receive_message(sd_event_source *s, int fd,
                 }
         }
 
-        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");
-
+        if (sd_dhcp_server_is_in_relay_mode(server)) {
+                r = dhcp_server_relay_message(server, message, len - sizeof(DHCPMessage));
+                if (r < 0)
+                        log_dhcp_server_errno(server, r, "Couldn't relay message: %m");
+        } else {
+                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;
 }
 
@@ -992,36 +1076,55 @@ int sd_dhcp_server_start(sd_dhcp_server *server) {
         r = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
         if (r < 0) {
                 r = -errno;
-                sd_dhcp_server_stop(server);
-                return r;
+                goto on_error;
         }
         server->fd_raw = r;
 
-        r = dhcp_network_bind_udp_socket(server->ifindex, INADDR_ANY, DHCP_PORT_SERVER, -1);
-        if (r < 0) {
-                sd_dhcp_server_stop(server);
-                return r;
-        }
+        if (server->bind_to_interface)
+                r = dhcp_network_bind_udp_socket(server->ifindex, INADDR_ANY, DHCP_PORT_SERVER, -1);
+        else
+                r = dhcp_network_bind_udp_socket(0, server->address, DHCP_PORT_SERVER, -1);
+        if (r < 0)
+                goto on_error;
         server->fd = r;
 
         r = sd_event_add_io(server->event, &server->receive_message,
                             server->fd, EPOLLIN,
                             server_receive_message, server);
-        if (r < 0) {
-                sd_dhcp_server_stop(server);
-                return r;
-        }
+        if (r < 0)
+                goto on_error;
 
         r = sd_event_source_set_priority(server->receive_message,
                                          server->event_priority);
-        if (r < 0) {
-                sd_dhcp_server_stop(server);
-                return r;
+        if (r < 0)
+                goto on_error;
+
+        if (!server->bind_to_interface) {
+                r = dhcp_network_bind_udp_socket(server->ifindex, INADDR_BROADCAST, DHCP_PORT_SERVER, -1);
+                if (r < 0)
+                        goto on_error;
+
+                server->fd_broadcast = r;
+
+                r = sd_event_add_io(server->event, &server->receive_broadcast,
+                                    server->fd_broadcast, EPOLLIN,
+                                    server_receive_message, server);
+                if (r < 0)
+                        goto on_error;
+
+                r = sd_event_source_set_priority(server->receive_broadcast,
+                                                 server->event_priority);
+                if (r < 0)
+                        goto on_error;
         }
 
         log_dhcp_server(server, "STARTED");
 
         return 0;
+
+on_error:
+    sd_dhcp_server_stop(server);
+    return r;
 }
 
 int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {
@@ -1048,6 +1151,18 @@ int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {
         return r;
 }
 
+int sd_dhcp_server_set_bind_to_interface(sd_dhcp_server *server, int enabled) {
+        assert_return(server, -EINVAL);
+        assert_return(!sd_dhcp_server_is_running(server), -EBUSY);
+
+        if (!!enabled == server->bind_to_interface)
+                return 0;
+
+        server->bind_to_interface = enabled;
+
+        return 1;
+}
+
 int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *tz) {
         int r;
 
@@ -1180,3 +1295,14 @@ int sd_dhcp_server_set_callback(sd_dhcp_server *server, sd_dhcp_server_callback_
 
         return 0;
 }
+
+int sd_dhcp_server_set_relay_target(sd_dhcp_server *server, const struct in_addr* address) {
+        assert_return(server, -EINVAL);
+        assert_return(!sd_dhcp_server_is_running(server), -EBUSY);
+
+        if (memcmp(address, &server->relay_target, sizeof(struct in_addr)) == 0)
+                return 0;
+
+        server->relay_target = *address;
+        return 1;
+}
index 410bfda10eaaab91f96f466c3e55be7a40eea771..10f82996c8c260f3633113a1158b86f1b34e9c0c 100644 (file)
@@ -21,6 +21,7 @@
 #include "hexdecoct.h"
 #include "hostname-util.h"
 #include "in-addr-util.h"
+#include "network-common.h"
 #include "random-util.h"
 #include "socket-util.h"
 #include "string-table.h"
@@ -47,6 +48,7 @@ struct sd_dhcp6_client {
         sd_event *event;
         int event_priority;
         int ifindex;
+        char *ifname;
         DHCP6Address hint_pd_prefix;
         struct in6_addr local_address;
         uint8_t mac_addr[MAX_MAC_ADDR_LEN];
@@ -159,12 +161,29 @@ int sd_dhcp6_client_set_callback(
 int sd_dhcp6_client_set_ifindex(sd_dhcp6_client *client, int ifindex) {
         assert_return(client, -EINVAL);
         assert_return(ifindex > 0, -EINVAL);
-        assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
+        assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
 
         client->ifindex = ifindex;
         return 0;
 }
 
+int sd_dhcp6_client_set_ifname(sd_dhcp6_client *client, const char *ifname) {
+        assert_return(client, -EINVAL);
+        assert_return(ifname, -EINVAL);
+
+        if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
+                return -EINVAL;
+
+        return free_and_strdup(&client->ifname, ifname);
+}
+
+const char *sd_dhcp6_client_get_ifname(sd_dhcp6_client *client) {
+        if (!client)
+                return NULL;
+
+        return get_ifname(client->ifindex, &client->ifname);
+}
+
 int sd_dhcp6_client_set_local_address(
                 sd_dhcp6_client *client,
                 const struct in6_addr *local_address) {
@@ -172,8 +191,7 @@ int sd_dhcp6_client_set_local_address(
         assert_return(client, -EINVAL);
         assert_return(local_address, -EINVAL);
         assert_return(in6_addr_is_link_local(local_address) > 0, -EINVAL);
-
-        assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
+        assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
 
         client->local_address = *local_address;
 
@@ -188,8 +206,7 @@ int sd_dhcp6_client_set_mac(
         assert_return(client, -EINVAL);
         assert_return(addr, -EINVAL);
         assert_return(addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
-
-        assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
+        assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
 
         if (arp_type == ARPHRD_ETHER)
                 assert_return(addr_len == ETH_ALEN, -EINVAL);
@@ -219,8 +236,7 @@ int sd_dhcp6_client_set_prefix_delegation_hint(
 
         assert_return(client, -EINVAL);
         assert_return(pd_address, -EINVAL);
-
-        assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
+        assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
 
         client->hint_pd_prefix.iapdprefix.address = *pd_address;
         client->hint_pd_prefix.iapdprefix.prefixlen = prefixlen;
@@ -265,7 +281,7 @@ static int dhcp6_client_set_duid_internal(
 
         assert_return(client, -EINVAL);
         assert_return(duid_len == 0 || duid != NULL, -EINVAL);
-        assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
+        assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
 
         if (duid) {
                 r = dhcp_validate_duid_len(duid_type, duid_len, true);
@@ -374,7 +390,7 @@ int sd_dhcp6_client_duid_as_string(
 
 int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) {
         assert_return(client, -EINVAL);
-        assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
+        assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
 
         client->ia_na.ia_na.id = htobe32(iaid);
         client->ia_pd.ia_pd.id = htobe32(iaid);
@@ -411,7 +427,7 @@ int sd_dhcp6_client_set_fqdn(
 
 int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled) {
         assert_return(client, -EINVAL);
-        assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
+        assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
 
         client->information_request = enabled;
 
@@ -1172,7 +1188,7 @@ static int client_parse_message(
                                 break;
                         }
 
-                        r = dhcp6_option_parse_ia(option, &lease->ia, &ia_na_status);
+                        r = dhcp6_option_parse_ia(client, option, &lease->ia, &ia_na_status);
                         if (r < 0 && r != -ENOMSG)
                                 return r;
 
@@ -1205,7 +1221,7 @@ static int client_parse_message(
                                 break;
                         }
 
-                        r = dhcp6_option_parse_ia(option, &lease->pd, &ia_pd_status);
+                        r = dhcp6_option_parse_ia(client, option, &lease->pd, &ia_pd_status);
                         if (r < 0 && r != -ENOMSG)
                                 return r;
 
@@ -1686,7 +1702,7 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
         assert_return(client->ifindex > 0, -EINVAL);
         assert_return(in6_addr_is_link_local(&client->local_address) > 0, -EINVAL);
 
-        if (!IN_SET(client->state, DHCP6_STATE_STOPPED))
+        if (client->state != DHCP6_STATE_STOPPED)
                 return -EBUSY;
 
         if (!client->information_request && !client->request)
@@ -1787,6 +1803,7 @@ static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) {
         ordered_hashmap_free(client->extra_options);
         strv_free(client->user_class);
         strv_free(client->vendor_class);
+        free(client->ifname);
 
         return mfree(client);
 }
index d6f0708c942a81220485288113bd692195d06091..aca2c1f7e072546929bf5a2d7beb3965bb0cab85 100644 (file)
@@ -206,7 +206,7 @@ int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
                                         lease->dns_count,
                                         &lease->dns_allocated);
         if (r < 0)
-                return log_dhcp6_client_errno(client, r, "Invalid DNS server option: %m");
+                return r;
 
         lease->dns_count = r;
 
@@ -321,19 +321,16 @@ int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen)
         if (!optlen)
                 return 0;
 
-        if (lease->ntp || lease->ntp_fqdn) {
-                log_dhcp6_client(client, "NTP information already provided");
+        if (lease->ntp || lease->ntp_fqdn)
+                return -EEXIST;
 
-                return 0;
-        }
-
-        log_dhcp6_client(client, "Using deprecated SNTP information");
+        /* Using deprecated SNTP information */
 
         r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->ntp,
                                         lease->ntp_count,
                                         &lease->ntp_allocated);
         if (r < 0)
-                return log_dhcp6_client_errno(client, r, "Invalid SNTP server option: %m");
+                return r;
 
         lease->ntp_count = r;
 
index defd23d85a76201d0b424aea308e6b31b62a80c4..b4af60741a13cd35321103b2f248a0781e3759fc 100644 (file)
@@ -16,9 +16,9 @@
 #include "ether-addr-util.h"
 #include "event-util.h"
 #include "fd-util.h"
-#include "format-util.h"
 #include "in-addr-util.h"
 #include "log-link.h"
+#include "network-common.h"
 #include "random-util.h"
 #include "siphash24.h"
 #include "string-table.h"
@@ -56,7 +56,7 @@ struct sd_ipv4acd {
         int ifindex;
         int fd;
 
-        char ifname[IF_NAMESIZE + 1];
+        char *ifname;
         unsigned n_iteration;
         unsigned n_conflict;
 
@@ -75,10 +75,16 @@ struct sd_ipv4acd {
         void* userdata;
 };
 
-#define log_ipv4acd_errno(acd, error, fmt, ...)                         \
-        log_interface_full_errno(sd_ipv4acd_get_ifname(acd), LOG_DEBUG, error, "IPV4ACD: " fmt, ##__VA_ARGS__)
+#define log_ipv4acd_errno(acd, error, fmt, ...)         \
+        log_interface_prefix_full_errno(                \
+                "IPv4ACD: ",                            \
+                sd_ipv4acd_get_ifname(acd),             \
+                error, fmt, ##__VA_ARGS__)
 #define log_ipv4acd(acd, fmt, ...)                      \
-        log_ipv4acd_errno(acd, 0, fmt, ##__VA_ARGS__)
+        log_interface_prefix_full_errno_zerook(         \
+                "IPv4ACD: ",                            \
+                sd_ipv4acd_get_ifname(acd),             \
+                0, fmt, ##__VA_ARGS__)
 
 static const char * const ipv4acd_state_table[_IPV4ACD_STATE_MAX] = {
         [IPV4ACD_STATE_INIT]             = "init",
@@ -125,7 +131,7 @@ static sd_ipv4acd *ipv4acd_free(sd_ipv4acd *acd) {
 
         ipv4acd_reset(acd);
         sd_ipv4acd_detach_event(acd);
-
+        free(acd->ifname);
         return mfree(acd);
 }
 
@@ -398,16 +404,10 @@ fail:
 }
 
 int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int ifindex) {
-        char ifname[IF_NAMESIZE + 1];
-
         assert_return(acd, -EINVAL);
         assert_return(ifindex > 0, -EINVAL);
         assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY);
 
-        if (!format_ifname(ifindex, ifname))
-                return -ENODEV;
-
-        strcpy(acd->ifname, ifname);
         acd->ifindex = ifindex;
 
         return 0;
@@ -420,11 +420,21 @@ int sd_ipv4acd_get_ifindex(sd_ipv4acd *acd) {
         return acd->ifindex;
 }
 
+int sd_ipv4acd_set_ifname(sd_ipv4acd *acd, const char *ifname) {
+        assert_return(acd, -EINVAL);
+        assert_return(ifname, -EINVAL);
+
+        if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
+                return -EINVAL;
+
+        return free_and_strdup(&acd->ifname, ifname);
+}
+
 const char *sd_ipv4acd_get_ifname(sd_ipv4acd *acd) {
         if (!acd)
                 return NULL;
 
-        return empty_to_null(acd->ifname);
+        return get_ifname(acd->ifindex, &acd->ifname);
 }
 
 int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr) {
index a83c9b06de50d7557286449e58b95cc287866183..8053afee938896e6a0ef22b398c6646fbc56d66c 100644 (file)
@@ -49,10 +49,16 @@ struct sd_ipv4ll {
         void* userdata;
 };
 
-#define log_ipv4ll_errno(ll, error, fmt, ...)                           \
-        log_interface_full_errno(sd_ipv4ll_get_ifname(ll), LOG_DEBUG, error, "IPV4LL: " fmt, ##__VA_ARGS__)
+#define log_ipv4ll_errno(ll, error, fmt, ...)           \
+        log_interface_prefix_full_errno(                \
+                "IPv4LL: ",                             \
+                sd_ipv4ll_get_ifname(ll),               \
+                error, fmt, ##__VA_ARGS__)
 #define log_ipv4ll(ll, fmt, ...)                        \
-        log_ipv4ll_errno(ll, 0, fmt, ##__VA_ARGS__)
+        log_interface_prefix_full_errno_zerook(         \
+                "IPv4LL: ",                             \
+                sd_ipv4ll_get_ifname(ll),               \
+                0, fmt, ##__VA_ARGS__)
 
 static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata);
 
@@ -112,6 +118,13 @@ int sd_ipv4ll_get_ifindex(sd_ipv4ll *ll) {
         return sd_ipv4acd_get_ifindex(ll->acd);
 }
 
+int sd_ipv4ll_set_ifname(sd_ipv4ll *ll, const char *ifname) {
+        assert_return(ll, -EINVAL);
+        assert_return(ifname, -EINVAL);
+
+        return sd_ipv4acd_set_ifname(ll->acd, ifname);
+}
+
 const char *sd_ipv4ll_get_ifname(sd_ipv4ll *ll) {
         if (!ll)
                 return NULL;
index 3c0285df4e92308856af3294e111210ffeacad1a..49aa876a530f2714b2ecc83505a1b68cd3f670cf 100644 (file)
@@ -14,6 +14,7 @@
 #include "lldp-neighbor.h"
 #include "lldp-network.h"
 #include "memory-util.h"
+#include "network-common.h"
 #include "socket-util.h"
 #include "sort-util.h"
 #include "string-table.h"
@@ -39,12 +40,10 @@ static void lldp_callback(sd_lldp *lldp, sd_lldp_event_t event, sd_lldp_neighbor
         assert(lldp);
         assert(event >= 0 && event < _SD_LLDP_EVENT_MAX);
 
-        if (!lldp->callback) {
-                log_lldp("Received '%s' event.", lldp_event_to_string(event));
-                return;
-        }
+        if (!lldp->callback)
+                return (void) log_lldp(lldp, "Received '%s' event.", lldp_event_to_string(event));
 
-        log_lldp("Invoking callback for '%s' event.", lldp_event_to_string(event));
+        log_lldp(lldp, "Invoking callback for '%s' event.", lldp_event_to_string(event));
         lldp->callback(lldp, event, n, lldp->userdata);
 }
 
@@ -186,11 +185,11 @@ static int lldp_handle_datagram(sd_lldp *lldp, sd_lldp_neighbor *n) {
 
         r = lldp_add_neighbor(lldp, n);
         if (r < 0) {
-                log_lldp_errno(r, "Failed to add datagram. Ignoring.");
+                log_lldp_errno(lldp, r, "Failed to add datagram. Ignoring.");
                 return 0;
         }
 
-        log_lldp("Successfully processed LLDP datagram.");
+        log_lldp(lldp, "Successfully processed LLDP datagram.");
         return 0;
 }
 
@@ -204,8 +203,10 @@ static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, v
         assert(lldp);
 
         space = next_datagram_size_fd(fd);
-        if (space < 0)
-                return log_lldp_errno(space, "Failed to determine datagram size to read: %m");
+        if (space < 0) {
+                log_lldp_errno(lldp, space, "Failed to determine datagram size to read, ignoring: %m");
+                return 0;
+        }
 
         n = lldp_neighbor_new(space);
         if (!n)
@@ -216,12 +217,13 @@ static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, v
                 if (IN_SET(errno, EAGAIN, EINTR))
                         return 0;
 
-                return log_lldp_errno(errno, "Failed to read LLDP datagram: %m");
+                log_lldp_errno(lldp, errno, "Failed to read LLDP datagram, ignoring: %m");
+                return 0;
         }
 
         if ((size_t) length != n->raw_size) {
-                log_lldp("Packet size mismatch.");
-                return -EINVAL;
+                log_lldp(lldp, "Packet size mismatch, ignoring");
+                return 0;
         }
 
         /* Try to get the timestamp of this packet if it is known */
@@ -267,7 +269,7 @@ _public_ int sd_lldp_start(sd_lldp *lldp) {
 
         (void) sd_event_source_set_description(lldp->io_event_source, "lldp-io");
 
-        log_lldp("Started LLDP client");
+        log_lldp(lldp, "Started LLDP client");
         return 1;
 
 fail:
@@ -282,7 +284,7 @@ _public_ int sd_lldp_stop(sd_lldp *lldp) {
         if (lldp->fd < 0)
                 return 0;
 
-        log_lldp("Stopping LLDP client");
+        log_lldp(lldp, "Stopping LLDP client");
 
         lldp_reset(lldp);
         lldp_flush_neighbors(lldp);
@@ -343,6 +345,23 @@ _public_ int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex) {
         return 0;
 }
 
+int sd_lldp_set_ifname(sd_lldp *lldp, const char *ifname) {
+        assert_return(lldp, -EINVAL);
+        assert_return(ifname, -EINVAL);
+
+        if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
+                return -EINVAL;
+
+        return free_and_strdup(&lldp->ifname, ifname);
+}
+
+const char *sd_lldp_get_ifname(sd_lldp *lldp) {
+        if (!lldp)
+                return NULL;
+
+        return get_ifname(lldp->ifindex, &lldp->ifname);
+}
+
 static sd_lldp* lldp_free(sd_lldp *lldp) {
         assert(lldp);
 
@@ -354,6 +373,7 @@ static sd_lldp* lldp_free(sd_lldp *lldp) {
 
         hashmap_free(lldp->neighbor_by_id);
         prioq_free(lldp->neighbor_by_expiry);
+        free(lldp->ifname);
         return mfree(lldp);
 }
 
@@ -398,12 +418,16 @@ static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
         int r;
 
         r = lldp_make_space(lldp, 0);
-        if (r < 0)
-                return log_lldp_errno(r, "Failed to make space: %m");
+        if (r < 0) {
+                log_lldp_errno(lldp, r, "Failed to make space, ignoring: %m");
+                return 0;
+        }
 
         r = lldp_start_timer(lldp, NULL);
-        if (r < 0)
-                return log_lldp_errno(r, "Failed to restart timer: %m");
+        if (r < 0) {
+                log_lldp_errno(lldp, r, "Failed to restart timer, ignoring: %m");
+                return 0;
+        }
 
         return 0;
 }
index 8f04001755ac4c85e61962f3c44a204ac8cb798d..4d5f1b54cd4d5f01a50604a3d3cba9c5ffd446fa 100644 (file)
@@ -16,6 +16,7 @@
 #include "memory-util.h"
 #include "ndisc-internal.h"
 #include "ndisc-router.h"
+#include "network-common.h"
 #include "random-util.h"
 #include "socket-util.h"
 #include "string-table.h"
@@ -34,12 +35,10 @@ static void ndisc_callback(sd_ndisc *ndisc, sd_ndisc_event_t event, sd_ndisc_rou
         assert(ndisc);
         assert(event >= 0 && event < _SD_NDISC_EVENT_MAX);
 
-        if (!ndisc->callback) {
-                log_ndisc("Received '%s' event.", ndisc_event_to_string(event));
-                return;
-        }
+        if (!ndisc->callback)
+                return (void) log_ndisc(ndisc, "Received '%s' event.", ndisc_event_to_string(event));
 
-        log_ndisc("Invoking callback for '%s' event.", ndisc_event_to_string(event));
+        log_ndisc(ndisc, "Invoking callback for '%s' event.", ndisc_event_to_string(event));
         ndisc->callback(ndisc, event, rt, ndisc->userdata);
 }
 
@@ -65,6 +64,23 @@ _public_ int sd_ndisc_set_ifindex(sd_ndisc *nd, int ifindex) {
         return 0;
 }
 
+int sd_ndisc_set_ifname(sd_ndisc *nd, const char *ifname) {
+        assert_return(nd, -EINVAL);
+        assert_return(ifname, -EINVAL);
+
+        if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
+                return -EINVAL;
+
+        return free_and_strdup(&nd->ifname, ifname);
+}
+
+const char *sd_ndisc_get_ifname(sd_ndisc *nd) {
+        if (!nd)
+                return NULL;
+
+        return get_ifname(nd->ifindex, &nd->ifname);
+}
+
 _public_ int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr) {
         assert_return(nd, -EINVAL);
 
@@ -129,6 +145,7 @@ static sd_ndisc *ndisc_free(sd_ndisc *nd) {
 
         ndisc_reset(nd);
         sd_ndisc_detach_event(nd);
+        free(nd->ifname);
         return mfree(nd);
 }
 
@@ -181,7 +198,7 @@ static int ndisc_handle_datagram(sd_ndisc *nd, sd_ndisc_router *rt) {
         assert(nd);
         assert(rt);
 
-        r = ndisc_router_parse(rt);
+        r = ndisc_router_parse(nd, rt);
         if (r == -EBADMSG) /* Bad packet */
                 return 0;
         if (r < 0)
@@ -193,7 +210,7 @@ static int ndisc_handle_datagram(sd_ndisc *nd, sd_ndisc_router *rt) {
         if (rt->hop_limit > 0)
                 nd->hop_limit = rt->hop_limit;
 
-        log_ndisc("Received Router Advertisement: flags %s preference %s lifetime %" PRIu16 " sec",
+        log_ndisc(nd, "Received Router Advertisement: flags %s preference %s lifetime %" PRIu16 " sec",
                   rt->flags & ND_RA_FLAG_MANAGED ? "MANAGED" : rt->flags & ND_RA_FLAG_OTHER ? "OTHER" : "none",
                   rt->preference == SD_NDISC_PREFERENCE_HIGH ? "high" : rt->preference == SD_NDISC_PREFERENCE_LOW ? "low" : "medium",
                   rt->lifetime);
@@ -214,8 +231,10 @@ static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userda
         assert(nd->event);
 
         buflen = next_datagram_size_fd(fd);
-        if (buflen < 0)
-                return log_ndisc_errno(buflen, "Failed to determine datagram size to read: %m");
+        if (buflen < 0) {
+                log_ndisc_errno(nd, buflen, "Failed to determine datagram size to read, ignoring: %m");
+                return 0;
+        }
 
         rt = ndisc_router_new(buflen);
         if (!rt)
@@ -226,22 +245,22 @@ static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userda
                 switch (r) {
                 case -EADDRNOTAVAIL:
                         (void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &rt->address, &addr);
-                        log_ndisc("Received RA from non-link-local address %s. Ignoring", addr);
+                        log_ndisc(nd, "Received RA from non-link-local address %s. Ignoring", addr);
                         break;
 
                 case -EMULTIHOP:
-                        log_ndisc("Received RA with invalid hop limit. Ignoring.");
+                        log_ndisc(nd, "Received RA with invalid hop limit. Ignoring.");
                         break;
 
                 case -EPFNOSUPPORT:
-                        log_ndisc("Received invalid source address from ICMPv6 socket. Ignoring.");
+                        log_ndisc(nd, "Received invalid source address from ICMPv6 socket. Ignoring.");
                         break;
 
                 case -EAGAIN: /* ignore spurious wakeups */
                         break;
 
                 default:
-                        log_ndisc_errno(r, "Unexpected error while reading from ICMPv6, ignoring: %m");
+                        log_ndisc_errno(nd, r, "Unexpected error while reading from ICMPv6, ignoring: %m");
                         break;
                 }
 
@@ -290,11 +309,11 @@ static int ndisc_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
 
         r = icmp6_send_router_solicitation(nd->fd, &nd->mac_addr);
         if (r < 0) {
-                log_ndisc_errno(r, "Error sending Router Solicitation: %m");
+                log_ndisc_errno(nd, r, "Error sending Router Solicitation: %m");
                 goto fail;
         }
 
-        log_ndisc("Sent Router Solicitation, next solicitation in %s",
+        log_ndisc(nd, "Sent Router Solicitation, next solicitation in %s",
                   format_timespan(time_string, FORMAT_TIMESPAN_MAX,
                                   nd->retransmit_time, USEC_PER_SEC));
 
@@ -311,7 +330,7 @@ static int ndisc_timeout_no_ra(sd_event_source *s, uint64_t usec, void *userdata
         assert(s);
         assert(nd);
 
-        log_ndisc("No RA received before link confirmation timeout");
+        log_ndisc(nd, "No RA received before link confirmation timeout");
 
         (void) event_source_disable(nd->timeout_no_ra);
         ndisc_callback(nd, SD_NDISC_EVENT_TIMEOUT, NULL);
@@ -326,7 +345,7 @@ _public_ int sd_ndisc_stop(sd_ndisc *nd) {
         if (nd->fd < 0)
                 return 0;
 
-        log_ndisc("Stopping IPv6 Router Solicitation client");
+        log_ndisc(nd, "Stopping IPv6 Router Solicitation client");
 
         ndisc_reset(nd);
         return 1;
@@ -379,7 +398,7 @@ _public_ int sd_ndisc_start(sd_ndisc *nd) {
         if (r < 0)
                 goto fail;
 
-        log_ndisc("Started IPv6 Router Solicitation client");
+        log_ndisc(nd, "Started IPv6 Router Solicitation client");
         return 1;
 
 fail:
index 164b24c6847f40ea49e2bf035fad4b61414a594b..857401bf6e06df3245ad54769c5153681782250e 100644 (file)
@@ -19,6 +19,7 @@
 #include "io-util.h"
 #include "macro.h"
 #include "memory-util.h"
+#include "network-common.h"
 #include "radv-internal.h"
 #include "random-util.h"
 #include "socket-util.h"
@@ -122,6 +123,7 @@ static sd_radv *radv_free(sd_radv *ra) {
         sd_radv_detach_event(ra);
 
         ra->fd = safe_close(ra->fd);
+        free(ra->ifname);
 
         return mfree(ra);
 }
@@ -245,22 +247,22 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
                 switch (r) {
                 case -EADDRNOTAVAIL:
                         (void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &src, &addr);
-                        log_radv("Received RS from non-link-local address %s. Ignoring", addr);
+                        log_radv(ra, "Received RS from non-link-local address %s. Ignoring", addr);
                         break;
 
                 case -EMULTIHOP:
-                        log_radv("Received RS with invalid hop limit. Ignoring.");
+                        log_radv(ra, "Received RS with invalid hop limit. Ignoring.");
                         break;
 
                 case -EPFNOSUPPORT:
-                        log_radv("Received invalid source address from ICMPv6 socket. Ignoring.");
+                        log_radv(ra, "Received invalid source address from ICMPv6 socket. Ignoring.");
                         break;
 
                 case -EAGAIN: /* ignore spurious wakeups */
                         break;
 
                 default:
-                        log_radv_errno(r, "Unexpected error receiving from ICMPv6 socket: %m");
+                        log_radv_errno(ra, r, "Unexpected error receiving from ICMPv6 socket, Ignoring: %m");
                         break;
                 }
 
@@ -268,7 +270,7 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
         }
 
         if ((size_t) buflen < sizeof(struct nd_router_solicit)) {
-                log_radv("Too short packet received");
+                log_radv(ra, "Too short packet received, ignoring");
                 return 0;
         }
 
@@ -276,9 +278,9 @@ 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_errno(r, "Unable to send solicited Router Advertisement to %s: %m", strnull(addr));
+                log_radv_errno(ra, r, "Unable to send solicited Router Advertisement to %s, ignoring: %m", strnull(addr));
         else
-                log_radv("Sent solicited Router Advertisement to %s", strnull(addr));
+                log_radv(ra, "Sent solicited Router Advertisement to %s", strnull(addr));
 
         return 0;
 }
@@ -311,7 +313,7 @@ static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
 
         r = radv_send(ra, NULL, ra->lifetime);
         if (r < 0)
-                log_radv_errno(r, "Unable to send Router Advertisement: %m");
+                log_radv_errno(ra, r, "Unable to send Router Advertisement: %m");
 
         /* RFC 4861, Section 6.2.4, sending initial Router Advertisements */
         if (ra->ra_sent < SD_RADV_MAX_INITIAL_RTR_ADVERTISEMENTS) {
@@ -328,7 +330,7 @@ static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
 
         timeout = radv_compute_timeout(min_timeout, max_timeout);
 
-        log_radv("Next Router Advertisement in %s",
+        log_radv(ra, "Next Router Advertisement in %s",
                  format_timespan(time_string, FORMAT_TIMESPAN_MAX,
                                  timeout, USEC_PER_SEC));
 
@@ -359,13 +361,13 @@ _public_ int sd_radv_stop(sd_radv *ra) {
         if (ra->state == SD_RADV_STATE_IDLE)
                 return 0;
 
-        log_radv("Stopping IPv6 Router Advertisement daemon");
+        log_radv(ra, "Stopping IPv6 Router Advertisement daemon");
 
         /* RFC 4861, Section 6.2.5, send at least one Router Advertisement
            with zero lifetime  */
         r = radv_send(ra, NULL, 0);
         if (r < 0)
-                log_radv_errno(r, "Unable to send last Router Advertisement with router lifetime set to zero: %m");
+                log_radv_errno(ra, r, "Unable to send last Router Advertisement with router lifetime set to zero: %m");
 
         radv_reset(ra);
         ra->fd = safe_close(ra->fd);
@@ -410,7 +412,7 @@ _public_ int sd_radv_start(sd_radv *ra) {
 
         ra->state = SD_RADV_STATE_ADVERTISING;
 
-        log_radv("Started IPv6 Router Advertisement daemon");
+        log_radv(ra, "Started IPv6 Router Advertisement daemon");
 
         return 0;
 
@@ -432,6 +434,23 @@ _public_ int sd_radv_set_ifindex(sd_radv *ra, int ifindex) {
         return 0;
 }
 
+int sd_radv_set_ifname(sd_radv *ra, const char *ifname) {
+        assert_return(ra, -EINVAL);
+        assert_return(ifname, -EINVAL);
+
+        if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
+                return -EINVAL;
+
+        return free_and_strdup(&ra->ifname, ifname);
+}
+
+const char *sd_radv_get_ifname(sd_radv *ra) {
+        if (!ra)
+                return NULL;
+
+        return get_ifname(ra->ifindex, &ra->ifname);
+}
+
 _public_ int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr) {
         assert_return(ra, -EINVAL);
 
@@ -562,10 +581,9 @@ _public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, int dynamic) {
                 (void) in_addr_prefix_to_string(AF_INET6,
                                                 (const union in_addr_union*) &cur->opt.in6_addr,
                                                 cur->opt.prefixlen, &addr_cur);
-                log_radv("IPv6 prefix %s already configured, ignoring %s",
-                         strna(addr_cur), strna(addr_p));
-
-                return -EEXIST;
+                return log_radv_errno(ra, SYNTHETIC_ERRNO(EEXIST),
+                                      "IPv6 prefix %s already configured, ignoring %s",
+                                      strna(addr_cur), strna(addr_p));
         }
 
         p = sd_radv_prefix_ref(p);
@@ -575,7 +593,7 @@ _public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, int dynamic) {
         ra->n_prefixes++;
 
         if (!dynamic) {
-                log_radv("Added prefix %s", strna(addr_p));
+                log_radv(ra, "Added prefix %s", strna(addr_p));
                 return 0;
         }
 
@@ -585,9 +603,9 @@ _public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, int dynamic) {
         if (ra->ra_sent > 0) {
                 r = radv_send(ra, NULL, ra->lifetime);
                 if (r < 0)
-                        log_radv_errno(r, "Unable to send Router Advertisement for added prefix: %m");
+                        log_radv_errno(ra, r, "Unable to send Router Advertisement for added prefix: %m");
                 else
-                        log_radv("Sent Router Advertisement for added prefix");
+                        log_radv(ra, "Sent Router Advertisement for added prefix");
         }
 
  update:
@@ -608,7 +626,7 @@ _public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, int dynamic) {
         cur->valid_until = valid_until;
         cur->preferred_until = preferred_until;
 
-        log_radv("Updated prefix %s preferred %s valid %s",
+        log_radv(ra, "Updated prefix %s preferred %s valid %s",
                  strna(addr_p),
                  format_timespan(time_string_preferred, FORMAT_TIMESPAN_MAX,
                                  preferred, USEC_PER_SEC),
@@ -678,10 +696,9 @@ _public_ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int
                 (void) in_addr_prefix_to_string(AF_INET6,
                                                 (const union in_addr_union*) &cur->opt.in6_addr,
                                                 cur->opt.prefixlen, &addr);
-                log_radv("IPv6 route prefix %s already configured, ignoring %s",
-                         strna(addr), strna(pretty));
-
-                return -EEXIST;
+                return log_radv_errno(ra, SYNTHETIC_ERRNO(EEXIST),
+                                      "IPv6 route prefix %s already configured, ignoring %s",
+                                      strna(addr), strna(pretty));
         }
 
         p = sd_radv_route_prefix_ref(p);
@@ -690,7 +707,7 @@ _public_ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int
         ra->n_route_prefixes++;
 
         if (!dynamic) {
-                log_radv("Added prefix %s", strna(pretty));
+                log_radv(ra, "Added prefix %s", strna(pretty));
                 return 0;
         }
 
@@ -698,9 +715,9 @@ _public_ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int
         if (ra->ra_sent > 0) {
                 r = radv_send(ra, NULL, ra->lifetime);
                 if (r < 0)
-                        log_radv_errno(r, "Unable to send Router Advertisement for added route prefix: %m");
+                        log_radv_errno(ra, r, "Unable to send Router Advertisement for added route prefix: %m");
                 else
-                        log_radv("Sent Router Advertisement for added route prefix");
+                        log_radv(ra, "Sent Router Advertisement for added route prefix");
         }
 
  update:
@@ -713,7 +730,7 @@ _public_ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int
         if (valid_until == USEC_INFINITY)
                 return -EOVERFLOW;
 
-        log_radv("Updated route prefix %s valid %s",
+        log_radv(ra, "Updated route prefix %s valid %s",
                  strna(pretty),
                  format_timespan(time_string_valid, FORMAT_TIMESPAN_MAX, valid, USEC_PER_SEC));
 
@@ -842,7 +859,7 @@ _public_ int sd_radv_prefix_set_prefix(sd_radv_prefix *p, const struct in6_addr
 
         if (prefixlen > 64)
                 /* unusual but allowed, log it */
-                log_radv("Unusual prefix length %d greater than 64", prefixlen);
+                log_radv(NULL, "Unusual prefix length %d greater than 64", prefixlen);
 
         p->opt.in6_addr = *in6_addr;
         p->opt.prefixlen = prefixlen;
@@ -932,7 +949,7 @@ _public_ int sd_radv_prefix_set_route_prefix(sd_radv_route_prefix *p, const stru
 
         if (prefixlen > 64)
                 /* unusual but allowed, log it */
-                log_radv("Unusual prefix length %u greater than 64", prefixlen);
+                log_radv(NULL, "Unusual prefix length %u greater than 64", prefixlen);
 
         p->opt.in6_addr = *in6_addr;
         p->opt.prefixlen = prefixlen;
index e91b440fe90952d9cbd301d0405cf0a60a8ba8f5..f0514207080133c0320c218e6856291369a46315 100644 (file)
@@ -20,7 +20,7 @@ static void test_pool(struct in_addr *address, unsigned size, int ret) {
         assert_se(sd_dhcp_server_configure_pool(server, address, 8, 0, size) == ret);
 }
 
-static int test_basic(sd_event *event) {
+static int test_basic(sd_event *event, bool bind_to_interface) {
         _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
         struct in_addr address_lo = {
                 .s_addr = htobe32(INADDR_LOOPBACK),
@@ -33,6 +33,7 @@ static int test_basic(sd_event *event) {
         /* attach to loopback interface */
         assert_se(sd_dhcp_server_new(&server, 1) >= 0);
         assert_se(server);
+        server->bind_to_interface = bind_to_interface;
 
         assert_se(sd_dhcp_server_attach_event(server, event, 0) >= 0);
         assert_se(sd_dhcp_server_attach_event(server, event, 0) == -EBUSY);
@@ -234,9 +235,13 @@ int main(int argc, char *argv[]) {
 
         assert_se(sd_event_new(&e) >= 0);
 
-        r = test_basic(e);
+        r = test_basic(e, true);
         if (r != 0)
-                return log_tests_skipped("cannot start dhcp server");
+                return log_tests_skipped("cannot start dhcp server(bound to interface)");
+
+        r = test_basic(e, false);
+        if (r != 0)
+                return log_tests_skipped("cannot start dhcp server(non-bound to interface)");
 
         test_message_handler();
         test_client_id_hash();
index 96dc02a7e84d4880a21f89b18e2a651f08016874..5d0c5ed2a21624a4602520e80e7c2bc733585885 100644 (file)
@@ -295,17 +295,17 @@ static int test_option_status(sd_event *e) {
         option = (DHCP6Option *)option1;
         assert_se(sizeof(option1) == sizeof(DHCP6Option) + be16toh(option->len));
 
-        r = dhcp6_option_parse_ia(option, &ia, NULL);
+        r = dhcp6_option_parse_ia(NULL, option, &ia, NULL);
         assert_se(r == 0);
         assert_se(ia.addresses == NULL);
 
         option->len = htobe16(17);
-        r = dhcp6_option_parse_ia(option, &ia, NULL);
+        r = dhcp6_option_parse_ia(NULL, option, &ia, NULL);
         assert_se(r == -ENOBUFS);
         assert_se(ia.addresses == NULL);
 
         option->len = htobe16(sizeof(DHCP6Option));
-        r = dhcp6_option_parse_ia(option, &ia, NULL);
+        r = dhcp6_option_parse_ia(NULL, option, &ia, NULL);
         assert_se(r == -ENOBUFS);
         assert_se(ia.addresses == NULL);
 
@@ -313,7 +313,7 @@ static int test_option_status(sd_event *e) {
         option = (DHCP6Option *)option2;
         assert_se(sizeof(option2) == sizeof(DHCP6Option) + be16toh(option->len));
 
-        r = dhcp6_option_parse_ia(option, &ia, NULL);
+        r = dhcp6_option_parse_ia(NULL, option, &ia, NULL);
         assert_se(r >= 0);
         assert_se(ia.addresses == NULL);
 
@@ -321,7 +321,7 @@ static int test_option_status(sd_event *e) {
         option = (DHCP6Option *)option3;
         assert_se(sizeof(option3) == sizeof(DHCP6Option) + be16toh(option->len));
 
-        r = dhcp6_option_parse_ia(option, &ia, NULL);
+        r = dhcp6_option_parse_ia(NULL, option, &ia, NULL);
         assert_se(r >= 0);
         assert_se(ia.addresses != NULL);
         dhcp6_lease_free_ia(&ia);
@@ -330,7 +330,7 @@ static int test_option_status(sd_event *e) {
         option = (DHCP6Option *)option4;
         assert_se(sizeof(option4) == sizeof(DHCP6Option) + be16toh(option->len));
 
-        r = dhcp6_option_parse_ia(option, &pd, NULL);
+        r = dhcp6_option_parse_ia(NULL, option, &pd, NULL);
         assert_se(r >= 0);
         assert_se(pd.addresses != NULL);
         assert_se(memcmp(&pd.ia_pd.id, &option4[4], 4) == 0);
@@ -342,7 +342,7 @@ static int test_option_status(sd_event *e) {
         option = (DHCP6Option *)option5;
         assert_se(sizeof(option5) == sizeof(DHCP6Option) + be16toh(option->len));
 
-        r = dhcp6_option_parse_ia(option, &pd, NULL);
+        r = dhcp6_option_parse_ia(NULL, option, &pd, NULL);
         assert_se(r >= 0);
         assert_se(pd.addresses != NULL);
         dhcp6_lease_free_ia(&pd);
@@ -461,7 +461,7 @@ static int test_advertise_option(sd_event *e) {
                         val = htobe32(120);
                         assert_se(!memcmp(optval + 8, &val, sizeof(val)));
 
-                        assert_se(dhcp6_option_parse_ia(option, &lease->ia, NULL) >= 0);
+                        assert_se(dhcp6_option_parse_ia(NULL, option, &lease->ia, NULL) >= 0);
 
                         break;
 
@@ -658,7 +658,7 @@ static int test_client_verify_request(DHCP6Message *request, size_t len) {
                         assert_se(!memcmp(optval + 8, &val, sizeof(val)));
 
                         /* Then, this should refuse all addresses. */
-                        assert_se(dhcp6_option_parse_ia(option, &lease->ia, NULL) >= 0);
+                        assert_se(dhcp6_option_parse_ia(NULL, option, &lease->ia, NULL) >= 0);
 
                         break;
 
index 74eff7fcf0822ab998ede1b69d975f793f9125a7..996bf25d6c220e6ae987b46134681936b545ea4b 100644 (file)
@@ -751,3 +751,10 @@ global:
         sd_device_new_from_stat_rdev;
         sd_device_trigger;
 } LIBSYSTEMD_247;
+
+LIBSYSTEMD_249 {
+global:
+        sd_device_monitor_filter_add_match_sysattr;
+        sd_device_monitor_filter_add_match_parent;
+        sd_device_get_usec_initialized;
+} LIBSYSTEMD_248;
index ad50815a7b6ddd289207c9f872d9799458618477..f55bdcd1a5c0da725d90d57e3d7e9f30c7636e4d 100644 (file)
@@ -127,6 +127,7 @@ libsystemd_sources = files('''
         sd-device/device-monitor.c
         sd-device/device-private.c
         sd-device/device-private.h
+        sd-device/device-util.c
         sd-device/device-util.h
         sd-device/sd-device.c
         sd-hwdb/hwdb-internal.h
@@ -307,6 +308,8 @@ tests += [
 
         [['src/libsystemd/sd-device/test-sd-device.c']],
 
+        [['src/libsystemd/sd-device/test-device-util.c']],
+
         [['src/libsystemd/sd-device/test-sd-device-monitor.c']],
 ]
 
index 8da2024a5028ffcfa8776cfb5f66799ad545c1fa..7483b46a11d7dc79367c0351573c3ed577e0ef10 100644 (file)
@@ -86,8 +86,10 @@ static int bus_error_name_to_errno(const char *name) {
                                 if (m->code == BUS_ERROR_MAP_END_MARKER)
                                         break;
 
-                                if (streq(m->name, name))
+                                if (streq(m->name, name)) {
+                                        assert(m->code > 0);
                                         return m->code;
+                                }
                         }
 
         m = ALIGN_TO_PTR(__start_SYSTEMD_BUS_ERROR_MAP, sizeof(void*));
@@ -103,8 +105,10 @@ static int bus_error_name_to_errno(const char *name) {
                         continue;
                 }
 
-                if (streq(m->name, name))
+                if (streq(m->name, name)) {
+                        assert(m->code > 0);
                         return m->code;
+                }
 
                 m++;
         }
@@ -208,30 +212,33 @@ _public_ void sd_bus_error_free(sd_bus_error *e) {
 }
 
 _public_ int sd_bus_error_set(sd_bus_error *e, const char *name, const char *message) {
+        int r;
 
         if (!name)
                 return 0;
-        if (!e)
-                goto finish;
 
-        assert_return(!bus_error_is_dirty(e), -EINVAL);
+        if (e) {
+                assert_return(!bus_error_is_dirty(e), -EINVAL);
 
-        e->name = strdup(name);
-        if (!e->name) {
-                *e = BUS_ERROR_OOM;
-                return -ENOMEM;
-        }
+                e->name = strdup(name);
+                if (!e->name) {
+                        *e = BUS_ERROR_OOM;
+                        return -ENOMEM;
+                }
 
-        if (message)
-                e->message = strdup(message);
+                if (message)
+                        e->message = strdup(message);
 
-        e->_need_free = 1;
+                e->_need_free = 1;
+        }
 
-finish:
-        return -bus_error_name_to_errno(name);
+        r = bus_error_name_to_errno(name);
+        assert(r > 0);
+        return -r;
 }
 
 int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_list ap) {
+        int r;
 
         if (!name)
                 return 0;
@@ -253,23 +260,28 @@ int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_li
                 e->_need_free = 1;
         }
 
-        return -bus_error_name_to_errno(name);
+        r = bus_error_name_to_errno(name);
+        assert(r > 0);
+        return -r;
 }
 
 _public_ int sd_bus_error_setf(sd_bus_error *e, const char *name, const char *format, ...) {
+        int r;
 
         if (format) {
-                int r;
                 va_list ap;
 
                 va_start(ap, format);
                 r = bus_error_setfv(e, name, format, ap);
+                assert(!name || r < 0);
                 va_end(ap);
 
                 return r;
         }
 
-        return sd_bus_error_set(e, name, NULL);
+        r = sd_bus_error_set(e, name, NULL);
+        assert(!name || r < 0);
+        return r;
 }
 
 _public_ int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e) {
@@ -455,7 +467,7 @@ _public_ int sd_bus_error_set_errno(sd_bus_error *e, int error) {
         if (!e)
                 return -error;
         if (error == 0)
-                return -error;
+                return 0;
 
         assert_return(!bus_error_is_dirty(e), -EINVAL);
 
index e719c74370f3f081e54f9acb9eca48c6a43b5f06..8bcf4f6c50630401d6b07a8bf2e3241575d9f5c6 100644 (file)
@@ -1800,7 +1800,9 @@ void bus_enter_closing(sd_bus *bus) {
 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus, sd_bus, bus_free);
 
 _public_ int sd_bus_is_open(sd_bus *bus) {
-        assert_return(bus, -EINVAL);
+        if (!bus)
+                return 0;
+
         assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
@@ -1808,7 +1810,9 @@ _public_ int sd_bus_is_open(sd_bus *bus) {
 }
 
 _public_ int sd_bus_is_ready(sd_bus *bus) {
-        assert_return(bus, -EINVAL);
+        if (!bus)
+                return 0;
+
         assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
@@ -2410,7 +2414,7 @@ _public_ int sd_bus_call(
                                                 return 1;
                                         }
 
-                                        return sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry.");
+                                        return sd_bus_error_set(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry.");
 
                                 } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
                                         return sd_bus_error_copy(error, &incoming->error);
index c98b029af23c84c26373e8fed865aa9d63afae71..a290dbcc9ce5b17ced396878ad95360cc36a69ce 100644 (file)
@@ -116,6 +116,8 @@ _public_ int sd_device_enumerator_add_match_sysattr(sd_device_enumerator *enumer
         else
                 hashmap = &enumerator->nomatch_sysattr;
 
+        /* Do not use string_has_ops_free_free or hashmap_put_strdup() here, as this may be called
+         * multiple times with the same sysattr but different value. */
         r = hashmap_put_strdup_full(hashmap, &trivial_hash_ops_free_free, sysattr, value);
         if (r <= 0)
                 return r;
@@ -131,6 +133,8 @@ _public_ int sd_device_enumerator_add_match_property(sd_device_enumerator *enume
         assert_return(enumerator, -EINVAL);
         assert_return(property, -EINVAL);
 
+        /* Do not use string_has_ops_free_free or hashmap_put_strdup() here, as this may be called
+         * multiple times with the same property but different value. */
         r = hashmap_put_strdup_full(&enumerator->match_property, &trivial_hash_ops_free_free, property, value);
         if (r <= 0)
                 return r;
@@ -283,42 +287,6 @@ int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *de
         return 0;
 }
 
-static bool match_sysattr_value(sd_device *device, const char *sysattr, const char *match_value) {
-        const char *value;
-
-        assert(device);
-        assert(sysattr);
-
-        if (sd_device_get_sysattr_value(device, sysattr, &value) < 0)
-                return false;
-
-        if (!match_value)
-                return true;
-
-        if (fnmatch(match_value, value, 0) == 0)
-                return true;
-
-        return false;
-}
-
-static bool match_sysattr(sd_device_enumerator *enumerator, sd_device *device) {
-        const char *sysattr;
-        const char *value;
-
-        assert(enumerator);
-        assert(device);
-
-        HASHMAP_FOREACH_KEY(value, sysattr, enumerator->nomatch_sysattr)
-                if (match_sysattr_value(device, sysattr, value))
-                        return false;
-
-        HASHMAP_FOREACH_KEY(value, sysattr, enumerator->match_sysattr)
-                if (!match_sysattr_value(device, sysattr, value))
-                        return false;
-
-        return true;
-}
-
 static bool match_property(sd_device_enumerator *enumerator, sd_device *device) {
         const char *property;
         const char *value;
@@ -363,24 +331,6 @@ static bool match_tag(sd_device_enumerator *enumerator, sd_device *device) {
         return true;
 }
 
-static bool match_parent(sd_device_enumerator *enumerator, sd_device *device) {
-        const char *syspath_parent, *syspath;
-
-        assert(enumerator);
-        assert(device);
-
-        if (set_isempty(enumerator->match_parent))
-                return true;
-
-        assert_se(sd_device_get_syspath(device, &syspath) >= 0);
-
-        SET_FOREACH(syspath_parent, enumerator->match_parent)
-                if (path_startswith(syspath, syspath_parent))
-                        return true;
-
-        return false;
-}
-
 static bool match_sysname(sd_device_enumerator *enumerator, const char *sysname) {
         const char *sysname_match;
 
@@ -466,7 +416,7 @@ static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator,
                      sd_device_get_ifindex(device, NULL) >= 0))
                         continue;
 
-                if (!match_parent(enumerator, device))
+                if (!device_match_parent(device, enumerator->match_parent, NULL))
                         continue;
 
                 if (!match_tag(enumerator, device))
@@ -475,7 +425,7 @@ static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator,
                 if (!match_property(enumerator, device))
                         continue;
 
-                if (!match_sysattr(enumerator, device))
+                if (!device_match_sysattr(device, enumerator->match_sysattr, enumerator->nomatch_sysattr))
                         continue;
 
                 k = device_enumerator_add_device(enumerator, device);
@@ -596,13 +546,13 @@ static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const c
                 if (!match_sysname(enumerator, sysname))
                         continue;
 
-                if (!match_parent(enumerator, device))
+                if (!device_match_parent(device, enumerator->match_parent, NULL))
                         continue;
 
                 if (!match_property(enumerator, device))
                         continue;
 
-                if (!match_sysattr(enumerator, device))
+                if (!device_match_sysattr(device, enumerator->match_sysattr, enumerator->nomatch_sysattr))
                         continue;
 
                 k = device_enumerator_add_device(enumerator, device);
@@ -663,7 +613,7 @@ static int parent_add_child(sd_device_enumerator *enumerator, const char *path)
         if (!match_property(enumerator, device))
                 return 0;
 
-        if (!match_sysattr(enumerator, device))
+        if (!device_match_sysattr(device, enumerator->match_sysattr, enumerator->nomatch_sysattr))
                 return 0;
 
         r = device_enumerator_add_device(enumerator, device);
index c1a81e3b41a1119d92921875f4d3fd6f3e93d1cf..9844608157976fda5d86f5d809dc7f84bd1bdbb4 100644 (file)
@@ -67,9 +67,9 @@ struct sd_device {
         char *driver_subsystem; /* only set for the 'drivers' subsystem */
         char *driver;
 
-        char *id_filename;
+        char *device_id;
 
-        uint64_t usec_initialized;
+        usec_t usec_initialized;
 
         mode_t devmode;
         uid_t devuid;
@@ -84,9 +84,7 @@ struct sd_device {
         bool property_tags_outdated:1; /* need to update TAGS= or CURRENT_TAGS= property */
         bool property_devlinks_outdated:1; /* need to update DEVLINKS= property */
         bool properties_buf_outdated:1; /* need to reread hashmap */
-        bool sysname_set:1; /* don't reread sysname */
         bool subsystem_set:1; /* don't reread subsystem */
-        bool driver_subsystem_set:1; /* don't reread subsystem */
         bool driver_set:1; /* don't reread driver */
         bool uevent_loaded:1; /* don't reread uevent */
         bool db_loaded; /* don't reread db */
index 203106ab44929546f2f5404761d923a15aeb0a4d..b485e3e2b632aba145bd654b28b0316bcabaa307 100644 (file)
@@ -37,6 +37,10 @@ struct sd_device_monitor {
 
         Hashmap *subsystem_filter;
         Set *tag_filter;
+        Hashmap *match_sysattr_filter;
+        Hashmap *nomatch_sysattr_filter;
+        Set *match_parent_filter;
+        Set *nomatch_parent_filter;
         bool filter_uptodate;
 
         sd_event *event;
@@ -83,8 +87,8 @@ static int monitor_set_nl_address(sd_device_monitor *m) {
 }
 
 int device_monitor_allow_unicast_sender(sd_device_monitor *m, sd_device_monitor *sender) {
-        assert_return(m, -EINVAL);
-        assert_return(sender, -EINVAL);
+        assert(m);
+        assert(sender);
 
         m->snl_trusted_sender.nl.nl_pid = sender->snl.nl.nl_pid;
         return 0;
@@ -104,7 +108,7 @@ int device_monitor_disconnect(sd_device_monitor *m) {
 }
 
 int device_monitor_get_fd(sd_device_monitor *m) {
-        assert_return(m, -EINVAL);
+        assert(m);
 
         return m->sock;
 }
@@ -114,8 +118,8 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group,
         _cleanup_close_ int sock = -1;
         int r;
 
+        assert(group >= 0 && group < _MONITOR_NETLINK_GROUP_MAX);
         assert_return(ret, -EINVAL);
-        assert_return(group >= 0 && group < _MONITOR_NETLINK_GROUP_MAX, -EINVAL);
 
         if (group == MONITOR_GROUP_UDEV &&
             access("/run/udev/control", F_OK) < 0 &&
@@ -304,7 +308,7 @@ _public_ sd_event_source *sd_device_monitor_get_event_source(sd_device_monitor *
 int device_monitor_enable_receiving(sd_device_monitor *m) {
         int r;
 
-        assert_return(m, -EINVAL);
+        assert(m);
 
         r = sd_device_monitor_filter_update(m);
         if (r < 0)
@@ -334,57 +338,80 @@ static sd_device_monitor *device_monitor_free(sd_device_monitor *m) {
 
         (void) sd_device_monitor_detach_event(m);
 
-        hashmap_free_free_free(m->subsystem_filter);
-        set_free_free(m->tag_filter);
+        hashmap_free(m->subsystem_filter);
+        set_free(m->tag_filter);
+        hashmap_free(m->match_sysattr_filter);
+        hashmap_free(m->nomatch_sysattr_filter);
+        set_free(m->match_parent_filter);
+        set_free(m->nomatch_parent_filter);
 
         return mfree(m);
 }
 
 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device_monitor, sd_device_monitor, device_monitor_free);
 
-static int passes_filter(sd_device_monitor *m, sd_device *device) {
-        const char *tag, *subsystem, *devtype, *s, *d = NULL;
+static int check_subsystem_filter(sd_device_monitor *m, sd_device *device) {
+        const char *s, *subsystem, *d, *devtype = NULL;
         int r;
 
-        assert_return(m, -EINVAL);
-        assert_return(device, -EINVAL);
+        assert(m);
+        assert(device);
 
         if (hashmap_isempty(m->subsystem_filter))
-                goto tag;
+                return true;
 
-        r = sd_device_get_subsystem(device, &s);
+        r = sd_device_get_subsystem(device, &subsystem);
         if (r < 0)
                 return r;
 
-        r = sd_device_get_devtype(device, &d);
+        r = sd_device_get_devtype(device, &devtype);
         if (r < 0 && r != -ENOENT)
                 return r;
 
-        HASHMAP_FOREACH_KEY(devtype, subsystem, m->subsystem_filter) {
+        HASHMAP_FOREACH_KEY(d, s, m->subsystem_filter) {
                 if (!streq(s, subsystem))
                         continue;
 
-                if (!devtype)
-                        goto tag;
+                if (!d || streq_ptr(d, devtype))
+                        return true;
+        }
 
-                if (!d)
-                        continue;
+        return false;
+}
 
-                if (streq(d, devtype))
-                        goto tag;
-        }
+static bool check_tag_filter(sd_device_monitor *m, sd_device *device) {
+        const char *tag;
 
-        return 0;
+        assert(m);
+        assert(device);
 
-tag:
         if (set_isempty(m->tag_filter))
-                return 1;
+                return true;
 
         SET_FOREACH(tag, m->tag_filter)
                 if (sd_device_has_tag(device, tag) > 0)
-                        return 1;
+                        return true;
 
-        return 0;
+        return false;
+}
+
+static int passes_filter(sd_device_monitor *m, sd_device *device) {
+        int r;
+
+        assert(m);
+        assert(device);
+
+        r = check_subsystem_filter(m, device);
+        if (r <= 0)
+                return r;
+
+        if (!check_tag_filter(m, device))
+                return false;
+
+        if (!device_match_sysattr(device, m->match_sysattr_filter, m->nomatch_sysattr_filter))
+                return false;
+
+        return device_match_parent(device, m->match_parent_filter, m->nomatch_parent_filter);
 }
 
 int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) {
@@ -413,6 +440,7 @@ int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) {
         bool is_initialized = false;
         int r;
 
+        assert(m);
         assert(ret);
 
         buflen = recvmsg(m->sock, &smsg, 0);
@@ -507,10 +535,10 @@ static uint64_t string_bloom64(const char *str) {
         uint64_t bits = 0;
         uint32_t hash = string_hash32(str);
 
-        bits |= 1LLU << (hash & 63);
-        bits |= 1LLU << ((hash >> 6) & 63);
-        bits |= 1LLU << ((hash >> 12) & 63);
-        bits |= 1LLU << ((hash >> 18) & 63);
+        bits |= UINT64_C(1) << (hash & 63);
+        bits |= UINT64_C(1) << ((hash >> 6) & 63);
+        bits |= UINT64_C(1) << ((hash >> 12) & 63);
+        bits |= UINT64_C(1) << ((hash >> 18) & 63);
         return bits;
 }
 
@@ -717,51 +745,82 @@ _public_ int sd_device_monitor_filter_update(sd_device_monitor *m) {
 }
 
 _public_ int sd_device_monitor_filter_add_match_subsystem_devtype(sd_device_monitor *m, const char *subsystem, const char *devtype) {
-        _cleanup_free_ char *s = NULL, *d = NULL;
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(subsystem, -EINVAL);
 
-        s = strdup(subsystem);
-        if (!s)
-                return -ENOMEM;
-
-        if (devtype) {
-                d = strdup(devtype);
-                if (!d)
-                        return -ENOMEM;
-        }
-
-        r = hashmap_ensure_put(&m->subsystem_filter, NULL, s, d);
-        if (r < 0)
+        /* Do not use string_has_ops_free_free or hashmap_put_strdup() here, as this may be called
+         * multiple times with the same subsystem but different devtypes. */
+        r = hashmap_put_strdup_full(&m->subsystem_filter, &trivial_hash_ops_free_free, subsystem, devtype);
+        if (r <= 0)
                 return r;
 
-        TAKE_PTR(s);
-        TAKE_PTR(d);
-
         m->filter_uptodate = false;
-
-        return 0;
+        return r;
 }
 
 _public_ int sd_device_monitor_filter_add_match_tag(sd_device_monitor *m, const char *tag) {
+        int r;
+
         assert_return(m, -EINVAL);
         assert_return(tag, -EINVAL);
 
-        int r = set_put_strdup(&m->tag_filter, tag);
-        if (r > 0)
-                m->filter_uptodate = false;
+        r = set_put_strdup(&m->tag_filter, tag);
+        if (r <= 0)
+                return r;
+
+        m->filter_uptodate = false;
         return r;
 }
 
+_public_ int sd_device_monitor_filter_add_match_sysattr(sd_device_monitor *m, const char *sysattr, const char *value, int match) {
+        Hashmap **hashmap;
+
+        assert_return(m, -EINVAL);
+        assert_return(sysattr, -EINVAL);
+
+        if (match)
+                hashmap = &m->match_sysattr_filter;
+        else
+                hashmap = &m->nomatch_sysattr_filter;
+
+        /* TODO: unset m->filter_uptodate on success when we support this filter on BPF. */
+        return hashmap_put_strdup_full(hashmap, &trivial_hash_ops_free_free, sysattr, value);
+}
+
+_public_ int sd_device_monitor_filter_add_match_parent(sd_device_monitor *m, sd_device *device, int match) {
+        const char *syspath;
+        Set **set;
+        int r;
+
+        assert_return(m, -EINVAL);
+        assert_return(device, -EINVAL);
+
+        r = sd_device_get_syspath(device, &syspath);
+        if (r < 0)
+                return r;
+
+        if (match)
+                set = &m->match_parent_filter;
+        else
+                set = &m->nomatch_parent_filter;
+
+        /* TODO: unset m->filter_uptodate on success when we support this filter on BPF. */
+        return set_put_strdup(set, syspath);
+}
+
 _public_ int sd_device_monitor_filter_remove(sd_device_monitor *m) {
         static const struct sock_fprog filter = { 0, NULL };
 
         assert_return(m, -EINVAL);
 
-        m->subsystem_filter = hashmap_free_free_free(m->subsystem_filter);
-        m->tag_filter = set_free_free(m->tag_filter);
+        m->subsystem_filter = hashmap_free(m->subsystem_filter);
+        m->tag_filter = set_free(m->tag_filter);
+        m->match_sysattr_filter = hashmap_free(m->match_sysattr_filter);
+        m->nomatch_sysattr_filter = hashmap_free(m->nomatch_sysattr_filter);
+        m->match_parent_filter = set_free(m->match_parent_filter);
+        m->nomatch_parent_filter = set_free(m->nomatch_parent_filter);
 
         if (setsockopt(m->sock, SOL_SOCKET, SO_DETACH_FILTER, &filter, sizeof(filter)) < 0)
                 return -errno;
index 7a7204b145b4397a47ce3fdf48be00baeffe7c50..e612dbe0a072ef5d8597487c529d3bd9ea63a650 100644 (file)
@@ -20,6 +20,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "set.h"
+#include "stdio-util.h"
 #include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
@@ -568,28 +569,142 @@ int device_get_devlink_priority(sd_device *device, int *priority) {
         return 0;
 }
 
-int device_get_watch_handle(sd_device *device, int *handle) {
+int device_get_watch_handle(sd_device *device) {
+        char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
+        _cleanup_free_ char *buf = NULL;
+        const char *id, *path_id;
+        int wd, r;
+
+        assert(device);
+
+        if (device->watch_handle >= 0)
+                return device->watch_handle;
+
+        r = device_get_device_id(device, &id);
+        if (r < 0)
+                return r;
+
+        path_id = strjoina("/run/udev/watch/", id);
+        r = readlink_malloc(path_id, &buf);
+        if (r < 0)
+                return r;
+
+        r = safe_atoi(buf, &wd);
+        if (r < 0)
+                return r;
+
+        if (wd < 0)
+                return -EBADF;
+
+        buf = mfree(buf);
+        xsprintf(path_wd, "/run/udev/watch/%d", wd);
+        r = readlink_malloc(path_wd, &buf);
+        if (r < 0)
+                return r;
+
+        if (!streq(buf, id))
+                return -EBADF;
+
+        return device->watch_handle = wd;
+}
+
+static void device_remove_watch_handle(sd_device *device) {
+        const char *id;
+        int wd;
+
+        assert(device);
+
+        /* First, remove the symlink from handle to device id. */
+        wd = device_get_watch_handle(device);
+        if (wd >= 0) {
+                char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
+
+                xsprintf(path_wd, "/run/udev/watch/%d", wd);
+                if (unlink(path_wd) < 0 && errno != ENOENT)
+                        log_device_debug_errno(device, errno,
+                                               "sd-device: failed to remove %s, ignoring: %m",
+                                               path_wd);
+        }
+
+        /* Next, remove the symlink from device id to handle. */
+        if (device_get_device_id(device, &id) >= 0) {
+                const char *path_id;
+
+                path_id = strjoina("/run/udev/watch/", id);
+                if (unlink(path_id) < 0 && errno != ENOENT)
+                        log_device_debug_errno(device, errno,
+                                               "sd-device: failed to remove %s, ignoring: %m",
+                                               path_id);
+        }
+
+        device->watch_handle = -1;
+}
+
+int device_set_watch_handle(sd_device *device, int wd) {
+        char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
+        const char *id, *path_id;
         int r;
 
         assert(device);
 
-        r = device_read_db(device);
+        if (wd >= 0 && wd == device->watch_handle)
+                return 0;
+
+        device_remove_watch_handle(device);
+
+        if (wd < 0)
+                /* negative wd means that the caller requests to clear saved watch handle. */
+                return 0;
+
+        r = device_get_device_id(device, &id);
         if (r < 0)
                 return r;
 
-        if (device->watch_handle < 0)
-                return -ENOENT;
+        path_id = strjoina("/run/udev/watch/", id);
+        xsprintf(path_wd, "/run/udev/watch/%d", wd);
 
-        if (handle)
-                *handle = device->watch_handle;
+        r = mkdir_parents(path_wd, 0755);
+        if (r < 0)
+                return r;
+
+        if (symlink(id, path_wd) < 0)
+                return -errno;
+
+        if (symlink(path_wd + STRLEN("/run/udev/watch/"), path_id) < 0) {
+                r = -errno;
+                if (unlink(path_wd) < 0 && errno != ENOENT)
+                        log_device_debug_errno(device, errno,
+                                               "sd-device: failed to remove %s, ignoring: %m",
+                                               path_wd);
+                return r;
+        }
+
+        device->watch_handle = wd;
 
         return 0;
 }
 
-void device_set_watch_handle(sd_device *device, int handle) {
-        assert(device);
+int device_new_from_watch_handle_at(sd_device **ret, int dirfd, int wd) {
+        char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
+        _cleanup_free_ char *id = NULL;
+        int r;
+
+        assert(ret);
+
+        if (wd < 0)
+                return -EBADF;
 
-        device->watch_handle = handle;
+        if (dirfd >= 0) {
+                xsprintf(path_wd, "%d", wd);
+                r = readlinkat_malloc(dirfd, path_wd, &id);
+        } else {
+                xsprintf(path_wd, "/run/udev/watch/%d", wd);
+                r = readlink_malloc(path_wd, &id);
+        }
+        if (r < 0)
+                return r;
+
+        return sd_device_new_from_device_id(ret, id);
 }
 
 int device_rename(sd_device *device, const char *name) {
@@ -761,7 +876,7 @@ static int device_tag(sd_device *device, const char *tag, bool add) {
         assert(device);
         assert(tag);
 
-        r = device_get_id_filename(device, &id);
+        r = device_get_device_id(device, &id);
         if (r < 0)
                 return r;
 
@@ -822,9 +937,6 @@ static bool device_has_info(sd_device *device) {
         if (!set_isempty(device->current_tags))
                 return true;
 
-        if (device->watch_handle >= 0)
-                return true;
-
         return false;
 }
 
@@ -846,7 +958,7 @@ int device_update_db(sd_device *device) {
 
         has_info = device_has_info(device);
 
-        r = device_get_id_filename(device, &id);
+        r = device_get_device_id(device, &id);
         if (r < 0)
                 return r;
 
@@ -899,9 +1011,6 @@ int device_update_db(sd_device *device) {
 
                         if (device->devlink_priority != 0)
                                 fprintf(f, "L:%i\n", device->devlink_priority);
-
-                        if (device->watch_handle >= 0)
-                                fprintf(f, "W:%i\n", device->watch_handle);
                 }
 
                 if (device->usec_initialized > 0)
@@ -950,7 +1059,7 @@ int device_delete_db(sd_device *device) {
 
         assert(device);
 
-        r = device_get_id_filename(device, &id);
+        r = device_get_device_id(device, &id);
         if (r < 0)
                 return r;
 
index ec76f772e5ff5386c2a3b3f354d2a93dcc4d1f14..fe268d7f2f8a58581656adf34366e177fadeee38 100644 (file)
 
 int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len);
 int device_new_from_strv(sd_device **ret, char **strv);
+int device_new_from_watch_handle_at(sd_device **ret, int dirfd, int wd);
+static inline int device_new_from_watch_handle(sd_device **ret, int wd) {
+        return device_new_from_watch_handle_at(ret, -1, wd);
+}
 
-int device_get_id_filename(sd_device *device, const char **ret);
+int device_get_device_id(sd_device *device, const char **ret);
 
 int device_get_devlink_priority(sd_device *device, int *priority);
-int device_get_watch_handle(sd_device *device, int *handle);
+int device_get_watch_handle(sd_device *device);
 int device_get_devnode_mode(sd_device *device, mode_t *mode);
 int device_get_devnode_uid(sd_device *device, uid_t *uid);
 int device_get_devnode_gid(sd_device *device, gid_t *gid);
 
 void device_seal(sd_device *device);
 void device_set_is_initialized(sd_device *device);
-void device_set_watch_handle(sd_device *device, int fd);
+int device_set_watch_handle(sd_device *device, int wd);
 void device_set_db_persist(sd_device *device);
 void device_set_devlink_priority(sd_device *device, int priority);
 int device_ensure_usec_initialized(sd_device *device, sd_device *device_old);
diff --git a/src/libsystemd/sd-device/device-util.c b/src/libsystemd/sd-device/device-util.c
new file mode 100644 (file)
index 0000000..616c16c
--- /dev/null
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <fnmatch.h>
+
+#include "device-util.h"
+#include "path-util.h"
+
+static bool device_match_sysattr_value(sd_device *device, const char *sysattr, const char *match_value) {
+        const char *value;
+
+        assert(device);
+        assert(sysattr);
+
+        if (sd_device_get_sysattr_value(device, sysattr, &value) < 0)
+                return false;
+
+        if (!match_value)
+                return true;
+
+        if (fnmatch(match_value, value, 0) == 0)
+                return true;
+
+        return false;
+}
+
+bool device_match_sysattr(sd_device *device, Hashmap *match_sysattr, Hashmap *nomatch_sysattr) {
+        const char *sysattr;
+        const char *value;
+
+        assert(device);
+
+        HASHMAP_FOREACH_KEY(value, sysattr, match_sysattr)
+                if (!device_match_sysattr_value(device, sysattr, value))
+                        return false;
+
+        HASHMAP_FOREACH_KEY(value, sysattr, nomatch_sysattr)
+                if (device_match_sysattr_value(device, sysattr, value))
+                        return false;
+
+        return true;
+}
+
+bool device_match_parent(sd_device *device, Set *match_parent, Set *nomatch_parent) {
+        const char *syspath_parent, *syspath;
+
+        assert(device);
+
+        if (sd_device_get_syspath(device, &syspath) < 0)
+                return false;
+
+        SET_FOREACH(syspath_parent, nomatch_parent)
+                if (path_startswith(syspath, syspath_parent))
+                        return false;
+
+        if (set_isempty(match_parent))
+                return true;
+
+        SET_FOREACH(syspath_parent, match_parent)
+                if (path_startswith(syspath, syspath_parent))
+                        return true;
+
+        return false;
+}
index 122620953a3aee9ddeb4fbb081807989ba902d36..e2adfe8132f2aeaf9caf7b85bb046b45a11fb73c 100644 (file)
@@ -1,6 +1,15 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include <stdbool.h>
+
+#include "sd-device.h"
+
+#include "hashmap.h"
+#include "log.h"
+#include "macro.h"
+#include "set.h"
+
 #define FOREACH_DEVICE_PROPERTY(device, key, value)                \
         for (key = sd_device_get_property_first(device, &(value)); \
              key;                                                  \
              device;                                                        \
              device = sd_device_enumerator_get_subsystem_next(enumerator))
 
-#define log_device_full_errno(device, level, error, ...)                \
+#define log_device_full_errno_zerook(device, level, error, ...)         \
         ({                                                              \
                 const char *_sysname = NULL;                            \
                 sd_device *_d = (device);                               \
-                int _level = (level), _error = (error);                 \
+                int _level = (level), _e = (error);                     \
                                                                         \
                 if (_d && _unlikely_(log_get_max_level() >= LOG_PRI(_level))) \
                         (void) sd_device_get_sysname(_d, &_sysname);    \
-                log_object_internal(_level, _error, PROJECT_FILE, __LINE__, __func__, \
+                log_object_internal(_level, _e, PROJECT_FILE, __LINE__, __func__, \
                                     _sysname ? "DEVICE=" : NULL, _sysname, \
                                     NULL, NULL, __VA_ARGS__);           \
         })
 
-#define log_device_full(device, level, ...) (void) log_device_full_errno(device, level, 0, __VA_ARGS__)
+#define log_device_full_errno(device, level, error, ...)                \
+        ({                                                              \
+                int _error = (error);                                   \
+                ASSERT_NON_ZERO(_error);                                \
+                log_device_full_errno_zerook(device, level, _error, __VA_ARGS__); \
+        })
 
-#define log_device_debug(device, ...)   log_device_full_errno(device, LOG_DEBUG, 0, __VA_ARGS__)
+#define log_device_full(device, level, ...) (void) log_device_full_errno_zerook(device, level, 0, __VA_ARGS__)
+
+#define log_device_debug(device, ...)   log_device_full(device, LOG_DEBUG, __VA_ARGS__)
 #define log_device_info(device, ...)    log_device_full(device, LOG_INFO, __VA_ARGS__)
 #define log_device_notice(device, ...)  log_device_full(device, LOG_NOTICE, __VA_ARGS__)
 #define log_device_warning(device, ...) log_device_full(device, LOG_WARNING, __VA_ARGS__)
@@ -62,3 +78,6 @@
 #define log_device_notice_errno(device, error, ...)  log_device_full_errno(device, LOG_NOTICE, error, __VA_ARGS__)
 #define log_device_warning_errno(device, error, ...) log_device_full_errno(device, LOG_WARNING, error, __VA_ARGS__)
 #define log_device_error_errno(device, error, ...)   log_device_full_errno(device, LOG_ERR, error, __VA_ARGS__)
+
+bool device_match_sysattr(sd_device *device, Hashmap *match_sysattr, Hashmap *nomatch_sysattr);
+bool device_match_parent(sd_device *device, Set *match_parent, Set *nomatch_parent);
index e556a6f838ca9237913c5b747296c8b8d0ae40d7..d0cba5b86009f07239f52d39041bfa902965a6d9 100644 (file)
@@ -62,7 +62,7 @@ static sd_device *device_free(sd_device *device) {
         free(device->subsystem);
         free(device->driver_subsystem);
         free(device->driver);
-        free(device->id_filename);
+        free(device->device_id);
         free(device->properties_strv);
         free(device->properties_nulstr);
 
@@ -178,13 +178,12 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
 
                         /* all 'devices' require an 'uevent' file */
                         path = strjoina(syspath, "/uevent");
-                        r = access(path, F_OK);
-                        if (r < 0) {
+                        if (access(path, F_OK) < 0) {
                                 if (errno == ENOENT)
                                         /* this is not a valid device */
                                         return -ENODEV;
 
-                                return log_debug_errno(errno, "sd-device: %s does not have an uevent file: %m", syspath);
+                                return log_debug_errno(errno, "sd-device: cannot access uevent file for %s: %m", syspath);
                         }
                 } else {
                         /* everything else just needs to be a directory */
@@ -246,72 +245,69 @@ _public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum)
 }
 
 _public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, const char *sysname) {
-        char *name, *syspath;
-        size_t len = 0;
+        char syspath[PATH_MAX], *name;
 
         assert_return(ret, -EINVAL);
         assert_return(subsystem, -EINVAL);
         assert_return(sysname, -EINVAL);
+        assert_return(strlen(sysname) < PATH_MAX - strlen("/sys/bus/"), -ENAMETOOLONG);
 
         if (streq(subsystem, "subsystem")) {
-                syspath = strjoina("/sys/subsystem/", sysname);
-                if (access(syspath, F_OK) >= 0)
+                if (snprintf_ok(syspath, sizeof syspath, "/sys/subsystem/%s", sysname) &&
+                    access(syspath, F_OK) >= 0)
                         return sd_device_new_from_syspath(ret, syspath);
 
-                syspath = strjoina("/sys/bus/", sysname);
-                if (access(syspath, F_OK) >= 0)
+                if (snprintf_ok(syspath, sizeof syspath, "/sys/bus/%s", sysname) &&
+                    access(syspath, F_OK) >= 0)
                         return sd_device_new_from_syspath(ret, syspath);
 
-                syspath = strjoina("/sys/class/", sysname);
-                if (access(syspath, F_OK) >= 0)
+                if (snprintf_ok(syspath, sizeof syspath, "/sys/class/%s", sysname) &&
+                    access(syspath, F_OK) >= 0)
                         return sd_device_new_from_syspath(ret, syspath);
+
         } else  if (streq(subsystem, "module")) {
-                syspath = strjoina("/sys/module/", sysname);
-                if (access(syspath, F_OK) >= 0)
+                if (snprintf_ok(syspath, sizeof syspath, "/sys/module/%s", sysname) &&
+                    access(syspath, F_OK) >= 0)
                         return sd_device_new_from_syspath(ret, syspath);
+
         } else if (streq(subsystem, "drivers")) {
-                char subsys[PATH_MAX];
-                char *driver;
+                const char *subsys, *sep;
 
-                strscpy(subsys, sizeof(subsys), sysname);
-                driver = strchr(subsys, ':');
-                if (driver) {
-                        driver[0] = '\0';
-                        driver++;
+                sep = strchr(sysname, ':');
+                if (sep && sep[1] != '\0') { /* Require ":" and something non-empty after that. */
+                        subsys = memdupa_suffix0(sysname, sep - sysname);
 
-                        syspath = strjoina("/sys/subsystem/", subsys, "/drivers/", driver);
-                        if (access(syspath, F_OK) >= 0)
+                        if (snprintf_ok(syspath, sizeof syspath, "/sys/subsystem/%s/drivers/%s", subsys, sep + 1) &&
+                            access(syspath, F_OK) >= 0)
                                 return sd_device_new_from_syspath(ret, syspath);
 
-                        syspath = strjoina("/sys/bus/", subsys, "/drivers/", driver);
-                        if (access(syspath, F_OK) >= 0)
+                        if (snprintf_ok(syspath, sizeof syspath, "/sys/bus/%s/drivers/%s", subsys, sep + 1) &&
+                            access(syspath, F_OK) >= 0)
                                 return sd_device_new_from_syspath(ret, syspath);
                 }
         }
 
         /* translate sysname back to sysfs filename */
         name = strdupa(sysname);
-        while (name[len] != '\0') {
-                if (name[len] == '/')
-                        name[len] = '!';
 
-                len++;
-        }
+        for (size_t i = 0; name[i]; i++)
+                if (name[i] == '/')
+                        name[i] = '!';
 
-        syspath = strjoina("/sys/subsystem/", subsystem, "/devices/", name);
-        if (access(syspath, F_OK) >= 0)
+        if (snprintf_ok(syspath, sizeof syspath, "/sys/subsystem/%s/devices/%s", subsystem, name) &&
+            access(syspath, F_OK) >= 0)
                 return sd_device_new_from_syspath(ret, syspath);
 
-        syspath = strjoina("/sys/bus/", subsystem, "/devices/", name);
-        if (access(syspath, F_OK) >= 0)
+        if (snprintf_ok(syspath, sizeof syspath, "/sys/bus/%s/devices/%s", subsystem, name) &&
+            access(syspath, F_OK) >= 0)
                 return sd_device_new_from_syspath(ret, syspath);
 
-        syspath = strjoina("/sys/class/", subsystem, "/", name);
-        if (access(syspath, F_OK) >= 0)
+        if (snprintf_ok(syspath, sizeof syspath, "/sys/class/%s/%s", subsystem, name) &&
+            access(syspath, F_OK) >= 0)
                 return sd_device_new_from_syspath(ret, syspath);
 
-        syspath = strjoina("/sys/firmware/", subsystem, "/", sysname);
-        if (access(syspath, F_OK) >= 0)
+        if (snprintf_ok(syspath, sizeof syspath, "/sys/firmware/%s/%s", subsystem, sysname) &&
+            access(syspath, F_OK) >= 0)
                 return sd_device_new_from_syspath(ret, syspath);
 
         return -ENODEV;
@@ -491,7 +487,6 @@ int device_read_uevent_file(sd_device *device) {
         const char *syspath, *key = NULL, *value = NULL, *major = NULL, *minor = NULL;
         char *path;
         size_t uevent_len;
-        unsigned i;
         int r;
 
         enum {
@@ -527,7 +522,7 @@ int device_read_uevent_file(sd_device *device) {
 
         device->uevent_loaded = true;
 
-        for (i = 0; i < uevent_len; i++)
+        for (size_t i = 0; i < uevent_len; i++)
                 switch (state) {
                 case PRE_KEY:
                         if (!strchr(NEWLINE, uevent[i])) {
@@ -625,7 +620,7 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
                 struct ifreq ifr = {};
                 int ifindex;
 
-                r = ifr.ifr_ifindex = parse_ifindex(&id[1]);
+                r = ifr.ifr_ifindex = parse_ifindex(id + 1);
                 if (r < 0)
                         return r;
 
@@ -654,18 +649,15 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
         }
 
         case '+': {
-                char subsys[PATH_MAX];
-                char *sysname;
+                const char *subsys, *sep;
 
-                (void) strscpy(subsys, sizeof(subsys), id + 1);
-                sysname = strchr(subsys, ':');
-                if (!sysname)
+                sep = strchr(id + 1, ':');
+                if (!sep || sep - id - 1 > NAME_MAX)
                         return -EINVAL;
 
-                sysname[0] = '\0';
-                sysname++;
+                subsys = memdupa_suffix0(id + 1, sep - id - 1);
 
-                return sd_device_new_from_subsystem_sysname(ret, subsys, sysname);
+                return sd_device_new_from_subsystem_sysname(ret, subsys, sep + 1);
         }
 
         default:
@@ -706,7 +698,7 @@ static int device_new_from_child(sd_device **ret, sd_device *child) {
 
                 pos = strrchr(subdir, '/');
                 if (!pos || pos < subdir + 2)
-                        break;
+                        return -ENODEV;
 
                 *pos = '\0';
 
@@ -716,8 +708,6 @@ static int device_new_from_child(sd_device **ret, sd_device *child) {
 
                 return 0;
         }
-
-        return -ENODEV;
 }
 
 _public_ int sd_device_get_parent(sd_device *child, sd_device **ret) {
@@ -756,15 +746,34 @@ int device_set_subsystem(sd_device *device, const char *_subsystem) {
         return free_and_replace(device->subsystem, subsystem);
 }
 
-static int device_set_drivers_subsystem(sd_device *device, const char *_subsystem) {
+static int device_set_drivers_subsystem(sd_device *device) {
         _cleanup_free_ char *subsystem = NULL;
+        const char *syspath, *drivers, *p;
         int r;
 
         assert(device);
-        assert(_subsystem);
-        assert(*_subsystem);
 
-        subsystem = strdup(_subsystem);
+        r = sd_device_get_syspath(device, &syspath);
+        if (r < 0)
+                return r;
+
+        drivers = strstr(syspath, "/drivers/");
+        if (!drivers)
+                return -EINVAL;
+
+        for (p = drivers - 1; p >= syspath; p--)
+                if (*p == '/')
+                        break;
+
+        if (p <= syspath)
+                /* syspath does not start with /sys/ ?? */
+                return -EINVAL;
+        p++;
+        if (p >= drivers)
+                /* refuse duplicated slashes */
+                return -EINVAL;
+
+        subsystem = strndup(p, drivers - p);
         if (!subsystem)
                 return -ENOMEM;
 
@@ -776,60 +785,46 @@ static int device_set_drivers_subsystem(sd_device *device, const char *_subsyste
 }
 
 _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
-        const char *syspath, *drivers = NULL;
         int r;
 
         assert_return(device, -EINVAL);
 
-        r = sd_device_get_syspath(device, &syspath);
-        if (r < 0)
-                return r;
-
         if (!device->subsystem_set) {
                 _cleanup_free_ char *subsystem = NULL;
+                const char *syspath;
                 char *path;
 
+                r = sd_device_get_syspath(device, &syspath);
+                if (r < 0)
+                        return r;
+
                 /* read 'subsystem' link */
                 path = strjoina(syspath, "/subsystem");
                 r = readlink_value(path, &subsystem);
-                if (r >= 0)
+                if (r < 0 && r != -ENOENT)
+                        return log_device_debug_errno(device, r,
+                                                      "sd-device: Failed to read subsystem for %s: %m",
+                                                      device->devpath);
+
+                if (subsystem)
                         r = device_set_subsystem(device, subsystem);
                 /* use implicit names */
                 else if (path_startswith(device->devpath, "/module/"))
                         r = device_set_subsystem(device, "module");
-                else if (!(drivers = strstr(syspath, "/drivers/")) &&
-                         PATH_STARTSWITH_SET(device->devpath, "/subsystem/",
+                else if (strstr(syspath, "/drivers/"))
+                        r = device_set_drivers_subsystem(device);
+                else if (PATH_STARTSWITH_SET(device->devpath, "/subsystem/",
                                                               "/class/",
                                                               "/bus/"))
                         r = device_set_subsystem(device, "subsystem");
-                if (r < 0 && r != -ENOENT)
-                        return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem for %s: %m", device->devpath);
-
-                device->subsystem_set = true;
-        } else if (!device->driver_subsystem_set)
-                drivers = strstr(syspath, "/drivers/");
-
-        if (!device->driver_subsystem_set) {
-                if (drivers) {
-                        _cleanup_free_ char *subpath = NULL;
-
-                        subpath = strndup(syspath, drivers - syspath);
-                        if (!subpath)
-                                r = -ENOMEM;
-                        else {
-                                const char *subsys;
-
-                                subsys = strrchr(subpath, '/');
-                                if (!subsys)
-                                        r = -EINVAL;
-                                else
-                                        r = device_set_drivers_subsystem(device, subsys + 1);
-                        }
-                        if (r < 0 && r != -ENOENT)
-                                return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem for driver %s: %m", device->devpath);
+                else {
+                        device->subsystem_set = true;
+                        r = 0;
                 }
-
-                device->driver_subsystem_set = true;
+                if (r < 0)
+                        return log_device_debug_errno(device, r,
+                                                      "sd-device: Failed to set subsystem for %s: %m",
+                                                      device->devpath);
         }
 
         if (!device->subsystem)
@@ -991,7 +986,7 @@ _public_ int sd_device_get_devname(sd_device *device, const char **devname) {
         return 0;
 }
 
-static int device_set_sysname(sd_device *device) {
+static int device_set_sysname_and_sysnum(sd_device *device) {
         _cleanup_free_ char *sysname = NULL;
         const char *sysnum = NULL;
         const char *pos;
@@ -1028,7 +1023,6 @@ static int device_set_sysname(sd_device *device) {
         if (len == 0)
                 sysnum = NULL;
 
-        device->sysname_set = true;
         device->sysnum = sysnum;
         return free_and_replace(device->sysname, sysname);
 }
@@ -1038,14 +1032,12 @@ _public_ int sd_device_get_sysname(sd_device *device, const char **ret) {
 
         assert_return(device, -EINVAL);
 
-        if (!device->sysname_set) {
-                r = device_set_sysname(device);
+        if (!device->sysname) {
+                r = device_set_sysname_and_sysnum(device);
                 if (r < 0)
                         return r;
         }
 
-        assert_return(device->sysname, -ENOENT);
-
         if (ret)
                 *ret = device->sysname;
         return 0;
@@ -1056,8 +1048,8 @@ _public_ int sd_device_get_sysnum(sd_device *device, const char **ret) {
 
         assert_return(device, -EINVAL);
 
-        if (!device->sysname_set) {
-                r = device_set_sysname(device);
+        if (!device->sysname) {
+                r = device_set_sysname_and_sysnum(device);
                 if (r < 0)
                         return r;
         }
@@ -1241,10 +1233,10 @@ static int handle_db_line(sd_device *device, char key, const char *value) {
 
                 break;
         case 'W':
-                r = safe_atoi(value, &device->watch_handle);
-                if (r < 0)
-                        return r;
-
+                /* Deprecated. Previously, watch handle is both saved in database and /run/udev/watch.
+                 * However, the handle saved in database may not be updated when the handle is updated
+                 * or removed. Moreover, it is not necessary to store the handle within the database,
+                 * as its value becomes meaningless when udevd is restarted. */
                 break;
         case 'V':
                 r = safe_atou(value, &device->database_version);
@@ -1259,11 +1251,11 @@ static int handle_db_line(sd_device *device, char key, const char *value) {
         return 0;
 }
 
-int device_get_id_filename(sd_device *device, const char **ret) {
+int device_get_device_id(sd_device *device, const char **ret) {
         assert(device);
         assert(ret);
 
-        if (!device->id_filename) {
+        if (!device->device_id) {
                 _cleanup_free_ char *id = NULL;
                 const char *subsystem;
                 dev_t devnum;
@@ -1300,7 +1292,6 @@ int device_get_id_filename(sd_device *device, const char **ret) {
                         if (!subsystem)
                                 return -EINVAL;
 
-
                         if (streq(subsystem, "drivers"))
                                 /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
                                  * encoded as well */
@@ -1311,17 +1302,20 @@ int device_get_id_filename(sd_device *device, const char **ret) {
                                 return -ENOMEM;
                 }
 
-                device->id_filename = TAKE_PTR(id);
+                if (!filename_is_valid(id))
+                        return -EINVAL;
+
+                device->device_id = TAKE_PTR(id);
         }
 
-        *ret = device->id_filename;
+        *ret = device->device_id;
         return 0;
 }
 
 int device_read_db_internal_filename(sd_device *device, const char *filename) {
         _cleanup_free_ char *db = NULL;
         const char *value;
-        size_t db_len, i;
+        size_t db_len;
         char key;
         int r;
 
@@ -1349,7 +1343,7 @@ int device_read_db_internal_filename(sd_device *device, const char *filename) {
 
         device->db_loaded = true;
 
-        for (i = 0; i < db_len; i++) {
+        for (size_t i = 0; i < db_len; i++) {
                 switch (state) {
                 case PRE_KEY:
                         if (!strchr(NEWLINE, db[i])) {
@@ -1387,7 +1381,8 @@ int device_read_db_internal_filename(sd_device *device, const char *filename) {
                                 db[i] = '\0';
                                 r = handle_db_line(device, key, value);
                                 if (r < 0)
-                                        log_device_debug_errno(device, r, "sd-device: Failed to handle db entry '%c:%s', ignoring: %m", key, value);
+                                        log_device_debug_errno(device, r, "sd-device: Failed to handle db entry '%c:%s', ignoring: %m",
+                                                               key, value);
 
                                 state = PRE_KEY;
                         }
@@ -1410,7 +1405,7 @@ int device_read_db_internal(sd_device *device, bool force) {
         if (device->db_loaded || (!force && device->sealed))
                 return 0;
 
-        r = device_get_id_filename(device, &id);
+        r = device_get_device_id(device, &id);
         if (r < 0)
                 return r;
 
@@ -1431,6 +1426,27 @@ _public_ int sd_device_get_is_initialized(sd_device *device) {
         return device->is_initialized;
 }
 
+_public_ int sd_device_get_usec_initialized(sd_device *device, uint64_t *ret) {
+        int r;
+
+        assert_return(device, -EINVAL);
+
+        r = device_read_db(device);
+        if (r < 0)
+                return r;
+
+        if (!device->is_initialized)
+                return -EBUSY;
+
+        if (device->usec_initialized == 0)
+                return -ENODATA;
+
+        if (ret)
+                *ret = device->usec_initialized;
+
+        return 0;
+}
+
 _public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec) {
         usec_t now_ts;
         int r;
@@ -1444,10 +1460,10 @@ _public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *u
         if (!device->is_initialized)
                 return -EBUSY;
 
-        if (!device->usec_initialized)
+        if (device->usec_initialized == 0)
                 return -ENODATA;
 
-        now_ts = now(clock_boottime_or_monotonic());
+        now_ts = now(CLOCK_MONOTONIC);
 
         if (now_ts < device->usec_initialized)
                 return -EIO;
@@ -1895,10 +1911,11 @@ _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr,
                 return r;
 
         path = prefix_roota(syspath, sysattr);
-        r = lstat(path, &statbuf);
-        if (r < 0) {
+        if (lstat(path, &statbuf) < 0) {
                 int k;
 
+                r = -errno;
+
                 /* remember that we could not access the sysattr */
                 k = device_cache_sysattr_value(device, sysattr, NULL);
                 if (k < 0)
diff --git a/src/libsystemd/sd-device/test-device-util.c b/src/libsystemd/sd-device/test-device-util.c
new file mode 100644 (file)
index 0000000..93fc105
--- /dev/null
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "device-util.h"
+#include "tests.h"
+
+static void test_log_device_full(void) {
+        int r;
+
+        log_info("/* %s */", __func__);
+
+        for (int level = LOG_ERR; level <= LOG_DEBUG; level++) {
+                log_device_full(NULL, level, "test level=%d: %m", level);
+
+                r = log_device_full_errno(NULL, level, EUCLEAN, "test level=%d errno=EUCLEAN: %m", level);
+                assert_se(r == -EUCLEAN);
+
+                r = log_device_full_errno(NULL, level, 0, "test level=%d errno=0: %m", level);
+                assert_se(r == 0);
+
+                r = log_device_full_errno(NULL, level, SYNTHETIC_ERRNO(ENODATA), "test level=%d errno=S(ENODATA): %m", level);
+                assert_se(r == -ENODATA);
+        }
+}
+
+int main(int argc, char **argv) {
+        test_setup_logging(LOG_INFO);
+
+        test_log_device_full();
+        return 0;
+}
index fddd1c152c91b2229f578340d95fefa8ffcee8d3..ae973cdba395aa03e91caac9688868c64d628ad6 100644 (file)
@@ -95,10 +95,10 @@ static void test_send_receive_one(sd_device *device, bool subsystem_filter, bool
 static void test_subsystem_filter(sd_device *device) {
         _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
         _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
-        const char *syspath, *subsystem, *p, *s;
+        const char *syspath, *subsystem;
         sd_device *d;
 
-        log_info("/* %s */", __func__);
+        log_device_info(device, "/* %s */", __func__);
 
         assert_se(sd_device_get_syspath(device, &syspath) >= 0);
         assert_se(sd_device_get_subsystem(device, &subsystem) >= 0);
@@ -116,16 +116,140 @@ static void test_subsystem_filter(sd_device *device) {
         assert_se(sd_device_enumerator_new(&e) >= 0);
         assert_se(sd_device_enumerator_add_match_subsystem(e, subsystem, false) >= 0);
         FOREACH_DEVICE(e, d) {
+                const char *p, *s;
+
                 assert_se(sd_device_get_syspath(d, &p) >= 0);
                 assert_se(sd_device_get_subsystem(d, &s) >= 0);
 
-                log_info("Sending device subsystem:%s syspath:%s", s, p);
+                log_device_debug(d, "Sending device subsystem:%s syspath:%s", s, p);
+                assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0);
+        }
+
+        log_device_info(device, "Sending device subsystem:%s syspath:%s", subsystem, syspath);
+        assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
+        assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100);
+}
+
+static void test_tag_filter(sd_device *device) {
+        _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
+        _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+        const char *syspath;
+        sd_device *d;
+
+        log_device_info(device, "/* %s */", __func__);
+
+        assert_se(sd_device_get_syspath(device, &syspath) >= 0);
+
+        assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
+        assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
+        assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
+
+        assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
+        assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
+        assert_se(sd_device_monitor_filter_add_match_tag(monitor_client, "TEST_SD_DEVICE_MONITOR") >= 0);
+        assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
+        assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
+
+        assert_se(sd_device_enumerator_new(&e) >= 0);
+        FOREACH_DEVICE(e, d) {
+                const char *p;
+
+                assert_se(sd_device_get_syspath(d, &p) >= 0);
+
+                log_device_debug(d, "Sending device syspath:%s", p);
                 assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0);
         }
 
-        log_info("Sending device subsystem:%s syspath:%s", subsystem, syspath);
+        log_device_info(device, "Sending device syspath:%s", syspath);
         assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
         assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100);
+
+}
+
+static void test_sysattr_filter(sd_device *device, const char *sysattr) {
+        _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
+        _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+        const char *syspath, *subsystem, *sysattr_value;
+        sd_device *d;
+
+        log_device_info(device, "/* %s(%s) */", __func__, sysattr);
+
+        assert_se(sd_device_get_syspath(device, &syspath) >= 0);
+        assert_se(sd_device_get_subsystem(device, &subsystem) >= 0);
+        assert_se(sd_device_get_sysattr_value(device, sysattr, &sysattr_value) >= 0);
+
+        assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
+        assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
+        assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
+
+        assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
+        assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
+        /* The sysattr filter is not implemented in BPF yet, so the below device_monito_send_device()
+         * may cause EAGAIN. So, let's also filter devices with subsystem. */
+        assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, NULL) >= 0);
+        assert_se(sd_device_monitor_filter_add_match_sysattr(monitor_client, sysattr, sysattr_value, true) >= 0);
+        assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
+        assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
+
+        assert_se(sd_device_enumerator_new(&e) >= 0);
+        assert_se(sd_device_enumerator_add_match_sysattr(e, sysattr, sysattr_value, false) >= 0);
+        FOREACH_DEVICE(e, d) {
+                const char *p;
+
+                assert_se(sd_device_get_syspath(d, &p) >= 0);
+
+                log_device_debug(d, "Sending device syspath:%s", p);
+                assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0);
+        }
+
+        log_device_info(device, "Sending device syspath:%s", syspath);
+        assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
+        assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100);
+
+}
+
+static void test_parent_filter(sd_device *device) {
+        _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
+        _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+        const char *syspath, *subsystem;
+        sd_device *parent, *d;
+        int r;
+
+        log_device_info(device, "/* %s */", __func__);
+
+        assert_se(sd_device_get_syspath(device, &syspath) >= 0);
+        assert_se(sd_device_get_subsystem(device, &subsystem) >= 0);
+        r = sd_device_get_parent(device, &parent);
+        if (r < 0)
+                return (void) log_device_info(device, "Device does not have parent, skipping.");
+
+        assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
+        assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
+        assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
+
+        assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
+        assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
+        /* The parent filter is not implemented in BPF yet, so the below device_monito_send_device()
+         * may cause EAGAIN. So, let's also filter devices with subsystem. */
+        assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, NULL) >= 0);
+        assert_se(sd_device_monitor_filter_add_match_parent(monitor_client, parent, true) >= 0);
+        assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
+        assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
+
+        assert_se(sd_device_enumerator_new(&e) >= 0);
+        FOREACH_DEVICE(e, d) {
+                const char *p;
+
+                assert_se(sd_device_get_syspath(d, &p) >= 0);
+
+                log_device_debug(d, "Sending device syspath:%s", p);
+                assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0);
+        }
+
+        log_device_info(device, "Sending device syspath:%s", syspath);
+        assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
+        assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100);
+
 }
 
 static void test_sd_device_monitor_filter_remove(sd_device *device) {
@@ -184,6 +308,7 @@ int main(int argc, char *argv[]) {
         assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0);
         assert_se(device_add_property(loopback, "ACTION", "add") >= 0);
         assert_se(device_add_property(loopback, "SEQNUM", "10") >= 0);
+        assert_se(device_add_tag(loopback, "TEST_SD_DEVICE_MONITOR", true) >= 0);
 
         test_send_receive_one(loopback, false, false, false);
         test_send_receive_one(loopback,  true, false, false);
@@ -194,6 +319,8 @@ int main(int argc, char *argv[]) {
         test_send_receive_one(loopback,  true,  true,  true);
 
         test_subsystem_filter(loopback);
+        test_tag_filter(loopback);
+        test_sysattr_filter(loopback, "ifindex");
         test_sd_device_monitor_filter_remove(loopback);
         test_device_copy_properties(loopback);
 
@@ -214,5 +341,7 @@ int main(int argc, char *argv[]) {
         test_send_receive_one(sda, false,  true,  true);
         test_send_receive_one(sda,  true,  true,  true);
 
+        test_parent_filter(sda);
+
         return 0;
 }
index b76b0623fe3562f80f8751ac3a0ec177931dbc3b..172be4e07e855c6f4b8b258ea599b020ed172852 100644 (file)
@@ -3171,7 +3171,7 @@ static int process_child(sd_event *e, int64_t threshold, int64_t *ret_min_priori
                 zero(s->child.siginfo);
                 if (waitid(P_PID, s->child.pid, &s->child.siginfo,
                            WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options) < 0)
-                        return -errno;
+                        return negative_errno();
 
                 if (s->child.siginfo.si_pid != 0) {
                         bool zombie = IN_SET(s->child.siginfo.si_code, CLD_EXITED, CLD_KILLED, CLD_DUMPED);
index a3f6da6381ca980606d84017a41bd165463a638e..2074771a41bfdb209cc4ecbde36815a10367e1ea 100644 (file)
@@ -210,3 +210,25 @@ sd_id128_t id128_make_v4_uuid(sd_id128_t id) {
 }
 
 DEFINE_HASH_OPS(id128_hash_ops, sd_id128_t, id128_hash_func, id128_compare_func);
+
+int id128_get_product(sd_id128_t *ret) {
+        sd_id128_t uuid;
+        int r;
+
+        assert(ret);
+
+        /* Reads the systems product UUID from DMI or devicetree (where it is located on POWER). This is
+         * particularly relevant in VM environments, where VM managers typically place a VM uuid there. */
+
+        r = id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, &uuid);
+        if (r == -ENOENT)
+                r = id128_read("/sys/firmware/devicetree/base/vm,uuid", ID128_UUID, &uuid);
+        if (r < 0)
+                return r;
+
+        if (sd_id128_is_null(uuid) || sd_id128_is_allf(uuid))
+                return -EADDRNOTAVAIL; /* Recognizable error */
+
+        *ret = uuid;
+        return 0;
+}
index 6b09bcd96a44ebccfea1b39d73feed169343b96c..053ef0a6a83f091a9aeddfa32b601d0e53dde0dd 100644 (file)
@@ -36,3 +36,5 @@ int id128_compare_func(const sd_id128_t *a, const sd_id128_t *b) _pure_;
 extern const struct hash_ops id128_hash_ops;
 
 sd_id128_t id128_make_v4_uuid(sd_id128_t id);
+
+int id128_get_product(sd_id128_t *ret);
index bdcf47a25bf4b87abf8e174eeccaf6c52f2563a7..f366a597b5a5b2693a965a8c633ddfe5a9c78228 100644 (file)
@@ -614,14 +614,10 @@ int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
 #if HAVE_LZ4
         LZ4F_errorCode_t c;
         _cleanup_(LZ4F_freeCompressionContextp) LZ4F_compressionContext_t ctx = NULL;
-        _cleanup_free_ char *buf = NULL;
-        char *src = NULL;
-        size_t size, n, total_in = 0, total_out, offset = 0, frame_size;
-        struct stat st;
+        _cleanup_free_ void *in_buff = NULL;
+        _cleanup_free_ char *out_buff = NULL;
+        size_t out_allocsize, n, total_in = 0, total_out, offset = 0, frame_size;
         int r;
-        static const LZ4F_compressOptions_t options = {
-                .stableSrc = 1,
-        };
         static const LZ4F_preferences_t preferences = {
                 .frameInfo.blockSizeID = 5,
         };
@@ -630,74 +626,66 @@ int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
         if (LZ4F_isError(c))
                 return -ENOMEM;
 
-        if (fstat(fdf, &st) < 0)
-                return log_debug_errno(errno, "fstat() failed: %m");
-
         frame_size = LZ4F_compressBound(LZ4_BUFSIZE, &preferences);
-        size =  frame_size + 64*1024; /* add some space for header and trailer */
-        buf = malloc(size);
-        if (!buf)
+        out_allocsize = frame_size + 64*1024; /* add some space for header and trailer */
+        out_buff = malloc(out_allocsize);
+        if (!out_buff)
                 return -ENOMEM;
 
-        n = offset = total_out = LZ4F_compressBegin(ctx, buf, size, &preferences);
+        in_buff = malloc(LZ4_BUFSIZE);
+        if (!in_buff)
+                return -ENOMEM;
+
+        n = offset = total_out = LZ4F_compressBegin(ctx, out_buff, out_allocsize, &preferences);
         if (LZ4F_isError(n))
                 return -EINVAL;
 
-        src = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fdf, 0);
-        if (src == MAP_FAILED)
-                return -errno;
-
-        log_debug("Buffer size is %zu bytes, header size %zu bytes.", size, n);
+        log_debug("Buffer size is %zu bytes, header size %zu bytes.", out_allocsize, n);
 
-        while (total_in < (size_t) st.st_size) {
+        for (;;) {
                 ssize_t k;
 
-                k = MIN(LZ4_BUFSIZE, st.st_size - total_in);
-                n = LZ4F_compressUpdate(ctx, buf + offset, size - offset,
-                                        src + total_in, k, &options);
-                if (LZ4F_isError(n)) {
-                        r = -ENOTRECOVERABLE;
-                        goto cleanup;
-                }
+                k = loop_read(fdf, in_buff, LZ4_BUFSIZE, true);
+                if (k < 0)
+                        return k;
+                if (k == 0)
+                        break;
+                n = LZ4F_compressUpdate(ctx, out_buff + offset, out_allocsize - offset,
+                                        in_buff, k, NULL);
+                if (LZ4F_isError(n))
+                        return -ENOTRECOVERABLE;
 
                 total_in += k;
                 offset += n;
                 total_out += n;
 
-                if (max_bytes != UINT64_MAX && total_out > (size_t) max_bytes) {
-                        r = log_debug_errno(SYNTHETIC_ERRNO(EFBIG),
-                                            "Compressed stream longer than %" PRIu64 " bytes", max_bytes);
-                        goto cleanup;
-                }
+                if (max_bytes != UINT64_MAX && total_out > (size_t) max_bytes)
+                        return log_debug_errno(SYNTHETIC_ERRNO(EFBIG),
+                                               "Compressed stream longer than %" PRIu64 " bytes", max_bytes);
 
-                if (size - offset < frame_size + 4) {
-                        k = loop_write(fdt, buf, offset, false);
-                        if (k < 0) {
-                                r = k;
-                                goto cleanup;
-                        }
+                if (out_allocsize - offset < frame_size + 4) {
+                        k = loop_write(fdt, out_buff, offset, false);
+                        if (k < 0)
+                                return k;
                         offset = 0;
                 }
         }
 
-        n = LZ4F_compressEnd(ctx, buf + offset, size - offset, &options);
-        if (LZ4F_isError(n)) {
-                r = -ENOTRECOVERABLE;
-                goto cleanup;
-        }
+        n = LZ4F_compressEnd(ctx, out_buff + offset, out_allocsize - offset, NULL);
+        if (LZ4F_isError(n))
+                return -ENOTRECOVERABLE;
 
         offset += n;
         total_out += n;
-        r = loop_write(fdt, buf, offset, false);
+        r = loop_write(fdt, out_buff, offset, false);
         if (r < 0)
-                goto cleanup;
+                return r;
 
         log_debug("LZ4 compression finished (%zu -> %zu bytes, %.1f%%)",
                   total_in, total_out,
                   (double) total_out / total_in * 100);
- cleanup:
-        munmap(src, st.st_size);
-        return r;
+
+        return 0;
 #else
         return -EPROTONOSUPPORT;
 #endif
index 7ea72495ef2ed325e4eb20ed90d039508a248544..ab4cef9841c50087147c611f463570c7fc1ff361 100644 (file)
@@ -99,10 +99,12 @@ _pure_ static uint64_t uint64_import(const void *buf, size_t buflen) {
 static void det_randomize(void *buf, size_t buflen, const void *seed, size_t seedlen, uint32_t idx) {
         gcry_md_hd_t hd, hd2;
         size_t olen, cpylen;
+        gcry_error_t err;
         uint32_t ctr;
 
         olen = gcry_md_get_algo_dlen(RND_HASH);
-        gcry_md_open(&hd, RND_HASH, 0);
+        err = gcry_md_open(&hd, RND_HASH, 0);
+        assert_se(gcry_err_code(err) == GPG_ERR_NO_ERROR); /* This shouldn't happen */
         gcry_md_write(hd, seed, seedlen);
         gcry_md_putc(hd, (idx >> 24) & 0xff);
         gcry_md_putc(hd, (idx >> 16) & 0xff);
@@ -110,7 +112,8 @@ static void det_randomize(void *buf, size_t buflen, const void *seed, size_t see
         gcry_md_putc(hd, (idx >>  0) & 0xff);
 
         for (ctr = 0; buflen; ctr++) {
-                gcry_md_copy(&hd2, hd);
+                err = gcry_md_copy(&hd2, hd);
+                assert_se(gcry_err_code(err) == GPG_ERR_NO_ERROR); /* This shouldn't happen */
                 gcry_md_putc(hd2, (ctr >> 24) & 0xff);
                 gcry_md_putc(hd2, (ctr >> 16) & 0xff);
                 gcry_md_putc(hd2, (ctr >>  8) & 0xff);
index d5b145f31d28ea141d4b6fdaa9b7e30123b321bc..aad653c12865532eec102a4fd6d287a1c236fd37 100755 (executable)
@@ -1,16 +1,17 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
+set -o pipefail
 
-cpp="$1"
+cpp="${1:?}"
 shift
 
-includes=""
+includes=()
 for i in "$@"; do
-    includes="$includes -include $i"
+    includes+=(-include "$i")
 done
 
-$cpp -dM $includes - </dev/null | \
-    grep -vE 'AUDIT_.*(FIRST|LAST)_' | \
-    sed -r -n 's/^#define\s+AUDIT_(\w+)\s+([0-9]{4})\s*$$/\1\t\2/p' | \
-    sort -k2
+$cpp -dM "${includes[@]}" - </dev/null | \
+     grep -vE 'AUDIT_.*(FIRST|LAST)_' | \
+     sed -r -n 's/^#define\s+AUDIT_(\w+)\s+([0-9]{4})\s*$$/\1\t\2/p' | \
+     sort -k2
index a5ff987d6ed604244cac240324885a17fff3bb44..0bfe9f7f477e16a0ed577f2161b201b1a0c9bf87 100644 (file)
@@ -65,6 +65,8 @@ int journal_file_append_tag(JournalFile *f) {
 
 int journal_file_hmac_start(JournalFile *f) {
         uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */
+        gcry_error_t err;
+
         assert(f);
 
         if (!f->seal)
@@ -76,7 +78,11 @@ int journal_file_hmac_start(JournalFile *f) {
         /* Prepare HMAC for next cycle */
         gcry_md_reset(f->hmac);
         FSPRG_GetKey(f->fsprg_state, key, sizeof(key), 0);
-        gcry_md_setkey(f->hmac, key, sizeof(key));
+        err = gcry_md_setkey(f->hmac, key, sizeof(key));
+        if (gcry_err_code(err) != GPG_ERR_NO_ERROR)
+                return log_debug_errno(SYNTHETIC_ERRNO(EIO),
+                                       "gcry_md_setkey() failed with error code: %d",
+                                       gcry_err_code(err));
 
         f->hmac_running = true;
 
index f8bb708e582bbbfb5e4bac582708b65b099e02d3..3cf26f8e44353659e0039e38b9b3c73c5db478a4 100644 (file)
@@ -707,9 +707,9 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size)
         /* Note that the glibc fallocate() fallback is very
            inefficient, hence we try to minimize the allocation area
            as we can. */
-        r = posix_fallocate(f->fd, old_size, new_size - old_size);
-        if (r != 0)
-                return -r;
+        r = posix_fallocate_loop(f->fd, old_size, new_size - old_size);
+        if (r < 0)
+                return r;
 
         f->header->arena_size = htole64(new_size - old_header_size);
 
index c1736641462d6bcf451db992878ad346a73a82fc..0f1c9eb8f73b19dfb5e7f3690bdbcec9f48d4963 100644 (file)
@@ -88,7 +88,7 @@ static void patch_realtime(
 }
 
 static int journal_file_empty(int dir_fd, const char *name) {
-        _cleanup_close_ int fd;
+        _cleanup_close_ int fd = -1;
         struct stat st;
         le64_t n_entries;
         ssize_t n;
index be92f803c95fd33d641b161b93f995ff0e6c0efd..c90b4c926e6d9abd5ecf627c7023739efcc519ee 100644 (file)
@@ -1860,7 +1860,7 @@ static int add_current_paths(sd_journal *j) {
          * treat them as fatal. */
 
         ORDERED_HASHMAP_FOREACH(f, j->files) {
-                _cleanup_free_ char *dir;
+                _cleanup_free_ char *dir = NULL;
                 int r;
 
                 dir = dirname_malloc(f->path);
index a3da2e3f24dbc43e129b09e3ce7bb383231e754e..b4e010e74c2844bc6be83a82cca0b2eb46df0fdc 100644 (file)
@@ -775,7 +775,7 @@ _public_ int sd_get_sessions(char ***sessions) {
 }
 
 _public_ int sd_get_uids(uid_t **users) {
-        _cleanup_closedir_ DIR *d;
+        _cleanup_closedir_ DIR *d = NULL;
         struct dirent *de;
         int r = 0;
         unsigned n = 0;
index cd5a0104a6c90e26a4186a271d5c7c68b68a473d..a939d655698aa9b3ec93cc22cf39563ec8fd32ea 100644 (file)
@@ -26,7 +26,6 @@ static const genl_family genl_families[] = {
 int sd_genl_socket_open(sd_netlink **ret) {
         return netlink_open_family(ret, NETLINK_GENERIC);
 }
-static int lookup_id(sd_netlink *nl, sd_genl_family_t family, uint16_t *id);
 
 static int genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint16_t nlmsg_type, uint8_t cmd, sd_netlink_message **ret) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
@@ -73,17 +72,6 @@ static int genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint16_t nl
         return 0;
 }
 
-int sd_genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **ret) {
-        uint16_t id;
-        int r;
-
-        r = lookup_id(nl, family, &id);
-        if (r < 0)
-                return r;
-
-        return genl_message_new(nl, family, id, cmd, ret);
-}
-
 static int lookup_id(sd_netlink *nl, sd_genl_family_t family, uint16_t *id) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
         uint16_t u;
@@ -129,6 +117,17 @@ static int lookup_id(sd_netlink *nl, sd_genl_family_t family, uint16_t *id) {
         return 0;
 }
 
+int sd_genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **ret) {
+        uint16_t id = 0; /* Unnecessary initialization to appease gcc */
+        int r;
+
+        r = lookup_id(nl, family, &id);
+        if (r < 0)
+                return r;
+
+        return genl_message_new(nl, family, id, cmd, ret);
+}
+
 int nlmsg_type_to_genl_family(const sd_netlink *nl, uint16_t type, sd_genl_family_t *ret) {
         void *p;
 
index ed7b9a8cd166f0b0d5af4b4bdae9105174c5d160..5ae15d67bcdf759757f5efa00d24ed16f88806a1 100644 (file)
@@ -683,13 +683,13 @@ static const NLType rtnl_address_types[] = {
         [IFA_ADDRESS]           = { .type = NETLINK_TYPE_IN_ADDR },
         [IFA_LOCAL]             = { .type = NETLINK_TYPE_IN_ADDR },
         [IFA_LABEL]             = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
-        [IFA_BROADCAST]         = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
+        [IFA_BROADCAST]         = { .type = NETLINK_TYPE_IN_ADDR },
+        [IFA_ANYCAST]           = { .type = NETLINK_TYPE_IN_ADDR },
         [IFA_CACHEINFO]         = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct ifa_cacheinfo) },
-/*
-        [IFA_ANYCAST],
-        [IFA_MULTICAST],
-*/
+        [IFA_MULTICAST]         = { .type = NETLINK_TYPE_IN_ADDR },
         [IFA_FLAGS]             = { .type = NETLINK_TYPE_U32 },
+        [IFA_RT_PRIORITY]       = { .type = NETLINK_TYPE_U32 },
+        [IFA_TARGET_NETNSID]    = { .type = NETLINK_TYPE_S32 },
 };
 
 static const NLTypeSystem rtnl_address_type_system = {
index d14fa1a5cb75664a03da2bd23db2c2dd16dd2622..ead19672587baf704cee1480a90e46288c2515c4 100644 (file)
@@ -447,7 +447,7 @@ int sd_rtnl_message_new_neigh(sd_netlink *rtnl, sd_netlink_message **ret, uint16
                 return r;
 
         if (nlmsg_type == RTM_NEWNEIGH)
-                (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
+                (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
 
         ndm = NLMSG_DATA((*ret)->hdr);
 
index acf7500970e382e619a9f4772ee19231920581c8..c1d3a9f6a2dd634edc58955319b35e92bc6bfe06 100644 (file)
@@ -56,6 +56,15 @@ static const char* const link_carrier_state_table[_LINK_CARRIER_STATE_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(link_carrier_state, LinkCarrierState);
 
+static const char* const link_required_address_family_table[_ADDRESS_FAMILY_MAX] = {
+        [ADDRESS_FAMILY_NO]   = "any",
+        [ADDRESS_FAMILY_IPV4] = "ipv4",
+        [ADDRESS_FAMILY_IPV6] = "ipv6",
+        [ADDRESS_FAMILY_YES]  = "both",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(link_required_address_family, AddressFamily);
+
 static const char* const link_address_state_table[_LINK_ADDRESS_STATE_MAX] = {
         [LINK_ADDRESS_STATE_OFF]      = "off",
         [LINK_ADDRESS_STATE_DEGRADED] = "degraded",
index dd6a7dbe88c04b437c5d132f458c2f78870279f2..3bd10c42de8e7dcb0a947e2a89b349dc7bed22c9 100644 (file)
 
 bool network_is_online(void);
 
+typedef enum AddressFamily {
+        /* This is a bitmask, though it usually doesn't feel that way! */
+        ADDRESS_FAMILY_NO             = 0,
+        ADDRESS_FAMILY_IPV4           = 1 << 0,
+        ADDRESS_FAMILY_IPV6           = 1 << 1,
+        ADDRESS_FAMILY_YES            = ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6,
+        _ADDRESS_FAMILY_MAX,
+        _ADDRESS_FAMILY_INVALID = -EINVAL,
+} AddressFamily;
+
 typedef enum LinkOperationalState {
         LINK_OPERSTATE_MISSING,
         LINK_OPERSTATE_OFF,
@@ -50,6 +60,9 @@ LinkOperationalState link_operstate_from_string(const char *s) _pure_;
 const char* link_carrier_state_to_string(LinkCarrierState s) _const_;
 LinkCarrierState link_carrier_state_from_string(const char *s) _pure_;
 
+const char* link_required_address_family_to_string(AddressFamily s) _const_;
+AddressFamily link_required_address_family_from_string(const char *s) _pure_;
+
 const char* link_address_state_to_string(LinkAddressState s) _const_;
 LinkAddressState link_address_state_from_string(const char *s) _pure_;
 
index ccdfde9137e7b1a3072e894d9852f957e1231cb0..b190e8f881081ba085abf286af2b78b635b2e606 100644 (file)
@@ -48,6 +48,14 @@ _public_ int sd_network_get_address_state(char **state) {
         return network_get_string("ADDRESS_STATE", state);
 }
 
+_public_ int sd_network_get_ipv4_address_state(char **state) {
+        return network_get_string("IPV4_ADDRESS_STATE", state);
+}
+
+_public_ int sd_network_get_ipv6_address_state(char **state) {
+        return network_get_string("IPV6_ADDRESS_STATE", state);
+}
+
 static int network_get_strv(const char *key, char ***ret) {
         _cleanup_strv_free_ char **a = NULL;
         _cleanup_free_ char *s = NULL;
@@ -160,6 +168,26 @@ _public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
         return network_link_get_string(ifindex, "OPER_STATE", state);
 }
 
+_public_ int sd_network_link_get_required_family_for_online(int ifindex, char **state) {
+        _cleanup_free_ char *s = NULL;
+        int r;
+
+        assert_return(state, -EINVAL);
+
+        r = network_link_get_string(ifindex, "REQUIRED_FAMILY_FOR_ONLINE", &s);
+        if (r < 0) {
+                if (r != -ENODATA)
+                        return r;
+
+                s = strdup("any");
+                if (!s)
+                        return -ENOMEM;
+        }
+
+        *state = TAKE_PTR(s);
+        return 0;
+}
+
 _public_ int sd_network_link_get_carrier_state(int ifindex, char **state) {
         return network_link_get_string(ifindex, "CARRIER_STATE", state);
 }
@@ -168,6 +196,14 @@ _public_ int sd_network_link_get_address_state(int ifindex, char **state) {
         return network_link_get_string(ifindex, "ADDRESS_STATE", state);
 }
 
+_public_ int sd_network_link_get_ipv4_address_state(int ifindex, char **state) {
+        return network_link_get_string(ifindex, "IPV4_ADDRESS_STATE", state);
+}
+
+_public_ int sd_network_link_get_ipv6_address_state(int ifindex, char **state) {
+        return network_link_get_string(ifindex, "IPV6_ADDRESS_STATE", state);
+}
+
 _public_ int sd_network_link_get_dhcp6_client_iaid_string(int ifindex, char **iaid) {
         return network_link_get_string(ifindex, "DHCP6_CLIENT_IAID", iaid);
 }
index 4ddcf95d05f57300c7b62b75e2c245a304de3515..d7c931d9f929d42d47a86b744781fa869d48683c 100644 (file)
@@ -265,9 +265,12 @@ _public_ struct udev_device *udev_monitor_receive_device(struct udev_monitor *ud
  * Returns: 0 on success, otherwise a negative error value.
  */
 _public_ int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype) {
+        int r;
+
         assert_return(udev_monitor, -EINVAL);
 
-        return sd_device_monitor_filter_add_match_subsystem_devtype(udev_monitor->monitor, subsystem, devtype);
+        r = sd_device_monitor_filter_add_match_subsystem_devtype(udev_monitor->monitor, subsystem, devtype);
+        return r < 0 ? r : 0;
 }
 
 /**
@@ -283,9 +286,12 @@ _public_ int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor
  * Returns: 0 on success, otherwise a negative error value.
  */
 _public_ int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag) {
+        int r;
+
         assert_return(udev_monitor, -EINVAL);
 
-        return sd_device_monitor_filter_add_match_tag(udev_monitor->monitor, tag);
+        r = sd_device_monitor_filter_add_match_tag(udev_monitor->monitor, tag);
+        return r < 0 ? r : 0;
 }
 
 /**
index 12bd0d62994f2daf28b45051c070bbdae4fc3406..a7510567954145197b634246824c32f31a862738 100644 (file)
@@ -6,7 +6,6 @@
 #include <unistd.h>
 
 #include "alloc-util.h"
-#include "build.h"
 #include "fd-util.h"
 #include "libudev-list-internal.h"
 #include "libudev-util.h"
@@ -15,6 +14,7 @@
 #include "stdio-util.h"
 #include "string-util.h"
 #include "tests.h"
+#include "version.h"
 
 static bool arg_monitor = false;
 
index e8de1b789a0e3f90a864a1786bc9249089bb659e..d2f0566dbc5214cc709c0b01dd7688d449c17b9a 100644 (file)
@@ -535,7 +535,7 @@ int vconsole_convert_to_x11(Context *c) {
 
 int find_converted_keymap(const char *x11_layout, const char *x11_variant, char **new_keymap) {
         const char *dir;
-        _cleanup_free_ char *n;
+        _cleanup_free_ char *n = NULL;
 
         if (x11_variant)
                 n = strjoin(x11_layout, "-", x11_variant);
index f44c0bab2a9e46e016ad1efc3fed1a8a963ae038..df0eb030d46651339fc35c11c0b61949b29e187e 100644 (file)
@@ -399,7 +399,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
         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");
+                return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Failed to read locale data");
         }
 
         /* Merge with the current settings */
@@ -457,7 +457,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
         (void) locale_update_system_manager(c, sd_bus_message_get_bus(m));
 
         if (settings) {
-                _cleanup_free_ char *line;
+                _cleanup_free_ char *line = NULL;
 
                 line = strv_join(settings, ", ");
                 log_info("Changed locale to %s.", strnull(line));
@@ -673,7 +673,7 @@ static int method_set_x11_keyboard(sd_bus_message *m, void *userdata, sd_bus_err
         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");
+                return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Failed to read x11 keyboard layout data");
         }
 
         if (streq_ptr(layout, c->x11_layout) &&
@@ -686,7 +686,7 @@ static int method_set_x11_keyboard(sd_bus_message *m, void *userdata, sd_bus_err
             (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, "Received invalid keyboard data");
 
         r = verify_xkb_rmlvo(model, layout, variant, options);
         if (r < 0) {
@@ -694,7 +694,7 @@ static int method_set_x11_keyboard(sd_bus_message *m, void *userdata, sd_bus_err
                                 strempty(model), strempty(layout), strempty(variant), strempty(options));
 
                 if (r == -EOPNOTSUPP)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Local keyboard configuration not supported on this system.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Local keyboard configuration not supported on this system.");
 
                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Specified keymap cannot be compiled, refusing as invalid.");
         }
index 45e4adfa0f5b24a015f93362fe300d592c066213..8d5fa47bf3ae7497971b3d126dcc8bc911f692a2 100644 (file)
@@ -30,19 +30,14 @@ SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", TAG+="uaccess
 SUBSYSTEM=="sound", TAG+="uaccess", \
   OPTIONS+="static_node=snd/timer", OPTIONS+="static_node=snd/seq"
 
-# ffado is an userspace driver for firewire sound cards
-SUBSYSTEM=="firewire", ENV{ID_FFADO}=="1", TAG+="uaccess"
-
 # Webcams, frame grabber, TV cards
 SUBSYSTEM=="video4linux", TAG+="uaccess"
 SUBSYSTEM=="dvb", TAG+="uaccess"
 
-# IIDC devices: industrial cameras and some webcams
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*",  TAG+="uaccess"
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*",  TAG+="uaccess"
-# AV/C devices: camcorders, set-top boxes, TV sets, audio devices, and more
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", TAG+="uaccess"
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", TAG+="uaccess"
+# industrial cameras, some webcams, camcorders, set-top boxes, TV sets, audio devices, and more
+SUBSYSTEM=="firewire", TEST=="units", ENV{IEEE1394_UNIT_FUNCTION_MIDI}=="1", TAG+="uaccess"
+SUBSYSTEM=="firewire", TEST=="units", ENV{IEEE1394_UNIT_FUNCTION_AUDIO}=="1", TAG+="uaccess"
+SUBSYSTEM=="firewire", TEST=="units", ENV{IEEE1394_UNIT_FUNCTION_VIDEO}=="1", TAG+="uaccess"
 
 # DRI video devices
 SUBSYSTEM=="drm", KERNEL=="card*", TAG+="uaccess"
index 4ece3fda5862c7bd2a5e1264a8f94fbb57a9ef76..7a2b13e4426781ae496a14d283c8be0d2e546670 100644 (file)
@@ -39,8 +39,7 @@
 #include "verbs.h"
 
 static char **arg_property = NULL;
-static bool arg_all = false;
-static bool arg_value = false;
+static BusPrintPropertyFlags arg_print_flags = 0;
 static bool arg_full = false;
 static PagerFlags arg_pager_flags = 0;
 static bool arg_legend = true;
@@ -57,7 +56,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
 static OutputFlags get_output_flags(void) {
 
         return
-                arg_all * OUTPUT_SHOW_ALL |
+                FLAGS_SET(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) * OUTPUT_SHOW_ALL |
                 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
                 colors_enabled() * OUTPUT_COLOR;
 }
@@ -705,7 +704,7 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line)
         return 0;
 }
 
-static int print_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) {
+static int print_property(const char *name, const char *expected_value, sd_bus_message *m, BusPrintPropertyFlags flags) {
         char type;
         const char *contents;
         int r;
@@ -728,8 +727,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
-                        if (all || !isempty(s))
-                                bus_print_property_value(name, expected_value, value, s);
+                        bus_print_property_value(name, expected_value, flags, s);
 
                         return 1;
 
@@ -745,7 +743,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                                        "Invalid user ID: " UID_FMT,
                                                        uid);
 
-                        bus_print_property_valuef(name, expected_value, value, UID_FMT, uid);
+                        bus_print_property_valuef(name, expected_value, flags, UID_FMT, uid);
                         return 1;
                 }
                 break;
@@ -760,7 +758,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
-                        if (!value)
+                        if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE))
                                 printf("%s=", name);
 
                         while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) {
@@ -768,7 +766,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 space = true;
                         }
 
-                        if (space || !value)
+                        if (space || !FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE))
                                 printf("\n");
 
                         if (r < 0)
@@ -804,8 +802,7 @@ static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
                         path,
                         print_property,
                         arg_property,
-                        arg_value,
-                        arg_all,
+                        arg_print_flags,
                         NULL);
         if (r < 0)
                 return bus_log_parse_error(r);
@@ -1331,7 +1328,7 @@ static int parse_argv(int argc, char *argv[]) {
                         return version();
 
                 case 'P':
-                        arg_value = true;
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_ONLY_VALUE, true);
                         _fallthrough_;
 
                 case 'p': {
@@ -1342,16 +1339,16 @@ static int parse_argv(int argc, char *argv[]) {
                         /* If the user asked for a particular
                          * property, show it to them, even if it is
                          * empty. */
-                        arg_all = true;
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
                         break;
                 }
 
                 case 'a':
-                        arg_all = true;
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
                         break;
 
                 case ARG_VALUE:
-                        arg_value = true;
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_ONLY_VALUE, true);
                         break;
 
                 case 'l':
index 2ecf2120fdbe5105affac2631e7e4e1c54b1f6ab..cd3a37420123fae987893da4543dcf6c47dfc73e 100644 (file)
@@ -485,7 +485,7 @@ int config_parse_n_autovts(
 static int vt_is_busy(unsigned vtnr) {
         struct vt_stat vt_stat;
         int r;
-        _cleanup_close_ int fd;
+        _cleanup_close_ int fd = -1;
 
         assert(vtnr >= 1);
 
index a539a2e9797d2e2a78336d32dbc52fa489a09434..3eb0e8fd4e7f29bcd26b86674ba293d4c9a55d95 100644 (file)
@@ -695,9 +695,9 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
                 return r;
 
         if (!uid_is_valid(uid))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
         if (leader < 0 || leader == 1 || leader == getpid_cached())
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
 
         if (isempty(type))
                 t = _SESSION_TYPE_INVALID;
@@ -831,7 +831,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
             vtnr < m->seat0->position_count &&
             m->seat0->positions[vtnr] &&
             m->seat0->positions[vtnr]->class != SESSION_GREETER)
-                return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
+                return sd_bus_error_set(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
 
         if (hashmap_size(m->sessions) >= m->sessions_max)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED,
@@ -1319,18 +1319,9 @@ static int trigger_device(Manager *m, sd_device *d) {
         }
 
         FOREACH_DEVICE(e, d) {
-                _cleanup_free_ char *t = NULL;
-                const char *p;
-
-                r = sd_device_get_syspath(d, &p);
+                r = sd_device_trigger(d, SD_DEVICE_CHANGE);
                 if (r < 0)
-                        return r;
-
-                t = path_join(p, "uevent");
-                if (!t)
-                        return -ENOMEM;
-
-                (void) write_string_file(t, "change", WRITE_STRING_FILE_DISABLE_BUFFER);
+                        log_device_debug_errno(d, r, "Failed to trigger device, ignoring: %m");
         }
 
         return 0;
@@ -1371,7 +1362,7 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs) {
 }
 
 static int flush_devices(Manager *m) {
-        _cleanup_closedir_ DIR *d;
+        _cleanup_closedir_ DIR *d = NULL;
 
         assert(m);
 
@@ -1879,7 +1870,9 @@ static int method_do_shutdown_or_sleep(
                 if (r < 0)
                         return r;
                 if ((flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC) != 0)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
+                if (!streq(unit_name, SPECIAL_REBOOT_TARGET) && (flags & SD_LOGIND_REBOOT_VIA_KEXEC))
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Reboot via kexec is only applicable with reboot operations");
         } else {
                 /* Old style method: no flags parameter, but interactive bool passed as boolean in
                  * payload. Let's convert this argument to the new-style flags parameter for our internal
@@ -1893,6 +1886,9 @@ static int method_do_shutdown_or_sleep(
                 flags = interactive ? SD_LOGIND_INTERACTIVE : 0;
         }
 
+        if ((flags & SD_LOGIND_REBOOT_VIA_KEXEC) && kexec_loaded())
+                unit_name = SPECIAL_KEXEC_TARGET;
+
         /* Don't allow multiple jobs being executed at the same time */
         if (m->action_what > 0)
                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS,
@@ -2068,7 +2064,7 @@ static int update_schedule_file(Manager *m) {
                 m->scheduled_shutdown_type);
 
         if (!isempty(m->wall_message)) {
-                _cleanup_free_ char *t;
+                _cleanup_free_ char *t = NULL;
 
                 t = cescape(m->wall_message);
                 if (!t) {
@@ -2135,6 +2131,8 @@ static int manager_scheduled_shutdown_handler(
                 target = SPECIAL_POWEROFF_TARGET;
         else if (streq(m->scheduled_shutdown_type, "reboot"))
                 target = SPECIAL_REBOOT_TARGET;
+        else if (streq(m->scheduled_shutdown_type, "kexec"))
+                target = SPECIAL_KEXEC_TARGET;
         else if (streq(m->scheduled_shutdown_type, "halt"))
                 target = SPECIAL_HALT_TARGET;
         else
@@ -2200,7 +2198,7 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
                 action = "org.freedesktop.login1.power-off";
                 action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
                 action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
-        } else if (streq(type, "reboot")) {
+        } else if (STR_IN_SET(type, "reboot", "kexec")) {
                 action = "org.freedesktop.login1.reboot";
                 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
                 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
@@ -2209,7 +2207,7 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
                 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
                 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
         } else
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
 
         r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, action, action_multiple_sessions,
                                   action_ignore_inhibit, 0, error);
@@ -2667,7 +2665,7 @@ static int method_set_reboot_to_firmware_setup(
 
                 r = efi_reboot_to_firmware_supported();
                 if (r == -EOPNOTSUPP)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
                 if (r < 0)
                         return r;
 
@@ -2679,7 +2677,7 @@ static int method_set_reboot_to_firmware_setup(
                 if (r < 0)
                         log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
 
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
         } else
                 /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to on */
                 use_efi = false;
@@ -2835,7 +2833,7 @@ static int method_set_reboot_to_boot_loader_menu(
                 if (r < 0)
                         log_warning_errno(r, "Failed to determine whether reboot to boot loader menu is supported: %m");
                 if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
 
                 use_efi = true;
 
@@ -2845,7 +2843,7 @@ static int method_set_reboot_to_boot_loader_menu(
                 if (r < 0)
                         log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
 
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
         } else
                 /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU is set to on */
                 use_efi = false;
@@ -3037,7 +3035,7 @@ static int method_set_reboot_to_boot_loader_entry(
                 if (r < 0)
                         log_warning_errno(r, "Failed to determine whether reboot into boot loader entry is supported: %m");
                 if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_ENTRY_ONESHOT))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
 
                 use_efi = true;
 
@@ -3047,7 +3045,7 @@ static int method_set_reboot_to_boot_loader_entry(
                 if (r < 0)
                         log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
 
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
         } else
                 /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY is set to on */
                 use_efi = false;
index 9c2625cdcc3245cbddcec808fc63c14c846d98af..cceb3b1d2d309fc22eb03ea9076ad7976c32af0d 100644 (file)
@@ -206,7 +206,7 @@ static int method_switch_to(sd_bus_message *message, void *userdata, sd_bus_erro
                 return r;
 
         if (to <= 0)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid virtual terminal");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid virtual terminal");
 
         r = check_polkit_chvt(message, s->manager, error);
         if (r < 0)
index d342dc4193aa42d53a969568d519ed640ac919b4..afaef1123d98e2bc156d484902f48e1defbbdfc7 100644 (file)
@@ -256,11 +256,11 @@ static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_
                 return r;
 
         if (uid != 0 && uid != s->user->user_record->uid)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set idle hint");
+                return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set idle hint");
 
         r = session_set_idle_hint(s, b);
         if (r == -ENOTTY)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Idle hint control is not supported on non-graphical sessions.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Idle hint control is not supported on non-graphical sessions.");
         if (r < 0)
                 return r;
 
@@ -289,7 +289,7 @@ static int method_set_locked_hint(sd_bus_message *message, void *userdata, sd_bu
                 return r;
 
         if (uid != 0 && uid != s->user->user_record->uid)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set locked hint");
+                return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set locked hint");
 
         session_set_locked_hint(s, b);
 
@@ -364,7 +364,7 @@ static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_e
                 return r;
 
         if (uid != 0 && (force || uid != s->user->user_record->uid))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may take control");
+                return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may take control");
 
         r = session_set_controller(s, sd_bus_message_get_sender(message), force, true);
         if (r < 0)
@@ -380,7 +380,7 @@ static int method_release_control(sd_bus_message *message, void *userdata, sd_bu
         assert(s);
 
         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
-                return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
+                return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
 
         session_drop_controller(s);
 
@@ -406,7 +406,7 @@ static int method_set_type(sd_bus_message *message, void *userdata, sd_bus_error
                                          "Invalid session type '%s'", t);
 
         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
-                return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You must be in control of this session to set type");
+                return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You must be in control of this session to set type");
 
         session_set_type(s, type);
 
@@ -428,10 +428,10 @@ static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_er
                 return r;
 
         if (!DEVICE_MAJOR_VALID(major) || !DEVICE_MINOR_VALID(minor))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid.");
 
         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
-                return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
+                return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
 
         dev = makedev(major, minor);
         sd = hashmap_get(s->devices, &dev);
@@ -441,7 +441,7 @@ static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_er
                  * The caller should use dup() if it requires more
                  * than one fd (it would be functionally
                  * equivalent). */
-                return sd_bus_error_setf(error, BUS_ERROR_DEVICE_IS_TAKEN, "Device already taken");
+                return sd_bus_error_set(error, BUS_ERROR_DEVICE_IS_TAKEN, "Device already taken");
 
         r = session_device_new(s, dev, true, &sd);
         if (r < 0)
@@ -478,15 +478,15 @@ static int method_release_device(sd_bus_message *message, void *userdata, sd_bus
                 return r;
 
         if (!DEVICE_MAJOR_VALID(major) || !DEVICE_MINOR_VALID(minor))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid.");
 
         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
-                return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
+                return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
 
         dev = makedev(major, minor);
         sd = hashmap_get(s->devices, &dev);
         if (!sd)
-                return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
+                return sd_bus_error_set(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
 
         session_device_free(sd);
         session_save(s);
@@ -509,15 +509,15 @@ static int method_pause_device_complete(sd_bus_message *message, void *userdata,
                 return r;
 
         if (!DEVICE_MAJOR_VALID(major) || !DEVICE_MINOR_VALID(minor))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid.");
 
         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
-                return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
+                return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
 
         dev = makedev(major, minor);
         sd = hashmap_get(s->devices, &dev);
         if (!sd)
-                return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
+                return sd_bus_error_set(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
 
         session_device_complete_pause(sd);
 
@@ -546,9 +546,9 @@ static int method_set_brightness(sd_bus_message *message, void *userdata, sd_bus
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not a valid device name %s, refusing.", name);
 
         if (!s->seat)
-                return sd_bus_error_setf(error, BUS_ERROR_NOT_YOUR_DEVICE, "Your session has no seat, refusing.");
+                return sd_bus_error_set(error, BUS_ERROR_NOT_YOUR_DEVICE, "Your session has no seat, refusing.");
         if (s->seat->active != s)
-                return sd_bus_error_setf(error, BUS_ERROR_NOT_YOUR_DEVICE, "Session is not in foreground, refusing.");
+                return sd_bus_error_set(error, BUS_ERROR_NOT_YOUR_DEVICE, "Session is not in foreground, refusing.");
 
         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
         if (r < 0)
@@ -559,7 +559,7 @@ static int method_set_brightness(sd_bus_message *message, void *userdata, sd_bus
                 return r;
 
         if (uid != 0 && uid != s->user->user_record->uid)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may change brightness.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may change brightness.");
 
         r = sd_device_new_from_subsystem_sysname(&d, subsystem, name);
         if (r < 0)
index 34fcde92aae10b1fdb66e5d1c17376ce5cf1882a..6a3dd860db4e9de5de10b695e8d820ec6716c8b3 100644 (file)
@@ -266,7 +266,7 @@ int session_save(Session *s) {
                 fprintf(f, "DISPLAY=%s\n", s->display);
 
         if (s->remote_host) {
-                _cleanup_free_ char *escaped;
+                _cleanup_free_ char *escaped = NULL;
 
                 escaped = cescape(s->remote_host);
                 if (!escaped) {
@@ -278,7 +278,7 @@ int session_save(Session *s) {
         }
 
         if (s->remote_user) {
-                _cleanup_free_ char *escaped;
+                _cleanup_free_ char *escaped = NULL;
 
                 escaped = cescape(s->remote_user);
                 if (!escaped) {
@@ -290,7 +290,7 @@ int session_save(Session *s) {
         }
 
         if (s->service) {
-                _cleanup_free_ char *escaped;
+                _cleanup_free_ char *escaped = NULL;
 
                 escaped = cescape(s->service);
                 if (!escaped) {
@@ -302,7 +302,7 @@ int session_save(Session *s) {
         }
 
         if (s->desktop) {
-                _cleanup_free_ char *escaped;
+                _cleanup_free_ char *escaped = NULL;
 
                 escaped = cescape(s->desktop);
                 if (!escaped) {
index 414d431217dff9c42e9423ef12f30cfe418f8320..9d48fd2402b4ade6f19ee40a06041a8cc687e1e4 100644 (file)
@@ -216,7 +216,7 @@ int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_er
         if (r == 0)
                 return 1; /* Will call us back */
 
-        r = user_stop(u, /* force */ true);
+        r = user_stop(u, /* force */ true);
         if (r < 0)
                 return r;
 
index 4887889facb482d61f3f36b8ad39d624428c486c..b782938a5c920d224e9bfdef463327e571aa0eb9 100644 (file)
@@ -268,8 +268,8 @@ static int manager_enumerate_seats(Manager *m) {
                 s = hashmap_get(m->seats, de->d_name);
                 if (!s) {
                         if (unlinkat(dirfd(d), de->d_name, 0) < 0)
-                                log_warning("Failed to remove /run/systemd/seats/%s: %m",
-                                            de->d_name);
+                                log_warning_errno(errno, "Failed to remove /run/systemd/seats/%s, ignoring: %m",
+                                                  de->d_name);
                         continue;
                 }
 
index 76f529c176be017003b5961b50340e208a69d0a8..564868e7ae61bc1d5cc79cdd8862e914b52045e7 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Entries in this file show the compile time defaults. Local configuration
 # should be created by either modifying this file, or by creating "drop-ins" in
-# the system.conf.d/ subdirectory. The latter is generally recommended.
+# the logind.conf.d/ subdirectory. The latter is generally recommended.
 # Defaults can be restored by simply deleting this file and all drop-ins.
 #
 # Use 'systemd-analyze cat-config systemd/logind.conf' to display the full config.
index 69fb71cdc2d7f837e96f4ddaa1e3c738a8231ab0..5af6bfeafe4af3b40668313505b956670a75b0ad 100644 (file)
@@ -6,20 +6,25 @@
 #include <stdlib.h>
 
 #include "alloc-util.h"
+#include "dissect-image.h"
 #include "id128-util.h"
 #include "log.h"
 #include "machine-id-setup.h"
 #include "main-func.h"
+#include "mount-util.h"
 #include "parse-argument.h"
 #include "path-util.h"
 #include "pretty-print.h"
+#include "terminal-util.h"
 #include "util.h"
 
 static char *arg_root = NULL;
+static char *arg_image = NULL;
 static bool arg_commit = false;
 static bool arg_print = false;
 
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
 
 static int help(void) {
         _cleanup_free_ char *link = NULL;
@@ -29,15 +34,18 @@ static int help(void) {
         if (r < 0)
                 return log_oom();
 
-        printf("%s [OPTIONS...]\n\n"
-               "Initialize /etc/machine-id from a random source.\n\n"
+        printf("%s [OPTIONS...]\n"
+               "\n%sInitialize /etc/machine-id from a random source.%s\n\n"
                "  -h --help             Show this help\n"
                "     --version          Show package version\n"
-               "     --root=ROOT        Filesystem root\n"
+               "     --root=PATH        Operate relative to root path\n"
+               "     --image=PATH       Operate relative to image file\n"
                "     --commit           Commit transient ID\n"
                "     --print            Print used machine ID\n"
                "\nSee the %s for details.\n",
                program_invocation_short_name,
+               ansi_highlight(),
+               ansi_normal(),
                link);
 
         return 0;
@@ -48,6 +56,7 @@ static int parse_argv(int argc, char *argv[]) {
         enum {
                 ARG_VERSION = 0x100,
                 ARG_ROOT,
+                ARG_IMAGE,
                 ARG_COMMIT,
                 ARG_PRINT,
         };
@@ -56,6 +65,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "help",      no_argument,       NULL, 'h'           },
                 { "version",   no_argument,       NULL, ARG_VERSION   },
                 { "root",      required_argument, NULL, ARG_ROOT      },
+                { "image",     required_argument, NULL, ARG_IMAGE     },
                 { "commit",    no_argument,       NULL, ARG_COMMIT    },
                 { "print",     no_argument,       NULL, ARG_PRINT     },
                 {}
@@ -82,6 +92,12 @@ static int parse_argv(int argc, char *argv[]) {
                                 return r;
                         break;
 
+                case ARG_IMAGE:
+                        r = parse_path_argument(optarg, false, &arg_image);
+                        if (r < 0)
+                                return r;
+                        break;
+
                 case ARG_COMMIT:
                         arg_commit = true;
                         break;
@@ -101,10 +117,16 @@ static int parse_argv(int argc, char *argv[]) {
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Extraneous arguments");
 
+        if (arg_image && arg_root)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported.");
+
         return 1;
 }
 
 static int run(int argc, char *argv[]) {
+        _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
+        _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
+        _cleanup_(umount_and_rmdir_and_freep) char *unlink_dir = NULL;
         char buf[SD_ID128_STRING_MAX];
         sd_id128_t id;
         int r;
@@ -116,6 +138,27 @@ static int run(int argc, char *argv[]) {
         if (r <= 0)
                 return r;
 
+        if (arg_image) {
+                assert(!arg_root);
+
+                r = mount_image_privately_interactively(
+                                arg_image,
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_VALIDATE_OS |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                DISSECT_IMAGE_FSCK |
+                                DISSECT_IMAGE_GROWFS,
+                                &unlink_dir,
+                                &loop_device,
+                                &decrypted_image);
+                if (r < 0)
+                        return r;
+
+                arg_root = strdup(unlink_dir);
+                if (!arg_root)
+                        return log_oom();
+        }
+
         if (arg_commit) {
                 const char *etc_machine_id;
 
index 309de0b116c80bc2e6d754987c159cd2b2fc9923..e6ffb52924c0f845f641e5f68ee3419e06400b1b 100644 (file)
@@ -41,7 +41,7 @@ int bus_image_method_remove(
         assert(image);
 
         if (m->n_operations >= OPERATIONS_MAX)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
 
         r = bus_verify_polkit_async(
                         message,
@@ -146,7 +146,7 @@ int bus_image_method_clone(
         assert(m);
 
         if (m->n_operations >= OPERATIONS_MAX)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
 
         r = sd_bus_message_read(message, "sb", &new_name, &read_only);
         if (r < 0)
@@ -252,7 +252,7 @@ int bus_image_method_set_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");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
 
         r = bus_verify_polkit_async(
                         message,
index e7c4ed3c7c17cdfef73b28e4edf482bd4ac1fd76..0022a980c52655d8c562911a1e66e59df374a203 100644 (file)
@@ -331,12 +331,12 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
                 if (r < 0)
                         return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
                 if (r != EXIT_SUCCESS)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
                 break;
         }
 
         default:
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting IP address data is only supported on container machines.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting IP address data is only supported on container machines.");
         }
 
         r = sd_bus_message_close_container(reply);
@@ -415,15 +415,15 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
                 if (r < 0)
                         return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
                 if (r == EXIT_NOT_FOUND)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Machine does not contain OS release information");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Machine does not contain OS release information");
                 if (r != EXIT_SUCCESS)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
 
                 break;
         }
 
         default:
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting OS release data is only supported on container machines.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting OS release data is only supported on container machines.");
         }
 
         return bus_reply_pair_array(message, l);
@@ -628,7 +628,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
         if (r < 0)
                 return r;
         if (!strv_env_is_valid(env))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
 
         const char *details[] = {
                 "machine", m->name,
@@ -820,19 +820,19 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
         assert(m);
 
         if (m->class != MACHINE_CONTAINER)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Bind mounting is only supported on container machines.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Bind mounting is only supported on container machines.");
 
         r = sd_bus_message_read(message, "ssbb", &src, &dest, &read_only, &make_file_or_directory);
         if (r < 0)
                 return r;
 
         if (!path_is_absolute(src) || !path_is_normalized(src))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and normalized.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and normalized.");
 
         if (isempty(dest))
                 dest = src;
         else if (!path_is_absolute(dest) || !path_is_normalized(dest))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and normalized.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and normalized.");
 
         r = bus_verify_polkit_async(
                         message,
@@ -852,7 +852,7 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
         if (r < 0)
                 return r;
         if (uid != 0)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Can't bind mount on container with user namespacing applied.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Can't bind mount on container with user namespacing applied.");
 
         propagate_directory = strjoina("/run/systemd/nspawn/propagate/", m->name);
         r = bind_mount_in_namespace(m->leader,
@@ -881,22 +881,22 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
         assert(m);
 
         if (m->manager->n_operations >= OPERATIONS_MAX)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing copies.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing copies.");
 
         if (m->class != MACHINE_CONTAINER)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Copying files is only supported on container machines.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Copying files is only supported on container machines.");
 
         r = sd_bus_message_read(message, "ss", &src, &dest);
         if (r < 0)
                 return r;
 
         if (!path_is_absolute(src))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute.");
 
         if (isempty(dest))
                 dest = src;
         else if (!path_is_absolute(dest))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute.");
 
         r = bus_verify_polkit_async(
                         message,
@@ -1074,7 +1074,7 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
                 if (r < 0)
                         return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
                 if (r != EXIT_SUCCESS)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
 
                 fd = receive_one_fd(pair[0], MSG_DONTWAIT);
                 if (fd < 0)
@@ -1084,7 +1084,7 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
         }
 
         default:
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Opening the root directory is only supported on container machines.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Opening the root directory is only supported on container machines.");
         }
 
         return sd_bus_reply_method_return(message, "h", fd);
@@ -1105,7 +1105,7 @@ int bus_machine_method_get_uid_shift(sd_bus_message *message, void *userdata, sd
                 return sd_bus_reply_method_return(message, "u", UINT32_C(0));
 
         if (m->class != MACHINE_CONTAINER)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "UID/GID shift may only be determined for container machines.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "UID/GID shift may only be determined for container machines.");
 
         r = machine_get_uid_shift(m, &shift);
         if (r == -ENXIO)
index 537b0cd77939ad466cb079370e6f12bcfc75e50f..6215b29c2768d54f51d48f3c47a23af7724a122b 100644 (file)
@@ -134,7 +134,7 @@ int machine_save(Machine *m) {
                 m->name);
 
         if (m->unit) {
-                _cleanup_free_ char *escaped;
+                _cleanup_free_ char *escaped = NULL;
 
                 escaped = cescape(m->unit);
                 if (!escaped) {
@@ -149,7 +149,7 @@ int machine_save(Machine *m) {
                 fprintf(f, "SCOPE_JOB=%s\n", m->scope_job);
 
         if (m->service) {
-                _cleanup_free_ char *escaped;
+                _cleanup_free_ char *escaped = NULL;
 
                 escaped = cescape(m->service);
                 if (!escaped) {
@@ -160,7 +160,7 @@ int machine_save(Machine *m) {
         }
 
         if (m->root_directory) {
-                _cleanup_free_ char *escaped;
+                _cleanup_free_ char *escaped = NULL;
 
                 escaped = cescape(m->root_directory);
                 if (!escaped) {
index d7849973b855c44291f49cb2db28516100d687ee..15f7d39921ec7bbd3c227f3c3cb943d093325e96 100644 (file)
@@ -63,7 +63,7 @@
 
 static char **arg_property = NULL;
 static bool arg_all = false;
-static bool arg_value = false;
+static BusPrintPropertyFlags arg_print_flags = 0;
 static bool arg_full = false;
 static PagerFlags arg_pager_flags = 0;
 static bool arg_legend = true;
@@ -89,7 +89,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_setenv, strv_freep);
 
 static OutputFlags get_output_flags(void) {
         return
-                arg_all * OUTPUT_SHOW_ALL |
+                FLAGS_SET(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) * OUTPUT_SHOW_ALL |
                 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
                 colors_enabled() * OUTPUT_COLOR |
                 !arg_quiet * OUTPUT_WARN_CUTOFF;
@@ -689,7 +689,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, NULL, arg_property, arg_value, arg_all, NULL);
+        r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, NULL, arg_property, arg_print_flags, NULL);
         if (r < 0)
                 log_error_errno(r, "Could not get properties: %m");
 
@@ -1002,7 +1002,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, NULL, arg_property, arg_value, arg_all, NULL);
+        r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, NULL, arg_property, arg_print_flags, NULL);
         if (r < 0)
                 log_error_errno(r, "Could not get properties: %m");
 
@@ -2673,15 +2673,16 @@ static int parse_argv(int argc, char *argv[]) {
                         /* If the user asked for a particular
                          * property, show it to them, even if it is
                          * empty. */
-                        arg_all = true;
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
                         break;
 
                 case 'a':
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
                         arg_all = true;
                         break;
 
                 case ARG_VALUE:
-                        arg_value = true;
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_ONLY_VALUE, true);
                         break;
 
                 case 'l':
index 0a6ae96bc6eeee50176195476b755808d558761a..342b18a8df925622e8f3a15f6507f4d12e8791af 100644 (file)
@@ -241,7 +241,7 @@ static int method_create_or_register_machine(Manager *manager, sd_bus_message *m
         if (r < 0)
                 return r;
         if (!hostname_is_valid(name, 0))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
 
         r = sd_bus_message_read_array(message, 'y', &v, &n);
         if (r < 0)
@@ -251,7 +251,7 @@ static int method_create_or_register_machine(Manager *manager, sd_bus_message *m
         else if (n == 16)
                 memcpy(&id, v, n);
         else
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
 
         r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory);
         if (r < 0)
@@ -275,14 +275,14 @@ static int method_create_or_register_machine(Manager *manager, sd_bus_message *m
         else {
                 c = machine_class_from_string(class);
                 if (c < 0)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
         }
 
         if (leader == 1)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
 
         if (!isempty(root_directory) && !path_is_absolute(root_directory))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
 
         if (leader == 0) {
                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
@@ -701,7 +701,7 @@ static int method_clean_pool(sd_bus_message *message, void *userdata, sd_bus_err
         assert(message);
 
         if (m->n_operations >= OPERATIONS_MAX)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
 
         r = sd_bus_message_read(message, "s", &mm);
         if (r < 0)
@@ -842,7 +842,7 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus
         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");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
 
         r = bus_verify_polkit_async(
                         message,
@@ -867,7 +867,7 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus
 
         r = btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, limit);
         if (r == -ENOTTY)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
+                return sd_bus_error_set(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");
 
@@ -898,7 +898,7 @@ static int method_map_from_machine_user(sd_bus_message *message, void *userdata,
                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
 
         if (machine->class != MACHINE_CONTAINER)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
 
         r = machine_translate_uid(machine, uid, &converted);
         if (r == -ESRCH)
@@ -957,7 +957,7 @@ static int method_map_from_machine_group(sd_bus_message *message, void *userdata
                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
 
         if (machine->class != MACHINE_CONTAINER)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
 
         r = machine_translate_gid(machine, gid, &converted);
         if (r == -ESRCH)
index 34565e3e69532f93be43a89a9e9d5bb9641b2ffb..42432f1f7fdd89ee69a03b208689827084df6655 100644 (file)
@@ -22,14 +22,14 @@ static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdat
         o->pid = 0;
 
         if (si->si_code != CLD_EXITED) {
-                r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
+                r = sd_bus_error_set(&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.");
+                r = sd_bus_error_set(&error, SD_BUS_ERROR_FAILED, "Child failed.");
                 goto fail;
         }
 
index 9cfd292011602d00427d83b5308b3b8e6a415a3a..b57d806fab289472681a73a15729858b53ca4932 100644 (file)
@@ -62,12 +62,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
 
 static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent) {
         _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_free_ char *pp = NULL;
         int r;
 
         assert(ctx);
         assert(path);
 
-        r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
+        r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f, &pp);
         if (r < 0) {
                 if (ignore_enoent && r == -ENOENT)
                         return 0;
@@ -75,7 +76,7 @@ static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent
                 return log_error_errno(r, "Failed to open %s: %m", path);
         }
 
-        log_debug("apply: %s", path);
+        log_debug("apply: %s", pp);
         for (;;) {
                 _cleanup_free_ char *line = NULL;
                 char *l;
@@ -83,7 +84,7 @@ static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent
 
                 k = read_line(f, LONG_LINE_MAX, &line);
                 if (k < 0)
-                        return log_error_errno(k, "Failed to read file '%s': %m", path);
+                        return log_error_errno(k, "Failed to read file '%s': %m", pp);
                 if (k == 0)
                         break;
 
index 8abe04489002ae8a45603c9575af9aba655b3808..6381bcfe0c5dcd3e56e4189d8404cc315525102b 100644 (file)
@@ -44,6 +44,7 @@ Match.Virtualization,                     config_parse_net_condition,
 Match.KernelCommandLine,                  config_parse_net_condition,                CONDITION_KERNEL_COMMAND_LINE, offsetof(NetDev, conditions)
 Match.KernelVersion,                      config_parse_net_condition,                CONDITION_KERNEL_VERSION,      offsetof(NetDev, conditions)
 Match.Architecture,                       config_parse_net_condition,                CONDITION_ARCHITECTURE,        offsetof(NetDev, conditions)
+Match.Firmware,                           config_parse_net_condition,                CONDITION_FIRMWARE,            offsetof(NetDev, conditions)
 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)
index b31f0fa81ab23f7c77fc604a28e37edd28c29635..81d9260c123968ad3d7e6b9baf6805cd9e62ca1f 100644 (file)
@@ -747,8 +747,7 @@ int netdev_load_one(Manager *manager, const char *filename) {
                 r = netdev_get_mac(netdev->ifname, &netdev->mac);
                 if (r < 0)
                         return log_netdev_error_errno(netdev, r,
-                                                      "Failed to generate predictable MAC address for %s: %m",
-                                                      netdev->ifname);
+                                                      "Failed to generate predictable MAC address: %m");
         }
 
         r = hashmap_ensure_put(&netdev->manager->netdevs, &string_hash_ops, netdev->ifname, netdev);
@@ -760,8 +759,8 @@ int netdev_load_one(Manager *manager, const char *filename) {
                 assert(n);
                 if (!streq(netdev->filename, n->filename))
                         log_netdev_warning_errno(netdev, r,
-                                                 "The setting Name=%s in %s conflicts with the one in %s, ignoring",
-                                                 netdev->ifname, netdev->filename, n->filename);
+                                                 "Device was already configured by file %s, ignoring %s.",
+                                                 n->filename, netdev->filename);
 
                 /* Clear ifname before netdev_free() is called. Otherwise, the NetDev object 'n' is
                  * removed from the hashmap 'manager->netdevs'. */
index 6d149da2e9c39ded66346c8369880f6768785827..08070abd0a6e0031811341ea64488091665b9300 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "conf-parser.h"
 #include "list.h"
+#include "log-link.h"
 #include "networkd-link.h"
 #include "time-util.h"
 
@@ -223,24 +224,32 @@ const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, GPERF_
 
 /* Macros which append INTERFACE= to the message */
 
-#define log_netdev_full(netdev, level, error, ...)                      \
+#define log_netdev_full_errno_zerook(netdev, level, error, ...)         \
         ({                                                              \
                 const NetDev *_n = (netdev);                            \
-                _n ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "INTERFACE=", _n->ifname, NULL, NULL, ##__VA_ARGS__) : \
-                        log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
+                log_interface_full_errno_zerook(_n ? _n->ifname : NULL, level, error, __VA_ARGS__); \
         })
 
-#define log_netdev_debug(netdev, ...)       log_netdev_full(netdev, LOG_DEBUG, 0, ##__VA_ARGS__)
-#define log_netdev_info(netdev, ...)        log_netdev_full(netdev, LOG_INFO, 0, ##__VA_ARGS__)
-#define log_netdev_notice(netdev, ...)      log_netdev_full(netdev, LOG_NOTICE, 0, ##__VA_ARGS__)
-#define log_netdev_warning(netdev, ...)     log_netdev_full(netdev, LOG_WARNING, 0, ## __VA_ARGS__)
-#define log_netdev_error(netdev, ...)       log_netdev_full(netdev, LOG_ERR, 0, ##__VA_ARGS__)
-
-#define log_netdev_debug_errno(netdev, error, ...)   log_netdev_full(netdev, LOG_DEBUG, error, ##__VA_ARGS__)
-#define log_netdev_info_errno(netdev, error, ...)    log_netdev_full(netdev, LOG_INFO, error, ##__VA_ARGS__)
-#define log_netdev_notice_errno(netdev, error, ...)  log_netdev_full(netdev, LOG_NOTICE, error, ##__VA_ARGS__)
-#define log_netdev_warning_errno(netdev, error, ...) log_netdev_full(netdev, LOG_WARNING, error, ##__VA_ARGS__)
-#define log_netdev_error_errno(netdev, error, ...)   log_netdev_full(netdev, LOG_ERR, error, ##__VA_ARGS__)
+#define log_netdev_full_errno(netdev, level, error, ...) \
+        ({                                                              \
+                int _error = (error);                                   \
+                ASSERT_NON_ZERO(_error);                                \
+                log_netdev_full_errno_zerook(netdev, level, _error, __VA_ARGS__); \
+        })
+
+#define log_netdev_full(netdev, level, ...) (void) log_netdev_full_errno_zerook(netdev, level, 0, __VA_ARGS__)
+
+#define log_netdev_debug(netdev, ...)   log_netdev_full(netdev, LOG_DEBUG, __VA_ARGS__)
+#define log_netdev_info(netdev, ...)    log_netdev_full(netdev, LOG_INFO, __VA_ARGS__)
+#define log_netdev_notice(netdev, ...)  log_netdev_full(netdev, LOG_NOTICE, __VA_ARGS__)
+#define log_netdev_warning(netdev, ...) log_netdev_full(netdev, LOG_WARNING,  __VA_ARGS__)
+#define log_netdev_error(netdev, ...)   log_netdev_full(netdev, LOG_ERR, __VA_ARGS__)
+
+#define log_netdev_debug_errno(netdev, error, ...)   log_netdev_full_errno(netdev, LOG_DEBUG, error, __VA_ARGS__)
+#define log_netdev_info_errno(netdev, error, ...)    log_netdev_full_errno(netdev, LOG_INFO, error, __VA_ARGS__)
+#define log_netdev_notice_errno(netdev, error, ...)  log_netdev_full_errno(netdev, LOG_NOTICE, error, __VA_ARGS__)
+#define log_netdev_warning_errno(netdev, error, ...) log_netdev_full_errno(netdev, LOG_WARNING, error, __VA_ARGS__)
+#define log_netdev_error_errno(netdev, error, ...)   log_netdev_full_errno(netdev, LOG_ERR, error, __VA_ARGS__)
 
 #define LOG_NETDEV_MESSAGE(netdev, fmt, ...) "MESSAGE=%s: " fmt, (netdev)->ifname, ##__VA_ARGS__
 #define LOG_NETDEV_INTERFACE(netdev) "INTERFACE=%s", (netdev)->ifname
index d9d654495e0de99d361fd21b3a00345e68b9ee96..0e13c4f88ada59be97e579314d0625e82b99ce1b 100644 (file)
@@ -46,7 +46,7 @@ static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) {
 }
 
 static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) {
-        _cleanup_close_ int fd;
+        _cleanup_close_ int fd = -1;
         TunTap *t = NULL;
         const char *user;
         const char *group;
index 75d6d376a537994fedcced6b98f10916bb097ca7..b8fc492d4fcc91c881777a1ee8da39b644b5373d 100644 (file)
@@ -914,14 +914,13 @@ static int wireguard_verify(NetDev *netdev, const char *filename) {
         r = wireguard_read_key_file(w->private_key_file, w->private_key);
         if (r < 0)
                 return log_netdev_error_errno(netdev, r,
-                                              "Failed to read private key from %s. Dropping network device %s.",
-                                              w->private_key_file, netdev->ifname);
+                                              "Failed to read private key from %s. Ignoring network device.",
+                                              w->private_key_file);
 
         if (eqzero(w->private_key))
                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
                                               "%s: Missing PrivateKey= or PrivateKeyFile=, "
-                                              "Dropping network device %s.",
-                                              filename, netdev->ifname);
+                                              "Ignoring network device.", filename);
 
         LIST_FOREACH_SAFE(peers, peer, peer_next, w->peers)
                 if (wireguard_peer_verify(peer) < 0)
index faaa6a7b6caefec839dfe4e094a2c8fee963c959..52abcddd641a0da872d2019ed48e7bb3fa270f3c 100644 (file)
@@ -77,35 +77,47 @@ static bool arg_full = false;
 static unsigned arg_lines = 10;
 
 static void operational_state_to_color(const char *name, const char *state, const char **on, const char **off) {
-        assert(on);
-        assert(off);
-
         if (STRPTR_IN_SET(state, "routable", "enslaved") ||
             (streq_ptr(name, "lo") && streq_ptr(state, "carrier"))) {
-                *on = ansi_highlight_green();
-                *off = ansi_normal();
+                if (on)
+                        *on = ansi_highlight_green();
+                if (off)
+                        *off = ansi_normal();
         } else if (streq_ptr(state, "degraded")) {
-                *on = ansi_highlight_yellow();
-                *off = ansi_normal();
-        } else
-                *on = *off = "";
+                if (on)
+                        *on = ansi_highlight_yellow();
+                if (off)
+                        *off = ansi_normal();
+        } else {
+                if (on)
+                        *on = "";
+                if (off)
+                        *off = "";
+        }
 }
 
 static void setup_state_to_color(const char *state, const char **on, const char **off) {
-        assert(on);
-        assert(off);
-
         if (streq_ptr(state, "configured")) {
-                *on = ansi_highlight_green();
-                *off = ansi_normal();
+                if (on)
+                        *on = ansi_highlight_green();
+                if (off)
+                        *off = ansi_normal();
         } else if (streq_ptr(state, "configuring")) {
-                *on = ansi_highlight_yellow();
-                *off = ansi_normal();
+                if (on)
+                        *on = ansi_highlight_yellow();
+                if (off)
+                        *off = ansi_normal();
         } else if (STRPTR_IN_SET(state, "failed", "linger")) {
-                *on = ansi_highlight_red();
-                *off = ansi_normal();
-        } else
-                *on = *off = "";
+                if (on)
+                        *on = ansi_highlight_red();
+                if (off)
+                        *off = ansi_normal();
+        } else {
+                if (on)
+                        *on = "";
+                if (off)
+                        *off = "";
+        }
 }
 
 typedef struct VxLanInfo {
@@ -692,17 +704,16 @@ static int list_links(int argc, char *argv[], void *userdata) {
 
         for (int i = 0; i < c; i++) {
                 _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
-                const char *on_color_operational, *off_color_operational,
-                           *on_color_setup, *off_color_setup;
+                const char *on_color_operational, *on_color_setup;
                 _cleanup_free_ char *t = NULL;
 
                 (void) sd_network_link_get_operational_state(links[i].ifindex, &operational_state);
-                operational_state_to_color(links[i].name, operational_state, &on_color_operational, &off_color_operational);
+                operational_state_to_color(links[i].name, operational_state, &on_color_operational, NULL);
 
                 r = sd_network_link_get_setup_state(links[i].ifindex, &setup_state);
                 if (r == -ENODATA) /* If there's no info available about this iface, it's unmanaged by networkd */
                         setup_state = strdup("unmanaged");
-                setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
+                setup_state_to_color(setup_state, &on_color_setup, NULL);
 
                 t = link_get_type_string(links[i].sd_device, links[i].iftype);
 
@@ -2145,7 +2156,7 @@ static int link_status_one(
 static int system_status(sd_netlink *rtnl, sd_hwdb *hwdb) {
         _cleanup_free_ char *operational_state = NULL;
         _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL;
-        const char *on_color_operational, *off_color_operational;
+        const char *on_color_operational;
         _cleanup_(table_unrefp) Table *table = NULL;
         TableCell *cell;
         int r;
@@ -2153,7 +2164,7 @@ static int system_status(sd_netlink *rtnl, sd_hwdb *hwdb) {
         assert(rtnl);
 
         (void) sd_network_get_operational_state(&operational_state);
-        operational_state_to_color(NULL, operational_state, &on_color_operational, &off_color_operational);
+        operational_state_to_color(NULL, operational_state, &on_color_operational, NULL);
 
         table = table_new("dot", "key", "value");
         if (!table)
index 58b089901bae4d4c28be37786e07ecad2bc79874..724b0f95d3142e8dcfe5aa5d464221763aa0a03f 100644 (file)
@@ -486,37 +486,38 @@ int link_has_ipv6_address(Link *link, const struct in6_addr *address) {
 }
 
 static void log_address_debug(const Address *address, const char *str, const Link *link) {
+        _cleanup_free_ char *addr = NULL, *peer = NULL;
+        char valid_buf[FORMAT_TIMESPAN_MAX], preferred_buf[FORMAT_TIMESPAN_MAX];
+        const char *valid_str = NULL, *preferred_str = NULL;
+        bool has_peer;
+
         assert(address);
         assert(str);
         assert(link);
 
-        if (DEBUG_LOGGING) {
-                _cleanup_free_ char *addr = NULL, *peer = NULL;
-                char valid_buf[FORMAT_TIMESPAN_MAX], preferred_buf[FORMAT_TIMESPAN_MAX];
-                const char *valid_str = NULL, *preferred_str = NULL;
-                bool has_peer;
-
-                (void) in_addr_to_string(address->family, &address->in_addr, &addr);
-                has_peer = in_addr_is_set(address->family, &address->in_addr_peer);
-                if (has_peer)
-                        (void) in_addr_to_string(address->family, &address->in_addr_peer, &peer);
-
-                if (address->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
-                        valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
-                                                    address->cinfo.ifa_valid * USEC_PER_SEC,
-                                                    USEC_PER_SEC);
-
-                if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME)
-                        preferred_str = format_timespan(preferred_buf, FORMAT_TIMESPAN_MAX,
-                                                        address->cinfo.ifa_prefered * USEC_PER_SEC,
-                                                        USEC_PER_SEC);
-
-                log_link_debug(link, "%s address: %s%s%s/%u (valid %s%s, preferred %s%s)",
-                               str, strnull(addr), has_peer ? " peer " : "",
-                               has_peer ? strnull(peer) : "", address->prefixlen,
-                               valid_str ? "for " : "forever", strempty(valid_str),
-                               preferred_str ? "for " : "forever", strempty(preferred_str));
-        }
+        if (!DEBUG_LOGGING)
+                return;
+
+        (void) in_addr_to_string(address->family, &address->in_addr, &addr);
+        has_peer = in_addr_is_set(address->family, &address->in_addr_peer);
+        if (has_peer)
+                (void) in_addr_to_string(address->family, &address->in_addr_peer, &peer);
+
+        if (address->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
+                valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
+                                            address->cinfo.ifa_valid * USEC_PER_SEC,
+                                            USEC_PER_SEC);
+
+        if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME)
+                preferred_str = format_timespan(preferred_buf, FORMAT_TIMESPAN_MAX,
+                                                address->cinfo.ifa_prefered * USEC_PER_SEC,
+                                                USEC_PER_SEC);
+
+        log_link_debug(link, "%s address: %s%s%s/%u (valid %s%s, preferred %s%s)",
+                       str, strnull(addr), has_peer ? " peer " : "",
+                       has_peer ? strnull(peer) : "", address->prefixlen,
+                       valid_str ? "for " : "forever", strempty(valid_str),
+                       preferred_str ? "for " : "forever", strempty(preferred_str));
 }
 
 static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
@@ -918,6 +919,10 @@ int address_configure(
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m");
 
+        r = sd_netlink_message_append_u32(req, IFA_RT_PRIORITY, address->route_metric);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFA_RT_PRIORITY attribute: %m");
+
         k = address_add(link, address, &a);
         if (k < 0)
                 return log_link_error_errno(link, k, "Could not add address: %m");
@@ -1091,6 +1096,7 @@ int link_set_addresses(Link *link) {
                         return log_link_warning_errno(link, r, "Could not generate EUI64 address: %m");
 
                 address->family = AF_INET6;
+                address->route_metric = p->route_metric;
                 r = static_address_configure(address, link);
                 if (r < 0)
                         return r;
@@ -1801,6 +1807,48 @@ int config_parse_address_scope(
         return 0;
 }
 
+int config_parse_address_route_metric(
+                const char *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_(address_free_or_set_invalidp) Address *n = NULL;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = address_new_static(network, filename, section_line, &n);
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to allocate new address, ignoring assignment: %m");
+                return 0;
+        }
+
+        r = safe_atou32(rvalue, &n->route_metric);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Could not parse %s=, ignoring assignment: %s", lvalue, rvalue);
+                return 0;
+        }
+
+        TAKE_PTR(n);
+        return 0;
+}
+
 int config_parse_duplicate_address_detection(
                 const char *unit,
                 const char *filename,
index e3ca868c2ee8d27e3377c46c683c6ea129e8fc2d..58f44cd4cd4e2530611f7d8ae1c4559773e93bb4 100644 (file)
@@ -28,6 +28,7 @@ typedef struct Address {
         unsigned char prefixlen;
         unsigned char scope;
         uint32_t flags;
+        uint32_t route_metric; /* route metric for prefix route */
         char *label;
 
         int set_broadcast;
@@ -83,6 +84,7 @@ 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);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_route_metric);
 CONFIG_PARSER_PROTOTYPE(config_parse_duplicate_address_detection);
 
 #define IPV4_ADDRESS_FMT_STR     "%u.%u.%u.%u"
index c0018c306f9212b5caf7bc559a4a929edeb9cef7..787cfd711e7e2acf4f74932e8aaedb99043a3310 100644 (file)
@@ -52,7 +52,7 @@ int config_parse_can_bitrate(
         return 0;
 }
 
-static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         int r;
 
         assert(link);
@@ -60,53 +60,24 @@ static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
                 return 1;
 
-        r = sd_netlink_message_get_errno(m);
-        if (r < 0)
-                /* we warn but don't fail the link, as it may be brought up later */
-                log_link_message_warning_errno(link, m, r, "Could not bring up interface");
-
-        return 1;
-}
-
-static int link_up_can(Link *link) {
-        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        int r;
-
-        assert(link);
-
-        log_link_debug(link, "Bringing CAN link up");
-
-        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);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set link flags: %m");
-
-        r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
-
-        link_ref(link);
-
-        return 0;
-}
-
-static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        int r;
-
-        assert(link);
-
-        log_link_debug(link, "Set link");
-
         r = sd_netlink_message_get_errno(m);
         if (r < 0 && r != -EEXIST) {
                 log_link_message_warning_errno(link, m, r, "Failed to configure CAN link");
                 link_enter_failed(link);
+                return 1;
+        }
+
+        log_link_debug(link, "Link set");
+
+        r = link_activate(link);
+        if (r < 0) {
+                link_enter_failed(link);
+                return 1;
         }
 
+        link->can_configured = true;
+        link_check_ready(link);
+
         return 1;
 }
 
@@ -255,9 +226,6 @@ static int link_set_can(Link *link) {
 
         link_ref(link);
 
-        if (!(link->flags & IFF_UP))
-                return link_up_can(link);
-
         return 0;
 }
 
@@ -290,30 +258,21 @@ int link_configure_can(Link *link) {
 
         if (streq_ptr(link->kind, "can")) {
                 /* The CAN interface must be down to configure bitrate, etc... */
-                if ((link->flags & IFF_UP)) {
+                if ((link->flags & IFF_UP))
                         r = link_down(link, link_down_handler);
-                        if (r < 0) {
-                                link_enter_failed(link);
-                                return r;
-                        }
-                } else {
+                else
                         r = link_set_can(link);
-                        if (r < 0) {
-                                link_enter_failed(link);
-                                return r;
-                        }
-                }
-
-                return 0;
-        }
-
-        if (!(link->flags & IFF_UP)) {
-                r = link_up_can(link);
-                if (r < 0) {
+                if (r < 0)
                         link_enter_failed(link);
-                        return r;
-                }
+                return r;
         }
 
+        r = link_activate(link);
+        if (r < 0)
+                return r;
+
+        link->can_configured = true;
+        link_check_ready(link);
+
         return 0;
 }
index c413f167394e811da0c9f308434fefa897b2e0f3..0b55ef29a2581252d606fd8b88588b3ef8e72e30 100644 (file)
@@ -3,20 +3,11 @@
   Copyright © 2014 Vinay Kulkarni <kulkarniv@vmware.com>
  ***/
 
-#include <ctype.h>
-#include <netinet/ip.h>
-
 #include "conf-parser.h"
 #include "def.h"
-#include "dhcp-identifier.h"
-#include "extract-word.h"
-#include "hexdecoct.h"
 #include "networkd-conf.h"
 #include "networkd-manager.h"
-#include "networkd-network.h"
 #include "networkd-speed-meter.h"
-#include "networkd-dhcp4.h"
-#include "string-table.h"
 
 int manager_parse_config_file(Manager *m) {
         int r;
@@ -27,6 +18,8 @@ int manager_parse_config_file(Manager *m) {
                         PKGSYSCONFDIR "/networkd.conf",
                         CONF_PATHS_NULSTR("systemd/networkd.conf.d"),
                         "Network\0"
+                        "DHCPv4\0"
+                        "DHCPv6\0"
                         "DHCP\0",
                         config_item_perf_lookup, networkd_gperf_lookup,
                         CONFIG_PARSE_WARN,
@@ -45,147 +38,3 @@ int manager_parse_config_file(Manager *m) {
 
         return 0;
 }
-
-static const char* const duid_type_table[_DUID_TYPE_MAX] = {
-        [DUID_TYPE_LLT]  = "link-layer-time",
-        [DUID_TYPE_EN]   = "vendor",
-        [DUID_TYPE_LL]   = "link-layer",
-        [DUID_TYPE_UUID] = "uuid",
-};
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(duid_type, DUIDType);
-
-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) {
-
-        _cleanup_free_ char *type_string = NULL;
-        const char *p = rvalue;
-        DUID *duid = data;
-        DUIDType type;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(duid);
-
-        r = extract_first_word(&p, &type_string, ":", 0);
-        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) {
-                log_syntax(unit, LOG_WARNING, filename, line, 0,
-                           "Failed to extract DUID type from '%s', ignoring.", rvalue);
-                return 0;
-        }
-
-        type = duid_type_from_string(type_string);
-        if (type < 0) {
-                log_syntax(unit, LOG_WARNING, filename, line, type,
-                           "Failed to parse DUID type '%s', ignoring.", type_string);
-                return 0;
-        }
-
-        if (!isempty(p)) {
-                usec_t u;
-
-                if (type != DUID_TYPE_LLT) {
-                        log_syntax(unit, LOG_WARNING, filename, line, r,
-                                   "Invalid syntax, ignoring: %s", rvalue);
-                        return 0;
-                }
-
-                r = parse_timestamp(p, &u);
-                if (r < 0) {
-                        log_syntax(unit, LOG_WARNING, filename, line, r,
-                                   "Failed to parse timestamp, ignoring: %s", p);
-                        return 0;
-                }
-
-                duid->llt_time = u;
-        }
-
-        duid->type = type;
-
-        return 0;
-}
-
-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) {
-
-        DUID *ret = data;
-        uint8_t raw_data[MAX_DUID_LEN];
-        unsigned count = 0;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(ret);
-
-        /* RawData contains DUID in format "NN:NN:NN..." */
-        for (const char *p = rvalue;;) {
-                int n1, n2, len, r;
-                uint32_t byte;
-                _cleanup_free_ char *cbyte = NULL;
-
-                r = extract_first_word(&p, &cbyte, ":", 0);
-                if (r == -ENOMEM)
-                        return log_oom();
-                if (r < 0) {
-                        log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to read DUID, ignoring assignment: %s.", rvalue);
-                        return 0;
-                }
-                if (r == 0)
-                        break;
-
-                if (count >= MAX_DUID_LEN) {
-                        log_syntax(unit, LOG_WARNING, filename, line, 0, "Max DUID length exceeded, ignoring assignment: %s.", rvalue);
-                        return 0;
-                }
-
-                len = strlen(cbyte);
-                if (!IN_SET(len, 1, 2)) {
-                        log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid length - DUID byte: %s, ignoring assignment: %s.", cbyte, rvalue);
-                        return 0;
-                }
-                n1 = unhexchar(cbyte[0]);
-                if (len == 2)
-                        n2 = unhexchar(cbyte[1]);
-                else
-                        n2 = 0;
-
-                if (n1 < 0 || n2 < 0) {
-                        log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid DUID byte: %s. Ignoring assignment: %s.", cbyte, rvalue);
-                        return 0;
-                }
-
-                byte = ((uint8_t) n1 << (4 * (len-1))) | (uint8_t) n2;
-                raw_data[count++] = byte;
-        }
-
-        assert_cc(sizeof(raw_data) == sizeof(ret->raw_data));
-        memcpy(ret->raw_data, raw_data, count);
-        ret->raw_data_len = count;
-        return 0;
-}
index b485e9e5418c695a8ba70bbad14b0f7cac388fbf..6f8612ac9191f0c874d1c1e6afc087fe4d5ecd45 100644 (file)
@@ -12,6 +12,3 @@ typedef struct Manager Manager;
 int manager_parse_config_file(Manager *m);
 
 const struct ConfigPerfItem* networkd_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-
-CONFIG_PARSER_PROTOTYPE(config_parse_duid_type);
-CONFIG_PARSER_PROTOTYPE(config_parse_duid_rawdata);
index 00d055cf8db355dd94ee7d9602605e5e736ae948..8357b2b99dffa83bd4b2e4c1a82374a0719a0909 100644 (file)
@@ -4,9 +4,11 @@
 #include <linux/if_arp.h>
 
 #include "bus-error.h"
+#include "dhcp-identifier.h"
 #include "dhcp-internal.h"
 #include "dhcp6-internal.h"
 #include "escape.h"
+#include "hexdecoct.h"
 #include "in-addr-util.h"
 #include "networkd-dhcp-common.h"
 #include "networkd-link.h"
@@ -57,33 +59,79 @@ void network_adjust_dhcp(Network *network) {
                             "Disabling DHCPv6 client.", network->filename);
                 SET_FLAG(network->dhcp, ADDRESS_FAMILY_IPV6, false);
         }
+
+        network_adjust_dhcp4(network);
+}
+
+static bool duid_needs_product_uuid(const DUID *duid) {
+        assert(duid);
+
+        return duid->type == DUID_TYPE_UUID && duid->raw_data_len == 0;
 }
 
-static struct DUID fallback_duid = { .type = DUID_TYPE_EN };
-DUID* link_get_duid(Link *link) {
-        if (link->network->duid.type != _DUID_TYPE_INVALID)
-                return &link->network->duid;
-        else if (link->hw_addr.length == 0 && IN_SET(link->manager->duid.type, DUID_TYPE_LLT, DUID_TYPE_LL))
+static const struct DUID fallback_duid = { .type = DUID_TYPE_EN };
+
+const DUID *link_get_duid(Link *link, int family) {
+        const DUID *duid;
+
+        assert(link);
+        assert(IN_SET(family, AF_INET, AF_INET6));
+
+        if (link->network) {
+                duid = family == AF_INET ? &link->network->dhcp_duid : &link->network->dhcp6_duid;
+                if (duid->type != _DUID_TYPE_INVALID) {
+                        if (duid_needs_product_uuid(duid))
+                                return &link->manager->duid_product_uuid;
+                        else
+                                return duid;
+                }
+        }
+
+        duid = family == AF_INET ? &link->manager->dhcp_duid : &link->manager->dhcp6_duid;
+        if (link->hw_addr.length == 0 && IN_SET(duid->type, DUID_TYPE_LLT, DUID_TYPE_LL))
                 /* Fallback to DUID that works without MAC address.
                  * This is useful for tunnel devices without MAC address. */
                 return &fallback_duid;
-        else
-                return &link->manager->duid;
+
+        return duid;
 }
 
-static int duid_set_uuid(DUID *duid, sd_id128_t uuid) {
-        assert(duid);
+static int link_configure_and_start_dhcp_delayed(Link *link) {
+        int r;
+
+        assert(link);
 
-        if (duid->raw_data_len > 0)
+        if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
                 return 0;
 
-        if (duid->type != DUID_TYPE_UUID)
-                return -EINVAL;
+        if (!link->dhcp_client) {
+                r = dhcp4_configure(link);
+                if (r < 0)
+                        return r;
+        }
+
+        if (!link->dhcp6_client) {
+                r = dhcp6_configure(link);
+                if (r < 0)
+                        return r;
+        }
 
-        memcpy(&duid->raw_data, &uuid, sizeof(sd_id128_t));
-        duid->raw_data_len = sizeof(sd_id128_t);
+        if (!link_has_carrier(link))
+                return 0;
 
-        return 1;
+        r = dhcp4_start(link);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to start DHCPv4 client: %m");
+
+        r = ndisc_start(link);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m");
+
+        r = dhcp6_start(link);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to start DHCPv6 client: %m");
+
+        return 0;
 }
 
 static int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
@@ -91,7 +139,6 @@ static int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_er
         const sd_bus_error *e;
         const void *a;
         size_t sz;
-        DUID *duid;
         Link *link;
         int r;
 
@@ -117,57 +164,38 @@ static int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_er
                 goto configure;
         }
 
-        memcpy(&manager->product_uuid, a, sz);
-        while ((duid = set_steal_first(manager->duids_requesting_uuid)))
-                (void) duid_set_uuid(duid, manager->product_uuid);
-
-        manager->duids_requesting_uuid = set_free(manager->duids_requesting_uuid);
+        memcpy(&manager->duid_product_uuid.raw_data, a, sz);
+        manager->duid_product_uuid.raw_data_len = sz;
 
 configure:
-        while ((link = set_steal_first(manager->links_requesting_uuid))) {
-                link_unref(link);
+        /* To avoid calling GetProductUUID() bus method so frequently, set the flag below
+         * even if the method fails. */
+        manager->has_product_uuid = true;
 
-                r = link_configure(link);
+        while ((link = set_steal_first(manager->links_requesting_uuid))) {
+                r = link_configure_and_start_dhcp_delayed(link);
                 if (r < 0)
                         link_enter_failed(link);
+
+                link_unref(link);
         }
 
         manager->links_requesting_uuid = set_free(manager->links_requesting_uuid);
 
-        /* To avoid calling GetProductUUID() bus method so frequently, set the flag below
-         * even if the method fails. */
-        manager->has_product_uuid = true;
-
         return 1;
 }
 
-int manager_request_product_uuid(Manager *m, Link *link) {
+int manager_request_product_uuid(Manager *m) {
         int r;
 
         assert(m);
 
-        if (m->has_product_uuid)
+        if (m->product_uuid_requested)
                 return 0;
 
         log_debug("Requesting product UUID");
 
-        if (link) {
-                DUID *duid;
-
-                assert_se(duid = link_get_duid(link));
-
-                r = set_ensure_put(&m->links_requesting_uuid, NULL, link);
-                if (r < 0)
-                        return log_oom();
-                if (r > 0)
-                        link_ref(link);
-
-                r = set_ensure_put(&m->duids_requesting_uuid, NULL, duid);
-                if (r < 0)
-                        return log_oom();
-        }
-
-        if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
+        if (sd_bus_is_ready(m->bus) <= 0) {
                 log_debug("Not connected to system bus, requesting product UUID later.");
                 return 0;
         }
@@ -186,71 +214,40 @@ int manager_request_product_uuid(Manager *m, Link *link) {
         if (r < 0)
                 return log_warning_errno(r, "Failed to get product UUID: %m");
 
-        return 0;
-}
-
-static bool link_requires_uuid(Link *link) {
-        const DUID *duid;
-
-        assert(link);
-        assert(link->manager);
-        assert(link->network);
-
-        duid = link_get_duid(link);
-        if (duid->type != DUID_TYPE_UUID || duid->raw_data_len != 0)
-                return false;
+        m->product_uuid_requested = true;
 
-        if (link_dhcp4_enabled(link) && IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY))
-                return true;
-
-        if (link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link))
-                return true;
-
-        return false;
+        return 0;
 }
 
-int link_configure_duid(Link *link) {
+int dhcp_configure_duid(Link *link, const DUID *duid) {
         Manager *m;
-        DUID *duid;
         int r;
 
         assert(link);
         assert(link->manager);
-        assert(link->network);
+        assert(duid);
 
         m = link->manager;
-        duid = link_get_duid(link);
 
-        if (!link_requires_uuid(link))
+        if (!duid_needs_product_uuid(duid))
                 return 1;
 
-        if (m->has_product_uuid) {
-                (void) duid_set_uuid(duid, m->product_uuid);
+        if (m->has_product_uuid)
                 return 1;
-        }
-
-        if (!m->links_requesting_uuid) {
-                r = manager_request_product_uuid(m, link);
-                if (r < 0) {
-                        if (r == -ENOMEM)
-                                return r;
 
-                        log_link_warning_errno(link, r,
-                                               "Failed to get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %m");
-                        return 1;
-                }
-        } else {
-                r = set_put(m->links_requesting_uuid, link);
-                if (r < 0)
-                        return log_oom();
-                if (r > 0)
-                        link_ref(link);
-
-                r = set_put(m->duids_requesting_uuid, duid);
-                if (r < 0)
-                        return log_oom();
+        r = manager_request_product_uuid(m);
+        if (r < 0) {
+                log_link_warning_errno(link, r,
+                                       "Failed to get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %m");
+                return 1;
         }
 
+        r = set_ensure_put(&m->links_requesting_uuid, NULL, link);
+        if (r < 0)
+                return log_oom();
+        if (r > 0)
+                link_ref(link);
+
         return 0;
 }
 
@@ -311,7 +308,7 @@ int config_parse_dhcp_route_metric(
                 void *data,
                 void *userdata) {
 
-        Network *network = data;
+        Network *network = userdata;
         uint32_t metric;
         int r;
 
@@ -330,14 +327,14 @@ int config_parse_dhcp_route_metric(
         if (streq_ptr(section, "DHCPv4")) {
                 network->dhcp_route_metric = metric;
                 network->dhcp_route_metric_set = true;
-        } else if (streq_ptr(section, "DHCPv6")) {
-                network->dhcp6_route_metric = metric;
-                network->dhcp6_route_metric_set = true;
+        } else if (STRPTR_IN_SET(section, "DHCPv6", "IPv6AcceptRA")) {
+                network->ipv6_accept_ra_route_metric = metric;
+                network->ipv6_accept_ra_route_metric_set = true;
         } else { /* [DHCP] section */
                 if (!network->dhcp_route_metric_set)
                         network->dhcp_route_metric = metric;
-                if (!network->dhcp6_route_metric_set)
-                        network->dhcp6_route_metric = metric;
+                if (!network->ipv6_accept_ra_route_metric_set)
+                        network->ipv6_accept_ra_route_metric = metric;
         }
 
         return 0;
@@ -355,7 +352,7 @@ int config_parse_dhcp_use_dns(
                 void *data,
                 void *userdata) {
 
-        Network *network = data;
+        Network *network = userdata;
         int r;
 
         assert(filename);
@@ -386,6 +383,49 @@ int config_parse_dhcp_use_dns(
         return 0;
 }
 
+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) {
+
+        Network *network = userdata;
+        DHCPUseDomains d;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        d = dhcp_use_domains_from_string(rvalue);
+        if (d < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, d,
+                           "Failed to parse %s=%s, ignoring assignment: %m", lvalue, rvalue);
+                return 0;
+        }
+
+        if (streq_ptr(section, "DHCPv4")) {
+                network->dhcp_use_domains = d;
+                network->dhcp_use_domains_set = true;
+        } else if (streq_ptr(section, "DHCPv6")) {
+                network->dhcp6_use_domains = d;
+                network->dhcp6_use_domains_set = true;
+        } else { /* [DHCP] section */
+                if (!network->dhcp_use_domains_set)
+                        network->dhcp_use_domains = d;
+                if (!network->dhcp6_use_domains_set)
+                        network->dhcp6_use_domains = d;
+        }
+
+        return 0;
+}
+
 int config_parse_dhcp_use_ntp(
                 const char* unit,
                 const char *filename,
@@ -398,7 +438,7 @@ int config_parse_dhcp_use_ntp(
                 void *data,
                 void *userdata) {
 
-        Network *network = data;
+        Network *network = userdata;
         int r;
 
         assert(filename);
@@ -441,7 +481,7 @@ int config_parse_section_route_table(
                 void *data,
                 void *userdata) {
 
-        Network *network = data;
+        Network *network = userdata;
         uint32_t rt;
         int r;
 
@@ -478,7 +518,8 @@ int config_parse_iaid(const char *unit,
                       const char *rvalue,
                       void *data,
                       void *userdata) {
-        Network *network = data;
+
+        Network *network = userdata;
         uint32_t iaid;
         int r;
 
@@ -486,6 +527,7 @@ int config_parse_iaid(const char *unit,
         assert(lvalue);
         assert(rvalue);
         assert(network);
+        assert(IN_SET(ltype, AF_INET, AF_INET6));
 
         r = safe_atou32(rvalue, &iaid);
         if (r < 0) {
@@ -494,8 +536,21 @@ int config_parse_iaid(const char *unit,
                 return 0;
         }
 
-        network->iaid = iaid;
-        network->iaid_set = true;
+        if (ltype == AF_INET) {
+                network->dhcp_iaid = iaid;
+                network->dhcp_iaid_set = true;
+                if (!network->dhcp6_iaid_set_explicitly) {
+                        /* Backward compatibility. Previously, IAID is shared by DHCP4 and DHCP6.
+                         * If DHCP6 IAID is not specified explicitly, then use DHCP4 IAID for DHCP6. */
+                        network->dhcp6_iaid = iaid;
+                        network->dhcp6_iaid_set = true;
+                }
+        } else {
+                assert(ltype == AF_INET6);
+                network->dhcp6_iaid = iaid;
+                network->dhcp6_iaid_set = true;
+                network->dhcp6_iaid_set_explicitly = true;
+        }
 
         return 0;
 }
@@ -807,7 +862,7 @@ int config_parse_dhcp_request_options(
                 void *data,
                 void *userdata) {
 
-        Network *network = data;
+        Network *network = userdata;
         int r;
 
         assert(filename);
@@ -861,9 +916,6 @@ int config_parse_dhcp_request_options(
         }
 }
 
-DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
-                         "Failed to parse DHCP use domains setting");
-
 static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
         [DHCP_USE_DOMAINS_NO] = "no",
         [DHCP_USE_DOMAINS_ROUTE] = "route",
@@ -882,3 +934,260 @@ static const char * const dhcp_option_data_type_table[_DHCP_OPTION_DATA_MAX] = {
 };
 
 DEFINE_STRING_TABLE_LOOKUP(dhcp_option_data_type, DHCPOptionDataType);
+
+static const char* const duid_type_table[_DUID_TYPE_MAX] = {
+        [DUID_TYPE_LLT]  = "link-layer-time",
+        [DUID_TYPE_EN]   = "vendor",
+        [DUID_TYPE_LL]   = "link-layer",
+        [DUID_TYPE_UUID] = "uuid",
+};
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(duid_type, DUIDType);
+
+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) {
+
+        _cleanup_free_ char *type_string = NULL;
+        const char *p = rvalue;
+        bool force = ltype;
+        DUID *duid = data;
+        DUIDType type;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(duid);
+
+        if (!force && duid->set)
+                return 0;
+
+        r = extract_first_word(&p, &type_string, ":", 0);
+        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) {
+                log_syntax(unit, LOG_WARNING, filename, line, 0,
+                           "Failed to extract DUID type from '%s', ignoring.", rvalue);
+                return 0;
+        }
+
+        type = duid_type_from_string(type_string);
+        if (type < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, type,
+                           "Failed to parse DUID type '%s', ignoring.", type_string);
+                return 0;
+        }
+
+        if (!isempty(p)) {
+                usec_t u;
+
+                if (type != DUID_TYPE_LLT) {
+                        log_syntax(unit, LOG_WARNING, filename, line, r,
+                                   "Invalid syntax, ignoring: %s", rvalue);
+                        return 0;
+                }
+
+                r = parse_timestamp(p, &u);
+                if (r < 0) {
+                        log_syntax(unit, LOG_WARNING, filename, line, r,
+                                   "Failed to parse timestamp, ignoring: %s", p);
+                        return 0;
+                }
+
+                duid->llt_time = u;
+        }
+
+        duid->type = type;
+        duid->set = force;
+
+        return 0;
+}
+
+int config_parse_manager_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) {
+
+        Manager *manager = userdata;
+        int r;
+
+        assert(manager);
+
+        /* For backward compatibility. Setting both DHCP4 and DHCP6 DUID if they are not specified explicitly. */
+
+        r = config_parse_duid_type(unit, filename, line, section, section_line, lvalue, false, rvalue, &manager->dhcp_duid, manager);
+        if (r < 0)
+                return r;
+
+        return config_parse_duid_type(unit, filename, line, section, section_line, lvalue, false, rvalue, &manager->dhcp6_duid, manager);
+}
+
+int config_parse_network_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) {
+
+        Network *network = userdata;
+        int r;
+
+        assert(network);
+
+        r = config_parse_duid_type(unit, filename, line, section, section_line, lvalue, true, rvalue, &network->dhcp_duid, network);
+        if (r < 0)
+                return r;
+
+        /* For backward compatibility, also set DHCP6 DUID if not specified explicitly. */
+        return config_parse_duid_type(unit, filename, line, section, section_line, lvalue, false, rvalue, &network->dhcp6_duid, network);
+}
+
+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) {
+
+        uint8_t raw_data[MAX_DUID_LEN];
+        unsigned count = 0;
+        bool force = ltype;
+        DUID *duid = data;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(duid);
+
+        if (!force && duid->set)
+                return 0;
+
+        /* RawData contains DUID in format "NN:NN:NN..." */
+        for (const char *p = rvalue;;) {
+                int n1, n2, len, r;
+                uint32_t byte;
+                _cleanup_free_ char *cbyte = NULL;
+
+                r = extract_first_word(&p, &cbyte, ":", 0);
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to read DUID, ignoring assignment: %s.", rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        break;
+
+                if (count >= MAX_DUID_LEN) {
+                        log_syntax(unit, LOG_WARNING, filename, line, 0, "Max DUID length exceeded, ignoring assignment: %s.", rvalue);
+                        return 0;
+                }
+
+                len = strlen(cbyte);
+                if (!IN_SET(len, 1, 2)) {
+                        log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid length - DUID byte: %s, ignoring assignment: %s.", cbyte, rvalue);
+                        return 0;
+                }
+                n1 = unhexchar(cbyte[0]);
+                if (len == 2)
+                        n2 = unhexchar(cbyte[1]);
+                else
+                        n2 = 0;
+
+                if (n1 < 0 || n2 < 0) {
+                        log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid DUID byte: %s. Ignoring assignment: %s.", cbyte, rvalue);
+                        return 0;
+                }
+
+                byte = ((uint8_t) n1 << (4 * (len-1))) | (uint8_t) n2;
+                raw_data[count++] = byte;
+        }
+
+        assert_cc(sizeof(raw_data) == sizeof(duid->raw_data));
+        memcpy(duid->raw_data, raw_data, count);
+        duid->raw_data_len = count;
+        duid->set = force;
+
+        return 0;
+}
+
+int config_parse_manager_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) {
+
+        Manager *manager = userdata;
+        int r;
+
+        assert(manager);
+
+        /* For backward compatibility. Setting both DHCP4 and DHCP6 DUID if they are not specified explicitly. */
+
+        r = config_parse_duid_rawdata(unit, filename, line, section, section_line, lvalue, false, rvalue, &manager->dhcp_duid, manager);
+        if (r < 0)
+                return r;
+
+        return config_parse_duid_rawdata(unit, filename, line, section, section_line, lvalue, false, rvalue, &manager->dhcp6_duid, manager);
+}
+
+int config_parse_network_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) {
+
+        Network *network = userdata;
+        int r;
+
+        assert(network);
+
+        r = config_parse_duid_rawdata(unit, filename, line, section, section_line, lvalue, true, rvalue, &network->dhcp_duid, network);
+        if (r < 0)
+                return r;
+
+        /* For backward compatibility, also set DHCP6 DUID if not specified explicitly. */
+        return config_parse_duid_rawdata(unit, filename, line, section, section_line, lvalue, false, rvalue, &network->dhcp6_duid, network);
+}
index acf80e62555bc0826bd9146f1ba86f16de0f3aff..316f5cf10b22be3260434a0c9f0c3ed1b07af82a 100644 (file)
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include <netinet/in.h>
+
 #include "conf-parser.h"
 #include "dhcp-identifier.h"
 #include "time-util.h"
@@ -37,6 +39,7 @@ typedef struct DUID {
         uint8_t raw_data_len;
         uint8_t raw_data[MAX_DUID_LEN];
         usec_t llt_time;
+        bool set;
 } DUID;
 
 bool link_dhcp_enabled(Link *link, int family);
@@ -49,9 +52,16 @@ static inline bool link_dhcp6_enabled(Link *link) {
 
 void network_adjust_dhcp(Network *network);
 
-DUID* link_get_duid(Link *link);
-int link_configure_duid(Link *link);
-int manager_request_product_uuid(Manager *m, Link *link);
+const DUID *link_get_duid(Link *link, int family);
+static inline const DUID *link_get_dhcp4_duid(Link *link) {
+        return link_get_duid(link, AF_INET);
+}
+static inline const DUID *link_get_dhcp6_duid(Link *link) {
+        return link_get_duid(link, AF_INET6);
+}
+
+int dhcp_configure_duid(Link *link, const DUID *duid);
+int manager_request_product_uuid(Manager *m);
 
 const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
 DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
@@ -69,3 +79,9 @@ CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_or_vendor_class);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_request_options);
+CONFIG_PARSER_PROTOTYPE(config_parse_duid_type);
+CONFIG_PARSER_PROTOTYPE(config_parse_manager_duid_type);
+CONFIG_PARSER_PROTOTYPE(config_parse_network_duid_type);
+CONFIG_PARSER_PROTOTYPE(config_parse_duid_rawdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_manager_duid_rawdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_network_duid_rawdata);
index 32f4baed78c6ff2c97750802fe51ff22ac8e4bf0..91a10dc33a036edc67f420d3b902f5fed0856a72 100644 (file)
@@ -31,6 +31,9 @@ static int property_get_leases(
         if (!s)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Link %s has no DHCP server.", l->ifname);
 
+        if (sd_dhcp_server_is_in_relay_mode(s))
+                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Link %s has DHCP relay agent active.", l->ifname);
+
         r = sd_bus_message_open_container(reply, 'a', "(uayayayayt)");
         if (r < 0)
                 return r;
index ad979fb2c4e7697a7f53e24e4aa1e11d5a2892d4..bd368672da77ae25b1ac7fb2c251b8d20ee1890d 100644 (file)
@@ -344,10 +344,18 @@ int dhcp4_server_configure(Link *link) {
                                                dhcp_lease_server_type_to_string(type));
         }
 
+        r = sd_dhcp_server_set_bind_to_interface(link->dhcp_server, link->network->dhcp_server_bind_to_interface);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to set interface binding for DHCP server: %m");
+
         r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router);
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to set router emission for DHCP server: %m");
 
+        r = sd_dhcp_server_set_relay_target(link->dhcp_server, &link->network->dhcp_server_relay_target);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to set relay target for DHCP server: %m");
+
         if (link->network->dhcp_server_emit_timezone) {
                 _cleanup_free_ char *buffer = NULL;
                 const char *tz;
@@ -394,6 +402,32 @@ int dhcp4_server_configure(Link *link) {
         return 0;
 }
 
+int config_parse_dhcp_server_relay_target(
+                const char *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;
+        union in_addr_union a;
+        int r;
+
+        r = in_addr_from_string(AF_INET, rvalue, &a);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to parse %s= address '%s', ignoring: %m", lvalue, rvalue);
+                return 0;
+        }
+        network->dhcp_server_relay_target = a.in;
+        return r;
+}
+
 int config_parse_dhcp_server_emit(
                 const char *unit,
                 const char *filename,
index 4bd5120ea0b2c0d8ac1ef9ce3825b2941cf3d7d5..9e5d24fbe8107200258897429a7251acd9b2ff73 100644 (file)
@@ -9,4 +9,5 @@ typedef struct Link Link;
 
 int dhcp4_server_configure(Link *link);
 
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_relay_target);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_emit);
index 6f06e2218d348897461b8b66984da1fc4351d998..f20264be9e28f1b2b7fbf014ae6cb3624437302d 100644 (file)
 static int dhcp4_update_address(Link *link, bool announce);
 static int dhcp4_remove_all(Link *link);
 
+void network_adjust_dhcp4(Network *network) {
+        assert(network);
+
+        if (!FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4))
+                return;
+
+        if (network->dhcp_use_gateway < 0)
+                network->dhcp_use_gateway = network->dhcp_use_routes;
+
+        /* RFC7844 section 3.: MAY contain the Client Identifier option
+         * Section 3.5: clients MUST use client identifiers based solely on the link-layer address
+         * NOTE: Using MAC, as it does not reveal extra information, and some servers might not answer
+         * if this option is not sent */
+        if (network->dhcp_anonymize &&
+            network->dhcp_client_identifier >= 0 &&
+            network->dhcp_client_identifier != DHCP_CLIENT_ID_MAC) {
+                log_warning("%s: ClientIdentifier= is set, although Anonymize=yes. Using ClientIdentifier=mac.",
+                            network->filename);
+                network->dhcp_client_identifier = DHCP_CLIENT_ID_MAC;
+        }
+
+        if (network->dhcp_client_identifier < 0)
+                network->dhcp_client_identifier = network->dhcp_anonymize ? DHCP_CLIENT_ID_MAC : DHCP_CLIENT_ID_DUID;
+}
+
 static int dhcp4_release_old_lease(Link *link) {
         Route *route;
         int k, r = 0;
@@ -118,25 +143,6 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
         return 1;
 }
 
-static int route_scope_from_address(const Route *route, const struct in_addr *self_addr) {
-        assert(route);
-        assert(self_addr);
-
-        if (in4_addr_is_localhost(&route->dst.in) ||
-            (in4_addr_is_set(self_addr) && in4_addr_equal(&route->dst.in, self_addr)))
-                return RT_SCOPE_HOST;
-        else if (in4_addr_is_null(&route->gw.in))
-                return RT_SCOPE_LINK;
-        else
-                return RT_SCOPE_UNIVERSE;
-}
-
-static bool link_prefixroute(Link *link) {
-        return !link->network->dhcp_route_table_set ||
-                link->network->dhcp_route_table == RT_TABLE_MAIN ||
-                link->manager->dhcp4_prefix_root_cannot_set_table;
-}
-
 static int dhcp_route_configure(Route *route, Link *link) {
         Route *ret;
         int r;
@@ -159,64 +165,281 @@ static int dhcp_route_configure(Route *route, Link *link) {
         return 0;
 }
 
-static int link_set_dns_routes(Link *link, const struct in_addr *address) {
-        const struct in_addr *dns;
-        uint32_t table;
+static bool link_prefixroute(Link *link) {
+        return !link->network->dhcp_route_table_set ||
+                link->network->dhcp_route_table == RT_TABLE_MAIN ||
+                link->manager->dhcp4_prefix_root_cannot_set_table;
+}
+
+static int link_set_dhcp_prefix_route(Link *link) {
+        _cleanup_(route_freep) Route *route = NULL;
+        struct in_addr address, netmask;
+        int r;
+
+        assert(link);
+        assert(link->dhcp_lease);
+
+        if (link_prefixroute(link))
+                /* When true, the route will be created by kernel. See dhcp4_update_address(). */
+                return 0;
+
+        r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
+        if (r < 0)
+                return r;
+
+        r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
+        if (r < 0)
+                return r;
+
+        r = route_new(&route);
+        if (r < 0)
+                return r;
+
+        route->family = AF_INET;
+        route->dst.in.s_addr = address.s_addr & netmask.s_addr;
+        route->dst_prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
+        route->prefsrc.in = address;
+        route->scope = RT_SCOPE_LINK;
+        route->protocol = RTPROT_DHCP;
+        route->table = link_get_dhcp_route_table(link);
+        route->mtu = link->network->dhcp_route_mtu;
+
+        return dhcp_route_configure(route, link);
+}
+
+static int link_set_dhcp_route_to_gateway(Link *link, const struct in_addr *gw) {
+        _cleanup_(route_freep) Route *route = NULL;
+        struct in_addr address;
+        int r;
+
+        assert(link);
+        assert(link->dhcp_lease);
+        assert(gw);
+
+        r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
+        if (r < 0)
+                return r;
+
+        r = route_new(&route);
+        if (r < 0)
+                return r;
+
+        route->family = AF_INET;
+        route->dst.in = *gw;
+        route->dst_prefixlen = 32;
+        route->prefsrc.in = address;
+        route->scope = RT_SCOPE_LINK;
+        route->protocol = RTPROT_DHCP;
+        route->priority = link->network->dhcp_route_metric;
+        route->table = link_get_dhcp_route_table(link);
+        route->mtu = link->network->dhcp_route_mtu;
+
+        return dhcp_route_configure(route, link);
+}
+
+static int dhcp_route_configure_auto(
+                Route *route,
+                Link *link,
+                const struct in_addr *gw) {
+
+        struct in_addr address, netmask, prefix;
+        uint8_t prefixlen;
+        int r;
+
+        assert(route);
+        assert(link);
+        assert(link->dhcp_lease);
+        assert(gw);
+
+        /* The route object may be reused in an iteration. All elements must be set or cleared. */
+
+        r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
+        if (r < 0)
+                return r;
+
+        r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
+        if (r < 0)
+                return r;
+
+        prefix.s_addr = address.s_addr & netmask.s_addr;
+        prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
+
+        if (in4_addr_is_localhost(&route->dst.in)) {
+                if (in4_addr_is_set(gw))
+                        log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is localhost, "
+                                       "ignoring gateway address "IPV4_ADDRESS_FMT_STR,
+                                       IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, IPV4_ADDRESS_FMT_VAL(*gw));
+
+                route->scope = RT_SCOPE_HOST;
+                route->gw_family = AF_UNSPEC;
+                route->gw = IN_ADDR_NULL;
+                route->prefsrc = IN_ADDR_NULL;
+
+        } else if (in4_addr_equal(&route->dst.in, &address)) {
+                if (in4_addr_is_set(gw))
+                        log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is equivalent to the acquired address, "
+                                       "ignoring gateway address "IPV4_ADDRESS_FMT_STR,
+                                       IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, IPV4_ADDRESS_FMT_VAL(*gw));
+
+                route->scope = RT_SCOPE_HOST;
+                route->gw_family = AF_UNSPEC;
+                route->gw = IN_ADDR_NULL;
+                route->prefsrc.in = address;
+
+        } else if (route->dst_prefixlen >= prefixlen &&
+                   (route->dst.in.s_addr & netmask.s_addr) == prefix.s_addr) {
+                if (in4_addr_is_set(gw))
+                        log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is in the assigned network "
+                                       IPV4_ADDRESS_FMT_STR"/%u, ignoring gateway address "IPV4_ADDRESS_FMT_STR,
+                                       IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen,
+                                       IPV4_ADDRESS_FMT_VAL(prefix), prefixlen,
+                                       IPV4_ADDRESS_FMT_VAL(*gw));
+
+                route->scope = RT_SCOPE_LINK;
+                route->gw_family = AF_UNSPEC;
+                route->gw = IN_ADDR_NULL;
+                route->prefsrc.in = address;
+
+        } else {
+                if (in4_addr_is_null(gw)) {
+                        log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is not in the assigned network "
+                                       IPV4_ADDRESS_FMT_STR"/%u, but no gateway is specified, ignoring.",
+                                       IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen,
+                                       IPV4_ADDRESS_FMT_VAL(prefix), prefixlen);
+                        return 0;
+                }
+
+                r = link_set_dhcp_route_to_gateway(link, gw);
+                if (r < 0)
+                        return r;
+
+                route->scope = RT_SCOPE_UNIVERSE;
+                route->gw_family = AF_INET;
+                route->gw.in = *gw;
+                route->prefsrc.in = address;
+        }
+
+        return dhcp_route_configure(route, link);
+}
+
+static int link_set_dhcp_static_routes(Link *link, struct in_addr *ret_default_gw) {
+        _cleanup_free_ sd_dhcp_route **static_routes = NULL;
+        bool classless_route = false, static_route = false;
+        _cleanup_(route_freep) Route *route = NULL;
+        struct in_addr default_gw = {};
         int n, r;
 
         assert(link);
         assert(link->dhcp_lease);
-        assert(link->network);
+        assert(ret_default_gw);
 
-        if (!link->network->dhcp_use_dns ||
-            !link->network->dhcp_routes_to_dns)
+        if (!link->network->dhcp_use_routes)
                 return 0;
 
-        n = sd_dhcp_lease_get_dns(link->dhcp_lease, &dns);
-        if (IN_SET(n, 0, -ENODATA))
+        n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
+        if (IN_SET(n, 0, -ENODATA)) {
+                log_link_debug(link, "DHCP: No static routes received from DHCP server.");
                 return 0;
+        }
         if (n < 0)
-                return log_link_warning_errno(link, n, "DHCP error: could not get DNS servers: %m");
+                return n;
 
-        table = link_get_dhcp_route_table(link);
+        for (int i = 0; i < n; i++) {
+                switch (sd_dhcp_route_get_option(static_routes[i])) {
+                case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
+                        classless_route = true;
+                        break;
+                case SD_DHCP_OPTION_STATIC_ROUTE:
+                        static_route = true;
+                        break;
+                }
+        }
+
+        /* 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. */
+        if (classless_route && static_route)
+                log_link_debug(link, "Classless static routes received from DHCP server: ignoring static-route option");
+
+        r = route_new(&route);
+        if (r < 0)
+                return r;
+
+        route->family = AF_INET;
+        route->gw_family = AF_INET;
+        route->protocol = RTPROT_DHCP;
+        route->priority = link->network->dhcp_route_metric;
+        route->table = link_get_dhcp_route_table(link);
+        route->mtu = link->network->dhcp_route_mtu;
 
-        for (int i = 0; i < n; i ++) {
-                _cleanup_(route_freep) Route *route = NULL;
+        for (int i = 0; i < n; i++) {
+                struct in_addr gw;
 
-                r = route_new(&route);
+                if (sd_dhcp_route_get_option(static_routes[i]) !=
+                    (classless_route ? SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE : SD_DHCP_OPTION_STATIC_ROUTE))
+                        continue;
+
+                r = sd_dhcp_route_get_gateway(static_routes[i], &gw);
                 if (r < 0)
-                        return log_link_error_errno(link, r, "Could not allocate route: %m");
+                        return r;
 
-                /* Set routes to DNS servers. */
+                r = sd_dhcp_route_get_destination(static_routes[i], &route->dst.in);
+                if (r < 0)
+                        return r;
 
-                route->family = AF_INET;
-                route->dst.in = dns[i];
-                route->dst_prefixlen = 32;
-                route->prefsrc.in = *address;
-                route->scope = RT_SCOPE_LINK;
-                route->protocol = RTPROT_DHCP;
-                route->priority = link->network->dhcp_route_metric;
-                route->table = table;
+                r = sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen);
+                if (r < 0)
+                        return r;
+
+                /* When classless static routes are provided, then router option will be ignored. To
+                 * use the default gateway later in other routes, e.g., routes to dns servers, here we
+                 * need to find the default gateway in the classless static routes. */
+                if (classless_route &&
+                    in4_addr_is_null(&route->dst.in) && route->dst_prefixlen == 0 &&
+                    in4_addr_is_null(&default_gw))
+                        default_gw = gw;
 
-                r = dhcp_route_configure(route, link);
+                r = dhcp_route_configure_auto(route, link, &gw);
                 if (r < 0)
-                        return log_link_error_errno(link, r, "Could not set route to DNS server: %m");
+                        return r;
         }
 
-        return 0;
+        *ret_default_gw = default_gw;
+        return classless_route;
 }
 
-static int dhcp_prefix_route_from_lease(
-                const sd_dhcp_lease *lease,
-                uint32_t table,
-                const struct in_addr *address,
-                Route **ret_route) {
-
-        Route *route;
-        struct in_addr netmask;
+static int link_set_dhcp_gateway(Link *link, struct in_addr *ret_gw) {
+        _cleanup_(route_freep) Route *route = NULL;
+        const struct in_addr *router;
+        struct in_addr address;
+        Route *rt;
         int r;
 
-        r = sd_dhcp_lease_get_netmask((sd_dhcp_lease*) lease, &netmask);
+        assert(link);
+        assert(link->dhcp_lease);
+        assert(ret_gw);
+
+        if (!link->network->dhcp_use_gateway)
+                return 0;
+
+        r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
+        if (r < 0)
+                return r;
+
+        r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
+        if (IN_SET(r, 0, -ENODATA)) {
+                log_link_debug(link, "DHCP: No gateway received from DHCP server.");
+                return 0;
+        }
+        if (r < 0)
+                return r;
+        if (in4_addr_is_null(&router[0])) {
+                log_link_debug(link, "DHCP: Received gateway address is null.");
+                return 0;
+        }
+
+        /* The dhcp netmask may mask out the gateway. First, add an explicit route for the gateway host
+         * so that we can route no matter the netmask or existing kernel route tables. */
+        r = link_set_dhcp_route_to_gateway(link, &router[0]);
         if (r < 0)
                 return r;
 
@@ -224,24 +447,134 @@ static int dhcp_prefix_route_from_lease(
         if (r < 0)
                 return r;
 
+        /* Next, add a default gateway. */
         route->family = AF_INET;
-        route->dst.in.s_addr = address->s_addr & netmask.s_addr;
-        route->dst_prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
-        route->prefsrc.in = *address;
-        route->scope = RT_SCOPE_LINK;
+        route->gw_family = AF_INET;
+        route->gw.in = router[0];
+        route->prefsrc.in = address;
         route->protocol = RTPROT_DHCP;
-        route->table = table;
-        *ret_route = route;
+        route->priority = link->network->dhcp_route_metric;
+        route->table = link_get_dhcp_route_table(link);
+        route->mtu = link->network->dhcp_route_mtu;
+
+        r = dhcp_route_configure(route, link);
+        if (r < 0)
+                return r;
+
+        HASHMAP_FOREACH(rt, link->network->routes_by_section) {
+                if (!rt->gateway_from_dhcp_or_ra)
+                        continue;
+
+                if (rt->gw_family != AF_INET)
+                        continue;
+
+                rt->gw.in = router[0];
+                if (!rt->protocol_set)
+                        rt->protocol = RTPROT_DHCP;
+                if (!rt->priority_set)
+                        rt->priority = link->network->dhcp_route_metric;
+                if (!rt->table_set)
+                        rt->table = link_get_dhcp_route_table(link);
+                if (rt->mtu == 0)
+                        rt->mtu = link->network->dhcp_route_mtu;
+
+                r = dhcp_route_configure(rt, link);
+                if (r < 0)
+                        return r;
+        }
+
+        *ret_gw = router[0];
         return 0;
 }
 
+static int link_set_routes_to_servers(
+                Link *link,
+                const struct in_addr *servers,
+                size_t n_servers,
+                const struct in_addr *gw) {
+
+        _cleanup_(route_freep) Route *route = NULL;
+        int r;
+
+        assert(link);
+        assert(link->dhcp_lease);
+        assert(link->network);
+        assert(servers || n_servers == 0);
+        assert(gw);
+
+        r = route_new(&route);
+        if (r < 0)
+                return r;
+
+        route->family = AF_INET;
+        route->dst_prefixlen = 32;
+        route->protocol = RTPROT_DHCP;
+        route->priority = link->network->dhcp_route_metric;
+        route->table = link_get_dhcp_route_table(link);
+        route->mtu = link->network->dhcp_route_mtu;
+
+        for (size_t i = 0; i < n_servers; i++) {
+                if (in4_addr_is_null(&servers[i]))
+                        continue;
+
+                route->dst.in = servers[i];
+
+                r = dhcp_route_configure_auto(route, link, gw);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+static int link_set_routes_to_dns(Link *link, const struct in_addr *gw) {
+        const struct in_addr *dns;
+        int r;
+
+        assert(link);
+        assert(link->dhcp_lease);
+        assert(link->network);
+        assert(gw);
+
+        if (!link->network->dhcp_use_dns ||
+            !link->network->dhcp_routes_to_dns)
+                return 0;
+
+        r = sd_dhcp_lease_get_dns(link->dhcp_lease, &dns);
+        if (IN_SET(r, 0, -ENODATA))
+                return 0;
+        if (r < 0)
+                return r;
+
+        return link_set_routes_to_servers(link, dns, r, gw);
+}
+
+static int link_set_routes_to_ntp(Link *link, const struct in_addr *gw) {
+        const struct in_addr *ntp;
+        int r;
+
+        assert(link);
+        assert(link->dhcp_lease);
+        assert(link->network);
+        assert(gw);
+
+        if (!link->network->dhcp_use_ntp ||
+            !link->network->dhcp_routes_to_ntp)
+                return 0;
+
+        r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &ntp);
+        if (IN_SET(r, 0, -ENODATA))
+                return 0;
+        if (r < 0)
+                return r;
+
+        return link_set_routes_to_servers(link, ntp, r, gw);
+}
+
 static int link_set_dhcp_routes(Link *link) {
-        _cleanup_free_ sd_dhcp_route **static_routes = NULL;
-        bool classless_route = false, static_route = false;
-        struct in_addr address;
-        uint32_t table;
+        struct in_addr gw = {};
         Route *rt;
-        int r, n;
+        int r;
 
         assert(link);
 
@@ -262,160 +595,30 @@ static int link_set_dhcp_routes(Link *link) {
                         return log_link_error_errno(link, r, "Failed to store old DHCPv4 route: %m");
         }
 
-        table = link_get_dhcp_route_table(link);
-
-        r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
+        r = link_set_dhcp_prefix_route(link);
         if (r < 0)
-                return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
-
-        if (!link_prefixroute(link)) {
-                _cleanup_(route_freep) Route *prefix_route = NULL;
+                return log_link_error_errno(link, r, "DHCP error: Could not set prefix route: %m");
 
-                r = dhcp_prefix_route_from_lease(link->dhcp_lease, table, &address, &prefix_route);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not create prefix route: %m");
-
-                r = dhcp_route_configure(prefix_route, link);
+        r = link_set_dhcp_static_routes(link, &gw);
+        if (r < 0)
+                return log_link_error_errno(link, r, "DHCP error: Could not set static routes: %m");
+        if (r == 0) {
+                /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and
+                 * a Router option, the DHCP client MUST ignore the Router option. */
+                r = link_set_dhcp_gateway(link, &gw);
                 if (r < 0)
-                        return log_link_error_errno(link, r, "Could not set prefix route: %m");
-        }
-
-        n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
-        if (n == -ENODATA)
-                log_link_debug_errno(link, n, "DHCP: No routes received from DHCP server: %m");
-        else if (n < 0)
-                return log_link_error_errno(link, n, "DHCP: could not get routes: %m");
-
-        for (int i = 0; i < n; i++) {
-                switch (sd_dhcp_route_get_option(static_routes[i])) {
-                case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
-                        classless_route = true;
-                        break;
-                case SD_DHCP_OPTION_STATIC_ROUTE:
-                        static_route = true;
-                        break;
-                }
-        }
-
-        if (link->network->dhcp_use_routes) {
-                /* 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. */
-                if (classless_route && static_route)
-                        log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option");
-
-                for (int i = 0; i < n; i++) {
-                        _cleanup_(route_freep) Route *route = NULL;
-
-                        if (classless_route &&
-                            sd_dhcp_route_get_option(static_routes[i]) != SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE)
-                                continue;
-
-                        r = route_new(&route);
-                        if (r < 0)
-                                return log_link_error_errno(link, r, "Could not allocate route: %m");
-
-                        route->family = AF_INET;
-                        route->protocol = RTPROT_DHCP;
-                        route->gw_family = AF_INET;
-                        assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0);
-                        assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0);
-                        assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
-                        route->priority = link->network->dhcp_route_metric;
-                        route->table = table;
-                        route->mtu = link->network->dhcp_route_mtu;
-                        route->scope = route_scope_from_address(route, &address);
-                        if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE))
-                                route->prefsrc.in = address;
-
-                        if (set_contains(link->dhcp_routes, route))
-                                continue;
-
-                        r = dhcp_route_configure(route, link);
-                        if (r < 0)
-                                return log_link_error_errno(link, r, "Could not set route: %m");
-                }
+                        return log_link_error_errno(link, r, "DHCP error: Could not set gateway: %m");
         }
 
-        if (link->network->dhcp_use_gateway) {
-                const struct in_addr *router;
-
-                r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
-                if (IN_SET(r, 0, -ENODATA))
-                        log_link_info(link, "DHCP: No gateway received from DHCP server.");
-                else if (r < 0)
-                        return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m");
-                else if (in4_addr_is_null(&router[0]))
-                        log_link_info(link, "DHCP: Received gateway is null.");
-                else if (classless_route)
-                        /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and
-                         * a Router option, the DHCP client MUST ignore the Router option. */
-                        log_link_warning(link, "Classless static routes received from DHCP server: ignoring router option");
-                else {
-                        _cleanup_(route_freep) Route *route = NULL, *route_gw = NULL;
-
-                        r = route_new(&route_gw);
-                        if (r < 0)
-                                return log_link_error_errno(link, r, "Could not allocate route: %m");
-
-                        /* The dhcp netmask may mask out the gateway. Add an explicit
-                         * route for the gw host so that we can route no matter the
-                         * netmask or existing kernel route tables. */
-                        route_gw->family = AF_INET;
-                        route_gw->dst.in = router[0];
-                        route_gw->dst_prefixlen = 32;
-                        route_gw->prefsrc.in = address;
-                        route_gw->scope = RT_SCOPE_LINK;
-                        route_gw->protocol = RTPROT_DHCP;
-                        route_gw->priority = link->network->dhcp_route_metric;
-                        route_gw->table = table;
-                        route_gw->mtu = link->network->dhcp_route_mtu;
-
-                        r = dhcp_route_configure(route_gw, link);
-                        if (r < 0)
-                                return log_link_error_errno(link, r, "Could not set host route: %m");
+        r = link_set_routes_to_dns(link, &gw);
+        if (r < 0)
+                return log_link_error_errno(link, r, "DHCP error: Could not set routes to DNS servers: %m");
 
-                        r = route_new(&route);
-                        if (r < 0)
-                                return log_link_error_errno(link, r, "Could not allocate route: %m");
-
-                        route->family = AF_INET;
-                        route->gw_family = AF_INET;
-                        route->gw.in = router[0];
-                        route->prefsrc.in = address;
-                        route->protocol = RTPROT_DHCP;
-                        route->priority = link->network->dhcp_route_metric;
-                        route->table = table;
-                        route->mtu = link->network->dhcp_route_mtu;
-
-                        r = dhcp_route_configure(route, link);
-                        if (r < 0)
-                                return log_link_error_errno(link, r, "Could not set router: %m");
-
-                        HASHMAP_FOREACH(rt, link->network->routes_by_section) {
-                                if (!rt->gateway_from_dhcp_or_ra)
-                                        continue;
-
-                                if (rt->gw_family != AF_INET)
-                                        continue;
-
-                                rt->gw.in = router[0];
-                                if (!rt->protocol_set)
-                                        rt->protocol = RTPROT_DHCP;
-                                if (!rt->priority_set)
-                                        rt->priority = link->network->dhcp_route_metric;
-                                if (!rt->table_set)
-                                        rt->table = table;
-                                if (rt->mtu == 0)
-                                        rt->mtu = link->network->dhcp_route_mtu;
-
-                                r = dhcp_route_configure(rt, link);
-                                if (r < 0)
-                                        return log_link_error_errno(link, r, "Could not set gateway: %m");
-                        }
-                }
-        }
+        r = link_set_routes_to_ntp(link, &gw);
+        if (r < 0)
+                return log_link_error_errno(link, r, "DHCP error: Could not set routes to NTP servers: %m");
 
-        return link_set_dns_routes(link, &address);
+        return 0;
 }
 
 static int dhcp_reset_mtu(Link *link) {
@@ -868,6 +1071,7 @@ static int dhcp4_update_address(Link *link, bool announce) {
         if (prefixlen <= 30)
                 addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
         SET_FLAG(addr->flags, IFA_F_NOPREFIXROUTE, !link_prefixroute(link));
+        addr->route_metric = link->network->dhcp_route_metric;
 
         /* allow reusing an existing address and simply update its lifetime
          * in case it already exists */
@@ -1070,7 +1274,9 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                                 if (link->network->dhcp_send_release) {
                                         r = sd_dhcp_client_send_release(client);
                                         if (r < 0)
-                                                log_link_warning_errno(link, r, "Failed to send DHCP RELEASE, ignoring: %m");
+                                                log_link_full_errno(link,
+                                                                    ERRNO_IS_DISCONNECT(r) ? LOG_DEBUG : LOG_WARNING,
+                                                                    r, "Failed to send DHCP RELEASE, ignoring: %m");
                                 }
 
                                 r = dhcp_lease_lost(link);
@@ -1199,17 +1405,17 @@ static int dhcp4_set_client_identifier(Link *link) {
         switch (link->network->dhcp_client_identifier) {
         case DHCP_CLIENT_ID_DUID: {
                 /* If configured, apply user specified DUID and IAID */
-                const DUID *duid = link_get_duid(link);
+                const DUID *duid = link_get_dhcp4_duid(link);
 
                 if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
                         r = sd_dhcp_client_set_iaid_duid_llt(link->dhcp_client,
-                                                             link->network->iaid_set,
-                                                             link->network->iaid,
+                                                             link->network->dhcp_iaid_set,
+                                                             link->network->dhcp_iaid,
                                                              duid->llt_time);
                 else
                         r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
-                                                         link->network->iaid_set,
-                                                         link->network->iaid,
+                                                         link->network->dhcp_iaid_set,
+                                                         link->network->dhcp_iaid,
                                                          duid->type,
                                                          duid->raw_data_len > 0 ? duid->raw_data : NULL,
                                                          duid->raw_data_len);
@@ -1219,7 +1425,7 @@ static int dhcp4_set_client_identifier(Link *link) {
         }
         case DHCP_CLIENT_ID_DUID_ONLY: {
                 /* If configured, apply user specified DUID */
-                const DUID *duid = link_get_duid(link);
+                const DUID *duid = link_get_dhcp4_duid(link);
 
                 if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
                         r = sd_dhcp_client_set_duid_llt(link->dhcp_client,
@@ -1258,6 +1464,15 @@ static int dhcp4_set_client_identifier(Link *link) {
         return 0;
 }
 
+static int dhcp4_configure_duid(Link *link) {
+        assert(link);
+
+        if (!IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY))
+                return 1;
+
+        return dhcp_configure_duid(link, link_get_dhcp4_duid(link));
+}
+
 static int dhcp4_set_request_address(Link *link) {
         Address *a;
 
@@ -1283,6 +1498,30 @@ static int dhcp4_set_request_address(Link *link) {
         return sd_dhcp_client_set_request_address(link->dhcp_client, &a->in_addr.in);
 }
 
+static bool link_needs_dhcp_broadcast(Link *link) {
+        const char *val;
+        int r;
+
+        assert(link);
+        assert(link->network);
+
+        /* Return the setting in DHCP[4].RequestBroadcast if specified. Otherwise return the device property
+         * ID_NET_DHCP_BROADCAST setting, which may be set for interfaces requiring that the DHCPOFFER message
+         * is being broadcast because they can't  handle unicast messages while not fully configured.
+         * If neither is set or a failure occurs, return false, which is the default for this flag.
+         */
+        r = link->network->dhcp_broadcast;
+        if (r < 0 && link->sd_device && sd_device_get_property_value(link->sd_device, "ID_NET_DHCP_BROADCAST", &val) >= 0) {
+                r = parse_boolean(val);
+                if (r < 0)
+                        log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to parse ID_NET_DHCP_BROADCAST, ignoring: %m");
+                else
+                        log_link_debug(link, "DHCP4 CLIENT: Detected ID_NET_DHCP_BROADCAST='%d'.", r);
+
+        }
+        return r == true;
+}
+
 int dhcp4_configure(Link *link) {
         sd_dhcp_option *send_option;
         void *request_options;
@@ -1294,15 +1533,20 @@ int dhcp4_configure(Link *link) {
         if (!link_dhcp4_enabled(link))
                 return 0;
 
-        if (!link->dhcp_client) {
-                r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to allocate DHCP4 client: %m");
+        if (link->dhcp_client)
+                return -EBUSY; /* Already configured. */
 
-                r = sd_dhcp_client_attach_event(link->dhcp_client, link->manager->event, 0);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to attach event to DHCP4 client: %m");
-        }
+        r = dhcp4_configure_duid(link);
+        if (r <= 0)
+                return r;
+
+        r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to allocate DHCP4 client: %m");
+
+        r = sd_dhcp_client_attach_event(link->dhcp_client, link->manager->event, 0);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to attach event to DHCP4 client: %m");
 
         r = sd_dhcp_client_set_mac(link->dhcp_client,
                                    link->hw_addr.addr.bytes,
@@ -1319,7 +1563,7 @@ int dhcp4_configure(Link *link) {
         if (r < 0)
                 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set callback: %m");
 
-        r = sd_dhcp_client_set_request_broadcast(link->dhcp_client, link->network->dhcp_broadcast);
+        r = sd_dhcp_client_set_request_broadcast(link->dhcp_client, link_needs_dhcp_broadcast(link));
         if (r < 0)
                 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for broadcast: %m");
 
@@ -1329,96 +1573,93 @@ int dhcp4_configure(Link *link) {
                         return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set MTU: %m");
         }
 
-        if (link->network->dhcp_use_mtu) {
-                r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_INTERFACE_MTU);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for MTU: %m");
-        }
-
-        /* NOTE: even if this variable is called "use", it also "sends" PRL
-         * options, maybe there should be a different configuration variable
-         * to send or not route options?. */
-        /* NOTE: when using Anonymize=yes, routes PRL options are sent
-         * by default, so they don't need to be added here. */
-        if (link->network->dhcp_use_routes && !link->network->dhcp_anonymize) {
-                r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_STATIC_ROUTE);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for static route: %m");
+        if (!link->network->dhcp_anonymize) {
+                if (link->network->dhcp_use_mtu) {
+                        r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_INTERFACE_MTU);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for MTU: %m");
+                }
 
-                r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for classless static route: %m");
-        }
+                if (link->network->dhcp_use_routes) {
+                        r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_STATIC_ROUTE);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for static route: %m");
 
-        if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO && !link->network->dhcp_anonymize) {
-                r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_DOMAIN_SEARCH_LIST);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for domain search list: %m");
-        }
+                        r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for classless static route: %m");
+                }
 
-        if (link->network->dhcp_use_ntp) {
-                r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for NTP server: %m");
-        }
+                if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
+                        r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_DOMAIN_SEARCH_LIST);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for domain search list: %m");
+                }
 
-        if (link->network->dhcp_use_sip) {
-                r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_SIP_SERVER);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for SIP server: %m");
-        }
+                if (link->network->dhcp_use_ntp) {
+                        r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for NTP server: %m");
+                }
 
-        if (link->network->dhcp_use_timezone) {
-                r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for timezone: %m");
-        }
+                if (link->network->dhcp_use_sip) {
+                        r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_SIP_SERVER);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for SIP server: %m");
+                }
 
-        SET_FOREACH(request_options, link->network->dhcp_request_options) {
-                uint32_t option = PTR_TO_UINT32(request_options);
+                if (link->network->dhcp_use_timezone) {
+                        r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for timezone: %m");
+                }
 
-                r = sd_dhcp_client_set_request_option(link->dhcp_client, option);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for '%u': %m", option);
-        }
+                SET_FOREACH(request_options, link->network->dhcp_request_options) {
+                        uint32_t option = PTR_TO_UINT32(request_options);
 
-        ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_client_send_options) {
-                r = sd_dhcp_client_add_option(link->dhcp_client, send_option);
-                if (r == -EEXIST)
-                        continue;
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set send option: %m");
-        }
+                        r = sd_dhcp_client_set_request_option(link->dhcp_client, option);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for '%u': %m", option);
+                }
 
-        ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_client_send_vendor_options) {
-                r = sd_dhcp_client_add_vendor_option(link->dhcp_client, send_option);
-                if (r == -EEXIST)
-                        continue;
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set send option: %m");
-        }
+                ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_client_send_options) {
+                        r = sd_dhcp_client_add_option(link->dhcp_client, send_option);
+                        if (r == -EEXIST)
+                                continue;
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set send option: %m");
+                }
 
-        r = dhcp4_set_hostname(link);
-        if (r < 0)
-                return r;
+                ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_client_send_vendor_options) {
+                        r = sd_dhcp_client_add_vendor_option(link->dhcp_client, send_option);
+                        if (r == -EEXIST)
+                                continue;
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set send option: %m");
+                }
 
-        if (link->network->dhcp_vendor_class_identifier) {
-                r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,
-                                                               link->network->dhcp_vendor_class_identifier);
+                r = dhcp4_set_hostname(link);
                 if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set vendor class identifier: %m");
-        }
+                        return r;
 
-       if (link->network->dhcp_mudurl) {
-                r = sd_dhcp_client_set_mud_url(link->dhcp_client, link->network->dhcp_mudurl);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set MUD URL: %m");
-        }
+                if (link->network->dhcp_vendor_class_identifier) {
+                        r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,
+                                                                       link->network->dhcp_vendor_class_identifier);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set vendor class identifier: %m");
+                }
 
-        if (link->network->dhcp_user_class) {
-                r = sd_dhcp_client_set_user_class(link->dhcp_client, link->network->dhcp_user_class);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set user class: %m");
+                if (link->network->dhcp_mudurl) {
+                        r = sd_dhcp_client_set_mud_url(link->dhcp_client, link->network->dhcp_mudurl);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set MUD URL: %m");
+                }
+
+                if (link->network->dhcp_user_class) {
+                        r = sd_dhcp_client_set_user_class(link->dhcp_client, link->network->dhcp_user_class);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set user class: %m");
+                }
         }
 
         if (link->network->dhcp_client_port > 0) {
@@ -1481,6 +1722,20 @@ int dhcp4_update_mac(Link *link) {
         return 0;
 }
 
+int dhcp4_start(Link *link) {
+        assert(link);
+
+        if (!link->dhcp_client)
+                return 0;
+
+        if (sd_dhcp_client_is_running(link->dhcp_client) > 0)
+                return 0;
+
+        log_link_debug(link, "Acquiring DHCPv4 lease");
+
+        return sd_dhcp_client_start(link->dhcp_client);
+}
+
 int config_parse_dhcp_max_attempts(
                 const char *unit,
                 const char *filename,
index 5ec2f88b7ee4321066d93c3c5974953364315af4..a33fe403be87003aaab7c9d662ffdbabcf27490c 100644 (file)
@@ -17,8 +17,10 @@ typedef enum DHCPClientIdentifier {
         _DHCP_CLIENT_ID_INVALID = -EINVAL,
 } DHCPClientIdentifier;
 
+void network_adjust_dhcp4(Network *network);
 int dhcp4_configure(Link *link);
 int dhcp4_update_mac(Link *link);
+int dhcp4_start(Link *link);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_acl_ip_address);
index 72bb46b18650a87549814cf8557769dfdbad60be..b13a635a7821a82764bbb3f54355729cb00c33a5 100644 (file)
 #include "radv-internal.h"
 #include "web-util.h"
 
+bool link_dhcp6_with_address_enabled(Link *link) {
+        if (!link_dhcp6_enabled(link))
+                return false;
+
+        return link->network->dhcp6_use_address;
+}
+
 bool link_dhcp6_pd_is_enabled(Link *link) {
         assert(link);
 
@@ -277,6 +284,7 @@ static int dhcp6_set_pd_route(Link *link, const union in_addr_union *prefix, con
         route->dst = *prefix;
         route->dst_prefixlen = 64;
         route->protocol = RTPROT_DHCP;
+        route->priority = link->network->dhcp6_pd_route_metric;
 
         r = route_configure(route, link, dhcp6_pd_route_handler, &ret);
         if (r < 0)
@@ -356,6 +364,33 @@ static int dhcp6_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Lin
         return 1;
 }
 
+static void log_dhcp6_pd_address(Link *link, const Address *address) {
+        char valid_buf[FORMAT_TIMESPAN_MAX], preferred_buf[FORMAT_TIMESPAN_MAX];
+        const char *valid_str = NULL, *preferred_str = NULL;
+        _cleanup_free_ char *buffer = NULL;
+        int log_level;
+
+        log_level = address_get(link, address, NULL) >= 0 ? LOG_DEBUG : LOG_INFO;
+
+        if (log_level < log_get_max_level())
+                return;
+
+        (void) in_addr_prefix_to_string(address->family, &address->in_addr, address->prefixlen, &buffer);
+        if (address->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
+                valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
+                                            address->cinfo.ifa_valid * USEC_PER_SEC,
+                                            USEC_PER_SEC);
+        if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME)
+                preferred_str = format_timespan(preferred_buf, FORMAT_TIMESPAN_MAX,
+                                                address->cinfo.ifa_prefered * USEC_PER_SEC,
+                                                USEC_PER_SEC);
+
+        log_link_full(link, log_level, "DHCPv6-PD address %s (valid %s%s, preferred %s%s)",
+                      strna(buffer),
+                      valid_str ? "for " : "forever", strempty(valid_str),
+                      preferred_str ? "for " : "forever", strempty(preferred_str));
+}
+
 static int dhcp6_set_pd_address(
                 Link *link,
                 const union in_addr_union *prefix,
@@ -392,7 +427,9 @@ static int dhcp6_set_pd_address(
         address->cinfo.ifa_prefered = lifetime_preferred;
         address->cinfo.ifa_valid = lifetime_valid;
         SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp6_pd_manage_temporary_address);
+        address->route_metric = link->network->dhcp6_pd_route_metric;
 
+        log_dhcp6_pd_address(link, address);
         r = address_configure(address, link, dhcp6_pd_address_handler, &ret);
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to set DHCPv6 delegated prefix address: %m");
@@ -645,6 +682,8 @@ static void dhcp6_pd_prefix_lost(Link *dhcp6_link) {
                 if (r < 0)
                         link_enter_failed(link);
         }
+
+        set_clear(dhcp6_link->dhcp6_pd_prefixes);
 }
 
 static int dhcp6_remove_old(Link *link, bool force);
@@ -787,20 +826,12 @@ static int dhcp6_set_unreachable_route(Link *link, const union in_addr_union *ad
 
         (void) in_addr_prefix_to_string(AF_INET6, addr, prefixlen, &buf);
 
-        if (prefixlen > 64) {
-                log_link_debug(link, "PD Prefix length > 64, ignoring prefix %s", strna(buf));
-                return 0;
-        }
-
         if (prefixlen == 64) {
                 log_link_debug(link, "Not adding a blocking route for DHCPv6 delegated subnet %s since distributed prefix is 64",
                                strna(buf));
-                return 1;
+                return 0;
         }
 
-        if (prefixlen < 48)
-                log_link_warning(link, "PD Prefix length < 48, looks unusual: %s", strna(buf));
-
         r = route_new(&route);
         if (r < 0)
                 return log_oom();
@@ -828,7 +859,45 @@ static int dhcp6_set_unreachable_route(Link *link, const union in_addr_union *ad
 
         (void) set_remove(link->dhcp6_routes_old, ret);
 
-        return 1;
+        return 0;
+}
+
+static int dhcp6_pd_prefix_add(Link *link, const union in_addr_union *prefix, uint8_t prefixlen) {
+        _cleanup_free_ struct in_addr_prefix *p = NULL;
+        _cleanup_free_ char *buf = NULL;
+        int r;
+
+        assert(link);
+        assert(prefix);
+
+        p = new(struct in_addr_prefix, 1);
+        if (!p)
+                return log_oom();
+
+        *p = (struct in_addr_prefix) {
+                .family = AF_INET6,
+                .prefixlen = prefixlen,
+                .address = *prefix,
+        };
+
+        (void) in_addr_prefix_to_string(p->family, &p->address, p->prefixlen, &buf);
+
+        log_link_full(link,
+                      set_contains(link->dhcp6_pd_prefixes, p) ? LOG_DEBUG :
+                      prefixlen > 64 || prefixlen < 48 ? LOG_WARNING : LOG_INFO,
+                      "DHCP6: received PD Prefix %s%s",
+                      strna(buf),
+                      prefixlen > 64 ? " with prefix length > 64, ignoring." :
+                      prefixlen < 48 ? " with prefix length < 48, looks unusual.": "");
+
+        /* Store PD prefix even if prefixlen > 64, not to make logged at warning level so frequently. */
+        r = set_ensure_put(&link->dhcp6_pd_prefixes, &in_addr_prefix_hash_ops_free, p);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to store DHCP6 PD prefix %s: %m", strna(buf));
+        if (r > 0)
+                TAKE_PTR(p);
+
+        return prefixlen <= 64;
 }
 
 static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
@@ -857,12 +926,16 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
                 if (r < 0)
                         break;
 
-                r = dhcp6_set_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len);
+                r = dhcp6_pd_prefix_add(dhcp6_link, &pd_prefix, pd_prefix_len);
                 if (r < 0)
                         return r;
                 if (r == 0)
                         continue;
 
+                r = dhcp6_set_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len);
+                if (r < 0)
+                        return r;
+
                 /* We are doing prefix allocation in two steps:
                  * 1. all those links that have a preferred subnet id will be assigned their subnet
                  * 2. all those links that remain will receive prefixes in sequential order. Prefixes
@@ -1281,6 +1354,31 @@ int dhcp6_request_address(Link *link, int ir) {
         return 0;
 }
 
+int dhcp6_start(Link *link) {
+        assert(link);
+
+        if (!link->dhcp6_client)
+                return 0;
+
+        if (!link_dhcp6_enabled(link))
+                return 0;
+
+        if (link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_NO)
+                return 0;
+
+        if (!in6_addr_is_link_local(&link->ipv6ll_address)) {
+                log_link_debug(link, "IPv6 link-local address is not set, delaying to start DHCPv6 client.");
+                return 0;
+        }
+
+        if (sd_dhcp6_client_is_running(link->dhcp6_client) > 0)
+                return 0;
+
+        log_link_debug(link, "Acquiring DHCPv6 lease");
+
+        return dhcp6_request_address(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST);
+}
+
 int dhcp6_request_prefix_delegation(Link *link) {
         Link *l;
 
@@ -1415,13 +1513,13 @@ static int dhcp6_set_identifier(Link *link, sd_dhcp6_client *client) {
         if (r < 0)
                 return r;
 
-        if (link->network->iaid_set) {
-                r = sd_dhcp6_client_set_iaid(client, link->network->iaid);
+        if (link->network->dhcp6_iaid_set) {
+                r = sd_dhcp6_client_set_iaid(client, link->network->dhcp6_iaid);
                 if (r < 0)
                         return r;
         }
 
-        duid = link_get_duid(link);
+        duid = link_get_dhcp6_duid(link);
         if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
                 r = sd_dhcp6_client_set_duid_llt(client, duid->llt_time);
         else
@@ -1449,7 +1547,11 @@ int dhcp6_configure(Link *link) {
                 return 0;
 
         if (link->dhcp6_client)
-                return 0;
+                return -EBUSY;
+
+        r = dhcp_configure_duid(link, link_get_dhcp6_duid(link));
+        if (r <= 0)
+                return r;
 
         r = sd_dhcp6_client_new(&client);
         if (r == -ENOMEM)
index f74476d575ec1e67226f57d5413b72dfaadc5832..025bbb6188185572ba4bbce3feb9f5f1c648f1c1 100644 (file)
@@ -26,10 +26,12 @@ typedef struct DHCP6DelegatedPrefix {
 DHCP6DelegatedPrefix *dhcp6_pd_free(DHCP6DelegatedPrefix *p);
 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCP6DelegatedPrefix*, dhcp6_pd_free);
 
+bool link_dhcp6_with_address_enabled(Link *link);
 bool link_dhcp6_pd_is_enabled(Link *link);
 int dhcp6_pd_remove(Link *link);
 int dhcp6_configure(Link *link);
 int dhcp6_update_mac(Link *link);
+int dhcp6_start(Link *link);
 int dhcp6_request_address(Link *link, int ir);
 int dhcp6_request_prefix_delegation(Link *link);
 
index b2a2f55790f53ad3f1c05c1066050ca4317b4412..20c33e8c80f176de99cfec30467bec7848105592 100644 (file)
@@ -6,6 +6,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
 #include <stddef.h>
 #include "conf-parser.h"
 #include "networkd-conf.h"
+#include "networkd-dhcp-common.h"
 #include "networkd-manager.h"
 #include "networkd-route.h"
 %}
@@ -20,9 +21,15 @@ struct ConfigPerfItem;
 %struct-type
 %includes
 %%
-Network.SpeedMeter,            config_parse_bool,                      0,          offsetof(Manager, use_speed_meter)
-Network.SpeedMeterIntervalSec, config_parse_sec,                       0,          offsetof(Manager, speed_meter_interval_usec)
-Network.ManageForeignRoutes,   config_parse_bool,                      0,          offsetof(Manager, manage_foreign_routes)
-Network.RouteTable,            config_parse_route_table_names,         0,          0
-DHCP.DUIDType,                 config_parse_duid_type,                 0,          offsetof(Manager, duid)
-DHCP.DUIDRawData,              config_parse_duid_rawdata,              0,          offsetof(Manager, duid)
+Network.SpeedMeter,                      config_parse_bool,                      0,          offsetof(Manager, use_speed_meter)
+Network.SpeedMeterIntervalSec,           config_parse_sec,                       0,          offsetof(Manager, speed_meter_interval_usec)
+Network.ManageForeignRoutingPolicyRules, config_parse_bool,                      0,          offsetof(Manager, manage_foreign_rules)
+Network.ManageForeignRoutes,             config_parse_bool,                      0,          offsetof(Manager, manage_foreign_routes)
+Network.RouteTable,                      config_parse_route_table_names,         0,          0
+DHCPv4.DUIDType,                         config_parse_duid_type,                 0,          offsetof(Manager, dhcp_duid)
+DHCPv4.DUIDRawData,                      config_parse_duid_rawdata,              0,          offsetof(Manager, dhcp_duid)
+DHCPv6.DUIDType,                         config_parse_duid_type,                 0,          offsetof(Manager, dhcp6_duid)
+DHCPv6.DUIDRawData,                      config_parse_duid_rawdata,              0,          offsetof(Manager, dhcp6_duid)
+/* Deprecated */
+DHCP.DUIDType,                           config_parse_manager_duid_type,         0,          0
+DHCP.DUIDRawData,                        config_parse_manager_duid_rawdata,      0,          0
index 65266633e3b01f40da887c9cbfd8bff900daae87..5390c537993a8da5bc5220c74e785a2a08ad6f9c 100644 (file)
@@ -91,6 +91,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
         ll_addr->prefixlen = 16;
         ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htobe32(0xfffffffflu >> ll_addr->prefixlen);
         ll_addr->scope = RT_SCOPE_LINK;
+        ll_addr->route_metric = IPV4LL_ROUTE_METRIC;
 
         r = address_configure(ll_addr, link, ipv4ll_address_handler, NULL);
         if (r < 0)
@@ -151,15 +152,16 @@ int ipv4ll_configure(Link *link) {
         if (!link_ipv4ll_enabled(link))
                 return 0;
 
-        if (!link->ipv4ll) {
-                r = sd_ipv4ll_new(&link->ipv4ll);
-                if (r < 0)
-                        return r;
+        if (link->ipv4ll)
+                return -EBUSY;
 
-                r = sd_ipv4ll_attach_event(link->ipv4ll, link->manager->event, 0);
-                if (r < 0)
-                        return r;
-        }
+        r = sd_ipv4ll_new(&link->ipv4ll);
+        if (r < 0)
+                return r;
+
+        r = sd_ipv4ll_attach_event(link->ipv4ll, link->manager->event, 0);
+        if (r < 0)
+                return r;
 
         if (link->sd_device &&
             net_get_unique_predictable_data(link->sd_device, true, &seed) >= 0) {
index f57828b57da4e5f77649628ad2fef8a257aaf920..a999b05845c1422221d3bcdff0120a34b0077337 100644 (file)
@@ -178,7 +178,7 @@ int bus_link_method_set_dns_servers_ex(sd_bus_message *message, void *userdata,
 }
 
 int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_(ordered_set_freep) OrderedSet *search_domains = NULL, *route_domains = NULL;
+        _cleanup_ordered_set_free_ OrderedSet *search_domains = NULL, *route_domains = NULL;
         Link *l = userdata;
         int r;
 
@@ -211,22 +211,22 @@ int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_
                 if (r == 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name);
                 if (!route_only && dns_name_is_root(name))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain");
 
                 r = dns_name_normalize(name, 0, &str);
                 if (r < 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name);
 
                 domains = route_only ? &route_domains : &search_domains;
-                r = ordered_set_ensure_allocated(domains, &string_hash_ops);
+                r = ordered_set_ensure_allocated(domains, &string_hash_ops_free);
                 if (r < 0)
                         return r;
 
-                r = ordered_set_put(*domains, str);
+                r = ordered_set_consume(*domains, TAKE_PTR(str));
+                if (r == -EEXIST)
+                        continue;
                 if (r < 0)
                         return r;
-
-                TAKE_PTR(str);
         }
 
         r = sd_bus_message_exit_container(message);
@@ -242,8 +242,8 @@ int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_
         if (r == 0)
                 return 1; /* Polkit will call us back */
 
-        ordered_set_free_free(l->search_domains);
-        ordered_set_free_free(l->route_domains);
+        ordered_set_free(l->search_domains);
+        ordered_set_free(l->route_domains);
         l->search_domains = TAKE_PTR(search_domains);
         l->route_domains = TAKE_PTR(route_domains);
 
@@ -684,6 +684,8 @@ const sd_bus_vtable link_vtable[] = {
         SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Link, operstate), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("CarrierState", "s", property_get_carrier_state, offsetof(Link, carrier_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Link, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("IPv4AddressState", "s", property_get_address_state, offsetof(Link, ipv4_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("IPv6AddressState", "s", property_get_address_state, offsetof(Link, ipv6_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("BitRates", "(tt)", property_get_bit_rates, 0, 0),
 
@@ -854,7 +856,7 @@ int link_send_changed_strv(Link *link, char **properties) {
         assert(link->manager);
         assert(properties);
 
-        if (!link->manager->bus)
+        if (sd_bus_is_ready(link->manager->bus) <= 0)
                 return 0;
 
         p = link_bus_path(link);
index 6868a7ccb2c227c6ff3700fd17c66e71f39713ae..ffaebbbf6d34abe089fa7650c40a7675fc10f044 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/if.h>
 #include <linux/if_arp.h>
 #include <linux/if_link.h>
+#include <sys/socket.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
@@ -163,12 +164,25 @@ static void link_update_master_operstate(Link *link, NetDev *netdev) {
         link_update_operstate(master, true);
 }
 
+static LinkAddressState address_state_from_scope(uint8_t scope) {
+        if (scope < RT_SCOPE_SITE)
+                /* universally accessible addresses found */
+                return LINK_ADDRESS_STATE_ROUTABLE;
+
+        if (scope < RT_SCOPE_HOST)
+                /* only link or site local addresses found */
+                return LINK_ADDRESS_STATE_DEGRADED;
+
+        /* no useful addresses found */
+        return LINK_ADDRESS_STATE_OFF;
+}
+
 void link_update_operstate(Link *link, bool also_update_master) {
         LinkOperationalState operstate;
         LinkCarrierState carrier_state;
-        LinkAddressState address_state;
+        LinkAddressState ipv4_address_state, ipv6_address_state, address_state;
         _cleanup_strv_free_ char **p = NULL;
-        uint8_t scope = RT_SCOPE_NOWHERE;
+        uint8_t ipv4_scope = RT_SCOPE_NOWHERE, ipv6_scope = RT_SCOPE_NOWHERE;
         bool changed = false;
         Address *address;
 
@@ -201,8 +215,11 @@ void link_update_operstate(Link *link, bool also_update_master) {
                 if (!address_is_ready(address))
                         continue;
 
-                if (address->scope < scope)
-                        scope = address->scope;
+                if (address->family == AF_INET)
+                        ipv4_scope = MIN(ipv4_scope, address->scope);
+
+                if (address->family == AF_INET6)
+                        ipv6_scope = MIN(ipv6_scope, address->scope);
         }
 
         /* for operstate we also take foreign addresses into account */
@@ -210,19 +227,16 @@ void link_update_operstate(Link *link, bool also_update_master) {
                 if (!address_is_ready(address))
                         continue;
 
-                if (address->scope < scope)
-                        scope = address->scope;
+                if (address->family == AF_INET)
+                        ipv4_scope = MIN(ipv4_scope, address->scope);
+
+                if (address->family == AF_INET6)
+                        ipv6_scope = MIN(ipv6_scope, address->scope);
         }
 
-        if (scope < RT_SCOPE_SITE)
-                /* universally accessible addresses found */
-                address_state = LINK_ADDRESS_STATE_ROUTABLE;
-        else if (scope < RT_SCOPE_HOST)
-                /* only link or site local addresses found */
-                address_state = LINK_ADDRESS_STATE_DEGRADED;
-        else
-                /* no useful addresses found */
-                address_state = LINK_ADDRESS_STATE_OFF;
+        ipv4_address_state = address_state_from_scope(ipv4_scope);
+        ipv6_address_state = address_state_from_scope(ipv6_scope);
+        address_state = address_state_from_scope(MIN(ipv4_scope, ipv6_scope));
 
         /* Mapping of address and carrier state vs operational state
          *                                                     carrier state
@@ -256,6 +270,20 @@ void link_update_operstate(Link *link, bool also_update_master) {
                         log_oom();
         }
 
+        if (link->ipv4_address_state != ipv4_address_state) {
+                link->ipv4_address_state = ipv4_address_state;
+                changed = true;
+                if (strv_extend(&p, "IPv4AddressState") < 0)
+                        log_oom();
+        }
+
+        if (link->ipv6_address_state != ipv6_address_state) {
+                link->ipv6_address_state = ipv6_address_state;
+                changed = true;
+                if (strv_extend(&p, "IPv6AddressState") < 0)
+                        log_oom();
+        }
+
         if (link->operstate != operstate) {
                 link->operstate = operstate;
                 changed = true;
@@ -478,8 +506,8 @@ void link_dns_settings_clear(Link *link) {
         link->dns = mfree(link->dns);
         link->n_dns = UINT_MAX;
 
-        link->search_domains = ordered_set_free_free(link->search_domains);
-        link->route_domains = ordered_set_free_free(link->route_domains);
+        link->search_domains = ordered_set_free(link->search_domains);
+        link->route_domains = ordered_set_free(link->route_domains);
 
         link->dns_default_route = -1;
         link->llmnr = _RESOLVE_SUPPORT_INVALID;
@@ -545,6 +573,8 @@ static Link *link_free(Link *link) {
         link->dhcp6_pd_addresses_old = set_free(link->dhcp6_pd_addresses_old);
         link->ndisc_addresses = set_free(link->ndisc_addresses);
 
+        link->dhcp6_pd_prefixes = set_free(link->dhcp6_pd_prefixes);
+
         link_free_engines(link);
 
         free(link->ifname);
@@ -734,6 +764,15 @@ void link_check_ready(Link *link) {
         if (!link->network)
                 return;
 
+        if (link->iftype == ARPHRD_CAN) {
+                /* let's shortcut things for CAN which doesn't need most of checks below. */
+                if (!link->can_configured)
+                        return (void) log_link_debug(link, "%s(): CAN device is not configured.", __func__);
+
+                link_enter_configured(link);
+                return;
+        }
+
         if (!link->addresses_configured)
                 return (void) log_link_debug(link, "%s(): static addresses are not configured.", __func__);
 
@@ -779,7 +818,7 @@ void link_check_ready(Link *link) {
                                 break;
                         }
 
-                if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_ipv4ll_enabled(link)) &&
+                if ((link_dhcp4_enabled(link) || link_dhcp6_with_address_enabled(link) || link_ipv4ll_enabled(link)) &&
                     !link->dhcp_address && set_isempty(link->dhcp6_addresses) && !has_ndisc_address &&
                     !link->ipv4ll_address_configured)
                         /* When DHCP[46] or IPv4LL is enabled, at least one address is acquired by them. */
@@ -1149,14 +1188,6 @@ static int link_acquire_ipv6_conf(Link *link) {
 
         assert(link);
 
-        if (link->ndisc) {
-                log_link_debug(link, "Discovering IPv6 routers");
-
-                r = sd_ndisc_start(link->ndisc);
-                if (r < 0 && r != -EBUSY)
-                        return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
-        }
-
         if (link->radv) {
                 assert(link->radv);
                 assert(in6_addr_is_link_local(&link->ipv6ll_address));
@@ -1172,18 +1203,13 @@ static int link_acquire_ipv6_conf(Link *link) {
                         return log_link_warning_errno(link, r, "Could not start IPv6 Router Advertisement: %m");
         }
 
-        if (link_dhcp6_enabled(link) && IN_SET(link->network->dhcp6_without_ra,
-                                               DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST,
-                                               DHCP6_CLIENT_START_MODE_SOLICIT)) {
-                assert(link->dhcp6_client);
-                assert(in6_addr_is_link_local(&link->ipv6ll_address));
+        r = ndisc_start(link);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m");
 
-                r = dhcp6_request_address(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST);
-                if (r < 0 && r != -EBUSY)
-                        return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m");
-                else
-                        log_link_debug(link, "Acquiring DHCPv6 lease");
-        }
+        r = dhcp6_start(link);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to start DHCPv6 client: %m");
 
         r = dhcp6_request_prefix_delegation(link);
         if (r < 0)
@@ -1200,11 +1226,9 @@ static int link_acquire_ipv4_conf(Link *link) {
         assert(link->manager->event);
 
         if (link->dhcp_client) {
-                log_link_debug(link, "Acquiring DHCPv4 lease");
-
-                r = sd_dhcp_client_start(link->dhcp_client);
+                r = dhcp4_start(link);
                 if (r < 0)
-                        return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m");
+                        return log_link_warning_errno(link, r, "Failed to start DHCPv4 client: %m");
 
         } else if (link->ipv4ll) {
                 log_link_debug(link, "Acquiring IPv4 link-local address");
@@ -1312,8 +1336,9 @@ static int link_configure_addrgen_mode(Link *link) {
                 r = sysctl_read_ip_property(AF_INET6, link->ifname, "stable_secret", NULL);
                 if (r < 0) {
                         /* The file may not exist. And even if it exists, when stable_secret is unset,
-                         * reading the file fails with EIO. */
-                        log_link_debug_errno(link, r, "Failed to read sysctl property stable_secret: %m");
+                         * reading the file fails with ENOMEM when read_full_virtual_file(), which uses
+                         * read() as the backend, and EIO when read_one_line_file() which uses fgetc(). */
+                        log_link_debug_errno(link, r, "Failed to read sysctl property stable_secret, ignoring: %m");
 
                         ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64;
                 } else
@@ -1360,7 +1385,7 @@ static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
         return 1;
 }
 
-static int link_up(Link *link) {
+int link_up(Link *link) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
@@ -1755,7 +1780,7 @@ static void link_drop(Link *link) {
         link_detach_from_manager(link);
 }
 
-static int link_joined(Link *link) {
+int link_activate(Link *link) {
         int r;
 
         assert(link);
@@ -1773,10 +1798,8 @@ static int link_joined(Link *link) {
                 _fallthrough_;
         case ACTIVATION_POLICY_ALWAYS_UP:
                 r = link_up(link);
-                if (r < 0) {
-                        link_enter_failed(link);
+                if (r < 0)
                         return r;
-                }
                 break;
         case ACTIVATION_POLICY_DOWN:
                 if (link->activated)
@@ -1784,16 +1807,27 @@ static int link_joined(Link *link) {
                 _fallthrough_;
         case ACTIVATION_POLICY_ALWAYS_DOWN:
                 r = link_down(link, NULL);
-                if (r < 0) {
-                        link_enter_failed(link);
+                if (r < 0)
                         return r;
-                }
                 break;
         default:
                 break;
         }
         link->activated = true;
 
+        return 0;
+}
+
+static int link_joined(Link *link) {
+        int r;
+
+        assert(link);
+        assert(link->network);
+
+        r = link_activate(link);
+        if (r < 0)
+                return r;
+
         if (link->network->bridge) {
                 r = link_set_bridge(link);
                 if (r < 0)
@@ -2060,6 +2094,7 @@ int link_configure(Link *link) {
                 return r;
 
         if (link->iftype == ARPHRD_CAN)
+                /* let's shortcut things for CAN which doesn't need most of what's done below. */
                 return link_configure_can(link);
 
         r = link_set_sysctl(link);
@@ -2202,7 +2237,7 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for
                 return r;
 
         if (!IN_SET(link->state, LINK_STATE_UNMANAGED, LINK_STATE_PENDING, LINK_STATE_INITIALIZED)) {
-                log_link_debug(link, "State is %s, dropping config", link_state_to_string(link->state));
+                log_link_debug(link, "State is %s, dropping foreign config", link_state_to_string(link->state));
                 r = link_drop_foreign_config(link);
                 if (r < 0)
                         return r;
@@ -2224,12 +2259,6 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for
         link_set_state(link, LINK_STATE_INITIALIZED);
         link->activated = false;
 
-        /* link_configure_duid() returns 0 if it requests product UUID. In that case,
-         * link_configure() is called later asynchronously. */
-        r = link_configure_duid(link);
-        if (r <= 0)
-                return r;
-
         r = link_configure(link);
         if (r < 0)
                 return r;
@@ -2344,12 +2373,6 @@ static int link_initialized_and_synced(Link *link) {
         if (r < 0)
                 return r;
 
-        /* link_configure_duid() returns 0 if it requests product UUID. In that case,
-         * link_configure() is called later asynchronously. */
-        r = link_configure_duid(link);
-        if (r <= 0)
-                return r;
-
         r = link_configure(link);
         if (r < 0)
                 return r;
@@ -2446,7 +2469,7 @@ static int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
                 sprintf(ifindex_str, "n%d", link->ifindex);
                 r = sd_device_new_from_device_id(&device, ifindex_str);
                 if (r < 0) {
-                        log_link_warning_errno(link, r, "Could not find device, waiting for device initialization: %m");
+                        log_link_debug_errno(link, r, "Could not find device, waiting for device initialization: %m");
                         return 0;
                 }
 
@@ -2563,6 +2586,10 @@ static int link_carrier_gained(Link *link) {
 
         assert(link);
 
+        if (link->iftype == ARPHRD_CAN)
+                /* let's shortcut things for CAN which doesn't need most of what's done below. */
+                return link_handle_bound_by_list(link);
+
         r = wifi_get_info(link);
         if (r < 0)
                 return r;
@@ -2621,6 +2648,10 @@ static int link_carrier_lost(Link *link) {
         if (link->network && link->network->ignore_carrier_loss)
                 return 0;
 
+        if (link->iftype == ARPHRD_CAN)
+                /* let's shortcut things for CAN which doesn't need most of what's done below. */
+                return link_handle_bound_by_list(link);
+
         /* Some devices reset itself while setting the MTU. This causes the DHCP client fall into a loop.
          * setting_mtu keep track whether the device got reset because of setting MTU and does not drop the
          * configuration and stop the clients as well. */
@@ -2638,7 +2669,7 @@ static int link_carrier_lost(Link *link) {
                 return r;
 
         if (!IN_SET(link->state, LINK_STATE_UNMANAGED, LINK_STATE_PENDING, LINK_STATE_INITIALIZED)) {
-                log_link_debug(link, "State is %s, dropping config", link_state_to_string(link->state));
+                log_link_debug(link, "State is %s, dropping foreign config", link_state_to_string(link->state));
                 r = link_drop_foreign_config(link);
                 if (r < 0)
                         return r;
@@ -2708,6 +2739,10 @@ static int link_admin_state_down(Link *link) {
                 return 0;
 
         if (link->network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) {
+                if (streq_ptr(link->kind, "can") && !link->can_configured)
+                        /* CAN device needs to be down on configure. */
+                        return 0;
+
                 log_link_info(link, "ActivationPolicy is \"always-on\", forcing link up");
                 return link_up(link);
         }
@@ -2806,6 +2841,12 @@ static int link_update(Link *link, sd_netlink_message *m) {
                                 return log_link_warning_errno(link, r, "Could not update MAC for NDisc: %m");
                 }
 
+                if (link->lldp) {
+                        r = sd_lldp_set_filter_address(link->lldp, &link->hw_addr.addr.ether);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "Could not update MAC address for LLDP: %m");
+                }
+
                 r = ipv4_dad_update_mac(link);
                 if (r < 0)
                         return log_link_warning_errno(link, r, "Could not update MAC address in IPv4 ACD client: %m");
@@ -2957,15 +2998,3 @@ static const char* const link_state_table[_LINK_STATE_MAX] = {
 };
 
 DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
-
-int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg) {
-        const char *err_msg = NULL;
-
-        (void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
-        return log_link_full_errno(link, level, err,
-                                   "%s: %s%s%s%m",
-                                   msg,
-                                   strempty(err_msg),
-                                   err_msg && !endswith(err_msg, ".") ? "." : "",
-                                   err_msg ? " " : "");
-}
index d3353a1c4f20ccd928c11566de7d96d0eb55dd64..b560dde0dcadb844ba0e8c4e1d92f9d14921f123 100644 (file)
@@ -75,6 +75,8 @@ typedef struct Link {
         LinkOperationalState operstate;
         LinkCarrierState carrier_state;
         LinkAddressState address_state;
+        LinkAddressState ipv4_address_state;
+        LinkAddressState ipv6_address_state;
 
         unsigned address_messages;
         unsigned address_remove_messages;
@@ -129,6 +131,7 @@ typedef struct Link {
         bool setting_genmode:1;
         bool ipv6_mtu_set:1;
         bool bridge_mdb_configured:1;
+        bool can_configured:1;
         bool activated:1;
 
         sd_dhcp_server *dhcp_server;
@@ -149,6 +152,7 @@ typedef struct Link {
         sd_dhcp6_lease *dhcp6_lease;
         Set *dhcp6_addresses, *dhcp6_addresses_old;
         Set *dhcp6_routes, *dhcp6_routes_old;
+        Set *dhcp6_pd_prefixes;
         Set *dhcp6_pd_addresses, *dhcp6_pd_addresses_old;
         Set *dhcp6_pd_routes, *dhcp6_pd_routes_old;
         unsigned dhcp6_address_messages;
@@ -204,7 +208,9 @@ DEFINE_TRIVIAL_DESTRUCTOR(link_netlink_destroy_callback, Link, link_unref);
 
 int link_get(Manager *m, int ifindex, Link **ret);
 
+int link_up(Link *link);
 int link_down(Link *link, link_netlink_message_handler_t callback);
+int link_activate(Link *link);
 
 void link_enter_failed(Link *link);
 
@@ -234,10 +240,3 @@ int link_reconfigure(Link *link, bool force);
 
 int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, void *userdata);
 int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
-
-int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg);
-#define log_link_message_error_errno(link, m, err, msg)   log_link_message_full_errno(link, m, LOG_ERR, err, msg)
-#define log_link_message_warning_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_WARNING, err, msg)
-#define log_link_message_notice_errno(link, m, err, msg)  log_link_message_full_errno(link, m, LOG_NOTICE, err, msg)
-#define log_link_message_info_errno(link, m, err, msg)    log_link_message_full_errno(link, m, LOG_INFO, err, msg)
-#define log_link_message_debug_errno(link, m, err, msg)   log_link_message_full_errno(link, m, LOG_DEBUG, err, msg)
index bf1dd045b870a4622737a8abd66d1c3197987d87..5b1b90cdd3deb0210dbfaa19eaebf9e24b1e8c63 100644 (file)
@@ -73,15 +73,16 @@ int link_lldp_rx_configure(Link *link) {
         if (!link_lldp_rx_enabled(link))
                 return 0;
 
-        if (!link->lldp) {
-                r = sd_lldp_new(&link->lldp);
-                if (r < 0)
-                        return r;
+        if (link->lldp)
+                return -EBUSY;
 
-                r = sd_lldp_attach_event(link->lldp, link->manager->event, 0);
-                if (r < 0)
-                        return r;
-        }
+        r = sd_lldp_new(&link->lldp);
+        if (r < 0)
+                return r;
+
+        r = sd_lldp_attach_event(link->lldp, link->manager->event, 0);
+        if (r < 0)
+                return r;
 
         r = sd_lldp_set_ifindex(link->lldp, link->ifindex);
         if (r < 0)
index 1b97e6584e2235226bfce52314a9dd201d3ea7e4..bd77b788529e3edf9f33dab1fa42693337e53a18 100644 (file)
@@ -378,7 +378,7 @@ int link_lldp_emit_start(Link *link) {
         link->lldp_tx_fast = LLDP_TX_FAST_INIT;
 
         next = usec_add(usec_add(now(clock_boottime_or_monotonic()), LLDP_FAST_TX_USEC),
-                     (usec_t) random_u64() % LLDP_JITTER_USEC);
+                        (usec_t) random_u64() % LLDP_JITTER_USEC);
 
         if (link->lldp_emit_event_source) {
                 usec_t old;
index fce10a7e7dcfaeb20f80713b093fec735c35fcf7..0acaeb2bed0cb2af251e92901b6312014d9b847e 100644 (file)
@@ -235,6 +235,8 @@ const sd_bus_vtable manager_vtable[] = {
         SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Manager, operational_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("CarrierState", "s", property_get_carrier_state, offsetof(Manager, carrier_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Manager, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("IPv4AddressState", "s", property_get_address_state, offsetof(Manager, ipv4_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("IPv6AddressState", "s", property_get_address_state, offsetof(Manager, ipv6_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
 
         SD_BUS_METHOD_WITH_ARGS("ListLinks",
                                 SD_BUS_NO_ARGS,
@@ -339,7 +341,7 @@ int manager_send_changed_strv(Manager *manager, char **properties) {
         assert(manager);
         assert(properties);
 
-        if (!manager->bus)
+        if (sd_bus_is_ready(manager->bus) <= 0)
                 return 0;
 
         return sd_bus_emit_properties_changed_strv(
index bfdb1f8c96643574015257448cbcbb1ea7a453dd..562ce5ca54292723dc7cbbe037e52cd8388763db 100644 (file)
@@ -100,8 +100,8 @@ static int on_connected(sd_bus_message *message, void *userdata, sd_bus_error *r
                 (void) manager_set_hostname(m, m->dynamic_hostname);
         if (m->dynamic_timezone)
                 (void) manager_set_timezone(m, m->dynamic_timezone);
-        if (m->links_requesting_uuid)
-                (void) manager_request_product_uuid(m, NULL);
+        if (!set_isempty(m->links_requesting_uuid))
+                (void) manager_request_product_uuid(m);
 
         return 0;
 }
@@ -380,7 +380,11 @@ int manager_new(Manager **ret) {
         *m = (Manager) {
                 .speed_meter_interval_usec = SPEED_METER_DEFAULT_TIME_INTERVAL,
                 .manage_foreign_routes = true,
+                .manage_foreign_rules = true,
                 .ethtool_fd = -1,
+                .dhcp_duid.type = DUID_TYPE_EN,
+                .dhcp6_duid.type = DUID_TYPE_EN,
+                .duid_product_uuid.type = DUID_TYPE_UUID,
         };
 
         m->state_file = strdup("/run/systemd/netif/state");
@@ -426,8 +430,6 @@ int manager_new(Manager **ret) {
         if (r < 0)
                 return r;
 
-        m->duid.type = DUID_TYPE_EN;
-
         *ret = TAKE_PTR(m);
 
         return 0;
@@ -451,7 +453,6 @@ Manager* manager_free(Manager *m) {
         m->links_requesting_uuid = set_free_with_destructor(m->links_requesting_uuid, link_unref);
         m->links = hashmap_free_with_destructor(m->links, link_unref);
 
-        m->duids_requesting_uuid = set_free(m->duids_requesting_uuid);
         m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref);
 
         m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
@@ -655,6 +656,9 @@ static int manager_enumerate_rules(Manager *m) {
         assert(m);
         assert(m->rtnl);
 
+        if (!m->manage_foreign_rules)
+                return 0;
+
         r = sd_rtnl_message_new_routing_policy_rule(m->rtnl, &req, RTM_GETRULE, 0);
         if (r < 0)
                 return r;
@@ -767,8 +771,8 @@ int manager_set_hostname(Manager *m, const char *hostname) {
         if (r < 0)
                 return r;
 
-        if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
-                log_debug("Not connected to system bus, setting hostname later.");
+        if (sd_bus_is_ready(m->bus) <= 0) {
+                log_debug("Not connected to system bus, setting system hostname later.");
                 return 0;
         }
 
@@ -784,7 +788,6 @@ int manager_set_hostname(Manager *m, const char *hostname) {
                         "sb",
                         hostname,
                         false);
-
         if (r < 0)
                 return log_error_errno(r, "Could not set transient hostname: %m");
 
@@ -817,8 +820,8 @@ int manager_set_timezone(Manager *m, const char *tz) {
         if (r < 0)
                 return r;
 
-        if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
-                log_debug("Not connected to system bus, setting timezone later.");
+        if (sd_bus_is_ready(m->bus) <= 0) {
+                log_debug("Not connected to system bus, setting system timezone later.");
                 return 0;
         }
 
index 929855daaf1bd2b1300fd0a9e6944d10981ae58a..301b97c1a100789f4ca3410877f57cfae374eb81 100644 (file)
@@ -28,10 +28,11 @@ struct Manager {
         Hashmap *polkit_registry;
         int ethtool_fd;
 
-        bool enumerating:1;
-        bool dirty:1;
-        bool restarting:1;
+        bool enumerating;
+        bool dirty;
+        bool restarting;
         bool manage_foreign_routes;
+        bool manage_foreign_rules;
 
         Set *dirty_links;
 
@@ -39,6 +40,8 @@ struct Manager {
         LinkOperationalState operational_state;
         LinkCarrierState carrier_state;
         LinkAddressState address_state;
+        LinkAddressState ipv4_address_state;
+        LinkAddressState ipv6_address_state;
 
         Hashmap *links;
         Hashmap *netdevs;
@@ -49,11 +52,12 @@ struct Manager {
 
         usec_t network_dirs_ts_usec;
 
-        DUID duid;
-        sd_id128_t product_uuid;
+        DUID dhcp_duid;
+        DUID dhcp6_duid;
+        DUID duid_product_uuid;
         bool has_product_uuid;
+        bool product_uuid_requested;
         Set *links_requesting_uuid;
-        Set *duids_requesting_uuid;
 
         char* dynamic_hostname;
         char* dynamic_timezone;
@@ -83,8 +87,8 @@ struct Manager {
         usec_t speed_meter_usec_new;
         usec_t speed_meter_usec_old;
 
-        bool dhcp4_prefix_root_cannot_set_table:1;
-        bool bridge_mdb_on_master_not_supported:1;
+        bool dhcp4_prefix_root_cannot_set_table;
+        bool bridge_mdb_on_master_not_supported;
 
         FirewallContext *fw_ctx;
 };
index f5aff722488ef89e5ba5578009b0afcfb58f6443..b3d583e6e62ab1e8155a429ee6496549382e18c6 100644 (file)
@@ -208,8 +208,10 @@ int link_set_bridge_mdb(Link *link) {
         if (hashmap_isempty(link->network->mdb_entries_by_section))
                 goto finish;
 
-        if (!link_has_carrier(link))
-                return log_link_debug(link, "Link does not have carrier yet, setting MDB entries later.");
+        if (!link_has_carrier(link)) {
+                log_link_debug(link, "Link does not have carrier yet, setting MDB entries later.");
+                return 0;
+        }
 
         if (link->network->bridge) {
                 Link *master;
@@ -218,8 +220,10 @@ int link_set_bridge_mdb(Link *link) {
                 if (r < 0)
                         return log_link_error_errno(link, r, "Failed to get Link object for Bridge=%s", link->network->bridge->ifname);
 
-                if (!link_has_carrier(master))
-                        return log_link_debug(link, "Bridge interface %s does not have carrier yet, setting MDB entries later.", link->network->bridge->ifname);
+                if (!link_has_carrier(master)) {
+                        log_link_debug(link, "Bridge interface %s does not have carrier yet, setting MDB entries later.", link->network->bridge->ifname);
+                        return 0;
+                }
 
         } else if (!streq_ptr(link->kind, "bridge")) {
                 log_link_warning(link, "Link is neither a bridge master nor a bridge port, ignoring [BridgeMDB] sections.");
index 035e80dab0e7ed9dee9a1118f5704c99da05a25a..988c673255e9b4a42b4ec82af710987890925c6d 100644 (file)
@@ -530,7 +530,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
 
         route->family = AF_INET6;
         route->table = table;
-        route->priority = link->network->dhcp6_route_metric;
+        route->priority = link->network->ipv6_accept_ra_route_metric;
         route->protocol = RTPROT_RA;
         route->pref = preference;
         route->gw_family = AF_INET6;
@@ -554,11 +554,11 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
                 if (!route_gw->table_set)
                         route_gw->table = table;
                 if (!route_gw->priority_set)
-                        route_gw->priority = link->network->dhcp6_route_metric;
+                        route_gw->priority = link->network->ipv6_accept_ra_route_metric;
                 if (!route_gw->protocol_set)
                         route_gw->protocol = RTPROT_RA;
                 if (!route_gw->pref_set)
-                        route->pref = preference;
+                        route_gw->pref = preference;
                 route_gw->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC);
                 if (route_gw->mtu == 0)
                         route_gw->mtu = mtu;
@@ -814,7 +814,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
 
         route->family = AF_INET6;
         route->table = link_get_ipv6_accept_ra_route_table(link);
-        route->priority = link->network->dhcp6_route_metric;
+        route->priority = link->network->ipv6_accept_ra_route_metric;
         route->protocol = RTPROT_RA;
         route->flags = RTM_F_PREFIX;
         route->dst_prefixlen = prefixlen;
@@ -899,7 +899,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
 
         route->family = AF_INET6;
         route->table = link_get_ipv6_accept_ra_route_table(link);
-        route->priority = link->network->dhcp6_route_metric;
+        route->priority = link->network->ipv6_accept_ra_route_metric;
         route->protocol = RTPROT_RA;
         route->pref = preference;
         route->gw = gateway;
@@ -1315,15 +1315,16 @@ int ndisc_configure(Link *link) {
         if (!link_ipv6_accept_ra_enabled(link))
                 return 0;
 
-        if (!link->ndisc) {
-                r = sd_ndisc_new(&link->ndisc);
-                if (r < 0)
-                        return r;
+        if (link->ndisc)
+                return -EBUSY; /* Already configured. */
 
-                r = sd_ndisc_attach_event(link->ndisc, link->manager->event, 0);
-                if (r < 0)
-                        return r;
-        }
+        r = sd_ndisc_new(&link->ndisc);
+        if (r < 0)
+                return r;
+
+        r = sd_ndisc_attach_event(link->ndisc, link->manager->event, 0);
+        if (r < 0)
+                return r;
 
         r = sd_ndisc_set_mac(link->ndisc, &link->hw_addr.addr.ether);
         if (r < 0)
@@ -1340,6 +1341,17 @@ int ndisc_configure(Link *link) {
         return 0;
 }
 
+int ndisc_start(Link *link) {
+        assert(link);
+
+        if (!link->ndisc || !link->dhcp6_client)
+                return 0;
+
+        log_link_debug(link, "Discovering IPv6 routers");
+
+        return sd_ndisc_start(link->ndisc);
+}
+
 void ndisc_vacuum(Link *link) {
         NDiscRDNSS *r;
         NDiscDNSSL *d;
@@ -1555,8 +1567,10 @@ int config_parse_address_generation_type(
         return 0;
 }
 
+DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_use_domains, dhcp_use_domains, DHCPUseDomains,
+                         "Failed to parse UseDomains= setting");
 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client, ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client,
-                         "Failed to parse DHCPv6Client= setting")
+                         "Failed to parse DHCPv6Client= setting");
 static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = {
         [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO]     = "no",
         [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS] = "always",
index 8984d886115519f10650b32416d02bcb4347d32a..2ff9a8969d6bc8a0eb512825bb5897c1b131191c 100644 (file)
@@ -73,12 +73,14 @@ bool link_ipv6_accept_ra_enabled(Link *link);
 void network_adjust_ipv6_accept_ra(Network *network);
 
 int ndisc_configure(Link *link);
+int ndisc_start(Link *link);
 void ndisc_vacuum(Link *link);
 void ndisc_flush(Link *link);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_ndisc_address_filter);
 CONFIG_PARSER_PROTOTYPE(config_parse_address_generation_type);
 CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_start_dhcp6_client);
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_use_domains);
 
 const char* ipv6_accept_ra_start_dhcp6_client_to_string(IPv6AcceptRAStartDHCP6Client i) _const_;
 IPv6AcceptRAStartDHCP6Client ipv6_accept_ra_start_dhcp6_client_from_string(const char *s) _pure_;
index f54a2f9c99f458744c9da432abb87b384b142e03..b33f560b79870af8497b848c7c6c02f5f4d5b392 100644 (file)
@@ -213,6 +213,29 @@ static bool neighbor_equal(const Neighbor *n1, const Neighbor *n2) {
         return neighbor_compare_func(n1, n2) == 0;
 }
 
+static void log_neighbor_debug(const Neighbor *neighbor, const char *str, const Link *link) {
+        _cleanup_free_ char *lladdr = NULL, *dst = NULL;
+
+        assert(neighbor);
+        assert(str);
+
+        if (!DEBUG_LOGGING)
+                return;
+
+        if (neighbor->lladdr_size == sizeof(struct ether_addr))
+                (void) ether_addr_to_string_alloc(&neighbor->lladdr.mac, &lladdr);
+        else if (neighbor->lladdr_size == sizeof(struct in_addr))
+                (void) in_addr_to_string(AF_INET, &neighbor->lladdr.ip, &lladdr);
+        else if (neighbor->lladdr_size == sizeof(struct in6_addr))
+                (void) in_addr_to_string(AF_INET6, &neighbor->lladdr.ip, &lladdr);
+
+        (void) in_addr_to_string(neighbor->family, &neighbor->in_addr, &dst);
+
+        log_link_debug(link,
+                       "%s neighbor: lladdr: %s, dst: %s",
+                       str, strna(lladdr), strna(dst));
+}
+
 static int neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         int r;
 
@@ -249,6 +272,8 @@ static int neighbor_configure(Neighbor *neighbor, Link *link) {
         assert(link->manager);
         assert(link->manager->rtnl);
 
+        log_neighbor_debug(neighbor, "Configuring", link);
+
         r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH,
                                       link->ifindex, neighbor->family);
         if (r < 0)
@@ -258,10 +283,6 @@ static int neighbor_configure(Neighbor *neighbor, Link *link) {
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not set state: %m");
 
-        r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_REPLACE);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set flags: %m");
-
         r = sd_netlink_message_append_data(req, NDA_LLADDR, &neighbor->lladdr, neighbor->lladdr_size);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not append NDA_LLADDR attribute: %m");
@@ -344,6 +365,8 @@ static int neighbor_remove(Neighbor *neighbor, Link *link) {
         assert(link->manager);
         assert(link->manager->rtnl);
 
+        log_neighbor_debug(neighbor, "Removing", link);
+
         r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_DELNEIGH,
                                       link->ifindex, neighbor->family);
         if (r < 0)
@@ -414,50 +437,9 @@ int link_drop_neighbors(Link *link) {
         return r;
 }
 
-static int manager_rtnl_process_neighbor_lladdr(sd_netlink_message *message, union lladdr_union *lladdr, size_t *size, char **str) {
-        int r;
-
-        assert(message);
-        assert(lladdr);
-        assert(size);
-        assert(str);
-
-        *str = NULL;
-
-        r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in6), &lladdr->ip.in6);
-        if (r >= 0) {
-                *size = sizeof(lladdr->ip.in6);
-                if (in_addr_to_string(AF_INET6, &lladdr->ip, str) < 0)
-                        log_warning_errno(r, "Could not print lower address: %m");
-                return r;
-        }
-
-        r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->mac), &lladdr->mac);
-        if (r >= 0) {
-                *size = sizeof(lladdr->mac);
-                *str = new(char, ETHER_ADDR_TO_STRING_MAX);
-                if (!*str) {
-                        log_oom();
-                        return r;
-                }
-                ether_addr_to_string(&lladdr->mac, *str);
-                return r;
-        }
-
-        r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in), &lladdr->ip.in);
-        if (r >= 0) {
-                *size = sizeof(lladdr->ip.in);
-                if (in_addr_to_string(AF_INET, &lladdr->ip, str) < 0)
-                        log_warning_errno(r, "Could not print lower address: %m");
-                return r;
-        }
-
-        return r;
-}
-
 int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
         _cleanup_(neighbor_freep) Neighbor *tmp = NULL;
-        _cleanup_free_ char *addr_str = NULL, *lladdr_str = NULL;
+        _cleanup_free_ void *lladdr = NULL;
         Neighbor *neighbor = NULL;
         uint16_t type, state;
         int ifindex, r;
@@ -504,10 +486,9 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message,
 
         r = link_get(m, ifindex, &link);
         if (r < 0 || !link) {
-                /* when enumerating we might be out of sync, but we will get the neighbor again, so just
-                 * ignore it */
-                if (!m->enumerating)
-                        log_warning("rtnl: received neighbor for link '%d' we don't know about, ignoring.", ifindex);
+                /* when enumerating we might be out of sync, but we will get the neighbor again. Also,
+                 * kernel sends messages about neighbors after a link is removed. So, just ignore it. */
+                log_debug("rtnl: received neighbor for link '%d' we don't know about, ignoring.", ifindex);
                 return 0;
         }
 
@@ -528,44 +509,36 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message,
                 return 0;
         }
 
-        if (in_addr_to_string(tmp->family, &tmp->in_addr, &addr_str) < 0)
-                log_link_warning_errno(link, r, "Could not print address: %m");
-
-        r = manager_rtnl_process_neighbor_lladdr(message, &tmp->lladdr, &tmp->lladdr_size, &lladdr_str);
+        r = sd_netlink_message_read_data(message, NDA_LLADDR, &tmp->lladdr_size, &lladdr);
         if (r < 0) {
-                log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid lladdr, ignoring: %m");
+                log_link_warning_errno(link, r, "rtnl: received neighbor message without valid lladdr, ignoring: %m");
+                return 0;
+        } else if (!IN_SET(tmp->lladdr_size, sizeof(struct ether_addr), sizeof(struct in_addr), sizeof(struct in6_addr))) {
+                log_link_warning(link, "rtnl: received neighbor message with invalid lladdr size (%zu), ignoring: %m", tmp->lladdr_size);
                 return 0;
         }
+        memcpy(&tmp->lladdr, lladdr, tmp->lladdr_size);
 
         (void) neighbor_get(link, tmp, &neighbor);
 
         switch (type) {
         case RTM_NEWNEIGH:
                 if (neighbor)
-                        log_link_debug(link, "Received remembered neighbor: %s->%s",
-                                       strnull(addr_str), strnull(lladdr_str));
+                        log_neighbor_debug(tmp, "Received remembered", link);
                 else {
-                        /* A neighbor appeared that we did not request */
+                        log_neighbor_debug(tmp, "Remembering foreign", link);
                         r = neighbor_add_foreign(link, tmp, NULL);
                         if (r < 0) {
-                                log_link_warning_errno(link, r, "Failed to remember foreign neighbor %s->%s, ignoring: %m",
-                                                       strnull(addr_str), strnull(lladdr_str));
+                                log_link_warning_errno(link, r, "Failed to remember foreign neighbor, ignoring: %m");
                                 return 0;
-                        } else
-                                log_link_debug(link, "Remembering foreign neighbor: %s->%s",
-                                               strnull(addr_str), strnull(lladdr_str));
+                        }
                 }
 
                 break;
 
         case RTM_DELNEIGH:
-                if (neighbor) {
-                        log_link_debug(link, "Forgetting neighbor: %s->%s",
-                                       strnull(addr_str), strnull(lladdr_str));
-                        (void) neighbor_free(neighbor);
-                } else
-                        log_link_debug(link, "Kernel removed a neighbor we don't remember: %s->%s, ignoring.",
-                                       strnull(addr_str), strnull(lladdr_str));
+                log_neighbor_debug(tmp, neighbor ? "Forgetting" : "Kernel removed unknown", link);
+                neighbor_free(neighbor);
 
                 break;
 
index a6111340687a1a370df612ba2dc06daee7d08ef4..902953a629c9cfdc34b796da9ca552e0963ef162 100644 (file)
@@ -10,7 +10,6 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
 #include "networkd-address-label.h"
 #include "networkd-address.h"
 #include "networkd-can.h"
-#include "networkd-conf.h"
 #include "networkd-dhcp-common.h"
 #include "networkd-dhcp-server.h"
 #include "networkd-dhcp4.h"
@@ -57,6 +56,7 @@ Match.Virtualization,                        config_parse_net_condition,
 Match.KernelCommandLine,                     config_parse_net_condition,                               CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, conditions)
 Match.KernelVersion,                         config_parse_net_condition,                               CONDITION_KERNEL_VERSION,      offsetof(Network, conditions)
 Match.Architecture,                          config_parse_net_condition,                               CONDITION_ARCHITECTURE,        offsetof(Network, conditions)
+Match.Firmware,                              config_parse_net_condition,                               CONDITION_FIRMWARE,            offsetof(Network, conditions)
 Link.MACAddress,                             config_parse_hwaddr,                                      0,                             offsetof(Network, mac)
 Link.MTUBytes,                               config_parse_mtu,                                         AF_UNSPEC,                     offsetof(Network, mtu)
 Link.Group,                                  config_parse_uint32,                                      0,                             offsetof(Network, group)
@@ -67,6 +67,7 @@ Link.Promiscuous,                            config_parse_tristate,
 Link.Unmanaged,                              config_parse_bool,                                        0,                             offsetof(Network, unmanaged)
 Link.ActivationPolicy,                       config_parse_activation_policy,                           0,                             offsetof(Network, activation_policy)
 Link.RequiredForOnline,                      config_parse_required_for_online,                         0,                             0
+Link.RequiredFamilyForOnline,                config_parse_required_family_for_online,                  0,                             offsetof(Network, required_family_for_online)
 SR-IOV.VirtualFunction,                      config_parse_sr_iov_uint32,                               0,                             0
 SR-IOV.VLANId,                               config_parse_sr_iov_uint32,                               0,                             0
 SR-IOV.QualityOfService,                     config_parse_sr_iov_uint32,                               0,                             0
@@ -145,6 +146,7 @@ Address.AddPrefixRoute,                      config_parse_address_flags,
 Address.AutoJoin,                            config_parse_address_flags,                               IFA_F_MCAUTOJOIN,              0
 Address.DuplicateAddressDetection,           config_parse_duplicate_address_detection,                 0,                             0
 Address.Scope,                               config_parse_address_scope,                               0,                             0
+Address.RouteMetric,                         config_parse_address_route_metric,                        0,                             0
 IPv6AddressLabel.Prefix,                     config_parse_address_label_prefix,                        0,                             0
 IPv6AddressLabel.Label,                      config_parse_address_label,                               0,                             0
 Neighbor.Address,                            config_parse_neighbor_address,                            0,                             0
@@ -196,27 +198,28 @@ DHCPv4.ClientIdentifier,                     config_parse_dhcp_client_identifier
 DHCPv4.UseDNS,                               config_parse_dhcp_use_dns,                                0,                             0
 DHCPv4.RoutesToDNS,                          config_parse_bool,                                        0,                             offsetof(Network, dhcp_routes_to_dns)
 DHCPv4.UseNTP,                               config_parse_dhcp_use_ntp,                                0,                             0
+DHCPv4.RoutesToNTP,                          config_parse_bool,                                        0,                             offsetof(Network, dhcp_routes_to_ntp)
 DHCPv4.UseSIP,                               config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_sip)
 DHCPv4.UseMTU,                               config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_mtu)
 DHCPv4.UseHostname,                          config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_hostname)
-DHCPv4.UseDomains,                           config_parse_dhcp_use_domains,                            0,                             offsetof(Network, dhcp_use_domains)
+DHCPv4.UseDomains,                           config_parse_dhcp_use_domains,                            0,                             0
 DHCPv4.UseRoutes,                            config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_routes)
 DHCPv4.UseGateway,                           config_parse_tristate,                                    0,                             offsetof(Network, dhcp_use_gateway)
 DHCPv4.RequestOptions,                       config_parse_dhcp_request_options,                        AF_INET,                       0
 DHCPv4.Anonymize,                            config_parse_bool,                                        0,                             offsetof(Network, dhcp_anonymize)
 DHCPv4.SendHostname,                         config_parse_bool,                                        0,                             offsetof(Network, dhcp_send_hostname)
 DHCPv4.Hostname,                             config_parse_hostname,                                    0,                             offsetof(Network, dhcp_hostname)
-DHCPv4.RequestBroadcast,                     config_parse_bool,                                        0,                             offsetof(Network, dhcp_broadcast)
+DHCPv4.RequestBroadcast,                     config_parse_tristate,                                    0,                             offsetof(Network, dhcp_broadcast)
 DHCPv4.VendorClassIdentifier,                config_parse_string,                                      0,                             offsetof(Network, dhcp_vendor_class_identifier)
 DHCPv4.MUDURL,                               config_parse_dhcp_mud_url,                                0,                             0
 DHCPv4.MaxAttempts,                          config_parse_dhcp_max_attempts,                           0,                             0
 DHCPv4.UserClass,                            config_parse_dhcp_user_or_vendor_class,                   AF_INET,                       offsetof(Network, dhcp_user_class)
-DHCPv4.DUIDType,                             config_parse_duid_type,                                   0,                             offsetof(Network, duid)
-DHCPv4.DUIDRawData,                          config_parse_duid_rawdata,                                0,                             offsetof(Network, duid)
+DHCPv4.IAID,                                 config_parse_iaid,                                        AF_INET,                       0
+DHCPv4.DUIDType,                             config_parse_network_duid_type,                           0,                             0
+DHCPv4.DUIDRawData,                          config_parse_network_duid_rawdata,                        0,                             0
 DHCPv4.RouteMetric,                          config_parse_dhcp_route_metric,                           0,                             0
 DHCPv4.RouteTable,                           config_parse_section_route_table,                         0,                             0
 DHCPv4.UseTimezone,                          config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_timezone)
-DHCPv4.IAID,                                 config_parse_iaid,                                        0,                             0
 DHCPv4.ListenPort,                           config_parse_uint16,                                      0,                             offsetof(Network, dhcp_client_port)
 DHCPv4.SendRelease,                          config_parse_bool,                                        0,                             offsetof(Network, dhcp_send_release)
 DHCPv4.SendDecline,                          config_parse_bool,                                        0,                             offsetof(Network, dhcp_send_decline)
@@ -230,6 +233,7 @@ DHCPv4.FallbackLeaseLifetimeSec,             config_parse_dhcp_fallback_lease_li
 DHCPv6.UseAddress,                           config_parse_bool,                                        0,                             offsetof(Network, dhcp6_use_address)
 DHCPv6.UseDNS,                               config_parse_dhcp_use_dns,                                0,                             0
 DHCPv6.UseHostname,                          config_parse_bool,                                        0,                             offsetof(Network, dhcp6_use_hostname)
+DHCPv6.UseDomains,                           config_parse_dhcp_use_domains,                            0,                             0
 DHCPv6.UseNTP,                               config_parse_dhcp_use_ntp,                                0,                             0
 DHCPv6.RapidCommit,                          config_parse_bool,                                        0,                             offsetof(Network, dhcp6_rapid_commit)
 DHCPv6.MUDURL,                               config_parse_dhcp6_mud_url,                               0,                             0
@@ -241,19 +245,23 @@ DHCPv6.ForceDHCPv6PDOtherInformation,        config_parse_bool,
 DHCPv6.PrefixDelegationHint,                 config_parse_dhcp6_pd_hint,                               0,                             0
 DHCPv6.WithoutRA,                            config_parse_dhcp6_client_start_mode,                     0,                             offsetof(Network, dhcp6_without_ra)
 DHCPv6.SendOption,                           config_parse_dhcp_send_option,                            AF_INET6,                      offsetof(Network, dhcp6_client_send_options)
-DHCPv6.RouteMetric,                          config_parse_dhcp_route_metric,                           0,                             0
+DHCPv6.IAID,                                 config_parse_iaid,                                        AF_INET6,                      0
+DHCPv6.DUIDType,                             config_parse_duid_type,                                   0,                             offsetof(Network, dhcp6_duid)
+DHCPv6.DUIDRawData,                          config_parse_duid_rawdata,                                0,                             offsetof(Network, dhcp6_duid)
 IPv6AcceptRA.UseAutonomousPrefix,            config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_autonomous_prefix)
 IPv6AcceptRA.UseOnLinkPrefix,                config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_onlink_prefix)
 IPv6AcceptRA.UseDNS,                         config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_dns)
-IPv6AcceptRA.UseDomains,                     config_parse_dhcp_use_domains,                            0,                             offsetof(Network, ipv6_accept_ra_use_domains)
+IPv6AcceptRA.UseDomains,                     config_parse_ipv6_accept_ra_use_domains,                  0,                             offsetof(Network, ipv6_accept_ra_use_domains)
 IPv6AcceptRA.DHCPv6Client,                   config_parse_ipv6_accept_ra_start_dhcp6_client,           0,                             offsetof(Network, ipv6_accept_ra_start_dhcp6_client)
 IPv6AcceptRA.RouteTable,                     config_parse_section_route_table,                         0,                             0
+IPv6AcceptRA.RouteMetric,                    config_parse_dhcp_route_metric,                           0,                             0
 IPv6AcceptRA.RouterAllowList,                config_parse_ndisc_address_filter,                        0,                             offsetof(Network, ndisc_allow_listed_router)
 IPv6AcceptRA.RouterDenyList,                 config_parse_ndisc_address_filter,                        0,                             offsetof(Network, ndisc_deny_listed_router)
 IPv6AcceptRA.PrefixAllowList,                config_parse_ndisc_address_filter,                        0,                             offsetof(Network, ndisc_allow_listed_prefix)
 IPv6AcceptRA.PrefixDenyList,                 config_parse_ndisc_address_filter,                        0,                             offsetof(Network, ndisc_deny_listed_prefix)
 IPv6AcceptRA.RouteAllowList,                 config_parse_ndisc_address_filter,                        0,                             offsetof(Network, ndisc_allow_listed_route_prefix)
 IPv6AcceptRA.RouteDenyList,                  config_parse_ndisc_address_filter,                        0,                             offsetof(Network, ndisc_deny_listed_route_prefix)
+DHCPServer.RelayTarget,                      config_parse_dhcp_server_relay_target,                    0,                             0
 DHCPServer.MaxLeaseTimeSec,                  config_parse_sec,                                         0,                             offsetof(Network, dhcp_server_max_lease_time_usec)
 DHCPServer.DefaultLeaseTimeSec,              config_parse_sec,                                         0,                             offsetof(Network, dhcp_server_default_lease_time_usec)
 DHCPServer.EmitDNS,                          config_parse_bool,                                        0,                             offsetof(Network, dhcp_server_emit[SD_DHCP_LEASE_DNS].emit)
@@ -275,6 +283,7 @@ DHCPServer.PoolOffset,                       config_parse_uint32,
 DHCPServer.PoolSize,                         config_parse_uint32,                                      0,                             offsetof(Network, dhcp_server_pool_size)
 DHCPServer.SendVendorOption,                 config_parse_dhcp_send_option,                            0,                             offsetof(Network, dhcp_server_send_vendor_options)
 DHCPServer.SendOption,                       config_parse_dhcp_send_option,                            0,                             offsetof(Network, dhcp_server_send_options)
+DHCPServer.BindToInterface,                  config_parse_bool,                                        0,                             offsetof(Network, dhcp_server_bind_to_interface)
 Bridge.Cost,                                 config_parse_uint32,                                      0,                             offsetof(Network, cost)
 Bridge.UseBPDU,                              config_parse_tristate,                                    0,                             offsetof(Network, use_bpdu)
 Bridge.HairPin,                              config_parse_tristate,                                    0,                             offsetof(Network, hairpin)
@@ -304,6 +313,7 @@ DHCPv6PrefixDelegation.Announce,             config_parse_bool,
 DHCPv6PrefixDelegation.Assign,               config_parse_bool,                                        0,                             offsetof(Network, dhcp6_pd_assign)
 DHCPv6PrefixDelegation.ManageTemporaryAddress, config_parse_bool,                                      0,                             offsetof(Network, dhcp6_pd_manage_temporary_address)
 DHCPv6PrefixDelegation.Token,                config_parse_dhcp6_pd_token,                              0,                             offsetof(Network, dhcp6_pd_token)
+DHCPv6PrefixDelegation.RouteMetric,          config_parse_uint32,                                      0,                             offsetof(Network, dhcp6_pd_route_metric)
 IPv6SendRA.RouterLifetimeSec,                config_parse_sec,                                         0,                             offsetof(Network, router_lifetime_usec)
 IPv6SendRA.Managed,                          config_parse_bool,                                        0,                             offsetof(Network, router_managed)
 IPv6SendRA.OtherInformation,                 config_parse_bool,                                        0,                             offsetof(Network, router_other_information)
@@ -319,6 +329,7 @@ IPv6Prefix.AddressAutoconfiguration,         config_parse_prefix_flags,
 IPv6Prefix.ValidLifetimeSec,                 config_parse_prefix_lifetime,                             0,                             0
 IPv6Prefix.PreferredLifetimeSec,             config_parse_prefix_lifetime,                             0,                             0
 IPv6Prefix.Assign,                           config_parse_prefix_assign,                               0,                             0
+IPv6Prefix.RouteMetric,                      config_parse_prefix_metric,                               0,                             0
 IPv6RoutePrefix.Route,                       config_parse_route_prefix,                                0,                             0
 IPv6RoutePrefix.LifetimeSec,                 config_parse_route_prefix_lifetime,                       0,                             0
 LLDP.MUDURL,                                 config_parse_lldp_mud,                                    0,                             0
@@ -466,27 +477,28 @@ DHCP.UseDNS,                                 config_parse_dhcp_use_dns,
 DHCP.UseNTP,                                 config_parse_dhcp_use_ntp,                                0,                             0
 DHCP.UseMTU,                                 config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_mtu)
 DHCP.UseHostname,                            config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_hostname)
-DHCP.UseDomains,                             config_parse_dhcp_use_domains,                            0,                             offsetof(Network, dhcp_use_domains)
-DHCP.UseDomainName,                          config_parse_dhcp_use_domains,                            0,                             offsetof(Network, dhcp_use_domains)
+DHCP.UseDomains,                             config_parse_dhcp_use_domains,                            0,                             0
+DHCP.UseDomainName,                          config_parse_dhcp_use_domains,                            0,                             0
 DHCP.UseRoutes,                              config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_routes)
 DHCP.Anonymize,                              config_parse_bool,                                        0,                             offsetof(Network, dhcp_anonymize)
 DHCP.SendHostname,                           config_parse_bool,                                        0,                             offsetof(Network, dhcp_send_hostname)
 DHCP.Hostname,                               config_parse_hostname,                                    0,                             offsetof(Network, dhcp_hostname)
-DHCP.RequestBroadcast,                       config_parse_bool,                                        0,                             offsetof(Network, dhcp_broadcast)
+DHCP.RequestBroadcast,                       config_parse_tristate,                                    0,                             offsetof(Network, dhcp_broadcast)
 DHCP.CriticalConnection,                     config_parse_tristate,                                    0,                             offsetof(Network, dhcp_critical)
 DHCP.VendorClassIdentifier,                  config_parse_string,                                      0,                             offsetof(Network, dhcp_vendor_class_identifier)
 DHCP.UserClass,                              config_parse_dhcp_user_or_vendor_class,                   AF_INET,                       offsetof(Network, dhcp_user_class)
-DHCP.DUIDType,                               config_parse_duid_type,                                   0,                             offsetof(Network, duid)
-DHCP.DUIDRawData,                            config_parse_duid_rawdata,                                0,                             offsetof(Network, duid)
+DHCP.IAID,                                   config_parse_iaid,                                        AF_INET,                       0
+DHCP.DUIDType,                               config_parse_network_duid_type,                           0,                             0
+DHCP.DUIDRawData,                            config_parse_network_duid_rawdata,                        0,                             0
 DHCP.RouteMetric,                            config_parse_dhcp_route_metric,                           0,                             0
 DHCP.RouteTable,                             config_parse_section_route_table,                         0,                             0
 DHCP.UseTimezone,                            config_parse_bool,                                        0,                             offsetof(Network, dhcp_use_timezone)
-DHCP.IAID,                                   config_parse_iaid,                                        0,                             0
 DHCP.ListenPort,                             config_parse_uint16,                                      0,                             offsetof(Network, dhcp_client_port)
 DHCP.RapidCommit,                            config_parse_bool,                                        0,                             offsetof(Network, dhcp6_rapid_commit)
 DHCP.ForceDHCPv6PDOtherInformation,          config_parse_bool,                                        0,                             offsetof(Network, dhcp6_force_pd_other_information)
-DHCPv4.UseDomainName,                        config_parse_dhcp_use_domains,                            0,                             offsetof(Network, dhcp_use_domains)
+DHCPv4.UseDomainName,                        config_parse_dhcp_use_domains,                            0,                             0
 DHCPv4.CriticalConnection,                   config_parse_tristate,                                    0,                             offsetof(Network, dhcp_critical)
+DHCPv6.RouteMetric,                          config_parse_dhcp_route_metric,                           0,                             0
 IPv6AcceptRA.DenyList,                       config_parse_ndisc_address_filter,                        0,                             offsetof(Network, ndisc_deny_listed_prefix)
 IPv6AcceptRA.BlackList,                      config_parse_ndisc_address_filter,                        0,                             offsetof(Network, ndisc_deny_listed_prefix)
 TrafficControlQueueingDiscipline.Parent,                        config_parse_qdisc_parent,             _QDISC_KIND_INVALID,           0
index e5ffd35b6f9ab4b6a785678acec3622d60357ddd..78a402625810b2f6541ec39c485df497cea6d29b 100644 (file)
 /* Let's assume that anything above this number is a user misconfiguration. */
 #define MAX_NTP_SERVERS 128
 
-/* Set defaults following RFC7844 */
-void network_apply_anonymize_if_set(Network *network) {
-        if (!network->dhcp_anonymize)
-                return;
-        /* RFC7844 3.7
-         SHOULD NOT send the Host Name option */
-        network->dhcp_send_hostname = false;
-        /* RFC7844 section 3.:
-         MAY contain the Client Identifier option
-         Section 3.5:
-         clients MUST use client identifiers based solely
-         on the link-layer address */
-        /* NOTE: Using MAC, as it does not reveal extra information,
-        * and some servers might not answer if this option is not sent */
-        network->dhcp_client_identifier = DHCP_CLIENT_ID_MAC;
-        /* RFC 7844 3.10:
-         SHOULD NOT use the Vendor Class Identifier option */
-        network->dhcp_vendor_class_identifier = mfree(network->dhcp_vendor_class_identifier);
-        /* RFC7844 section 3.6.:
-         The client intending to protect its privacy SHOULD only request a
-         minimal number of options in the PRL and SHOULD also randomly shuffle
-         the ordering of option codes in the PRL. If this random ordering
-         cannot be implemented, the client MAY order the option codes in the
-         PRL by option code number (lowest to highest).
-        */
-        /* NOTE: dhcp_use_mtu is false by default,
-        * though it was not initiallized to any value in network_load_one.
-        * Maybe there should be another var called *send*?
-        * (to use the MTU sent by the server but to do not send
-        * the option in the PRL). */
-        network->dhcp_use_mtu = false;
-        /* NOTE: when Anonymize=yes, the PRL route options are sent by default,
-         * but this is needed to use them. */
-        network->dhcp_use_routes = true;
-        /* RFC7844 section 3.6.
-        * same comments as previous option */
-        network->dhcp_use_timezone = false;
-}
-
 static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret_netdev) {
         const char *kind_string;
         NetDev *netdev;
@@ -223,9 +184,6 @@ int network_verify(Network *network) {
                 network->dhcp_use_mtu = false;
         }
 
-        if (network->dhcp_use_gateway < 0)
-                network->dhcp_use_gateway = network->dhcp_use_routes;
-
         if (network->dhcp_critical >= 0) {
                 if (network->keep_configuration >= 0)
                         log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
@@ -340,41 +298,33 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                 .allmulticast = -1,
                 .promiscuous = -1,
 
-                .configure_without_carrier = false,
                 .ignore_carrier_loss = -1,
                 .keep_configuration = _KEEP_CONFIGURATION_INVALID,
 
-                .dhcp = ADDRESS_FAMILY_NO,
-                .duid.type = _DUID_TYPE_INVALID,
+                .dhcp_duid.type = _DUID_TYPE_INVALID,
                 .dhcp_critical = -1,
                 .dhcp_use_ntp = true,
+                .dhcp_routes_to_ntp = true,
                 .dhcp_use_sip = true,
                 .dhcp_use_dns = true,
+                .dhcp_routes_to_dns = true,
                 .dhcp_use_hostname = true,
                 .dhcp_use_routes = true,
                 .dhcp_use_gateway = -1,
-                /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
                 .dhcp_send_hostname = true,
                 .dhcp_send_release = true,
-                /* To enable/disable RFC7844 Anonymity Profiles */
-                .dhcp_anonymize = false,
                 .dhcp_route_metric = DHCP_ROUTE_METRIC,
-                /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
-                .dhcp_client_identifier = DHCP_CLIENT_ID_DUID,
+                .dhcp_client_identifier = _DHCP_CLIENT_ID_INVALID,
                 .dhcp_route_table = RT_TABLE_MAIN,
-                .dhcp_route_table_set = false,
-                /* NOTE: from man: UseMTU=... Defaults to false*/
-                .dhcp_use_mtu = false,
-                /* NOTE: from man: UseTimezone=... Defaults to "no".*/
-                .dhcp_use_timezone = false,
                 .dhcp_ip_service_type = -1,
+                .dhcp_broadcast = -1,
 
                 .dhcp6_use_address = true,
                 .dhcp6_use_dns = true,
                 .dhcp6_use_hostname = true,
                 .dhcp6_use_ntp = true,
                 .dhcp6_rapid_commit = true,
-                .dhcp6_route_metric = DHCP_ROUTE_METRIC,
+                .dhcp6_duid.type = _DUID_TYPE_INVALID,
 
                 .dhcp6_pd = -1,
                 .dhcp6_pd_announce = true,
@@ -382,10 +332,10 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                 .dhcp6_pd_manage_temporary_address = true,
                 .dhcp6_pd_subnet_id = -1,
 
+                .dhcp_server_bind_to_interface = true,
                 .dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
                 .dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true,
                 .dhcp_server_emit[SD_DHCP_LEASE_SIP].emit = true,
-
                 .dhcp_server_emit_router = true,
                 .dhcp_server_emit_timezone = true,
 
@@ -432,7 +382,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                 .ipv6_accept_ra_use_autonomous_prefix = true,
                 .ipv6_accept_ra_use_onlink_prefix = true,
                 .ipv6_accept_ra_route_table = RT_TABLE_MAIN,
-                .ipv6_accept_ra_route_table_set = false,
+                .ipv6_accept_ra_route_metric = DHCP_ROUTE_METRIC,
                 .ipv6_accept_ra_start_dhcp6_client = IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES,
 
                 .can_triple_sampling = -1,
@@ -505,8 +455,6 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
         if (r < 0)
                 return r;
 
-        network_apply_anonymize_if_set(network);
-
         r = network_add_ipv4ll_route(network);
         if (r < 0)
                 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
@@ -655,10 +603,6 @@ static Network *network_free(Network *network) {
         ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
         ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free);
 
-        if (network->manager &&
-            network->manager->duids_requesting_uuid)
-                set_remove(network->manager->duids_requesting_uuid, &network->duid);
-
         free(network->name);
 
         free(network->dhcp_server_timezone);
@@ -896,11 +840,9 @@ int config_parse_domains(
                 }
 
                 OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
-                r = ordered_set_ensure_allocated(set, &string_hash_ops_free);
-                if (r < 0)
-                        return log_oom();
-
-                r = ordered_set_put_strdup(*set, domain);
+                r = ordered_set_put_strdup(set, domain);
+                if (r == -EEXIST)
+                        continue;
                 if (r < 0)
                         return log_oom();
         }
@@ -1198,6 +1140,9 @@ int config_parse_required_for_online(
         return 0;
 }
 
+DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online, link_required_address_family, AddressFamily,
+                         "Failed to parse RequiredFamilyForOnline= setting");
+
 DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
                          "Failed to parse KeepConfiguration= setting");
 
index e859b590c624e49d785e3f902794d3157f3acfae..e8c2428becc29cada4d9f6091fab6ba2b2ff33d9 100644 (file)
@@ -104,6 +104,7 @@ struct Network {
         bool unmanaged;
         bool required_for_online; /* Is this network required to be considered online? */
         LinkOperationalStateRange required_operstate_for_online;
+        AddressFamily required_family_for_online;
         ActivationPolicy activation_policy;
 
         /* misc settings */
@@ -117,9 +118,9 @@ struct Network {
         /* DHCP Client Support */
         AddressFamily dhcp;
         DHCPClientIdentifier dhcp_client_identifier;
-        DUID duid;
-        uint32_t iaid;
-        bool iaid_set;
+        DUID dhcp_duid;
+        uint32_t dhcp_iaid;
+        bool dhcp_iaid_set;
         char *dhcp_vendor_class_identifier;
         char *dhcp_mudurl;
         char **dhcp_user_class;
@@ -135,12 +136,13 @@ struct Network {
         int dhcp_ip_service_type;
         bool dhcp_anonymize;
         bool dhcp_send_hostname;
-        bool dhcp_broadcast;
+        int dhcp_broadcast;
         bool dhcp_use_dns;
         bool dhcp_use_dns_set;
         bool dhcp_routes_to_dns;
         bool dhcp_use_ntp;
         bool dhcp_use_ntp_set;
+        bool dhcp_routes_to_ntp;
         bool dhcp_use_sip;
         bool dhcp_use_mtu;
         bool dhcp_use_routes;
@@ -151,6 +153,7 @@ struct Network {
         bool dhcp_send_release;
         bool dhcp_send_decline;
         DHCPUseDomains dhcp_use_domains;
+        bool dhcp_use_domains_set;
         Set *dhcp_deny_listed_ip;
         Set *dhcp_allow_listed_ip;
         Set *dhcp_request_options;
@@ -165,9 +168,13 @@ struct Network {
         bool dhcp6_use_ntp;
         bool dhcp6_use_ntp_set;
         bool dhcp6_rapid_commit;
+        DHCPUseDomains dhcp6_use_domains;
+        bool dhcp6_use_domains_set;
+        uint32_t dhcp6_iaid;
+        bool dhcp6_iaid_set;
+        bool dhcp6_iaid_set_explicitly;
+        DUID dhcp6_duid;
         uint8_t dhcp6_pd_length;
-        uint32_t dhcp6_route_metric;
-        bool dhcp6_route_metric_set;
         char *dhcp6_mudurl;
         char **dhcp6_user_class;
         char **dhcp6_vendor_class;
@@ -181,6 +188,8 @@ struct Network {
 
         /* DHCP Server Support */
         bool dhcp_server;
+        bool dhcp_server_bind_to_interface;
+        struct in_addr dhcp_server_relay_target;
         NetworkDHCPServerEmitAddress dhcp_server_emit[_SD_DHCP_LEASE_SERVER_TYPE_MAX];
         bool dhcp_server_emit_router;
         bool dhcp_server_emit_timezone;
@@ -215,6 +224,7 @@ struct Network {
         bool dhcp6_pd_assign;
         bool dhcp6_pd_manage_temporary_address;
         int64_t dhcp6_pd_subnet_id;
+        uint32_t dhcp6_pd_route_metric;
         union in_addr_union dhcp6_pd_token;
 
         /* Bridge Support */
@@ -271,10 +281,12 @@ struct Network {
         bool ipv6_accept_ra_use_onlink_prefix;
         bool active_slave;
         bool primary_slave;
-        bool ipv6_accept_ra_route_table_set;
         DHCPUseDomains ipv6_accept_ra_use_domains;
         IPv6AcceptRAStartDHCP6Client ipv6_accept_ra_start_dhcp6_client;
         uint32_t ipv6_accept_ra_route_table;
+        bool ipv6_accept_ra_route_table_set;
+        uint32_t ipv6_accept_ra_route_metric;
+        bool ipv6_accept_ra_route_metric_set;
         Set *ndisc_deny_listed_router;
         Set *ndisc_allow_listed_router;
         Set *ndisc_deny_listed_prefix;
@@ -344,6 +356,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_timezone);
 CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_negative_trust_anchors);
 CONFIG_PARSER_PROTOTYPE(config_parse_ntp);
 CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online);
+CONFIG_PARSER_PROTOTYPE(config_parse_required_family_for_online);
 CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration);
 CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_link_local_address_gen_mode);
 CONFIG_PARSER_PROTOTYPE(config_parse_activation_policy);
index 470095c89741377e0651df86bdbbf376e8cad931..f3dbd98ed12b0b0b60f4ff155309c9813f2984df 100644 (file)
@@ -336,23 +336,24 @@ set_manager:
 }
 
 static void log_nexthop_debug(const NextHop *nexthop, uint32_t id, const char *str, const Link *link) {
+        _cleanup_free_ char *gw = NULL;
+
         assert(nexthop);
         assert(str);
 
         /* link may be NULL. */
 
-        if (DEBUG_LOGGING) {
-                _cleanup_free_ char *gw = NULL;
+        if (!DEBUG_LOGGING)
+                return;
 
-                (void) in_addr_to_string(nexthop->family, &nexthop->gw, &gw);
+        (void) in_addr_to_string(nexthop->family, &nexthop->gw, &gw);
 
-                if (nexthop->id == id)
-                        log_link_debug(link, "%s nexthop: id: %"PRIu32", gw: %s, blackhole: %s",
-                                       str, nexthop->id, strna(gw), yes_no(nexthop->blackhole));
-                else
-                        log_link_debug(link, "%s nexthop: id: %"PRIu32"→%"PRIu32", gw: %s, blackhole: %s",
-                                       str, nexthop->id, id, strna(gw), yes_no(nexthop->blackhole));
-        }
+        if (nexthop->id == id)
+                log_link_debug(link, "%s nexthop: id: %"PRIu32", gw: %s, blackhole: %s",
+                               str, nexthop->id, strna(gw), yes_no(nexthop->blackhole));
+        else
+                log_link_debug(link, "%s nexthop: id: %"PRIu32"→%"PRIu32", gw: %s, blackhole: %s",
+                               str, nexthop->id, id, strna(gw), yes_no(nexthop->blackhole));
 }
 
 static int nexthop_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
@@ -711,8 +712,10 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message,
         if (r < 0) {
                 log_link_warning_errno(link, r, "rtnl: could not get nexthop family, ignoring: %m");
                 return 0;
-        } else if (!IN_SET(tmp->family, AF_INET, AF_INET6))
-                return log_link_debug(link, "rtnl: received nexthop message with invalid family %d, ignoring.", tmp->family);
+        } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
+                log_link_debug(link, "rtnl: received nexthop message with invalid family %d, ignoring.", tmp->family);
+                return 0;
+        }
 
         r = sd_rtnl_message_nexthop_get_protocol(message, &tmp->protocol);
         if (r < 0) {
index 8d8c21c0d8d6634bca283f1d3d78c116f716273b..52c9afcc5e3eb003b0746e6dd0a120321c920f37 100644 (file)
@@ -382,6 +382,45 @@ int config_parse_prefix_assign(
         return 0;
 }
 
+int config_parse_prefix_metric(
+                const char *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_(prefix_free_or_set_invalidp) Prefix *p = NULL;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = prefix_new_static(network, filename, section_line, &p);
+        if (r < 0)
+                return log_oom();
+
+        r = safe_atou32(rvalue, &p->route_metric);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to parse %s=, ignoring assignment: %s",
+                           lvalue, rvalue);
+                return 0;
+        }
+
+        TAKE_PTR(p);
+
+        return 0;
+}
+
 int config_parse_route_prefix(
                 const char *unit,
                 const char *filename,
@@ -644,6 +683,9 @@ int radv_configure(Link *link) {
         if (!link_radv_enabled(link))
                 return 0;
 
+        if (link->radv)
+                return -EBUSY;
+
         r = sd_radv_new(&link->radv);
         if (r < 0)
                 return r;
index 73d2f245452b2ba619c1d3438dbba9198e5d0d2a..f6efd326979b3d440c2759e8bde2df6b936fa655 100644 (file)
@@ -33,6 +33,7 @@ typedef struct Prefix {
         sd_radv_prefix *radv_prefix;
 
         bool assign;
+        uint32_t route_metric;
 } Prefix;
 
 typedef struct RoutePrefix {
@@ -64,6 +65,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_prefix);
 CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags);
 CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime);
 CONFIG_PARSER_PROTOTYPE(config_parse_prefix_assign);
+CONFIG_PARSER_PROTOTYPE(config_parse_prefix_metric);
 CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns);
 CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains);
 CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix);
index a74541a6c95e8d56ce63cab98963b74054ef427c..8f3d84129a840f8908f89b8d5864b6923a9f8305 100644 (file)
@@ -605,35 +605,36 @@ static bool route_type_is_reject(const Route *route) {
 }
 
 static void log_route_debug(const Route *route, const char *str, const Link *link, const Manager *m) {
+        _cleanup_free_ char *dst = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL,
+                *table = NULL, *scope = NULL, *proto = NULL;
+
         assert(route);
         assert(str);
         assert(m);
 
         /* link may be NULL. */
 
-        if (DEBUG_LOGGING) {
-                _cleanup_free_ char *dst = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL,
-                        *table = NULL, *scope = NULL, *proto = NULL;
-
-                if (in_addr_is_set(route->family, &route->dst))
-                        (void) in_addr_prefix_to_string(route->family, &route->dst, route->dst_prefixlen, &dst);
-                if (in_addr_is_set(route->family, &route->src))
-                        (void) in_addr_to_string(route->family, &route->src, &src);
-                if (in_addr_is_set(route->gw_family, &route->gw))
-                        (void) in_addr_to_string(route->gw_family, &route->gw, &gw);
-                if (in_addr_is_set(route->family, &route->prefsrc))
-                        (void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc);
-                (void) route_scope_to_string_alloc(route->scope, &scope);
-                (void) manager_get_route_table_to_string(m, route->table, &table);
-                (void) route_protocol_full_to_string_alloc(route->protocol, &proto);
-
-                log_link_debug(link,
-                               "%s route: dst: %s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s, nexthop: %"PRIu32,
-                               str, strna(dst), strna(src), strna(gw), strna(prefsrc),
-                               strna(scope), strna(table), strna(proto),
-                               strna(route_type_to_string(route->type)),
-                               route->nexthop_id);
-        }
+        if (!DEBUG_LOGGING)
+                return;
+
+        if (in_addr_is_set(route->family, &route->dst))
+                (void) in_addr_prefix_to_string(route->family, &route->dst, route->dst_prefixlen, &dst);
+        if (in_addr_is_set(route->family, &route->src))
+                (void) in_addr_to_string(route->family, &route->src, &src);
+        if (in_addr_is_set(route->gw_family, &route->gw))
+                (void) in_addr_to_string(route->gw_family, &route->gw, &gw);
+        if (in_addr_is_set(route->family, &route->prefsrc))
+                (void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc);
+        (void) route_scope_to_string_alloc(route->scope, &scope);
+        (void) manager_get_route_table_to_string(m, route->table, &table);
+        (void) route_protocol_full_to_string_alloc(route->protocol, &proto);
+
+        log_link_debug(link,
+                       "%s route: dst: %s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s, nexthop: %"PRIu32", priority: %"PRIu32,
+                       str, strna(dst), strna(src), strna(gw), strna(prefsrc),
+                       strna(scope), strna(table), strna(proto),
+                       strna(route_type_to_string(route->type)),
+                       route->nexthop_id, route->priority);
 }
 
 static int route_set_netlink_message(const Route *route, sd_netlink_message *req, Link *link) {
@@ -645,7 +646,7 @@ static int route_set_netlink_message(const Route *route, sd_netlink_message *req
 
         /* link may be NULL */
 
-        if (in_addr_is_set(route->gw_family, &route->gw)) {
+        if (in_addr_is_set(route->gw_family, &route->gw) && route->nexthop_id == 0) {
                 if (route->gw_family == route->family) {
                         r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->gw_family, &route->gw);
                         if (r < 0)
@@ -717,10 +718,6 @@ static int route_set_netlink_message(const Route *route, sd_netlink_message *req
                 }
         }
 
-        r = sd_rtnl_message_route_set_type(req, route->type);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set route type: %m");
-
         if (!route_type_is_reject(route) && route->nexthop_id == 0) {
                 assert(link); /* Those routes must be attached to a specific link */
 
@@ -769,6 +766,7 @@ int route_remove(
                 link_netlink_message_handler_t callback) {
 
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        unsigned char type;
         int r;
 
         assert(link || manager);
@@ -786,6 +784,21 @@ int route_remove(
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not create RTM_DELROUTE message: %m");
 
+        if (route->family == AF_INET && route->nexthop_id > 0 && route->type == RTN_BLACKHOLE)
+                /* When IPv4 route has nexthop id and the nexthop type is blackhole, even though kernel
+                 * sends RTM_NEWROUTE netlink message with blackhole type, kernel's internal route type
+                 * fib_rt_info::type may not be blackhole. Thus, we cannot know the internal value.
+                 * Moreover, on route removal, the matching is done with the hidden value if we set
+                 * non-zero type in RTM_DELROUTE message. Note, sd_rtnl_message_new_route() sets
+                 * RTN_UNICAST by default. So, we need to clear the type here. */
+                type = RTN_UNSPEC;
+        else
+                type = route->type;
+
+        r = sd_rtnl_message_route_set_type(req, type);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not set route type: %m");
+
         r = route_set_netlink_message(route, req, link);
         if (r < 0)
                 return r;
@@ -842,6 +855,9 @@ static int manager_drop_routes_internal(Manager *manager, bool foreign, const Li
 
         routes = foreign ? manager->routes_foreign : manager->routes;
         SET_FOREACH(route, routes) {
+                if (route->removing)
+                        continue;
+
                 /* Do not touch routes managed by the kernel. */
                 if (route->protocol == RTPROT_KERNEL)
                         continue;
@@ -855,6 +871,8 @@ static int manager_drop_routes_internal(Manager *manager, bool foreign, const Li
                 k = route_remove(route, manager, NULL, NULL);
                 if (k < 0 && r >= 0)
                         r = k;
+
+                route->removing = true;
         }
 
         return r;
@@ -1083,8 +1101,8 @@ int route_configure(
                 Route **ret) {
 
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        int r, k = 0;
         Route *nr;
+        int r, k;
 
         assert(link);
         assert(link->manager);
@@ -1106,6 +1124,10 @@ int route_configure(
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not create RTM_NEWROUTE message: %m");
 
+        r = sd_rtnl_message_route_set_type(req, route->type);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not set route type: %m");
+
         r = route_set_netlink_message(route, req, link);
         if (r < 0)
                 return r;
@@ -1167,19 +1189,22 @@ int route_configure(
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
 
-        r = append_nexthops(route, req);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
-
-        if (ordered_set_isempty(route->multipath_routes)) {
+        if (route->nexthop_id != 0 ||
+            in_addr_is_set(route->gw_family, &route->gw) ||
+            ordered_set_isempty(route->multipath_routes)) {
                 k = route_add_and_setup_timer(link, route, NULL, &nr);
                 if (k < 0)
                         return k;
         } else {
                 MultipathRoute *m;
 
+                r = append_nexthops(route, req);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
+
                 assert(!ret);
 
+                k = 0;
                 ORDERED_SET_FOREACH(m, route->multipath_routes) {
                         r = route_add_and_setup_timer(link, route, m, NULL);
                         if (r < 0)
@@ -2745,8 +2770,17 @@ static int route_section_verify(Route *route, Network *network) {
                                                          route->section->filename, route->section->line);
         }
 
+        if ((route->gateway_from_dhcp_or_ra ||
+             in_addr_is_set(route->gw_family, &route->gw)) &&
+            !ordered_set_isempty(route->multipath_routes))
+                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
+                                         "%s: Gateway= cannot be specified with MultiPathRoute=. "
+                                         "Ignoring [Route] section from line %u.",
+                                         route->section->filename, route->section->line);
+
         if (route->nexthop_id > 0 &&
-            (in_addr_is_set(route->gw_family, &route->gw) ||
+            (route->gateway_from_dhcp_or_ra ||
+             in_addr_is_set(route->gw_family, &route->gw) ||
              !ordered_set_isempty(route->multipath_routes)))
                 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
                                          "%s: NextHopId= cannot be specified with Gateway= or MultiPathRoute=. "
index 331f1f9ea2e0f113bb2a6c41b6cd5bb406ee1ff7..ddb433817a9f3035002fd734e34fefc1cef76925 100644 (file)
@@ -52,6 +52,7 @@ typedef struct Route {
         bool protocol_set:1;
         bool pref_set:1;
         bool gateway_from_dhcp_or_ra:1;
+        bool removing:1;
 
         union in_addr_union gw;
         union in_addr_union dst;
index a7fddfd58fc9246371f5c0846e734feb36495585..14e079eed30a77892c0012bec9014f12ac4a4b58 100644 (file)
@@ -391,6 +391,8 @@ static int routing_policy_rule_consume_foreign(Manager *m, RoutingPolicyRule *ru
 }
 
 static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, int family, const char *str, const Link *link, const Manager *m) {
+        _cleanup_free_ char *from = NULL, *to = NULL, *table = NULL;
+
         assert(rule);
         assert(IN_SET(family, AF_INET, AF_INET6));
         assert(str);
@@ -398,18 +400,17 @@ static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, int fam
 
         /* link may be NULL. */
 
-        if (DEBUG_LOGGING) {
-                _cleanup_free_ char *from = NULL, *to = NULL, *table = NULL;
+        if (!DEBUG_LOGGING)
+                return;
 
-                (void) in_addr_prefix_to_string(family, &rule->from, rule->from_prefixlen, &from);
-                (void) in_addr_prefix_to_string(family, &rule->to, rule->to_prefixlen, &to);
-                (void) manager_get_route_table_to_string(m, rule->table, &table);
+        (void) in_addr_prefix_to_string(family, &rule->from, rule->from_prefixlen, &from);
+        (void) in_addr_prefix_to_string(family, &rule->to, rule->to_prefixlen, &to);
+        (void) manager_get_route_table_to_string(m, rule->table, &table);
 
-                log_link_debug(link,
-                               "%s routing policy rule: priority: %"PRIu32", %s -> %s, iif: %s, oif: %s, table: %s",
-                               str, rule->priority, strna(from), strna(to),
-                               strna(rule->iif), strna(rule->oif), strna(table));
-        }
+        log_link_debug(link,
+                       "%s routing policy rule: priority: %"PRIu32", %s -> %s, iif: %s, oif: %s, table: %s",
+                       str, rule->priority, strna(from), strna(to),
+                       strna(rule->iif), strna(rule->oif), strna(table));
 }
 
 static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule *rule, sd_netlink_message *m, Link *link) {
@@ -977,6 +978,8 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
         case RTM_NEWRULE:
                 if (rule)
                         log_routing_policy_rule_debug(tmp, tmp->family, "Received remembered", NULL, m);
+                else if (!m->manage_foreign_routes)
+                        log_routing_policy_rule_debug(tmp, tmp->family, "Ignoring received foreign", NULL, m);
                 else {
                         log_routing_policy_rule_debug(tmp, tmp->family, "Remembering foreign", NULL, m);
                         r = routing_policy_rule_consume_foreign(m, TAKE_PTR(tmp));
index 9c5c5047b34a23cfa03c6ff7189e69f81605dbc6..f8243cc3eef1b4b8d577824356c559f34100ebd7 100644 (file)
@@ -19,7 +19,7 @@
 #include "strv.h"
 #include "tmpfile-util.h"
 
-static int ordered_set_put_dns_server(OrderedSet *s, int ifindex, struct in_addr_full *dns) {
+static int ordered_set_put_dns_server(OrderedSet **s, int ifindex, struct in_addr_full *dns) {
         const char *p;
         int r;
 
@@ -40,7 +40,7 @@ static int ordered_set_put_dns_server(OrderedSet *s, int ifindex, struct in_addr
         return r;
 }
 
-static int ordered_set_put_dns_servers(OrderedSet *s, int ifindex, struct in_addr_full **dns, unsigned n) {
+static int ordered_set_put_dns_servers(OrderedSet **s, int ifindex, struct in_addr_full **dns, unsigned n) {
         int r, c = 0;
 
         assert(s);
@@ -57,8 +57,8 @@ static int ordered_set_put_dns_servers(OrderedSet *s, int ifindex, struct in_add
         return c;
 }
 
-static int ordered_set_put_in4_addr(OrderedSet *s, const struct in_addr *address) {
-        char *p;
+static int ordered_set_put_in4_addr(OrderedSet **s, const struct in_addr *address) {
+        _cleanup_free_ char *p = NULL;
         int r;
 
         assert(s);
@@ -68,7 +68,11 @@ static int ordered_set_put_in4_addr(OrderedSet *s, const struct in_addr *address
         if (r < 0)
                 return r;
 
-        r = ordered_set_consume(s, p);
+        r = ordered_set_ensure_allocated(s, &string_hash_ops_free);
+        if (r < 0)
+                return r;
+
+        r = ordered_set_consume(*s, TAKE_PTR(p));
         if (r == -EEXIST)
                 return 0;
 
@@ -76,7 +80,7 @@ static int ordered_set_put_in4_addr(OrderedSet *s, const struct in_addr *address
 }
 
 static int ordered_set_put_in4_addrv(
-                OrderedSet *s,
+                OrderedSet **s,
                 const struct in_addr *addresses,
                 size_t n,
                 bool (*predicate)(const struct in_addr *addr)) {
@@ -100,11 +104,12 @@ static int ordered_set_put_in4_addrv(
 }
 
 int manager_save(Manager *m) {
-        _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *search_domains = NULL, *route_domains = NULL;
-        const char *operstate_str, *carrier_state_str, *address_state_str;
+        _cleanup_ordered_set_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *search_domains = NULL, *route_domains = NULL;
+        const char *operstate_str, *carrier_state_str, *address_state_str, *ipv4_address_state_str, *ipv6_address_state_str;
         LinkOperationalState operstate = LINK_OPERSTATE_OFF;
         LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF;
-        LinkAddressState address_state = LINK_ADDRESS_STATE_OFF;
+        LinkAddressState ipv4_address_state = LINK_ADDRESS_STATE_OFF, ipv6_address_state = LINK_ADDRESS_STATE_OFF,
+                address_state = LINK_ADDRESS_STATE_OFF;
         _cleanup_(unlink_and_freep) char *temp_path = NULL;
         _cleanup_strv_free_ char **p = NULL;
         _cleanup_fclose_ FILE *f = NULL;
@@ -114,62 +119,38 @@ int manager_save(Manager *m) {
         assert(m);
         assert(m->state_file);
 
-        /* We add all NTP and DNS server to a set, to filter out duplicates */
-        dns = ordered_set_new(&string_hash_ops);
-        if (!dns)
-                return -ENOMEM;
-
-        ntp = ordered_set_new(&string_hash_ops);
-        if (!ntp)
-                return -ENOMEM;
-
-        sip = ordered_set_new(&string_hash_ops);
-        if (!sip)
-                return -ENOMEM;
-
-        search_domains = ordered_set_new(&dns_name_hash_ops);
-        if (!search_domains)
-                return -ENOMEM;
-
-        route_domains = ordered_set_new(&dns_name_hash_ops);
-        if (!route_domains)
-                return -ENOMEM;
-
         HASHMAP_FOREACH(link, m->links) {
                 const struct in_addr *addresses;
 
                 if (link->flags & IFF_LOOPBACK)
                         continue;
 
-                if (link->operstate > operstate)
-                        operstate = link->operstate;
-
-                if (link->carrier_state > carrier_state)
-                        carrier_state = link->carrier_state;
-
-                if (link->address_state > address_state)
-                        address_state = link->address_state;
+                operstate = MAX(operstate, link->operstate);
+                carrier_state = MAX(carrier_state, link->carrier_state);
+                address_state = MAX(address_state, link->address_state);
+                ipv4_address_state = MAX(ipv4_address_state, link->ipv4_address_state);
+                ipv6_address_state = MAX(ipv6_address_state, link->ipv6_address_state);
 
                 if (!link->network)
                         continue;
 
                 /* First add the static configured entries */
                 if (link->n_dns != UINT_MAX)
-                        r = ordered_set_put_dns_servers(dns, link->ifindex, link->dns, link->n_dns);
+                        r = ordered_set_put_dns_servers(&dns, link->ifindex, link->dns, link->n_dns);
                 else
-                        r = ordered_set_put_dns_servers(dns, link->ifindex, link->network->dns, link->network->n_dns);
+                        r = ordered_set_put_dns_servers(&dns, link->ifindex, link->network->dns, link->network->n_dns);
                 if (r < 0)
                         return r;
 
-                r = ordered_set_put_strdupv(ntp, link->ntp ?: link->network->ntp);
+                r = ordered_set_put_strdupv(&ntp, link->ntp ?: link->network->ntp);
                 if (r < 0)
                         return r;
 
-                r = ordered_set_put_string_set(search_domains, link->search_domains ?: link->network->search_domains);
+                r = ordered_set_put_string_set(&search_domains, link->search_domains ?: link->network->search_domains);
                 if (r < 0)
                         return r;
 
-                r = ordered_set_put_string_set(route_domains, link->route_domains ?: link->network->route_domains);
+                r = ordered_set_put_string_set(&route_domains, link->route_domains ?: link->network->route_domains);
                 if (r < 0)
                         return r;
 
@@ -180,7 +161,7 @@ int manager_save(Manager *m) {
                 if (link->network->dhcp_use_dns) {
                         r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
                         if (r > 0) {
-                                r = ordered_set_put_in4_addrv(dns, addresses, r, in4_addr_is_non_local);
+                                r = ordered_set_put_in4_addrv(&dns, addresses, r, in4_addr_is_non_local);
                                 if (r < 0)
                                         return r;
                         } else if (r < 0 && r != -ENODATA)
@@ -190,7 +171,7 @@ int manager_save(Manager *m) {
                 if (link->network->dhcp_use_ntp) {
                         r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
                         if (r > 0) {
-                                r = ordered_set_put_in4_addrv(ntp, addresses, r, in4_addr_is_non_local);
+                                r = ordered_set_put_in4_addrv(&ntp, addresses, r, in4_addr_is_non_local);
                                 if (r < 0)
                                         return r;
                         } else if (r < 0 && r != -ENODATA)
@@ -200,7 +181,7 @@ int manager_save(Manager *m) {
                 if (link->network->dhcp_use_sip) {
                         r = sd_dhcp_lease_get_sip(link->dhcp_lease, &addresses);
                         if (r > 0) {
-                                r = ordered_set_put_in4_addrv(sip, addresses, r, in4_addr_is_non_local);
+                                r = ordered_set_put_in4_addrv(&sip, addresses, r, in4_addr_is_non_local);
                                 if (r < 0)
                                         return r;
                         } else if (r < 0 && r != -ENODATA)
@@ -208,10 +189,11 @@ int manager_save(Manager *m) {
                 }
 
                 if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
+                        OrderedSet **target_domains;
                         const char *domainname;
                         char **domains = NULL;
 
-                        OrderedSet *target_domains = (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) ? search_domains : route_domains;
+                        target_domains = (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) ? &search_domains : &route_domains;
                         r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
                         if (r >= 0) {
                                 r = ordered_set_put_strdup(target_domains, domainname);
@@ -242,6 +224,12 @@ int manager_save(Manager *m) {
         address_state_str = link_address_state_to_string(address_state);
         assert(address_state_str);
 
+        ipv4_address_state_str = link_address_state_to_string(ipv4_address_state);
+        assert(ipv4_address_state_str);
+
+        ipv6_address_state_str = link_address_state_to_string(ipv6_address_state);
+        assert(ipv6_address_state_str);
+
         r = fopen_temporary(m->state_file, &f, &temp_path);
         if (r < 0)
                 return r;
@@ -252,8 +240,10 @@ int manager_save(Manager *m) {
                 "# This is private data. Do not parse.\n"
                 "OPER_STATE=%s\n"
                 "CARRIER_STATE=%s\n"
-                "ADDRESS_STATE=%s\n",
-                operstate_str, carrier_state_str, address_state_str);
+                "ADDRESS_STATE=%s\n"
+                "IPV4_ADDRESS_STATE=%s\n"
+                "IPV6_ADDRESS_STATE=%s\n",
+                operstate_str, carrier_state_str, address_state_str, ipv4_address_state_str, ipv6_address_state_str);
 
         ordered_set_print(f, "DNS=", dns);
         ordered_set_print(f, "NTP=", ntp);
@@ -289,6 +279,18 @@ int manager_save(Manager *m) {
                         log_oom();
         }
 
+        if (m->ipv4_address_state != ipv4_address_state) {
+                m->ipv4_address_state = ipv4_address_state;
+                if (strv_extend(&p, "IPv4AddressState") < 0)
+                        log_oom();
+        }
+
+        if (m->ipv6_address_state != ipv6_address_state) {
+                m->ipv6_address_state = ipv6_address_state;
+                if (strv_extend(&p, "IPv6AddressState") < 0)
+                        log_oom();
+        }
+
         if (p) {
                 r = manager_send_changed_strv(m, p);
                 if (r < 0)
@@ -392,7 +394,7 @@ static void serialize_addresses(
 }
 
 int link_save(Link *link) {
-        const char *admin_state, *oper_state, *carrier_state, *address_state;
+        const char *admin_state, *oper_state, *carrier_state, *address_state, *ipv4_address_state, *ipv6_address_state;
         _cleanup_(unlink_and_freep) char *temp_path = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         int r;
@@ -419,6 +421,12 @@ int link_save(Link *link) {
         address_state = link_address_state_to_string(link->address_state);
         assert(address_state);
 
+        ipv4_address_state = link_address_state_to_string(link->ipv4_address_state);
+        assert(ipv4_address_state);
+
+        ipv6_address_state = link_address_state_to_string(link->ipv6_address_state);
+        assert(ipv6_address_state);
+
         r = fopen_temporary(link->state_file, &f, &temp_path);
         if (r < 0)
                 return r;
@@ -430,8 +438,10 @@ int link_save(Link *link) {
                 "ADMIN_STATE=%s\n"
                 "OPER_STATE=%s\n"
                 "CARRIER_STATE=%s\n"
-                "ADDRESS_STATE=%s\n",
-                admin_state, oper_state, carrier_state, address_state);
+                "ADDRESS_STATE=%s\n"
+                "IPV4_ADDRESS_STATE=%s\n"
+                "IPV6_ADDRESS_STATE=%s\n",
+                admin_state, oper_state, carrier_state, address_state, ipv4_address_state, ipv6_address_state);
 
         if (link->network) {
                 char **dhcp6_domains = NULL, **dhcp_domains = NULL;
@@ -447,6 +457,9 @@ int link_save(Link *link) {
                         st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? ":" : "",
                         st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? strempty(link_operstate_to_string(st.max)) : "");
 
+                fprintf(f, "REQUIRED_FAMILY_FOR_ONLINE=%s\n",
+                        link_required_address_family_to_string(link->network->required_family_for_online));
+
                 fprintf(f, "ACTIVATION_POLICY=%s\n",
                         activation_policy_to_string(link->network->activation_policy));
 
@@ -504,14 +517,12 @@ int link_save(Link *link) {
 
                 /************************************************************/
 
-                if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
-                        if (link->dhcp_lease) {
-                                (void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname);
-                                (void) sd_dhcp_lease_get_search_domains(link->dhcp_lease, &dhcp_domains);
-                        }
-                        if (link->dhcp6_lease)
-                                (void) sd_dhcp6_lease_get_domains(link->dhcp6_lease, &dhcp6_domains);
+                if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO && link->dhcp_lease) {
+                        (void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname);
+                        (void) sd_dhcp_lease_get_search_domains(link->dhcp_lease, &dhcp_domains);
                 }
+                if (link->network->dhcp6_use_domains != DHCP_USE_DOMAINS_NO && link->dhcp6_lease)
+                        (void) sd_dhcp6_lease_get_domains(link->dhcp6_lease, &dhcp6_domains);
 
                 fputs("DOMAINS=", f);
                 space = false;
index a9dd6d45eb606ca01e10f9ae686d4abe68295c03..43ddf124d4457236a33bee8365a339823f0b8467 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "condition.h"
 #include "conf-parser.h"
+#include "networkd-link.h"
 #include "networkd-util.h"
 #include "parse-util.h"
 #include "string-table.h"
@@ -223,3 +224,17 @@ unsigned hashmap_find_free_section_line(Hashmap *hashmap) {
 
         return n + 1;
 }
+
+int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg) {
+        const char *err_msg = NULL;
+
+        /* link may be NULL. */
+
+        (void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
+        return log_link_full_errno(link, level, err,
+                                   "%s: %s%s%s%m",
+                                   msg,
+                                   strempty(err_msg),
+                                   err_msg && !endswith(err_msg, ".") ? "." : "",
+                                   err_msg ? " " : "");
+}
index 01675e8b5c5e13b6890b5bba67b31263caccc640..62f38bcdc2c0b51d3409ce16ac7aee884edc7ac2 100644 (file)
@@ -8,17 +8,10 @@
 #include "hashmap.h"
 #include "log.h"
 #include "macro.h"
+#include "network-util.h"
 #include "string-util.h"
 
-typedef enum AddressFamily {
-        /* This is a bitmask, though it usually doesn't feel that way! */
-        ADDRESS_FAMILY_NO             = 0,
-        ADDRESS_FAMILY_IPV4           = 1 << 0,
-        ADDRESS_FAMILY_IPV6           = 1 << 1,
-        ADDRESS_FAMILY_YES            = ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6,
-        _ADDRESS_FAMILY_MAX,
-        _ADDRESS_FAMILY_INVALID = -EINVAL,
-} AddressFamily;
+typedef struct Link Link;
 
 typedef struct NetworkConfigSection {
         unsigned line;
@@ -82,9 +75,15 @@ static inline bool section_is_invalid(NetworkConfigSection *section) {
         DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func);                  \
         DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid);
 
-static inline int log_message_warning_errno(sd_netlink_message *m, int err, const char *msg) {
-        const char *err_msg = NULL;
-
-        (void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
-        return log_warning_errno(err, "%s: %s%s%m", msg, strempty(err_msg), err_msg ? " " : "");
-}
+int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg);
+#define log_link_message_error_errno(link, m, err, msg)   log_link_message_full_errno(link, m, LOG_ERR, err, msg)
+#define log_link_message_warning_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_WARNING, err, msg)
+#define log_link_message_notice_errno(link, m, err, msg)  log_link_message_full_errno(link, m, LOG_NOTICE, err, msg)
+#define log_link_message_info_errno(link, m, err, msg)    log_link_message_full_errno(link, m, LOG_INFO, err, msg)
+#define log_link_message_debug_errno(link, m, err, msg)   log_link_message_full_errno(link, m, LOG_DEBUG, err, msg)
+#define log_message_full_errno(m, level, err, msg)        log_link_message_full_errno(NULL, m, level, err, msg)
+#define log_message_error_errno(m, err, msg)              log_message_full_errno(m, LOG_ERR, err, msg)
+#define log_message_warning_errno(m, err, msg)            log_message_full_errno(m, LOG_WARNING, err, msg)
+#define log_message_notice_errno(m, err, msg)             log_message_full_errno(m, LOG_NOTICE, err, msg)
+#define log_message_info_errno(m, err, msg)               log_message_full_errno(m, LOG_INFO, err, msg)
+#define log_message_debug_errno(m, err, msg)              log_message_full_errno(m, LOG_DEBUG, err, msg)
index 4850ba61f2fa1de18be759d48e491efd2d3a04f8..38dc9f1f79d9396386f9862358ac6c1d51e72ae4 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Entries in this file show the compile time defaults. Local configuration
 # should be created by either modifying this file, or by creating "drop-ins" in
-# the system.conf.d/ subdirectory. The latter is generally recommended.
+# the networkd.conf.d/ subdirectory. The latter is generally recommended.
 # Defaults can be restored by simply deleting this file and all drop-ins.
 #
 # See networkd.conf(5) for details.
 [Network]
 #SpeedMeter=no
 #SpeedMeterIntervalSec=10sec
+#ManageForeignRoutingPolicyRules=yes
 #ManageForeignRoutes=yes
+#RouteTable=
 
-[DHCP]
+[DHCPv4]
+#DUIDType=vendor
+#DUIDRawData=
+
+[DHCPv6]
 #DUIDType=vendor
 #DUIDRawData=
index f2d556f099e622a5cec1d61392846cf555d71cb1..5a33d563c240537eac7acf7ee760320fe7077a77 100644 (file)
@@ -97,7 +97,8 @@ int link_update_rtnl(Link *l, sd_netlink_message *m) {
 }
 
 int link_update_monitor(Link *l) {
-        _cleanup_free_ char *operstate = NULL, *required_operstate = NULL, *state = NULL;
+        _cleanup_free_ char *operstate = NULL, *required_operstate = NULL, *required_family = NULL,
+                *ipv4_address_state = NULL, *ipv6_address_state = NULL, *state = NULL;
         int r, ret = 0;
 
         assert(l);
@@ -135,6 +136,47 @@ int link_update_monitor(Link *l) {
                         l->operational_state = s;
         }
 
+        r = sd_network_link_get_required_family_for_online(l->ifindex, &required_family);
+        if (r < 0)
+                ret = log_link_debug_errno(l, r, "Failed to get required address family, ignoring: %m");
+        else if (isempty(required_family))
+                l->required_family = ADDRESS_FAMILY_NO;
+        else {
+                AddressFamily f;
+
+                f = link_required_address_family_from_string(required_family);
+                if (f < 0)
+                        ret = log_link_debug_errno(l, f, "Failed to parse required address family, ignoring: %m");
+                else
+                        l->required_family = f;
+        }
+
+        r = sd_network_link_get_ipv4_address_state(l->ifindex, &ipv4_address_state);
+        if (r < 0)
+                ret = log_link_debug_errno(l, r, "Failed to get IPv4 address state, ignoring: %m");
+        else {
+                LinkAddressState s;
+
+                s = link_address_state_from_string(ipv4_address_state);
+                if (s < 0)
+                        ret = log_link_debug_errno(l, s, "Failed to parse IPv4 address state, ignoring: %m");
+                else
+                        l->ipv4_address_state = s;
+        }
+
+        r = sd_network_link_get_ipv6_address_state(l->ifindex, &ipv6_address_state);
+        if (r < 0)
+                ret = log_link_debug_errno(l, r, "Failed to get IPv6 address state, ignoring: %m");
+        else {
+                LinkAddressState s;
+
+                s = link_address_state_from_string(ipv6_address_state);
+                if (s < 0)
+                        ret = log_link_debug_errno(l, s, "Failed to parse IPv6 address state, ignoring: %m");
+                else
+                        l->ipv6_address_state = s;
+        }
+
         r = sd_network_link_get_setup_state(l->ifindex, &state);
         if (r < 0)
                 ret = log_link_debug_errno(l, r, "Failed to get setup state, ignoring: %m");
index 3aa835729383cd27b5b54c6d23d13d9fd23b0412..3072a91e565b21beb9f0ff5a6fb2f944830660db 100644 (file)
@@ -19,6 +19,9 @@ struct Link {
         bool required_for_online;
         LinkOperationalStateRange required_operstate;
         LinkOperationalState operational_state;
+        AddressFamily required_family;
+        LinkAddressState ipv4_address_state;
+        LinkAddressState ipv6_address_state;
         char *state;
 };
 
index 1438b27445c898ea3d8550dcfefc326322b2912b..e1df0345c0de3a5ed773a2659ccf493195b00063 100644 (file)
@@ -32,6 +32,13 @@ static bool manager_ignore_link(Manager *m, Link *link) {
 }
 
 static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange s) {
+        AddressFamily required_family;
+        bool needs_ipv4;
+        bool needs_ipv6;
+
+        assert(m);
+        assert(l);
+
         /* This returns the following:
          * -EAGAIN: not processed by udev or networkd
          *       0: operstate is not enough
@@ -60,6 +67,34 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange
                 return 0;
         }
 
+        required_family = m->required_family > 0 ? m->required_family : l->required_family;
+        needs_ipv4 = required_family & ADDRESS_FAMILY_IPV4;
+        needs_ipv6 = required_family & ADDRESS_FAMILY_IPV6;
+
+        if (s.min >= LINK_OPERSTATE_DEGRADED) {
+                if (needs_ipv4 && l->ipv4_address_state < LINK_ADDRESS_STATE_DEGRADED) {
+                        log_link_debug(l, "No routable or link-local IPv4 address is configured.");
+                        return 0;
+                }
+
+                if (needs_ipv6 && l->ipv6_address_state < LINK_ADDRESS_STATE_DEGRADED) {
+                        log_link_debug(l, "No routable or link-local IPv6 address is configured.");
+                        return 0;
+                }
+        }
+
+        if (s.min >= LINK_OPERSTATE_ROUTABLE) {
+                if (needs_ipv4 && l->ipv4_address_state < LINK_ADDRESS_STATE_ROUTABLE) {
+                        log_link_debug(l, "No routable IPv4 address is configured.");
+                        return 0;
+                }
+
+                if (needs_ipv6 && l->ipv6_address_state < LINK_ADDRESS_STATE_ROUTABLE) {
+                        log_link_debug(l, "No routable IPv6 address is configured.");
+                        return 0;
+                }
+        }
+
         return 1;
 }
 
@@ -298,6 +333,7 @@ static int manager_network_monitor_listen(Manager *m) {
 
 int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
                 LinkOperationalStateRange required_operstate,
+                AddressFamily required_family,
                 bool any, usec_t timeout) {
         _cleanup_(manager_freep) Manager *m = NULL;
         int r;
@@ -312,6 +348,7 @@ int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
                 .interfaces = interfaces,
                 .ignore = ignore,
                 .required_operstate = required_operstate,
+                .required_family = required_family,
                 .any = any,
         };
 
index 9892a43dc989cb999268ed7682a841f291391084..f2e091638c42f85b42d9b725c01cacc8a606a475 100644 (file)
@@ -21,6 +21,7 @@ struct Manager {
         char **ignore;
 
         LinkOperationalStateRange required_operstate;
+        AddressFamily required_family;
         bool any;
 
         sd_netlink *rtnl;
@@ -35,6 +36,7 @@ struct Manager {
 Manager* manager_free(Manager *m);
 int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
                 LinkOperationalStateRange required_operstate,
+                AddressFamily required_family,
                 bool any, usec_t timeout);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
index ca0116e7f307278908d062f944b8bfb7ae106e9f..c65b885d2c19876c1b9903d07bf9dc331324205c 100644 (file)
@@ -19,6 +19,7 @@ static usec_t arg_timeout = 120 * USEC_PER_SEC;
 static Hashmap *arg_interfaces = NULL;
 static char **arg_ignore = NULL;
 static LinkOperationalStateRange arg_required_operstate = { _LINK_OPERSTATE_INVALID, _LINK_OPERSTATE_INVALID };
+static AddressFamily arg_required_family = ADDRESS_FAMILY_NO;
 static bool arg_any = false;
 
 STATIC_DESTRUCTOR_REGISTER(arg_interfaces, hashmap_free_free_freep);
@@ -42,6 +43,8 @@ static int help(void) {
                "     --ignore=INTERFACE     Don't take these interfaces into account\n"
                "  -o --operational-state=MIN_OPERSTATE[:MAX_OPERSTATE]\n"
                "                            Required operational state\n"
+               "  -4 --ipv4                 Requires at least one IPv4 address\n"
+               "  -6 --ipv6                 Requires at least one IPv6 address\n"
                "     --any                  Wait until at least one of the interfaces is online\n"
                "     --timeout=SECS         Maximum time to wait for network connectivity\n"
                "\nSee the %s for details.\n",
@@ -53,7 +56,7 @@ static int help(void) {
 
 static int parse_interface_with_operstate_range(const char *str) {
         _cleanup_free_ char *ifname = NULL;
-        _cleanup_free_ LinkOperationalStateRange *range;
+        _cleanup_free_ LinkOperationalStateRange *range = NULL;
         const char *p;
         int r;
 
@@ -111,6 +114,8 @@ static int parse_argv(int argc, char *argv[]) {
                 { "interface",         required_argument, NULL, 'i'         },
                 { "ignore",            required_argument, NULL, ARG_IGNORE  },
                 { "operational-state", required_argument, NULL, 'o'         },
+                { "ipv4",              no_argument,       NULL, '4'         },
+                { "ipv6",              no_argument,       NULL, '6'         },
                 { "any",               no_argument,       NULL, ARG_ANY     },
                 { "timeout",           required_argument, NULL, ARG_TIMEOUT },
                 {}
@@ -121,7 +126,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "hi:qo:", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "hi:qo:46", options, NULL)) >= 0)
 
                 switch (c) {
 
@@ -159,6 +164,15 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
                 }
+
+                case '4':
+                        arg_required_family |= ADDRESS_FAMILY_IPV4;
+                        break;
+
+                case '6':
+                        arg_required_family |= ADDRESS_FAMILY_IPV6;
+                        break;
+
                 case ARG_ANY:
                         arg_any = true;
                         break;
@@ -197,7 +211,7 @@ static int run(int argc, char *argv[]) {
 
         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
 
-        r = manager_new(&m, arg_interfaces, arg_ignore, arg_required_operstate, arg_any, arg_timeout);
+        r = manager_new(&m, arg_interfaces, arg_ignore, arg_required_operstate, arg_required_family, arg_any, arg_timeout);
         if (r < 0)
                 return log_error_errno(r, "Could not create manager: %m");
 
index 40cbc296bd516d05f47743d9eb261eabced4da2d..99f54ceaaab609d8c3b1bd0f24c88c4d91af2e96 100644 (file)
@@ -202,8 +202,15 @@ static int run(int argc, char* argv[]) {
         if (r <= 0)
                 return r;
 
-        if (arg_booted)
-                return sd_booted() <= 0;
+        if (arg_booted) {
+                r = sd_booted();
+                if (r < 0)
+                        log_debug_errno(r, "Failed to determine whether we are booted with systemd, assuming we aren't: %m");
+                else
+                        log_debug("The system %s booted with systemd.", r ? "was" : "was not");
+
+                return r <= 0;
+        }
 
         if (arg_ready)
                 our_env[i++] = (char*) "READY=1";
@@ -278,4 +285,4 @@ static int run(int argc, char* argv[]) {
         return 0;
 }
 
-DEFINE_MAIN_FUNCTION(run);
+DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE (run);
index d0c708a8a08c9524c7b6fefd29d244560d95d298..a5e6dbead5a92bbf408db62e7cb258823aaf886b 100644 (file)
@@ -149,7 +149,7 @@ typedef struct OciHook {
 } OciHook;
 
 typedef struct Settings {
-        /* [Run] */
+        /* [Exec] */
         StartMode start_mode;
         bool ephemeral;
         char **parameters;
@@ -180,7 +180,7 @@ typedef struct Settings {
         bool link_journal_try;
         TimezoneMode timezone;
 
-        /* [Image] */
+        /* [Files] */
         int read_only;
         VolatileMode volatile_mode;
         CustomMount *custom_mounts;
index a4ac8ed2bb752e6b478b8281d82aa6cd6e56191e..53b9fa84a7d8cdc6035e069fcb1244d1857aed07 100644 (file)
@@ -35,6 +35,7 @@
 #include "cgroup-util.h"
 #include "copy.h"
 #include "cpu-set-util.h"
+#include "creds-util.h"
 #include "dev-setup.h"
 #include "discover-image.h"
 #include "dissect-image.h"
@@ -1592,9 +1593,9 @@ static int parse_argv(int argc, char *argv[]) {
                         else {
                                 const char *e;
 
-                                e = getenv("CREDENTIALS_DIRECTORY");
-                                if (!e)
-                                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential not available (no credentials passed at all): %s", word);
+                                r = get_credentials_dir(&e);
+                                if (r < 0)
+                                        return log_error_errno(r, "Credential not available (no credentials passed at all): %s", word);
 
                                 j = path_join(e, p);
                                 if (!j)
@@ -2966,19 +2967,17 @@ static int determine_names(void) {
         if (!arg_machine) {
                 if (arg_directory && path_equal(arg_directory, "/"))
                         arg_machine = gethostname_malloc();
-                else {
-                        if (arg_image) {
-                                char *e;
+                else if (arg_image) {
+                        char *e;
 
-                                arg_machine = strdup(basename(arg_image));
+                        arg_machine = strdup(basename(arg_image));
 
-                                /* Truncate suffix if there is one */
-                                e = endswith(arg_machine, ".raw");
-                                if (e)
-                                        *e = 0;
-                        } else
-                                arg_machine = strdup(basename(arg_directory));
-                }
+                        /* Truncate suffix if there is one */
+                        e = endswith(arg_machine, ".raw");
+                        if (e)
+                                *e = 0;
+                } else
+                        arg_machine = strdup(basename(arg_directory));
                 if (!arg_machine)
                         return log_oom();
 
@@ -2986,20 +2985,11 @@ static int determine_names(void) {
                 if (!hostname_is_valid(arg_machine, 0))
                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine machine name automatically, please use -M.");
 
-                if (arg_ephemeral) {
-                        char *b;
-
-                        /* Add a random suffix when this is an
-                         * ephemeral machine, so that we can run many
-                         * instances at once without manually having
-                         * to specify -M each time. */
-
-                        if (asprintf(&b, "%s-%016" PRIx64, arg_machine, random_u64()) < 0)
+                /* Add a random suffix when this is an ephemeral machine, so that we can run many
+                 * instances at once without manually having to specify -M each time. */
+                if (arg_ephemeral)
+                        if (strextendf(&arg_machine, "-%016" PRIx64, random_u64()) < 0)
                                 return log_oom();
-
-                        free(arg_machine);
-                        arg_machine = b;
-                }
         }
 
         return 0;
@@ -3581,9 +3571,13 @@ static int outer_child(
                  * makes sure ESP partitions and userns are compatible. */
 
                 r = dissected_image_mount_and_warn(
-                                dissected_image, directory, arg_uid_shift,
-                                DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_DISCARD_ON_LOOP|
-                                (arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK)|
+                                dissected_image,
+                                directory,
+                                arg_uid_shift,
+                                DISSECT_IMAGE_MOUNT_ROOT_ONLY|
+                                DISSECT_IMAGE_DISCARD_ON_LOOP|
+                                DISSECT_IMAGE_USR_NO_ROOT|
+                                (arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS)|
                                 (arg_start_mode == START_BOOT ? DISSECT_IMAGE_VALIDATE_OS : 0));
                 if (r < 0)
                         return r;
@@ -3669,8 +3663,14 @@ static int outer_child(
 
         if (dissected_image) {
                 /* Now we know the uid shift, let's now mount everything else that might be in the image. */
-                r = dissected_image_mount(dissected_image, directory, arg_uid_shift,
-                                          DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY|DISSECT_IMAGE_DISCARD_ON_LOOP|(arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK));
+                r = dissected_image_mount(
+                                dissected_image,
+                                directory,
+                                arg_uid_shift,
+                                DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY|
+                                DISSECT_IMAGE_DISCARD_ON_LOOP|
+                                DISSECT_IMAGE_USR_NO_ROOT|
+                                (arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS));
                 if (r == -EUCLEAN)
                         return log_error_errno(r, "File system check for image failed: %m");
                 if (r < 0)
@@ -5378,7 +5378,11 @@ static int run(int argc, char *argv[]) {
                 }
 
         } else {
-                DissectImageFlags dissect_image_flags = DISSECT_IMAGE_REQUIRE_ROOT | DISSECT_IMAGE_RELAX_VAR_CHECK;
+                DissectImageFlags dissect_image_flags =
+                        DISSECT_IMAGE_GENERIC_ROOT |
+                        DISSECT_IMAGE_REQUIRE_ROOT |
+                        DISSECT_IMAGE_RELAX_VAR_CHECK |
+                        DISSECT_IMAGE_USR_NO_ROOT;
                 assert(arg_image);
                 assert(!arg_template);
 
@@ -5468,6 +5472,8 @@ static int run(int argc, char *argv[]) {
                                 arg_image,
                                 &arg_verity_settings,
                                 NULL,
+                                loop->uevent_seqnum_not_before,
+                                loop->timestamp_not_before,
                                 dissect_image_flags,
                                 &dissected_image);
                 if (r == -ENOPKG) {
index 6e37966da08c5bcedc67868b43a8c789bda39ed0..3536c5fc8370c5ed403f120d6f5e3a8fc16daf35 100644 (file)
@@ -54,8 +54,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
         assert(h_errnop);
 
         if (is_localhost(name)) {
-                /* We respond to 'localhost', so that /etc/hosts
-                 * is optional */
+                /* We respond to 'localhost', so that /etc/hosts is optional */
 
                 canonical = "localhost";
                 local_address_ipv4 = htobe32(INADDR_LOOPBACK);
@@ -68,6 +67,14 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
 
                 canonical = "_gateway";
 
+        } else if (is_outbound_hostname(name)) {
+
+                n_addresses = local_outbounds(NULL, 0, AF_UNSPEC, &addresses);
+                if (n_addresses <= 0)
+                        goto not_found;
+
+                canonical = "_outbound";
+
         } else {
                 hn = gethostname_malloc();
                 if (!hn) {
@@ -343,6 +350,14 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
 
                 canonical = "_gateway";
 
+        } else if (is_outbound_hostname(name)) {
+
+                n_addresses = local_outbounds(NULL, 0, af, &addresses);
+                if (n_addresses <= 0)
+                        goto not_found;
+
+                canonical = "_outbound";
+
         } else {
                 hn = gethostname_malloc();
                 if (!hn) {
index dfc0977c849c3692479bdc1428fa0bd20da716dd..e2a29475a225536ffb0c49ce71269393de1dbe29 100644 (file)
@@ -207,14 +207,10 @@ enum nss_status _nss_resolve_gethostbyname4_r(
                 int *errnop, int *h_errnop,
                 int32_t *ttlp) {
 
-        _cleanup_(resolve_hostname_reply_destroy) ResolveHostnameReply p = {};
-        _cleanup_(json_variant_unrefp) JsonVariant *cparams = NULL;
-        struct gaih_addrtuple *r_tuple = NULL, *r_tuple_first = NULL;
         _cleanup_(varlink_unrefp) Varlink *link = NULL;
-        const char *canonical = NULL, *error_id = NULL;
-        JsonVariant *entry, *rparams;
-        size_t l, ms, idx, c = 0;
-        char *r_name;
+        _cleanup_(json_variant_unrefp) JsonVariant *cparams = NULL;
+        _cleanup_(resolve_hostname_reply_destroy) ResolveHostnameReply p = {};
+        JsonVariant *rparams, *entry;
         int r;
 
         PROTECT_ERRNO;
@@ -241,6 +237,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
          * DNSSEC errors and suchlike. (We don't use UNAVAIL in this case so that the nsswitch.conf
          * configuration can distinguish such executed but negative replies from complete failure to
          * talk to resolved). */
+        const char *error_id;
         r = varlink_call(link, "io.systemd.Resolve.ResolveHostname", cparams, &rparams, &error_id, NULL);
         if (r < 0)
                 goto fail;
@@ -256,6 +253,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
         if (json_variant_is_blank_object(p.addresses))
                 goto not_found;
 
+        size_t n_addresses = 0;
         JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) {
                 AddressParameters q = {};
 
@@ -271,13 +269,13 @@ enum nss_status _nss_resolve_gethostbyname4_r(
                         goto fail;
                 }
 
-                c++;
+                n_addresses++;
         }
 
-        canonical = p.name ?: name;
+        const char *canonical = p.name ?: name;
+        size_t l = strlen(canonical);
+        size_t idx, ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * n_addresses;
 
-        l = strlen(canonical);
-        ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
         if (buflen < ms) {
                 UNPROTECT_ERRNO;
                 *errnop = ERANGE;
@@ -286,12 +284,13 @@ enum nss_status _nss_resolve_gethostbyname4_r(
         }
 
         /* First, append name */
-        r_name = buffer;
-        memcpy(r_name, canonical, l+1);
-        idx = ALIGN(l+1);
+        char *r_name = buffer;
+        memcpy(r_name, canonical, l + 1);
+        idx = ALIGN(l + 1);
 
         /* Second, append addresses */
-        r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);
+        struct gaih_addrtuple *r_tuple = NULL,
+                *r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);
 
         JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) {
                 AddressParameters q = {};
@@ -313,7 +312,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
                 idx += ALIGN(sizeof(struct gaih_addrtuple));
         }
 
-        assert(r_tuple);
+        assert(r_tuple);  /* We had at least one address, so r_tuple must be set */
         r_tuple->next = NULL;  /* Override last next pointer */
 
         assert(idx == ms);
@@ -353,13 +352,10 @@ enum nss_status _nss_resolve_gethostbyname3_r(
                 int32_t *ttlp,
                 char **canonp) {
 
-        _cleanup_(resolve_hostname_reply_destroy) ResolveHostnameReply p = {};
-        _cleanup_(json_variant_unrefp) JsonVariant *cparams = NULL;
-        char *r_name, *r_aliases, *r_addr, *r_addr_list;
         _cleanup_(varlink_unrefp) Varlink *link = NULL;
-        const char *canonical, *error_id = NULL;
-        size_t l, idx, ms, alen, i = 0, c = 0;
-        JsonVariant *entry, *rparams;
+        _cleanup_(json_variant_unrefp) JsonVariant *cparams = NULL;
+        _cleanup_(resolve_hostname_reply_destroy) ResolveHostnameReply p = {};
+        JsonVariant *rparams, *entry;
         int r;
 
         PROTECT_ERRNO;
@@ -389,6 +385,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
         if (r < 0)
                 goto fail;
 
+        const char *error_id;
         r = varlink_call(link, "io.systemd.Resolve.ResolveHostname", cparams, &rparams, &error_id, NULL);
         if (r < 0)
                 goto fail;
@@ -404,6 +401,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
         if (json_variant_is_blank_object(p.addresses))
                 goto not_found;
 
+        size_t n_addresses = 0;
         JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) {
                 AddressParameters q = {};
 
@@ -419,15 +417,15 @@ enum nss_status _nss_resolve_gethostbyname3_r(
                         goto fail;
                 }
 
-                c++;
+                n_addresses++;
         }
 
-        canonical = p.name ?: name;
+        const char *canonical = p.name ?: name;
 
-        alen = FAMILY_ADDRESS_SIZE(af);
-        l = strlen(canonical);
+        size_t alen = FAMILY_ADDRESS_SIZE(af);
+        size_t l = strlen(canonical);
 
-        ms = ALIGN(l+1) + c*ALIGN(alen) + (c+2) * sizeof(char*);
+        size_t idx, ms = ALIGN(l + 1) + n_addresses * ALIGN(alen) + (n_addresses + 2) * sizeof(char*);
 
         if (buflen < ms) {
                 UNPROTECT_ERRNO;
@@ -437,18 +435,19 @@ enum nss_status _nss_resolve_gethostbyname3_r(
         }
 
         /* First, append name */
-        r_name = buffer;
+        char *r_name = buffer;
         memcpy(r_name, canonical, l+1);
         idx = ALIGN(l+1);
 
         /* Second, create empty aliases array */
-        r_aliases = buffer + idx;
+        char *r_aliases = buffer + idx;
         ((char**) r_aliases)[0] = NULL;
         idx += sizeof(char*);
 
         /* Third, append addresses */
-        r_addr = buffer + idx;
+        char *r_addr = buffer + idx;
 
+        size_t i = 0;
         JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) {
                 AddressParameters q = {};
 
@@ -468,16 +467,16 @@ enum nss_status _nss_resolve_gethostbyname3_r(
                 i++;
         }
 
-        assert(i == c);
-        idx += c * ALIGN(alen);
+        assert(i == n_addresses);
+        idx += n_addresses * ALIGN(alen);
 
         /* Fourth, append address pointer array */
-        r_addr_list = buffer + idx;
-        for (i = 0; i < c; i++)
+        char *r_addr_list = buffer + idx;
+        for (i = 0; i < n_addresses; i++)
                 ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen);
 
         ((char**) r_addr_list)[i] = NULL;
-        idx += (c+1) * sizeof(char*);
+        idx += (n_addresses + 1) * sizeof(char*);
 
         assert(idx == ms);
 
@@ -540,8 +539,8 @@ static void name_parameters_destroy(NameParameters *p) {
 }
 
 static const JsonDispatch name_parameters_dispatch_table[] = {
-        { "ifindex", JSON_VARIANT_INTEGER,  json_dispatch_ifindex, offsetof(NameParameters, ifindex), 0              },
-        { "name",    JSON_VARIANT_UNSIGNED, json_dispatch_string,  offsetof(NameParameters, name),    JSON_MANDATORY },
+        { "ifindex", JSON_VARIANT_INTEGER, json_dispatch_ifindex, offsetof(NameParameters, ifindex), 0              },
+        { "name",    JSON_VARIANT_STRING,  json_dispatch_string,  offsetof(NameParameters, name),    JSON_MANDATORY },
         {}
 };
 
@@ -553,14 +552,10 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
                 int *errnop, int *h_errnop,
                 int32_t *ttlp) {
 
-        _cleanup_(resolve_address_reply_destroy) ResolveAddressReply p = {};
-        _cleanup_(json_variant_unrefp) JsonVariant *cparams = NULL;
-        char *r_name, *r_aliases, *r_addr, *r_addr_list;
         _cleanup_(varlink_unrefp) Varlink *link = NULL;
-        JsonVariant *entry, *rparams;
-        const char *n, *error_id;
-        unsigned c = 0, i = 0;
-        size_t ms = 0, idx;
+        _cleanup_(json_variant_unrefp) JsonVariant *cparams = NULL;
+        _cleanup_(resolve_address_reply_destroy) ResolveAddressReply p = {};
+        JsonVariant *rparams, *entry;
         int r;
 
         PROTECT_ERRNO;
@@ -594,6 +589,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
         if (r < 0)
                 goto fail;
 
+        const char* error_id;
         r = varlink_call(link, "io.systemd.Resolve.ResolveAddress", cparams, &rparams, &error_id, NULL);
         if (r < 0)
                 goto fail;
@@ -609,6 +605,8 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
         if (json_variant_is_blank_object(p.names))
                 goto not_found;
 
+        size_t ms = 0, idx;
+
         JSON_VARIANT_ARRAY_FOREACH(entry, p.names) {
                 _cleanup_(name_parameters_destroy) NameParameters q = {};
 
@@ -619,9 +617,10 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
                 ms += ALIGN(strlen(q.name) + 1);
         }
 
-        ms += ALIGN(len) +                                           /* the address */
-              2 * sizeof(char*) +                                    /* pointers to the address, plus trailing NULL */
-              json_variant_elements(p.names) * sizeof(char*);        /* pointers to aliases, plus trailing NULL */
+        size_t n_names = json_variant_elements(p.names);
+        ms += ALIGN(len) +                    /* the address */
+              2 * sizeof(char*) +             /* pointer to the address, plus trailing NULL */
+              n_names * sizeof(char*);        /* pointers to aliases, plus trailing NULL */
 
         if (buflen < ms) {
                 UNPROTECT_ERRNO;
@@ -631,44 +630,43 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
         }
 
         /* First, place address */
-        r_addr = buffer;
+        char *r_addr = buffer;
         memcpy(r_addr, addr, len);
         idx = ALIGN(len);
 
         /* Second, place address list */
-        r_addr_list = buffer + idx;
+        char *r_addr_list = buffer + idx;
         ((char**) r_addr_list)[0] = r_addr;
         ((char**) r_addr_list)[1] = NULL;
         idx += sizeof(char*) * 2;
 
-        /* Third, reserve space for the aliases array */
-        r_aliases = buffer + idx;
-        idx += sizeof(char*) * c;
+        /* Third, reserve space for the aliases array, plus trailing NULL */
+        char *r_aliases = buffer + idx;
+        idx += sizeof(char*) * n_names;
 
         /* Fourth, place aliases */
-        i = 0;
-        r_name = buffer + idx;
+        char *r_name = buffer + idx;
+
+        size_t i = 0;
         JSON_VARIANT_ARRAY_FOREACH(entry, p.names) {
                 _cleanup_(name_parameters_destroy) NameParameters q = {};
-                size_t l;
-                char *z;
 
                 r = json_dispatch(entry, name_parameters_dispatch_table, NULL, json_dispatch_flags, &q);
                 if (r < 0)
                         goto fail;
 
-                l = strlen(q.name);
-                z = buffer + idx;
-                memcpy(z, n, l+1);
+                size_t l = strlen(q.name);
+                char *z = buffer + idx;
+                memcpy(z, q.name, l + 1);
 
                 if (i > 0)
-                        ((char**) r_aliases)[i-1] = z;
+                        ((char**) r_aliases)[i - 1] = z;
                 i++;
 
-                idx += ALIGN(l+1);
+                idx += ALIGN(l + 1);
         }
+        ((char**) r_aliases)[n_names - 1] = NULL;
 
-        ((char**) r_aliases)[c-1] = NULL;
         assert(idx == ms);
 
         result->h_name = r_name;
index 0b716d22dddaa400fd639bd4fd7b1d30fd8d2e24..5592eaa3aa417b78f8936429bb12074ab5cbc76b 100644 (file)
@@ -20,7 +20,7 @@
 
 static const struct passwd root_passwd = {
         .pw_name = (char*) "root",
-        .pw_passwd = (char*) "x", /* see shadow file */
+        .pw_passwd = (char*) PASSWORD_SEE_SHADOW,
         .pw_uid = 0,
         .pw_gid = 0,
         .pw_gecos = (char*) "Super User",
@@ -30,7 +30,7 @@ static const struct passwd root_passwd = {
 
 static const struct passwd nobody_passwd = {
         .pw_name = (char*) NOBODY_USER_NAME,
-        .pw_passwd = (char*) "*", /* locked */
+        .pw_passwd = (char*) PASSWORD_LOCKED_AND_INVALID,
         .pw_uid = UID_NOBODY,
         .pw_gid = GID_NOBODY,
         .pw_gecos = (char*) "User Nobody",
@@ -41,14 +41,14 @@ static const struct passwd nobody_passwd = {
 static const struct group root_group = {
         .gr_name = (char*) "root",
         .gr_gid = 0,
-        .gr_passwd = (char*) "x", /* see shadow file */
+        .gr_passwd = (char*) PASSWORD_SEE_SHADOW,
         .gr_mem = (char*[]) { NULL },
 };
 
 static const struct group nobody_group = {
         .gr_name = (char*) NOBODY_GROUP_NAME,
         .gr_gid = GID_NOBODY,
-        .gr_passwd = (char*) "*", /* locked */
+        .gr_passwd = (char*) PASSWORD_LOCKED_AND_INVALID,
         .gr_mem = (char*[]) { NULL },
 };
 
@@ -294,8 +294,8 @@ static enum nss_status nss_systemd_endent(GetentData *p) {
 
         assert(p);
 
-        _cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
-        _l = pthread_mutex_lock_assert(&p->mutex);
+        _cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&p->mutex);
+        (void) _l; /* make llvm shut up about _l not being used. */
 
         p->iterator = userdb_iterator_free(p->iterator);
         p->by_membership = false;
@@ -312,16 +312,16 @@ enum nss_status _nss_systemd_endgrent(void) {
 }
 
 enum nss_status _nss_systemd_setpwent(int stayopen) {
+        int r;
+
         PROTECT_ERRNO;
         NSS_ENTRYPOINT_BEGIN;
 
         if (_nss_systemd_is_blocked())
                 return NSS_STATUS_NOTFOUND;
 
-        _cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
-        int r;
-
-        _l = pthread_mutex_lock_assert(&getpwent_data.mutex);
+        _cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&getpwent_data.mutex);
+        (void) _l; /* make llvm shut up about _l not being used. */
 
         getpwent_data.iterator = userdb_iterator_free(getpwent_data.iterator);
         getpwent_data.by_membership = false;
@@ -336,19 +336,19 @@ enum nss_status _nss_systemd_setpwent(int stayopen) {
 }
 
 enum nss_status _nss_systemd_setgrent(int stayopen) {
+        int r;
+
         PROTECT_ERRNO;
         NSS_ENTRYPOINT_BEGIN;
 
         if (_nss_systemd_is_blocked())
                 return NSS_STATUS_NOTFOUND;
 
-        _cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
-        int r;
-
-        _l = pthread_mutex_lock_assert(&getgrent_data.mutex);
+        _cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&getgrent_data.mutex);
+        (void) _l; /* make llvm shut up about _l not being used. */
 
         getgrent_data.iterator = userdb_iterator_free(getgrent_data.iterator);
-        getpwent_data.by_membership = false;
+        getgrent_data.by_membership = false;
 
         /* See _nss_systemd_setpwent() for an explanation why we use USERDB_DONT_SYNTHESIZE here */
         r = groupdb_all(nss_glue_userdb_flags() | USERDB_DONT_SYNTHESIZE, &getgrent_data.iterator);
@@ -372,9 +372,8 @@ enum nss_status _nss_systemd_getpwent_r(
         if (_nss_systemd_is_blocked())
                 return NSS_STATUS_NOTFOUND;
 
-        _cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
-
-        _l = pthread_mutex_lock_assert(&getpwent_data.mutex);
+        _cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&getpwent_data.mutex);
+        (void) _l; /* make llvm shut up about _l not being used. */
 
         if (!getpwent_data.iterator) {
                 UNPROTECT_ERRNO;
@@ -419,9 +418,8 @@ enum nss_status _nss_systemd_getgrent_r(
         if (_nss_systemd_is_blocked())
                 return NSS_STATUS_NOTFOUND;
 
-        _cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = NULL;
-
-        _l = pthread_mutex_lock_assert(&getgrent_data.mutex);
+        _cleanup_(pthread_mutex_unlock_assertp) pthread_mutex_t *_l = pthread_mutex_lock_assert(&getgrent_data.mutex);
+        (void) _l; /* make llvm shut up about _l not being used. */
 
         if (!getgrent_data.iterator) {
                 UNPROTECT_ERRNO;
@@ -441,7 +439,7 @@ enum nss_status _nss_systemd_getgrent_r(
                         getgrent_data.iterator = userdb_iterator_free(getgrent_data.iterator);
 
                         r = membershipdb_all(nss_glue_userdb_flags(), &getgrent_data.iterator);
-                        if (r < 0) {
+                        if (r < 0 && r != -ESRCH) {
                                 UNPROTECT_ERRNO;
                                 *errnop = -r;
                                 return NSS_STATUS_UNAVAIL;
@@ -454,7 +452,7 @@ enum nss_status _nss_systemd_getgrent_r(
                         return NSS_STATUS_UNAVAIL;
                 } else if (!STR_IN_SET(gr->group_name, root_group.gr_name, nobody_group.gr_name)) {
                         r = membershipdb_by_group_strv(gr->group_name, nss_glue_userdb_flags(), &members);
-                        if (r < 0) {
+                        if (r < 0 && r != -ESRCH) {
                                 UNPROTECT_ERRNO;
                                 *errnop = -r;
                                 return NSS_STATUS_UNAVAIL;
@@ -465,6 +463,9 @@ enum nss_status _nss_systemd_getgrent_r(
         if (getgrent_data.by_membership) {
                 _cleanup_(_nss_systemd_unblockp) bool blocked = false;
 
+                if (!getgrent_data.iterator)
+                        return NSS_STATUS_NOTFOUND;
+
                 for (;;) {
                         _cleanup_free_ char *user_name = NULL, *group_name = NULL;
 
index 22af0fde60176e50f524bb7c2128c21db0bae373..8f8988579b808fd0829da47a6f3c667b700e83be 100644 (file)
@@ -6,6 +6,7 @@
 #include "strv.h"
 #include "user-record-nss.h"
 #include "user-record.h"
+#include "user-util.h"
 #include "userdb-glue.h"
 #include "userdb.h"
 
@@ -50,7 +51,7 @@ int nss_pack_user_record(
                 .pw_name = buffer,
                 .pw_uid = hr->uid,
                 .pw_gid = user_record_gid(hr),
-                .pw_passwd = (char*) "x", /* means: see shadow file */
+                .pw_passwd = (char*) PASSWORD_SEE_SHADOW,
         };
 
         assert(buffer);
@@ -184,7 +185,7 @@ int nss_pack_group_record(
         *gr = (struct group) {
                 .gr_name = strcpy(p, g->group_name),
                 .gr_gid = g->gid,
-                .gr_passwd = (char*) "x", /* means: see shadow file */
+                .gr_passwd = (char*) PASSWORD_SEE_SHADOW,
                 .gr_mem = array,
         };
 
@@ -215,7 +216,7 @@ enum nss_status userdb_getgrnam(
         }
 
         r = membershipdb_by_group_strv(name, nss_glue_userdb_flags(), &members);
-        if (r < 0) {
+        if (r < 0 && r != -ESRCH) {
                 *errnop = -r;
                 return NSS_STATUS_UNAVAIL;
         }
@@ -308,7 +309,7 @@ enum nss_status userdb_getgrgid(
                 from_nss = false;
 
         r = membershipdb_by_group_strv(g->group_name, nss_glue_userdb_flags(), &members);
-        if (r < 0) {
+        if (r < 0 && r != -ESRCH) {
                 *errnop = -r;
                 return NSS_STATUS_UNAVAIL;
         }
index c3e84aadde98183fae6c6b5a9d3658807f25be2b..49dc5eb26e84480a2ded8aff77fb8638c8d625c9 100644 (file)
@@ -299,8 +299,7 @@ static int acquire_managed_oom_connect(Manager *m) {
         return 0;
 }
 
-static int monitor_cgroup_contexts_handler(sd_event_source *s, uint64_t usec, void *userdata) {
-        _cleanup_set_free_ Set *targets = NULL;
+static int monitor_swap_contexts_handler(sd_event_source *s, uint64_t usec, void *userdata) {
         Manager *m = userdata;
         usec_t usec_now;
         int r;
@@ -313,7 +312,7 @@ static int monitor_cgroup_contexts_handler(sd_event_source *s, uint64_t usec, vo
         if (r < 0)
                 return log_error_errno(r, "Failed to reset event timer: %m");
 
-        r = sd_event_source_set_time_relative(s, INTERVAL_USEC);
+        r = sd_event_source_set_time_relative(s, SWAP_INTERVAL_USEC);
         if (r < 0)
                 return log_error_errno(r, "Failed to set relative time for timer: %m");
 
@@ -324,97 +323,29 @@ static int monitor_cgroup_contexts_handler(sd_event_source *s, uint64_t usec, vo
                         return log_error_errno(r, "Failed to acquire varlink connection: %m");
         }
 
-        /* Update the cgroups used for detection/action */
-        r = update_monitored_cgroup_contexts(&m->monitored_swap_cgroup_contexts);
-        if (r == -ENOMEM)
-                return log_oom();
-        if (r < 0)
-                log_debug_errno(r, "Failed to update monitored swap cgroup contexts, ignoring: %m");
-
-        r = update_monitored_cgroup_contexts(&m->monitored_mem_pressure_cgroup_contexts);
-        if (r == -ENOMEM)
-                return log_oom();
-        if (r < 0)
-                log_debug_errno(r, "Failed to update monitored memory pressure cgroup contexts, ignoring: %m");
-
-        r = update_monitored_cgroup_contexts_candidates(
-                        m->monitored_mem_pressure_cgroup_contexts, &m->monitored_mem_pressure_cgroup_contexts_candidates);
-        if (r == -ENOMEM)
-                return log_oom();
-        if (r < 0)
-                log_debug_errno(r, "Failed to update monitored memory pressure candidate cgroup contexts, ignoring: %m");
-
+        /* We still try to acquire swap information for oomctl even if no units want swap monitoring */
         r = oomd_system_context_acquire("/proc/swaps", &m->system_context);
-        /* If there aren't units depending on swap actions, the only error we exit on is ENOMEM.
+        /* If there are no units depending on swap actions, the only error we exit on is ENOMEM.
          * Allow ENOENT in the event that swap is disabled on the system. */
-        if (r == -ENOMEM || (r < 0 && r != -ENOENT && !hashmap_isempty(m->monitored_swap_cgroup_contexts)))
-                return log_error_errno(r, "Failed to acquire system context: %m");
-        else if (r == -ENOENT)
+        if (r == -ENOENT) {
                 zero(m->system_context);
+                return 0;
+        } else if (r == -ENOMEM || (r < 0 && !hashmap_isempty(m->monitored_swap_cgroup_contexts)))
+                return log_error_errno(r, "Failed to acquire system context: %m");
 
-        if (oomd_memory_reclaim(m->monitored_mem_pressure_cgroup_contexts))
-                m->last_reclaim_at = usec_now;
+        /* Return early if nothing is requesting swap monitoring */
+        if (hashmap_isempty(m->monitored_swap_cgroup_contexts))
+                return 0;
 
-        /* If we're still recovering from a kill, don't try to kill again yet */
-        if (m->post_action_delay_start > 0) {
-                if (m->post_action_delay_start + POST_ACTION_DELAY_USEC > usec_now)
-                        return 0;
-                else
-                        m->post_action_delay_start = 0;
-        }
-
-        r = oomd_pressure_above(m->monitored_mem_pressure_cgroup_contexts, m->default_mem_pressure_duration_usec, &targets);
-        if (r == -ENOMEM)
-                return log_oom();
-        if (r < 0)
-                log_debug_errno(r, "Failed to check if memory pressure exceeded limits, ignoring: %m");
-        else if (r == 1) {
-                /* Check if there was reclaim activity in the given interval. The concern is the following case:
-                 * Pressure climbed, a lot of high-frequency pages were reclaimed, and we killed the offending
-                 * cgroup. Even after this, well-behaved processes will fault in recently resident pages and
-                 * this will cause pressure to remain high. Thus if there isn't any reclaim pressure, no need
-                 * to kill something (it won't help anyways). */
-                if ((usec_now - m->last_reclaim_at) <= RECLAIM_DURATION_USEC) {
-                        OomdCGroupContext *t;
-
-                        SET_FOREACH(t, targets) {
-                                _cleanup_free_ char *selected = NULL;
-                                char ts[FORMAT_TIMESPAN_MAX];
-
-                                log_debug("Memory pressure for %s is %lu.%02lu%% > %lu.%02lu%% for > %s with reclaim activity",
-                                          t->path,
-                                          LOAD_INT(t->memory_pressure.avg10), LOAD_FRAC(t->memory_pressure.avg10),
-                                          LOAD_INT(t->mem_pressure_limit), LOAD_FRAC(t->mem_pressure_limit),
-                                          format_timespan(ts, sizeof ts,
-                                                          m->default_mem_pressure_duration_usec,
-                                                          USEC_PER_SEC));
-
-                                r = oomd_kill_by_pgscan_rate(m->monitored_mem_pressure_cgroup_contexts_candidates, t->path, m->dry_run, &selected);
-                                if (r == -ENOMEM)
-                                        return log_oom();
-                                if (r < 0)
-                                        log_notice_errno(r, "Failed to kill any cgroup(s) under %s based on pressure: %m", t->path);
-                                else {
-                                        /* Don't act on all the high pressure cgroups at once; return as soon as we kill one */
-                                        m->post_action_delay_start = usec_now;
-                                        if (selected)
-                                                log_notice("Killed %s due to memory pressure for %s being %lu.%02lu%% > %lu.%02lu%%"
-                                                           " for > %s with reclaim activity",
-                                                           selected, t->path,
-                                                           LOAD_INT(t->memory_pressure.avg10), LOAD_FRAC(t->memory_pressure.avg10),
-                                                           LOAD_INT(t->mem_pressure_limit), LOAD_FRAC(t->mem_pressure_limit),
-                                                           format_timespan(ts, sizeof ts,
-                                                                           m->default_mem_pressure_duration_usec,
-                                                                           USEC_PER_SEC));
-                                        return 0;
-                                }
-                        }
-                }
-        }
+        /* Note that m->monitored_swap_cgroup_contexts does not need to be updated every interval because only the
+         * system context is used for deciding whether the swap threshold is hit. m->monitored_swap_cgroup_contexts
+         * is only used to decide which cgroups to kill (and even then only the resource usages of its descendent
+         * nodes are the ones that matter). */
 
         if (oomd_swap_free_below(&m->system_context, 10000 - m->swap_used_limit_permyriad)) {
                 _cleanup_hashmap_free_ Hashmap *candidates = NULL;
                 _cleanup_free_ char *selected = NULL;
+                uint64_t threshold;
 
                 log_debug("Swap used (%"PRIu64") / total (%"PRIu64") is more than " PERMYRIAD_AS_PERCENT_FORMAT_STR,
                           m->system_context.swap_used, m->system_context.swap_total,
@@ -426,13 +357,13 @@ static int monitor_cgroup_contexts_handler(sd_event_source *s, uint64_t usec, vo
                 if (r < 0)
                         log_debug_errno(r, "Failed to get monitored swap cgroup candidates, ignoring: %m");
 
-                r = oomd_kill_by_swap_usage(candidates, m->dry_run, &selected);
+                threshold = m->system_context.swap_total * THRESHOLD_SWAP_USED_PERCENT / 100;
+                r = oomd_kill_by_swap_usage(candidates, threshold, m->dry_run, &selected);
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0)
                         log_notice_errno(r, "Failed to kill any cgroup(s) based on swap: %m");
                 else {
-                        m->post_action_delay_start = usec_now;
                         if (selected)
                                 log_notice("Killed %s due to swap used (%"PRIu64") / total (%"PRIu64") being more than "
                                            PERMYRIAD_AS_PERCENT_FORMAT_STR,
@@ -445,14 +376,183 @@ static int monitor_cgroup_contexts_handler(sd_event_source *s, uint64_t usec, vo
         return 0;
 }
 
-static int monitor_cgroup_contexts(Manager *m) {
+static void clear_candidate_hashmapp(Manager **m) {
+        if (*m)
+                hashmap_clear((*m)->monitored_mem_pressure_cgroup_contexts_candidates);
+}
+
+static int monitor_memory_pressure_contexts_handler(sd_event_source *s, uint64_t usec, void *userdata) {
+        /* Don't want to use stale candidate data. Setting this will clear the candidate hashmap on return unless we
+         * update the candidate data (in which case clear_candidates will be NULL). */
+        _cleanup_(clear_candidate_hashmapp) Manager *clear_candidates = userdata;
+        _cleanup_set_free_ Set *targets = NULL;
+        bool in_post_action_delay = false;
+        Manager *m = userdata;
+        usec_t usec_now;
+        int r;
+
+        assert(s);
+        assert(userdata);
+
+        /* Reset timer */
+        r = sd_event_now(sd_event_source_get_event(s), CLOCK_MONOTONIC, &usec_now);
+        if (r < 0)
+                return log_error_errno(r, "Failed to reset event timer: %m");
+
+        r = sd_event_source_set_time_relative(s, MEM_PRESSURE_INTERVAL_USEC);
+        if (r < 0)
+                return log_error_errno(r, "Failed to set relative time for timer: %m");
+
+        /* Reconnect if our connection dropped */
+        if (!m->varlink) {
+                r = acquire_managed_oom_connect(m);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to acquire varlink connection: %m");
+        }
+
+        /* Return early if nothing is requesting memory pressure monitoring */
+        if (hashmap_isempty(m->monitored_mem_pressure_cgroup_contexts))
+                return 0;
+
+        /* Update the cgroups used for detection/action */
+        r = update_monitored_cgroup_contexts(&m->monitored_mem_pressure_cgroup_contexts);
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0)
+                log_debug_errno(r, "Failed to update monitored memory pressure cgroup contexts, ignoring: %m");
+
+        r = update_monitored_cgroup_contexts_candidates(
+                        m->monitored_mem_pressure_cgroup_contexts, &m->monitored_mem_pressure_cgroup_contexts_candidates);
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0)
+                log_debug_errno(r, "Failed to update monitored memory pressure candidate cgroup contexts, ignoring: %m");
+
+        /* Since pressure counters are lagging, we need to wait a bit after a kill to ensure we don't read stale
+         * values and go on a kill storm. */
+        if (m->mem_pressure_post_action_delay_start > 0) {
+                if (m->mem_pressure_post_action_delay_start + POST_ACTION_DELAY_USEC > usec_now)
+                        in_post_action_delay = true;
+                else
+                        m->mem_pressure_post_action_delay_start = 0;
+        }
+
+        r = oomd_pressure_above(m->monitored_mem_pressure_cgroup_contexts, m->default_mem_pressure_duration_usec, &targets);
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0)
+                log_debug_errno(r, "Failed to check if memory pressure exceeded limits, ignoring: %m");
+        else if (r == 1 && !in_post_action_delay) {
+                OomdCGroupContext *t;
+                SET_FOREACH(t, targets) {
+                        _cleanup_free_ char *selected = NULL;
+                        char ts[FORMAT_TIMESPAN_MAX];
+
+                        /* Check if there was reclaim activity in the given interval. The concern is the following case:
+                         * Pressure climbed, a lot of high-frequency pages were reclaimed, and we killed the offending
+                         * cgroup. Even after this, well-behaved processes will fault in recently resident pages and
+                         * this will cause pressure to remain high. Thus if there isn't any reclaim pressure, no need
+                         * to kill something (it won't help anyways). */
+                        if ((now(CLOCK_MONOTONIC) - t->last_had_mem_reclaim) > RECLAIM_DURATION_USEC)
+                                continue;
+
+                        log_debug("Memory pressure for %s is %lu.%02lu%% > %lu.%02lu%% for > %s with reclaim activity",
+                                  t->path,
+                                  LOAD_INT(t->memory_pressure.avg10), LOAD_FRAC(t->memory_pressure.avg10),
+                                  LOAD_INT(t->mem_pressure_limit), LOAD_FRAC(t->mem_pressure_limit),
+                                  format_timespan(ts, sizeof ts,
+                                                  m->default_mem_pressure_duration_usec,
+                                                  USEC_PER_SEC));
+
+                        r = update_monitored_cgroup_contexts_candidates(
+                                        m->monitored_mem_pressure_cgroup_contexts, &m->monitored_mem_pressure_cgroup_contexts_candidates);
+                        if (r == -ENOMEM)
+                                return log_oom();
+                        if (r < 0)
+                                log_debug_errno(r, "Failed to update monitored memory pressure candidate cgroup contexts, ignoring: %m");
+                        else
+                                clear_candidates = NULL;
+
+                        r = oomd_kill_by_pgscan_rate(m->monitored_mem_pressure_cgroup_contexts_candidates, t->path, m->dry_run, &selected);
+                        if (r == -ENOMEM)
+                                return log_oom();
+                        if (r < 0)
+                                log_notice_errno(r, "Failed to kill any cgroup(s) under %s based on pressure: %m", t->path);
+                        else {
+                                /* Don't act on all the high pressure cgroups at once; return as soon as we kill one */
+                                m->mem_pressure_post_action_delay_start = usec_now;
+                                if (selected)
+                                        log_notice("Killed %s due to memory pressure for %s being %lu.%02lu%% > %lu.%02lu%%"
+                                                   " for > %s with reclaim activity",
+                                                   selected, t->path,
+                                                   LOAD_INT(t->memory_pressure.avg10), LOAD_FRAC(t->memory_pressure.avg10),
+                                                   LOAD_INT(t->mem_pressure_limit), LOAD_FRAC(t->mem_pressure_limit),
+                                                   format_timespan(ts, sizeof ts,
+                                                                   m->default_mem_pressure_duration_usec,
+                                                                   USEC_PER_SEC));
+                                return 0;
+                        }
+                }
+        } else {
+                /* If any monitored cgroup is over their pressure limit, get all the kill candidates for every
+                 * monitored cgroup. This saves CPU cycles from doing it every interval by only doing it when a kill
+                 * might happen.
+                 * Candidate cgroup data will continue to get updated during the post-action delay period in case
+                 * pressure continues to be high after a kill. */
+                OomdCGroupContext *c;
+                HASHMAP_FOREACH(c, m->monitored_mem_pressure_cgroup_contexts) {
+                        if (c->mem_pressure_limit_hit_start == 0)
+                                continue;
+
+                        r = update_monitored_cgroup_contexts_candidates(
+                                        m->monitored_mem_pressure_cgroup_contexts, &m->monitored_mem_pressure_cgroup_contexts_candidates);
+                        if (r == -ENOMEM)
+                                return log_oom();
+                        if (r < 0)
+                                log_debug_errno(r, "Failed to update monitored memory pressure candidate cgroup contexts, ignoring: %m");
+                        else {
+                                clear_candidates = NULL;
+                                break;
+                        }
+                }
+        }
+
+        return 0;
+}
+
+static int monitor_swap_contexts(Manager *m) {
+        _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
+        int r;
+
+        assert(m);
+        assert(m->event);
+
+        r = sd_event_add_time(m->event, &s, CLOCK_MONOTONIC, 0, 0, monitor_swap_contexts_handler, m);
+        if (r < 0)
+                return r;
+
+        r = sd_event_source_set_exit_on_failure(s, true);
+        if (r < 0)
+                return r;
+
+        r = sd_event_source_set_enabled(s, SD_EVENT_ON);
+        if (r < 0)
+                return r;
+
+        (void) sd_event_source_set_description(s, "oomd-swap-timer");
+
+        m->swap_context_event_source = TAKE_PTR(s);
+        return 0;
+}
+
+static int monitor_memory_pressure_contexts(Manager *m) {
         _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
         int r;
 
         assert(m);
         assert(m->event);
 
-        r = sd_event_add_time(m->event, &s, CLOCK_MONOTONIC, 0, 0, monitor_cgroup_contexts_handler, m);
+        r = sd_event_add_time(m->event, &s, CLOCK_MONOTONIC, 0, 0, monitor_memory_pressure_contexts_handler, m);
         if (r < 0)
                 return r;
 
@@ -464,9 +564,9 @@ static int monitor_cgroup_contexts(Manager *m) {
         if (r < 0)
                 return r;
 
-        (void) sd_event_source_set_description(s, "oomd-timer");
+        (void) sd_event_source_set_description(s, "oomd-memory-pressure-timer");
 
-        m->cgroup_context_event_source = TAKE_PTR(s);
+        m->mem_pressure_context_event_source = TAKE_PTR(s);
         return 0;
 }
 
@@ -474,7 +574,8 @@ Manager* manager_free(Manager *m) {
         assert(m);
 
         varlink_close_unref(m->varlink);
-        sd_event_source_unref(m->cgroup_context_event_source);
+        sd_event_source_unref(m->swap_context_event_source);
+        sd_event_source_unref(m->mem_pressure_context_event_source);
         sd_event_unref(m->event);
 
         bus_verify_polkit_async_registry_free(m->polkit_registry);
@@ -596,7 +697,11 @@ int manager_start(
         if (r < 0)
                 return r;
 
-        r = monitor_cgroup_contexts(m);
+        r = monitor_memory_pressure_contexts(m);
+        if (r < 0)
+                return r;
+
+        r = monitor_swap_contexts(m);
         if (r < 0)
                 return r;
 
index 9c580c8a249c5bd7f1841077ed69d9633fb58a02..dc170f2bdaac0dc4f94fbee49570c0596ce374cc 100644 (file)
@@ -7,10 +7,9 @@
 #include "varlink.h"
 
 /* Polling interval for monitoring stats */
-#define INTERVAL_USEC (1 * USEC_PER_SEC)
-
-/* Used to weight the averages */
-#define AVERAGE_SIZE_DECAY 4
+#define SWAP_INTERVAL_USEC 150000 /* 0.15 seconds */
+/* Pressure counters are lagging (~2 seconds) compared to swap so polling too frequently just wastes CPU */
+#define MEM_PRESSURE_INTERVAL_USEC (1 * USEC_PER_SEC)
 
 /* Take action if 10s of memory pressure > 60 for more than 30s. We use the "full" value from PSI so this is the
  * percentage of time all tasks were delayed (i.e. unproductive).
@@ -20,6 +19,9 @@
 #define DEFAULT_MEM_PRESSURE_LIMIT_PERCENT 60
 #define DEFAULT_SWAP_USED_LIMIT_PERCENT 90
 
+/* Only tackle candidates with large swap usage. */
+#define THRESHOLD_SWAP_USED_PERCENT 5
+
 #define RECLAIM_DURATION_USEC (30 * USEC_PER_SEC)
 #define POST_ACTION_DELAY_USEC (15 * USEC_PER_SEC)
 
@@ -44,10 +46,10 @@ struct Manager {
 
         OomdSystemContext system_context;
 
-        usec_t last_reclaim_at;
-        usec_t post_action_delay_start;
+        usec_t mem_pressure_post_action_delay_start;
 
-        sd_event_source *cgroup_context_event_source;
+        sd_event_source *swap_context_event_source;
+        sd_event_source *mem_pressure_context_event_source;
 
         Varlink *varlink;
 };
index 894d23a83a4a19746efec90d6de105fc622ed9bc..5bf81479c9f44b61acda229b2b1d279d55800151 100644 (file)
@@ -82,17 +82,17 @@ int oomd_pressure_above(Hashmap *h, usec_t duration, Set **ret) {
                 if (ctx->memory_pressure.avg10 > ctx->mem_pressure_limit) {
                         usec_t diff;
 
-                        if (ctx->last_hit_mem_pressure_limit == 0)
-                                ctx->last_hit_mem_pressure_limit = now(CLOCK_MONOTONIC);
+                        if (ctx->mem_pressure_limit_hit_start == 0)
+                                ctx->mem_pressure_limit_hit_start = now(CLOCK_MONOTONIC);
 
-                        diff = now(CLOCK_MONOTONIC) - ctx->last_hit_mem_pressure_limit;
+                        diff = now(CLOCK_MONOTONIC) - ctx->mem_pressure_limit_hit_start;
                         if (diff >= duration) {
                                 r = set_put(targets, ctx);
                                 if (r < 0)
                                         return -ENOMEM;
                         }
                 } else
-                        ctx->last_hit_mem_pressure_limit = 0;
+                        ctx->mem_pressure_limit_hit_start = 0;
         }
 
         if (!set_isempty(targets)) {
@@ -104,34 +104,21 @@ int oomd_pressure_above(Hashmap *h, usec_t duration, Set **ret) {
         return 0;
 }
 
-bool oomd_memory_reclaim(Hashmap *h) {
-        uint64_t pgscan = 0, pgscan_of = 0, last_pgscan = 0, last_pgscan_of = 0;
-        OomdCGroupContext *ctx;
-
-        assert(h);
-
-        /* If sum of all the current pgscan values are greater than the sum of all the last_pgscan values,
-         * there was reclaim activity. Used along with pressure checks to decide whether to take action. */
+uint64_t oomd_pgscan_rate(const OomdCGroupContext *c) {
+        uint64_t last_pgscan;
 
-        HASHMAP_FOREACH(ctx, h) {
-                uint64_t sum;
+        assert(c);
 
-                sum = pgscan + ctx->pgscan;
-                if (sum < pgscan || sum < ctx->pgscan)
-                        pgscan_of++; /* count overflows */
-                pgscan = sum;
-
-                sum = last_pgscan + ctx->last_pgscan;
-                if (sum < last_pgscan || sum < ctx->last_pgscan)
-                        last_pgscan_of++; /* count overflows */
-                last_pgscan = sum;
+        /* If last_pgscan > pgscan, assume the cgroup was recreated and reset last_pgscan to zero.
+         * pgscan is monotonic and in practice should not decrease (except in the recreation case). */
+        last_pgscan = c->last_pgscan;
+        if (c->last_pgscan > c->pgscan) {
+                log_debug("Last pgscan %"PRIu64" greater than current pgscan %"PRIu64" for %s. Using last pgscan of zero.",
+                                c->last_pgscan, c->pgscan, c->path);
+                last_pgscan = 0;
         }
 
-        /* overflow counts are the same, return sums comparison */
-        if (last_pgscan_of == pgscan_of)
-                return pgscan > last_pgscan;
-
-        return pgscan_of > last_pgscan_of;
+        return c->pgscan - last_pgscan;
 }
 
 bool oomd_swap_free_below(const OomdSystemContext *ctx, int threshold_permyriad) {
@@ -246,7 +233,7 @@ int oomd_kill_by_pgscan_rate(Hashmap *h, const char *prefix, bool dry_run, char
         return ret;
 }
 
-int oomd_kill_by_swap_usage(Hashmap *h, bool dry_run, char **ret_selected) {
+int oomd_kill_by_swap_usage(Hashmap *h, uint64_t threshold_usage, bool dry_run, char **ret_selected) {
         _cleanup_free_ OomdCGroupContext **sorted = NULL;
         int n, r, ret = 0;
 
@@ -257,12 +244,12 @@ int oomd_kill_by_swap_usage(Hashmap *h, bool dry_run, char **ret_selected) {
         if (n < 0)
                 return n;
 
-        /* Try to kill cgroups with non-zero swap usage until we either succeed in
-         * killing or we get to a cgroup with no swap usage. */
+        /* Try to kill cgroups with non-zero swap usage until we either succeed in killing or we get to a cgroup with
+         * no swap usage. Threshold killing only cgroups with more than threshold swap usage. */
         for (int i = 0; i < n; i++) {
-                /* Skip over cgroups with no resource usage.
-                 * Continue break since there might be "avoid" cgroups at the end. */
-                if (sorted[i]->swap_usage == 0)
+                /* Skip over cgroups with not enough swap usage. Don't break since there might be "avoid"
+                 * cgroups at the end. */
+                if (sorted[i]->swap_usage <= threshold_usage)
                         continue;
 
                 r = oomd_cgroup_kill(sorted[i]->path, true, dry_run);
@@ -430,9 +417,13 @@ int oomd_insert_cgroup_context(Hashmap *old_h, Hashmap *new_h, const char *path)
         if (old_ctx) {
                 curr_ctx->last_pgscan = old_ctx->pgscan;
                 curr_ctx->mem_pressure_limit = old_ctx->mem_pressure_limit;
-                curr_ctx->last_hit_mem_pressure_limit = old_ctx->last_hit_mem_pressure_limit;
+                curr_ctx->mem_pressure_limit_hit_start = old_ctx->mem_pressure_limit_hit_start;
+                curr_ctx->last_had_mem_reclaim = old_ctx->last_had_mem_reclaim;
         }
 
+        if (oomd_pgscan_rate(curr_ctx) > 0)
+                curr_ctx->last_had_mem_reclaim = now(CLOCK_MONOTONIC);
+
         r = hashmap_put(new_h, curr_ctx->path, curr_ctx);
         if (r < 0)
                 return r;
@@ -456,7 +447,11 @@ void oomd_update_cgroup_contexts_between_hashmaps(Hashmap *old_h, Hashmap *curr_
 
                 ctx->last_pgscan = old_ctx->pgscan;
                 ctx->mem_pressure_limit = old_ctx->mem_pressure_limit;
-                ctx->last_hit_mem_pressure_limit = old_ctx->last_hit_mem_pressure_limit;
+                ctx->mem_pressure_limit_hit_start = old_ctx->mem_pressure_limit_hit_start;
+                ctx->last_had_mem_reclaim = old_ctx->last_had_mem_reclaim;
+
+                if (oomd_pgscan_rate(ctx) > 0)
+                        ctx->last_had_mem_reclaim = now(CLOCK_MONOTONIC);
         }
 }
 
index 51423130d1b8c8c964d3b608f04fa0841e02148c..81fdc5e088c03b79a332b4ddcb15d1bf4b3a8bc5 100644 (file)
@@ -32,10 +32,10 @@ struct OomdCGroupContext {
 
         ManagedOOMPreference preference;
 
-        /* These are only used by oomd_pressure_above for acting on high memory pressure. */
+        /* These are only used for acting on high memory pressure. */
         loadavg_t mem_pressure_limit;
-        usec_t mem_pressure_duration_usec;
-        usec_t last_hit_mem_pressure_limit;
+        usec_t mem_pressure_limit_hit_start;
+        usec_t last_had_mem_reclaim;
 };
 
 struct OomdSystemContext {
@@ -51,23 +51,22 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(OomdCGroupContext*, oomd_cgroup_context_free);
 
 /* Scans all the OomdCGroupContexts in `h` and returns 1 and a set of pointers to those OomdCGroupContexts in `ret`
  * if any of them have exceeded their supplied memory pressure limits for the `duration` length of time.
- * `last_hit_mem_pressure_limit` is updated accordingly for each entry when the limit is exceeded, and when it returns
+ * `mem_pressure_limit_hit_start` is updated accordingly for the first time the limit is exceeded, and when it returns
  * below the limit.
  * Returns 0 and sets `ret` to an empty set if no entries exceeded limits for `duration`.
  * Returns -ENOMEM for allocation errors. */
 int oomd_pressure_above(Hashmap *h, usec_t duration, Set **ret);
 
-/* Sum up current OomdCGroupContexts' pgscan values and last interval's pgscan values in `h`. Returns true if the
- * current sum is higher than the last interval's sum (there was some reclaim activity). */
-bool oomd_memory_reclaim(Hashmap *h);
-
 /* Returns true if the amount of swap free is below the permyriad of swap specified by `threshold_permyriad`. */
 bool oomd_swap_free_below(const OomdSystemContext *ctx, int threshold_permyriad);
 
+/* Returns pgscan - last_pgscan, accounting for corner cases. */
+uint64_t oomd_pgscan_rate(const OomdCGroupContext *c);
+
 /* The compare functions will sort from largest to smallest, putting all the contexts with "avoid" at the end
  * (after the smallest values). */
 static inline int compare_pgscan_rate_and_memory_usage(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) {
-        uint64_t last1, last2;
+        uint64_t diff1, diff2;
         int r;
 
         assert(c1);
@@ -77,22 +76,9 @@ static inline int compare_pgscan_rate_and_memory_usage(OomdCGroupContext * const
         if (r != 0)
                 return r;
 
-        /* If last_pgscan > pgscan, assume the cgroup was recreated and reset last_pgscan to zero. */
-        last2 = (*c2)->last_pgscan;
-        if ((*c2)->last_pgscan > (*c2)->pgscan) {
-                log_info("Last pgscan %" PRIu64 "greater than current pgscan %" PRIu64 "for %s. Using last pgscan of zero.",
-                                (*c2)->last_pgscan, (*c2)->pgscan, (*c2)->path);
-                last2 = 0;
-        }
-
-        last1 = (*c1)->last_pgscan;
-        if ((*c1)->last_pgscan > (*c1)->pgscan) {
-                log_info("Last pgscan %" PRIu64 "greater than current pgscan %" PRIu64 "for %s. Using last pgscan of zero.",
-                                (*c1)->last_pgscan, (*c1)->pgscan, (*c1)->path);
-                last1 = 0;
-        }
-
-        r = CMP((*c2)->pgscan - last2, (*c1)->pgscan - last1);
+        diff1 = oomd_pgscan_rate(*c1);
+        diff2 = oomd_pgscan_rate(*c2);
+        r = CMP(diff2, diff1);
         if (r != 0)
                 return r;
 
@@ -125,7 +111,7 @@ int oomd_cgroup_kill(const char *path, bool recurse, bool dry_run);
  * everything in `h` is a candidate.
  * Returns the killed cgroup in ret_selected. */
 int oomd_kill_by_pgscan_rate(Hashmap *h, const char *prefix, bool dry_run, char **ret_selected);
-int oomd_kill_by_swap_usage(Hashmap *h, bool dry_run, char **ret_selected);
+int oomd_kill_by_swap_usage(Hashmap *h, uint64_t threshold_usage, bool dry_run, char **ret_selected);
 
 int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret);
 int oomd_system_context_acquire(const char *proc_swaps_path, OomdSystemContext *ret);
index 6e2a5889d1e276bd8a8be810f6b5bfd811cdc5bb..deb7b094d504b49858f78f57a1ff9bf5361ac859 100644 (file)
@@ -155,6 +155,9 @@ static int run(int argc, char *argv[]) {
 
         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
 
+        if (arg_mem_pressure_usec > 0 && arg_mem_pressure_usec < 1 * USEC_PER_SEC)
+                log_error_errno(SYNTHETIC_ERRNO(EINVAL), "DefaultMemoryPressureDurationSec= must be 0 or at least 1s");
+
         r = manager_new(&m);
         if (r < 0)
                 return log_error_errno(r, "Failed to create manager: %m");
index d1dca0d64d15f60c3f63f54e4ddc6e5d184c9f70..b3a457f887738c009ea3ea4166cadcad749fd624 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Entries in this file show the compile time defaults. Local configuration
 # should be created by either modifying this file, or by creating "drop-ins" in
-# the system.conf.d/ subdirectory. The latter is generally recommended.
+# the oomd.conf.d/ subdirectory. The latter is generally recommended.
 # Defaults can be restored by simply deleting this file and all drop-ins.
 #
 # Use 'systemd-analyze cat-config systemd/oomd.conf' to display the full config.
index bd1c574ca7fa02cabb24d155edcf9f541d190625..7ebea29c1a6b3e3b2e044b27d9321b3ab354b080 100644 (file)
@@ -88,9 +88,10 @@ static void test_oomd_cgroup_context_acquire_and_insert(void) {
         _cleanup_hashmap_free_ Hashmap *h1 = NULL, *h2 = NULL;
         _cleanup_(oomd_cgroup_context_freep) OomdCGroupContext *ctx = NULL;
         _cleanup_free_ char *cgroup = NULL;
+        ManagedOOMPreference root_pref;
         OomdCGroupContext *c1, *c2;
         bool test_xattrs;
-        int r;
+        int root_xattrs, r;
 
         if (geteuid() != 0)
                 return (void) log_tests_skipped("not root");
@@ -140,10 +141,16 @@ static void test_oomd_cgroup_context_acquire_and_insert(void) {
         ctx = oomd_cgroup_context_free(ctx);
 
         /* Test the root cgroup */
+        /* Root cgroup is live and not made on demand like the cgroup the test runs in. It can have varying
+         * xattrs set already so let's read in the booleans first to get the final preference value. */
+        root_xattrs = cg_get_xattr_bool(SYSTEMD_CGROUP_CONTROLLER, "", "user.oomd_omit");
+        root_pref = root_xattrs > 0 ? MANAGED_OOM_PREFERENCE_OMIT : MANAGED_OOM_PREFERENCE_NONE;
+        root_xattrs = cg_get_xattr_bool(SYSTEMD_CGROUP_CONTROLLER, "", "user.oomd_avoid");
+        root_pref = root_xattrs > 0 ? MANAGED_OOM_PREFERENCE_AVOID : MANAGED_OOM_PREFERENCE_NONE;
         assert_se(oomd_cgroup_context_acquire("", &ctx) == 0);
         assert_se(streq(ctx->path, "/"));
         assert_se(ctx->current_memory_usage > 0);
-        assert_se(ctx->preference == MANAGED_OOM_PREFERENCE_NONE);
+        assert_se(ctx->preference == root_pref);
 
         /* Test hashmap inserts */
         assert_se(h1 = hashmap_new(&oomd_cgroup_ctx_hash_ops));
@@ -153,9 +160,10 @@ static void test_oomd_cgroup_context_acquire_and_insert(void) {
         assert_se(oomd_insert_cgroup_context(NULL, h1, cgroup) == -EEXIST);
 
          /* make sure certain values from h1 get updated in h2 */
-        c1->pgscan = 5555;
+        c1->pgscan = UINT64_MAX;
         c1->mem_pressure_limit = 6789;
-        c1->last_hit_mem_pressure_limit = 42;
+        c1->mem_pressure_limit_hit_start = 42;
+        c1->last_had_mem_reclaim = 888;
         assert_se(h2 = hashmap_new(&oomd_cgroup_ctx_hash_ops));
         assert_se(oomd_insert_cgroup_context(h1, h2, cgroup) == 0);
         c1 = hashmap_get(h1, cgroup);
@@ -163,9 +171,10 @@ static void test_oomd_cgroup_context_acquire_and_insert(void) {
         assert_se(c1);
         assert_se(c2);
         assert_se(c1 != c2);
-        assert_se(c2->last_pgscan == 5555);
+        assert_se(c2->last_pgscan == UINT64_MAX);
         assert_se(c2->mem_pressure_limit == 6789);
-        assert_se(c2->last_hit_mem_pressure_limit == 42);
+        assert_se(c2->mem_pressure_limit_hit_start == 42);
+        assert_se(c2->last_had_mem_reclaim == 888); /* assumes the live pgscan is less than UINT64_MAX */
 
         /* Assert that avoid/omit are not set if the cgroup is not owned by root */
         if (test_xattrs) {
@@ -182,20 +191,22 @@ static void test_oomd_update_cgroup_contexts_between_hashmaps(void) {
         char **paths = STRV_MAKE("/0.slice",
                                  "/1.slice");
 
-        OomdCGroupContext ctx_old[3] = {
+        OomdCGroupContext ctx_old[2] = {
                 { .path = paths[0],
                   .mem_pressure_limit = 5,
-                  .last_hit_mem_pressure_limit = 777,
+                  .mem_pressure_limit_hit_start = 777,
+                  .last_had_mem_reclaim = 888,
                   .pgscan = 57 },
                 { .path = paths[1],
                   .mem_pressure_limit = 6,
-                  .last_hit_mem_pressure_limit = 888,
+                  .mem_pressure_limit_hit_start = 888,
+                  .last_had_mem_reclaim = 888,
                   .pgscan = 42 },
         };
 
-        OomdCGroupContext ctx_new[3] = {
+        OomdCGroupContext ctx_new[2] = {
                 { .path = paths[0],
-                  .pgscan = 100 },
+                  .pgscan = 57 },
                 { .path = paths[1],
                   .pgscan = 101 },
         };
@@ -214,13 +225,15 @@ static void test_oomd_update_cgroup_contexts_between_hashmaps(void) {
         assert_se(c_new = hashmap_get(h_new, "/0.slice"));
         assert_se(c_old->pgscan == c_new->last_pgscan);
         assert_se(c_old->mem_pressure_limit == c_new->mem_pressure_limit);
-        assert_se(c_old->last_hit_mem_pressure_limit == c_new->last_hit_mem_pressure_limit);
+        assert_se(c_old->mem_pressure_limit_hit_start == c_new->mem_pressure_limit_hit_start);
+        assert_se(c_old->last_had_mem_reclaim == c_new->last_had_mem_reclaim);
 
         assert_se(c_old = hashmap_get(h_old, "/1.slice"));
         assert_se(c_new = hashmap_get(h_new, "/1.slice"));
         assert_se(c_old->pgscan == c_new->last_pgscan);
         assert_se(c_old->mem_pressure_limit == c_new->mem_pressure_limit);
-        assert_se(c_old->last_hit_mem_pressure_limit == c_new->last_hit_mem_pressure_limit);
+        assert_se(c_old->mem_pressure_limit_hit_start == c_new->mem_pressure_limit_hit_start);
+        assert_se(c_new->last_had_mem_reclaim > c_old->last_had_mem_reclaim);
 }
 
 static void test_oomd_system_context_acquire(void) {
@@ -283,7 +296,7 @@ static void test_oomd_pressure_above(void) {
         assert_se(oomd_pressure_above(h1, 0 /* duration */, &t1) == 1);
         assert_se(set_contains(t1, &ctx[0]) == true);
         assert_se(c = hashmap_get(h1, "/herp.slice"));
-        assert_se(c->last_hit_mem_pressure_limit > 0);
+        assert_se(c->mem_pressure_limit_hit_start > 0);
 
         /* Low memory pressure */
         assert_se(h2 = hashmap_new(&string_hash_ops));
@@ -291,7 +304,7 @@ static void test_oomd_pressure_above(void) {
         assert_se(oomd_pressure_above(h2, 0 /* duration */, &t2) == 0);
         assert_se(t2 == NULL);
         assert_se(c = hashmap_get(h2, "/derp.slice"));
-        assert_se(c->last_hit_mem_pressure_limit == 0);
+        assert_se(c->mem_pressure_limit_hit_start == 0);
 
         /* High memory pressure w/ multiple cgroups */
         assert_se(hashmap_put(h1, "/derp.slice", &ctx[1]) >= 0);
@@ -299,50 +312,9 @@ static void test_oomd_pressure_above(void) {
         assert_se(set_contains(t3, &ctx[0]) == true);
         assert_se(set_size(t3) == 1);
         assert_se(c = hashmap_get(h1, "/herp.slice"));
-        assert_se(c->last_hit_mem_pressure_limit > 0);
+        assert_se(c->mem_pressure_limit_hit_start > 0);
         assert_se(c = hashmap_get(h1, "/derp.slice"));
-        assert_se(c->last_hit_mem_pressure_limit == 0);
-}
-
-static void test_oomd_memory_reclaim(void) {
-        _cleanup_hashmap_free_ Hashmap *h1 = NULL;
-        char **paths = STRV_MAKE("/0.slice",
-                                 "/1.slice",
-                                 "/2.slice",
-                                 "/3.slice",
-                                 "/4.slice");
-
-        OomdCGroupContext ctx[5] = {
-                { .path = paths[0],
-                  .last_pgscan = 100,
-                  .pgscan = 100 },
-                { .path = paths[1],
-                  .last_pgscan = 100,
-                  .pgscan = 100 },
-                { .path = paths[2],
-                  .last_pgscan = 77,
-                  .pgscan = 33 },
-                { .path = paths[3],
-                  .last_pgscan = UINT64_MAX,
-                  .pgscan = 100 },
-                { .path = paths[4],
-                  .last_pgscan = 100,
-                  .pgscan = UINT64_MAX },
-        };
-
-        assert_se(h1 = hashmap_new(&string_hash_ops));
-        assert_se(hashmap_put(h1, paths[0], &ctx[0]) >= 0);
-        assert_se(hashmap_put(h1, paths[1], &ctx[1]) >= 0);
-        assert_se(oomd_memory_reclaim(h1) == false);
-
-        assert_se(hashmap_put(h1, paths[2], &ctx[2]) >= 0);
-        assert_se(oomd_memory_reclaim(h1) == false);
-
-        assert_se(hashmap_put(h1, paths[4], &ctx[4]) >= 0);
-        assert_se(oomd_memory_reclaim(h1) == true);
-
-        assert_se(hashmap_put(h1, paths[3], &ctx[3]) >= 0);
-        assert_se(oomd_memory_reclaim(h1) == false);
+        assert_se(c->mem_pressure_limit_hit_start == 0);
 }
 
 static void test_oomd_swap_free_below(void) {
@@ -461,7 +433,6 @@ int main(void) {
         test_oomd_update_cgroup_contexts_between_hashmaps();
         test_oomd_system_context_acquire();
         test_oomd_pressure_above();
-        test_oomd_memory_reclaim();
         test_oomd_swap_free_below();
         test_oomd_sort_cgroups();
 
index f6d337ee2bfed8ffadd3afd1324f75c9af09dc36..51b8f20dbcc2868d38bb7b5bf3c8068d83d46a59 100644 (file)
@@ -26,6 +26,7 @@
 #include "conf-parser.h"
 #include "cryptsetup-util.h"
 #include "def.h"
+#include "dirent-util.h"
 #include "efivars.h"
 #include "errno-util.h"
 #include "fd-util.h"
@@ -44,6 +45,7 @@
 #include "mkdir.h"
 #include "mkfs-util.h"
 #include "mount-util.h"
+#include "mountpoint-util.h"
 #include "parse-argument.h"
 #include "parse-util.h"
 #include "path-util.h"
 /* LUKS2 takes off 16M of the partition size with its metadata by default */
 #define LUKS2_METADATA_SIZE (16*1024*1024)
 
-#if !HAVE_LIBCRYPTSETUP
-struct crypt_device;
-static inline void sym_crypt_free(struct crypt_device* cd) {}
-static inline void sym_crypt_freep(struct crypt_device** cd) {}
-#endif
-
 /* Note: When growing and placing new partitions we always align to 4K sector size. It's how newer hard disks
  * are designed, and if everything is aligned to that performance is best. And for older hard disks with 512B
  * sector size devices were generally assumed to have an even number of sectors, hence at the worst we'll
@@ -98,6 +94,7 @@ static enum {
 static bool arg_dry_run = true;
 static const char *arg_node = NULL;
 static char *arg_root = NULL;
+static char *arg_image = NULL;
 static char *arg_definitions = NULL;
 static bool arg_discard = true;
 static bool arg_can_factory_reset = false;
@@ -116,6 +113,7 @@ static char *arg_tpm2_device = NULL;
 static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
 
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_definitions, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_key, erase_and_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
@@ -161,13 +159,19 @@ struct Partition {
         FreeArea *allocated_to_area;
 
         char *copy_blocks_path;
+        bool copy_blocks_auto;
         int copy_blocks_fd;
         uint64_t copy_blocks_size;
 
         char *format;
         char **copy_files;
+        char **make_directories;
         EncryptMode encrypt;
 
+        uint64_t gpt_flags;
+        int read_only;
+        int growfs;
+
         LIST_FIELDS(Partition, partitions);
 };
 
@@ -239,6 +243,8 @@ static Partition *partition_new(void) {
                 .offset = UINT64_MAX,
                 .copy_blocks_fd = -1,
                 .copy_blocks_size = UINT64_MAX,
+                .read_only = -1,
+                .growfs = -1,
         };
 
         return p;
@@ -262,6 +268,7 @@ static Partition* partition_free(Partition *p) {
 
         free(p->format);
         strv_free(p->copy_files);
+        strv_free(p->make_directories);
 
         return mfree(p);
 }
@@ -967,6 +974,9 @@ static int config_parse_label(
         assert(rvalue);
         assert(label);
 
+        /* Nota bene: the empty label is a totally valid one. Let's hence not follow our usual rule of
+         * assigning the empty string to reset to default here, but really accept it as label to set. */
+
         r = specifier_printf(rvalue, specifier_table, NULL, &resolved);
         if (r < 0) {
                 log_syntax(unit, LOG_WARNING, filename, line, r,
@@ -1139,11 +1149,9 @@ static int config_parse_copy_files(
                 return 0;
         }
 
-        if (!path_is_absolute(resolved_source) || !path_is_normalized(resolved_source)) {
-                log_syntax(unit, LOG_WARNING, filename, line, 0,
-                           "Invalid path name in CopyFiles= source, ignoring: %s", resolved_source);
+        r = path_simplify_and_warn(resolved_source, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+        if (r < 0)
                 return 0;
-        }
 
         r = specifier_printf(target, specifier_table, NULL, &resolved_target);
         if (r < 0) {
@@ -1152,11 +1160,9 @@ static int config_parse_copy_files(
                 return 0;
         }
 
-        if (!path_is_absolute(resolved_target) || !path_is_normalized(resolved_target)) {
-                log_syntax(unit, LOG_WARNING, filename, line, 0,
-                           "Invalid path name in CopyFiles= source, ignoring: %s", resolved_target);
+        r = path_simplify_and_warn(resolved_target, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+        if (r < 0)
                 return 0;
-        }
 
         r = strv_consume_pair(&partition->copy_files, TAKE_PTR(resolved_source), TAKE_PTR(resolved_target));
         if (r < 0)
@@ -1165,26 +1171,154 @@ static int config_parse_copy_files(
         return 0;
 }
 
+static int config_parse_copy_blocks(
+                const char *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_free_ char *d = NULL;
+        Partition *partition = data;
+        int r;
+
+        assert(rvalue);
+        assert(partition);
+
+        if (isempty(rvalue)) {
+                partition->copy_blocks_path = mfree(partition->copy_blocks_path);
+                partition->copy_blocks_auto = false;
+                return 0;
+        }
+
+        if (streq(rvalue, "auto")) {
+                partition->copy_blocks_path = mfree(partition->copy_blocks_path);
+                partition->copy_blocks_auto = true;
+                return 0;
+        }
+
+        r = specifier_printf(rvalue, specifier_table, NULL, &d);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to expand specifiers in CopyBlocks= source path, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        r = path_simplify_and_warn(d, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+        if (r < 0)
+                return 0;
+
+        free_and_replace(partition->copy_blocks_path, d);
+        partition->copy_blocks_auto = false;
+        return 0;
+}
+
+static int config_parse_make_dirs(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Partition *partition = data;
+        const char *p = rvalue;
+        int r;
+
+        assert(rvalue);
+        assert(partition);
+
+        for (;;) {
+                _cleanup_free_ char *word = NULL, *d = NULL;
+
+                r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
+                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)
+                        return 0;
+
+                r = specifier_printf(word, specifier_table, NULL, &d);
+                if (r < 0) {
+                        log_syntax(unit, LOG_WARNING, filename, line, r,
+                                   "Failed to expand specifiers in MakeDirectories= parameter, ignoring: %s", word);
+                        continue;
+                }
+
+                r = path_simplify_and_warn(d, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
+                if (r < 0)
+                        continue;
+
+                r = strv_consume(&partition->make_directories, TAKE_PTR(d));
+                if (r < 0)
+                        return log_oom();
+        }
+}
+
 static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_encrypt, encrypt_mode, EncryptMode, ENCRYPT_OFF, "Invalid encryption mode");
 
+static int config_parse_gpt_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) {
+
+        uint64_t *gpt_flags = data;
+        int r;
+
+        assert(rvalue);
+        assert(gpt_flags);
+
+        r = safe_atou64(rvalue, gpt_flags);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to parse Flags= value, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        return 0;
+}
+
 static int partition_read_definition(Partition *p, const char *path) {
 
         ConfigTableItem table[] = {
-                { "Partition", "Type",            config_parse_type,       0, &p->type_uuid        },
-                { "Partition", "Label",           config_parse_label,      0, &p->new_label        },
-                { "Partition", "UUID",            config_parse_id128,      0, &p->new_uuid         },
-                { "Partition", "Priority",        config_parse_int32,      0, &p->priority         },
-                { "Partition", "Weight",          config_parse_weight,     0, &p->weight           },
-                { "Partition", "PaddingWeight",   config_parse_weight,     0, &p->padding_weight   },
-                { "Partition", "SizeMinBytes",    config_parse_size4096,   1, &p->size_min         },
-                { "Partition", "SizeMaxBytes",    config_parse_size4096,  -1, &p->size_max         },
-                { "Partition", "PaddingMinBytes", config_parse_size4096,   1, &p->padding_min      },
-                { "Partition", "PaddingMaxBytes", config_parse_size4096,  -1, &p->padding_max      },
-                { "Partition", "FactoryReset",    config_parse_bool,       0, &p->factory_reset    },
-                { "Partition", "CopyBlocks",      config_parse_path,       0, &p->copy_blocks_path },
-                { "Partition", "Format",          config_parse_fstype,     0, &p->format           },
-                { "Partition", "CopyFiles",       config_parse_copy_files, 0, p                    },
-                { "Partition", "Encrypt",         config_parse_encrypt,    0, &p->encrypt          },
+                { "Partition", "Type",            config_parse_type,        0, &p->type_uuid        },
+                { "Partition", "Label",           config_parse_label,       0, &p->new_label        },
+                { "Partition", "UUID",            config_parse_id128,       0, &p->new_uuid         },
+                { "Partition", "Priority",        config_parse_int32,       0, &p->priority         },
+                { "Partition", "Weight",          config_parse_weight,      0, &p->weight           },
+                { "Partition", "PaddingWeight",   config_parse_weight,      0, &p->padding_weight   },
+                { "Partition", "SizeMinBytes",    config_parse_size4096,    1, &p->size_min         },
+                { "Partition", "SizeMaxBytes",    config_parse_size4096,   -1, &p->size_max         },
+                { "Partition", "PaddingMinBytes", config_parse_size4096,    1, &p->padding_min      },
+                { "Partition", "PaddingMaxBytes", config_parse_size4096,   -1, &p->padding_max      },
+                { "Partition", "FactoryReset",    config_parse_bool,        0, &p->factory_reset    },
+                { "Partition", "CopyBlocks",      config_parse_copy_blocks, 0, p                    },
+                { "Partition", "Format",          config_parse_fstype,      0, &p->format           },
+                { "Partition", "CopyFiles",       config_parse_copy_files,  0, p                    },
+                { "Partition", "MakeDirectories", config_parse_make_dirs,   0, p                    },
+                { "Partition", "Encrypt",         config_parse_encrypt,     0, &p->encrypt          },
+                { "Partition", "Flags",           config_parse_gpt_flags,   0, &p->gpt_flags        },
+                { "Partition", "ReadOnly",        config_parse_tristate,    0, &p->read_only        },
+                { "Partition", "GrowFileSystem",  config_parse_tristate,    0, &p->growfs           },
                 {}
         };
         int r;
@@ -1210,21 +1344,33 @@ static int partition_read_definition(Partition *p, const char *path) {
                 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
                                   "Type= not defined, refusing.");
 
-        if (p->copy_blocks_path && (p->format || !strv_isempty(p->copy_files)))
+        if ((p->copy_blocks_path || p->copy_blocks_auto) &&
+            (p->format || !strv_isempty(p->copy_files) || !strv_isempty(p->make_directories)))
                 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
-                                  "Format= and CopyBlocks= cannot be combined, refusing.");
+                                  "Format=/CopyFiles=/MakeDirectories= and CopyBlocks= cannot be combined, refusing.");
 
-        if (!strv_isempty(p->copy_files) && streq_ptr(p->format, "swap"))
+        if ((!strv_isempty(p->copy_files) || !strv_isempty(p->make_directories)) && streq_ptr(p->format, "swap"))
                 return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
                                   "Format=swap and CopyFiles= cannot be combined, refusing.");
 
-        if (!p->format && (!strv_isempty(p->copy_files) || (p->encrypt != ENCRYPT_OFF && !p->copy_blocks_path))) {
+        if (!p->format && (!strv_isempty(p->copy_files) || !strv_isempty(p->make_directories) || (p->encrypt != ENCRYPT_OFF && !(p->copy_blocks_path || p->copy_blocks_auto)))) {
                 /* Pick "ext4" as file system if we are configured to copy files or encrypt the device */
                 p->format = strdup("ext4");
                 if (!p->format)
                         return log_oom();
         }
 
+        /* Verity partitions are read only, let's imply the RO flag hence, unless explicitly configured otherwise. */
+        if ((gpt_partition_type_is_root_verity(p->type_uuid) ||
+             gpt_partition_type_is_usr_verity(p->type_uuid)) &&
+            p->read_only < 0)
+                p->read_only = true;
+
+        /* Default to "growfs" on, unless read-only */
+        if (gpt_partition_type_knows_growfs(p->type_uuid) &&
+            p->read_only <= 0)
+                p->growfs = true;
+
         return 0;
 }
 
@@ -1881,7 +2027,7 @@ static int context_dump_partitions(Context *context, const char *node) {
                 r = table_add_many(
                                 t,
                                 TABLE_STRING, gpt_partition_type_uuid_to_string_harder(p->type_uuid, uuid_buffer),
-                                TABLE_STRING, label ?: "-", TABLE_SET_COLOR, label ? NULL : ansi_grey(),
+                                TABLE_STRING, empty_to_null(label) ?: "-", TABLE_SET_COLOR, empty_to_null(label) ? NULL : ansi_grey(),
                                 TABLE_UUID, sd_id128_is_null(p->new_uuid) ? p->current_uuid : p->new_uuid,
                                 TABLE_STRING, p->definition_path ? basename(p->definition_path) : "-", TABLE_SET_COLOR, p->definition_path ? NULL : ansi_grey(),
                                 TABLE_STRING, partname ?: "-", TABLE_SET_COLOR, partname ? NULL : ansi_highlight(),
@@ -2235,6 +2381,9 @@ static int context_discard_range(
 
                 range[0] = round_up_size(offset, 512);
 
+                if (offset > UINT64_MAX - size)
+                        return -ERANGE;
+
                 end = offset + size;
                 if (end <= range[0])
                         return 0;
@@ -2274,6 +2423,11 @@ static int context_discard_partition(Context *context, Partition *p) {
                 log_info("Storage does not support discard, not discarding data in future partition %" PRIu64 ".", p->partno);
                 return 0;
         }
+        if (r == -EBUSY) {
+                /* Let's handle this gracefully: https://bugzilla.kernel.org/show_bug.cgi?id=211167 */
+                log_info("Block device is busy, not discarding partition %" PRIu64 " because it probably is mounted.", p->partno);
+                return 0;
+        }
         if (r == 0) {
                 log_info("Partition %" PRIu64 " too short for discard, skipping.", p->partno);
                 return 0;
@@ -2444,7 +2598,7 @@ static int partition_encrypt(
                          volume_key,
                          volume_key_size,
                          &(struct crypt_params_luks2) {
-                                 .label = p->new_label,
+                                 .label = strempty(p->new_label),
                                  .sector_size = 512U,
                          });
         if (r < 0)
@@ -2655,11 +2809,6 @@ static int do_copy_files(Partition *p, const char *fs) {
 
         STRV_FOREACH_PAIR(source, target, p->copy_files) {
                 _cleanup_close_ int sfd = -1, pfd = -1, tfd = -1;
-                _cleanup_free_ char *dn = NULL;
-
-                dn = dirname_malloc(*target);
-                if (!dn)
-                        return log_oom();
 
                 sfd = chase_symlinks_and_open(*source, arg_root, CHASE_PREFIX_ROOT|CHASE_WARN, O_CLOEXEC|O_NOCTTY, NULL);
                 if (sfd < 0)
@@ -2673,9 +2822,19 @@ static int do_copy_files(Partition *p, const char *fs) {
                         /* We are looking at a directory */
                         tfd = chase_symlinks_and_open(*target, fs, CHASE_PREFIX_ROOT|CHASE_WARN, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
                         if (tfd < 0) {
+                                _cleanup_free_ char *dn = NULL, *fn = NULL;
+
                                 if (tfd != -ENOENT)
                                         return log_error_errno(tfd, "Failed to open target directory '%s': %m", *target);
 
+                                r = path_extract_filename(*target, &fn);
+                                if (r < 0)
+                                        return log_error_errno(r, "Failed to extract filename from '%s': %m", *target);
+
+                                r = path_extract_directory(*target, &dn);
+                                if (r < 0)
+                                        return log_error_errno(r, "Failed to extract directory from '%s': %m", *target);
+
                                 r = mkdir_p_root(fs, dn, UID_INVALID, GID_INVALID, 0755);
                                 if (r < 0)
                                         return log_error_errno(r, "Failed to create parent directory '%s': %m", dn);
@@ -2686,7 +2845,7 @@ static int do_copy_files(Partition *p, const char *fs) {
 
                                 r = copy_tree_at(
                                                 sfd, ".",
-                                                pfd, basename(*target),
+                                                pfd, fn,
                                                 UID_INVALID, GID_INVALID,
                                                 COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS);
                         } else
@@ -2696,25 +2855,38 @@ static int do_copy_files(Partition *p, const char *fs) {
                                                 UID_INVALID, GID_INVALID,
                                                 COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS);
                         if (r < 0)
-                                return log_error_errno(r, "Failed to copy %s%s to %s: %m", strempty(arg_root), *source, *target);
+                                return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_root), *target);
                 } else {
+                        _cleanup_free_ char *dn = NULL, *fn = NULL;
+
                         /* We are looking at a regular file */
 
+                        r = path_extract_filename(*target, &fn);
+                        if (r == -EADDRNOTAVAIL || r == O_DIRECTORY)
+                                return log_error_errno(SYNTHETIC_ERRNO(EISDIR),
+                                                       "Target path '%s' refers to a directory, but source path '%s' refers to regular file, can't copy.", *target, *source);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to extract filename from '%s': %m", *target);
+
+                        r = path_extract_directory(*target, &dn);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to extract directory from '%s': %m", *target);
+
                         r = mkdir_p_root(fs, dn, UID_INVALID, GID_INVALID, 0755);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to create parent directory: %m");
 
                         pfd = chase_symlinks_and_open(dn, fs, CHASE_PREFIX_ROOT|CHASE_WARN, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
                         if (pfd < 0)
-                                return log_error_errno(tfd, "Failed to open parent directory of target: %m");
+                                return log_error_errno(pfd, "Failed to open parent directory of target: %m");
 
-                        tfd = openat(pfd, basename(*target), O_CREAT|O_EXCL|O_WRONLY|O_CLOEXEC, 0700);
+                        tfd = openat(pfd, fn, O_CREAT|O_EXCL|O_WRONLY|O_CLOEXEC, 0700);
                         if (tfd < 0)
                                 return log_error_errno(errno, "Failed to create target file '%s': %m", *target);
 
                         r = copy_bytes(sfd, tfd, UINT64_MAX, COPY_REFLINK|COPY_SIGINT);
                         if (r < 0)
-                                return log_error_errno(r, "Failed to copy '%s%s' to '%s': %m", strempty(arg_root), *source, *target);
+                                return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_root), *target);
 
                         (void) copy_xattr(sfd, tfd);
                         (void) copy_access(sfd, tfd);
@@ -2725,13 +2897,30 @@ static int do_copy_files(Partition *p, const char *fs) {
         return 0;
 }
 
-static int partition_copy_files(Partition *p, const char *node) {
+static int do_make_directories(Partition *p, const char *fs) {
+        char **d;
+        int r;
+
+        assert(p);
+        assert(fs);
+
+        STRV_FOREACH(d, p->make_directories) {
+
+                r = mkdir_p_root(fs, *d, UID_INVALID, GID_INVALID, 0755);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to create directory '%s' in file system: %m", *d);
+        }
+
+        return 0;
+}
+
+static int partition_populate(Partition *p, const char *node) {
         int r;
 
         assert(p);
         assert(node);
 
-        if (strv_isempty(p->copy_files))
+        if (strv_isempty(p->copy_files) && strv_isempty(p->make_directories))
                 return 0;
 
         log_info("Populating partition %" PRIu64 " with files.", p->partno);
@@ -2759,6 +2948,9 @@ static int partition_copy_files(Partition *p, const char *node) {
                 if (do_copy_files(p, fs) < 0)
                         _exit(EXIT_FAILURE);
 
+                if (do_make_directories(p, fs) < 0)
+                        _exit(EXIT_FAILURE);
+
                 r = syncfs_path(AT_FDCWD, fs);
                 if (r < 0) {
                         log_error_errno(r, "Failed to synchronize written files: %m");
@@ -2834,7 +3026,7 @@ static int context_mkfs(Context *context) {
                 if (r < 0)
                         return r;
 
-                r = make_filesystem(fsdev, p->format, p->new_label, fs_uuid, arg_discard);
+                r = make_filesystem(fsdev, p->format, strempty(p->new_label), fs_uuid, arg_discard);
                 if (r < 0) {
                         encrypted_dev_fd = safe_close(encrypted_dev_fd);
                         (void) deactivate_luks(cd, encrypted);
@@ -2848,7 +3040,7 @@ static int context_mkfs(Context *context) {
                         if (flock(encrypted_dev_fd, LOCK_UN) < 0)
                                 return log_error_errno(errno, "Failed to unlock LUKS device: %m");
 
-                r = partition_copy_files(p, fsdev);
+                r = partition_populate(p, fsdev);
                 if (r < 0) {
                         encrypted_dev_fd = safe_close(encrypted_dev_fd);
                         (void) deactivate_luks(cd, encrypted);
@@ -2945,9 +3137,8 @@ static int partition_acquire_uuid(Context *context, Partition *p, sd_id128_t *re
                 if (p == q)
                         continue;
 
-                if (sd_id128_equal(q->current_uuid, result.id) ||
-                    sd_id128_equal(q->new_uuid, result.id)) {
-                        log_warning("Partition UUID calculated from seed for partition %" PRIu64 " exists already, reverting to randomized UUID.", p->partno);
+                if (sd_id128_in_set(result.id, q->current_uuid, q->new_uuid)) {
+                        log_warning("Partition UUID calculated from seed for partition %" PRIu64 " already used, reverting to randomized UUID.", p->partno);
 
                         r = sd_id128_randomize(&result.id);
                         if (r < 0)
@@ -3020,10 +3211,9 @@ static int context_acquire_partition_uuids_and_labels(Context *context) {
                         p->new_uuid = p->current_uuid;
 
                         if (p->current_label) {
-                                free(p->new_label);
-                                p->new_label = strdup(p->current_label);
-                                if (!p->new_label)
-                                        return log_oom();
+                                r = free_and_strdup_warn(&p->new_label, strempty(p->current_label));
+                                if (r < 0)
+                                        return r;
                         }
 
                         continue;
@@ -3039,10 +3229,10 @@ static int context_acquire_partition_uuids_and_labels(Context *context) {
                 }
 
                 if (!isempty(p->current_label)) {
-                        free(p->new_label);
-                        p->new_label = strdup(p->current_label); /* never change initialized labels */
-                        if (!p->new_label)
-                                return log_oom();
+                        /* never change initialized labels */
+                        r = free_and_strdup_warn(&p->new_label, p->current_label);
+                        if (r < 0)
+                                return r;
                 } else if (!p->new_label) {
                         /* Not explicitly set by user! */
 
@@ -3055,6 +3245,56 @@ static int context_acquire_partition_uuids_and_labels(Context *context) {
         return 0;
 }
 
+static int set_gpt_flags(struct fdisk_partition *q, uint64_t flags) {
+        _cleanup_free_ char *a = NULL;
+
+        for (unsigned i = 0; i < sizeof(flags) * 8; i++) {
+                uint64_t bit = UINT64_C(1) << i;
+                char buf[DECIMAL_STR_MAX(unsigned)+1];
+
+                if (!FLAGS_SET(flags, bit))
+                        continue;
+
+                xsprintf(buf, "%u", i);
+                if (!strextend_with_separator(&a, ",", buf))
+                        return -ENOMEM;
+        }
+
+        return fdisk_partition_set_attrs(q, a);
+}
+
+static uint64_t partition_merge_flags(Partition *p) {
+        uint64_t f;
+
+        assert(p);
+
+        f = p->gpt_flags;
+
+        if (p->read_only >= 0) {
+                if (gpt_partition_type_knows_read_only(p->type_uuid))
+                        SET_FLAG(f, GPT_FLAG_READ_ONLY, p->read_only);
+                else {
+                        char buffer[ID128_UUID_STRING_MAX];
+                        log_warning("Configured ReadOnly=%s for partition type '%s' that doesn't support it, ignoring.",
+                                    yes_no(p->read_only),
+                                    gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
+                }
+        }
+
+        if (p->growfs >= 0) {
+                if (gpt_partition_type_knows_growfs(p->type_uuid))
+                        SET_FLAG(f, GPT_FLAG_GROWFS, p->growfs);
+                else {
+                        char buffer[ID128_UUID_STRING_MAX];
+                        log_warning("Configured GrowFileSystem=%s for partition type '%s' that doesn't support it, ignoring.",
+                                    yes_no(p->growfs),
+                                    gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
+                }
+        }
+
+        return f;
+}
+
 static int context_mangle_partitions(Context *context) {
         Partition *p;
         int r;
@@ -3104,9 +3344,7 @@ static int context_mangle_partitions(Context *context) {
                         }
 
                         if (!streq_ptr(p->new_label, p->current_label)) {
-                                assert(!isempty(p->new_label));
-
-                                r = fdisk_partition_set_name(p->current_partition, p->new_label);
+                                r = fdisk_partition_set_name(p->current_partition, strempty(p->new_label));
                                 if (r < 0)
                                         return log_error_errno(r, "Failed to set partition label: %m");
 
@@ -3130,7 +3368,7 @@ static int context_mangle_partitions(Context *context) {
                         assert(p->offset % 512 == 0);
                         assert(p->new_size % 512 == 0);
                         assert(!sd_id128_is_null(p->new_uuid));
-                        assert(!isempty(p->new_label));
+                        assert(p->new_label);
 
                         t = fdisk_new_parttype();
                         if (!t)
@@ -3168,10 +3406,15 @@ static int context_mangle_partitions(Context *context) {
                         if (r < 0)
                                 return log_error_errno(r, "Failed to set partition UUID: %m");
 
-                        r = fdisk_partition_set_name(q, p->new_label);
+                        r = fdisk_partition_set_name(q, strempty(p->new_label));
                         if (r < 0)
                                 return log_error_errno(r, "Failed to set partition label: %m");
 
+                        /* Merge the read only + growfs setting with the literal flags, and set them for the partition */
+                        r = set_gpt_flags(q, partition_merge_flags(p));
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to set GPT partition flags: %m");
+
                         log_info("Adding new partition %" PRIu64 " to partition table.", p->partno);
 
                         r = fdisk_add_partition(context->fdisk_context, q, NULL);
@@ -3383,7 +3626,311 @@ static int context_can_factory_reset(Context *context) {
         return false;
 }
 
-static int context_open_copy_block_paths(Context *context) {
+static int resolve_copy_blocks_auto_candidate(
+                dev_t partition_devno,
+                sd_id128_t partition_type_uuid,
+                dev_t restrict_devno,
+                sd_id128_t *ret_uuid) {
+
+        _cleanup_(blkid_free_probep) blkid_probe b = NULL;
+        _cleanup_free_ char *p = NULL;
+        _cleanup_close_ int fd = -1;
+        const char *pttype, *t;
+        sd_id128_t pt_parsed, u;
+        blkid_partition pp;
+        dev_t whole_devno;
+        blkid_partlist pl;
+        struct stat st;
+        int r;
+
+        /* Checks if the specified partition has the specified GPT type UUID, and is located on the specified
+         * 'restrict_devno' device. The type check is particularly relevant if we have Verity volume which is
+         * backed by two separate partitions: the data and the hash partitions, and we need to find the right
+         * one of the two. */
+
+        r = block_get_whole_disk(partition_devno, &whole_devno);
+        if (r < 0)
+                return log_error_errno(
+                                r,
+                                "Unable to determine containing block device of partition %u:%u: %m",
+                                major(partition_devno), minor(partition_devno));
+
+        if (restrict_devno != (dev_t) -1 &&
+            restrict_devno != whole_devno)
+                return log_error_errno(
+                                SYNTHETIC_ERRNO(EPERM),
+                                "Partition %u:%u is located outside of block device %u:%u, refusing.",
+                                major(partition_devno), minor(partition_devno),
+                                major(restrict_devno), minor(restrict_devno));
+
+        r = device_path_make_major_minor(S_IFBLK, whole_devno, &p);
+        if (r < 0)
+                return log_error_errno(r, "Failed to convert block device to device node path: %m");
+
+        fd = open(p, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
+        if (fd < 0)
+                return log_error_errno(r, "Failed to open '%s': %m", p);
+
+        if (fstat(fd, &st) < 0)
+                return log_error_errno(r, "Failed to stat '%s': %m", p);
+
+        if (!S_ISBLK(st.st_mode) || st.st_rdev != whole_devno)
+                return log_error_errno(
+                                SYNTHETIC_ERRNO(EPERM),
+                                "Opened and determined block device don't match, refusing.");
+
+        b = blkid_new_probe();
+        if (!b)
+                return log_oom();
+
+        errno = 0;
+        r = blkid_probe_set_device(b, fd, 0, 0);
+        if (r != 0)
+                return log_error_errno(errno_or_else(ENOMEM), "Failed to open block device '%s': %m", p);
+
+        (void) blkid_probe_enable_partitions(b, 1);
+        (void) blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
+
+        errno = 0;
+        r = blkid_do_safeprobe(b);
+        if (IN_SET(r, -2, 1)) { /* nothing found or ambiguous result */
+                log_debug("Didn't find partition table on block device '%s'.", p);
+                return false;
+        }
+        if (r != 0)
+                return log_error_errno(errno_or_else(EIO), "Unable to probe for partition table of '%s': %m", p);
+
+        (void) blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
+        if (!streq_ptr(pttype, "gpt")) {
+                log_debug("Didn't find a GPT partition table on '%s'.", p);
+                return false;
+        }
+
+        errno = 0;
+        pl = blkid_probe_get_partitions(b);
+        if (!pl)
+                return log_error_errno(errno_or_else(EIO), "Unable read partition table of '%s': %m", p);
+        errno = 0;
+
+        pp = blkid_partlist_devno_to_partition(pl, partition_devno);
+        if (!pp) {
+                log_debug("Partition %u:%u has no matching partition table entry on '%s'.",
+                          major(partition_devno), minor(partition_devno), p);
+                return false;
+        }
+
+        t = blkid_partition_get_type_string(pp);
+        if (isempty(t)) {
+                log_debug("Partition %u:%u has no type on '%s'.",
+                          major(partition_devno), minor(partition_devno), p);
+                return false;
+        }
+
+        r = sd_id128_from_string(t, &pt_parsed);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to parse partition type \"%s\": %m", t);
+                return false;
+        }
+
+        if (!sd_id128_equal(pt_parsed, partition_type_uuid)) {
+                log_debug("Partition %u:%u has non-matching partition type " SD_ID128_FORMAT_STR " (needed: " SD_ID128_FORMAT_STR "), ignoring.",
+                          major(partition_devno), minor(partition_devno),
+                          SD_ID128_FORMAT_VAL(pt_parsed), SD_ID128_FORMAT_VAL(partition_type_uuid));
+                return false;
+        }
+
+        t = blkid_partition_get_uuid(pp);
+        if (isempty(t)) {
+                log_debug("Partition %u:%u has no UUID.",
+                          major(partition_devno), minor(partition_devno));
+                return false;
+        }
+
+        r = sd_id128_from_string(t, &u);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to parse partition UUID \"%s\": %m", t);
+                return false;
+        }
+
+        log_debug("Automatically found partition %u:%u of right type " SD_ID128_FORMAT_STR ".",
+                  major(partition_devno), minor(partition_devno),
+                  SD_ID128_FORMAT_VAL(pt_parsed));
+
+        if (ret_uuid)
+                *ret_uuid = u;
+
+        return true;
+}
+
+static int find_backing_devno(
+                const char *path,
+                const char *root,
+                dev_t *ret) {
+
+        _cleanup_free_ char *resolved = NULL;
+        int r;
+
+        assert(path);
+
+        r = chase_symlinks(path, root, CHASE_PREFIX_ROOT, &resolved, NULL);
+        if (r < 0)
+                return r;
+
+        r = path_is_mount_point(resolved, NULL, 0);
+        if (r < 0)
+                return r;
+        if (r == 0) /* Not a mount point, then it's not a partition of its own, let's not automatically use it. */
+                return -ENOENT;
+
+        r = get_block_device(resolved, ret);
+        if (r < 0)
+                return r;
+        if (r == 0) /* Not backed by physical file system, we can't use this */
+                return -ENOENT;
+
+        return 0;
+}
+
+static int resolve_copy_blocks_auto(
+                sd_id128_t type_uuid,
+                const char *root,
+                dev_t restrict_devno,
+                char **ret_path,
+                sd_id128_t *ret_uuid) {
+
+        const char *try1 = NULL, *try2 = NULL;
+        char p[SYS_BLOCK_PATH_MAX("/slaves")];
+        _cleanup_(closedirp) DIR *d = NULL;
+        sd_id128_t found_uuid = SD_ID128_NULL;
+        dev_t devno, found = 0;
+        int r;
+
+        assert(ret_path);
+
+        /* Enforce some security restrictions: CopyBlocks=auto should not be an avenue to get outside of the
+         * --root=/--image= confinement. Specifically, refuse CopyBlocks= in combination with --root= at all,
+         * and restrict block device references in the --image= case to loopback block device we set up.
+         *
+         * restrict_devno contain the dev_t of the loop back device we operate on in case of --image=, and
+         * thus declares which device (and its partition subdevices) we shall limit access to. If
+         * restrict_devno is zero no device probing access shall be allowed at all (used for --root=) and if
+         * it is (dev_t) -1 then free access shall be allowed (if neither switch is used). */
+
+        if (restrict_devno == 0)
+                return log_error_errno(SYNTHETIC_ERRNO(EPERM),
+                                       "Automatic discovery of backing block devices not permitted in --root= mode, refusing.");
+
+        /* Handles CopyBlocks=auto, and finds the right source partition to copy from. We look for matching
+         * partitions in the host, using the appropriate directory as key and ensuring that the partition
+         * type matches. */
+
+        if (gpt_partition_type_is_root(type_uuid))
+                try1 = "/";
+        else if (gpt_partition_type_is_usr(type_uuid))
+                try1 = "/usr/";
+        else if (gpt_partition_type_is_root_verity(type_uuid))
+                try1 = "/";
+        else if (gpt_partition_type_is_usr_verity(type_uuid))
+                try1 = "/usr/";
+        else if (sd_id128_equal(type_uuid, GPT_ESP)) {
+                try1 = "/efi/";
+                try2 = "/boot/";
+        } else if (sd_id128_equal(type_uuid, GPT_XBOOTLDR))
+                try1 = "/boot/";
+        else
+                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+                                       "Partition type " SD_ID128_FORMAT_STR " not supported from automatic source block device discovery.",
+                                       SD_ID128_FORMAT_VAL(type_uuid));
+
+        r = find_backing_devno(try1, root, &devno);
+        if (r == -ENOENT && try2)
+                r = find_backing_devno(try2, root, &devno);
+        if (r < 0)
+                return log_error_errno(r, "Failed to resolve automatic CopyBlocks= path for partition type " SD_ID128_FORMAT_STR ", sorry: %m",
+                                       SD_ID128_FORMAT_VAL(type_uuid));
+
+        xsprintf_sys_block_path(p, "/slaves", devno);
+        d = opendir(p);
+        if (d) {
+                struct dirent *de;
+
+                for (;;) {
+                        _cleanup_free_ char *q = NULL, *t = NULL;
+                        sd_id128_t u;
+                        dev_t sl;
+
+                        errno = 0;
+                        de = readdir_no_dot(d);
+                        if (!de) {
+                                if (errno != 0)
+                                        return log_error_errno(errno, "Failed to read directory '%s': %m", p);
+
+                                break;
+                        }
+
+                        if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
+                                continue;
+
+                        q = path_join(p, de->d_name, "/dev");
+                        if (!q)
+                                return log_oom();
+
+                        r = read_one_line_file(q, &t);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to read %s: %m", q);
+
+                        r = parse_dev(t, &sl);
+                        if (r < 0) {
+                                log_debug_errno(r, "Failed to parse %s, ignoring: %m", q);
+                                continue;
+                        }
+                        if (major(sl) == 0) {
+                                log_debug_errno(r, "Device backing %s is special, ignoring: %m", q);
+                                continue;
+                        }
+
+                        r = resolve_copy_blocks_auto_candidate(sl, type_uuid, restrict_devno, &u);
+                        if (r < 0)
+                                return r;
+                        if (r > 0) {
+                                /* We found a matching one! */
+                                if (found != 0)
+                                        return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
+                                                               "Multiple matching partitions found, refusing.");
+
+                                found = sl;
+                                found_uuid = u;
+                        }
+                }
+        } else if (errno != ENOENT)
+                return log_error_errno(errno, "Failed open %s: %m", p);
+        else {
+                r = resolve_copy_blocks_auto_candidate(devno, type_uuid, restrict_devno, &found_uuid);
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        found = devno;
+        }
+
+        if (found == 0)
+                return log_error_errno(SYNTHETIC_ERRNO(ENXIO),
+                                       "Unable to automatically discover suitable partition to copy blocks from.");
+
+        r = device_path_make_major_minor(S_IFBLK, found, ret_path);
+        if (r < 0)
+                return log_error_errno(r, "Failed to convert dev_t to device node path: %m");
+
+        if (ret_uuid)
+                *ret_uuid = found_uuid;
+
+        return 0;
+}
+
+static int context_open_copy_block_paths(
+                Context *context,
+                const char *root,
+                dev_t restrict_devno) {
+
         Partition *p;
         int r;
 
@@ -3391,6 +3938,8 @@ static int context_open_copy_block_paths(Context *context) {
 
         LIST_FOREACH(partitions, p, context->partitions) {
                 _cleanup_close_ int source_fd = -1;
+                _cleanup_free_ char *opened = NULL;
+                sd_id128_t uuid = SD_ID128_NULL;
                 uint64_t size;
                 struct stat st;
 
@@ -3400,15 +3949,38 @@ static int context_open_copy_block_paths(Context *context) {
                 if (PARTITION_EXISTS(p)) /* Never copy over partitions that already exist! */
                         continue;
 
-                if (!p->copy_blocks_path)
-                        continue;
+                if (p->copy_blocks_path) {
+
+                        source_fd = chase_symlinks_and_open(p->copy_blocks_path, root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NONBLOCK, &opened);
+                        if (source_fd < 0)
+                                return log_error_errno(source_fd, "Failed to open '%s': %m", p->copy_blocks_path);
+
+                        if (fstat(source_fd, &st) < 0)
+                                return log_error_errno(errno, "Failed to stat block copy file '%s': %m", opened);
+
+                        if (!S_ISREG(st.st_mode) && restrict_devno != (dev_t) -1)
+                                return log_error_errno(SYNTHETIC_ERRNO(EPERM),
+                                                       "Copying from block device node is not permitted in --image=/--root= mode, refusing.");
+
+                } else if (p->copy_blocks_auto) {
+
+                        r = resolve_copy_blocks_auto(p->type_uuid, root, restrict_devno, &opened, &uuid);
+                        if (r < 0)
+                                return r;
 
-                source_fd = open(p->copy_blocks_path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
-                if (source_fd < 0)
-                        return log_error_errno(errno, "Failed to open block copy file '%s': %m", p->copy_blocks_path);
+                        source_fd = open(opened, O_RDONLY|O_CLOEXEC|O_NOCTTY);
+                        if (source_fd < 0)
+                                return log_error_errno(errno, "Failed to open automatically determined source block copy device '%s': %m", opened);
 
-                if (fstat(source_fd, &st) < 0)
-                        return log_error_errno(errno, "Failed to stat block copy file '%s': %m", p->copy_blocks_path);
+                        if (fstat(source_fd, &st) < 0)
+                                return log_error_errno(errno, "Failed to stat block copy file '%s': %m", opened);
+
+                        /* If we found it automatically, it must be a block device, let's enforce that */
+                        if (!S_ISBLK(st.st_mode))
+                                return log_error_errno(SYNTHETIC_ERRNO(EBADF),
+                                                       "Automatically detected source block copy device '%s' is not a block device, refusing: %m", opened);
+                }  else
+                        continue;
 
                 if (S_ISDIR(st.st_mode)) {
                         _cleanup_free_ char *bdev = NULL;
@@ -3424,14 +3996,14 @@ static int context_open_copy_block_paths(Context *context) {
 
                                 r = btrfs_get_block_device_fd(source_fd, &devt);
                                 if (r == -EUCLEAN)
-                                        return btrfs_log_dev_root(LOG_ERR, r, p->copy_blocks_path);
+                                        return btrfs_log_dev_root(LOG_ERR, r, opened);
                                 if (r < 0)
-                                        return log_error_errno(r, "Unable to determine backing block device of '%s': %m", p->copy_blocks_path);
+                                        return log_error_errno(r, "Unable to determine backing block device of '%s': %m", opened);
 
                                 r = device_path_make_major_minor(S_IFBLK, devt, &bdev);
                         }
                         if (r < 0)
-                                return log_error_errno(r, "Failed to determine block device path for block device backing '%s': %m", p->copy_blocks_path);
+                                return log_error_errno(r, "Failed to determine block device path for block device backing '%s': %m", opened);
 
                         safe_close(source_fd);
 
@@ -3452,15 +4024,21 @@ static int context_open_copy_block_paths(Context *context) {
                         if (ioctl(source_fd, BLKGETSIZE64, &size) != 0)
                                 return log_error_errno(errno, "Failed to determine size of block device to copy from: %m");
                 } else
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified path to copy blocks from '%s' is not a regular file, block device or directory, refusing: %m", p->copy_blocks_path);
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified path to copy blocks from '%s' is not a regular file, block device or directory, refusing: %m", opened);
 
                 if (size <= 0)
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has zero size, refusing.", p->copy_blocks_path);
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has zero size, refusing.", opened);
                 if (size % 512 != 0)
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has size that is not multiple of 512, refusing.", p->copy_blocks_path);
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has size that is not multiple of 512, refusing.", opened);
 
                 p->copy_blocks_fd = TAKE_FD(source_fd);
                 p->copy_blocks_size = size;
+
+                free_and_replace(p->copy_blocks_path, opened);
+
+                /* When copying from an existing partition copy that partitions UUID if none is configured explicitly */
+                if (sd_id128_is_null(p->new_uuid) && !sd_id128_is_null(uuid))
+                        p->new_uuid = uuid;
         }
 
         return 0;
@@ -3489,6 +4067,7 @@ static int help(void) {
                "                          them\n"
                "     --can-factory-reset  Test whether factory reset is defined\n"
                "     --root=PATH          Operate relative to root path\n"
+               "     --image=PATH         Operate relative to image file\n"
                "     --definitions=DIR    Find partition definitions in specified directory\n"
                "     --key-file=PATH      Key to use when encrypting partitions\n"
                "     --tpm2-device=PATH   Path to TPM2 device node to use\n"
@@ -3519,6 +4098,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_FACTORY_RESET,
                 ARG_CAN_FACTORY_RESET,
                 ARG_ROOT,
+                ARG_IMAGE,
                 ARG_SEED,
                 ARG_PRETTY,
                 ARG_DEFINITIONS,
@@ -3540,6 +4120,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "factory-reset",     required_argument, NULL, ARG_FACTORY_RESET     },
                 { "can-factory-reset", no_argument,       NULL, ARG_CAN_FACTORY_RESET },
                 { "root",              required_argument, NULL, ARG_ROOT              },
+                { "image",             required_argument, NULL, ARG_IMAGE             },
                 { "seed",              required_argument, NULL, ARG_SEED              },
                 { "pretty",            required_argument, NULL, ARG_PRETTY            },
                 { "definitions",       required_argument, NULL, ARG_DEFINITIONS       },
@@ -3619,7 +4200,13 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_ROOT:
-                        r = parse_path_argument(optarg, false, &arg_root);
+                        r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_root);
+                        if (r < 0)
+                                return r;
+                        break;
+
+                case ARG_IMAGE:
+                        r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
                         if (r < 0)
                                 return r;
                         break;
@@ -3769,9 +4356,28 @@ static int parse_argv(int argc, char *argv[]) {
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "If --empty=create is specified, --size= must be specified, too.");
 
+        if (arg_image && arg_root)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported.");
+        else if (!arg_image && !arg_root && in_initrd()) {
+
+                /* By default operate on /sysusr/ or /sysroot/ when invoked in the initrd. We prefer the
+                 * former, if it is mounted, so that we have deterministic behaviour on systems where /usr/
+                 * is vendor-supplied but the root fs formatted on first boot. */
+                r = path_is_mount_point("/sysusr/usr", NULL, 0);
+                if (r <= 0) {
+                        if (r < 0 && r != -ENOENT)
+                                log_debug_errno(r, "Unable to determine whether /sysusr/usr is a mount point, assuming it is not: %m");
+
+                        arg_root = strdup("/sysroot");
+                } else
+                        arg_root = strdup("/sysusr");
+                if (!arg_root)
+                        return log_oom();
+        }
+
         arg_node = argc > optind ? argv[optind] : NULL;
 
-        if (IN_SET(arg_empty, EMPTY_FORCE, EMPTY_REQUIRE, EMPTY_CREATE) && !arg_node)
+        if (IN_SET(arg_empty, EMPTY_FORCE, EMPTY_REQUIRE, EMPTY_CREATE) && !arg_node && !arg_image)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "A path to a device node or loopback file must be specified when --empty=force, --empty=require or --empty=create are used.");
 
@@ -3826,7 +4432,7 @@ static int parse_efi_variable_factory_reset(void) {
 
         arg_factory_reset = r;
         if (r)
-                log_notice("Honouring factory reset requested via EFI variable FactoryReset: %m");
+                log_notice("Factory reset requested via EFI variable FactoryReset.");
 
         return 0;
 }
@@ -3844,39 +4450,44 @@ static int remove_efi_variable_factory_reset(void) {
         return 0;
 }
 
-static int acquire_root_devno(const char *p, int mode, char **ret, int *ret_fd) {
+static int acquire_root_devno(
+                const char *p,
+                const char *root,
+                int mode,
+                char **ret,
+                int *ret_fd) {
+
+        _cleanup_free_ char *found_path = NULL;
+        dev_t devno, fd_devno = MODE_INVALID;
         _cleanup_close_ int fd = -1;
         struct stat st;
-        dev_t devno, fd_devno = MODE_INVALID;
         int r;
 
         assert(p);
         assert(ret);
         assert(ret_fd);
 
-        fd = open(p, mode);
+        fd = chase_symlinks_and_open(p, root, CHASE_PREFIX_ROOT, mode, &found_path);
         if (fd < 0)
-                return -errno;
+                return fd;
 
         if (fstat(fd, &st) < 0)
                 return -errno;
 
         if (S_ISREG(st.st_mode)) {
-                char *s;
-
-                s = strdup(p);
-                if (!s)
-                        return log_oom();
-
-                *ret = s;
+                *ret = TAKE_PTR(found_path);
                 *ret_fd = TAKE_FD(fd);
-
                 return 0;
         }
 
-        if (S_ISBLK(st.st_mode))
+        if (S_ISBLK(st.st_mode)) {
+                /* Refuse referencing explicit block devices if a root dir is specified, after all we should
+                 * not be able to leave the image the root path constrains us to. */
+                if (root)
+                        return -EPERM;
+
                 fd_devno = devno = st.st_rdev;
-        else if (S_ISDIR(st.st_mode)) {
+        else if (S_ISDIR(st.st_mode)) {
 
                 devno = st.st_dev;
                 if (major(devno) == 0) {
@@ -3891,7 +4502,9 @@ static int acquire_root_devno(const char *p, int mode, char **ret, int *ret_fd)
 
         /* From dm-crypt to backing partition */
         r = block_get_originating(devno, &devno);
-        if (r < 0)
+        if (r == -ENOENT)
+                log_debug_errno(r, "Device '%s' has no dm-crypt/dm-verity device, no need to look for underlying block device.", p);
+        else if (r < 0)
                 log_debug_errno(r, "Failed to find underlying block device for '%s', ignoring: %m", p);
 
         /* From partition to whole disk containing it */
@@ -3909,8 +4522,43 @@ static int acquire_root_devno(const char *p, int mode, char **ret, int *ret_fd)
         return 0;
 }
 
+static int find_os_prefix(const char **ret) {
+        int r;
+
+        assert(ret);
+
+        /* Searches for the right place to look for the OS root. This is relevant in the initrd: in the
+         * initrd the host OS is typically mounted to /sysroot/ — except in setups where /usr/ is a separate
+         * partition, in which case it is mounted to /sysusr/usr/ before being moved to /sysroot/usr/. */
+
+        if (!in_initrd()) {
+                *ret = NULL; /* no prefix */
+                return 0;
+        }
+
+        r = path_is_mount_point("/sysroot", NULL, 0);
+        if (r < 0 && r != -ENOENT)
+                log_debug_errno(r, "Failed to determine whether /sysroot/ is a mount point, assuming it is not: %m");
+        else if (r > 0) {
+                log_debug("/sysroot/ is a mount point, assuming it's the prefix.");
+                *ret = "/sysroot";
+                return 0;
+        }
+
+        r = path_is_mount_point("/sysusr/usr", NULL, 0);
+        if (r < 0 && r != -ENOENT)
+                log_debug_errno(r, "Failed to determine whether /sysusr/usr is a mount point, assuming it is not: %m");
+        else if (r > 0) {
+                log_debug("/sysusr/usr/ is a mount point, assuming /sysusr/ is the prefix.");
+                *ret = "/sysusr";
+                return 0;
+        }
+
+        return -ENOENT;
+}
+
 static int find_root(char **ret, int *ret_fd) {
-        const char *t;
+        const char *t, *prefix;
         int r;
 
         assert(ret);
@@ -3934,7 +4582,9 @@ static int find_root(char **ret, int *ret_fd) {
                         return 0;
                 }
 
-                r = acquire_root_devno(arg_node, O_RDONLY|O_CLOEXEC, ret, ret_fd);
+                /* Note that we don't specify a root argument here: if the user explicitly configured a node
+                 * we'll take it relative to the host, not the image */
+                r = acquire_root_devno(arg_node, NULL, O_RDONLY|O_CLOEXEC, ret, ret_fd);
                 if (r == -EUCLEAN)
                         return btrfs_log_dev_root(LOG_ERR, r, arg_node);
                 if (r < 0)
@@ -3949,12 +4599,16 @@ static int find_root(char **ret, int *ret_fd) {
          * latter we check for cases where / is a tmpfs and only /usr is an actual persistent block device
          * (think: volatile setups) */
 
+        r = find_os_prefix(&prefix);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine OS prefix: %m");
+
         FOREACH_STRING(t, "/", "/usr") {
                 _cleanup_free_ char *j = NULL;
                 const char *p;
 
-                if (in_initrd()) {
-                        j = path_join("/sysroot", t);
+                if (prefix) {
+                        j = path_join(prefix, t);
                         if (!j)
                                 return log_oom();
 
@@ -3962,7 +4616,7 @@ static int find_root(char **ret, int *ret_fd) {
                 } else
                         p = t;
 
-                r = acquire_root_devno(p, O_RDONLY|O_DIRECTORY|O_CLOEXEC, ret, ret_fd);
+                r = acquire_root_devno(p, arg_root, O_RDONLY|O_DIRECTORY|O_CLOEXEC, ret, ret_fd);
                 if (r < 0) {
                         if (r == -EUCLEAN)
                                 return btrfs_log_dev_root(LOG_ERR, r, p);
@@ -4009,9 +4663,15 @@ static int resize_pt(int fd) {
         return 1;
 }
 
-static int resize_backing_fd(const char *node, int *fd) {
+static int resize_backing_fd(
+                const char *node,           /* The primary way we access the disk image to operate on */
+                int *fd,                    /* An O_RDONLY fd referring to that inode */
+                const char *backing_file,   /* If the above refers to a loopback device, the backing regular file for that, which we can grow */
+                LoopDevice *loop_device) {
+
         char buf1[FORMAT_BYTES_MAX], buf2[FORMAT_BYTES_MAX];
         _cleanup_close_ int writable_fd = -1;
+        uint64_t current_size;
         struct stat st;
         int r;
 
@@ -4032,25 +4692,64 @@ static int resize_backing_fd(const char *node, int *fd) {
         if (fstat(*fd, &st) < 0)
                 return log_error_errno(errno, "Failed to stat '%s': %m", node);
 
-        r = stat_verify_regular(&st);
-        if (r < 0)
-                return log_error_errno(r, "Specified path '%s' is not a regular file, cannot resize: %m", node);
+        if (S_ISBLK(st.st_mode)) {
+                if (!backing_file)
+                        return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Cannot resize block device '%s'.", node);
 
-        assert_se(format_bytes(buf1, sizeof(buf1), st.st_size));
+                assert(loop_device);
+
+                if (ioctl(*fd, BLKGETSIZE64, &current_size) < 0)
+                        return log_error_errno(errno, "Failed to determine size of block device %s: %m", node);
+        } else {
+                r = stat_verify_regular(&st);
+                if (r < 0)
+                        return log_error_errno(r, "Specified path '%s' is not a regular file or loopback block device, cannot resize: %m", node);
+
+                assert(!backing_file);
+                assert(!loop_device);
+                current_size = st.st_size;
+        }
+
+        assert_se(format_bytes(buf1, sizeof(buf1), current_size));
         assert_se(format_bytes(buf2, sizeof(buf2), arg_size));
 
-        if ((uint64_t) st.st_size >= arg_size) {
+        if (current_size >= arg_size) {
                 log_info("File '%s' already is of requested size or larger, not growing. (%s >= %s)", node, buf1, buf2);
                 return 0;
         }
 
-        /* The file descriptor is read-only. In order to grow the file we need to have a writable fd. We
-         * reopen the file for that temporarily. We keep the writable fd only open for this operation though,
-         * as fdisk can't accept it anyway. */
+        if (S_ISBLK(st.st_mode)) {
+                assert(backing_file);
+
+                /* This is a loopback device. We can't really grow those directly, but we can grow the
+                 * backing file, hence let's do that. */
 
-        writable_fd = fd_reopen(*fd, O_WRONLY|O_CLOEXEC);
-        if (writable_fd < 0)
-                return log_error_errno(writable_fd, "Failed to reopen backing file '%s' writable: %m", node);
+                writable_fd = open(backing_file, O_WRONLY|O_CLOEXEC|O_NONBLOCK);
+                if (writable_fd < 0)
+                        return log_error_errno(errno, "Failed to open backing file '%s': %m", backing_file);
+
+                if (fstat(writable_fd, &st) < 0)
+                        return log_error_errno(errno, "Failed to stat() backing file '%s': %m", backing_file);
+
+                r = stat_verify_regular(&st);
+                if (r < 0)
+                        return log_error_errno(r, "Backing file '%s' of block device is not a regular file: %m", backing_file);
+
+                if ((uint64_t) st.st_size != current_size)
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "Size of backing file '%s' of loopback block device '%s' don't match, refusing.", node, backing_file);
+        } else {
+                assert(S_ISREG(st.st_mode));
+                assert(!backing_file);
+
+                /* The file descriptor is read-only. In order to grow the file we need to have a writable fd. We
+                 * reopen the file for that temporarily. We keep the writable fd only open for this operation though,
+                 * as fdisk can't accept it anyway. */
+
+                writable_fd = fd_reopen(*fd, O_WRONLY|O_CLOEXEC);
+                if (writable_fd < 0)
+                        return log_error_errno(writable_fd, "Failed to reopen backing file '%s' writable: %m", node);
+        }
 
         if (!arg_discard) {
                 if (fallocate(writable_fd, 0, 0, arg_size) < 0) {
@@ -4061,16 +4760,12 @@ static int resize_backing_fd(const char *node, int *fd) {
                         /* Fallback to truncation, if fallocate() is not supported. */
                         log_debug("Backing file system does not support fallocate(), falling back to ftruncate().");
                 } else {
-                        r = resize_pt(writable_fd);
-                        if (r < 0)
-                                return r;
-
-                        if (st.st_size == 0) /* Likely regular file just created by us */
+                        if (current_size == 0) /* Likely regular file just created by us */
                                 log_info("Allocated %s for '%s'.", buf2, node);
                         else
                                 log_info("File '%s' grown from %s to %s by allocation.", node, buf1, buf2);
 
-                        return 1;
+                        goto done;
                 }
         }
 
@@ -4078,14 +4773,21 @@ static int resize_backing_fd(const char *node, int *fd) {
                 return log_error_errno(errno, "Failed to grow '%s' from %s to %s by truncation: %m",
                                        node, buf1, buf2);
 
+        if (current_size == 0) /* Likely regular file just created by us */
+                log_info("Sized '%s' to %s.", node, buf2);
+        else
+                log_info("File '%s' grown from %s to %s by truncation.", node, buf1, buf2);
+
+done:
         r = resize_pt(writable_fd);
         if (r < 0)
                 return r;
 
-        if (st.st_size == 0) /* Likely regular file just created by us */
-                log_info("Sized '%s' to %s.", node, buf2);
-        else
-                log_info("File '%s' grown from %s to %s by truncation.", node, buf1, buf2);
+        if (loop_device) {
+                r = loop_device_refresh_size(loop_device, UINT64_MAX, arg_size);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to update loop device size: %m");
+        }
 
         return 1;
 }
@@ -4096,8 +4798,6 @@ static int determine_auto_size(Context *c) {
         Partition *p;
 
         assert_se(c);
-        assert_se(arg_size == UINT64_MAX);
-        assert_se(arg_size_auto);
 
         LIST_FOREACH(partitions, p, c->partitions) {
                 uint64_t m;
@@ -4120,23 +4820,19 @@ static int determine_auto_size(Context *c) {
 }
 
 static int run(int argc, char *argv[]) {
+        _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
+        _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
+        _cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL;
         _cleanup_(context_freep) Context* context = NULL;
         _cleanup_free_ char *node = NULL;
         _cleanup_close_ int backing_fd = -1;
-        bool from_scratch;
+        bool from_scratch, node_is_our_loop = false;
         int r;
 
         log_show_color(true);
         log_parse_environment();
         log_open();
 
-        if (in_initrd()) {
-                /* Default to operation on /sysroot when invoked in the initrd! */
-                arg_root = strdup("/sysroot");
-                if (!arg_root)
-                        return log_oom();
-        }
-
         r = parse_argv(argc, argv);
         if (r <= 0)
                 return r;
@@ -4149,6 +4845,40 @@ static int run(int argc, char *argv[]) {
         if (r < 0)
                 return r;
 
+        if (arg_image) {
+                assert(!arg_root);
+
+                /* Mount this strictly read-only: we shall modify the partition table, not the file
+                 * systems */
+                r = mount_image_privately_interactively(
+                                arg_image,
+                                DISSECT_IMAGE_MOUNT_READ_ONLY |
+                                (arg_node ? DISSECT_IMAGE_DEVICE_READ_ONLY : 0) | /* If a different node to make changes to is specified let's open the device in read-only mode) */
+                                DISSECT_IMAGE_GPT_ONLY |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                DISSECT_IMAGE_USR_NO_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT,
+                                &mounted_dir,
+                                &loop_device,
+                                &decrypted_image);
+                if (r < 0)
+                        return r;
+
+                arg_root = strdup(mounted_dir);
+                if (!arg_root)
+                        return log_oom();
+
+                if (!arg_node) {
+                        arg_node = strdup(loop_device->node);
+                        if (!arg_node)
+                                return log_oom();
+
+                        /* Remember that the the device we are about to manipulate is actually the one we
+                         * allocated here, and thus to increase its backing file we know what to do */
+                        node_is_our_loop = true;
+                }
+        }
+
         context = context_new(arg_seed);
         if (!context)
                 return log_oom();
@@ -4167,7 +4897,11 @@ static int run(int argc, char *argv[]) {
                 return r;
 
         if (arg_size != UINT64_MAX) {
-                r = resize_backing_fd(node, &backing_fd);
+                r = resize_backing_fd(
+                                node,
+                                &backing_fd,
+                                node_is_our_loop ? arg_image : NULL,
+                                node_is_our_loop ? loop_device : NULL);
                 if (r < 0)
                         return r;
         }
@@ -4216,7 +4950,12 @@ static int run(int argc, char *argv[]) {
                 return r;
 
         /* Open all files to copy blocks from now, since we want to take their size into consideration */
-        r = context_open_copy_block_paths(context);
+        r = context_open_copy_block_paths(
+                        context,
+                        arg_root,
+                        loop_device ? loop_device->devno :         /* if --image= is specified, only allow partitions on the loopback device*/
+                                      arg_root && !arg_image ? 0 : /* if --root= is specified, don't accept any block device */
+                                      (dev_t) -1);                 /* if neither is specified, make no restrictions */
         if (r < 0)
                 return r;
 
@@ -4229,7 +4968,11 @@ static int run(int argc, char *argv[]) {
                 context_unload_partition_table(context);
 
                 assert_se(arg_size != UINT64_MAX);
-                r = resize_backing_fd(node, &backing_fd);
+                r = resize_backing_fd(
+                                node,
+                                &backing_fd,
+                                node_is_our_loop ? arg_image : NULL,
+                                node_is_our_loop ? loop_device : NULL);
                 if (r < 0)
                         return r;
 
@@ -4243,9 +4986,13 @@ static int run(int argc, char *argv[]) {
                 if (context_allocate_partitions(context))
                         break; /* Success! */
 
-                if (!context_drop_one_priority(context))
-                        return log_error_errno(SYNTHETIC_ERRNO(ENOSPC),
-                                               "Can't fit requested partitions into free space, refusing.");
+                if (!context_drop_one_priority(context)) {
+                        r = log_error_errno(SYNTHETIC_ERRNO(ENOSPC),
+                                            "Can't fit requested partitions into free space, refusing.");
+
+                        determine_auto_size(context);
+                        return r;
+                }
         }
 
         /* Now assign free space according to the weight logic */
index d21865dd6470d4b8b7418e0b1e968fb29732e5ef..525be8e56ad204d3746c119fc0d3ce7a620f1ab4 100755 (executable)
@@ -1,25 +1,28 @@
 #!/usr/bin/env bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
-set -ex
+set -eux
+set -o pipefail
 
 [[ -e /dev/loop-control ]] || exit 77
 
-repart=$1
-test -x $repart
+repart="${1:?}"
+test -x "$repart"
 
-D=$(mktemp --tmpdir --directory "test-repart.XXXXXXXXXX")
+D="$(mktemp --tmpdir --directory "test-repart.XXXXXXXXXX")"
+
+# shellcheck disable=SC2064
 trap "rm -rf '$D'" EXIT INT QUIT PIPE
-mkdir -p $D/definitions
+mkdir -p "$D/definitions"
 
 SEED=e2a40bf9-73f1-4278-9160-49c031e7aef8
 
 echo "### Testing systemd-repart --empty=create ###"
 
-$repart $D/zzz --empty=create --size=1G --seed=$SEED
+"$repart" "$D/zzz" --empty=create --size=1G --seed="$SEED"
 
-sfdisk -d $D/zzz | grep -v -e 'sector-size' -e '^$' >$D/empty
+sfdisk -d "$D/zzz" | grep -v -e 'sector-size' -e '^$' >"$D/empty"
 
-cmp $D/empty - <<EOF
+cmp "$D/empty" - <<EOF
 label: gpt
 label-id: EF7F7EE2-47B3-4251-B1A1-09EA8BF12D5D
 device: $D/zzz
@@ -30,105 +33,105 @@ EOF
 
 echo "### Testing with root, root2, home, & swap ###"
 
-cat >$D/definitions/root.conf <<EOF
+cat >"$D/definitions/root.conf" <<EOF
 [Partition]
 Type=root-x86-64
 EOF
 
-ln -s root.conf $D/definitions/root2.conf
+ln -s root.conf "$D/definitions/root2.conf"
 
-cat >$D/definitions/home.conf <<EOF
+cat >"$D/definitions/home.conf" <<EOF
 [Partition]
 Type=home
 Label=home-first
 Label=home-always-too-long-xxxxxxxxxxxxxx-%v
 EOF
 
-cat >$D/definitions/swap.conf <<EOF
+cat >"$D/definitions/swap.conf" <<EOF
 [Partition]
 Type=swap
 SizeMaxBytes=64M
 PaddingMinBytes=92M
 EOF
 
-$repart $D/zzz --dry-run=no --seed=$SEED --definitions=$D/definitions
+"$repart" "$D/zzz" --dry-run=no --seed="$SEED" --definitions="$D/definitions"
 
-sfdisk -d $D/zzz | grep -v -e 'sector-size' -e '^$' >$D/populated
+sfdisk -d "$D/zzz" | grep -v -e 'sector-size' -e '^$' >"$D/populated"
 
-cmp $D/populated - <<EOF
+cmp "$D/populated" - <<EOF
 label: gpt
 label-id: EF7F7EE2-47B3-4251-B1A1-09EA8BF12D5D
 device: $D/zzz
 unit: sectors
 first-lba: 2048
 last-lba: 2097118
-$D/zzz1 : start=        2048, size=      591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
-$D/zzz2 : start=      593904, size=      591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
-$D/zzz3 : start=     1185760, size=      591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
+$D/zzz1 : start=        2048, size=      591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
+$D/zzz2 : start=      593904, size=      591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
+$D/zzz3 : start=     1185760, size=      591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
 $D/zzz4 : start=     1777624, size=      131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
 EOF
 
 echo "### Testing with root, root2, home, swap, & another partition ###"
 
-cat >$D/definitions/swap.conf <<EOF
+cat >"$D/definitions/swap.conf" <<EOF
 [Partition]
 Type=swap
 SizeMaxBytes=64M
 EOF
 
-cat >$D/definitions/extra.conf <<EOF
+cat >"$D/definitions/extra.conf" <<EOF
 [Partition]
 Type=linux-generic
 Label=custom_label
 UUID=a0a1a2a3a4a5a6a7a8a9aaabacadaeaf
 EOF
 
-echo "Label=ignored_label" >>$D/definitions/home.conf
-echo "UUID=b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" >>$D/definitions/home.conf
+echo "Label=ignored_label" >>"$D/definitions/home.conf"
+echo "UUID=b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" >>"$D/definitions/home.conf"
 
-$repart $D/zzz --dry-run=no --seed=$SEED --definitions=$D/definitions
+"$repart" "$D/zzz" --dry-run=no --seed="$SEED" --definitions="$D/definitions"
 
-sfdisk -d $D/zzz | grep -v -e 'sector-size' -e '^$' >$D/populated2
+sfdisk -d "$D/zzz" | grep -v -e 'sector-size' -e '^$' >"$D/populated2"
 
-cmp $D/populated2 - <<EOF
+cmp "$D/populated2" - <<EOF
 label: gpt
 label-id: EF7F7EE2-47B3-4251-B1A1-09EA8BF12D5D
 device: $D/zzz
 unit: sectors
 first-lba: 2048
 last-lba: 2097118
-$D/zzz1 : start=        2048, size=      591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
-$D/zzz2 : start=      593904, size=      591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
-$D/zzz3 : start=     1185760, size=      591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
+$D/zzz1 : start=        2048, size=      591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
+$D/zzz2 : start=      593904, size=      591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
+$D/zzz3 : start=     1185760, size=      591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
 $D/zzz4 : start=     1777624, size=      131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
 $D/zzz5 : start=     1908696, size=      188416, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
 EOF
 
 echo "### Resizing to 2G ###"
 
-$repart $D/zzz --size=2G --dry-run=no --seed=$SEED --definitions=$D/definitions
+"$repart" "$D/zzz" --size=2G --dry-run=no --seed="$SEED" --definitions="$D/definitions"
 
-sfdisk -d $D/zzz | grep -v -e 'sector-size' -e '^$' >$D/populated3
+sfdisk -d "$D/zzz" | grep -v -e 'sector-size' -e '^$' >"$D/populated3"
 
-cmp $D/populated3 - <<EOF
+cmp "$D/populated3" - <<EOF
 label: gpt
 label-id: EF7F7EE2-47B3-4251-B1A1-09EA8BF12D5D
 device: $D/zzz
 unit: sectors
 first-lba: 2048
 last-lba: 4194270
-$D/zzz1 : start=        2048, size=      591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
-$D/zzz2 : start=      593904, size=      591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
-$D/zzz3 : start=     1185760, size=      591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
+$D/zzz1 : start=        2048, size=      591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
+$D/zzz2 : start=      593904, size=      591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
+$D/zzz3 : start=     1185760, size=      591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
 $D/zzz4 : start=     1777624, size=      131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
 $D/zzz5 : start=     1908696, size=     2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
 EOF
 
-dd if=/dev/urandom of=$D/block-copy bs=4096 count=10240
+dd if=/dev/urandom of="$D/block-copy" bs=4096 count=10240
 
 echo "### Testing with root, root2, home, swap, another partition, & partition copy ###"
 
-cat >$D/definitions/extra2.conf <<EOF
+cat >"$D/definitions/extra2.conf" <<EOF
 [Partition]
 Type=linux-generic
 Label=block-copy
@@ -136,33 +139,33 @@ UUID=2a1d97e1d0a346cca26eadc643926617
 CopyBlocks=$D/block-copy
 EOF
 
-$repart $D/zzz --size=3G --dry-run=no --seed=$SEED --definitions=$D/definitions
+"$repart" "$D/zzz" --size=3G --dry-run=no --seed="$SEED" --definitions="$D/definitions"
 
-sfdisk -d $D/zzz | grep -v -e 'sector-size' -e '^$' >$D/populated4
+sfdisk -d "$D/zzz" | grep -v -e 'sector-size' -e '^$' >"$D/populated4"
 
-cmp $D/populated4 - <<EOF
+cmp "$D/populated4" - <<EOF
 label: gpt
 label-id: EF7F7EE2-47B3-4251-B1A1-09EA8BF12D5D
 device: $D/zzz
 unit: sectors
 first-lba: 2048
 last-lba: 6291422
-$D/zzz1 : start=        2048, size=      591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
-$D/zzz2 : start=      593904, size=      591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
-$D/zzz3 : start=     1185760, size=      591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
+$D/zzz1 : start=        2048, size=      591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
+$D/zzz2 : start=      593904, size=      591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
+$D/zzz3 : start=     1185760, size=      591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
 $D/zzz4 : start=     1777624, size=      131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
 $D/zzz5 : start=     1908696, size=     2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
 $D/zzz6 : start=     4194264, size=     2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name="block-copy"
 EOF
 
-cmp --bytes=41943040 --ignore-initial=0:$((512*4194264)) $D/block-copy $D/zzz
+cmp --bytes=41943040 --ignore-initial=0:$((512*4194264)) "$D/block-copy" "$D/zzz"
 
-if [ `id -u` == 0 ] && type -P cryptsetup diff losetup > /dev/null ; then
+if [ "$(id -u)" -eq 0 ] && type -P cryptsetup diff losetup >/dev/null ; then
     echo "### Testing Format=/Encrypt=/CopyFiles="
 
     # These tests require privileges unfortunately
 
-    cat >$D/definitions/extra3.conf <<EOF
+    cat >"$D/definitions/extra3.conf" <<EOF
 [Partition]
 Type=linux-generic
 Label=luks-format-copy
@@ -173,42 +176,43 @@ CopyFiles=$D/definitions:/def
 SizeMinBytes=48M
 EOF
 
-    $repart $D/zzz --size=auto --dry-run=no --seed=$SEED --definitions=$D/definitions
+    "$repart" "$D/zzz" --size=auto --dry-run=no --seed="$SEED" --definitions="$D/definitions"
 
-    sfdisk -d $D/zzz | grep -v -e 'sector-size' -e '^$' >$D/populated5
+    sfdisk -d "$D/zzz" | grep -v -e 'sector-size' -e '^$' >"$D/populated5"
 
-    cmp $D/populated5 - <<EOF
+    cmp "$D/populated5" - <<EOF
 label: gpt
 label-id: EF7F7EE2-47B3-4251-B1A1-09EA8BF12D5D
 device: $D/zzz
 unit: sectors
 first-lba: 2048
 last-lba: 6389726
-$D/zzz1 : start=        2048, size=      591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first"
-$D/zzz2 : start=      593904, size=      591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64"
-$D/zzz3 : start=     1185760, size=      591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2"
+$D/zzz1 : start=        2048, size=      591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
+$D/zzz2 : start=      593904, size=      591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
+$D/zzz3 : start=     1185760, size=      591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
 $D/zzz4 : start=     1777624, size=      131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
 $D/zzz5 : start=     1908696, size=     2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
 $D/zzz6 : start=     4194264, size=     2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name="block-copy"
 $D/zzz7 : start=     6291416, size=       98304, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=7B93D1F2-595D-4CE3-B0B9-837FBD9E63B0, name="luks-format-copy"
 EOF
 
-    LOOP=`losetup -P --show --find $D/zzz`
-    VOLUME=test-repart-$RANDOM
-
-    touch $D/empty-password
-    cryptsetup open --type=luks2 --key-file=$D/empty-password ${LOOP}p7 $VOLUME
-    mkdir $D/mount
-    mount -t ext4 /dev/mapper/$VOLUME $D/mount
-    diff -r $D/mount/def $D/definitions > /dev/null
-    umount $D/mount
-    cryptsetup close $VOLUME
-    losetup -d $LOOP
+    LOOP="$(losetup -P --show --find "$D/zzz")"
+    VOLUME="test-repart-$RANDOM"
+
+    touch "$D/empty-password"
+    cryptsetup open --type=luks2 --key-file="$D/empty-password" "${LOOP}p7" "$VOLUME"
+    mkdir "$D/mount"
+    mount -t ext4 "/dev/mapper/$VOLUME" "$D/mount"
+    # Use deferred closing on the mapper and autoclear on the loop, so they are cleaned up on umount
+    cryptsetup close --deferred "$VOLUME"
+    losetup -d "$LOOP"
+    diff -r "$D/mount/def" "$D/definitions" >/dev/null
+    umount "$D/mount"
 else
     echo "### Skipping Format=/Encrypt=/CopyFiles= test, lacking privileges or missing cryptsetup/diff/losetup"
 fi
 
 echo "### Testing json output ###"
-$repart $D/zzz --size=3G --dry-run=no --seed=$SEED --definitions=$D/definitions --json=help
-$repart $D/zzz --size=3G --dry-run=no --seed=$SEED --definitions=$D/definitions --json=pretty
-$repart $D/zzz --size=3G --dry-run=no --seed=$SEED --definitions=$D/definitions --json=short
+"$repart" "$D/zzz" --size=3G --dry-run=no --seed="$SEED" --definitions="$D/definitions" --json=help
+"$repart" "$D/zzz" --size=3G --dry-run=no --seed="$SEED" --definitions="$D/definitions" --json=pretty
+"$repart" "$D/zzz" --size=3G --dry-run=no --seed="$SEED" --definitions="$D/definitions" --json=short
index 6c09e8bbd4f61eea68e54e69d272bf3434dbe7ad..53c4d8e25b02fcf9873ce66a250dd0dbf8735ce1 100644 (file)
@@ -11,6 +11,7 @@
 #include "discover-image.h"
 #include "dissect-image.h"
 #include "errno-list.h"
+#include "escape.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
@@ -74,17 +75,26 @@ static bool unit_match(const char *unit, char **matches) {
         return false;
 }
 
-static PortableMetadata *portable_metadata_new(const char *name, int fd) {
+static PortableMetadata *portable_metadata_new(const char *name, const char *path, int fd) {
         PortableMetadata *m;
 
         m = malloc0(offsetof(PortableMetadata, name) + strlen(name) + 1);
         if (!m)
                 return NULL;
 
+        /* In case of a layered attach, we want to remember which image the unit came from */
+        if (path) {
+                m->image_path = strdup(path);
+                if (!m->image_path) {
+                        free(m);
+                        return NULL;
+                }
+        }
+
         strcpy(m->name, name);
         m->fd = fd;
 
-        return m;
+        return TAKE_PTR(m);
 }
 
 PortableMetadata *portable_metadata_unref(PortableMetadata *i) {
@@ -93,6 +103,7 @@ PortableMetadata *portable_metadata_unref(PortableMetadata *i) {
 
         safe_close(i->fd);
         free(i->source);
+        free(i->image_path);
 
         return mfree(i);
 }
@@ -255,7 +266,7 @@ static int extract_now(
                 }
 
                 if (ret_os_release) {
-                        os_release = portable_metadata_new("/etc/os-release", os_release_fd);
+                        os_release = portable_metadata_new("/etc/os-release", NULL, os_release_fd);
                         if (!os_release)
                                 return -ENOMEM;
 
@@ -316,7 +327,7 @@ static int extract_now(
                                         return log_debug_errno(r, "Failed to send unit metadata to parent: %m");
                         }
 
-                        m = portable_metadata_new(de->d_name, fd);
+                        m = portable_metadata_new(de->d_name, NULL, fd);
                         if (!m)
                                 return -ENOMEM;
                         fd = -1;
@@ -342,6 +353,7 @@ static int extract_now(
 
 static int portable_extract_by_path(
                 const char *path,
+                bool extract_os_release,
                 char **matches,
                 PortableMetadata **ret_os_release,
                 Hashmap **ret_unit_files,
@@ -364,7 +376,7 @@ static int portable_extract_by_path(
                         return r;
 
         } else if (r < 0)
-                return log_debug_errno(r, "Failed to set up loopback device: %m");
+                return log_debug_errno(r, "Failed to set up loopback device for %s: %m", path);
         else {
                 _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
                 _cleanup_(rmdir_and_freep) char *tmpdir = NULL;
@@ -380,7 +392,18 @@ static int portable_extract_by_path(
                 if (r < 0)
                         return log_debug_errno(r, "Failed to create temporary directory: %m");
 
-                r = dissect_image(d->fd, NULL, NULL, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK, &m);
+                r = dissect_image(
+                                d->fd,
+                                NULL, NULL,
+                                d->uevent_seqnum_not_before,
+                                d->timestamp_not_before,
+                                DISSECT_IMAGE_READ_ONLY |
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_DISCARD_ON_LOOP |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                DISSECT_IMAGE_USR_NO_ROOT,
+                                &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)
@@ -403,7 +426,7 @@ static int portable_extract_by_path(
                 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);
+                        r = dissected_image_mount(m, tmpdir, UID_INVALID, DISSECT_IMAGE_READ_ONLY);
                         if (r < 0) {
                                 log_debug_errno(r, "Failed to mount dissected image: %m");
                                 goto child_finish;
@@ -439,7 +462,7 @@ static int portable_extract_by_path(
                                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
                                                        "Invalid item sent from child.");
 
-                        add = portable_metadata_new(name, fd);
+                        add = portable_metadata_new(name, path, fd);
                         if (!add)
                                 return -ENOMEM;
                         fd = -1;
@@ -469,10 +492,12 @@ static int portable_extract_by_path(
                 child = 0;
         }
 
-        if (!os_release)
+        /* When the portable image is layered, the image with units will not
+         * have a full filesystem, so no os-release - it will be in the root layer */
+        if (extract_os_release && !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))
+        if (!extract_os_release && 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)
@@ -487,11 +512,16 @@ static int portable_extract_by_path(
 int portable_extract(
                 const char *name_or_path,
                 char **matches,
+                char **extension_image_paths,
                 PortableMetadata **ret_os_release,
                 Hashmap **ret_unit_files,
                 sd_bus_error *error) {
 
+        _cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
+        _cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL;
+        _cleanup_hashmap_free_ Hashmap *unit_files = NULL;
         _cleanup_(image_unrefp) Image *image = NULL;
+        Image *ext;
         int r;
 
         assert(name_or_path);
@@ -500,7 +530,46 @@ int portable_extract(
         if (r < 0)
                 return r;
 
-        return portable_extract_by_path(image->path, matches, ret_os_release, ret_unit_files, error);
+        if (!strv_isempty(extension_image_paths)) {
+                char **p;
+
+                extension_images = ordered_hashmap_new(&image_hash_ops);
+                if (!extension_images)
+                        return -ENOMEM;
+
+                STRV_FOREACH(p, extension_image_paths) {
+                        _cleanup_(image_unrefp) Image *new = NULL;
+
+                        r = image_find_harder(IMAGE_PORTABLE, *p, NULL, &new);
+                        if (r < 0)
+                                return r;
+
+                        r = ordered_hashmap_put(extension_images, new->name, new);
+                        if (r < 0)
+                                return r;
+                        TAKE_PTR(new);
+                }
+        }
+
+        r = portable_extract_by_path(image->path, true, matches, &os_release, &unit_files, error);
+        if (r < 0)
+                return r;
+
+        ORDERED_HASHMAP_FOREACH(ext, extension_images) {
+                _cleanup_hashmap_free_ Hashmap *extra_unit_files = NULL;
+
+                r = portable_extract_by_path(ext->path, false, matches, NULL, &extra_unit_files, error);
+                if (r < 0)
+                        return r;
+                r = hashmap_move(unit_files, extra_unit_files);
+                if (r < 0)
+                        return r;
+        }
+
+        *ret_os_release = TAKE_PTR(os_release);
+        *ret_unit_files = TAKE_PTR(unit_files);
+
+        return 0;
 }
 
 static int unit_file_is_active(
@@ -675,9 +744,49 @@ void portable_changes_free(PortableChange *changes, size_t n_changes) {
         free(changes);
 }
 
+static const char *root_setting_from_image(ImageType type) {
+        return IN_SET(type, IMAGE_DIRECTORY, IMAGE_SUBVOLUME) ? "RootDirectory=" : "RootImage=";
+}
+
+static int make_marker_text(const char *image_path, OrderedHashmap *extension_images, char **ret_text) {
+        _cleanup_free_ char *text = NULL, *escaped_image_path = NULL;
+        Image *ext;
+
+        assert(image_path);
+        assert(ret_text);
+
+        escaped_image_path = xescape(image_path, ":");
+        if (!escaped_image_path)
+                return -ENOMEM;
+
+        /* If the image is layered, include all layers in the marker as a colon-separated
+         * list of paths, so that we can do exact matches on removal. */
+        text = strjoin(PORTABLE_DROPIN_MARKER_BEGIN, escaped_image_path);
+        if (!text)
+                return -ENOMEM;
+
+        ORDERED_HASHMAP_FOREACH(ext, extension_images) {
+                _cleanup_free_ char *escaped = NULL;
+
+                escaped = xescape(ext->path, ":");
+                if (!escaped)
+                        return -ENOMEM;
+
+                if (!strextend(&text, ":", escaped))
+                        return -ENOMEM;
+        }
+
+        if (!strextend(&text, PORTABLE_DROPIN_MARKER_END "\n"))
+                return -ENOMEM;
+
+        *ret_text = TAKE_PTR(text);
+        return 0;
+}
+
 static int install_chroot_dropin(
                 const char *image_path,
                 ImageType type,
+                OrderedHashmap *extension_images,
                 const PortableMetadata *m,
                 const char *dropin_dir,
                 char **ret_dropin,
@@ -685,6 +794,7 @@ static int install_chroot_dropin(
                 size_t *n_changes) {
 
         _cleanup_free_ char *text = NULL, *dropin = NULL;
+        Image *ext;
         int r;
 
         assert(image_path);
@@ -695,12 +805,15 @@ static int install_chroot_dropin(
         if (!dropin)
                 return -ENOMEM;
 
-        text = strjoin(PORTABLE_DROPIN_MARKER_BEGIN, image_path, PORTABLE_DROPIN_MARKER_END "\n");
-        if (!text)
-                return -ENOMEM;
+        r = make_marker_text(image_path, extension_images, &text);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to generate marker string for portable drop-in: %m");
 
         if (endswith(m->name, ".service")) {
-                const char *os_release_source;
+                const char *os_release_source, *root_type;
+                _cleanup_free_ char *base_name = NULL;
+
+                root_type = root_setting_from_image(type);
 
                 if (access("/etc/os-release", F_OK) < 0) {
                         if (errno != ENOENT)
@@ -710,14 +823,23 @@ static int install_chroot_dropin(
                 } else
                         os_release_source = "/etc/os-release";
 
+                r = path_extract_filename(m->image_path ?: image_path, &base_name);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to extract basename from '%s': %m", m->image_path ?: image_path);
+
                 if (!strextend(&text,
                                "\n"
                                "[Service]\n",
-                               IN_SET(type, IMAGE_DIRECTORY, IMAGE_SUBVOLUME) ? "RootDirectory=" : "RootImage=", image_path, "\n"
-                               "Environment=PORTABLE=", basename(image_path), "\n"
+                               root_type, image_path, "\n"
+                               "Environment=PORTABLE=", base_name, "\n"
                                "BindReadOnlyPaths=", os_release_source, ":/run/host/os-release\n"
-                               "LogExtraFields=PORTABLE=", basename(image_path), "\n"))
+                               "LogExtraFields=PORTABLE=", base_name, "\n"))
                         return -ENOMEM;
+
+                if (m->image_path && !path_equal(m->image_path, image_path))
+                        ORDERED_HASHMAP_FOREACH(ext, extension_images)
+                                if (!strextend(&text, "ExtensionImages=", ext->path, "\n"))
+                                        return -ENOMEM;
         }
 
         r = write_string_file(dropin, text, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
@@ -741,7 +863,7 @@ static int find_profile(const char *name, const char *unit, char **ret) {
         assert_se(dot = strrchr(unit, '.'));
 
         NULSTR_FOREACH(p, profile_dirs) {
-                _cleanup_free_ char *joined;
+                _cleanup_free_ char *joined = NULL;
 
                 joined = strjoin(p, "/", name, "/", dot + 1, ".conf");
                 if (!joined)
@@ -832,6 +954,7 @@ static int attach_unit_file(
                 const LookupPaths *paths,
                 const char *image_path,
                 ImageType type,
+                OrderedHashmap *extension_images,
                 const PortableMetadata *m,
                 const char *profile,
                 PortableFlags flags,
@@ -872,7 +995,7 @@ static int attach_unit_file(
          * 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);
+        r = install_chroot_dropin(image_path, type, extension_images, m, dropin_dir, &chroot_dropin, changes, n_changes);
         if (r < 0)
                 return r;
 
@@ -975,20 +1098,49 @@ static int install_image_symlink(
         return 0;
 }
 
+static int install_image_and_extensions_symlinks(
+                const Image *image,
+                OrderedHashmap *extension_images,
+                PortableFlags flags,
+                PortableChange **changes,
+                size_t *n_changes) {
+
+        Image *ext;
+        int r;
+
+        assert(image);
+
+        ORDERED_HASHMAP_FOREACH(ext, extension_images) {
+                r = install_image_symlink(ext->path, flags, changes, n_changes);
+                if (r < 0)
+                        return r;
+        }
+
+        r = install_image_symlink(image->path, flags, changes, n_changes);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
 int portable_attach(
                 sd_bus *bus,
                 const char *name_or_path,
                 char **matches,
                 const char *profile,
+                char **extension_image_paths,
                 PortableFlags flags,
                 PortableChange **changes,
                 size_t *n_changes,
                 sd_bus_error *error) {
 
+        _cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL;
         _cleanup_hashmap_free_ Hashmap *unit_files = NULL;
         _cleanup_(lookup_paths_free) LookupPaths paths = {};
         _cleanup_(image_unrefp) Image *image = NULL;
         PortableMetadata *item;
+        Image *ext;
+        char **p;
         int r;
 
         assert(name_or_path);
@@ -996,11 +1148,40 @@ int portable_attach(
         r = image_find_harder(IMAGE_PORTABLE, name_or_path, NULL, &image);
         if (r < 0)
                 return r;
+        if (!strv_isempty(extension_image_paths)) {
+                extension_images = ordered_hashmap_new(&image_hash_ops);
+                if (!extension_images)
+                        return -ENOMEM;
+
+                STRV_FOREACH(p, extension_image_paths) {
+                        _cleanup_(image_unrefp) Image *new = NULL;
+
+                        r = image_find_harder(IMAGE_PORTABLE, *p, NULL, &new);
+                        if (r < 0)
+                                return r;
+
+                        r = ordered_hashmap_put(extension_images, new->name, new);
+                        if (r < 0)
+                                return r;
+                        TAKE_PTR(new);
+                }
+        }
 
-        r = portable_extract_by_path(image->path, matches, NULL, &unit_files, error);
+        r = portable_extract_by_path(image->path, true, matches, NULL, &unit_files, error);
         if (r < 0)
                 return r;
 
+        ORDERED_HASHMAP_FOREACH(ext, extension_images) {
+                _cleanup_hashmap_free_ Hashmap *extra_unit_files = NULL;
+
+                r = portable_extract_by_path(ext->path, false, matches, NULL, &extra_unit_files, error);
+                if (r < 0)
+                        return r;
+                r = hashmap_move(unit_files, extra_unit_files);
+                if (r < 0)
+                        return r;
+        }
+
         r = lookup_paths_init(&paths, UNIT_FILE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, NULL);
         if (r < 0)
                 return r;
@@ -1020,62 +1201,95 @@ int portable_attach(
         }
 
         HASHMAP_FOREACH(item, unit_files) {
-                r = attach_unit_file(&paths, image->path, image->type, item, profile, flags, changes, n_changes);
+                r = attach_unit_file(&paths, image->path, image->type, extension_images,
+                                     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);
+        (void) install_image_and_extensions_symlinks(image, extension_images, flags, changes, n_changes);
 
         return 0;
 }
 
-static bool marker_matches_image(const char *marker, const char *name_or_path) {
+static bool marker_matches_images(const char *marker, const char *name_or_path, char **extension_image_paths) {
+        _cleanup_strv_free_ char **root_and_extensions = NULL;
+        char **image_name_or_path;
         const char *a;
+        int r;
 
         assert(marker);
         assert(name_or_path);
 
-        a = last_path_component(marker);
+        /* If extensions were used when attaching, the marker will be a colon-separated
+         * list of images/paths. We enforce strict 1:1 matching, so that we are sure
+         * we are detaching exactly what was attached.
+         * For each image, starting with the root, we look for a token in the marker,
+         * and return a negative answer on any non-matching combination. */
 
-        if (image_name_is_valid(name_or_path)) {
-                const char *e, *underscore;
+        root_and_extensions = strv_new(name_or_path);
+        if (!root_and_extensions)
+                return -ENOMEM;
 
-                /* 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 "/".
-                 * But allow matching on a different version of the same image, when a "_" is used as a separator. */
-                underscore = strchr(name_or_path, '_');
-                if (underscore)
-                        return strneq(a, name_or_path, underscore - name_or_path);
+        r = strv_extend_strv(&root_and_extensions, extension_image_paths, false);
+        if (r < 0)
+                return r;
 
-                e = startswith(a, name_or_path);
-                if (!e)
+        STRV_FOREACH(image_name_or_path, root_and_extensions) {
+                _cleanup_free_ char *image = NULL;
+
+                r = extract_first_word(&marker, &image, ":", EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to parse marker: %s", marker);
+                if (r == 0)
                         return false;
 
-                return
-                        e[strspn(e, "/")] == 0 ||
-                        streq(e, ".raw");
-        } else {
-                const char *b, *underscore;
-                size_t l;
+                a = last_path_component(image);
+
+                if (image_name_is_valid(*image_name_or_path)) {
+                        const char *e, *underscore;
 
-                /* 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. */
+                        /* 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 "/".
+                        * But allow matching on a different version of the same image, when a "_" is used as a separator. */
+                        underscore = strchr(*image_name_or_path, '_');
+                        if (underscore) {
+                                if (strneq(a, *image_name_or_path, underscore - *image_name_or_path))
+                                        continue;
+                                return false;
+                        }
 
-                l = strcspn(a, "/");
-                b = last_path_component(name_or_path);
+                        e = startswith(a, *image_name_or_path);
+                        if (!e)
+                                return false;
 
-                if (strcspn(b, "/") != l)
-                        return false;
+                        if(!(e[strspn(e, "/")] == 0 || streq(e, ".raw")))
+                                return false;
+                } else {
+                        const char *b, *underscore;
+                        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(*image_name_or_path);
+
+                        if (strcspn(b, "/") != l)
+                                return false;
 
-                underscore = strchr(b, '_');
-                if (underscore)
-                        l = underscore - b;
+                        underscore = strchr(b, '_');
+                        if (underscore)
+                                l = underscore - b;
 
-                return strneq(a, b, l);
+                        if (!strneq(a, b, l))
+                                return false;
+                }
         }
+
+        return true;
 }
 
 static int test_chroot_dropin(
@@ -1083,6 +1297,7 @@ static int test_chroot_dropin(
                 const char *where,
                 const char *fname,
                 const char *name_or_path,
+                char **extension_image_paths,
                 char **ret_marker) {
 
         _cleanup_free_ char *line = NULL, *marker = NULL;
@@ -1129,7 +1344,7 @@ static int test_chroot_dropin(
         if (!name_or_path)
                 r = true;
         else
-                r = marker_matches_image(marker, name_or_path);
+                r = marker_matches_images(marker, name_or_path, extension_image_paths);
 
         if (ret_marker)
                 *ret_marker = TAKE_PTR(marker);
@@ -1140,6 +1355,7 @@ static int test_chroot_dropin(
 int portable_detach(
                 sd_bus *bus,
                 const char *name_or_path,
+                char **extension_image_paths,
                 PortableFlags flags,
                 PortableChange **changes,
                 size_t *n_changes,
@@ -1184,7 +1400,7 @@ int portable_detach(
                 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
                         continue;
 
-                r = test_chroot_dropin(d, where, de->d_name, name_or_path, &marker);
+                r = test_chroot_dropin(d, where, de->d_name, name_or_path, extension_image_paths, &marker);
                 if (r < 0)
                         return r;
                 if (r == 0)
@@ -1206,12 +1422,20 @@ int portable_detach(
                 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, NULL, marker)) {
+                for (const char *p = marker;;) {
+                        _cleanup_free_ char *image = NULL;
 
-                        r = set_ensure_consume(&markers, &path_hash_ops_free, TAKE_PTR(marker));
+                        r = extract_first_word(&p, &image, ":", EXTRACT_UNESCAPE_SEPARATORS|EXTRACT_RETAIN_ESCAPE);
                         if (r < 0)
-                                return r;
+                                return log_debug_errno(r, "Failed to parse marker: %s", p);
+                        if (r == 0)
+                                break;
+
+                        if (path_is_absolute(image) && !image_in_search_path(IMAGE_PORTABLE, NULL, image)) {
+                                r = set_ensure_consume(&markers, &path_hash_ops_free, TAKE_PTR(image));
+                                if (r < 0)
+                                        return r;
+                        }
                 }
         }
 
@@ -1349,7 +1573,7 @@ static int portable_get_state_internal(
                 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
                         continue;
 
-                r = test_chroot_dropin(d, where, de->d_name, name_or_path, NULL);
+                r = test_chroot_dropin(d, where, de->d_name, name_or_path, NULL, NULL);
                 if (r < 0)
                         return r;
                 if (r == 0)
index 5694bd2b623eaf36f2b82ef730abdad2ecae484a..dd080edf4e0a449134849dc244aef4e137dba382 100644 (file)
@@ -11,6 +11,7 @@
 typedef struct PortableMetadata {
         int fd;
         char *source;
+        char *image_path;
         char name[];
 } PortableMetadata;
 
@@ -18,10 +19,13 @@ typedef struct PortableMetadata {
 #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,
+        PORTABLE_RUNTIME        = 1 << 0, /* Public API via DBUS, do not change */
+        PORTABLE_PREFER_COPY    = 1 << 1,
+        PORTABLE_PREFER_SYMLINK = 1 << 2,
         PORTABLE_REATTACH       = 1 << 3,
+        _PORTABLE_MASK_PUBLIC   = PORTABLE_RUNTIME,
+        _PORTABLE_TYPE_MAX,
+        _PORTABLE_TYPE_INVALID  = -EINVAL,
 } PortableFlags;
 
 /* This enum is anonymous, since we usually store it in an 'int', as we overload it with negative errno
@@ -59,10 +63,10 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(PortableMetadata*, portable_metadata_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_extract(const char *image, char **matches, char **extension_image_paths, 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_attach(sd_bus *bus, const char *name_or_path, char **matches, const char *profile, char **extension_images, PortableFlags flags, PortableChange **changes, size_t *n_changes, sd_bus_error *error);
+int portable_detach(sd_bus *bus, const char *name_or_path, char **extension_image_paths, 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);
 
index 77fcd4fe6fcbc374b4cff8055103448163cb3d25..2d8079ad97992ef795d688351aa0938bb8a45db9 100644 (file)
 #include "main-func.h"
 #include "os-util.h"
 #include "pager.h"
+#include "parse-argument.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "pretty-print.h"
+#include "portable.h"
 #include "spawn-polkit-agent.h"
 #include "string-util.h"
 #include "strv.h"
@@ -44,6 +46,9 @@ static const char *arg_host = NULL;
 static bool arg_enable = false;
 static bool arg_now = false;
 static bool arg_no_block = false;
+static char **arg_extension_images = NULL;
+
+STATIC_DESTRUCTOR_REGISTER(arg_extension_images, strv_freep);
 
 static bool is_portable_managed(const char *unit) {
         return ENDSWITH_SET(unit, ".service", ".target", ".socket", ".path", ".timer");
@@ -83,6 +88,38 @@ static int determine_image(const char *image, bool permit_non_existing, char **r
         return 0;
 }
 
+static int attach_extensions_to_message(sd_bus_message *m, char **extensions) {
+        char **p;
+        int r;
+
+        assert(m);
+
+        if (strv_isempty(extensions))
+                return 0;
+
+        r = sd_bus_message_open_container(m, 'a', "s");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        STRV_FOREACH(p, extensions) {
+                _cleanup_free_ char *resolved_extension_image = NULL;
+
+                r = determine_image(*p, false, &resolved_extension_image);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_append(m, "s", resolved_extension_image);
+                if (r < 0)
+                        return bus_log_create_error(r);
+        }
+
+        r = sd_bus_message_close_container(m);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        return 0;
+}
+
 static int extract_prefix(const char *path, char **ret) {
         _cleanup_free_ char *name = NULL;
         const char *bn, *underscore;
@@ -219,15 +256,55 @@ static int maybe_reload(sd_bus **bus) {
         return 0;
 }
 
-static int inspect_image(int argc, char *argv[], void *userdata) {
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+static int get_image_metadata(sd_bus *bus, const char *image, char **matches, sd_bus_message **reply) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        const char *method;
+        uint64_t flags = 0;
+        int r;
+
+        assert(bus);
+        assert(reply);
+
+        method = strv_isempty(arg_extension_images) ? "GetImageMetadata" : "GetImageMetadataWithExtensions";
+
+        r = bus_message_new_method_call(bus, &m, bus_portable_mgr, method);
+        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 = attach_extensions_to_message(m, arg_extension_images);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append_strv(m, matches);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        if (!strv_isempty(arg_extension_images)) {
+                r = sd_bus_message_append(m, "t", flags);
+                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));
+
+        return 0;
+}
+
+static int inspect_image(int argc, char *argv[], void *userdata) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = 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;
+        const void *data;
         size_t sz;
         int r;
 
@@ -243,21 +320,9 @@ static int inspect_image(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        r = bus_message_new_method_call(bus, &m, bus_portable_mgr, "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);
+        r = get_image_metadata(bus, image, matches, &reply);
         if (r < 0)
-                return log_error_errno(r, "Failed to inspect image metadata: %s", bus_error_message(&error, r));
+                return r;
 
         r = sd_bus_message_read(reply, "s", &path);
         if (r < 0)
@@ -276,7 +341,7 @@ static int inspect_image(int argc, char *argv[], void *userdata) {
                 nl = true;
         } else {
                 _cleanup_free_ char *pretty_portable = NULL, *pretty_os = NULL;
-                _cleanup_fclose_ FILE *f;
+                _cleanup_fclose_ FILE *f = NULL;
 
                 f = fmemopen_unlocked((void*) data, sz, "re");
                 if (!f)
@@ -607,8 +672,7 @@ static int maybe_stop_enable_restart(sd_bus *bus, sd_bus_message *reply) {
 
 static int maybe_stop_disable(sd_bus *bus, char *image, char *argv[]) {
         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *wait = NULL;
-        _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_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_strv_free_ char **matches = NULL;
         int r;
 
@@ -623,21 +687,9 @@ static int maybe_stop_disable(sd_bus *bus, char *image, char *argv[]) {
         if (r < 0)
                 return log_error_errno(r, "Could not watch jobs: %m");
 
-        r = bus_message_new_method_call(bus, &m, bus_portable_mgr, "GetImageMetadata");
+        r = get_image_metadata(bus, image, matches, &reply);
         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));
+                return r;
 
         r = sd_bus_message_skip(reply, "say");
         if (r < 0)
@@ -693,7 +745,7 @@ static int attach_reattach_image(int argc, char *argv[], const char *method) {
         int r;
 
         assert(method);
-        assert(STR_IN_SET(method, "AttachImage", "ReattachImage"));
+        assert(STR_IN_SET(method, "AttachImage", "ReattachImage", "AttachImageWithExtensions", "ReattachImageWithExtensions"));
 
         r = determine_image(argv[1], false, &image);
         if (r < 0)
@@ -717,11 +769,24 @@ static int attach_reattach_image(int argc, char *argv[], const char *method) {
         if (r < 0)
                 return bus_log_create_error(r);
 
+        r = attach_extensions_to_message(m, arg_extension_images);
+        if (r < 0)
+                return 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);
+        r = sd_bus_message_append(m, "s", arg_profile);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        if (STR_IN_SET(method, "AttachImageWithExtensions", "ReattachImageWithExtensions")) {
+                uint64_t flags = arg_runtime ? PORTABLE_RUNTIME : 0;
+
+                r = sd_bus_message_append(m, "st", arg_copy_mode, flags);
+        } else
+                r = sd_bus_message_append(m, "bs", arg_runtime, arg_copy_mode);
         if (r < 0)
                 return bus_log_create_error(r);
 
@@ -733,7 +798,7 @@ static int attach_reattach_image(int argc, char *argv[], const char *method) {
 
         print_changes(reply);
 
-        if (streq(method, "AttachImage"))
+        if (STR_IN_SET(method, "AttachImage", "AttachImageWithExtensions"))
                 (void) maybe_enable_start(bus, reply);
         else {
                 /* ReattachImage returns 2 lists - removed units first, and changed/added second */
@@ -745,18 +810,19 @@ static int attach_reattach_image(int argc, char *argv[], const char *method) {
 }
 
 static int attach_image(int argc, char *argv[], void *userdata) {
-        return attach_reattach_image(argc, argv, "AttachImage");
+        return attach_reattach_image(argc, argv, strv_isempty(arg_extension_images) ? "AttachImage" : "AttachImageWithExtensions");
 }
 
 static int reattach_image(int argc, char *argv[], void *userdata) {
-        return attach_reattach_image(argc, argv, "ReattachImage");
+        return attach_reattach_image(argc, argv, strv_isempty(arg_extension_images) ? "ReattachImage" : "ReattachImageWithExtensions");
 }
 
 static int detach_image(int argc, char *argv[], void *userdata) {
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _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_free_ char *image = NULL;
+        const char *method;
         int r;
 
         r = determine_image(argv[1], true, &image);
@@ -771,9 +837,32 @@ static int detach_image(int argc, char *argv[], void *userdata) {
 
         (void) maybe_stop_disable(bus, image, argv);
 
-        r = bus_call_method(bus, bus_portable_mgr, "DetachImage", &error, &reply, "sb", image, arg_runtime);
+        method = strv_isempty(arg_extension_images) ? "DetachImage" : "DetachImageWithExtensions";
+
+        r = bus_message_new_method_call(bus, &m, bus_portable_mgr, method);
+        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 = attach_extensions_to_message(m, arg_extension_images);
+        if (r < 0)
+                return r;
+
+        if (!strv_isempty(arg_extension_images)) {
+                uint64_t flags = arg_runtime ? PORTABLE_RUNTIME : 0;
+
+                r = sd_bus_message_append(m, "t", flags);
+        } else
+                r = sd_bus_message_append(m, "b", arg_runtime);
         if (r < 0)
-                return log_error_errno(r, "Failed to detach image: %s", bus_error_message(&error, r));
+                return bus_log_create_error(r);
+
+        r = sd_bus_call(bus, m, 0, &error, &reply);
+        if (r < 0)
+                return log_error_errno(r, "%s failed: %s", method, bus_error_message(&error, r));
 
         (void) maybe_reload(&bus);
 
@@ -1045,6 +1134,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --now                    Immediately start/stop the portable service after\n"
                "                              attach/before detach\n"
                "     --no-block               Don't block waiting for attach --now to complete\n"
+               "     --extension=PATH         Extend the image with an overlay\n"
                "\nSee the %s for details.\n",
                program_invocation_short_name,
                ansi_highlight(),
@@ -1055,6 +1145,7 @@ static int help(int argc, char *argv[], void *userdata) {
 }
 
 static int parse_argv(int argc, char *argv[]) {
+        int r;
 
         enum {
                 ARG_VERSION = 0x100,
@@ -1068,6 +1159,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_ENABLE,
                 ARG_NOW,
                 ARG_NO_BLOCK,
+                ARG_EXTENSION,
         };
 
         static const struct option options[] = {
@@ -1087,6 +1179,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "enable",          no_argument,       NULL, ARG_ENABLE          },
                 { "now",             no_argument,       NULL, ARG_NOW             },
                 { "no-block",        no_argument,       NULL, ARG_NO_BLOCK        },
+                { "extension",       required_argument, NULL, ARG_EXTENSION       },
                 {}
         };
 
@@ -1185,6 +1278,12 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_no_block = true;
                         break;
 
+                case ARG_EXTENSION:
+                        r = strv_extend(&arg_extension_images, optarg);
+                        if (r < 0)
+                                return log_oom();
+                        break;
+
                 case '?':
                         return -EINVAL;
 
index 6d0dee99c3f703494329f3cfa65c9d6c821d027a..5b992d9df83937b0777076700be2f8cedfbbeb6a 100644 (file)
@@ -252,11 +252,13 @@ static int method_attach_image(sd_bus_message *message, void *userdata, sd_bus_e
 }
 
 static int method_detach_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_strv_free_ char **extension_images = NULL;
         PortableChange *changes = NULL;
+        PortableFlags flags = 0;
         Manager *m = userdata;
         size_t n_changes = 0;
         const char *name_or_path;
-        int r, runtime;
+        int r;
 
         assert(message);
         assert(m);
@@ -265,10 +267,37 @@ static int method_detach_image(sd_bus_message *message, void *userdata, sd_bus_e
          * 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);
+        r = sd_bus_message_read(message, "s", &name_or_path);
         if (r < 0)
                 return r;
 
+        if (sd_bus_message_is_method_call(message, NULL, "DetachImageWithExtensions")) {
+                uint64_t input_flags = 0;
+
+                r = sd_bus_message_read_strv(message, &extension_images);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_read(message, "t", &input_flags);
+                if (r < 0)
+                        return r;
+
+                if ((input_flags & ~_PORTABLE_MASK_PUBLIC) != 0)
+                        return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS,
+                                                          "Invalid 'flags' parameter '%" PRIu64 "'",
+                                                          input_flags);
+                flags |= input_flags;
+        } else {
+                int runtime;
+
+                r = sd_bus_message_read(message, "b", &runtime);
+                if (r < 0)
+                        return r;
+
+                if (runtime)
+                        flags |= PORTABLE_RUNTIME;
+        }
+
         r = bus_verify_polkit_async(
                         message,
                         CAP_SYS_ADMIN,
@@ -286,7 +315,8 @@ static int method_detach_image(sd_bus_message *message, void *userdata, sd_bus_e
         r = portable_detach(
                         sd_bus_message_get_bus(message),
                         name_or_path,
-                        runtime ? PORTABLE_RUNTIME : 0,
+                        extension_images,
+                        flags,
                         &changes,
                         &n_changes,
                         error);
@@ -327,7 +357,7 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus
         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");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
 
         r = bus_verify_polkit_async(
                         message,
@@ -347,7 +377,7 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus
 
         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.");
+                return sd_bus_error_set(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");
 
@@ -383,6 +413,16 @@ const sd_bus_vtable manager_vtable[] = {
                                               "a{say}", units),
                                 method_get_image_metadata,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("GetImageMetadataWithExtensions",
+                                SD_BUS_ARGS("s", image,
+                                            "as", extensions,
+                                            "as", matches,
+                                            "t", flags),
+                                SD_BUS_RESULT("s", image,
+                                              "ay", os_release,
+                                              "a{say}", units),
+                                method_get_image_metadata,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("GetImageState",
                                 SD_BUS_ARGS("s", image),
                                 SD_BUS_RESULT("s", state),
@@ -397,12 +437,29 @@ const sd_bus_vtable manager_vtable[] = {
                                 SD_BUS_RESULT("a(sss)", changes),
                                 method_attach_image,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("AttachImageWithExtensions",
+                                SD_BUS_ARGS("s", image,
+                                            "as", extensions,
+                                            "as", matches,
+                                            "s", profile,
+                                            "s", copy_mode,
+                                            "t", flags),
+                                SD_BUS_RESULT("a(sss)", changes),
+                                method_attach_image,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("DetachImage",
                                 SD_BUS_ARGS("s", image,
                                             "b", runtime),
                                 SD_BUS_RESULT("a(sss)", changes),
                                 method_detach_image,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("DetachImageWithExtensions",
+                                SD_BUS_ARGS("s", image,
+                                            "as", extensions,
+                                            "t", flags),
+                                SD_BUS_RESULT("a(sss)", changes),
+                                method_detach_image,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("ReattachImage",
                                 SD_BUS_ARGS("s", image,
                                             "as", matches,
@@ -413,6 +470,17 @@ const sd_bus_vtable manager_vtable[] = {
                                               "a(sss)", changes_updated),
                                 method_reattach_image,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("ReattachImageWithExtensions",
+                                SD_BUS_ARGS("s", image,
+                                            "as", extensions,
+                                            "as", matches,
+                                            "s", profile,
+                                            "s", copy_mode,
+                                            "t", flags),
+                                SD_BUS_RESULT("a(sss)", changes_removed,
+                                              "a(sss)", changes_updated),
+                                method_reattach_image,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("RemoveImage",
                                 SD_BUS_ARGS("s", image),
                                 SD_BUS_NO_RESULT,
index 8332332c9159ce1989766fede7ccd4905c25528b..595fe8a60a4fd7a9fec381d972ce3f6a85194295 100644 (file)
@@ -75,20 +75,22 @@ static int bus_image_method_get_os_release(sd_bus_message *message, void *userda
 static int append_fd(sd_bus_message *m, PortableMetadata *d) {
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_free_ char *buf = NULL;
-        size_t n;
+        size_t n = 0;
         int r;
 
         assert(m);
-        assert(d);
-        assert(d->fd >= 0);
 
-        f = take_fdopen(&d->fd, "r");
-        if (!f)
-                return -errno;
+        if (d) {
+                assert(d->fd >= 0);
 
-        r = read_full_stream(f, &buf, &n);
-        if (r < 0)
-                return r;
+                f = take_fdopen(&d->fd, "r");
+                if (!f)
+                        return -errno;
+
+                r = read_full_stream(f, &buf, &n);
+                if (r < 0)
+                        return r;
+        }
 
         return sd_bus_message_append_array(m, 'y', buf, n);
 }
@@ -101,10 +103,12 @@ int bus_image_common_get_metadata(
                 sd_bus_error *error) {
 
         _cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
+        _cleanup_strv_free_ char **matches = NULL, **extension_images = NULL;
         _cleanup_hashmap_free_ 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;
+        /* Unused for now, but added to the DBUS methods for future-proofing */
+        uint64_t input_flags = 0;
         size_t i;
         int r;
 
@@ -116,10 +120,29 @@ int bus_image_common_get_metadata(
                 m = image->userdata;
         }
 
+        if (sd_bus_message_is_method_call(message, NULL, "GetImageMetadataWithExtensions") ||
+            sd_bus_message_is_method_call(message, NULL, "GetMetadataWithExtensions")) {
+                r = sd_bus_message_read_strv(message, &extension_images);
+                if (r < 0)
+                        return r;
+        }
+
         r = sd_bus_message_read_strv(message, &matches);
         if (r < 0)
                 return r;
 
+        if (sd_bus_message_is_method_call(message, NULL, "GetImageMetadataWithExtensions") ||
+            sd_bus_message_is_method_call(message, NULL, "GetMetadataWithExtensions")) {
+                r = sd_bus_message_read(message, "t", &input_flags);
+                if (r < 0)
+                        return r;
+                /* Let clients know that this version doesn't support any flags */
+                if (input_flags != 0)
+                        return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS,
+                                                          "Invalid 'flags' parameter '%" PRIu64 "'",
+                                                          input_flags);
+        }
+
         r = bus_image_acquire(m,
                               message,
                               name_or_path,
@@ -136,6 +159,7 @@ int bus_image_common_get_metadata(
         r = portable_extract(
                         image->path,
                         matches,
+                        extension_images,
                         &os_release,
                         &unit_files,
                         error);
@@ -223,12 +247,12 @@ int bus_image_common_attach(
                 Image *image,
                 sd_bus_error *error) {
 
-        _cleanup_strv_free_ char **matches = NULL;
+        _cleanup_strv_free_ char **matches = NULL, **extension_images = NULL;
         PortableChange *changes = NULL;
         PortableFlags flags = 0;
         const char *profile, *copy_mode;
         size_t n_changes = 0;
-        int runtime, r;
+        int r;
 
         assert(message);
         assert(name_or_path || image);
@@ -238,14 +262,44 @@ int bus_image_common_attach(
                 m = image->userdata;
         }
 
+        if (sd_bus_message_is_method_call(message, NULL, "AttachImageWithExtensions") ||
+            sd_bus_message_is_method_call(message, NULL, "AttachWithExtensions")) {
+                r = sd_bus_message_read_strv(message, &extension_images);
+                if (r < 0)
+                        return r;
+        }
+
         r = sd_bus_message_read_strv(message, &matches);
         if (r < 0)
                 return r;
 
-        r = sd_bus_message_read(message, "sbs", &profile, &runtime, &copy_mode);
+        r = sd_bus_message_read(message, "s", &profile);
         if (r < 0)
                 return r;
 
+        if (sd_bus_message_is_method_call(message, NULL, "AttachImageWithExtensions") ||
+            sd_bus_message_is_method_call(message, NULL, "AttachWithExtensions")) {
+                uint64_t input_flags = 0;
+
+                r = sd_bus_message_read(message, "st", &copy_mode, &input_flags);
+                if (r < 0)
+                        return r;
+                if ((input_flags & ~_PORTABLE_MASK_PUBLIC) != 0)
+                        return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS,
+                                                          "Invalid 'flags' parameter '%" PRIu64 "'",
+                                                          input_flags);
+                flags |= input_flags;
+        } else {
+                int runtime;
+
+                r = sd_bus_message_read(message, "bs", &runtime, &copy_mode);
+                if (r < 0)
+                        return r;
+
+                if (runtime)
+                        flags |= PORTABLE_RUNTIME;
+        }
+
         if (streq(copy_mode, "symlink"))
                 flags |= PORTABLE_PREFER_SYMLINK;
         else if (streq(copy_mode, "copy"))
@@ -253,9 +307,6 @@ int bus_image_common_attach(
         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,
@@ -274,6 +325,7 @@ int bus_image_common_attach(
                         image->path,
                         matches,
                         profile,
+                        extension_images,
                         flags,
                         &changes,
                         &n_changes,
@@ -297,19 +349,46 @@ static int bus_image_method_detach(
                 void *userdata,
                 sd_bus_error *error) {
 
+        _cleanup_strv_free_ char **extension_images = NULL;
         PortableChange *changes = NULL;
         Image *image = userdata;
         Manager *m = image->userdata;
+        PortableFlags flags = 0;
         size_t n_changes = 0;
-        int r, runtime;
+        int r;
 
         assert(message);
         assert(image);
         assert(m);
 
-        r = sd_bus_message_read(message, "b", &runtime);
-        if (r < 0)
-                return r;
+        if (sd_bus_message_is_method_call(message, NULL, "DetachWithExtensions")) {
+                r = sd_bus_message_read_strv(message, &extension_images);
+                if (r < 0)
+                        return r;
+        }
+
+        if (sd_bus_message_is_method_call(message, NULL, "DetachWithExtensions")) {
+                uint64_t input_flags = 0;
+
+                r = sd_bus_message_read(message, "t", &input_flags);
+                if (r < 0)
+                        return r;
+
+                if ((input_flags & ~_PORTABLE_MASK_PUBLIC) != 0)
+                        return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS,
+                                                          "Invalid 'flags' parameter '%" PRIu64 "'",
+                                                          input_flags);
+                flags |= input_flags;
+        } else {
+                int runtime;
+
+                r = sd_bus_message_read(message, "b", &runtime);
+                if (r < 0)
+                        return r;
+
+                if (runtime)
+                        flags |= PORTABLE_RUNTIME;
+        }
 
         r = bus_verify_polkit_async(
                         message,
@@ -328,7 +407,8 @@ static int bus_image_method_detach(
         r = portable_detach(
                         sd_bus_message_get_bus(message),
                         image->path,
-                        runtime ? PORTABLE_RUNTIME : 0,
+                        extension_images,
+                        flags,
                         &changes,
                         &n_changes,
                         error);
@@ -363,7 +443,7 @@ int bus_image_common_remove(
         }
 
         if (m->n_operations >= OPERATIONS_MAX)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
 
         r = bus_image_acquire(m,
                               message,
@@ -510,10 +590,10 @@ int bus_image_common_reattach(
 
         PortableChange *changes_detached = NULL, *changes_attached = NULL, *changes_gone = NULL;
         size_t n_changes_detached = 0, n_changes_attached = 0, n_changes_gone = 0;
-        _cleanup_strv_free_ char **matches = NULL;
+        _cleanup_strv_free_ char **matches = NULL, **extension_images = NULL;
         PortableFlags flags = PORTABLE_REATTACH;
         const char *profile, *copy_mode;
-        int runtime, r;
+        int r;
 
         assert(message);
         assert(name_or_path || image);
@@ -523,14 +603,45 @@ int bus_image_common_reattach(
                 m = image->userdata;
         }
 
+        if (sd_bus_message_is_method_call(message, NULL, "ReattachImageWithExtensions") ||
+            sd_bus_message_is_method_call(message, NULL, "ReattachWithExtensions")) {
+                r = sd_bus_message_read_strv(message, &extension_images);
+                if (r < 0)
+                        return r;
+        }
+
         r = sd_bus_message_read_strv(message, &matches);
         if (r < 0)
                 return r;
 
-        r = sd_bus_message_read(message, "sbs", &profile, &runtime, &copy_mode);
+        r = sd_bus_message_read(message, "s", &profile);
         if (r < 0)
                 return r;
 
+        if (sd_bus_message_is_method_call(message, NULL, "ReattachImageWithExtensions") ||
+            sd_bus_message_is_method_call(message, NULL, "ReattachWithExtensions")) {
+                uint64_t input_flags = 0;
+
+                r = sd_bus_message_read(message, "st", &copy_mode, &input_flags);
+                if (r < 0)
+                        return r;
+
+                if ((input_flags & ~_PORTABLE_MASK_PUBLIC) != 0)
+                        return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS,
+                                                          "Invalid 'flags' parameter '%" PRIu64 "'",
+                                                          input_flags);
+                flags |= input_flags;
+        } else {
+                int runtime;
+
+                r = sd_bus_message_read(message, "bs", &runtime, &copy_mode);
+                if (r < 0)
+                        return r;
+
+                if (runtime)
+                        flags |= PORTABLE_RUNTIME;
+        }
+
         if (streq(copy_mode, "symlink"))
                 flags |= PORTABLE_PREFER_SYMLINK;
         else if (streq(copy_mode, "copy"))
@@ -538,9 +649,6 @@ int bus_image_common_reattach(
         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,
@@ -557,6 +665,7 @@ int bus_image_common_reattach(
         r = portable_detach(
                         sd_bus_message_get_bus(message),
                         image->path,
+                        extension_images,
                         flags,
                         &changes_detached,
                         &n_changes_detached,
@@ -569,6 +678,7 @@ int bus_image_common_reattach(
                         image->path,
                         matches,
                         profile,
+                        extension_images,
                         flags,
                         &changes_attached,
                         &n_changes_attached,
@@ -671,7 +781,7 @@ int bus_image_common_set_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");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
 
         r = bus_image_acquire(m,
                               message,
@@ -721,6 +831,15 @@ const sd_bus_vtable image_vtable[] = {
                                               "a{say}", units),
                                 bus_image_method_get_metadata,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("GetMetadataWithExtensions",
+                                SD_BUS_ARGS("as", extensions,
+                                            "as", matches,
+                                            "t", flags),
+                                SD_BUS_RESULT("s", image,
+                                              "ay", os_release,
+                                              "a{say}", units),
+                                bus_image_method_get_metadata,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("GetState",
                                 SD_BUS_NO_ARGS,
                                 SD_BUS_RESULT("s", state),
@@ -734,11 +853,26 @@ const sd_bus_vtable image_vtable[] = {
                                 SD_BUS_RESULT("a(sss)", changes),
                                 bus_image_method_attach,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("AttachWithExtensions",
+                                SD_BUS_ARGS("as", extensions,
+                                            "as", matches,
+                                            "s", profile,
+                                            "s", copy_mode,
+                                            "t", flags),
+                                SD_BUS_RESULT("a(sss)", changes),
+                                bus_image_method_attach,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("Detach",
                                 SD_BUS_ARGS("b", runtime),
                                 SD_BUS_RESULT("a(sss)", changes),
                                 bus_image_method_detach,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("DetachWithExtensions",
+                                SD_BUS_ARGS("as", extensions,
+                                            "t", flags),
+                                SD_BUS_RESULT("a(sss)", changes),
+                                bus_image_method_detach,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("Reattach",
                                 SD_BUS_ARGS("as", matches,
                                             "s", profile,
@@ -748,6 +882,16 @@ const sd_bus_vtable image_vtable[] = {
                                               "a(sss)", changes_updated),
                                 bus_image_method_reattach,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("ReattacheWithExtensions",
+                                SD_BUS_ARGS("as", extensions,
+                                            "as", matches,
+                                            "s", profile,
+                                            "s", copy_mode,
+                                            "t", flags),
+                                SD_BUS_RESULT("a(sss)", changes_removed,
+                                              "a(sss)", changes_updated),
+                                bus_image_method_reattach,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("Remove",
                                 SD_BUS_NO_ARGS,
                                 SD_BUS_NO_RESULT,
index 848b784908f0693680d57607e6d2bfdfdaeab1d3..6f06367d2067199ffd53697f0a096e82c87d7a80 100644 (file)
@@ -20,14 +20,14 @@ static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdat
         o->pid = 0;
 
         if (si->si_code != CLD_EXITED) {
-                r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
+                r = sd_bus_error_set(&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.");
+                r = sd_bus_error_set(&error, SD_BUS_ERROR_FAILED, "Child failed.");
                 goto fail;
         }
 
index 7b7b1e84932f78abb21ca29ece55b7e2a7cd8188..68fb04ae0a0c696081c57465dc317207a12e6028 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Entries in this file show the compile time defaults. Local configuration
 # should be created by either modifying this file, or by creating "drop-ins" in
-# the system.conf.d/ subdirectory. The latter is generally recommended.
+# the pstore.conf.d/ subdirectory. The latter is generally recommended.
 # Defaults can be restored by simply deleting this file and all drop-ins.
 #
 # See pstore.conf(5) for details.
index 4caf9678071ac5e534dc838df8448830c8894265..e003ca60e3c39281a25a278254bc38569fa21df9 100644 (file)
@@ -262,7 +262,7 @@ static int run(int argc, char *argv[]) {
                 if (k < 0)
                         log_debug_errno(errno, "Failed to read random data with getrandom(), falling back to /dev/urandom: %m");
                 else if ((size_t) k < buf_size)
-                        log_debug("Short read from getrandom(), falling back to /dev/urandom: %m");
+                        log_debug("Short read from getrandom(), falling back to /dev/urandom.");
                 else
                         getrandom_worked = true;
 
index c3624669ce18b954fb29890bce42c936ce4005cd..31c96706a21bd9cd8a25006ec942f0e5ffde2809 100644 (file)
@@ -299,7 +299,7 @@ static int validate_and_mangle_flags(
                        SD_RESOLVED_NO_TRUST_ANCHOR|
                        SD_RESOLVED_NO_NETWORK|
                        ok))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
 
         if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
                 *flags |= SD_RESOLVED_PROTOCOLS_ALL;
@@ -420,7 +420,7 @@ static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata,
                 return r;
 
         if (ifindex < 0)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
 
         if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
@@ -581,7 +581,7 @@ static int bus_method_resolve_address(sd_bus_message *message, void *userdata, s
                 return r;
 
         if (ifindex < 0)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
 
         r = validate_and_mangle_flags(NULL, &flags, 0, error);
         if (r < 0)
@@ -738,7 +738,7 @@ static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd
                 return r;
 
         if (ifindex < 0)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
 
         r = dns_name_is_valid(name);
         if (r < 0)
@@ -749,7 +749,7 @@ static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd
         if (!dns_type_is_valid_query(type))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified resource record type %" PRIu16 " may not be used in a query.", type);
         if (dns_type_is_zone_transer(type))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Zone transfers not permitted via this programming interface.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Zone transfers not permitted via this programming interface.");
         if (dns_type_is_obsolete(type))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Specified DNS resource record type %" PRIu16 " is obsolete.", type);
 
@@ -765,7 +765,7 @@ static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd
         if (!key)
                 return -ENOMEM;
 
-        r = dns_question_add(question, key);
+        r = dns_question_add(question, key, 0);
         if (r < 0)
                 return r;
 
@@ -1267,7 +1267,7 @@ static int bus_method_resolve_service(sd_bus_message *message, void *userdata, s
                 return r;
 
         if (ifindex < 0)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
 
         if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
@@ -1289,7 +1289,7 @@ static int bus_method_resolve_service(sd_bus_message *message, void *userdata, s
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid domain '%s'", domain);
 
         if (name && !type)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
 
         r = validate_and_mangle_flags(name, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
         if (r < 0)
@@ -1861,7 +1861,7 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata,
         assert(m);
 
         if (m->mdns_support != RESOLVE_SUPPORT_YES)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for MulticastDNS is disabled");
+                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for MulticastDNS is disabled");
 
         service = new0(DnssdService, 1);
         if (!service)
@@ -1928,7 +1928,7 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata,
                                 return r;
 
                         if (isempty(key))
-                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Keys in DNS-SD TXT RRs can't be empty");
+                                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Keys in DNS-SD TXT RRs can't be empty");
 
                         if (!ascii_is_valid(key))
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TXT key '%s' contains non-ASCII symbols", key);
index a032ac157e067b3dd53061b105caed6444610d73..978d14818ab63ebbf5fafdb3352e4430085820cc 100644 (file)
@@ -277,7 +277,7 @@ int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags
         return found;
 }
 
-int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) {
+bool dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) {
         DnsResourceRecord *i;
 
         DNS_ANSWER_FOREACH(i, a)
@@ -314,7 +314,7 @@ int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone) {
         return false;
 }
 
-int dns_answer_contains(DnsAnswer *answer, DnsResourceRecord *rr) {
+bool dns_answer_contains(DnsAnswer *answer, DnsResourceRecord *rr) {
         DnsResourceRecord *i;
 
         DNS_ANSWER_FOREACH(i, answer)
index 447da5d6cc3437e282c6cd7265ab8d78b27a7cad..3eb573b2c144874e62c3071b32dbefbeee0a0a46 100644 (file)
@@ -50,10 +50,10 @@ int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFl
 int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags, DnsResourceRecord *rrsig);
 int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex);
 
-int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *combined_flags);
-int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a);
+int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags);
+bool dns_answer_contains_nsec_or_nsec3(DnsAnswer *a);
 int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone);
-int dns_answer_contains(DnsAnswer *answer, DnsResourceRecord *rr);
+bool dns_answer_contains(DnsAnswer *answer, DnsResourceRecord *rr);
 
 int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *ret_flags);
 int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *ret_flags);
@@ -93,37 +93,38 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref);
 
 #define _DNS_ANSWER_FOREACH(q, kk, a)                                   \
         for (size_t UNIQ_T(i, q) = ({                                   \
-                                (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
-                                0;                                      \
-                        });                                             \
-             (a) && (UNIQ_T(i, q) < (a)->n_rrs);                        \
-             UNIQ_T(i, q)++, (kk) = (UNIQ_T(i, q) < (a)->n_rrs ? (a)->items[UNIQ_T(i, q)].rr : NULL))
+                        (kk) = dns_answer_isempty(a) ? NULL : (a)->items[0].rr; \
+                        0;                                              \
+                });                                                     \
+             UNIQ_T(i, q) < dns_answer_size(a);                         \
+             UNIQ_T(i, q)++,                                            \
+                     (kk) = UNIQ_T(i, q) < dns_answer_size(a) ? (a)->items[UNIQ_T(i, q)].rr : NULL)
 
 #define DNS_ANSWER_FOREACH(kk, a) _DNS_ANSWER_FOREACH(UNIQ, kk, a)
 
 #define _DNS_ANSWER_FOREACH_IFINDEX(q, kk, ifi, a)                      \
         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; \
+                                (kk) = dns_answer_isempty(a) ? NULL : (a)->items[0].rr; \
+                                (ifi) = dns_answer_isempty(a) ? 0 : (a)->items[0].ifindex; \
                                 0;                                      \
                         });                                             \
-             (a) && (UNIQ_T(i, q) < (a)->n_rrs);                        \
+             UNIQ_T(i, q) < dns_answer_size(a);                         \
              UNIQ_T(i, q)++,                                            \
-                     (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \
-                     (ifi) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].ifindex : 0))
+                     (kk) = UNIQ_T(i, q) < dns_answer_size(a) ? (a)->items[UNIQ_T(i, q)].rr : NULL, \
+                     (ifi) = UNIQ_T(i, q) < dns_answer_size(a) ? (a)->items[UNIQ_T(i, q)].ifindex : 0)
 
 #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 (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; \
+                                (kk) = dns_answer_isempty(a) ? NULL : (a)->items[0].rr; \
+                                (fl) = dns_answer_isempty(a) ? 0 : (a)->items[0].flags; \
                                 0;                                      \
                         });                                             \
-             (a) && (UNIQ_T(i, q) < (a)->n_rrs);                        \
+             UNIQ_T(i, q) < dns_answer_size(a);                         \
              UNIQ_T(i, q)++,                                            \
-                     (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \
-                     (fl) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].flags : 0))
+                     (kk) = UNIQ_T(i, q) < dns_answer_size(a) ? (a)->items[UNIQ_T(i, q)].rr : NULL, \
+                     (fl) = UNIQ_T(i, q) < dns_answer_size(a) ? (a)->items[UNIQ_T(i, q)].flags : 0)
 
 #define DNS_ANSWER_FOREACH_FLAGS(kk, flags, a) _DNS_ANSWER_FOREACH_FLAGS(UNIQ, kk, flags, a)
 
@@ -134,6 +135,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref);
                         });                                             \
              UNIQ_T(i, q) < dns_answer_size(a);                         \
              UNIQ_T(i, q)++,                                            \
-                     (item) = ((UNIQ_T(i, q) < dns_answer_size(a)) ? (a)->items + UNIQ_T(i, q) : NULL))
+                     (item) = (UNIQ_T(i, q) < dns_answer_size(a)) ? (a)->items + UNIQ_T(i, q) : NULL)
 
 #define DNS_ANSWER_FOREACH_ITEM(item, a) _DNS_ANSWER_FOREACH_ITEM(UNIQ, item, a)
index c019dc38c9dd41cce12713158cd7b4f7c5498b98..f73ead872dd616efe7c3b799d1118da7dd2bd5e4 100644 (file)
@@ -36,14 +36,13 @@ enum DnsCacheItemType {
 
 struct DnsCacheItem {
         DnsCacheItemType type;
+        int rcode;
         DnsResourceKey *key;     /* The key for this item, i.e. the lookup key */
         DnsResourceRecord *rr;   /* The RR for this item, i.e. the lookup value for positive queries */
         DnsAnswer *answer;       /* The full validated answer, if this is an RRset acquired via a "primary" lookup */
         DnsPacket *full_packet;  /* The full packet this information was acquired with */
-        int rcode;
 
         usec_t until;
-        bool shared_owner:1;
         uint64_t query_flags;    /* SD_RESOLVED_AUTHENTICATED and/or SD_RESOLVED_CONFIDENTIAL */
         DnssecResult dnssec_result;
 
@@ -53,6 +52,8 @@ struct DnsCacheItem {
 
         unsigned prioq_idx;
         LIST_FIELDS(DnsCacheItem, by_key);
+
+        bool shared_owner;
 };
 
 /* Returns true if this is a cache item created as result of an explicit lookup, or created as "side-effect"
@@ -937,6 +938,8 @@ static int answer_add_clamp_ttl(
         if (FLAGS_SET(query_flags, SD_RESOLVED_CLAMP_TTL)) {
                 uint32_t left_ttl;
 
+                assert(current > 0);
+
                 /* Let's determine how much time is left for this cache entry. Note that we round down, but
                  * clamp this to be 1s at minimum, since we usually want records to remain cached better too
                  * short a time than too long a time, but otoh don't want to return 0 ever, since that has
@@ -987,7 +990,7 @@ int dns_cache_lookup(
         bool nxdomain = false;
         DnsCacheItem *j, *first, *nsec = NULL;
         bool have_authenticated = false, have_non_authenticated = false, have_confidential = false, have_non_confidential = false;
-        usec_t current;
+        usec_t current = 0;
         int found_rcode = -1;
         DnssecResult dnssec_result = -1;
         int have_dnssec_result = -1;
@@ -1013,8 +1016,12 @@ int dns_cache_lookup(
                 goto miss;
         }
 
-        if (FLAGS_SET(query_flags, SD_RESOLVED_CLAMP_TTL))
+        if (FLAGS_SET(query_flags, SD_RESOLVED_CLAMP_TTL)) {
+                /* 'current' is always passed to answer_add_clamp_ttl(), but is only used conditionally.
+                 * We'll do the same assert there to make sure that it was initialized properly. */
                 current = now(clock_boottime_or_monotonic());
+                assert(current > 0);
+        }
 
         LIST_FOREACH(by_key, j, first) {
                 /* If the caller doesn't allow us to answer questions from cache data learned from
index 4b12e483523d3723c47069aa46e1cd0d77ce5671..a107769130b0f042d33a364ce5594f24ecafdd45 100644 (file)
@@ -1089,6 +1089,7 @@ static int digest_to_gcrypt_md(uint8_t algorithm) {
 int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) {
         uint8_t wire_format[DNS_WIRE_FORMAT_HOSTNAME_MAX];
         _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
+        gcry_error_t err;
         size_t hash_size;
         int md_algorithm, r;
         void *result;
@@ -1130,8 +1131,8 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds,
         if (r < 0)
                 return r;
 
-        gcry_md_open(&md, md_algorithm, 0);
-        if (!md)
+        err = gcry_md_open(&md, md_algorithm, 0);
+        if (gcry_err_code(err) != GPG_ERR_NO_ERROR || !md)
                 return -EIO;
 
         gcry_md_write(md, wire_format, r);
@@ -1204,7 +1205,8 @@ 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_FORMAT_HOSTNAME_MAX];
-        gcry_md_hd_t md = NULL;
+        _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
+        gcry_error_t err;
         size_t hash_size;
         int algorithm;
         void *result;
@@ -1239,18 +1241,16 @@ int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
         if (r < 0)
                 return r;
 
-        gcry_md_open(&md, algorithm, 0);
-        if (!md)
+        err = gcry_md_open(&md, algorithm, 0);
+        if (gcry_err_code(err) != GPG_ERR_NO_ERROR || !md)
                 return -EIO;
 
         gcry_md_write(md, wire_format, r);
         gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
 
         result = gcry_md_read(md, 0);
-        if (!result) {
-                r = -EIO;
-                goto finish;
-        }
+        if (!result)
+                return -EIO;
 
         for (k = 0; k < nsec3->nsec3.iterations; k++) {
                 uint8_t tmp[hash_size];
@@ -1261,18 +1261,12 @@ int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
                 gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
 
                 result = gcry_md_read(md, 0);
-                if (!result) {
-                        r = -EIO;
-                        goto finish;
-                }
+                if (!result)
+                        return -EIO;
         }
 
         memcpy(ret, result, hash_size);
-        r = (int) hash_size;
-
-finish:
-        gcry_md_close(md);
-        return r;
+        return (int) hash_size;
 }
 
 static int nsec3_is_good(DnsResourceRecord *rr, DnsResourceRecord *nsec3) {
index 8de407d21aed6c243668b7c6e46cb22b23101cf5..a197f94bcfdf84ede66a57154a3df9e7a076b695 100644 (file)
@@ -627,7 +627,7 @@ int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, const DnsAnswer
         if (r < 0)
                 goto fail;
 
-        class = flags & DNS_ANSWER_CACHE_FLUSH ? k->class | MDNS_RR_CACHE_FLUSH : k->class;
+        class = flags & DNS_ANSWER_CACHE_FLUSH ? k->class | MDNS_RR_CACHE_FLUSH_OR_QU : k->class;
         r = dns_packet_append_uint16(p, class, NULL);
         if (r < 0)
                 goto fail;
@@ -1628,12 +1628,12 @@ static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t siz
 int dns_packet_read_key(
                 DnsPacket *p,
                 DnsResourceKey **ret,
-                bool *ret_cache_flush,
+                bool *ret_cache_flush_or_qu,
                 size_t *ret_start) {
 
         _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
         _cleanup_free_ char *name = NULL;
-        bool cache_flush = false;
+        bool cache_flush_or_qu = false;
         uint16_t class, type;
         int r;
 
@@ -1653,11 +1653,11 @@ int dns_packet_read_key(
                 return r;
 
         if (p->protocol == DNS_PROTOCOL_MDNS) {
-                /* See RFC6762, Section 10.2 */
+                /* See RFC6762, sections 5.4 and 10.2 */
 
-                if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH)) {
-                        class &= ~MDNS_RR_CACHE_FLUSH;
-                        cache_flush = true;
+                if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH_OR_QU)) {
+                        class &= ~MDNS_RR_CACHE_FLUSH_OR_QU;
+                        cache_flush_or_qu = true;
                 }
         }
 
@@ -1672,8 +1672,8 @@ int dns_packet_read_key(
                 *ret = key;
         }
 
-        if (ret_cache_flush)
-                *ret_cache_flush = cache_flush;
+        if (ret_cache_flush_or_qu)
+                *ret_cache_flush_or_qu = cache_flush_or_qu;
         if (ret_start)
                 *ret_start = rewinder.saved_rindex;
 
@@ -2221,15 +2221,12 @@ static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question)
 
                 for (i = 0; i < n; i++) {
                         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
-                        bool cache_flush;
+                        bool qu;
 
-                        r = dns_packet_read_key(p, &key, &cache_flush, NULL);
+                        r = dns_packet_read_key(p, &key, &qu, NULL);
                         if (r < 0)
                                 return r;
 
-                        if (cache_flush)
-                                return -EBADMSG;
-
                         if (!dns_type_is_valid_query(key->type))
                                 return -EBADMSG;
 
@@ -2240,7 +2237,7 @@ static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question)
                                 /* Already in the Question, let's skip */
                                 continue;
 
-                        r = dns_question_add_raw(question, key);
+                        r = dns_question_add_raw(question, key, qu ? DNS_QUESTION_WANTS_UNICAST_REPLY : 0);
                         if (r < 0)
                                 return r;
                 }
@@ -2451,7 +2448,7 @@ int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) {
         if (p->question->n_keys != 1)
                 return 0;
 
-        return dns_resource_key_equal(p->question->keys[0], key);
+        return dns_resource_key_equal(dns_question_first_key(p->question), key);
 }
 
 int dns_packet_patch_max_udp_size(DnsPacket *p, uint16_t max_udp_size) {
index 7b2abe3e7643bb2c77ff1180dce713650c72d322..e9820795c0593a8385137a5f64cdacfaec69cf18 100644 (file)
@@ -233,7 +233,7 @@ int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start);
 int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start);
 int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start);
 int dns_packet_read_name(DnsPacket *p, char **ret, bool allow_compression, size_t *start);
-int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start);
+int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush_or_qu, size_t *start);
 int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start);
 
 void dns_packet_rewind(DnsPacket *p, size_t idx);
index e960ac0322730b062d301c11e641c42ea84b952a..5517db149d0827465686c1f8d09b5b4e596df751 100644 (file)
@@ -183,7 +183,7 @@ static DnsTransactionState dns_query_candidate_state(DnsQueryCandidate *c) {
         if (c->error_code != 0)
                 return DNS_TRANSACTION_ERRNO;
 
-        SET_FOREACH(t, c->transactions) {
+        SET_FOREACH(t, c->transactions)
 
                 switch (t->state) {
 
@@ -213,7 +213,6 @@ static DnsTransactionState dns_query_candidate_state(DnsQueryCandidate *c) {
 
                         break;
                 }
-        }
 
         return state;
 }
@@ -232,7 +231,7 @@ static int dns_query_candidate_setup_transactions(DnsQueryCandidate *c) {
 
                 assert(dns_question_size(c->query->question_bypass->question) == 1);
 
-                if (!dns_scope_good_key(c->scope, c->query->question_bypass->question->keys[0]))
+                if (!dns_scope_good_key(c->scope, dns_question_first_key(c->query->question_bypass->question)))
                         return 0;
 
                 r = dns_query_candidate_add_transaction(c, NULL, c->query->question_bypass);
@@ -496,14 +495,14 @@ int dns_query_new(
                         log_debug("Looking up bypass packet for %s.",
                                   dns_resource_key_to_string(key, key_str, sizeof key_str));
         } else {
-                /* First dump UTF8  question */
+                /* First dump UTF8 question */
                 DNS_QUESTION_FOREACH(key, question_utf8)
                         log_debug("Looking up RR for %s.",
                                   dns_resource_key_to_string(key, key_str, sizeof key_str));
 
                 /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
                 DNS_QUESTION_FOREACH(key, question_idna) {
-                        r = dns_question_contains(question_utf8, key);
+                        r = dns_question_contains_key(question_utf8, key);
                         if (r < 0)
                                 return r;
                         if (r > 0)
index ef40932630407471787b1f5d27802f6a1ad37b73..aefdaa0eeb76f53147848fddb3f0aa61620ae775 100644 (file)
@@ -11,7 +11,7 @@ DnsQuestion *dns_question_new(size_t n) {
         if (n > UINT16_MAX) /* We can only place 64K key in an question section at max */
                 n = UINT16_MAX;
 
-        q = malloc0(offsetof(DnsQuestion, keys) + sizeof(DnsResourceKey*) * n);
+        q = malloc0(offsetof(DnsQuestion, items) + sizeof(DnsQuestionItem) * n);
         if (!q)
                 return NULL;
 
@@ -22,18 +22,19 @@ DnsQuestion *dns_question_new(size_t n) {
 }
 
 static DnsQuestion *dns_question_free(DnsQuestion *q) {
-        size_t i;
+        DnsResourceKey *key;
 
         assert(q);
 
-        for (i = 0; i < q->n_keys; i++)
-                dns_resource_key_unref(q->keys[i]);
+        DNS_QUESTION_FOREACH(key, q)
+                dns_resource_key_unref(key);
+
         return mfree(q);
 }
 
 DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsQuestion, dns_question, dns_question_free);
 
-int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key) {
+int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key, DnsQuestionFlags flags) {
         /* Insert without checking for duplicates. */
 
         assert(key);
@@ -42,11 +43,15 @@ int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key) {
         if (q->n_keys >= q->n_allocated)
                 return -ENOSPC;
 
-        q->keys[q->n_keys++] = dns_resource_key_ref(key);
+        q->items[q->n_keys++] = (DnsQuestionItem) {
+                .key = dns_resource_key_ref(key),
+                .flags = flags,
+        };
         return 0;
 }
 
-int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
+int dns_question_add(DnsQuestion *q, DnsResourceKey *key, DnsQuestionFlags flags) {
+        DnsQuestionItem *item;
         int r;
 
         assert(key);
@@ -54,19 +59,20 @@ int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
         if (!q)
                 return -ENOSPC;
 
-        for (size_t i = 0; i < q->n_keys; i++) {
-                r = dns_resource_key_equal(q->keys[i], key);
+
+        DNS_QUESTION_FOREACH_ITEM(item, q) {
+                r = dns_resource_key_equal(item->key, key);
                 if (r < 0)
                         return r;
-                if (r > 0)
+                if (r > 0 && item->flags == flags)
                         return 0;
         }
 
-        return dns_question_add_raw(q, key);
+        return dns_question_add_raw(q, key, flags);
 }
 
 int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
-        size_t i;
+        DnsResourceKey *key;
         int r;
 
         assert(rr);
@@ -74,8 +80,8 @@ int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *s
         if (!q)
                 return 0;
 
-        for (i = 0; i < q->n_keys; i++) {
-                r = dns_resource_key_match_rr(q->keys[i], rr, search_domain);
+        DNS_QUESTION_FOREACH(key, q) {
+                r = dns_resource_key_match_rr(key, rr, search_domain);
                 if (r != 0)
                         return r;
         }
@@ -84,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) {
-        size_t i;
+        DnsResourceKey *key;
         int r;
 
         assert(rr);
@@ -95,12 +101,12 @@ int dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, c
         if (!IN_SET(rr->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME))
                 return 0;
 
-        for (i = 0; i < q->n_keys; i++) {
+        DNS_QUESTION_FOREACH(key, q) {
                 /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */
-                if (!dns_type_may_redirect(q->keys[i]->type))
+                if (!dns_type_may_redirect(key->type))
                         return 0;
 
-                r = dns_resource_key_match_cname_or_dname(q->keys[i], rr->key, search_domain);
+                r = dns_resource_key_match_cname_or_dname(key, rr->key, search_domain);
                 if (r != 0)
                         return r;
         }
@@ -122,38 +128,39 @@ int dns_question_is_valid_for_query(DnsQuestion *q) {
         if (q->n_keys > 65535)
                 return 0;
 
-        name = dns_resource_key_name(q->keys[0]);
+        name = dns_resource_key_name(q->items[0].key);
         if (!name)
                 return 0;
 
         /* Check that all keys in this question bear the same name */
         for (i = 0; i < q->n_keys; i++) {
-                assert(q->keys[i]);
+                assert(q->items[i].key);
 
                 if (i > 0) {
-                        r = dns_name_equal(dns_resource_key_name(q->keys[i]), name);
+                        r = dns_name_equal(dns_resource_key_name(q->items[i].key), name);
                         if (r <= 0)
                                 return r;
                 }
 
-                if (!dns_type_is_valid_query(q->keys[i]->type))
+                if (!dns_type_is_valid_query(q->items[i].key->type))
                         return 0;
         }
 
         return 1;
 }
 
-int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k) {
+int dns_question_contains_key(DnsQuestion *q, const DnsResourceKey *k) {
         size_t j;
         int r;
 
         assert(k);
 
-        if (!a)
+        if (!q)
                 return 0;
 
-        for (j = 0; j < a->n_keys; j++) {
-                r = dns_resource_key_equal(a->keys[j], k);
+
+        for (j = 0; j < q->n_keys; j++) {
+                r = dns_resource_key_equal(q->items[j].key, k);
                 if (r != 0)
                         return r;
         }
@@ -161,8 +168,25 @@ int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k) {
         return 0;
 }
 
+static int dns_question_contains_item(DnsQuestion *q, const DnsQuestionItem *i) {
+        DnsQuestionItem *item;
+        int r;
+
+        assert(i);
+
+        DNS_QUESTION_FOREACH_ITEM(item, q) {
+                if (item->flags != i->flags)
+                        continue;
+                r = dns_resource_key_equal(item->key, i->key);
+                if (r != 0)
+                        return r;
+        }
+
+        return false;
+}
+
 int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) {
-        size_t j;
+        DnsQuestionItem *item;
         int r;
 
         if (a == b)
@@ -173,16 +197,15 @@ int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) {
         if (!b)
                 return a->n_keys == 0;
 
-        /* Checks if all keys in a are also contained b, and vice versa */
+        /* Checks if all items in a are also contained b, and vice versa */
 
-        for (j = 0; j < a->n_keys; j++) {
-                r = dns_question_contains(b, a->keys[j]);
+        DNS_QUESTION_FOREACH_ITEM(item, a) {
+                r = dns_question_contains_item(b, item);
                 if (r <= 0)
                         return r;
         }
-
-        for (j = 0; j < b->n_keys; j++) {
-                r = dns_question_contains(a, b->keys[j]);
+        DNS_QUESTION_FOREACH_ITEM(item, b) {
+                r = dns_question_contains_item(a, item);
                 if (r <= 0)
                         return r;
         }
@@ -249,7 +272,7 @@ int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname,
                 if (!k)
                         return -ENOMEM;
 
-                r = dns_question_add(n, k);
+                r = dns_question_add(n, k, 0);
                 if (r < 0)
                         return r;
         }
@@ -267,7 +290,7 @@ const char *dns_question_first_name(DnsQuestion *q) {
         if (q->n_keys < 1)
                 return NULL;
 
-        return dns_resource_key_name(q->keys[0]);
+        return dns_resource_key_name(q->items[0].key);
 }
 
 int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bool convert_idna) {
@@ -306,7 +329,7 @@ int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bo
                 if (!key)
                         return -ENOMEM;
 
-                r = dns_question_add(q, key);
+                r = dns_question_add(q, key, 0);
                 if (r < 0)
                         return r;
         }
@@ -318,7 +341,7 @@ int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bo
                 if (!key)
                         return -ENOMEM;
 
-                r = dns_question_add(q, key);
+                r = dns_question_add(q, key, 0);
                 if (r < 0)
                         return r;
         }
@@ -354,7 +377,7 @@ int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_
 
         reverse = NULL;
 
-        r = dns_question_add(q, key);
+        r = dns_question_add(q, key, 0);
         if (r < 0)
                 return r;
 
@@ -426,7 +449,7 @@ int dns_question_new_service(
         if (!key)
                 return -ENOMEM;
 
-        r = dns_question_add(q, key);
+        r = dns_question_add(q, key, 0);
         if (r < 0)
                 return r;
 
@@ -436,7 +459,7 @@ int dns_question_new_service(
                 if (!key)
                         return -ENOMEM;
 
-                r = dns_question_add(q, key);
+                r = dns_question_add(q, key, 0);
                 if (r < 0)
                         return r;
         }
index 8f9a84c82d936d6e088a118febfddca6a4121f04..31b8a2ec3efc3772156d3ab1f9df1d1feeffd479 100644 (file)
@@ -2,16 +2,26 @@
 #pragma once
 
 typedef struct DnsQuestion DnsQuestion;
+typedef struct DnsQuestionItem DnsQuestionItem;
 
 #include "macro.h"
 #include "resolved-dns-rr.h"
 
 /* A simple array of resource keys */
 
+typedef enum DnsQuestionFlags {
+        DNS_QUESTION_WANTS_UNICAST_REPLY = 1 << 0, /* For mDNS: sender is willing to accept unicast replies */
+} DnsQuestionFlags;
+
+struct DnsQuestionItem {
+        DnsResourceKey *key;
+        DnsQuestionFlags flags;
+};
+
 struct DnsQuestion {
         unsigned n_ref;
         size_t n_keys, n_allocated;
-        DnsResourceKey* keys[0];
+        DnsQuestionItem items[0];
 };
 
 DnsQuestion *dns_question_new(size_t n);
@@ -22,13 +32,13 @@ int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bo
 int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a);
 int dns_question_new_service(DnsQuestion **ret, const char *service, const char *type, const char *domain, bool with_txt, bool convert_idna);
 
-int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key);
-int dns_question_add(DnsQuestion *q, DnsResourceKey *key);
+int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key, DnsQuestionFlags flags);
+int dns_question_add(DnsQuestion *q, DnsResourceKey *key, DnsQuestionFlags flags);
 
 int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain);
 int dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, const char* search_domain);
 int dns_question_is_valid_for_query(DnsQuestion *q);
-int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k);
+int dns_question_contains_key(DnsQuestion *q, const DnsResourceKey *k);
 int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b);
 
 int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret);
@@ -37,6 +47,10 @@ void dns_question_dump(DnsQuestion *q, FILE *f);
 
 const char *dns_question_first_name(DnsQuestion *q);
 
+static inline DnsResourceKey *dns_question_first_key(DnsQuestion *q) {
+        return (q && q->n_keys > 0) ? q->items[0].key : NULL;
+}
+
 static inline size_t dns_question_size(DnsQuestion *q) {
         return q ? q->n_keys : 0;
 }
@@ -47,12 +61,22 @@ static inline bool dns_question_isempty(DnsQuestion *q) {
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuestion*, dns_question_unref);
 
-#define _DNS_QUESTION_FOREACH(u, key, q)                                \
-        for (size_t UNIQ_T(i, u) = ({                                 \
-                                (key) = ((q) && (q)->n_keys > 0) ? (q)->keys[0] : NULL; \
-                                0;                                      \
-                        });                                             \
-             (q) && (UNIQ_T(i, u) < (q)->n_keys);                       \
-             UNIQ_T(i, u)++, (key) = (UNIQ_T(i, u) < (q)->n_keys ? (q)->keys[UNIQ_T(i, u)] : NULL))
+#define _DNS_QUESTION_FOREACH(u, k, q)                                     \
+        for (size_t UNIQ_T(i, u) = ({                                      \
+                                (k) = ((q) && (q)->n_keys > 0) ? (q)->items[0].key : NULL; \
+                                0;                                         \
+                        });                                                \
+             (q) && (UNIQ_T(i, u) < (q)->n_keys);                          \
+             UNIQ_T(i, u)++, (k) = (UNIQ_T(i, u) < (q)->n_keys ? (q)->items[UNIQ_T(i, u)].key : NULL))
 
 #define DNS_QUESTION_FOREACH(key, q) _DNS_QUESTION_FOREACH(UNIQ, key, q)
+
+#define _DNS_QUESTION_FOREACH_ITEM(u, item, q)                             \
+        for (size_t UNIQ_T(i, u) = ({                                      \
+                     (item) = dns_question_isempty(q) ? NULL : (q)->items; \
+                     0;                                                    \
+             });                                                           \
+             UNIQ_T(i, u) < dns_question_size(q);                          \
+             UNIQ_T(i, u)++, (item) = (UNIQ_T(i, u) < dns_question_size(q) ? (q)->items + UNIQ_T(i, u) : NULL))
+
+#define DNS_QUESTION_FOREACH_ITEM(item, q) _DNS_QUESTION_FOREACH_ITEM(UNIQ, item, q)
index ab48ea5f2a091297168491c236adad1b68f9404b..43bbcb30735b77c3b1e8bc7f5a09d89298afa0ee 100644 (file)
@@ -16,12 +16,12 @@ typedef struct DnsResourceRecord DnsResourceRecord;
 typedef struct DnsTxtItem DnsTxtItem;
 
 /* DNSKEY RR flags */
-#define DNSKEY_FLAG_SEP      (UINT16_C(1) << 0)
-#define DNSKEY_FLAG_REVOKE   (UINT16_C(1) << 7)
-#define DNSKEY_FLAG_ZONE_KEY (UINT16_C(1) << 8)
+#define DNSKEY_FLAG_SEP            (UINT16_C(1) << 0)
+#define DNSKEY_FLAG_REVOKE         (UINT16_C(1) << 7)
+#define DNSKEY_FLAG_ZONE_KEY       (UINT16_C(1) << 8)
 
 /* mDNS RR flags */
-#define MDNS_RR_CACHE_FLUSH  (UINT16_C(1) << 15)
+#define MDNS_RR_CACHE_FLUSH_OR_QU  (UINT16_C(1) << 15)
 
 /* DNSSEC algorithm identifiers, see
  * http://tools.ietf.org/html/rfc4034#appendix-A.1 and
index 67c6f54dc5d9f17dbc47544240fc866961b567d2..178482727c3ecb95611bfa4de08fdc20bda851e7 100644 (file)
@@ -287,17 +287,23 @@ static int dns_scope_emit_one(DnsScope *s, int fd, int family, DnsPacket *p) {
                         return -EBUSY;
 
                 if (family == AF_INET) {
-                        addr.in = MDNS_MULTICAST_IPV4_ADDRESS;
+                        if (in4_addr_is_null(&p->destination.in))
+                                addr.in = MDNS_MULTICAST_IPV4_ADDRESS;
+                        else
+                                addr = p->destination;
                         fd = manager_mdns_ipv4_fd(s->manager);
                 } else if (family == AF_INET6) {
-                        addr.in6 = MDNS_MULTICAST_IPV6_ADDRESS;
+                        if (in6_addr_is_null(&p->destination.in6))
+                                addr.in6 = MDNS_MULTICAST_IPV6_ADDRESS;
+                        else
+                                addr = p->destination;
                         fd = manager_mdns_ipv6_fd(s->manager);
                 } else
                         return -EAFNOSUPPORT;
                 if (fd < 0)
                         return fd;
 
-                r = manager_send(s->manager, fd, s->link->ifindex, family, &addr, MDNS_PORT, NULL, p);
+                r = manager_send(s->manager, fd, s->link->ifindex, family, &addr, p->destination_port ?: MDNS_PORT, NULL, p);
                 if (r < 0)
                         return r;
 
@@ -624,8 +630,8 @@ DnsScopeMatch dns_scope_good_domain(
         if (dns_name_endswith(domain, "invalid") > 0)
                 return DNS_SCOPE_NO;
 
-        /* Never go to network for the _gateway domain, it's something special, synthesized locally. */
-        if (is_gateway_hostname(domain))
+        /* Never go to network for the _gateway or _outbound domain — they're something special, synthesized locally. */
+        if (is_gateway_hostname(domain) || is_outbound_hostname(domain))
                 return DNS_SCOPE_NO;
 
         switch (s->protocol) {
@@ -733,6 +739,7 @@ DnsScopeMatch dns_scope_good_domain(
 
                 if ((dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */
                      !is_gateway_hostname(domain) && /* don't resolve "_gateway" with LLMNR, let local synthesizing logic handle that */
+                     !is_outbound_hostname(domain) && /* similar for "_outbound" */
                      dns_name_equal(domain, "local") == 0 && /* don't resolve "local" with LLMNR, it's the top-level domain of mDNS after all, see above */
                      manager_is_own_hostname(s->manager, domain) <= 0))  /* never resolve the local hostname via LLMNR */
                         return DNS_SCOPE_YES_BASE + 1; /* Return +1, as we consider ourselves authoritative
@@ -984,7 +991,7 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
         }
 
         assert(dns_question_size(p->question) == 1);
-        key = p->question->keys[0];
+        key = dns_question_first_key(p->question);
 
         r = dns_zone_lookup(&s->zone, key, 0, &answer, &soa, &tentative);
         if (r < 0) {
@@ -1441,7 +1448,7 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) {
 
         /* Since all the active services are in the zone make them discoverable now. */
         SET_FOREACH(service_type, types) {
-                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr;
+                _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
 
                 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR,
                                                   "_services._dns-sd._udp.local");
index 10641f6ac59d943aece88fb1b50caa770071c2bc..3e6505cd75b879c00ffcbd33526d43fd2ac82f62 100644 (file)
@@ -315,15 +315,14 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
             s->write_packet &&
             s->n_written < sizeof(s->write_size) + s->write_packet->size) {
 
-                struct iovec iov[2];
-                ssize_t ss;
-
-                iov[0] = IOVEC_MAKE(&s->write_size, sizeof(s->write_size));
-                iov[1] = IOVEC_MAKE(DNS_PACKET_DATA(s->write_packet), s->write_packet->size);
+                struct iovec iov[] = {
+                        IOVEC_MAKE(&s->write_size, sizeof(s->write_size)),
+                        IOVEC_MAKE(DNS_PACKET_DATA(s->write_packet), s->write_packet->size),
+                };
 
-                IOVEC_INCREMENT(iov, 2, s->n_written);
+                IOVEC_INCREMENT(iov, ELEMENTSOF(iov), s->n_written);
 
-                ss = dns_stream_writev(s, iov, 2, 0);
+                ssize_t ss = dns_stream_writev(s, iov, ELEMENTSOF(iov), 0);
                 if (ss < 0) {
                         if (!IN_SET(-ss, EINTR, EAGAIN))
                                 return dns_stream_complete(s, -ss);
index 602720bf505d6decee5845c2b9953e9cf3076e45..5b9d32f0013085758eb228541f089c8bc7232e85 100644 (file)
@@ -433,6 +433,7 @@ static int dns_stub_finish_reply_packet(
                 int rcode,
                 bool tc,        /* set the Truncated bit? */
                 bool aa,        /* set the Authoritative Answer bit? */
+                bool rd,        /* set the Recursion Desired bit? */
                 bool add_opt,   /* add an OPT RR to this packet? */
                 bool edns0_do,  /* set the EDNS0 DNSSEC OK bit? */
                 bool ad,        /* set the DNSSEC authenticated data bit? */
@@ -473,7 +474,7 @@ static int dns_stub_finish_reply_packet(
                                                               0  /* opcode */,
                                                               aa /* aa */,
                                                               tc /* tc */,
-                                                               /* rd */,
+                                                              rd /* rd */,
                                                               1  /* ra */,
                                                               ad /* ad */,
                                                               cd /* cd */,
@@ -581,6 +582,7 @@ static int dns_stub_send_reply(
                         rcode,
                         truncated,
                         dns_query_fully_authoritative(q),
+                        DNS_PACKET_RD(q->request_packet),
                         !!q->request_packet->opt,
                         edns0_do,
                         DNS_PACKET_AD(q->request_packet) && dns_query_fully_authenticated(q),
@@ -622,6 +624,7 @@ static int dns_stub_send_failure(
                         rcode,
                         truncated,
                         false,
+                        DNS_PACKET_RD(p),
                         !!p->opt,
                         DNS_PACKET_DO(p),
                         DNS_PACKET_AD(p) && authenticated,
@@ -879,13 +882,13 @@ static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStrea
                 return;
         }
 
-        if (dns_type_is_obsolete(p->question->keys[0]->type)) {
+        if (dns_type_is_obsolete(dns_question_first_key(p->question)->type)) {
                 log_debug("Got message with obsolete key type, refusing.");
                 dns_stub_send_failure(m, l, s, p, DNS_RCODE_REFUSED, false);
                 return;
         }
 
-        if (dns_type_is_zone_transer(p->question->keys[0]->type)) {
+        if (dns_type_is_zone_transer(dns_question_first_key(p->question)->type)) {
                 log_debug("Got request for zone transfer, refusing.");
                 dns_stub_send_failure(m, l, s, p, DNS_RCODE_REFUSED, false);
                 return;
index d4a4be71b07a038eb54b3f1e30aa34cfefd038e7..ef1423f44169521856dec0dd9d27f716f8ab0267 100644 (file)
@@ -311,27 +311,33 @@ static int synthesize_system_hostname_ptr(Manager *m, int af, const union in_add
         return added;
 }
 
-static int synthesize_gateway_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
+static int synthesize_gateway_rr(
+                Manager *m,
+                const DnsResourceKey *key,
+                int ifindex,
+                int (*lookup)(sd_netlink *context, int ifindex, int af, struct local_address **ret), /* either local_gateways() or local_outbound() */
+                DnsAnswer **answer) {
         _cleanup_free_ struct local_address *addresses = NULL;
         int n = 0, af, r;
 
         assert(m);
         assert(key);
+        assert(lookup);
         assert(answer);
 
         af = dns_type_to_af(key->type);
         if (af >= 0) {
-                n = local_gateways(m->rtnl, ifindex, af, &addresses);
+                n = lookup(m->rtnl, ifindex, af, &addresses);
                 if (n < 0) /* < 0 means: error */
                         return n;
 
                 if (n == 0) { /* == 0 means we have no gateway */
                         /* See if there's a gateway on the other protocol */
                         if (af == AF_INET)
-                                n = local_gateways(m->rtnl, ifindex, AF_INET6, NULL);
+                                n = lookup(m->rtnl, ifindex, AF_INET6, NULL);
                         else {
                                 assert(af == AF_INET6);
-                                n = local_gateways(m->rtnl, ifindex, AF_INET, NULL);
+                                n = lookup(m->rtnl, ifindex, AF_INET, NULL);
                         }
                         if (n <= 0) /* error (if < 0) or really no gateway at all (if == 0) */
                                 return n;
@@ -402,7 +408,7 @@ int dns_synthesize_answer(
 
                 } else if (is_gateway_hostname(name)) {
 
-                        r = synthesize_gateway_rr(m, key, ifindex, &answer);
+                        r = synthesize_gateway_rr(m, key, ifindex, local_gateways, &answer);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
                         if (r == 0) { /* if we have no gateway return NXDOMAIN */
@@ -410,6 +416,16 @@ int dns_synthesize_answer(
                                 continue;
                         }
 
+                } else if (is_outbound_hostname(name)) {
+
+                        r = synthesize_gateway_rr(m, key, ifindex, local_outbounds, &answer);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to synthesize outbound RRs: %m");
+                        if (r == 0) { /* if we have no gateway return NXDOMAIN */
+                                nxdomain = true;
+                                continue;
+                        }
+
                 } else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
                            dns_name_equal(name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) {
 
@@ -431,6 +447,10 @@ int dns_synthesize_answer(
                         if (v == 0 && w == 0) /* This IP address is neither a local one nor a gateway */
                                 continue;
 
+                        /* Note that we never synthesize reverse PTR for _outbound, since those are local
+                         * addresses and thus mapped to the local hostname anyway, hence they already have a
+                         * mapping. */
+
                 } else
                         continue;
 
index 6eac7e9c579f7d046ad5ba10335d57e881ca5131..89a8e415e8c6c96173e32392e36316c3847d4cc9 100644 (file)
@@ -510,7 +510,7 @@ static void dns_transaction_retry(DnsTransaction *t, bool next_server) {
 
         /* Retries the transaction as it is, possibly on a different server */
 
-        if (next_server)
+        if (next_server && t->scope->protocol == DNS_PROTOCOL_DNS)
                 log_debug("Retrying transaction %" PRIu16 ", after switching servers.", t->id);
         else
                 log_debug("Retrying transaction %" PRIu16 ".", t->id);
@@ -1510,7 +1510,10 @@ static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdat
         assert(s);
         assert(t);
 
-        if (!t->initial_jitter_scheduled || t->initial_jitter_elapsed) {
+        if (t->initial_jitter_scheduled && !t->initial_jitter_elapsed) {
+                log_debug("Initial jitter phase for transaction %" PRIu16 " elapsed.", t->id);
+                t->initial_jitter_elapsed = true;
+        } else {
                 /* Timeout reached? Increase the timeout for the server used */
                 switch (t->scope->protocol) {
 
@@ -1528,14 +1531,12 @@ static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdat
                         assert_not_reached("Invalid DNS protocol.");
                 }
 
-                if (t->initial_jitter_scheduled)
-                        t->initial_jitter_elapsed = true;
+                log_debug("Timeout reached on transaction %" PRIu16 ".", t->id);
         }
 
-        log_debug("Timeout reached on transaction %" PRIu16 ".", t->id);
-
-        dns_transaction_retry(t, true); /* try a different server, but given this means packet loss, let's do
-                                         * so even if we already tried a bunch */
+        dns_transaction_retry(t, /* next_server= */ true); /* try a different server, but given this means
+                                                            * packet loss, let's do so even if we already
+                                                            * tried a bunch */
         return 0;
 }
 
@@ -1928,8 +1929,8 @@ int dns_transaction_go(DnsTransaction *t) {
         if (r <= 0)
                 return r;
 
-        log_debug("%s transaction %" PRIu16 " for <%s> scope %s on %s/%s (validate=%s).",
-                  t->bypass ? "Bypass" : "Regular",
+        log_debug("Firing %s transaction %" PRIu16 " for <%s> scope %s on %s/%s (validate=%s).",
+                  t->bypass ? "bypass" : "regular",
                   t->id,
                   dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str),
                   dns_protocol_to_string(t->scope->protocol),
@@ -1941,34 +1942,33 @@ int dns_transaction_go(DnsTransaction *t) {
             IN_SET(t->scope->protocol, DNS_PROTOCOL_LLMNR, DNS_PROTOCOL_MDNS)) {
                 usec_t jitter, accuracy;
 
-                /* RFC 4795 Section 2.7 suggests all queries should be
-                 * delayed by a random time from 0 to JITTER_INTERVAL. */
+                /* RFC 4795 Section 2.7 suggests all queries should be delayed by a random time from 0 to
+                 * JITTER_INTERVAL. */
 
                 t->initial_jitter_scheduled = true;
 
-                random_bytes(&jitter, sizeof(jitter));
-
                 switch (t->scope->protocol) {
 
                 case DNS_PROTOCOL_LLMNR:
-                        jitter %= LLMNR_JITTER_INTERVAL_USEC;
+                        jitter = random_u64_range(LLMNR_JITTER_INTERVAL_USEC);
                         accuracy = LLMNR_JITTER_INTERVAL_USEC;
                         break;
 
                 case DNS_PROTOCOL_MDNS:
-                        jitter %= MDNS_JITTER_RANGE_USEC;
-                        jitter += MDNS_JITTER_MIN_USEC;
+                        jitter = usec_add(random_u64_range(MDNS_JITTER_RANGE_USEC), MDNS_JITTER_MIN_USEC);
                         accuracy = MDNS_JITTER_RANGE_USEC;
                         break;
                 default:
                         assert_not_reached("bad protocol");
                 }
 
-                r = sd_event_add_time(
+                assert(!t->timeout_event_source);
+
+                r = sd_event_add_time_relative(
                                 t->scope->manager->event,
                                 &t->timeout_event_source,
                                 clock_boottime_or_monotonic(),
-                                ts + jitter, accuracy,
+                                jitter, accuracy,
                                 on_transaction_timeout, t);
                 if (r < 0)
                         return r;
@@ -1979,7 +1979,10 @@ int dns_transaction_go(DnsTransaction *t) {
                 t->next_attempt_after = ts;
                 t->state = DNS_TRANSACTION_PENDING;
 
-                log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter);
+                log_debug("Delaying %s transaction %" PRIu16 " for " USEC_FMT "us.",
+                          dns_protocol_to_string(t->scope->protocol),
+                          t->id,
+                          jitter);
                 return 1;
         }
 
@@ -2222,13 +2225,7 @@ static int dns_transaction_has_unsigned_negative_answer(DnsTransaction *t) {
          * question. If so, let's see if there are any NSEC/NSEC3 RRs
          * included. If not, the answer is unsigned. */
 
-        r = dns_answer_contains_nsec_or_nsec3(t->answer);
-        if (r < 0)
-                return r;
-        if (r > 0)
-                return false;
-
-        return true;
+        return !dns_answer_contains_nsec_or_nsec3(t->answer);
 }
 
 static int dns_transaction_is_primary_response(DnsTransaction *t, DnsResourceRecord *rr) {
index a8ec6e18d5cafa68ca54ae806ddbd1716496d45e..c2d73cbedc5dac6a9ce473f4da0bf0f9ae5e1801 100644 (file)
@@ -166,10 +166,7 @@ static inline DnsResourceKey *dns_transaction_key(DnsTransaction *t) {
 
         assert(t->bypass);
 
-        if (dns_question_isempty(t->bypass->question))
-                return NULL;
-
-        return t->bypass->question->keys[0];
+        return dns_question_first_key(t->bypass->question);
 }
 
 static inline uint64_t dns_transaction_source_to_query_flags(DnsTransactionSource s) {
index 8ba459b3e53bfa19e90d34e6dd2a9f57aeb62ed3..b036aa402c4411fce7b9cb4b7814949bbddeee38 100644 (file)
@@ -160,7 +160,10 @@ static int dns_trust_anchor_add_builtin_negative(DnsTrustAnchor *d) {
                 "lan\0"
                 "intranet\0"
                 "internal\0"
-                "private\0";
+                "private\0"
+
+                /* Defined by RFC 8375. The most official choice. */
+                "home.arpa\0";
 
         const char *name;
         int r;
index d56d5de4df7cafe1f710596ff3255d998d7b3119..8d533d7ecf9ad1dc2f63f862a8872a402e94efcb 100644 (file)
@@ -386,7 +386,7 @@ int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_
                 if (r == 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name);
                 if (!route_only && dns_name_is_root(name))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain");
+                        return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain");
 
                 if (route_only) {
                         prefixed = strjoin("~", name);
index 2857b58e89e287003b63b99d6f820e601c2ec8a5..0d19d084556a9dd06b2d533aa065da9bbb63787f 100644 (file)
@@ -10,7 +10,7 @@
 #include "resolved-mdns.h"
 #include "sort-util.h"
 
-#define CLEAR_CACHE_FLUSH(x) (~MDNS_RR_CACHE_FLUSH & (x))
+#define CLEAR_CACHE_FLUSH(x) (~MDNS_RR_CACHE_FLUSH_OR_QU & (x))
 
 void manager_mdns_stop(Manager *m) {
         assert(m);
@@ -173,12 +173,69 @@ static int mdns_do_tiebreak(DnsResourceKey *key, DnsAnswer *answer, DnsPacket *p
         return 0;
 }
 
+static bool mdns_should_reply_using_unicast(DnsPacket *p) {
+        DnsQuestionItem *item;
+
+        /* Work out if we should respond using multicast or unicast. */
+
+        /* The query was a legacy "one-shot mDNS query", RFC 6762, sections 5.1 and 6.7 */
+        if (p->sender_port != MDNS_PORT)
+                return true;
+
+        /* The query was a "direct unicast query", RFC 6762, section 5.5 */
+        switch (p->family) {
+        case AF_INET:
+                if (!in4_addr_equal(&p->destination.in, &MDNS_MULTICAST_IPV4_ADDRESS))
+                        return true;
+                break;
+        case AF_INET6:
+                if (!in6_addr_equal(&p->destination.in6, &MDNS_MULTICAST_IPV6_ADDRESS))
+                        return true;
+                break;
+        }
+
+        /* All the questions in the query had a QU bit set, RFC 6762, section 5.4 */
+        DNS_QUESTION_FOREACH_ITEM(item, p->question) {
+                if (!FLAGS_SET(item->flags, DNS_QUESTION_WANTS_UNICAST_REPLY))
+                        return false;
+        }
+        return true;
+}
+
+static bool sender_on_local_subnet(DnsScope *s, DnsPacket *p) {
+        LinkAddress *a;
+        int r;
+
+        /* Check whether the sender is on a local subnet. */
+
+        if (!s->link)
+                return false;
+
+        LIST_FOREACH(addresses, a, s->link->addresses) {
+                if (a->family != p->family)
+                        continue;
+                if (a->prefixlen == UCHAR_MAX) /* don't know subnet mask */
+                        continue;
+
+                r = in_addr_prefix_covers(a->family, &a->in_addr, a->prefixlen, &p->sender);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to determine whether link address covers sender address: %m");
+                if (r > 0)
+                        return true;
+        }
+
+        return false;
+}
+
+
 static int mdns_scope_process_query(DnsScope *s, DnsPacket *p) {
         _cleanup_(dns_answer_unrefp) DnsAnswer *full_answer = NULL;
         _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
         DnsResourceKey *key = NULL;
         DnsResourceRecord *rr;
         bool tentative = false;
+        bool legacy_query = p->sender_port != MDNS_PORT;
+        bool unicast_reply;
         int r;
 
         assert(s);
@@ -190,8 +247,18 @@ static int mdns_scope_process_query(DnsScope *s, DnsPacket *p) {
 
         assert_return((dns_question_size(p->question) > 0), -EINVAL);
 
+        unicast_reply = mdns_should_reply_using_unicast(p);
+        if (unicast_reply && !sender_on_local_subnet(s, p)) {
+                /* RFC 6762, section 5.5 recommends silently ignoring unicast queries
+                 * from senders outside the local network, so that we don't reveal our
+                 * internal network structure to outsiders. */
+                log_debug("Sender wants a unicast reply, but is not on a local subnet. Ignoring.");
+                return 0;
+        }
+
         DNS_QUESTION_FOREACH(key, p->question) {
                 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
+                DnsAnswerItem *item;
 
                 r = dns_zone_lookup(&s->zone, key, 0, &answer, &soa, &tentative);
                 if (r < 0)
@@ -222,21 +289,48 @@ static int mdns_scope_process_query(DnsScope *s, DnsPacket *p) {
                         }
                 }
 
-                r = dns_answer_extend(&full_answer, answer);
-                if (r < 0)
-                        return log_debug_errno(r, "Failed to extend answer: %m");
+                if (dns_answer_isempty(answer))
+                        continue;
+
+                /* Copy answer items from full_answer to answer, tweaking them if needed. */
+                if (full_answer) {
+                        r = dns_answer_reserve(&full_answer, dns_answer_size(answer));
+                        if (r < 0)
+                                return log_debug_errno(r, "Failed to reserve space in answer");
+                } else {
+                        full_answer = dns_answer_new(dns_answer_size(answer));
+                        if (!full_answer)
+                                return log_oom();
+                }
+
+                DNS_ANSWER_FOREACH_ITEM(item, answer) {
+                        DnsAnswerFlags flags = item->flags;
+                        /* The cache-flush bit must not be set in legacy unicast responses.
+                         * See section 6.7 of RFC 6762. */
+                        if (legacy_query)
+                                flags &= ~DNS_ANSWER_CACHE_FLUSH;
+                        r = dns_answer_add(full_answer, item->rr, item->ifindex, flags, item->rrsig);
+                        if (r < 0)
+                                return log_debug_errno(r, "Failed to extend answer: %m");
+                }
         }
 
         if (dns_answer_isempty(full_answer))
                 return 0;
 
-        r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, NULL, full_answer, NULL, false, &reply);
+        r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS,
+                                        legacy_query ? p->question : NULL, full_answer,
+                                        NULL, false, &reply);
         if (r < 0)
                 return log_debug_errno(r, "Failed to build reply packet: %m");
 
         if (!ratelimit_below(&s->ratelimit))
                 return 0;
 
+        if (unicast_reply) {
+                reply->destination = p->sender;
+                reply->destination_port = p->sender_port;
+        }
         r = dns_scope_emit_udp(s, -1, AF_UNSPEC, reply);
         if (r < 0)
                 return log_debug_errno(r, "Failed to send reply packet: %m");
index f88a4e97c0d9b7e4cb74d688e884e2134e917aa0..0ef77fc6e7a72631e58dec1a90338d119b479b43 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Entries in this file show the compile time defaults. Local configuration
 # should be created by either modifying this file, or by creating "drop-ins" in
-# the system.conf.d/ subdirectory. The latter is generally recommended.
+# the resolved.conf.d/ subdirectory. The latter is generally recommended.
 # Defaults can be restored by simply deleting this file and all drop-ins.
 #
 # Use 'systemd-analyze cat-config systemd/resolved.conf' to display the full config.
@@ -16,9 +16,9 @@
 
 [Resolve]
 # Some examples of DNS servers which may be used for DNS= and FallbackDNS=:
-# Cloudflare: 1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001
-# Google:     8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844
-# Quad9:      9.9.9.9 2620:fe::fe
+# Cloudflare: 1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 2606:4700:4700::1001#cloudflare-dns.com
+# Google:     8.8.8.8#dns.google 8.8.4.4#dns.google 2001:4860:4860::8888#dns.google 2001:4860:4860::8844#dns.google
+# Quad9:      9.9.9.9#dns.quad9.net 2620:fe::fe#dns.quad9.net
 #DNS=
 #FallbackDNS=@DNS_SERVERS@
 #Domains=
index e2d1a1be5fae3d33359a2f7955b687c49239c999..bff1a2886be3bd7afca6d3f52ecfd7d0ad68ef00 100644 (file)
@@ -177,7 +177,7 @@ static int load_state(Context *c, const struct rfkill_event *event) {
         ssize_t l = write(c->rfkill_fd, &we, sizeof we);
         if (l < 0)
                 return log_error_errno(errno, "Failed to restore rfkill state for %i: %m", event->idx);
-        if (l < RFKILL_EVENT_SIZE_V1)
+        if ((size_t)l < RFKILL_EVENT_SIZE_V1) /* l cannot be < 0 here. Cast to fix -Werror=sign-compare */
                 return log_error_errno(SYNTHETIC_ERRNO(EIO),
                                        "Couldn't write rfkill event structure, too short (wrote %zd of %zu bytes).",
                                        l, sizeof we);
@@ -335,9 +335,9 @@ static int run(int argc, char *argv[]) {
                         break;
                 }
 
-                if (l < RFKILL_EVENT_SIZE_V1)
-                        return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read of struct rfkill_event: (%zd < %d)",
-                                               l, RFKILL_EVENT_SIZE_V1);
+                if ((size_t)l < RFKILL_EVENT_SIZE_V1) /* l cannot be < 0 here. Cast to fix -Werror=sign-compare */
+                        return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read of struct rfkill_event: (%zd < %zu)",
+                                               l, (size_t) RFKILL_EVENT_SIZE_V1); /* Casting necessary to make compiling with different kernel versions happy */
                 log_debug("Reading struct rfkill_event: got %zd bytes.", l);
 
                 /* The event structure has more fields. We only care about the first few, so it's OK if we
index 24996de10ab46710ddc670ef6832a70267721e26..244c274d29789007b948d721ce231584cd820a83 100644 (file)
@@ -47,8 +47,8 @@ OrderWithRequires(postun): systemd \
 %systemd_post() \
 %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_post}} \
 if [ $1 -eq 1 ] && [ -x @bindir@/systemctl ]; then \
-        # Initial installation \
-        @bindir@/systemctl --no-reload preset %{?*} || : \
+    # Initial installation \
+    @bindir@/systemctl --no-reload preset %{?*} || : \
 fi \
 %{nil}
 
@@ -57,16 +57,20 @@ fi \
 %systemd_preun() \
 %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_preun}} \
 if [ $1 -eq 0 ] && [ -x @bindir@/systemctl ]; then \
-        # Package removal, not upgrade \
-        @bindir@/systemctl --no-reload disable --now %{?*} || : \
+    # Package removal, not upgrade \
+    if [ -d /run/systemd/system ]; then \
+          @bindir@/systemctl --no-reload disable --now %{?*} || : \
+    else \
+          @bindir@/systemctl --no-reload disable %{?*} || : \
+    fi \
 fi \
 %{nil}
 
 %systemd_user_preun() \
 %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_preun}} \
 if [ $1 -eq 0 ] && [ -x @bindir@/systemctl ]; then \
-        # Package removal, not upgrade \
-        @bindir@/systemctl --global disable %{?*} || : \
+    # Package removal, not upgrade \
+    @bindir@/systemctl --global disable %{?*} || : \
 fi \
 %{nil}
 
@@ -81,10 +85,10 @@ fi \
 %systemd_postun_with_restart() \
 %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_postun_with_restart}} \
 if [ $1 -ge 1 ] && [ -x @bindir@/systemctl ]; then \
-        # Package upgrade, not uninstall \
-        for unit in %{?*}; do \
-                @bindir@/systemctl set-property $unit Markers=+needs-restart || : \
-        done \
+    # Package upgrade, not uninstall \
+    for unit in %{?*}; do \
+         @bindir@/systemctl set-property $unit Markers=+needs-restart || : \
+    done \
 fi \
 %{nil}
 
index ef4b88361f29bf14d62f85dee9e4c583670d2aae..10e1857649403a0380b33b8a97d2b83958c6a7f8 100644 (file)
@@ -211,7 +211,7 @@ int acl_search_groups(const char *path, char ***ret_groups) {
 
 int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) {
         _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not freed */
-        _cleanup_strv_free_ char **split;
+        _cleanup_strv_free_ char **split = NULL;
         char **entry;
         int r = -EINVAL;
         _cleanup_(acl_freep) acl_t a_acl = NULL, d_acl = NULL;
@@ -233,7 +233,7 @@ int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want
         }
 
         if (!strv_isempty(a)) {
-                _cleanup_free_ char *join;
+                _cleanup_free_ char *join = NULL;
 
                 join = strv_join(a, ",");
                 if (!join)
@@ -251,7 +251,7 @@ int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want
         }
 
         if (!strv_isempty(d)) {
-                _cleanup_free_ char *join;
+                _cleanup_free_ char *join = NULL;
 
                 join = strv_join(d, ",");
                 if (!join)
index 729aa1fb00a20ec4ab7c522f87853fa304cd58f2..04c6b5287ed3f1bd9bfe9bf96d8b8e62a31e5d77 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "alloc-util.h"
 #include "ask-password-api.h"
+#include "creds-util.h"
 #include "def.h"
 #include "fd-util.h"
 #include "fileio.h"
@@ -971,11 +972,33 @@ finish:
         return r;
 }
 
+static int ask_password_credential(const char *credential_name, AskPasswordFlags flags, char ***ret) {
+        _cleanup_(erase_and_freep) char *buffer = NULL;
+        size_t size;
+        char **l;
+        int r;
+
+        assert(credential_name);
+        assert(ret);
+
+        r = read_credential(credential_name, (void**) &buffer, &size);
+        if (IN_SET(r, -ENXIO, -ENOENT)) /* No credentials passed or this credential not defined? */
+                return -ENOKEY;
+
+        l = strv_parse_nulstr(buffer, size);
+        if (!l)
+                return -ENOMEM;
+
+        *ret = l;
+        return 0;
+}
+
 int ask_password_auto(
                 const char *message,
                 const char *icon,
-                const char *id,
-                const char *keyname,
+                const char *id,                /* id in "ask-password" protocol */
+                const char *key_name,          /* name in kernel keyring */
+                const char *credential_name,   /* name in $CREDENTIALS_DIRECTORY directory */
                 usec_t until,
                 AskPasswordFlags flags,
                 char ***ret) {
@@ -984,20 +1007,26 @@ int ask_password_auto(
 
         assert(ret);
 
+        if (!(flags & ASK_PASSWORD_NO_CREDENTIAL) && credential_name) {
+                r = ask_password_credential(credential_name, flags, ret);
+                if (r != -ENOKEY)
+                        return r;
+        }
+
         if ((flags & ASK_PASSWORD_ACCEPT_CACHED) &&
-            keyname &&
+            key_name &&
             ((flags & ASK_PASSWORD_NO_TTY) || !isatty(STDIN_FILENO)) &&
             (flags & ASK_PASSWORD_NO_AGENT)) {
-                r = ask_password_keyring(keyname, flags, ret);
+                r = ask_password_keyring(key_name, flags, ret);
                 if (r != -ENOKEY)
                         return r;
         }
 
         if (!(flags & ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO))
-                return ask_password_tty(-1, message, keyname, until, flags, NULL, ret);
+                return ask_password_tty(-1, message, key_name, until, flags, NULL, ret);
 
         if (!(flags & ASK_PASSWORD_NO_AGENT))
-                return ask_password_agent(message, icon, id, keyname, until, flags, ret);
+                return ask_password_agent(message, icon, id, key_name, until, flags, ret);
 
         return -EUNATCH;
 }
index 7aac5e597608208bb9923e532125b14c13bedf30..bb507b2e8de0bb8c07dc50b0997b638fad3a468d 100644 (file)
@@ -6,16 +6,17 @@
 #include "time-util.h"
 
 typedef enum AskPasswordFlags {
-        ASK_PASSWORD_ACCEPT_CACHED = 1 << 0,
-        ASK_PASSWORD_PUSH_CACHE    = 1 << 1,
+        ASK_PASSWORD_ACCEPT_CACHED = 1 << 0, /* read from kernel keyring */
+        ASK_PASSWORD_PUSH_CACHE    = 1 << 1, /* write to kernel keyring after getting password from elsewhere */
         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_NO_TTY        = 1 << 4, /* never ask for password on tty */
+        ASK_PASSWORD_NO_AGENT      = 1 << 5, /* never ask for password via agent */
         ASK_PASSWORD_CONSOLE_COLOR = 1 << 6, /* Use color if /dev/console points to a console that supports color */
+        ASK_PASSWORD_NO_CREDENTIAL = 1 << 7, /* never use $CREDENTIALS_DIRECTORY data */
 } 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);
+int ask_password_tty(int tty_fd, const char *message, const char *key_name, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
 int ask_password_plymouth(const char *message, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
-int ask_password_agent(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret);
-int ask_password_auto(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret);
+int ask_password_agent(const char *message, const char *icon, const char *id, const char *key_name, usec_t until, AskPasswordFlags flag, char ***ret);
+int ask_password_auto(const char *message, const char *icon, const char *id, const char *key_name, const char *credential_name, usec_t until, AskPasswordFlags flag, char ***ret);
index 1d054090863e68ed4fee2fd2b9c86ec417e270f1..016eb7b82a733590e7626a22a96a35f7b04d6abb 100644 (file)
@@ -46,14 +46,13 @@ static const BaseFilesystem table[] = {
 
 int base_filesystem_create(const char *root, uid_t uid, gid_t gid) {
         _cleanup_close_ int fd = -1;
-        size_t i;
         int r;
 
         fd = open(root, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
         if (fd < 0)
                 return log_error_errno(errno, "Failed to open root file system: %m");
 
-        for (i = 0; i < ELEMENTSOF(table); i ++) {
+        for (size_t i = 0; i < ELEMENTSOF(table); i++) {
                 if (faccessat(fd, table[i].dir, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
                         continue;
 
@@ -94,10 +93,9 @@ int base_filesystem_create(const char *root, uid_t uid, gid_t gid) {
                                 return -errno;
                         }
 
-                        if (uid_is_valid(uid) || gid_is_valid(gid)) {
+                        if (uid_is_valid(uid) || gid_is_valid(gid))
                                 if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0)
                                         return log_error_errno(errno, "Failed to chown symlink at %s/%s: %m", root, table[i].dir);
-                        }
 
                         continue;
                 }
@@ -114,10 +112,9 @@ int base_filesystem_create(const char *root, uid_t uid, gid_t gid) {
                         return -errno;
                 }
 
-                if (uid != UID_INVALID || gid != UID_INVALID) {
+                if (uid != UID_INVALID || gid != UID_INVALID)
                         if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0)
                                 return log_error_errno(errno, "Failed to chown directory at %s/%s: %m", root, table[i].dir);
-                }
         }
 
         return 0;
diff --git a/src/shared/bpf-link.c b/src/shared/bpf-link.c
new file mode 100644 (file)
index 0000000..f718cb7
--- /dev/null
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "bpf-link.h"
+#include "serialize.h"
+
+bool can_link_bpf_program(struct bpf_program *prog) {
+        _cleanup_(bpf_link_freep) struct bpf_link *link = NULL;
+
+        assert(prog);
+
+        /* Pass invalid cgroup fd intentionally. */
+        link = bpf_program__attach_cgroup(prog, /*cgroup_fd=*/-1);
+
+        /* EBADF indicates that bpf_link is supported by kernel. */
+        return libbpf_get_error(link) == -EBADF;
+}
+
+int serialize_bpf_link(FILE *f, FDSet *fds, const char *key, struct bpf_link *link) {
+        int fd;
+
+        assert(key);
+
+        if (!link)
+                return -ENOENT;
+
+        if (libbpf_get_error(link) != 0)
+                return -EINVAL;
+
+        fd = bpf_link__fd(link);
+        return serialize_fd(f, fds, key, fd);
+}
+
+struct bpf_link *bpf_link_free(struct bpf_link *link) {
+        /* bpf_link__destroy handles link == NULL case */
+        (void) bpf_link__destroy(link);
+
+        return NULL;
+}
diff --git a/src/shared/bpf-link.h b/src/shared/bpf-link.h
new file mode 100644 (file)
index 0000000..095465b
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#pragma once
+
+#include <bpf/libbpf.h>
+#include <stdio.h>
+
+#include "fdset.h"
+#include "macro.h"
+
+bool can_link_bpf_program(struct bpf_program *prog);
+
+int serialize_bpf_link(FILE *f, FDSet *fds, const char *key, struct bpf_link *link);
+
+struct bpf_link *bpf_link_free(struct bpf_link *p);
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct bpf_link *, bpf_link_free);
index 10239142af30898fc556b476fa553868d10fc530..a8a34521fd640c24c1a816e39c8424e4769f9f86 100644 (file)
 #include "memory-util.h"
 #include "missing_syscall.h"
 #include "path-util.h"
+#include "string-table.h"
+
+static const char *const bpf_cgroup_attach_type_table[__MAX_BPF_ATTACH_TYPE] = {
+        [BPF_CGROUP_INET_INGRESS] =     "ingress",
+        [BPF_CGROUP_INET_EGRESS] =      "egress",
+        [BPF_CGROUP_INET_SOCK_CREATE] = "sock_create",
+        [BPF_CGROUP_SOCK_OPS] =         "sock_ops",
+        [BPF_CGROUP_DEVICE] =           "device",
+        [BPF_CGROUP_INET4_BIND] =       "bind4",
+        [BPF_CGROUP_INET6_BIND] =       "bind6",
+        [BPF_CGROUP_INET4_CONNECT] =    "connect4",
+        [BPF_CGROUP_INET6_CONNECT] =    "connect6",
+        [BPF_CGROUP_INET4_POST_BIND] =  "post_bind4",
+        [BPF_CGROUP_INET6_POST_BIND] =  "post_bind6",
+        [BPF_CGROUP_UDP4_SENDMSG] =     "sendmsg4",
+        [BPF_CGROUP_UDP6_SENDMSG] =     "sendmsg6",
+        [BPF_CGROUP_SYSCTL] =           "sysctl",
+        [BPF_CGROUP_UDP4_RECVMSG] =     "recvmsg4",
+        [BPF_CGROUP_UDP6_RECVMSG] =     "recvmsg6",
+        [BPF_CGROUP_GETSOCKOPT] =       "getsockopt",
+        [BPF_CGROUP_SETSOCKOPT] =       "setsockopt",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(bpf_cgroup_attach_type, int);
+
+ /* struct bpf_prog_info info must be initialized since its value is both input and output
+  * for BPF_OBJ_GET_INFO_BY_FD syscall. */
+static int bpf_program_get_info_by_fd(int prog_fd, struct bpf_prog_info *info, uint32_t info_len) {
+        union bpf_attr attr;
+
+        /* Explicitly memset to zero since some compilers may produce non-zero-initialized padding when
+         * structured initialization is used.
+         * Refer to https://github.com/systemd/systemd/issues/18164
+         */
+        zero(attr);
+        attr.info.bpf_fd = prog_fd;
+        attr.info.info_len = info_len;
+        attr.info.info = PTR_TO_UINT64(info);
+
+        if (bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr)) < 0)
+                return -errno;
+
+        return 0;
+}
 
 int bpf_program_new(uint32_t prog_type, BPFProgram **ret) {
         _cleanup_(bpf_program_unrefp) BPFProgram *p = NULL;
@@ -28,6 +72,38 @@ int bpf_program_new(uint32_t prog_type, BPFProgram **ret) {
         return 0;
 }
 
+int bpf_program_new_from_bpffs_path(const char *path, BPFProgram **ret) {
+        _cleanup_(bpf_program_unrefp) BPFProgram *p = NULL;
+        struct bpf_prog_info info = {};
+        int r;
+
+        assert(path);
+        assert(ret);
+
+        p = new(BPFProgram, 1);
+        if (!p)
+                return -ENOMEM;
+
+        *p = (BPFProgram) {
+                .prog_type = BPF_PROG_TYPE_UNSPEC,
+                .n_ref = 1,
+                .kernel_fd = -1,
+        };
+
+        r = bpf_program_load_from_bpf_fs(p, path);
+        if (r < 0)
+                return r;
+
+        r = bpf_program_get_info_by_fd(p->kernel_fd, &info, sizeof(info));
+        if (r < 0)
+                return r;
+
+        p->prog_type = info.type;
+        *ret = TAKE_PTR(p);
+
+        return 0;
+}
+
 static BPFProgram *bpf_program_free(BPFProgram *p) {
         assert(p);
 
@@ -254,3 +330,31 @@ int bpf_map_lookup_element(int fd, const void *key, void *value) {
 
         return 0;
 }
+
+int bpf_program_pin(int prog_fd, const char *bpffs_path) {
+        union bpf_attr attr;
+
+        zero(attr);
+        attr.pathname = PTR_TO_UINT64((void *) bpffs_path);
+        attr.bpf_fd = prog_fd;
+
+        if (bpf(BPF_OBJ_PIN, &attr, sizeof(attr)) < 0)
+                return -errno;
+
+        return 0;
+}
+
+int bpf_program_get_id_by_fd(int prog_fd, uint32_t *ret_id) {
+        struct bpf_prog_info info = {};
+        int r;
+
+        assert(ret_id);
+
+        r = bpf_program_get_info_by_fd(prog_fd, &info, sizeof(info));
+        if (r < 0)
+                return r;
+
+        *ret_id = info.id;
+
+        return 0;
+};
index eef77f9d8e1a6dde7c7be9bf836ce8f9eabc3998..86fd338c93c44d61a18d4c792bcff75e84060dc5 100644 (file)
@@ -26,8 +26,9 @@ struct BPFProgram {
 };
 
 int bpf_program_new(uint32_t prog_type, BPFProgram **ret);
-BPFProgram *bpf_program_unref(BPFProgram *p);
+int bpf_program_new_from_bpffs_path(const char *path, BPFProgram **ret);
 BPFProgram *bpf_program_ref(BPFProgram *p);
+BPFProgram *bpf_program_unref(BPFProgram *p);
 
 int bpf_program_add_instructions(BPFProgram *p, const struct bpf_insn *insn, size_t count);
 int bpf_program_load_kernel(BPFProgram *p, char *log_buf, size_t log_size);
@@ -35,9 +36,14 @@ int bpf_program_load_from_bpf_fs(BPFProgram *p, const char *path);
 
 int bpf_program_cgroup_attach(BPFProgram *p, int type, const char *path, uint32_t flags);
 int bpf_program_cgroup_detach(BPFProgram *p);
+int bpf_program_pin(int prog_fd, const char *bpffs_path);
+int bpf_program_get_id_by_fd(int prog_fd, uint32_t *ret_id);
 
 int bpf_map_new(enum bpf_map_type type, size_t key_size, size_t value_size, size_t max_entries, uint32_t flags);
 int bpf_map_update_element(int fd, const void *key, void *value);
 int bpf_map_lookup_element(int fd, const void *key, void *value);
 
+int bpf_cgroup_attach_type_from_string(const char *str) _pure_;
+const char *bpf_cgroup_attach_type_to_string(int attach_type) _const_;
+
 DEFINE_TRIVIAL_CLEANUP_FUNC(BPFProgram*, bpf_program_unref);
index 19500a552d7ef9b6d2ec3c5a09949f75f5eba32e..14a4a4cfd6bac8380a687f6b29b02cf8afcf1c0a 100644 (file)
@@ -17,7 +17,7 @@ int bus_message_read_ifindex(sd_bus_message *message, sd_bus_error *error, int *
                 return r;
 
         if (ifindex <= 0)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
 
         *ret = ifindex;
 
@@ -62,7 +62,7 @@ int bus_message_read_in_addr_auto(sd_bus_message *message, sd_bus_error *error,
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
 
         if (sz != FAMILY_ADDRESS_SIZE(family))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
+                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
 
         if (ret_family)
                 *ret_family = family;
@@ -98,8 +98,11 @@ static int bus_message_read_dns_one(
         if (r < 0)
                 return r;
 
-        if (!dns_server_address_valid(family, &a))
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address");
+        if (!dns_server_address_valid(family, &a)) {
+                r = sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address");
+                assert(r < 0);
+                return r;
+        }
 
         if (extended) {
                 r = sd_bus_message_read(message, "q", &port);
index dc16c2f763582a246a73148c1337217428d0909e..cbd5fb087e01d3008d1a856eaa900bac441b1b91 100644 (file)
 #include "time-util.h"
 #include "user-util.h"
 
-int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *value) {
+int bus_print_property_value(const char *name, const char *expected_value, BusPrintPropertyFlags flags, const char *value) {
         assert(name);
 
         if (expected_value && !streq_ptr(expected_value, value))
                 return 0;
 
-        if (only_value)
-                puts(value);
+        if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) && isempty(value))
+                return 0;
+
+        if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE))
+                puts(strempty(value));
         else
-                printf("%s=%s\n", name, value);
+                printf("%s=%s\n", name, strempty(value));
 
         return 0;
 }
 
-int bus_print_property_valuef(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) {
+int bus_print_property_valuef(const char *name, const char *expected_value, BusPrintPropertyFlags flags, const char *fmt, ...) {
+        _cleanup_free_ char *s = NULL;
         va_list ap;
         int r;
 
         assert(name);
         assert(fmt);
 
-        if (expected_value) {
-                _cleanup_free_ char *s = NULL;
-
-                va_start(ap, fmt);
-                r = vasprintf(&s, fmt, ap);
-                va_end(ap);
-                if (r < 0)
-                        return -ENOMEM;
-
-                if (streq_ptr(expected_value, s)) {
-                        if (only_value)
-                                puts(s);
-                        else
-                                printf("%s=%s\n", name, s);
-                }
-
-                return 0;
-        }
-
-        if (!only_value)
-                printf("%s=", name);
         va_start(ap, fmt);
-        vprintf(fmt, ap);
+        r = vasprintf(&s, fmt, ap);
         va_end(ap);
-        puts("");
+        if (r < 0)
+                return -ENOMEM;
 
-        return 0;
+        return bus_print_property_value(name, expected_value, flags, s);
 }
 
-static int bus_print_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) {
+static int bus_print_property(const char *name, const char *expected_value, sd_bus_message *m, BusPrintPropertyFlags flags) {
         char type;
         const char *contents;
         int r;
@@ -84,13 +68,13 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                 if (r < 0)
                         return r;
 
-                if (all || !isempty(s)) {
+                if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) || !isempty(s)) {
                         bool good;
 
                         /* This property has a single value, so we need to take
                          * care not to print a new line, everything else is OK. */
                         good = !strchr(s, '\n');
-                        bus_print_property_value(name, expected_value, value, good ? s : "[unprintable]");
+                        bus_print_property_value(name, expected_value, flags, good ? s : "[unprintable]");
                 }
 
                 return 1;
@@ -106,7 +90,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                 if (expected_value && parse_boolean(expected_value) != b)
                         return 1;
 
-                bus_print_property_value(name, NULL, value, yes_no(b));
+                bus_print_property_value(name, NULL, flags, yes_no(b));
                 return 1;
         }
 
@@ -126,22 +110,18 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                         const char *t;
 
                         t = format_timestamp(timestamp, sizeof(timestamp), u);
-                        if (t || all)
-                                bus_print_property_value(name, expected_value, value, strempty(t));
+                        bus_print_property_value(name, expected_value, flags, t);
 
                 } else if (strstr(name, "USec")) {
                         char timespan[FORMAT_TIMESPAN_MAX];
 
                         (void) format_timespan(timespan, sizeof(timespan), u, 0);
-                        bus_print_property_value(name, expected_value, value, timespan);
-
-                } else if (streq(name, "CoredumpFilter")) {
-                        char buf[STRLEN("0xFFFFFFFF")];
+                        bus_print_property_value(name, expected_value, flags, timespan);
 
-                        xsprintf(buf, "0x%"PRIx64, u);
-                        bus_print_property_value(name, expected_value, value, buf);
+                } else if (streq(name, "CoredumpFilter"))
+                        bus_print_property_valuef(name, expected_value, flags, "0x%"PRIx64, u);
 
-                else if (streq(name, "RestrictNamespaces")) {
+                else if (streq(name, "RestrictNamespaces")) {
                         _cleanup_free_ char *s = NULL;
                         const char *result;
 
@@ -154,10 +134,10 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                                 if (r < 0)
                                         return r;
 
-                                result = strempty(s);
+                                result = s;
                         }
 
-                        bus_print_property_value(name, expected_value, value, result);
+                        bus_print_property_value(name, expected_value, flags, result);
 
                 } else if (streq(name, "MountFlags")) {
                         const char *result;
@@ -166,7 +146,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                         if (!result)
                                 return -EINVAL;
 
-                        bus_print_property_value(name, expected_value, value, result);
+                        bus_print_property_value(name, expected_value, flags, result);
 
                 } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
                         _cleanup_free_ char *s = NULL;
@@ -175,7 +155,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                         if (r < 0)
                                 return r;
 
-                        bus_print_property_value(name, expected_value, value, s);
+                        bus_print_property_value(name, expected_value, flags, s);
 
                 } else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
                            (STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) ||
@@ -183,18 +163,18 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                            (STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == UINT64_MAX) ||
                            (endswith(name, "NSec") && u == UINT64_MAX))
 
-                        bus_print_property_value(name, expected_value, value, "[not set]");
+                        bus_print_property_value(name, expected_value, flags, "[not set]");
 
                 else if ((STR_IN_SET(name, "DefaultMemoryLow", "DefaultMemoryMin", "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u == CGROUP_LIMIT_MAX) ||
                          (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == UINT64_MAX) ||
                          (startswith(name, "Limit") && u == UINT64_MAX) ||
                          (startswith(name, "DefaultLimit") && u == UINT64_MAX))
 
-                        bus_print_property_value(name, expected_value, value, "infinity");
+                        bus_print_property_value(name, expected_value, flags, "infinity");
                 else if (STR_IN_SET(name, "IPIngressBytes", "IPIngressPackets", "IPEgressBytes", "IPEgressPackets") && u == UINT64_MAX)
-                        bus_print_property_value(name, expected_value, value, "[no data]");
+                        bus_print_property_value(name, expected_value, flags, "[no data]");
                 else
-                        bus_print_property_valuef(name, expected_value, value, "%"PRIu64, u);
+                        bus_print_property_valuef(name, expected_value, flags, "%"PRIu64, u);
 
                 return 1;
         }
@@ -206,7 +186,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                 if (r < 0)
                         return r;
 
-                bus_print_property_valuef(name, expected_value, value, "%"PRIi64, i);
+                bus_print_property_valuef(name, expected_value, flags, "%"PRIi64, i);
                 return 1;
         }
 
@@ -218,20 +198,20 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                         return r;
 
                 if (strstr(name, "UMask") || strstr(name, "Mode"))
-                        bus_print_property_valuef(name, expected_value, value, "%04o", u);
+                        bus_print_property_valuef(name, expected_value, flags, "%04o", u);
 
                 else if (streq(name, "UID")) {
                         if (u == UID_INVALID)
-                                bus_print_property_value(name, expected_value, value, "[not set]");
+                                bus_print_property_value(name, expected_value, flags, "[not set]");
                         else
-                                bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
+                                bus_print_property_valuef(name, expected_value, flags, "%"PRIu32, u);
                 } else if (streq(name, "GID")) {
                         if (u == GID_INVALID)
-                                bus_print_property_value(name, expected_value, value, "[not set]");
+                                bus_print_property_value(name, expected_value, flags, "[not set]");
                         else
-                                bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
+                                bus_print_property_valuef(name, expected_value, flags, "%"PRIu32, u);
                 } else
-                        bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
+                        bus_print_property_valuef(name, expected_value, flags, "%"PRIu32, u);
 
                 return 1;
         }
@@ -243,7 +223,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                 if (r < 0)
                         return r;
 
-                bus_print_property_valuef(name, expected_value, value, "%"PRIi32, i);
+                bus_print_property_valuef(name, expected_value, flags, "%"PRIi32, i);
                 return 1;
         }
 
@@ -254,7 +234,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                 if (r < 0)
                         return r;
 
-                bus_print_property_valuef(name, expected_value, value, "%g", d);
+                bus_print_property_valuef(name, expected_value, flags, "%g", d);
                 return 1;
         }
 
@@ -275,7 +255,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                                         return -ENOMEM;
 
                                 if (first) {
-                                        if (!value)
+                                        if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE))
                                                 printf("%s=", name);
                                         first = false;
                                 } else
@@ -286,9 +266,9 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                         if (r < 0)
                                 return r;
 
-                        if (first && all && !value)
+                        if (first && FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) && !FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE))
                                 printf("%s=", name);
-                        if (!first || all)
+                        if (!first || FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY))
                                 puts("");
 
                         r = sd_bus_message_exit_container(m);
@@ -305,10 +285,10 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                         if (r < 0)
                                 return r;
 
-                        if (all || n > 0) {
+                        if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) || n > 0) {
                                 unsigned i;
 
-                                if (!value)
+                                if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE))
                                         printf("%s=", name);
 
                                 for (i = 0; i < n; i++)
@@ -327,10 +307,10 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                         if (r < 0)
                                 return r;
 
-                        if (all || n > 0) {
+                        if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) || n > 0) {
                                 unsigned i;
 
-                                if (!value)
+                                if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE))
                                         printf("%s=", name);
 
                                 for (i = 0; i < n; i++)
@@ -352,8 +332,7 @@ int bus_message_print_all_properties(
                 sd_bus_message *m,
                 bus_message_print_t func,
                 char **filter,
-                bool value,
-                bool all,
+                BusPrintPropertyFlags flags,
                 Set **found_properties) {
 
         int r;
@@ -393,13 +372,13 @@ int bus_message_print_all_properties(
                                 return r;
 
                         if (func)
-                                r = func(name, expected_value, m, value, all);
+                                r = func(name, expected_value, m, flags);
                         if (!func || r == 0)
-                                r = bus_print_property(name, expected_value, m, value, all);
+                                r = bus_print_property(name, expected_value, m, flags);
                         if (r < 0)
                                 return r;
                         if (r == 0) {
-                                if (all && !expected_value)
+                                if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) && !expected_value)
                                         printf("%s=[unprintable]\n", name);
                                 /* skip what we didn't read */
                                 r = sd_bus_message_skip(m, contents);
@@ -436,8 +415,7 @@ int bus_print_all_properties(
                 const char *path,
                 bus_message_print_t func,
                 char **filter,
-                bool value,
-                bool all,
+                BusPrintPropertyFlags flags,
                 Set **found_properties) {
 
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
@@ -458,5 +436,5 @@ int bus_print_all_properties(
         if (r < 0)
                 return r;
 
-        return bus_message_print_all_properties(reply, func, filter, value, all, found_properties);
+        return bus_message_print_all_properties(reply, func, filter, flags, found_properties);
 }
index a4574758e5522a50886e9e880a8af4032a0f9509..a17875cc47ce8417e45ae8dd4bc1d94bd618900b 100644 (file)
@@ -8,9 +8,14 @@
 #include "macro.h"
 #include "set.h"
 
-typedef int (*bus_message_print_t) (const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all);
+typedef enum BusPrintPropertyFlags {
+        BUS_PRINT_PROPERTY_ONLY_VALUE = 1 << 0,  /* e.g. systemctl --value */
+        BUS_PRINT_PROPERTY_SHOW_EMPTY = 1 << 1,  /* e.g. systemctl --all */
+} BusPrintPropertyFlags;
 
-int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *value);
-int bus_print_property_valuef(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) _printf_(4,5);
-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);
+typedef int (*bus_message_print_t) (const char *name, const char *expected_value, sd_bus_message *m, BusPrintPropertyFlags flags);
+
+int bus_print_property_value(const char *name, const char *expected_value, BusPrintPropertyFlags flags, const char *value);
+int bus_print_property_valuef(const char *name, const char *expected_value, BusPrintPropertyFlags flags, const char *fmt, ...) _printf_(4,5);
+int bus_message_print_all_properties(sd_bus_message *m, bus_message_print_t func, char **filter, BusPrintPropertyFlags flags, Set **found_properties);
+int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, bus_message_print_t func, char **filter, BusPrintPropertyFlags flags, Set **found_properties);
index a75178068b507f661985eaa77f4e6b43792f0545..20d368efcae818e5fcc9a1b6ea500d5761344114 100644 (file)
@@ -842,6 +842,77 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
                 return 1;
         }
 
+        if (streq(field, "BPFProgram")) {
+                if (isempty(eq))
+                        r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 0);
+                else {
+                        _cleanup_free_ char *word = NULL;
+
+                        r = extract_first_word(&eq, &word, ":", 0);
+                        if (r == -ENOMEM)
+                                return log_oom();
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse %s: %m", field);
+
+                        r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 1, word, eq);
+                }
+                if (r < 0)
+                        return bus_log_create_error(r);
+
+                return 1;
+        }
+
+        if (STR_IN_SET(field, "SocketBindAllow",
+                              "SocketBindDeny")) {
+                if (isempty(eq))
+                        r = sd_bus_message_append(m, "(sv)", field, "a(iqq)", 0);
+                else {
+                        const char *address_family, *user_port;
+                        _cleanup_free_ char *word = NULL;
+                        int family = AF_UNSPEC;
+
+                        r = extract_first_word(&eq, &word, ":", 0);
+                        if (r == -ENOMEM)
+                                return log_oom();
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse %s: %m", field);
+
+                        address_family = eq ? word : NULL;
+                        if (address_family) {
+                                if (!STR_IN_SET(address_family, "IPv4", "IPv6"))
+                                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                "Only IPv4 and IPv6 protocols are supported");
+
+                                if (streq(address_family, "IPv4"))
+                                        family = AF_INET;
+                                else
+                                        family = AF_INET6;
+                        }
+
+                        user_port = eq ? eq : word;
+                        if (streq(user_port, "any")) {
+                                r = sd_bus_message_append(m, "(sv)", field, "a(iqq)", 1, family, 0, 0);
+                                if (r < 0)
+                                        return bus_log_create_error(r);
+                        } else {
+                                uint16_t port_min, port_max;
+
+                                r = parse_ip_port_range(user_port, &port_min, &port_max);
+                                if (r == -ENOMEM)
+                                        return log_oom();
+                                if (r < 0)
+                                        return log_error_errno(r, "Invalid port or port range: %s", user_port);
+
+                                r = sd_bus_message_append(
+                                                m, "(sv)", field, "a(iqq)", 1, family, port_max - port_min + 1, port_min);
+                        }
+                }
+                if (r < 0)
+                        return bus_log_create_error(r);
+
+                return 1;
+        }
+
         return 0;
 }
 
@@ -1947,6 +2018,7 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con
 
         if (STR_IN_SET(field, "PIDFile",
                               "Type",
+                              "ExitType",
                               "Restart",
                               "BusName",
                               "NotifyAccess",
index f325dd4e6d06ca5ab7240b2f48c7f18fa96b81a2..e4a3ab9a956b5a90ded066c82042387a3039cf5f 100644 (file)
@@ -184,7 +184,7 @@ static void log_job_error_with_service_result(const char* service, const char *r
         service_shell_quoted = shell_maybe_quote(service, 0);
 
         if (!strv_isempty((char**) extra_args)) {
-                _cleanup_free_ char *t;
+                _cleanup_free_ char *t = NULL;
 
                 t = strv_join((char**) extra_args, " ");
                 systemctl = strjoina("systemctl ", t ? : "<args>");
@@ -306,7 +306,8 @@ int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char* const* extra_ar
                         if (q < 0 && r == 0)
                                 r = q;
 
-                        log_debug_errno(q, "Got result %s/%m for job %s", d->result, d->name);
+                        log_full_errno_zerook(LOG_DEBUG, q,
+                                              "Got result %s/%m for job %s", d->result, d->name);
                 }
 
                 d->name = mfree(d->name);
index 77fe227e36f8d5f0e625331bc39792dedd73e60d..497b0884d49f63ae8a7ac1a77d214ef044e13c33 100644 (file)
@@ -240,7 +240,7 @@ static int clean_posix_shm_internal(const char *dirname, DIR *dir, uid_t uid, gi
                 }
 
                 if (S_ISDIR(st.st_mode)) {
-                        _cleanup_closedir_ DIR *kid;
+                        _cleanup_closedir_ DIR *kid = NULL;
 
                         kid = xopendirat(dirfd(dir), de->d_name, O_NOFOLLOW|O_NOATIME);
                         if (!kid) {
index ec67b054b4e7ad72b138f92666ebd697ab383015..b446daf5819731c02af0432fce2ac58b22a13e17 100644 (file)
@@ -55,7 +55,7 @@ int clock_set_hwclock(const struct tm *tm) {
 }
 
 int clock_is_localtime(const char* adjtime_path) {
-        _cleanup_fclose_ FILE *f;
+        _cleanup_fclose_ FILE *f = NULL;
         int r;
 
         if (!adjtime_path)
index d84377c269e2553ffa1b84398c65cc655bc5773c..d4d9eacc4bd11c5f8ea8522655cd8327b8cd290e 100644 (file)
@@ -5,6 +5,7 @@
 #include <fnmatch.h>
 #include <limits.h>
 #include <stdlib.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/utsname.h>
 #include <time.h>
@@ -450,6 +451,81 @@ static int condition_test_architecture(Condition *c, char **env) {
         return a == b;
 }
 
+#define DTCOMPAT_FILE "/sys/firmware/devicetree/base/compatible"
+static int condition_test_firmware_devicetree_compatible(const char *dtcarg) {
+        int r;
+        _cleanup_free_ char *dtcompat = NULL;
+        _cleanup_strv_free_ char **dtcompatlist = NULL;
+        size_t size;
+
+        r = read_full_virtual_file(DTCOMPAT_FILE, &dtcompat, &size);
+        if (r < 0) {
+                /* if the path doesn't exist it is incompatible */
+                if (r != -ENOENT)
+                        log_debug_errno(r, "Failed to open() '%s', assuming machine is incompatible: %m", DTCOMPAT_FILE);
+                return false;
+        }
+
+        /* Not sure this can happen, but play safe. */
+        if (size == 0) {
+                log_debug("%s has zero length, assuming machine is incompatible", DTCOMPAT_FILE);
+                return false;
+        }
+
+        /*
+         * /sys/firmware/devicetree/base/compatible consists of one or more
+         * strings, each ending in '\0'. So the last character in dtcompat must
+         * be a '\0'.
+         */
+        if (dtcompat[size - 1] != '\0') {
+                log_debug("%s is in an unknown format, assuming machine is incompatible", DTCOMPAT_FILE);
+                return false;
+        }
+
+        dtcompatlist = strv_parse_nulstr(dtcompat, size);
+        if (!dtcompatlist)
+                return -ENOMEM;
+
+        return strv_contains(dtcompatlist, dtcarg);
+}
+
+static int condition_test_firmware(Condition *c, char **env) {
+        sd_char *dtc;
+
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_FIRMWARE);
+
+        if (streq(c->parameter, "device-tree")) {
+                if (access("/sys/firmware/device-tree/", F_OK) < 0) {
+                        if (errno != ENOENT)
+                                log_debug_errno(errno, "Unexpected error when checking for /sys/firmware/device-tree/: %m");
+                        return false;
+                } else
+                        return true;
+        } else if ((dtc = startswith(c->parameter, "device-tree-compatible("))) {
+                _cleanup_free_ char *dtcarg = NULL;
+                char *end;
+
+                end = strchr(dtc, ')');
+                if (!end || *(end + 1) != '\0') {
+                        log_debug("Malformed Firmware condition \"%s\"", c->parameter);
+                        return false;
+                }
+
+                dtcarg = strndup(dtc, end - dtc);
+                if (!dtcarg)
+                        return -ENOMEM;
+
+                return condition_test_firmware_devicetree_compatible(dtcarg);
+        } else if (streq(c->parameter, "uefi"))
+                return is_efi_boot();
+        else {
+                log_debug("Unsupported Firmware condition \"%s\"", c->parameter);
+                return false;
+        }
+}
+
 static int condition_test_host(Condition *c, char **env) {
         _cleanup_free_ char *h = NULL;
         sd_id128_t x, y;
@@ -843,6 +919,7 @@ int condition_test(Condition *c, char **env) {
                 [CONDITION_HOST]                     = condition_test_host,
                 [CONDITION_AC_POWER]                 = condition_test_ac_power,
                 [CONDITION_ARCHITECTURE]             = condition_test_architecture,
+                [CONDITION_FIRMWARE]                 = condition_test_firmware,
                 [CONDITION_NEEDS_UPDATE]             = condition_test_needs_update,
                 [CONDITION_FIRST_BOOT]               = condition_test_first_boot,
                 [CONDITION_USER]                     = condition_test_user,
@@ -949,6 +1026,7 @@ void condition_dump_list(Condition *first, FILE *f, const char *prefix, conditio
 
 static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
         [CONDITION_ARCHITECTURE] = "ConditionArchitecture",
+        [CONDITION_FIRMWARE] = "ConditionFirmware",
         [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
         [CONDITION_HOST] = "ConditionHost",
         [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
@@ -981,6 +1059,7 @@ DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
 
 static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
         [CONDITION_ARCHITECTURE] = "AssertArchitecture",
+        [CONDITION_FIRMWARE] = "AssertFirmware",
         [CONDITION_VIRTUALIZATION] = "AssertVirtualization",
         [CONDITION_HOST] = "AssertHost",
         [CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine",
index 75c430e9e07211aad4b5708b393519bcadf7adc2..6678689d7c3a53038039baaebbb96c9f7ecdcaf9 100644 (file)
@@ -9,6 +9,7 @@
 
 typedef enum ConditionType {
         CONDITION_ARCHITECTURE,
+        CONDITION_FIRMWARE,
         CONDITION_VIRTUALIZATION,
         CONDITION_HOST,
         CONDITION_KERNEL_COMMAND_LINE,
index 9dfa1907511d16d3c0f4941328be424397c63cd8..fa4079cff7717bbeb63a521959c4ef08b6fce57e 100644 (file)
@@ -300,7 +300,8 @@ int config_parse(
 
                 (void) stat_warn_permissions(filename, &st);
                 mtime = timespec_load(&st.st_mtim);
-        }
+        } else
+                mtime = 0;
 
         for (;;) {
                 _cleanup_free_ char *buf = NULL;
index 5ebb0ac576ad4ecfb5f86a2fa6804687d61e25e2..855997f3354c26383fad1b5801b1a813bd52b7ff 100644 (file)
@@ -61,4 +61,12 @@ int cryptsetup_get_token_as_json(struct crypt_device *cd, int idx, const char *v
 int cryptsetup_get_keyslot_from_token(JsonVariant *v);
 int cryptsetup_add_token_json(struct crypt_device *cd, JsonVariant *v);
 
+#else
+
+/* If libcryptsetup is not available, let's at least define the basic type and NOP destructors for it, to
+ * make a little bit less #ifdeferry necessary in main programs. */
+struct crypt_device;
+static inline void sym_crypt_free(struct crypt_device* cd) {}
+static inline void sym_crypt_freep(struct crypt_device** cd) {}
+
 #endif
index 79c4c70a41cf88028074f3d722e08f803f70ccd2..8d04ba04fc3dc33f6b1b6e47b1f50bdf3d5b75ef 100644 (file)
@@ -1198,7 +1198,16 @@ int image_read_metadata(Image *i) {
                 if (r < 0)
                         return r;
 
-                r = dissect_image(d->fd, NULL, NULL, DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_RELAX_VAR_CHECK, &m);
+                r = dissect_image(
+                                d->fd,
+                                NULL, NULL,
+                                d->uevent_seqnum_not_before,
+                                d->timestamp_not_before,
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                DISSECT_IMAGE_USR_NO_ROOT,
+                                &m);
                 if (r < 0)
                         return r;
 
index cca92e7fb4e3ab969e7b18c59723e57c57987b39..1f7ea3ec5b32d76f842ed879fc40d947437b476b 100644 (file)
@@ -46,6 +46,7 @@
 #include "path-util.h"
 #include "process-util.h"
 #include "raw-clone.h"
+#include "resize-fs.h"
 #include "signal-util.h"
 #include "stat-util.h"
 #include "stdio-util.h"
@@ -123,7 +124,7 @@ static int enumerator_for_parent(sd_device *d, sd_device_enumerator **ret) {
         if (r < 0)
                 return r;
 
-        r = sd_device_enumerator_allow_uninitialized(e);
+        r = sd_device_enumerator_add_match_subsystem(e, "block", true);
         if (r < 0)
                 return r;
 
@@ -131,31 +132,63 @@ static int enumerator_for_parent(sd_device *d, sd_device_enumerator **ret) {
         if (r < 0)
                 return r;
 
+        r = sd_device_enumerator_add_match_sysattr(e, "partition", NULL, true);
+        if (r < 0)
+                return r;
+
         *ret = TAKE_PTR(e);
         return 0;
 }
 
-static int device_is_partition(sd_device *d, blkid_partition pp) {
+static int device_is_partition(
+                sd_device *d,
+                sd_device *expected_parent,
+                blkid_partition pp) {
+
+        const char *v, *parent_syspath, *expected_parent_syspath;
         blkid_loff_t bsize, bstart;
         uint64_t size, start;
         int partno, bpartno, r;
-        const char *ss, *v;
+        sd_device *parent;
 
         assert(d);
+        assert(expected_parent);
         assert(pp);
 
-        r = sd_device_get_subsystem(d, &ss);
+        r = sd_device_get_subsystem(d, &v);
         if (r < 0)
                 return r;
-        if (!streq(ss, "block"))
+        if (!streq(v, "block"))
                 return false;
 
-        r = sd_device_get_sysattr_value(d, "partition", &v);
-        if (r == -ENOENT ||        /* Not a partition device */
-            ERRNO_IS_PRIVILEGE(r)) /* Not ready to access? */
+        if (sd_device_get_devtype(d, &v) < 0 || !streq(v, "partition"))
                 return false;
+
+        r = sd_device_get_parent(d, &parent);
+        if (r < 0)
+                return false; /* Doesn't have a parent? No relevant to us */
+
+        r = sd_device_get_syspath(parent, &parent_syspath); /* Check parent of device of this action */
         if (r < 0)
                 return r;
+
+        r = sd_device_get_syspath(expected_parent, &expected_parent_syspath); /* Check parent of device we are looking for */
+        if (r < 0)
+                return r;
+
+        if (!path_equal(parent_syspath, expected_parent_syspath))
+                return false; /* Has a different parent than what we need, not interesting to us */
+
+        /* On kernel uevents we may find the partition number in the PARTN= field. Let's use that preferably,
+         * since it's cheaper and more importantly: the sysfs attribute "partition" appears to become
+         * available late, hence let's use the property instead, which is available at the moment we see the
+         * uevent. */
+        r = sd_device_get_property_value(d, "PARTN", &v);
+        if (r == -ENOENT)
+                r = sd_device_get_sysattr_value(d, "partition", &v);
+        if (r < 0)
+                return r;
+
         r = safe_atoi(v, &partno);
         if (r < 0)
                 return r;
@@ -204,6 +237,7 @@ static int device_is_partition(sd_device *d, blkid_partition pp) {
 static int find_partition(
                 sd_device *parent,
                 blkid_partition pp,
+                usec_t timestamp_not_before,
                 sd_device **ret) {
 
         _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
@@ -219,7 +253,19 @@ static int find_partition(
                 return r;
 
         FOREACH_DEVICE(e, q) {
-                r = device_is_partition(q, pp);
+                uint64_t usec;
+
+                r = sd_device_get_usec_initialized(q, &usec);
+                if (r == -EBUSY) /* Not initialized yet */
+                        continue;
+                if (r < 0)
+                        return r;
+
+                if (timestamp_not_before != USEC_INFINITY &&
+                    usec < timestamp_not_before) /* udev database entry older than our attachment? Then it's not ours */
+                        continue;
+
+                r = device_is_partition(q, parent, pp);
                 if (r < 0)
                         return r;
                 if (r > 0) {
@@ -235,6 +281,7 @@ struct wait_data {
         sd_device *parent_device;
         blkid_partition blkidp;
         sd_device *found;
+        uint64_t uevent_seqnum_not_before;
 };
 
 static inline void wait_data_done(struct wait_data *d) {
@@ -242,9 +289,7 @@ static inline void wait_data_done(struct wait_data *d) {
 }
 
 static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device, void *userdata) {
-        const char *parent1_path, *parent2_path;
         struct wait_data *w = userdata;
-        sd_device *pp;
         int r;
 
         assert(w);
@@ -252,22 +297,21 @@ static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device,
         if (device_for_action(device, SD_DEVICE_REMOVE))
                 return 0;
 
-        r = sd_device_get_parent(device, &pp);
-        if (r < 0)
-                return 0; /* Doesn't have a parent? No relevant to us */
-
-        r = sd_device_get_syspath(pp, &parent1_path); /* Check parent of device of this action */
-        if (r < 0)
-                goto finish;
+        if (w->uevent_seqnum_not_before != UINT64_MAX) {
+                uint64_t seqnum;
 
-        r = sd_device_get_syspath(w->parent_device, &parent2_path); /* Check parent of device we are looking for */
-        if (r < 0)
-                goto finish;
+                r = sd_device_get_seqnum(device, &seqnum);
+                if (r < 0)
+                        goto finish;
 
-        if (!path_equal(parent1_path, parent2_path))
-                return 0; /* Has a different parent than what we need, not interesting to us */
+                if (seqnum <= w->uevent_seqnum_not_before) { /* From an older use of this loop device */
+                        log_debug("Dropping event because seqnum too old (%" PRIu64 " <= %" PRIu64 ")",
+                                  seqnum, w->uevent_seqnum_not_before);
+                        return 0;
+                }
+        }
 
-        r = device_is_partition(device, w->blkidp);
+        r = device_is_partition(device, w->parent_device, w->blkidp);
         if (r < 0)
                 goto finish;
         if (r == 0) /* Not the one we need */
@@ -286,6 +330,8 @@ static int wait_for_partition_device(
                 sd_device *parent,
                 blkid_partition pp,
                 usec_t deadline,
+                uint64_t uevent_seqnum_not_before,
+                usec_t timestamp_not_before,
                 sd_device **ret) {
 
         _cleanup_(sd_event_source_unrefp) sd_event_source *timeout_source = NULL;
@@ -297,7 +343,7 @@ static int wait_for_partition_device(
         assert(pp);
         assert(ret);
 
-        r = find_partition(parent, pp, ret);
+        r = find_partition(parent, pp, timestamp_not_before, ret);
         if (r != -ENXIO)
                 return r;
 
@@ -313,6 +359,14 @@ static int wait_for_partition_device(
         if (r < 0)
                 return r;
 
+        r = sd_device_monitor_filter_add_match_parent(monitor, parent, true);
+        if (r < 0)
+                return r;
+
+        r = sd_device_monitor_filter_add_match_sysattr(monitor, "partition", NULL, true);
+        if (r < 0)
+                return r;
+
         r = sd_device_monitor_attach_event(monitor, event);
         if (r < 0)
                 return r;
@@ -320,6 +374,7 @@ static int wait_for_partition_device(
         _cleanup_(wait_data_done) struct wait_data w = {
                 .parent_device = parent,
                 .blkidp = pp,
+                .uevent_seqnum_not_before = uevent_seqnum_not_before,
         };
 
         r = sd_device_monitor_start(monitor, device_monitor_handler, &w);
@@ -327,7 +382,7 @@ static int wait_for_partition_device(
                 return r;
 
         /* Check again, the partition might have appeared in the meantime */
-        r = find_partition(parent, pp, ret);
+        r = find_partition(parent, pp, timestamp_not_before, ret);
         if (r != -ENXIO)
                 return r;
 
@@ -378,7 +433,6 @@ static int device_wait_for_initialization_harder(
                 usec_t deadline,
                 sd_device **ret) {
 
-        _cleanup_free_ char *uevent = NULL;
         usec_t start, left, retrigger_timeout;
         int r;
 
@@ -390,7 +444,8 @@ static int device_wait_for_initialization_harder(
                 const char *sn = NULL;
 
                 (void) sd_device_get_sysname(device, &sn);
-                log_debug("Waiting for device '%s' to initialize for %s.", strna(sn), format_timespan(buf, sizeof(buf), left, 0));
+                log_device_debug(device,
+                                 "Waiting for device '%s' to initialize for %s.", strna(sn), format_timespan(buf, sizeof(buf), left, 0));
         }
 
         if (left != USEC_INFINITY)
@@ -421,33 +476,24 @@ static int device_wait_for_initialization_harder(
                         const char *sn = NULL;
 
                         (void) sd_device_get_sysname(device, &sn);
-                        log_debug("Successfully waited for device '%s' to initialize for %s.", strna(sn), format_timespan(buf, sizeof(buf), usec_sub_unsigned(now(CLOCK_MONOTONIC), start), 0));
+                        log_device_debug(device,
+                                         "Successfully waited for device '%s' to initialize for %s.",
+                                         strna(sn),
+                                         format_timespan(buf, sizeof(buf), usec_sub_unsigned(now(CLOCK_MONOTONIC), start), 0));
 
                 }
                 if (r != -ETIMEDOUT || last_try)
                         return r;
 
-                if (!uevent) {
-                        const char *syspath;
-
-                        r = sd_device_get_syspath(device, &syspath);
-                        if (r < 0)
-                                return r;
-
-                        uevent = path_join(syspath, "uevent");
-                        if (!uevent)
-                                return -ENOMEM;
-                }
-
                 if (DEBUG_LOGGING) {
                         char buf[FORMAT_TIMESPAN_MAX];
 
-                        log_debug("Device didn't initialize within %s, assuming lost event. Retriggering device through %s.",
-                                  format_timespan(buf, sizeof(buf), usec_sub_unsigned(now(CLOCK_MONOTONIC), start), 0),
-                                  uevent);
+                        log_device_debug(device,
+                                         "Device didn't initialize within %s, assuming lost event. Retriggering device.",
+                                         format_timespan(buf, sizeof(buf), usec_sub_unsigned(now(CLOCK_MONOTONIC), start), 0));
                 }
 
-                r = write_string_file(uevent, "change", WRITE_STRING_FILE_DISABLE_BUFFER);
+                r = sd_device_trigger(device, SD_DEVICE_CHANGE);
                 if (r < 0)
                         return r;
         }
@@ -456,10 +502,28 @@ static int device_wait_for_initialization_harder(
 
 #define DEVICE_TIMEOUT_USEC (45 * USEC_PER_SEC)
 
+static void dissected_partition_done(DissectedPartition *p) {
+        assert(p);
+
+        free(p->fstype);
+        free(p->node);
+        free(p->label);
+        free(p->decrypted_fstype);
+        free(p->decrypted_node);
+        free(p->mount_options);
+
+        *p = (DissectedPartition) {
+                .partno = -1,
+                .architecture = -1
+        };
+}
+
 int dissect_image(
                 int fd,
                 const VeritySettings *verity,
                 const MountOptions *mount_options,
+                uint64_t uevent_seqnum_not_before,
+                usec_t timestamp_not_before,
                 DissectImageFlags flags,
                 DissectedImage **ret) {
 
@@ -470,7 +534,9 @@ int dissect_image(
 #ifdef GPT_USR_NATIVE
         sd_id128_t usr_uuid = SD_ID128_NULL, usr_verity_uuid = SD_ID128_NULL;
 #endif
-        bool is_gpt, is_mbr, generic_rw, multiple_generic = false;
+        bool is_gpt, is_mbr, multiple_generic = false,
+                generic_rw = false,  /* initialize to appease gcc */
+                generic_growfs = false;
         _cleanup_(sd_device_unrefp) sd_device *d = NULL;
         _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
         _cleanup_(blkid_free_probep) blkid_probe b = NULL;
@@ -478,7 +544,7 @@ int dissect_image(
         sd_id128_t generic_uuid = SD_ID128_NULL;
         const char *pttype = NULL, *sysname = NULL;
         blkid_partlist pl;
-        int r, generic_nr, n_partitions;
+        int r, generic_nr = -1, n_partitions;
         struct stat st;
         usec_t deadline;
 
@@ -490,7 +556,9 @@ int dissect_image(
         /* Probes a disk image, and returns information about what it found in *ret.
          *
          * Returns -ENOPKG if no suitable partition table or file system could be found.
-         * Returns -EADDRNOTAVAIL if a root hash was specified but no matching root/verity partitions found. */
+         * Returns -EADDRNOTAVAIL if a root hash was specified but no matching root/verity partitions found.
+         * Returns -ENXIO if we couldn't find any partition suitable as root or /usr partition
+         * Returns -ENOTUNIQ if we only found multiple generic partitions and thus don't know what to do with that */
 
         if (verity && verity->root_hash) {
                 sd_id128_t fsuuid, vuuid;
@@ -612,7 +680,7 @@ int dissect_image(
         }
 
         if ((!(flags & DISSECT_IMAGE_GPT_ONLY) &&
-            (flags & DISSECT_IMAGE_REQUIRE_ROOT)) ||
+            (flags & DISSECT_IMAGE_GENERIC_ROOT)) ||
             (flags & DISSECT_IMAGE_NO_PARTITION_TABLE)) {
                 const char *usage = NULL;
 
@@ -709,7 +777,7 @@ int dissect_image(
                 if (!pp)
                         return errno_or_else(EIO);
 
-                r = wait_for_partition_device(d, pp, deadline, &q);
+                r = wait_for_partition_device(d, pp, deadline, uevent_seqnum_not_before, timestamp_not_before, &q);
                 if (r < 0)
                         return r;
 
@@ -727,9 +795,9 @@ int dissect_image(
                 if (is_gpt) {
                         PartitionDesignator designator = _PARTITION_DESIGNATOR_INVALID;
                         int architecture = _ARCHITECTURE_INVALID;
-                        const char *stype, *sid, *fstype = NULL;
+                        const char *stype, *sid, *fstype = NULL, *label;
                         sd_id128_t type_id, id;
-                        bool rw = true;
+                        bool rw = true, growfs = false;
 
                         sid = blkid_partition_get_uuid(pp);
                         if (!sid)
@@ -743,25 +811,29 @@ int dissect_image(
                         if (sd_id128_from_string(stype, &type_id) < 0)
                                 continue;
 
+                        label = blkid_partition_get_name(pp); /* libblkid returns NULL here if empty */
+
                         if (sd_id128_equal(type_id, GPT_HOME)) {
 
-                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
 
                                 if (pflags & GPT_FLAG_NO_AUTO)
                                         continue;
 
                                 designator = PARTITION_HOME;
                                 rw = !(pflags & GPT_FLAG_READ_ONLY);
+                                growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
 
                         } else if (sd_id128_equal(type_id, GPT_SRV)) {
 
-                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
 
                                 if (pflags & GPT_FLAG_NO_AUTO)
                                         continue;
 
                                 designator = PARTITION_SRV;
                                 rw = !(pflags & GPT_FLAG_READ_ONLY);
+                                growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
 
                         } else if (sd_id128_equal(type_id, GPT_ESP)) {
 
@@ -778,18 +850,19 @@ int dissect_image(
 
                         } else if (sd_id128_equal(type_id, GPT_XBOOTLDR)) {
 
-                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
 
                                 if (pflags & GPT_FLAG_NO_AUTO)
                                         continue;
 
                                 designator = PARTITION_XBOOTLDR;
                                 rw = !(pflags & GPT_FLAG_READ_ONLY);
+                                growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
                         }
 #ifdef GPT_ROOT_NATIVE
                         else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE)) {
 
-                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
 
                                 if (pflags & GPT_FLAG_NO_AUTO)
                                         continue;
@@ -801,6 +874,7 @@ int dissect_image(
                                 designator = PARTITION_ROOT;
                                 architecture = native_architecture();
                                 rw = !(pflags & GPT_FLAG_READ_ONLY);
+                                growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
 
                         } else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE_VERITY)) {
 
@@ -824,7 +898,7 @@ int dissect_image(
 #ifdef GPT_ROOT_SECONDARY
                         else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY)) {
 
-                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
 
                                 if (pflags & GPT_FLAG_NO_AUTO)
                                         continue;
@@ -836,6 +910,7 @@ int dissect_image(
                                 designator = PARTITION_ROOT_SECONDARY;
                                 architecture = SECONDARY_ARCHITECTURE;
                                 rw = !(pflags & GPT_FLAG_READ_ONLY);
+                                growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
 
                         } else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY_VERITY)) {
 
@@ -859,7 +934,7 @@ int dissect_image(
 #ifdef GPT_USR_NATIVE
                         else if (sd_id128_equal(type_id, GPT_USR_NATIVE)) {
 
-                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
 
                                 if (pflags & GPT_FLAG_NO_AUTO)
                                         continue;
@@ -871,6 +946,7 @@ int dissect_image(
                                 designator = PARTITION_USR;
                                 architecture = native_architecture();
                                 rw = !(pflags & GPT_FLAG_READ_ONLY);
+                                growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
 
                         } else if (sd_id128_equal(type_id, GPT_USR_NATIVE_VERITY)) {
 
@@ -894,7 +970,7 @@ int dissect_image(
 #ifdef GPT_USR_SECONDARY
                         else if (sd_id128_equal(type_id, GPT_USR_SECONDARY)) {
 
-                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
 
                                 if (pflags & GPT_FLAG_NO_AUTO)
                                         continue;
@@ -906,6 +982,7 @@ int dissect_image(
                                 designator = PARTITION_USR_SECONDARY;
                                 architecture = SECONDARY_ARCHITECTURE;
                                 rw = !(pflags & GPT_FLAG_READ_ONLY);
+                                growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
 
                         } else if (sd_id128_equal(type_id, GPT_USR_SECONDARY_VERITY)) {
 
@@ -938,7 +1015,7 @@ int dissect_image(
 
                         } else if (sd_id128_equal(type_id, GPT_LINUX_GENERIC)) {
 
-                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
 
                                 if (pflags & GPT_FLAG_NO_AUTO)
                                         continue;
@@ -948,6 +1025,7 @@ int dissect_image(
                                 else {
                                         generic_nr = nr;
                                         generic_rw = !(pflags & GPT_FLAG_READ_ONLY);
+                                        generic_growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
                                         generic_uuid = id;
                                         generic_node = strdup(node);
                                         if (!generic_node)
@@ -956,17 +1034,18 @@ int dissect_image(
 
                         } else if (sd_id128_equal(type_id, GPT_TMP)) {
 
-                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
 
                                 if (pflags & GPT_FLAG_NO_AUTO)
                                         continue;
 
                                 designator = PARTITION_TMP;
                                 rw = !(pflags & GPT_FLAG_READ_ONLY);
+                                growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
 
                         } else if (sd_id128_equal(type_id, GPT_VAR)) {
 
-                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY);
+                                check_partition_flags(node, pflags, GPT_FLAG_NO_AUTO|GPT_FLAG_READ_ONLY|GPT_FLAG_GROWFS);
 
                                 if (pflags & GPT_FLAG_NO_AUTO)
                                         continue;
@@ -994,15 +1073,25 @@ int dissect_image(
 
                                 designator = PARTITION_VAR;
                                 rw = !(pflags & GPT_FLAG_READ_ONLY);
+                                growfs = FLAGS_SET(pflags, GPT_FLAG_GROWFS);
                         }
 
                         if (designator != _PARTITION_DESIGNATOR_INVALID) {
-                                _cleanup_free_ char *t = NULL, *n = NULL, *o = NULL;
+                                _cleanup_free_ char *t = NULL, *n = NULL, *o = NULL, *l = NULL;
                                 const char *options = NULL;
 
-                                /* First one wins */
-                                if (m->partitions[designator].found)
-                                        continue;
+                                if (m->partitions[designator].found) {
+                                        /* For most partition types the first one we see wins. Except for the
+                                         * rootfs and /usr, where we do a version compare of the label, and
+                                         * let the newest version win. This permits a simple A/B versioning
+                                         * scheme in OS images. */
+
+                                        if (!PARTITION_DESIGNATOR_VERSIONED(designator) ||
+                                            strverscmp_improved(m->partitions[designator].label, label) >= 0)
+                                                continue;
+
+                                        dissected_partition_done(m->partitions + designator);
+                                }
 
                                 if (fstype) {
                                         t = strdup(fstype);
@@ -1014,6 +1103,12 @@ int dissect_image(
                                 if (!n)
                                         return -ENOMEM;
 
+                                if (label) {
+                                        l = strdup(label);
+                                        if (!l)
+                                                return -ENOMEM;
+                                }
+
                                 options = mount_options_from_designator(mount_options, designator);
                                 if (options) {
                                         o = strdup(options);
@@ -1025,9 +1120,11 @@ int dissect_image(
                                         .found = true,
                                         .partno = nr,
                                         .rw = rw,
+                                        .growfs = growfs,
                                         .architecture = architecture,
                                         .node = TAKE_PTR(n),
                                         .fstype = TAKE_PTR(t),
+                                        .label = TAKE_PTR(l),
                                         .uuid = id,
                                         .mount_options = TAKE_PTR(o),
                                 };
@@ -1047,6 +1144,7 @@ int dissect_image(
                                 else {
                                         generic_nr = nr;
                                         generic_rw = true;
+                                        generic_growfs = false;
                                         generic_node = strdup(node);
                                         if (!generic_node)
                                                 return -ENOMEM;
@@ -1082,6 +1180,7 @@ int dissect_image(
                                         .found = true,
                                         .partno = nr,
                                         .rw = true,
+                                        .growfs = false,
                                         .architecture = _ARCHITECTURE_INVALID,
                                         .node = TAKE_PTR(n),
                                         .uuid = id,
@@ -1100,46 +1199,64 @@ int dissect_image(
                 m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found = false;
                 m->partitions[PARTITION_USR_SECONDARY].found = false;
                 m->partitions[PARTITION_USR_SECONDARY_VERITY].found = false;
-        } else {
-                /* No root partition found? Then let's see if ther's one for the secondary architecture. And if not
-                 * either, then check if there's a single generic one, and use that. */
 
-                if (m->partitions[PARTITION_ROOT_VERITY].found)
-                        return -EADDRNOTAVAIL;
+        } else if (m->partitions[PARTITION_ROOT_VERITY].found)
+                return -EADDRNOTAVAIL; /* Verity found but no matching rootfs? Something is off, refuse. */
 
-                /* We didn't find a primary architecture root, but we found a primary architecture /usr? Refuse that for now. */
-                if (m->partitions[PARTITION_USR].found || m->partitions[PARTITION_USR_VERITY].found)
-                        return -EADDRNOTAVAIL;
+        else if (m->partitions[PARTITION_ROOT_SECONDARY].found) {
 
-                if (m->partitions[PARTITION_ROOT_SECONDARY].found) {
-                        /* Upgrade secondary arch to first */
-                        m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_SECONDARY];
-                        zero(m->partitions[PARTITION_ROOT_SECONDARY]);
-                        m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY];
-                        zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]);
+                /* No root partition found but there's one for the secondary architecture? Then upgrade
+                 * secondary arch to first */
 
-                        m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_SECONDARY];
-                        zero(m->partitions[PARTITION_USR_SECONDARY]);
-                        m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_SECONDARY_VERITY];
-                        zero(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
+                m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_SECONDARY];
+                zero(m->partitions[PARTITION_ROOT_SECONDARY]);
+                m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY];
+                zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]);
 
-                } else if (flags & DISSECT_IMAGE_REQUIRE_ROOT) {
-                        _cleanup_free_ char *o = NULL;
-                        const char *options = NULL;
+                m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_SECONDARY];
+                zero(m->partitions[PARTITION_USR_SECONDARY]);
+                m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_SECONDARY_VERITY];
+                zero(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
 
-                        /* If the root hash was set, then we won't fall back to a generic node, because the
-                         * root hash decides. */
-                        if (verity && verity->root_hash)
-                                return -EADDRNOTAVAIL;
+        } else if (m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found)
+                return -EADDRNOTAVAIL; /* as above */
+
+        else if (m->partitions[PARTITION_USR].found) {
+
+                /* Invalidate secondary arch /usr/ if we found the primary arch */
+                m->partitions[PARTITION_USR_SECONDARY].found = false;
+                m->partitions[PARTITION_USR_SECONDARY_VERITY].found = false;
+
+        } else if (m->partitions[PARTITION_USR_VERITY].found)
+                return -EADDRNOTAVAIL; /* as above */
+
+        else if (m->partitions[PARTITION_USR_SECONDARY].found) {
+
+                /* Upgrade secondary arch to primary */
+                m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_SECONDARY];
+                zero(m->partitions[PARTITION_USR_SECONDARY]);
+                m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_SECONDARY_VERITY];
+                zero(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
+
+        } else if (m->partitions[PARTITION_USR_SECONDARY_VERITY].found)
+                return -EADDRNOTAVAIL; /* as above */
 
-                        /* If we didn't find a generic node, then we can't fix this up either */
-                        if (!generic_node)
-                                return -ENXIO;
+        else if ((flags & DISSECT_IMAGE_GENERIC_ROOT) &&
+                 (!verity || !verity->root_hash)) {
 
-                        /* If we didn't find a properly marked root partition, but we did find a single suitable
-                         * generic Linux partition, then use this as root partition, if the caller asked for it. */
-                        if (multiple_generic)
-                                return -ENOTUNIQ;
+                /* OK, we found nothing usable, then check if there's a single generic one distro, and use
+                 * that. If the root hash was set however, then we won't fall back to a generic node, because
+                 * the root hash decides. */
+
+                /* If we didn't find a properly marked root partition, but we did find a single suitable
+                 * generic Linux partition, then use this as root partition, if the caller asked for it. */
+                if (multiple_generic)
+                        return -ENOTUNIQ;
+
+                /* If we didn't find a generic node, then we can't fix this up either */
+                if (generic_node) {
+                        _cleanup_free_ char *o = NULL;
+                        const char *options;
 
                         options = mount_options_from_designator(mount_options, PARTITION_ROOT);
                         if (options) {
@@ -1148,9 +1265,11 @@ int dissect_image(
                                         return -ENOMEM;
                         }
 
+                        assert(generic_nr >= 0);
                         m->partitions[PARTITION_ROOT] = (DissectedPartition) {
                                 .found = true,
                                 .rw = generic_rw,
+                                .growfs = generic_growfs,
                                 .partno = generic_nr,
                                 .architecture = _ARCHITECTURE_INVALID,
                                 .node = TAKE_PTR(generic_node),
@@ -1160,6 +1279,11 @@ int dissect_image(
                 }
         }
 
+        /* Check if we have a root fs if we are told to do check. /usr alone is fine too, but only if appropriate flag for that is set too */
+        if (FLAGS_SET(flags, DISSECT_IMAGE_REQUIRE_ROOT) &&
+            !(m->partitions[PARTITION_ROOT].found || (m->partitions[PARTITION_USR].found && FLAGS_SET(flags, DISSECT_IMAGE_USR_NO_ROOT))))
+                return -ENXIO;
+
         /* Refuse if we found a verity partition for /usr but no matching file system partition */
         if (!m->partitions[PARTITION_USR].found && m->partitions[PARTITION_USR_VERITY].found)
                 return -EADDRNOTAVAIL;
@@ -1208,6 +1332,9 @@ int dissect_image(
 
                 if (p->fstype && fstype_is_ro(p->fstype))
                         p->rw = false;
+
+                if (!p->rw)
+                        p->growfs = false;
         }
 
         *ret = TAKE_PTR(m);
@@ -1221,13 +1348,8 @@ DissectedImage* dissected_image_unref(DissectedImage *m) {
         if (!m)
                 return NULL;
 
-        for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
-                free(m->partitions[i].fstype);
-                free(m->partitions[i].node);
-                free(m->partitions[i].decrypted_fstype);
-                free(m->partitions[i].decrypted_node);
-                free(m->partitions[i].mount_options);
-        }
+        for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++)
+                dissected_partition_done(m->partitions + i);
 
         free(m->image_name);
         free(m->hostname);
@@ -1308,6 +1430,43 @@ static int run_fsck(const char *node, const char *fstype) {
         return 0;
 }
 
+static int fs_grow(const char *node_path, const char *mount_path) {
+        _cleanup_close_ int mount_fd = -1, node_fd = -1;
+        char fb[FORMAT_BYTES_MAX];
+        uint64_t size, newsize;
+        int r;
+
+        node_fd = open(node_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+        if (node_fd < 0)
+                return log_debug_errno(errno, "Failed to open node device %s: %m", node_path);
+
+        if (ioctl(node_fd, BLKGETSIZE64, &size) != 0)
+                return log_debug_errno(errno, "Failed to get block device size of %s: %m", node_path);
+
+        mount_fd = open(mount_path, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
+        if (mount_fd < 0)
+                return log_debug_errno(errno, "Failed to open mountd file system %s: %m", mount_path);
+
+        log_debug("Resizing \"%s\" to %"PRIu64" bytes...", mount_path, size);
+        r = resize_fs(mount_fd, size, &newsize);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to resize \"%s\" to %"PRIu64" bytes: %m", mount_path, size);
+
+        if (newsize == size)
+                log_debug("Successfully resized \"%s\" to %s bytes.",
+                          mount_path,
+                          format_bytes(fb, sizeof fb, newsize));
+        else {
+                assert(newsize < size);
+                log_debug("Successfully resized \"%s\" to %s bytes (%"PRIu64" bytes lost due to blocksize).",
+                          mount_path,
+                          format_bytes(fb, sizeof fb, newsize),
+                          size - newsize);
+        }
+
+        return 0;
+}
+
 static int mount_partition(
                 DissectedPartition *m,
                 const char *where,
@@ -1336,7 +1495,7 @@ static int mount_partition(
         if (streq(fstype, "crypto_LUKS"))
                 return -EUNATCH;
 
-        rw = m->rw && !(flags & DISSECT_IMAGE_READ_ONLY);
+        rw = m->rw && !(flags & DISSECT_IMAGE_MOUNT_READ_ONLY);
 
         if (FLAGS_SET(flags, DISSECT_IMAGE_FSCK) && rw) {
                 r = run_fsck(node, fstype);
@@ -1391,10 +1550,60 @@ static int mount_partition(
                 if (!strextend_with_separator(&options, ",", m->mount_options))
                         return -ENOMEM;
 
+        /* So, when you request MS_RDONLY from ext4, then this means nothing. It happily still writes to the
+         * backing storage. What's worse, the BLKRO[GS]ET flag and (in case of loopback devices)
+         * LO_FLAGS_READ_ONLY don't mean anything, they affect userspace accesses only, and write accesses
+         * from the upper file system still get propagated through to the underlying file system,
+         * unrestricted. To actually get ext4/xfs/btrfs to stop writing to the device we need to specify
+         * "norecovery" as mount option, in addition to MS_RDONLY. Yes, this sucks, since it means we need to
+         * carry a per file system table here.
+         *
+         * Note that this means that we might not be able to mount corrupted file systems as read-only
+         * anymore (since in some cases the kernel implementations will refuse mounting when corrupted,
+         * read-only and "norecovery" is specified). But I think for the case of automatically determined
+         * mount options for loopback devices this is the right choice, since otherwise using the same
+         * loopback file twice even in read-only mode, is going to fail badly sooner or later. The usecase of
+         * making reuse of the immutable images "just work" is more relevant to us than having read-only
+         * access that actually modifies stuff work on such image files. Or to say this differently: if
+         * people want their file systems to be fixed up they should just open them in writable mode, where
+         * all these problems don't exist. */
+        if (!rw && STRPTR_IN_SET(fstype, "ext3", "ext4", "xfs", "btrfs"))
+                if (!strextend_with_separator(&options, ",", "norecovery"))
+                        return -ENOMEM;
+
         r = mount_nofollow_verbose(LOG_DEBUG, node, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), options);
         if (r < 0)
                 return r;
 
+        if (rw && m->growfs && FLAGS_SET(flags, DISSECT_IMAGE_GROWFS))
+                (void) fs_grow(node, p);
+
+        return 1;
+}
+
+static int mount_root_tmpfs(const char *where, uid_t uid_shift, DissectImageFlags flags) {
+        _cleanup_free_ char *options = NULL;
+        int r;
+
+        assert(where);
+
+        /* For images that contain /usr/ but no rootfs, let's mount rootfs as tmpfs */
+
+        if (FLAGS_SET(flags, DISSECT_IMAGE_MKDIR)) {
+                r = mkdir_p(where, 0755);
+                if (r < 0)
+                        return r;
+        }
+
+        if (uid_is_valid(uid_shift)) {
+                if (asprintf(&options, "uid=" UID_FMT ",gid=" GID_FMT, uid_shift, (gid_t) uid_shift) < 0)
+                        return -ENOMEM;
+        }
+
+        r = mount_nofollow_verbose(LOG_DEBUG, "rootfs", where, "tmpfs", MS_NODEV, options);
+        if (r < 0)
+                return r;
+
         return 1;
 }
 
@@ -1414,16 +1623,20 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift,
          *  -EAFNOSUPPORT → File system type not supported or not known
          */
 
-        if (!m->partitions[PARTITION_ROOT].found)
-                return -ENXIO;
+        if (!(m->partitions[PARTITION_ROOT].found ||
+              (m->partitions[PARTITION_USR].found && FLAGS_SET(flags, DISSECT_IMAGE_USR_NO_ROOT))))
+                return -ENXIO; /* Require a root fs or at least a /usr/ fs (the latter is subject to a flag of its own) */
 
         if ((flags & DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY) == 0) {
-                r = mount_partition(m->partitions + PARTITION_ROOT, where, NULL, uid_shift, flags);
+
+                /* First mount the root fs. If there's none we use a tmpfs. */
+                if (m->partitions[PARTITION_ROOT].found)
+                        r = mount_partition(m->partitions + PARTITION_ROOT, where, NULL, uid_shift, flags);
+                else
+                        r = mount_root_tmpfs(where, uid_shift, flags);
                 if (r < 0)
                         return r;
-        }
 
-        if ((flags & DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY) == 0) {
                 /* For us mounting root always means mounting /usr as well */
                 r = mount_partition(m->partitions + PARTITION_USR, where, "/usr", uid_shift, flags);
                 if (r < 0)
@@ -1654,7 +1867,7 @@ static int decrypt_partition(
                 return log_debug_errno(r, "Failed to load LUKS metadata: %m");
 
         r = sym_crypt_activate_by_passphrase(cd, name, CRYPT_ANY_SLOT, passphrase, strlen(passphrase),
-                                             ((flags & DISSECT_IMAGE_READ_ONLY) ? CRYPT_ACTIVATE_READONLY : 0) |
+                                             ((flags & DISSECT_IMAGE_DEVICE_READ_ONLY) ? CRYPT_ACTIVATE_READONLY : 0) |
                                              ((flags & DISSECT_IMAGE_DISCARD_ON_CRYPTO) ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0));
         if (r < 0) {
                 log_debug_errno(r, "Failed to activate LUKS device: %m");
@@ -1993,7 +2206,7 @@ int dissected_image_decrypt_interactively(
 
                 z = strv_free(z);
 
-                r = ask_password_auto("Please enter image passphrase:", NULL, "dissect", "dissect", USEC_INFINITY, 0, &z);
+                r = ask_password_auto("Please enter image passphrase:", NULL, "dissect", "dissect", "dissect.passphrase", USEC_INFINITY, 0, &z);
                 if (r < 0)
                         return log_error_errno(r, "Failed to query for passphrase: %m");
 
@@ -2306,7 +2519,14 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
         if (r == 0) {
                 error_pipe[0] = safe_close(error_pipe[0]);
 
-                r = dissected_image_mount(m, t, UID_INVALID, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_VALIDATE_OS);
+                r = dissected_image_mount(
+                                m,
+                                t,
+                                UID_INVALID,
+                                DISSECT_IMAGE_READ_ONLY|
+                                DISSECT_IMAGE_MOUNT_ROOT_ONLY|
+                                DISSECT_IMAGE_VALIDATE_OS|
+                                DISSECT_IMAGE_USR_NO_ROOT);
                 if (r < 0) {
                         /* Let parent know the error */
                         (void) write(error_pipe[1], &r, sizeof(r));
@@ -2449,6 +2669,8 @@ int dissect_image_and_warn(
                 const char *name,
                 const VeritySettings *verity,
                 const MountOptions *mount_options,
+                uint64_t uevent_seqnum_not_before,
+                usec_t timestamp_not_before,
                 DissectImageFlags flags,
                 DissectedImage **ret) {
 
@@ -2463,7 +2685,7 @@ int dissect_image_and_warn(
                 name = buffer;
         }
 
-        r = dissect_image(fd, verity, mount_options, flags, ret);
+        r = dissect_image(fd, verity, mount_options, uevent_seqnum_not_before, timestamp_not_before, flags, ret);
         switch (r) {
 
         case -EOPNOTSUPP:
@@ -2538,6 +2760,7 @@ int mount_image_privately_interactively(
                 LoopDevice **ret_loop_device,
                 DecryptedImage **ret_decrypted_image) {
 
+        _cleanup_(verity_settings_done) VeritySettings verity = VERITY_SETTINGS_DEFAULT;
         _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
         _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
         _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
@@ -2554,23 +2777,27 @@ int mount_image_privately_interactively(
         assert(ret_loop_device);
         assert(ret_decrypted_image);
 
+        r = verity_settings_load(&verity, image, NULL, NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to load root hash data: %m");
+
         r = tempfn_random_child(NULL, program_invocation_short_name, &temp);
         if (r < 0)
                 return log_error_errno(r, "Failed to generate temporary mount directory: %m");
 
         r = loop_device_make_by_path(
                         image,
-                        FLAGS_SET(flags, DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : O_RDWR,
+                        FLAGS_SET(flags, DISSECT_IMAGE_DEVICE_READ_ONLY) ? O_RDONLY : O_RDWR,
                         FLAGS_SET(flags, DISSECT_IMAGE_NO_PARTITION_TABLE) ? 0 : LO_FLAGS_PARTSCAN,
                         &d);
         if (r < 0)
-                return log_error_errno(r, "Failed to set up loopback device: %m");
+                return log_error_errno(r, "Failed to set up loopback device for %s: %m", image);
 
-        r = dissect_image_and_warn(d->fd, image, NULL, NULL, flags, &dissected_image);
+        r = dissect_image_and_warn(d->fd, image, &verity, NULL, d->uevent_seqnum_not_before, d->timestamp_not_before, flags, &dissected_image);
         if (r < 0)
                 return r;
 
-        r = dissected_image_decrypt_interactively(dissected_image, NULL, NULL, flags, &decrypted_image);
+        r = dissected_image_decrypt_interactively(dissected_image, NULL, &verity, flags, &decrypted_image);
         if (r < 0)
                 return r;
 
@@ -2657,6 +2884,8 @@ int verity_dissect_and_mount(
                         loop_device->fd,
                         &verity,
                         options,
+                        loop_device->uevent_seqnum_not_before,
+                        loop_device->timestamp_not_before,
                         dissect_image_flags,
                         &dissected_image);
         /* No partition table? Might be a single-filesystem image, try again */
@@ -2665,7 +2894,9 @@ int verity_dissect_and_mount(
                                 loop_device->fd,
                                 &verity,
                                 options,
-                                dissect_image_flags|DISSECT_IMAGE_NO_PARTITION_TABLE,
+                                loop_device->uevent_seqnum_not_before,
+                                loop_device->timestamp_not_before,
+                                dissect_image_flags | DISSECT_IMAGE_NO_PARTITION_TABLE,
                                 &dissected_image);
         if (r < 0)
                 return log_debug_errno(r, "Failed to dissect image: %m");
index ddadda1c0cdcbb8177d153b34a6466a1621a4389..b2f5c5dc96b16f29aa04a6d0f9976694d0ddd92e 100644 (file)
@@ -18,11 +18,13 @@ typedef struct VeritySettings VeritySettings;
 struct DissectedPartition {
         bool found:1;
         bool rw:1;
+        bool growfs:1;
         int partno;        /* -1 if there was no partition and the images contains a file system directly */
         int architecture;  /* Intended architecture: either native, secondary or unset (-1). */
         sd_id128_t uuid;   /* Partition entry UUID as reported by the GPT */
         char *fstype;
         char *node;
+        char *label;
         char *decrypted_node;
         char *decrypted_fstype;
         char *mount_options;
@@ -48,6 +50,23 @@ typedef enum PartitionDesignator {
         _PARTITION_DESIGNATOR_INVALID = -EINVAL,
 } PartitionDesignator;
 
+static inline bool PARTITION_DESIGNATOR_VERSIONED(PartitionDesignator d) {
+        /* Returns true for all designators where we want to support a concept of "versioning", i.e. which
+         * likely contain software binaries (or hashes thereof) that make sense to be versioned as a
+         * whole. We use this check to automatically pick the newest version of these partitions, by version
+         * comparing the partition labels. */
+
+        return IN_SET(d,
+                      PARTITION_ROOT,
+                      PARTITION_ROOT_SECONDARY,
+                      PARTITION_USR,
+                      PARTITION_USR_SECONDARY,
+                      PARTITION_ROOT_VERITY,
+                      PARTITION_ROOT_SECONDARY_VERITY,
+                      PARTITION_USR_VERITY,
+                      PARTITION_USR_SECONDARY_VERITY);
+}
+
 static inline PartitionDesignator PARTITION_VERITY_OF(PartitionDesignator p) {
         switch (p) {
 
@@ -69,15 +88,15 @@ static inline PartitionDesignator PARTITION_VERITY_OF(PartitionDesignator p) {
 }
 
 typedef enum DissectImageFlags {
-        DISSECT_IMAGE_READ_ONLY           = 1 << 0,
+        DISSECT_IMAGE_DEVICE_READ_ONLY    = 1 << 0,  /* Make device read-only */
         DISSECT_IMAGE_DISCARD_ON_LOOP     = 1 << 1,  /* Turn on "discard" if on a loop device and file system supports it */
         DISSECT_IMAGE_DISCARD             = 1 << 2,  /* Turn on "discard" if file system supports it, on all block devices */
         DISSECT_IMAGE_DISCARD_ON_CRYPTO   = 1 << 3,  /* Turn on "discard" also on crypto devices */
-        DISSECT_IMAGE_DISCARD_ANY = DISSECT_IMAGE_DISCARD_ON_LOOP |
-                                    DISSECT_IMAGE_DISCARD |
-                                    DISSECT_IMAGE_DISCARD_ON_CRYPTO,
+        DISSECT_IMAGE_DISCARD_ANY         = DISSECT_IMAGE_DISCARD_ON_LOOP |
+                                            DISSECT_IMAGE_DISCARD |
+                                            DISSECT_IMAGE_DISCARD_ON_CRYPTO,
         DISSECT_IMAGE_GPT_ONLY            = 1 << 4,  /* Only recognize images with GPT partition tables */
-        DISSECT_IMAGE_REQUIRE_ROOT        = 1 << 5,  /* Don't accept disks without root partition (and if no partition table or only single generic partition, assume it's root) */
+        DISSECT_IMAGE_GENERIC_ROOT        = 1 << 5,  /* If no partition table or only single generic partition, assume it's the root fs */
         DISSECT_IMAGE_MOUNT_ROOT_ONLY     = 1 << 6,  /* Mount only the root and /usr partitions */
         DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY = 1 << 7,  /* Mount only the non-root and non-/usr partitions */
         DISSECT_IMAGE_VALIDATE_OS         = 1 << 8,  /* Refuse mounting images that aren't identifiable as OS images */
@@ -87,6 +106,12 @@ typedef enum DissectImageFlags {
         DISSECT_IMAGE_NO_PARTITION_TABLE  = 1 << 12, /* Only recognize single file system images */
         DISSECT_IMAGE_VERITY_SHARE        = 1 << 13, /* When activating a verity device, reuse existing one if already open */
         DISSECT_IMAGE_MKDIR               = 1 << 14, /* Make top-level directory to mount right before mounting, if missing */
+        DISSECT_IMAGE_USR_NO_ROOT         = 1 << 15, /* If no root fs is in the image, but /usr is, then allow this (so that we can mount the rootfs as tmpfs or so */
+        DISSECT_IMAGE_REQUIRE_ROOT        = 1 << 16, /* Don't accept disks without root partition (or at least /usr partition if DISSECT_IMAGE_USR_NO_ROOT is set) */
+        DISSECT_IMAGE_MOUNT_READ_ONLY     = 1 << 17, /* Make mounts read-only */
+        DISSECT_IMAGE_READ_ONLY           = DISSECT_IMAGE_DEVICE_READ_ONLY |
+                                            DISSECT_IMAGE_MOUNT_READ_ONLY,
+        DISSECT_IMAGE_GROWFS              = 1 << 18, /* Grow file systems in partitions marked for that to the size of the partitions after mount */
 } DissectImageFlags;
 
 struct DissectedImage {
@@ -136,8 +161,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all);
 const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator);
 
 int probe_filesystem(const char *node, char **ret_fstype);
-int dissect_image(int fd, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret);
-int dissect_image_and_warn(int fd, const char *name, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret);
+int dissect_image(int fd, const VeritySettings *verity, const MountOptions *mount_options, uint64_t uevent_seqnum_not_before, usec_t timestamp_not_before, DissectImageFlags flags, DissectedImage **ret);
+int dissect_image_and_warn(int fd, const char *name, const VeritySettings *verity, const MountOptions *mount_options, uint64_t uevent_seqnum_not_before, usec_t timestamp_not_before, DissectImageFlags flags, DissectedImage **ret);
 
 DissectedImage* dissected_image_unref(DissectedImage *m);
 DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref);
index 982c61d8fbd81627bd70bdb219b1628074769608..d53a394895aae835f1334fe137ed2e67619aace9 100644 (file)
@@ -102,9 +102,9 @@ int fw_iptables_add_masquerade(
         if (!source || source_prefixlen == 0)
                 return -EINVAL;
 
-        h = iptc_init("nat");
-        if (!h)
-                return -errno;
+        r = fw_iptables_init_nat(&h);
+        if (r < 0)
+                return r;
 
         sz = XT_ALIGN(sizeof(struct ipt_entry)) +
              XT_ALIGN(sizeof(struct ipt_entry_target)) +
@@ -192,9 +192,9 @@ int fw_iptables_add_local_dnat(
         if (remote_port <= 0)
                 return -EINVAL;
 
-        h = iptc_init("nat");
-        if (!h)
-                return -errno;
+        r = fw_iptables_init_nat(&h);
+        if (r < 0)
+                return r;
 
         sz = XT_ALIGN(sizeof(struct ipt_entry)) +
              XT_ALIGN(sizeof(struct ipt_entry_match)) +
@@ -348,3 +348,16 @@ int fw_iptables_add_local_dnat(
 
         return 0;
 }
+
+int fw_iptables_init_nat(struct xtc_handle **ret) {
+        _cleanup_(iptc_freep) struct xtc_handle *h = NULL;
+
+        h = iptc_init("nat");
+        if (!h)
+                return log_debug_errno(errno, "Failed to init \"nat\" table: %s", iptc_strerror(errno));
+
+        if (ret)
+                *ret = TAKE_PTR(h);
+
+        return 0;
+}
index 07e2d0bbd3dc35db035eaf22afd3b393bf6f56f3..14f5a35a878efe89a3c2e395299015be452cec7c 100644 (file)
@@ -46,6 +46,7 @@ int fw_nftables_add_local_dnat(
                 const union in_addr_union *previous_remote);
 
 #if HAVE_LIBIPTC
+struct xtc_handle;
 
 int fw_iptables_add_masquerade(
                 bool add,
@@ -61,4 +62,6 @@ int fw_iptables_add_local_dnat(
                 const union in_addr_union *remote,
                 uint16_t remote_port,
                 const union in_addr_union *previous_remote);
+
+int fw_iptables_init_nat(struct xtc_handle **ret);
 #endif
index 6bbc8bd509e1dfc9b0562b5b3336bcfbaa331e3b..76cf3343db78a1e88480c569eade2a13415bcf1c 100644 (file)
@@ -783,19 +783,17 @@ int table_update(Table *t, TableCell *cell, TableDataType type, const void *data
 }
 
 int table_add_many_internal(Table *t, TableDataType first_type, ...) {
-        TableDataType type;
-        va_list ap;
         TableCell *last_cell = NULL;
+        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 (;;) {
+
+        for (TableDataType type = first_type;; type = va_arg(ap, TableDataType)) {
                 const void *data;
                 union {
                         uint64_t size;
@@ -968,43 +966,43 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) {
                         size_t w = va_arg(ap, size_t);
 
                         r = table_set_minimum_width(t, last_cell, w);
-                        break;
+                        goto check;
                 }
 
                 case TABLE_SET_MAXIMUM_WIDTH: {
                         size_t w = va_arg(ap, size_t);
                         r = table_set_maximum_width(t, last_cell, w);
-                        break;
+                        goto check;
                 }
 
                 case TABLE_SET_WEIGHT: {
                         unsigned w = va_arg(ap, unsigned);
                         r = table_set_weight(t, last_cell, w);
-                        break;
+                        goto check;
                 }
 
                 case TABLE_SET_ALIGN_PERCENT: {
                         unsigned p = va_arg(ap, unsigned);
                         r = table_set_align_percent(t, last_cell, p);
-                        break;
+                        goto check;
                 }
 
                 case TABLE_SET_ELLIPSIZE_PERCENT: {
                         unsigned p = va_arg(ap, unsigned);
                         r = table_set_ellipsize_percent(t, last_cell, p);
-                        break;
+                        goto check;
                 }
 
                 case TABLE_SET_COLOR: {
                         const char *c = va_arg(ap, const char*);
                         r = table_set_color(t, last_cell, c);
-                        break;
+                        goto check;
                 }
 
                 case TABLE_SET_RGAP_COLOR: {
                         const char *c = va_arg(ap, const char*);
                         r = table_set_rgap_color(t, last_cell, c);
-                        break;
+                        goto check;
                 }
 
                 case TABLE_SET_BOTH_COLORS: {
@@ -1017,19 +1015,19 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) {
                         }
 
                         r = table_set_rgap_color(t, last_cell, c);
-                        break;
+                        goto check;
                 }
 
                 case TABLE_SET_URL: {
                         const char *u = va_arg(ap, const char*);
                         r = table_set_url(t, last_cell, u);
-                        break;
+                        goto check;
                 }
 
                 case TABLE_SET_UPPERCASE: {
                         int u = va_arg(ap, int);
                         r = table_set_uppercase(t, last_cell, u);
-                        break;
+                        goto check;
                 }
 
                 case _TABLE_DATA_TYPE_MAX:
@@ -1041,15 +1039,12 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) {
                         assert_not_reached("Uh? Unexpected data type.");
                 }
 
-                if (type < _TABLE_DATA_TYPE_MAX)
-                        r = table_add_cell(t, &last_cell, type, data);
-
+                r = table_add_cell(t, &last_cell, type, data);
+        check:
                 if (r < 0) {
                         va_end(ap);
                         return r;
                 }
-
-                type = va_arg(ap, TableDataType);
         }
 }
 
@@ -1414,7 +1409,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         case TABLE_TIMESTAMP:
         case TABLE_TIMESTAMP_UTC:
         case TABLE_TIMESTAMP_RELATIVE: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
                 char *ret;
 
                 p = new(char, FORMAT_TIMESTAMP_MAX);
@@ -1436,7 +1431,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
 
         case TABLE_TIMESPAN:
         case TABLE_TIMESPAN_MSEC: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = new(char, FORMAT_TIMESPAN_MAX);
                 if (!p)
@@ -1451,7 +1446,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         }
 
         case TABLE_SIZE: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = new(char, FORMAT_BYTES_MAX);
                 if (!p)
@@ -1465,7 +1460,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         }
 
         case TABLE_BPS: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
                 size_t n;
 
                 p = new(char, FORMAT_BYTES_MAX+2);
@@ -1483,7 +1478,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         }
 
         case TABLE_INT: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = new(char, DECIMAL_STR_WIDTH(d->int_val) + 1);
                 if (!p)
@@ -1495,7 +1490,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         }
 
         case TABLE_INT8: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = new(char, DECIMAL_STR_WIDTH(d->int8) + 1);
                 if (!p)
@@ -1507,7 +1502,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         }
 
         case TABLE_INT16: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = new(char, DECIMAL_STR_WIDTH(d->int16) + 1);
                 if (!p)
@@ -1519,7 +1514,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         }
 
         case TABLE_INT32: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = new(char, DECIMAL_STR_WIDTH(d->int32) + 1);
                 if (!p)
@@ -1531,7 +1526,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         }
 
         case TABLE_INT64: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = new(char, DECIMAL_STR_WIDTH(d->int64) + 1);
                 if (!p)
@@ -1543,7 +1538,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         }
 
         case TABLE_UINT: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = new(char, DECIMAL_STR_WIDTH(d->uint_val) + 1);
                 if (!p)
@@ -1555,7 +1550,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         }
 
         case TABLE_UINT8: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = new(char, DECIMAL_STR_WIDTH(d->uint8) + 1);
                 if (!p)
@@ -1567,7 +1562,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         }
 
         case TABLE_UINT16: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = new(char, DECIMAL_STR_WIDTH(d->uint16) + 1);
                 if (!p)
@@ -1579,7 +1574,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         }
 
         case TABLE_UINT32: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = new(char, DECIMAL_STR_WIDTH(d->uint32) + 1);
                 if (!p)
@@ -1591,7 +1586,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         }
 
         case TABLE_UINT64: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = new(char, DECIMAL_STR_WIDTH(d->uint64) + 1);
                 if (!p)
@@ -1603,7 +1598,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
         }
 
         case TABLE_PERCENT: {
-                _cleanup_free_ char *p;
+                _cleanup_free_ char *p = NULL;
 
                 p = new(char, DECIMAL_STR_WIDTH(d->percent) + 2);
                 if (!p)
index 749a1305c1b9d58d4edebd2b2e850aa56d8a26d7..1144e8027fbcd74bfba364272f5a91818a8ee8c1 100755 (executable)
@@ -1,8 +1,9 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 set -eu
+set -o pipefail
 
-$1 -dM -include netinet/in.h - </dev/null | \
-    awk '/^#define[ \t]+IPPROTO_[^ \t]+[ \t]+[^ \t]/ { print $2; }' | \
-    sed -e 's/IPPROTO_//'
+${1:?} -dM -include netinet/in.h - </dev/null | \
+       awk '/^#define[ \t]+IPPROTO_[^ \t]+[ \t]+[^ \t]/ { print $2; }' | \
+       sed -e 's/IPPROTO_//'
index 5b9c43252714b7b891f88b823af9d82c5f75bd65..4be1dd4ff47b2ccd182cb09d39bdc1300795ecaa 100644 (file)
@@ -71,12 +71,22 @@ int generator_add_symlink(const char *dir, const char *dst, const char *dep_type
         return 0;
 }
 
-static int write_fsck_sysroot_service(const char *dir, const char *what) {
+static int write_fsck_sysroot_service(
+                const char *unit, /* Either SPECIAL_FSCK_ROOT_SERVICE or SPECIAL_FSCK_USR_SERVICE */
+                const char *dir,
+                const char *what,
+                const char *extra_after) {
+
         _cleanup_free_ char *device = NULL, *escaped = NULL, *escaped2 = NULL;
         _cleanup_fclose_ FILE *f = NULL;
-        const char *unit;
+        const char *fn;
         int r;
 
+        /* Writes out special versions of systemd-root-fsck.service and systemd-usr-fsck.service for use in
+         * the initrd. The regular statically shipped versions of these unit files use / and /usr for as
+         * paths, which doesn't match what we need for the initrd (where the dirs are /sysroot +
+         * /sysusr/usr), hence we overwrite those versions here. */
+
         escaped = specifier_escape(what);
         if (!escaped)
                 return log_oom();
@@ -85,41 +95,44 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) {
         if (!escaped2)
                 return log_oom();
 
-        unit = strjoina(dir, "/"SPECIAL_FSCK_ROOT_SERVICE);
-        log_debug("Creating %s", unit);
+        fn = strjoina(dir, "/", unit);
+        log_debug("Creating %s", fn);
 
         r = unit_name_from_path(what, ".device", &device);
         if (r < 0)
                 return log_error_errno(r, "Failed to convert device \"%s\" to unit name: %m", what);
 
-        f = fopen(unit, "wxe");
+        f = fopen(fn, "wxe");
         if (!f)
-                return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
+                return log_error_errno(errno, "Failed to create unit file %s: %m", fn);
 
         fprintf(f,
                 "# Automatically generated by %1$s\n\n"
                 "[Unit]\n"
                 "Description=File System Check on %2$s\n"
-                "Documentation=man:systemd-fsck-root.service(8)\n"
+                "Documentation=man:%3$s(8)\n"
                 "DefaultDependencies=no\n"
-                "BindsTo=%3$s\n"
+                "BindsTo=%4$s\n"
                 "Conflicts=shutdown.target\n"
-                "After=initrd-root-device.target local-fs-pre.target %3$s\n"
+                "After=%5$s%6$slocal-fs-pre.target %4$s\n"
                 "Before=shutdown.target\n"
                 "\n"
                 "[Service]\n"
                 "Type=oneshot\n"
                 "RemainAfterExit=yes\n"
-                "ExecStart=" SYSTEMD_FSCK_PATH " %4$s\n"
+                "ExecStart=" SYSTEMD_FSCK_PATH " %7$s\n"
                 "TimeoutSec=0\n",
                 program_invocation_short_name,
                 escaped,
+                unit,
                 device,
+                strempty(extra_after),
+                isempty(extra_after) ? "" : " ",
                 escaped2);
 
         r = fflush_and_check(f);
         if (r < 0)
-                return log_error_errno(r, "Failed to write unit file %s: %m", unit);
+                return log_error_errno(r, "Failed to write unit file %s: %m", fn);
 
         return 0;
 }
@@ -138,6 +151,13 @@ int generator_write_fsck_deps(
         assert(what);
         assert(where);
 
+        /* Let's do an early exit if we are invoked for the root and /usr/ trees in the initrd, to avoid
+         * generating confusing log messages */
+        if (in_initrd() && PATH_IN_SET(where, "/", "/usr")) {
+                log_debug("Skipping fsck for %s in initrd.", where);
+                return 0;
+        }
+
         if (!is_device_path(what)) {
                 log_warning("Checking was requested for \"%s\", but it is not a device.", what);
                 return 0;
@@ -157,6 +177,11 @@ int generator_write_fsck_deps(
         if (path_equal(where, "/")) {
                 const char *lnk;
 
+                /* We support running the fsck instance for the root fs while it is already mounted, for
+                 * compatibility with non-initrd boots. It's ugly, but it is how it is. Since – unlike for
+                 * regular file systems – this means the ordering is reversed (i.e. mount *before* fsck) we
+                 * have a separate fsck unit for this, independent of systemd-fsck@.service. */
+
                 lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/" SPECIAL_FSCK_ROOT_SERVICE);
 
                 (void) mkdir_parents(lnk, 0755);
@@ -168,19 +193,27 @@ int generator_write_fsck_deps(
                 const char *fsck, *dep;
 
                 if (in_initrd() && path_equal(where, "/sysroot")) {
-                        r = write_fsck_sysroot_service(dir, what);
+                        r = write_fsck_sysroot_service(SPECIAL_FSCK_ROOT_SERVICE, dir, what, SPECIAL_INITRD_ROOT_DEVICE_TARGET);
                         if (r < 0)
                                 return r;
 
                         fsck = SPECIAL_FSCK_ROOT_SERVICE;
                         dep = "Requires";
+
+                } else if (in_initrd() && path_equal(where, "/sysusr/usr")) {
+                        r = write_fsck_sysroot_service(SPECIAL_FSCK_USR_SERVICE, dir, what, NULL);
+                        if (r < 0)
+                                return r;
+
+                        fsck = SPECIAL_FSCK_USR_SERVICE;
+                        dep = "Requires";
                 } else {
                         /* When this is /usr, then let's add a Wants= dependency, otherwise a Requires=
                          * dependency. Why? We can't possibly unmount /usr during shutdown, but if we have a
                          * Requires= from /usr onto a fsck@.service unit and that unit is shut down, then
                          * we'd have to unmount /usr too.  */
 
-                        dep = !in_initrd() && path_equal(where, "/usr") ? "Wants" : "Requires";
+                        dep = path_equal(where, "/usr") ? "Wants" : "Requires";
 
                         r = unit_name_from_path_instance("systemd-fsck", what, ".service", &_fsck);
                         if (r < 0)
@@ -470,6 +503,9 @@ int generator_hook_up_growfs(
         const char *unit_file;
         int r;
 
+        assert(dir);
+        assert(where);
+
         escaped = cescape(where);
         if (!escaped)
                 return log_oom();
@@ -501,9 +537,10 @@ int generator_hook_up_growfs(
                 "BindsTo=%%i.mount\n"
                 "Conflicts=shutdown.target\n"
                 "After=%%i.mount\n"
-                "Before=shutdown.target %s\n",
+                "Before=shutdown.target%s%s\n",
                 program_invocation_short_name,
-                target);
+                target ? " " : "",
+                strempty(target));
 
         if (empty_or_root(where)) /* Make sure the root fs is actually writable before we resize it */
                 fprintf(f,
index a96f5ee02daba899a757806dcbe8cd9f856c381a..558b69c48793400500dc41de2d4589018307c1b1 100644 (file)
@@ -106,3 +106,71 @@ int gpt_partition_label_valid(const char *s) {
 
         return char16_strlen(recoded) <= 36;
 }
+
+bool gpt_partition_type_is_root(sd_id128_t id) {
+        return sd_id128_in_set(id,
+                               GPT_ROOT_X86,
+                               GPT_ROOT_X86_64,
+                               GPT_ROOT_ARM,
+                               GPT_ROOT_ARM_64,
+                               GPT_ROOT_IA64,
+                               GPT_ROOT_RISCV32,
+                               GPT_ROOT_RISCV64);
+}
+
+bool gpt_partition_type_is_root_verity(sd_id128_t id) {
+        return sd_id128_in_set(id,
+                               GPT_ROOT_X86_VERITY,
+                               GPT_ROOT_X86_64_VERITY,
+                               GPT_ROOT_ARM_VERITY,
+                               GPT_ROOT_ARM_64_VERITY,
+                               GPT_ROOT_IA64_VERITY,
+                               GPT_ROOT_RISCV32_VERITY,
+                               GPT_ROOT_RISCV64_VERITY);
+}
+
+bool gpt_partition_type_is_usr(sd_id128_t id) {
+        return sd_id128_in_set(id,
+                               GPT_USR_X86,
+                               GPT_USR_X86_64,
+                               GPT_USR_ARM,
+                               GPT_USR_ARM_64,
+                               GPT_USR_IA64,
+                               GPT_USR_RISCV32,
+                               GPT_USR_RISCV64);
+}
+
+bool gpt_partition_type_is_usr_verity(sd_id128_t id) {
+        return sd_id128_in_set(id,
+                               GPT_USR_X86_VERITY,
+                               GPT_USR_X86_64_VERITY,
+                               GPT_USR_ARM_VERITY,
+                               GPT_USR_ARM_64_VERITY,
+                               GPT_USR_IA64_VERITY,
+                               GPT_USR_RISCV32_VERITY,
+                               GPT_USR_RISCV64_VERITY);
+}
+
+bool gpt_partition_type_knows_read_only(sd_id128_t id) {
+        return gpt_partition_type_is_root(id) ||
+                gpt_partition_type_is_usr(id) ||
+                sd_id128_in_set(id,
+                                GPT_HOME,
+                                GPT_SRV,
+                                GPT_VAR,
+                                GPT_TMP,
+                                GPT_XBOOTLDR) ||
+                gpt_partition_type_is_root_verity(id) || /* pretty much implied, but let's set the bit to make things really clear */
+                gpt_partition_type_is_usr_verity(id);    /* ditto */
+}
+
+bool gpt_partition_type_knows_growfs(sd_id128_t id) {
+        return gpt_partition_type_is_root(id) ||
+                gpt_partition_type_is_usr(id) ||
+                sd_id128_in_set(id,
+                                GPT_HOME,
+                                GPT_SRV,
+                                GPT_VAR,
+                                GPT_TMP,
+                                GPT_XBOOTLDR);
+}
index 2e0f50c3c648fc83798261ff301524dd63676c96..6581973793d66fe9cf6e2dab3648edfe003321bd 100644 (file)
  * auto-discovery. These happen to be identical to what Microsoft defines for its own Basic Data Partitions,
  * but that's just because we saw no point in defining any other values here. */
 #define GPT_FLAG_READ_ONLY (1ULL << 60)
-#define GPT_FLAG_NO_AUTO (1ULL << 63)
+#define GPT_FLAG_NO_AUTO   (1ULL << 63)
+#define GPT_FLAG_GROWFS    (1ULL << 59)
 
 const char *gpt_partition_type_uuid_to_string(sd_id128_t id);
 const char *gpt_partition_type_uuid_to_string_harder(
@@ -128,3 +129,11 @@ typedef struct GptPartitionType {
 extern const GptPartitionType gpt_partition_type_table[];
 
 int gpt_partition_label_valid(const char *s);
+
+bool gpt_partition_type_is_root(sd_id128_t id);
+bool gpt_partition_type_is_root_verity(sd_id128_t id);
+bool gpt_partition_type_is_usr(sd_id128_t id);
+bool gpt_partition_type_is_usr_verity(sd_id128_t id);
+
+bool gpt_partition_type_knows_read_only(sd_id128_t id);
+bool gpt_partition_type_knows_growfs(sd_id128_t id);
index c6cea43126f866a8aac41862f1eced06e27caf46..3e9f6a3df309987fcb98fdfd3ed8ca27d7357aa0 100644 (file)
@@ -350,6 +350,11 @@ void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *chang
                                 log_info("Unit %s is an alias to a unit that is not present, ignoring.",
                                          changes[i].path);
                         break;
+                case UNIT_FILE_DESTINATION_NOT_PRESENT:
+                        if (!quiet)
+                                log_warning("Unit %s is added as a dependency to a non-existent unit %s.",
+                                            changes[i].source, changes[i].path);
+                        break;
                 case -EEXIST:
                         if (changes[i].source)
                                 log_error_errno(changes[i].type_or_errno,
@@ -1749,12 +1754,12 @@ int unit_file_verify_alias(const UnitFileInstallInfo *i, const char *dst, char *
                                                  "Invalid path \"%s\" in alias.", dir);
                 *p = '\0'; /* dir should now be a unit name */
 
-                r = unit_name_classify(dir);
-                if (r < 0)
+                UnitNameFlags type = unit_name_classify(dir);
+                if (type < 0)
                         return log_warning_errno(SYNTHETIC_ERRNO(EXDEV),
                                                  "Invalid unit name component \"%s\" in alias.", dir);
 
-                const bool instance_propagation = r == UNIT_NAME_TEMPLATE;
+                const bool instance_propagation = type == UNIT_NAME_TEMPLATE;
 
                 /* That's the name we want to use for verification. */
                 r = unit_symlink_name_compatible(path_alias, i->name, instance_propagation);
@@ -1771,11 +1776,11 @@ int unit_file_verify_alias(const UnitFileInstallInfo *i, const char *dst, char *
                 if (unit_name_is_valid(dst, UNIT_NAME_TEMPLATE)) {
                         _cleanup_free_ char *inst = NULL;
 
-                        r = unit_name_to_instance(i->name, &inst);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to extract instance name from %s: %m", i->name);
+                        UnitNameFlags type = unit_name_to_instance(i->name, &inst);
+                        if (type < 0)
+                                return log_error_errno(type, "Failed to extract instance name from %s: %m", i->name);
 
-                        if (r == UNIT_NAME_INSTANCE) {
+                        if (type == UNIT_NAME_INSTANCE) {
                                 r = unit_name_replace_instance(dst, inst, &dst_updated);
                                 if (r < 0)
                                         return log_error_errno(r, "Failed to build unit name from %s+%s: %m",
@@ -1832,6 +1837,7 @@ static int install_info_symlink_alias(
 }
 
 static int install_info_symlink_wants(
+                UnitFileScope scope,
                 UnitFileInstallInfo *i,
                 const LookupPaths *paths,
                 const char *config_path,
@@ -1902,6 +1908,9 @@ static int install_info_symlink_wants(
                 q = create_symlink(paths, i->path, path, true, changes, n_changes);
                 if (r == 0)
                         r = q;
+
+                if (unit_file_exists(scope, paths, dst) == 0)
+                        unit_file_changes_add(changes, n_changes, UNIT_FILE_DESTINATION_NOT_PRESENT, dst, i->path);
         }
 
         return r;
@@ -1937,6 +1946,7 @@ static int install_info_symlink_link(
 }
 
 static int install_info_apply(
+                UnitFileScope scope,
                 UnitFileInstallInfo *i,
                 const LookupPaths *paths,
                 const char *config_path,
@@ -1955,11 +1965,11 @@ static int install_info_apply(
 
         r = install_info_symlink_alias(i, paths, config_path, force, changes, n_changes);
 
-        q = install_info_symlink_wants(i, paths, config_path, i->wanted_by, ".wants/", changes, n_changes);
+        q = install_info_symlink_wants(scope, i, paths, config_path, i->wanted_by, ".wants/", changes, n_changes);
         if (r == 0)
                 r = q;
 
-        q = install_info_symlink_wants(i, paths, config_path, i->required_by, ".requires/", changes, n_changes);
+        q = install_info_symlink_wants(scope, i, paths, config_path, i->required_by, ".requires/", changes, n_changes);
         if (r == 0)
                 r = q;
 
@@ -2023,7 +2033,7 @@ static int install_context_apply(
                 if (i->type != UNIT_FILE_TYPE_REGULAR)
                         continue;
 
-                q = install_info_apply(i, paths, config_path, force, changes, n_changes);
+                q = install_info_apply(scope, i, paths, config_path, force, changes, n_changes);
                 if (r >= 0) {
                         if (q < 0)
                                 r = q;
@@ -2950,7 +2960,7 @@ static int read_presets(UnitFileScope scope, const char *root_dir, UnitFilePrese
                 return r;
 
         STRV_FOREACH(p, files) {
-                _cleanup_fclose_ FILE *f;
+                _cleanup_fclose_ FILE *f = NULL;
                 int n = 0;
 
                 f = fopen(*p, "re");
@@ -3457,10 +3467,11 @@ static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
 
 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
-        [UNIT_FILE_SYMLINK]     = "symlink",
-        [UNIT_FILE_UNLINK]      = "unlink",
-        [UNIT_FILE_IS_MASKED]   = "masked",
-        [UNIT_FILE_IS_DANGLING] = "dangling",
+        [UNIT_FILE_SYMLINK]                 = "symlink",
+        [UNIT_FILE_UNLINK]                  = "unlink",
+        [UNIT_FILE_IS_MASKED]               = "masked",
+        [UNIT_FILE_IS_DANGLING]             = "dangling",
+        [UNIT_FILE_DESTINATION_NOT_PRESENT] = "destination not present",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, int);
index 948faa0ca7d8b479fc05fae6cbe3f75f69d8903e..7ab0a871e04af2fce4577d9c157e6011b85d20b3 100644 (file)
@@ -32,6 +32,7 @@ enum {
         UNIT_FILE_UNLINK,
         UNIT_FILE_IS_MASKED,
         UNIT_FILE_IS_DANGLING,
+        UNIT_FILE_DESTINATION_NOT_PRESENT,
         _UNIT_FILE_CHANGE_TYPE_MAX,
         _UNIT_FILE_CHANGE_TYPE_INVALID = -EINVAL,
 };
index 22b8aba07e5028a30d372272b339ee61cb0acdbf..951ed09899c5dce36e0b68fc18dd7daa52724469 100644 (file)
@@ -566,7 +566,7 @@ int fido2_generate_hmac_hash(
                         if (!has_client_pin)
                                 log_warning("Weird, device asked for client PIN, but does not advertise it as feature. Ignoring.");
 
-                        r = ask_password_auto("Please enter security token PIN:", askpw_icon_name, NULL, "fido2-pin", USEC_INFINITY, 0, &pin);
+                        r = ask_password_auto("Please enter security token PIN:", askpw_icon_name, NULL, "fido2-pin", "fido2-pin", USEC_INFINITY, 0, &pin);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to acquire user PIN: %m");
 
index 1de890f1421fe5416bcd2135e8ab8ebbee3d5ed4..c97687cd054b0cc4b69f4a004f8e501e40ad793a 100644 (file)
@@ -1,8 +1,11 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include <net/if_arp.h>
+
 #include "sd-netlink.h"
 
 #include "alloc-util.h"
+#include "fd-util.h"
 #include "local-addresses.h"
 #include "macro.h"
 #include "netlink-util.h"
@@ -33,7 +36,34 @@ static int address_compare(const struct local_address *a, const struct local_add
         return memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(a->family));
 }
 
-int local_addresses(sd_netlink *context, int ifindex, int af, struct local_address **ret) {
+static void suppress_duplicates(struct local_address *list, size_t *n_list) {
+        size_t old_size, new_size;
+
+        /* Removes duplicate entries, assumes the list of addresses is already sorted. Updates in-place. */
+
+        if (*n_list < 2) /* list with less than two entries can't have duplicates */
+                return;
+
+        old_size = *n_list;
+        new_size = 1;
+
+        for (size_t i = 1; i < old_size; i++) {
+
+                if (address_compare(list + i, list + new_size - 1) == 0)
+                        continue;
+
+                list[new_size++] = list[i];
+        }
+
+        *n_list = new_size;
+}
+
+int local_addresses(
+                sd_netlink *context,
+                int ifindex,
+                int af,
+                struct local_address **ret) {
+
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         _cleanup_free_ struct local_address *list = NULL;
@@ -135,6 +165,7 @@ int local_addresses(sd_netlink *context, int ifindex, int af, struct local_addre
 
         if (ret) {
                 typesafe_qsort(list, n_list, address_compare);
+                suppress_duplicates(list, &n_list);
                 *ret = TAKE_PTR(list);
         }
 
@@ -171,7 +202,12 @@ static int add_local_gateway(
         return 0;
 }
 
-int local_gateways(sd_netlink *context, int ifindex, int af, struct local_address **ret) {
+int local_gateways(
+                sd_netlink *context,
+                int ifindex,
+                int af,
+                struct local_address **ret) {
+
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         _cleanup_free_ struct local_address *list = NULL;
@@ -308,6 +344,151 @@ int local_gateways(sd_netlink *context, int ifindex, int af, struct local_addres
 
         if (ret) {
                 typesafe_qsort(list, n_list, address_compare);
+                suppress_duplicates(list, &n_list);
+                *ret = TAKE_PTR(list);
+        }
+
+        return (int) n_list;
+}
+
+int local_outbounds(
+                sd_netlink *context,
+                int ifindex,
+                int af,
+                struct local_address **ret) {
+
+        _cleanup_free_ struct local_address *list = NULL, *gateways = NULL;
+        size_t n_list = 0, n_allocated = 0;
+        int r, n_gateways;
+
+        /* Determines our default outbound addresses, i.e. the "primary" local addresses we use to talk to IP
+         * addresses behind the default routes. This is still an address of the local host (i.e. this doesn't
+         * resolve NAT or so), but it's the set of addresses the local IP stack most likely uses to talk to
+         * other hosts.
+         *
+         * This works by connect()ing a SOCK_DGRAM socket to the local gateways, and then reading the IP
+         * address off the socket that was chosen for the routing decision. */
+
+        n_gateways = local_gateways(context, ifindex, af, &gateways);
+        if (n_gateways < 0)
+                return n_gateways;
+        if (n_gateways == 0) {
+                /* No gateways? Then we have no outbound addresses either. */
+                if (ret)
+                        *ret = NULL;
+
+                return 0;
+        }
+
+        for (int i = 0; i < n_gateways; i++) {
+                _cleanup_close_ int fd = -1;
+                union sockaddr_union sa;
+                socklen_t salen;
+
+                fd = socket(gateways[i].family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+                if (fd < 0)
+                        return -errno;
+
+                switch (gateways[i].family) {
+
+                case AF_INET:
+                        sa.in = (struct sockaddr_in) {
+                                .sin_family = AF_INET,
+                                .sin_addr = gateways[i].address.in,
+                                .sin_port = htobe16(53), /* doesn't really matter which port we pick — we just care about the routing decision */
+                        };
+
+                        break;
+
+                case AF_INET6:
+                        sa.in6 = (struct sockaddr_in6) {
+                                .sin6_family = AF_INET6,
+                                .sin6_addr = gateways[i].address.in6,
+                                .sin6_port = htobe16(53),
+                                .sin6_scope_id = gateways[i].ifindex,
+                        };
+
+                        break;
+
+                default:
+                        assert_not_reached("Unexpected protocol");
+                }
+
+                /* So ideally we'd just use IP_UNICAST_IF here to pass the ifindex info to the kernel before
+                 * connect()ing, sot that it influences the routing decision. However, on current kernels
+                 * IP_UNICAST_IF doesn't actually influence the routing decision for UDP — which I think
+                 * should probably just be considered a bug. Once that bug is fixed this is the best API to
+                 * use, since it is the most lightweight. */
+                r = socket_set_unicast_if(fd, gateways[i].family, gateways[i].ifindex);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to set unicast interface index %i, ignoring: %m", gateways[i].ifindex);
+
+                /* We'll also use SO_BINDTOINDEX. This requires CAP_NET_RAW on old kernels, hence there's a
+                 * good chance this fails. Since 5.7 this restriction was dropped and the first
+                 * SO_BINDTOINDEX on a socket may be done without privileges. This one has the benefit of
+                 * really influencing the routing decision, i.e. this one definitely works for us — as long
+                 * as we have the privileges for it.*/
+                r = socket_bind_to_ifindex(fd, gateways[i].ifindex);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to bind socket to interface %i, ignoring: %m", gateways[i].ifindex);
+
+                /* Let's now connect() to the UDP socket, forcing the kernel to make a routing decision and
+                 * auto-bind the socket. We ignore failures on this, since that failure might happen for a
+                 * multitude of reasons (policy/firewall issues, who knows?) and some of them might be
+                 * *after* the routing decision and the auto-binding already took place. If so we can still
+                 * make use of the binding and return it. Hence, let's not unnecessarily fail early here: we
+                 * can still easily detect if the auto-binding worked or not, by comparing the bound IP
+                 * address with zero — which we do below.  */
+                if (connect(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0)
+                        log_debug_errno(errno, "Failed to connect SOCK_DGRAM socket to gateway, ignoring: %m");
+
+                /* Let's now read the socket address of the socket. A routing decision should have been
+                 * made. Let's verify that and use the data. */
+                salen = SOCKADDR_LEN(sa);
+                if (getsockname(fd, &sa.sa, &salen) < 0)
+                        return -errno;
+                assert(sa.sa.sa_family == gateways[i].family);
+                assert(salen == SOCKADDR_LEN(sa));
+
+                switch (gateways[i].family) {
+
+                case AF_INET:
+                        if (in4_addr_is_null(&sa.in.sin_addr)) /* Auto-binding didn't work. :-( */
+                                continue;
+
+                        if (!GREEDY_REALLOC(list, n_allocated, n_list+1))
+                                return -ENOMEM;
+
+                        list[n_list++] = (struct local_address) {
+                                .family = gateways[i].family,
+                                .ifindex = gateways[i].ifindex,
+                                .address.in = sa.in.sin_addr,
+                        };
+
+                        break;
+
+                case AF_INET6:
+                        if (in6_addr_is_null(&sa.in6.sin6_addr))
+                                continue;
+
+                        if (!GREEDY_REALLOC(list, n_allocated, n_list+1))
+                                return -ENOMEM;
+
+                        list[n_list++] = (struct local_address) {
+                                .family = gateways[i].family,
+                                .ifindex = gateways[i].ifindex,
+                                .address.in6 = sa.in6.sin6_addr,
+                        };
+                        break;
+
+                default:
+                        assert_not_reached("Unexpected protocol");
+                }
+        }
+
+        if (ret) {
+                typesafe_qsort(list, n_list, address_compare);
+                suppress_duplicates(list, &n_list);
                 *ret = TAKE_PTR(list);
         }
 
index c633995dc9a62b7b7c0f5113c9dbed5f7a1e2b6a..38a17d233e61eb7d5847d510e781b5944e32b9ae 100644 (file)
@@ -15,3 +15,5 @@ struct local_address {
 int local_addresses(sd_netlink *rtnl, int ifindex, int af, struct local_address **ret);
 
 int local_gateways(sd_netlink *rtnl, int ifindex, int af, struct local_address **ret);
+
+int local_outbounds(sd_netlink *rtnl, int ifindex, int af, struct local_address **ret);
index 3a4dcaa267b2db2f8992d1660357c284a3941867..51eaa0c06e28c13e444e7f37fbe0f923ec8ad696 100644 (file)
@@ -3,13 +3,38 @@
 
 #include "log.h"
 
-#define log_interface_full_errno(ifname, level, error, ...)             \
+#define log_interface_full_errno_zerook(ifname, level, error, ...)      \
         ({                                                              \
                 const char *_ifname = (ifname);                         \
                 _ifname ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "INTERFACE=", _ifname, NULL, NULL, ##__VA_ARGS__) : \
                         log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
         })
 
+#define log_interface_full_errno(ifname, level, error, ...)             \
+        ({                                                              \
+                int _error = (error);                                   \
+                ASSERT_NON_ZERO(_error);                                \
+                log_interface_full_errno_zerook(ifname, level, _error, __VA_ARGS__); \
+        })
+
+#define log_interface_prefix_full_errno_zerook(prefix, ifname_expr, error, fmt, ...) \
+        ({                                                              \
+                int _e = (error);                                       \
+                if (DEBUG_LOGGING)                                      \
+                        log_interface_full_errno_zerook(                \
+                                ifname_expr,                            \
+                                LOG_DEBUG, _e, prefix fmt,              \
+                                ##__VA_ARGS__);                         \
+                -ERRNO_VALUE(_e);                                       \
+        })
+
+#define log_interface_prefix_full_errno(prefix, ifname_expr, error, fmt, ...) \
+        ({                                                              \
+                int _error = (error);                                   \
+                ASSERT_NON_ZERO(_error);                                \
+                log_interface_prefix_full_errno_zerook(prefix, ifname_expr, _error, fmt, ##__VA_ARGS__); \
+        })
+
 /*
  * The following macros append INTERFACE= to the message.
  * The macros require a struct named 'Link' which contains 'char *ifname':
  * See, network/networkd-link.h for example.
  */
 
-#define log_link_full_errno(link, level, error, ...)                    \
+#define log_link_full_errno_zerook(link, level, error, ...)             \
         ({                                                              \
                 const Link *_l = (link);                                \
-                log_interface_full_errno(_l ? _l->ifname : NULL, level, error, ##__VA_ARGS__); \
+                log_interface_full_errno_zerook(_l ? _l->ifname : NULL, level, error, __VA_ARGS__); \
+        })
+
+#define log_link_full_errno(link, level, error, ...)                    \
+        ({                                                              \
+                int _error = (error);                                   \
+                ASSERT_NON_ZERO(_error);                                \
+                log_link_full_errno_zerook(link, level, _error, __VA_ARGS__); \
         })
 
-#define log_link_full(link, level, ...) (void) log_link_full_errno(link, level, 0, __VA_ARGS__)
+#define log_link_full(link, level, ...) (void) log_link_full_errno_zerook(link, level, 0, __VA_ARGS__)
 
-#define log_link_debug(link, ...)   log_link_full_errno(link, LOG_DEBUG, 0, __VA_ARGS__)
+#define log_link_debug(link, ...)   log_link_full(link, LOG_DEBUG, __VA_ARGS__)
 #define log_link_info(link, ...)    log_link_full(link, LOG_INFO, __VA_ARGS__)
 #define log_link_notice(link, ...)  log_link_full(link, LOG_NOTICE, __VA_ARGS__)
 #define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, __VA_ARGS__)
index 706a00c7f0612d6e087f265e965c2d2908a3aceb..e63c59bd94e324b686a42b1d6986a941ac0c677f 100644 (file)
@@ -294,7 +294,7 @@ static bool print_multiline(
                                         continuation * prefix, "",
                                         color_on, len, pos, color_off);
                         else {
-                                _cleanup_free_ char *e;
+                                _cleanup_free_ char *e = NULL;
 
                                 e = ellipsize_mem(pos, len, n_columns - prefix,
                                                   tail_line ? 100 : 90);
@@ -1651,7 +1651,7 @@ int show_journal_by_unit(
                 return r;
 
         if (DEBUG_LOGGING) {
-                _cleanup_free_ char *filter;
+                _cleanup_free_ char *filter = NULL;
 
                 filter = journal_make_match_string(j);
                 if (!filter)
index 84f415aa61c1eb33af8adda898bdad419672a879..c038e7aae6c60aae05586765fa8002e6e69908c7 100644 (file)
@@ -53,6 +53,23 @@ static int loop_is_bound(int fd) {
         return true; /* bound! */
 }
 
+static int get_current_uevent_seqnum(uint64_t *ret) {
+        _cleanup_free_ char *p = NULL;
+        int r;
+
+        r = read_full_virtual_file("/sys/kernel/uevent_seqnum", &p, NULL);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to read current uevent sequence number: %m");
+
+        truncate_nl(p);
+
+        r = safe_atou64(p, ret);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to parse current uevent sequence number: %s", p);
+
+        return 0;
+}
+
 static int device_has_block_children(sd_device *d) {
         _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
         const char *main_sn, *main_ss;
@@ -114,11 +131,15 @@ static int loop_configure(
                 int fd,
                 int nr,
                 const struct loop_config *c,
-                bool *try_loop_configure) {
+                bool *try_loop_configure,
+                uint64_t *ret_seqnum_not_before,
+                usec_t *ret_timestamp_not_before) {
 
         _cleanup_(sd_device_unrefp) sd_device *d = NULL;
         _cleanup_free_ char *sysname = NULL;
         _cleanup_close_ int lock_fd = -1;
+        uint64_t seqnum;
+        usec_t timestamp;
         int r;
 
         assert(fd >= 0);
@@ -167,6 +188,17 @@ static int loop_configure(
         }
 
         if (*try_loop_configure) {
+                /* Acquire uevent seqnum immediately before attaching the loopback device. This allows
+                 * callers to ignore all uevents with a seqnum before this one, if they need to associate
+                 * uevent with this attachment. Doing so isn't race-free though, as uevents that happen in
+                 * the window between this reading of the seqnum, and the LOOP_CONFIGURE call might still be
+                 * mistaken as originating from our attachment, even though might be caused by an earlier
+                 * use. But doing this at least shortens the race window a bit. */
+                r = get_current_uevent_seqnum(&seqnum);
+                if (r < 0)
+                        return r;
+                timestamp = now(CLOCK_MONOTONIC);
+
                 if (ioctl(fd, LOOP_CONFIGURE, c) < 0) {
                         /* Do fallback only if LOOP_CONFIGURE is not supported, propagate all other
                          * errors. Note that the kernel is weird: non-existing ioctls currently return EINVAL
@@ -224,10 +256,21 @@ static int loop_configure(
                                 goto fail;
                         }
 
+                        if (ret_seqnum_not_before)
+                                *ret_seqnum_not_before = seqnum;
+                        if (ret_timestamp_not_before)
+                                *ret_timestamp_not_before = timestamp;
+
                         return 0;
                 }
         }
 
+        /* Let's read the seqnum again, to shorten the window. */
+        r = get_current_uevent_seqnum(&seqnum);
+        if (r < 0)
+                return r;
+        timestamp = now(CLOCK_MONOTONIC);
+
         /* Since kernel commit 5db470e229e22b7eda6e23b5566e532c96fb5bc3 (kernel v5.0) the LOOP_SET_STATUS64
          * ioctl can return EAGAIN in case we change the lo_offset field, if someone else is accessing the
          * block device while we try to reconfigure it. This is a pretty common case, since udev might
@@ -252,9 +295,14 @@ static int loop_configure(
                 /* Sleep some random time, but at least 10ms, at most 250ms. Increase the delay the more
                  * failed attempts we see */
                 (void) usleep(UINT64_C(10) * USEC_PER_MSEC +
-                              random_u64() % (UINT64_C(240) * USEC_PER_MSEC * n_attempts/64));
+                              random_u64_range(UINT64_C(240) * USEC_PER_MSEC * n_attempts/64));
         }
 
+        if (ret_seqnum_not_before)
+                *ret_seqnum_not_before = seqnum;
+        if (ret_timestamp_not_before)
+                *ret_timestamp_not_before = timestamp;
+
         return 0;
 
 fail:
@@ -312,6 +360,8 @@ int loop_device_make(
         bool try_loop_configure = true;
         struct loop_config config;
         LoopDevice *d = NULL;
+        uint64_t seqnum = UINT64_MAX;
+        usec_t timestamp = USEC_INFINITY;
         struct stat st;
         int nr = -1, r;
 
@@ -353,6 +403,9 @@ int loop_device_make(
                                 .nr = nr,
                                 .node = TAKE_PTR(loopdev),
                                 .relinquished = true, /* It's not allocated by us, don't destroy it when this object is freed */
+                                .devno = st.st_rdev,
+                                .uevent_seqnum_not_before = UINT64_MAX,
+                                .timestamp_not_before = USEC_INFINITY,
                         };
 
                         *ret = d;
@@ -400,7 +453,7 @@ int loop_device_make(
                         if (!IN_SET(errno, ENOENT, ENXIO))
                                 return -errno;
                 } else {
-                        r = loop_configure(loop, nr, &config, &try_loop_configure);
+                        r = loop_configure(loop, nr, &config, &try_loop_configure, &seqnum, &timestamp);
                         if (r >= 0) {
                                 loop_with_fd = TAKE_FD(loop);
                                 break;
@@ -421,10 +474,14 @@ int loop_device_make(
 
                 /* Wait some random time, to make collision less likely. Let's pick a random time in the
                  * range 0ms…250ms, linearly scaled by the number of failed attempts. */
-                (void) usleep(random_u64() % (UINT64_C(10) * USEC_PER_MSEC +
-                                              UINT64_C(240) * USEC_PER_MSEC * n_attempts/64));
+                (void) usleep(random_u64_range(UINT64_C(10) * USEC_PER_MSEC +
+                                               UINT64_C(240) * USEC_PER_MSEC * n_attempts/64));
         }
 
+        if (fstat(loop_with_fd, &st) < 0)
+                return -errno;
+        assert(S_ISBLK(st.st_mode));
+
         d = new(LoopDevice, 1);
         if (!d)
                 return -ENOMEM;
@@ -432,13 +489,21 @@ int loop_device_make(
                 .fd = TAKE_FD(loop_with_fd),
                 .node = TAKE_PTR(loopdev),
                 .nr = nr,
+                .devno = st.st_rdev,
+                .uevent_seqnum_not_before = seqnum,
+                .timestamp_not_before = timestamp,
         };
 
         *ret = d;
-        return 0;
+        return d->fd;
 }
 
-int loop_device_make_by_path(const char *path, int open_flags, uint32_t loop_flags, LoopDevice **ret) {
+int loop_device_make_by_path(
+                const char *path,
+                int open_flags,
+                uint32_t loop_flags,
+                LoopDevice **ret) {
+
         _cleanup_close_ int fd = -1;
         int r;
 
@@ -561,6 +626,9 @@ int loop_device_open(const char *loop_path, int open_flags, LoopDevice **ret) {
                 .nr = nr,
                 .node = TAKE_PTR(p),
                 .relinquished = true, /* It's not ours, don't try to destroy it when this object is freed */
+                .devno = st.st_dev,
+                .uevent_seqnum_not_before = UINT64_MAX,
+                .timestamp_not_before = USEC_INFINITY,
         };
 
         *ret = d;
index 9538daea3116cc48cdf6e58df94e654303657fd9..e06dfebb7c6656ca39b12deb6298c9cab358f70e 100644 (file)
@@ -2,6 +2,7 @@
 #pragma once
 
 #include "macro.h"
+#include "time-util.h"
 
 typedef struct LoopDevice LoopDevice;
 
@@ -10,8 +11,11 @@ typedef struct LoopDevice LoopDevice;
 struct LoopDevice {
         int fd;
         int nr;
+        dev_t devno;
         char *node;
         bool relinquished;
+        uint64_t uevent_seqnum_not_before; /* uevent sequm right before we attached the loopback device, or UINT64_MAX if we don't know */
+        usec_t timestamp_not_before; /* CLOCK_MONOTONIC timestamp taken immediately before attaching the loopback device, or USEC_INFINITY if we don't know */
 };
 
 int loop_device_make(int fd, int open_flags, uint64_t offset, uint64_t size, uint32_t loop_flags, LoopDevice **ret);
index 6d15f9cd09cf7647e0195e73122b14533b745453..d2f989272ddd12563dd5f99ff7ecf592824841e1 100644 (file)
@@ -60,19 +60,14 @@ static int generate_machine_id(const char *root, sd_id128_t *ret) {
                                 return 0;
                         }
 
-                } else if (detect_vm() == VIRTUALIZATION_KVM) {
+                } else if (IN_SET(detect_vm(), VIRTUALIZATION_KVM, VIRTUALIZATION_AMAZON, VIRTUALIZATION_QEMU)) {
 
-                        /* If we are not running in a container, see if we are
-                         * running in qemu/kvm and a machine ID was passed in
-                         * via -uuid on the qemu/kvm command line */
+                        /* If we are not running in a container, see if we are running in a VM that provides
+                         * a system UUID via the SMBIOS/DMI interfaces.  Such environments include QEMU/KVM
+                         * with the -uuid on the qemu command line or the Amazon EC2 Nitro hypervisor. */
 
-                        if (id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, ret) >= 0) {
-                                log_info("Initializing machine ID from KVM UUID.");
-                                return 0;
-                        }
-                        /* on POWER, it's exported here instead */
-                        if (id128_read("/sys/firmware/devicetree/base/vm,uuid", ID128_UUID, ret) >= 0) {
-                                log_info("Initializing machine ID from KVM UUID.");
+                        if (id128_get_product(ret) >= 0) {
+                                log_info("Initializing machine ID from VM UUID.");
                                 return 0;
                         }
                 }
index a2e4958fdcd4a65e45557218aa8d8ed339821e35..4b590be1e03e5975645d51cbf0595941de7bdd60 100644 (file)
@@ -319,6 +319,13 @@ if conf.get('HAVE_LIBIPTC') == 1
         shared_sources += files('firewall-util-iptables.c')
 endif
 
+if conf.get('HAVE_LIBBPF') == 1
+        shared_sources += files('''
+                bpf-link.c
+                bpf-link.h
+        '''.split())
+endif
+
 if conf.get('HAVE_KMOD') == 1
         shared_sources += files('module-util.c')
 endif
@@ -378,6 +385,7 @@ libshared_name = 'systemd-shared-@0@'.format(meson.project_version())
 libshared_deps = [threads,
                   libacl,
                   libblkid,
+                  libbpf,
                   libcap,
                   libcrypt,
                   libgcrypt,
index 587e6369fb89f8b2f08ede3ec20e86d1ee627126..1526f59b0aa028fc1ea8b6e51d7e610a699dbc56 100644 (file)
@@ -20,11 +20,10 @@ int module_load_and_warn(struct kmod_ctx *ctx, const char *module, bool verbose)
                 return log_full_errno(verbose ? LOG_ERR : LOG_DEBUG, r,
                                       "Failed to look up module alias '%s': %m", module);
 
-        if (!modlist) {
-                log_full_errno(verbose ? LOG_ERR : LOG_DEBUG, r,
-                               "Failed to find module '%s'", module);
-                return -ENOENT;
-        }
+        if (!modlist)
+                return log_full_errno(verbose ? LOG_ERR : LOG_DEBUG,
+                                      SYNTHETIC_ERRNO(ENOENT),
+                                      "Failed to find module '%s'", module);
 
         kmod_list_foreach(itr, modlist) {
                 _cleanup_(kmod_module_unrefp) struct kmod_module *mod = NULL;
index 576e4054c2944d2e1179761f19d78655e7b46a14..13f202d7e7dfb241fb2eda925b9d2ecc7d289c1c 100644 (file)
@@ -84,9 +84,8 @@ int umount_recursive(const char *prefix, int flags) {
         int n = 0, r;
         bool again;
 
-        /* Try to umount everything recursively below a
-         * directory. Also, take care of stacked mounts, and keep
-         * unmounting them until they are gone. */
+        /* Try to umount everything recursively below a directory. Also, take care of stacked mounts, and
+         * keep unmounting them until they are gone. */
 
         do {
                 _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
@@ -132,68 +131,6 @@ int umount_recursive(const char *prefix, int flags) {
         return n;
 }
 
-static int get_mount_flags(
-                struct libmnt_table *table,
-                const char *path,
-                unsigned long *ret) {
-
-        _cleanup_close_ int fd = -1;
-        struct libmnt_fs *fs;
-        struct statvfs buf;
-        const char *opts;
-        int r;
-
-        /* Get the mount flags for the mountpoint at "path" from "table". We have a fallback using statvfs()
-         * in place (which provides us with mostly the same info), but it's just a fallback, since using it
-         * means triggering autofs or NFS mounts, which we'd rather avoid needlessly.
-         *
-         * This generally doesn't follow symlinks. */
-
-        fs = mnt_table_find_target(table, path, MNT_ITER_FORWARD);
-        if (!fs) {
-                log_debug("Could not find '%s' in mount table, ignoring.", path);
-                goto fallback;
-        }
-
-        opts = mnt_fs_get_vfs_options(fs);
-        if (!opts) {
-                *ret = 0;
-                return 0;
-        }
-
-        r = mnt_optstr_get_flags(opts, ret, mnt_get_builtin_optmap(MNT_LINUX_MAP));
-        if (r != 0) {
-                log_debug_errno(r, "Could not get flags for '%s', ignoring: %m", path);
-                goto fallback;
-        }
-
-        /* MS_RELATIME is default and trying to set it in an unprivileged container causes EPERM */
-        *ret &= ~MS_RELATIME;
-        return 0;
-
-fallback:
-        fd = open(path, O_PATH|O_CLOEXEC|O_NOFOLLOW);
-        if (fd < 0)
-                return -errno;
-
-        if (fstatvfs(fd, &buf) < 0)
-                return -errno;
-
-        /* The statvfs() flags and the mount flags mostly have the same values, but for some cases do
-         * not. Hence map the flags manually. (Strictly speaking, ST_RELATIME/MS_RELATIME is the most
-         * prominent one that doesn't match, but that's the one we mask away anyway, see above.) */
-
-        *ret =
-                FLAGS_SET(buf.f_flag, ST_RDONLY) * MS_RDONLY |
-                FLAGS_SET(buf.f_flag, ST_NODEV) * MS_NODEV |
-                FLAGS_SET(buf.f_flag, ST_NOEXEC) * MS_NOEXEC |
-                FLAGS_SET(buf.f_flag, ST_NOSUID) * MS_NOSUID |
-                FLAGS_SET(buf.f_flag, ST_NOATIME) * MS_NOATIME |
-                FLAGS_SET(buf.f_flag, ST_NODIRATIME) * MS_NODIRATIME;
-
-        return 0;
-}
-
 /* Use this function only if you do not have direct access to /proc/self/mountinfo but the caller can open it
  * for you. This is the case when /proc is masked or not mounted. Otherwise, use bind_remount_recursive. */
 int bind_remount_recursive_with_mountinfo(
@@ -203,8 +140,8 @@ int bind_remount_recursive_with_mountinfo(
                 char **deny_list,
                 FILE *proc_self_mountinfo) {
 
-        _cleanup_set_free_free_ Set *done = NULL;
-        _cleanup_free_ char *simplified = NULL;
+        _cleanup_set_free_ Set *done = NULL;
+        unsigned n_tries = 0;
         int r;
 
         assert(prefix);
@@ -217,32 +154,21 @@ int bind_remount_recursive_with_mountinfo(
          * access, too. When mounts are stacked on the same mount point we only care for each individual
          * "top-level" mount on each point, as we cannot influence/access the underlying mounts anyway. We do
          * not have any effect on future submounts that might get propagated, they might be writable
-         * etc. This includes future submounts that have been triggered via autofs.
+         * etc. This includes future submounts that have been triggered via autofs. Also note that we can't
+         * operate atomically here. Mounts established while we process the tree might or might not get
+         * noticed and thus might or might not be covered.
          *
          * If the "deny_list" parameter is specified it may contain a list of subtrees to exclude from the
          * remount operation. Note that we'll ignore the deny list for the top-level path. */
 
-        simplified = strdup(prefix);
-        if (!simplified)
-                return -ENOMEM;
-
-        path_simplify(simplified, false);
-
-        done = set_new(&path_hash_ops);
-        if (!done)
-                return -ENOMEM;
-
         for (;;) {
-                _cleanup_set_free_free_ Set *todo = NULL;
                 _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
                 _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
+                _cleanup_hashmap_free_ Hashmap *todo = NULL;
                 bool top_autofs = false;
-                char *x;
-                unsigned long orig_flags;
 
-                todo = set_new(&path_hash_ops);
-                if (!todo)
-                        return -ENOMEM;
+                if (n_tries++ >= 32) /* Let's not retry this loop forever */
+                        return -EBUSY;
 
                 rewind(proc_self_mountinfo);
 
@@ -251,130 +177,159 @@ int bind_remount_recursive_with_mountinfo(
                         return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
                 for (;;) {
+                        _cleanup_free_ char *d = NULL;
+                        const char *path, *type, *opts;
+                        unsigned long flags = 0;
                         struct libmnt_fs *fs;
-                        const char *path, *type;
 
                         r = mnt_table_next_fs(table, iter, &fs);
-                        if (r == 1)
+                        if (r == 1) /* EOF */
                                 break;
                         if (r < 0)
                                 return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
 
                         path = mnt_fs_get_target(fs);
+                        if (!path)
+                                continue;
+
+                        if (!path_startswith(path, prefix))
+                                continue;
+
                         type = mnt_fs_get_fstype(fs);
-                        if (!path || !type)
+                        if (!type)
+                                continue;
+
+                        /* Let's ignore autofs mounts. If they aren't triggered yet, we want to avoid
+                         * triggering them, as we don't make any guarantees for future submounts anyway. If
+                         * they are already triggered, then we will find another entry for this. */
+                        if (streq(type, "autofs")) {
+                                top_autofs = top_autofs || path_equal(path, prefix);
                                 continue;
+                        }
 
-                        if (!path_startswith(path, simplified))
+                        if (set_contains(done, path))
                                 continue;
 
                         /* Ignore this mount if it is deny-listed, but only if it isn't the top-level mount
                          * we shall operate on. */
-                        if (!path_equal(path, simplified)) {
+                        if (!path_equal(path, prefix)) {
                                 bool deny_listed = false;
                                 char **i;
 
                                 STRV_FOREACH(i, deny_list) {
-                                        if (path_equal(*i, simplified))
+                                        if (path_equal(*i, prefix))
                                                 continue;
 
-                                        if (!path_startswith(*i, simplified))
+                                        if (!path_startswith(*i, prefix))
                                                 continue;
 
                                         if (path_startswith(path, *i)) {
                                                 deny_listed = true;
-                                                log_debug("Not remounting %s deny-listed by %s, called for %s",
-                                                          path, *i, simplified);
+                                                log_debug("Not remounting %s deny-listed by %s, called for %s", path, *i, prefix);
                                                 break;
                                         }
                                 }
+
                                 if (deny_listed)
                                         continue;
                         }
 
-                        /* Let's ignore autofs mounts.  If they aren't
-                         * triggered yet, we want to avoid triggering
-                         * them, as we don't make any guarantees for
-                         * future submounts anyway.  If they are
-                         * already triggered, then we will find
-                         * another entry for this. */
-                        if (streq(type, "autofs")) {
-                                top_autofs = top_autofs || path_equal(path, simplified);
-                                continue;
-                        }
-
-                        if (!set_contains(done, path)) {
-                                r = set_put_strdup(&todo, path);
+                        opts = mnt_fs_get_vfs_options(fs);
+                        if (opts) {
+                                r = mnt_optstr_get_flags(opts, &flags, mnt_get_builtin_optmap(MNT_LINUX_MAP));
                                 if (r < 0)
-                                        return r;
+                                        log_debug_errno(r, "Could not get flags for '%s', ignoring: %m", path);
                         }
-                }
 
-                /* If we have no submounts to process anymore and if
-                 * the root is either already done, or an autofs, we
-                 * are done */
-                if (set_isempty(todo) &&
-                    (top_autofs || set_contains(done, simplified)))
-                        return 0;
+                        d = strdup(path);
+                        if (!d)
+                                return -ENOMEM;
 
-                if (!set_contains(done, simplified) &&
-                    !set_contains(todo, simplified)) {
-                        /* The prefix directory itself is not yet a mount, make it one. */
-                        r = mount_nofollow(simplified, simplified, NULL, MS_BIND|MS_REC, NULL);
+                        r = hashmap_ensure_put(&todo, &path_hash_ops_free, d, ULONG_TO_PTR(flags));
+                        if (r == -EEXIST)
+                                continue;
                         if (r < 0)
                                 return r;
+                        if (r > 0)
+                                TAKE_PTR(d);
+                }
 
-                        orig_flags = 0;
-                        (void) get_mount_flags(table, simplified, &orig_flags);
+                /* Check if the top-level directory was among what we have seen so far. For that check both
+                 * 'done' and 'todo'. Also check 'top_autofs' because if the top-level dir is an autofs we'll
+                 * not include it in either set but will set this bool. */
+                if (!set_contains(done, prefix) &&
+                    !(top_autofs || hashmap_contains(todo, prefix))) {
 
-                        r = mount_nofollow(NULL, simplified, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL);
+                        /* The prefix directory itself is not yet a mount, make it one. */
+                        r = mount_nofollow(prefix, prefix, NULL, MS_BIND|MS_REC, NULL);
                         if (r < 0)
                                 return r;
 
-                        log_debug("Made top-level directory %s a mount point.", prefix);
-
-                        r = set_put_strdup(&done, simplified);
-                        if (r < 0)
-                                return r;
+                        /* Immediately rescan, so that we pick up the new mount's flags */
+                        continue;
                 }
 
-                while ((x = set_steal_first(todo))) {
+                /* If we have no submounts to process anymore, we are done */
+                if (hashmap_isempty(todo))
+                        return 0;
+
+                for (;;) {
+                        unsigned long flags;
+                        char *x = NULL;
+
+                        /* Take the first mount from our list of mounts to still process */
+                        flags = PTR_TO_ULONG(hashmap_steal_first_key_and_value(todo, (void**) &x));
+                        if (!x)
+                                break;
 
-                        r = set_consume(done, x);
+                        r = set_ensure_consume(&done, &path_hash_ops_free, x);
                         if (IN_SET(r, 0, -EEXIST))
-                                continue;
+                                continue; /* Already done */
                         if (r < 0)
                                 return r;
 
-                        /* Deal with mount points that are obstructed by a later mount */
-                        r = path_is_mount_point(x, NULL, 0);
-                        if (IN_SET(r, 0, -ENOENT))
-                                continue;
+                        /* Now, remount this with the new flags set, but exclude MS_RELATIME from it. (It's
+                         * the default anyway, thus redundant, and in userns we'll get an error if we try to
+                         * explicitly enable it) */
+                        r = mount_nofollow(NULL, x, NULL, ((flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags) & ~MS_RELATIME, NULL);
                         if (r < 0) {
-                                if (!ERRNO_IS_PRIVILEGE(r))
+                                int q;
+
+                                /* OK, so the remount of this entry failed. We'll ultimately ignore this in
+                                 * almost all cases (there are simply so many reasons why this can fail,
+                                 * think autofs, NFS, FUSE, …), but let's generate useful debug messages at
+                                 * the very least. */
+
+                                q = path_is_mount_point(x, NULL, 0);
+                                if (IN_SET(q, 0, -ENOENT)) {
+                                        /* Hmm, whaaaa? The mount point is not actually a mount point? Then
+                                         * it is either obstructed by a later mount or somebody has been
+                                         * racing against us and removed it. Either way the mount point
+                                         * doesn't matter to us, let's ignore it hence. */
+                                        log_debug_errno(r, "Mount point '%s' to remount is not a mount point anymore, ignoring remount failure: %m", x);
+                                        continue;
+                                }
+                                if (q < 0) /* Any other error on this? Just log and continue */
+                                        log_debug_errno(q, "Failed to determine whether '%s' is a mount point or not, ignoring: %m", x);
+
+                                if (((flags ^ new_flags) & flags_mask & ~MS_RELATIME) == 0) { /* ignore MS_RELATIME while comparing */
+                                        log_debug_errno(r, "Couldn't remount '%s', but the flags already match what we want, hence ignoring: %m", x);
+                                        continue;
+                                }
+
+                                /* Make this fatal if this is the top-level mount */
+                                if (path_equal(x, prefix))
                                         return r;
 
-                                /* Even if root user invoke this, submounts under private FUSE or NFS mount points
-                                 * may not be acceessed. E.g.,
-                                 *
-                                 * $ bindfs --no-allow-other ~/mnt/mnt ~/mnt/mnt
-                                 * $ bindfs --no-allow-other ~/mnt ~/mnt
-                                 *
-                                 * Then, root user cannot access the mount point ~/mnt/mnt.
-                                 * In such cases, the submounts are ignored, as we have no way to manage them. */
-                                log_debug_errno(r, "Failed to determine '%s' is mount point or not, ignoring: %m", x);
+                                /* If this is not the top-level mount, then handle this gracefully: log but
+                                 * otherwise ignore. With NFS, FUSE, autofs there are just too many reasons
+                                 * this might fail without a chance for us to do anything about it, let's
+                                 * hence be strict on the top-level mount and lenient on the inner ones. */
+                                log_debug_errno(r, "Couldn't remount submount '%s' for unexpected reason, ignoring: %m", x);
                                 continue;
                         }
 
-                        /* Try to reuse the original flag set */
-                        orig_flags = 0;
-                        (void) get_mount_flags(table, x, &orig_flags);
-
-                        r = mount_nofollow(NULL, x, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL);
-                        if (r < 0)
-                                return r;
-
-                        log_debug("Remounted %s read-only.", x);
+                        log_debug("Remounted %s.", x);
                 }
         }
 }
@@ -402,7 +357,9 @@ int bind_remount_one_with_mountinfo(
                 FILE *proc_self_mountinfo) {
 
         _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
-        unsigned long orig_flags = 0;
+        unsigned long flags = 0;
+        struct libmnt_fs *fs;
+        const char *opts;
         int r;
 
         assert(path);
@@ -418,12 +375,32 @@ int bind_remount_one_with_mountinfo(
         if (r < 0)
                 return r;
 
-        /* Try to reuse the original flag set */
-        (void) get_mount_flags(table, path, &orig_flags);
+        fs = mnt_table_find_target(table, path, MNT_ITER_FORWARD);
+        if (!fs) {
+                if (laccess(path, F_OK) < 0) /* Hmm, it's not in the mount table, but does it exist at all? */
+                        return -errno;
+
+                return -EINVAL; /* Not a mount point we recognize */
+        }
 
-        r = mount_nofollow(NULL, path, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL);
-        if (r < 0)
-                return r;
+        opts = mnt_fs_get_vfs_options(fs);
+        if (opts) {
+                r = mnt_optstr_get_flags(opts, &flags, mnt_get_builtin_optmap(MNT_LINUX_MAP));
+                if (r < 0)
+                        log_debug_errno(r, "Could not get flags for '%s', ignoring: %m", path);
+        }
+
+        r = mount_nofollow(NULL, path, NULL, ((flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags) & ~MS_RELATIME, NULL);
+        if (r < 0) {
+                if (((flags ^ new_flags) & flags_mask & ~MS_RELATIME) != 0) /* Ignore MS_RELATIME again,
+                                                                             * since kernel adds it in
+                                                                             * everywhere, because it's the
+                                                                             * default. */
+                        return r;
+
+                /* Let's handle redundant remounts gracefully */
+                log_debug_errno(r, "Failed to remount '%s' but flags already match what we want, ignoring: %m", path);
+        }
 
         return 0;
 }
index 718389768605233971462af33ab8c6c480294fb7..6469181d1cf46a37ca1124f48ba6a6175e55f039 100644 (file)
@@ -93,8 +93,10 @@ int mode_to_inaccessible_node(const char *runtime_dir, mode_t mode, char **dest)
 /* Useful for usage with _cleanup_(), unmounts, removes a directory and frees the pointer */
 static inline char* umount_and_rmdir_and_free(char *p) {
         PROTECT_ERRNO;
-        (void) umount_recursive(p, 0);
-        (void) rmdir(p);
+        if (p) {
+                (void) umount_recursive(p, 0);
+                (void) rmdir(p);
+        }
         return mfree(p);
 }
 DEFINE_TRIVIAL_CLEANUP_FUNC(char*, umount_and_rmdir_and_free);
index 174bb2a7ea0a866bceb6d4ba57fcc8ac27b6fbfd..2479a5672c5ed1bcb0965165452d5b7bc7c19f04 100644 (file)
@@ -147,7 +147,7 @@ bool net_match_config(
                 const char *ssid,
                 const struct ether_addr *bssid) {
 
-        _cleanup_free_ char *iftype_str;
+        _cleanup_free_ char *iftype_str = NULL;
         const char *path = NULL;
 
         assert(match);
index df520ab89ed31ec015026eb4f4fcf73da08d9736..82c6625e56a6c4dd46ea9182fcea473c6de467d1 100644 (file)
@@ -13,6 +13,7 @@ static const NamingScheme naming_schemes[] = {
         { "v243", NAMING_V243 },
         { "v245", NAMING_V245 },
         { "v247", NAMING_V247 },
+        { "v249", NAMING_V249 },
         /* … add more schemes here, as the logic to name devices is updated … */
 };
 
index 28cd4e41f23c0e3aef1f82b301847bec5e5a5211..c0f94d0407cd04f8b121d7ea5c3f4070a4b72632 100644 (file)
@@ -32,6 +32,8 @@ typedef enum NamingSchemeFlags {
         NAMING_LABEL_NOPREFIX      = 1 << 7, /* Don't prepend ID_NET_LABEL_ONBOARD with interface type prefix */
         NAMING_NSPAWN_LONG_HASH    = 1 << 8, /* Shorten nspawn interfaces by including 24bit hash, instead of simple truncation  */
         NAMING_BRIDGE_NO_SLOT      = 1 << 9, /* Don't use PCI hotplug slot information if the corresponding device is a PCI bridge */
+        NAMING_SLOT_FUNCTION_ID    = 1 << 10, /* Use function_id if present to identify PCI hotplug slots */
+        NAMING_16BIT_INDEX         = 1 << 11, /* Allow full 16-bit for the onboard index */
 
         /* And now the masks that combine the features above */
         NAMING_V238 = 0,
@@ -41,6 +43,7 @@ typedef enum NamingSchemeFlags {
         NAMING_V243 = NAMING_V241 | NAMING_NETDEVSIM | NAMING_LABEL_NOPREFIX,
         NAMING_V245 = NAMING_V243 | NAMING_NSPAWN_LONG_HASH,
         NAMING_V247 = NAMING_V245 | NAMING_BRIDGE_NO_SLOT,
+        NAMING_V249 = NAMING_V247 | NAMING_SLOT_FUNCTION_ID | NAMING_16BIT_INDEX,
 
         _NAMING_SCHEME_FLAGS_INVALID = -EINVAL,
 } NamingSchemeFlags;
index 4ea72a8b2b0e441e6712bbedc784c0a072a71c6d..bb47ae5e873844b4137cae8b2844e116ccf286f3 100644 (file)
@@ -46,7 +46,7 @@ int rsa_pkey_to_suitable_key_size(
                 size_t *ret_suitable_key_size) {
 
         size_t suitable_key_size;
-        RSA *rsa;
+        const RSA *rsa;
         int bits;
 
         assert_se(pkey);
index 54433c79b851f4863d649bdc3472645b95089ed6..4ddfce39e6b01355200c5cdb617670046834924b 100644 (file)
@@ -29,9 +29,6 @@ struct DosFileHeader {
         le32_t ExeHeader;
 } _packed_;
 
-#define PE_HEADER_MACHINE_I386 0x014cU
-#define PE_HEADER_MACHINE_X64  0x8664U
-
 struct PeFileHeader {
         le16_t Machine;
         le16_t NumberOfSections;
index 27c209cdf8ab6f9afe86f9a8b311da9bdaf5a733..aff45ed868c426d1c7f071ea9f22cabba7f5647c 100644 (file)
@@ -31,7 +31,7 @@ bool pkcs11_uri_valid(const char *uri) {
         if (isempty(p))
                 return false;
 
-        if (!in_charset(p, ALPHANUMERICAL "-_?;&%="))
+        if (!in_charset(p, ALPHANUMERICAL ".~/-_?;&%="))
                 return false;
 
         return true;
@@ -181,7 +181,8 @@ int pkcs11_token_login(
                 const CK_TOKEN_INFO *token_info,
                 const char *friendly_name,
                 const char *icon_name,
-                const char *keyname,
+                const char *key_name,
+                const char *credential_name,
                 usec_t until,
                 char **ret_used_pin) {
 
@@ -269,7 +270,7 @@ int pkcs11_token_login(
                                 return log_oom();
 
                         /* We never cache PINs, simply because it's fatal if we use wrong PINs, since usually there are only 3 tries */
-                        r = ask_password_auto(text, icon_name, id, keyname, until, 0, &passwords);
+                        r = ask_password_auto(text, icon_name, id, key_name, credential_name, until, 0, &passwords);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to query PIN for security token '%s': %m", token_label);
                 }
@@ -959,7 +960,7 @@ static int pkcs11_acquire_certificate_callback(
 
         /* Called for every token matching our URI */
 
-        r = pkcs11_token_login(m, session, slot_id, token_info, data->askpw_friendly_name, data->askpw_icon_name, "pkcs11-pin", UINT64_MAX, &pin_used);
+        r = pkcs11_token_login(m, session, slot_id, token_info, data->askpw_friendly_name, data->askpw_icon_name, "pkcs11-pin", "pkcs11-pin", UINT64_MAX, &pin_used);
         if (r < 0)
                 return r;
 
index f32ab304299e458a470825ea5a22639217458cfa..c2c852f0ebe356b8fe965bdf2f3141d80325faba 100644 (file)
@@ -30,7 +30,7 @@ char *pkcs11_token_label(const CK_TOKEN_INFO *token_info);
 char *pkcs11_token_manufacturer_id(const CK_TOKEN_INFO *token_info);
 char *pkcs11_token_model(const CK_TOKEN_INFO *token_info);
 
-int pkcs11_token_login(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, const char *icon_name, const char *keyname, usec_t until, char **ret_used_pin);
+int pkcs11_token_login(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, const char *icon_name, const char *key_name, const char *credential_name, usec_t until, char **ret_used_pin);
 
 int pkcs11_token_find_x509_certificate(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, P11KitUri *search_uri, CK_OBJECT_HANDLE *ret_object);
 #if HAVE_OPENSSL
index 0f02f327601171d77aa690ca01063984aff4a668..137ba77b3a6ea700396cce26608e02f230ee7734 100644 (file)
@@ -280,7 +280,7 @@ static int guess_type(const char **name, char ***prefixes, bool *is_collection,
 int conf_files_cat(const char *root, const char *name) {
         _cleanup_strv_free_ char **dirs = NULL, **files = NULL;
         _cleanup_free_ char *path = NULL;
-        char **prefixes, **prefix;
+        char **prefix, **prefixes = NULL; /* explicit initialization to appease gcc */
         bool is_collection;
         const char *extension;
         char **t;
@@ -289,6 +289,8 @@ int conf_files_cat(const char *root, const char *name) {
         r = guess_type(&name, &prefixes, &is_collection, &extension);
         if (r < 0)
                 return r;
+        assert(prefixes);
+        assert(extension);
 
         STRV_FOREACH(prefix, prefixes) {
                 assert(endswith(*prefix, "/"));
index 6b9ff8531bbe171a68a0cfa6b0c71fb55aa8aacb..79ac640672563291d9f9f644afdb7763c3f25b36 100644 (file)
@@ -110,7 +110,7 @@ int print_qrcode(FILE *out, const char *header, const char *string) {
         if (r < 0)
                 return r;
 
-        qr = sym_QRcode_encodeString(string, 0, QR_ECLEVEL_L, QR_MODE_8, 0);
+        qr = sym_QRcode_encodeString(string, 0, QR_ECLEVEL_L, QR_MODE_8, 1);
         if (!qr)
                 return -ENOMEM;
 
index cea51482deec43476c37f4fc0b913fff59dd9dfa..53280cf40a2e1df81840d9961daaf245e581315b 100644 (file)
@@ -34,7 +34,7 @@
 #include "time-util.h"
 
 int parse_sleep_config(SleepConfig **ret_sleep_config) {
-        _cleanup_(free_sleep_configp) SleepConfig *sc;
+        _cleanup_(free_sleep_configp) SleepConfig *sc = NULL;
         int allow_suspend = -1, allow_hibernate = -1,
             allow_s2h = -1, allow_hybrid_sleep = -1;
 
@@ -324,7 +324,7 @@ static bool location_is_resume_device(const HibernateLocation *location, dev_t s
 int find_hibernate_location(HibernateLocation **ret_hibernate_location) {
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_(hibernate_location_freep) HibernateLocation *hibernate_location = NULL;
-        dev_t sys_resume;
+        dev_t sys_resume = 0; /* Unnecessary initialization to appease gcc */
         uint64_t sys_offset = 0;
         bool resume_match = false;
         int r;
index 24e8781805a878c8c0a62810ff57bf86c578d411..6edf4a215ca7df41a2e15ba988b0c36101fb906d 100644 (file)
@@ -234,6 +234,14 @@ int specifier_os_variant_id(char specifier, const void *data, const void *userda
         return specifier_os_release_common("VARIANT_ID", ret);
 }
 
+int specifier_os_image_id(char specifier, const void *data, const void *userdata, char **ret) {
+        return specifier_os_release_common("IMAGE_ID", ret);
+}
+
+int specifier_os_image_version(char specifier, const void *data, const void *userdata, char **ret) {
+        return specifier_os_release_common("IMAGE_VERSION", ret);
+}
+
 int specifier_group_name(char specifier, const void *data, const void *userdata, char **ret) {
         char *t;
 
index 1323b41d98567c52bb542c40355779c1c5c7d1c2..6735a7a363a656b6ea23862b8e45e3c8456a3c32 100644 (file)
@@ -25,6 +25,8 @@ int specifier_os_id(char specifier, const void *data, const void *userdata, char
 int specifier_os_version_id(char specifier, const void *data, const void *userdata, char **ret);
 int specifier_os_build_id(char specifier, const void *data, const void *userdata, char **ret);
 int specifier_os_variant_id(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_os_image_id(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_os_image_version(char specifier, const void *data, const void *userdata, char **ret);
 
 int specifier_group_name(char specifier, const void *data, const void *userdata, char **ret);
 int specifier_group_id(char specifier, const void *data, const void *userdata, char **ret);
@@ -41,11 +43,13 @@ int specifier_var_tmp_dir(char specifier, const void *data, const void *userdata
  *
  * COMMON_SYSTEM_SPECIFIERS:
  * %a: the native userspace architecture
+ * %A: the OS image version, according to /etc/os-release
  * %b: the boot ID of the running system
  * %B: the OS build ID, according to /etc/os-release
  * %H: the hostname of the running system
  * %l: the short hostname of the running system
  * %m: the machine ID of the running system
+ * %M: the OS image ID, according to /etc/os-release
  * %o: the OS ID according to /etc/os-release
  * %v: the kernel version
  * %w: the OS version ID, according to /etc/os-release
@@ -64,16 +68,19 @@ int specifier_var_tmp_dir(char specifier, const void *data, const void *userdata
 
 #define COMMON_SYSTEM_SPECIFIERS                  \
         { 'a', specifier_architecture,    NULL }, \
+        { 'A', specifier_os_image_version,NULL }, \
         { 'b', specifier_boot_id,         NULL }, \
         { 'B', specifier_os_build_id,     NULL }, \
         { 'H', specifier_host_name,       NULL }, \
         { 'l', specifier_short_host_name, NULL }, \
         { 'm', specifier_machine_id,      NULL }, \
+        { 'M', specifier_os_image_id,     NULL }, \
         { 'o', specifier_os_id,           NULL }, \
         { 'v', specifier_kernel_release,  NULL }, \
         { 'w', specifier_os_version_id,   NULL }, \
         { 'W', specifier_os_variant_id,   NULL }
 
+
 #define COMMON_CREDS_SPECIFIERS                   \
         { 'g', specifier_group_name,      NULL }, \
         { 'G', specifier_group_id,        NULL }, \
index 8a0f45c2db764f2ff5415cc9a4b572c6de9918b8..4d17f3c96a2238ea92bc93e24c0ae9057e34e44f 100644 (file)
@@ -686,6 +686,10 @@ int tpm2_unseal(
 
         assert(pcr_mask < (UINT32_C(1) << TPM2_PCRS_MAX)); /* Support 24 PCR banks */
 
+        r = dlopen_tpm2();
+        if (r < 0)
+                return log_error_errno(r, "TPM2 support is not installed.");
+
         /* So here's what we do here: We connect to the TPM2 chip. As we do when sealing we generate a
          * "primary" key on the TPM2 chip, with the same parameters as well as a PCR-bound policy
          * session. Given we pass the same parameters, this will result in the same "primary" key, and same
index 0d471a2f942f5ca3eac204f3e93f3fdaf4e2dcd9..e4a04123c0e7f3e6ef699f7ea3da9eb262e1c874 100644 (file)
@@ -27,6 +27,7 @@ typedef enum LookupWhat {
 
 struct UserDBIterator {
         LookupWhat what;
+        UserDBFlags flags;
         Set *links;
         bool nss_covered:1;
         bool nss_iterating:1;
@@ -92,7 +93,7 @@ UserDBIterator* userdb_iterator_free(UserDBIterator *iterator) {
         return mfree(iterator);
 }
 
-static UserDBIterator* userdb_iterator_new(LookupWhat what) {
+static UserDBIterator* userdb_iterator_new(LookupWhat what, UserDBFlags flags) {
         UserDBIterator *i;
 
         assert(what >= 0);
@@ -104,6 +105,7 @@ static UserDBIterator* userdb_iterator_new(LookupWhat what) {
 
         *i = (UserDBIterator) {
                 .what = what,
+                .flags = flags,
         };
 
         return i;
@@ -608,7 +610,7 @@ int userdb_by_name(const char *name, UserDBFlags flags, UserRecord **ret) {
         if (r < 0)
                 return r;
 
-        iterator = userdb_iterator_new(LOOKUP_USER);
+        iterator = userdb_iterator_new(LOOKUP_USER, flags);
         if (!iterator)
                 return -ENOMEM;
 
@@ -655,7 +657,7 @@ int userdb_by_uid(uid_t uid, UserDBFlags flags, UserRecord **ret) {
         if (r < 0)
                 return r;
 
-        iterator = userdb_iterator_new(LOOKUP_USER);
+        iterator = userdb_iterator_new(LOOKUP_USER, flags);
         if (!iterator)
                 return -ENOMEM;
 
@@ -693,7 +695,7 @@ int userdb_all(UserDBFlags flags, UserDBIterator **ret) {
 
         assert(ret);
 
-        iterator = userdb_iterator_new(LOOKUP_USER);
+        iterator = userdb_iterator_new(LOOKUP_USER, flags);
         if (!iterator)
                 return -ENOMEM;
 
@@ -738,10 +740,15 @@ int userdb_iterator_get(UserDBIterator *iterator, UserRecord **ret) {
                         if (pw->pw_uid == UID_NOBODY)
                                 iterator->synthesize_nobody = false;
 
-                        r = nss_spwd_for_passwd(pw, &spwd, &buffer);
-                        if (r < 0) {
-                                log_debug_errno(r, "Failed to acquire shadow entry for user %s, ignoring: %m", pw->pw_name);
-                                incomplete = ERRNO_IS_PRIVILEGE(r);
+                        if (!FLAGS_SET(iterator->flags, USERDB_AVOID_SHADOW)) {
+                                r = nss_spwd_for_passwd(pw, &spwd, &buffer);
+                                if (r < 0) {
+                                        log_debug_errno(r, "Failed to acquire shadow entry for user %s, ignoring: %m", pw->pw_name);
+                                        incomplete = ERRNO_IS_PRIVILEGE(r);
+                                }
+                        } else {
+                                r = -EUCLEAN;
+                                incomplete = true;
                         }
 
                         r = nss_passwd_to_user_record(pw, r >= 0 ? &spwd : NULL, ret);
@@ -750,6 +757,8 @@ int userdb_iterator_get(UserDBIterator *iterator, UserRecord **ret) {
 
                         if (ret)
                                 (*ret)->incomplete = incomplete;
+
+                        iterator->n_found++;
                         return r;
                 }
 
@@ -774,11 +783,11 @@ int userdb_iterator_get(UserDBIterator *iterator, UserRecord **ret) {
                         iterator->n_found++;
                         return synthetic_nobody_user_build(ret);
                 }
-        }
 
-        /* if we found at least one entry, then ignore errors and indicate that we reached the end */
-        if (r < 0 && iterator->n_found > 0)
-                return -ESRCH;
+                /* if we found at least one entry, then ignore errors and indicate that we reached the end */
+                if (iterator->n_found > 0)
+                        return -ESRCH;
+        }
 
         return r;
 }
@@ -812,7 +821,7 @@ int groupdb_by_name(const char *name, UserDBFlags flags, GroupRecord **ret) {
         if (r < 0)
                 return r;
 
-        iterator = userdb_iterator_new(LOOKUP_GROUP);
+        iterator = userdb_iterator_new(LOOKUP_GROUP, flags);
         if (!iterator)
                 return -ENOMEM;
 
@@ -856,7 +865,7 @@ int groupdb_by_gid(gid_t gid, UserDBFlags flags, GroupRecord **ret) {
         if (r < 0)
                 return r;
 
-        iterator = userdb_iterator_new(LOOKUP_GROUP);
+        iterator = userdb_iterator_new(LOOKUP_GROUP, flags);
         if (!iterator)
                 return -ENOMEM;
 
@@ -893,7 +902,7 @@ int groupdb_all(UserDBFlags flags, UserDBIterator **ret) {
 
         assert(ret);
 
-        iterator = userdb_iterator_new(LOOKUP_GROUP);
+        iterator = userdb_iterator_new(LOOKUP_GROUP, flags);
         if (!iterator)
                 return -ENOMEM;
 
@@ -908,8 +917,8 @@ int groupdb_all(UserDBFlags flags, UserDBIterator **ret) {
 
                 setgrent();
                 iterator->nss_iterating = true;
-        } if (r < 0)
-                  return r;
+        } else if (r < 0)
+                return r;
 
         *ret = TAKE_PTR(iterator);
         return 0;
@@ -936,10 +945,15 @@ int groupdb_iterator_get(UserDBIterator *iterator, GroupRecord **ret) {
                         if (gr->gr_gid == GID_NOBODY)
                                 iterator->synthesize_nobody = false;
 
-                        r = nss_sgrp_for_group(gr, &sgrp, &buffer);
-                        if (r < 0) {
-                                log_debug_errno(r, "Failed to acquire shadow entry for group %s, ignoring: %m", gr->gr_name);
-                                incomplete = ERRNO_IS_PRIVILEGE(r);
+                        if (!FLAGS_SET(iterator->flags, USERDB_AVOID_SHADOW)) {
+                                r = nss_sgrp_for_group(gr, &sgrp, &buffer);
+                                if (r < 0) {
+                                        log_debug_errno(r, "Failed to acquire shadow entry for group %s, ignoring: %m", gr->gr_name);
+                                        incomplete = ERRNO_IS_PRIVILEGE(r);
+                                }
+                        } else {
+                                r = -EUCLEAN;
+                                incomplete = true;
                         }
 
                         r = nss_group_to_group_record(gr, r >= 0 ? &sgrp : NULL, ret);
@@ -948,6 +962,8 @@ int groupdb_iterator_get(UserDBIterator *iterator, GroupRecord **ret) {
 
                         if (ret)
                                 (*ret)->incomplete = incomplete;
+
+                        iterator->n_found++;
                         return r;
                 }
 
@@ -971,11 +987,11 @@ int groupdb_iterator_get(UserDBIterator *iterator, GroupRecord **ret) {
                         iterator->n_found++;
                         return synthetic_nobody_group_build(ret);
                 }
-        }
 
-        /* if we found at least one entry, then ignore errors and indicate that we reached the end */
-        if (r < 0 && iterator->n_found > 0)
-                return -ESRCH;
+                /* if we found at least one entry, then ignore errors and indicate that we reached the end */
+                if (iterator->n_found > 0)
+                        return -ESRCH;
+        }
 
         return r;
 }
@@ -995,7 +1011,7 @@ int membershipdb_by_user(const char *name, UserDBFlags flags, UserDBIterator **r
         if (r < 0)
                 return r;
 
-        iterator = userdb_iterator_new(LOOKUP_MEMBERSHIP);
+        iterator = userdb_iterator_new(LOOKUP_MEMBERSHIP, flags);
         if (!iterator)
                 return -ENOMEM;
 
@@ -1038,7 +1054,7 @@ int membershipdb_by_group(const char *name, UserDBFlags flags, UserDBIterator **
         if (r < 0)
                 return r;
 
-        iterator = userdb_iterator_new(LOOKUP_MEMBERSHIP);
+        iterator = userdb_iterator_new(LOOKUP_MEMBERSHIP, flags);
         if (!iterator)
                 return -ENOMEM;
 
@@ -1079,7 +1095,7 @@ int membershipdb_all(UserDBFlags flags, UserDBIterator **ret) {
 
         assert(ret);
 
-        iterator = userdb_iterator_new(LOOKUP_MEMBERSHIP);
+        iterator = userdb_iterator_new(LOOKUP_MEMBERSHIP, flags);
         if (!iterator)
                 return -ENOMEM;
 
@@ -1113,7 +1129,7 @@ int membershipdb_iterator_get(
         assert(iterator);
 
         for (;;) {
-                /* If we are iteratring through NSS acquire a new group entry if we haven't acquired one yet. */
+                /* If we are iterating through NSS acquire a new group entry if we haven't acquired one yet. */
                 if (!iterator->members_of_group) {
                         struct group *g;
 
index 6ed72075ba5beda6ac98bb2dbcaad0f96c19fcd4..a271082ac33a9dca7c05e37c37919e2bda9839ac 100644 (file)
@@ -448,13 +448,16 @@ static int varlink_write(Varlink *v) {
         assert(v->fd >= 0);
 
         /* We generally prefer recv()/send() (mostly because of MSG_NOSIGNAL) but also want to be compatible
-         * with non-socket IO, hence fall back automatically */
-        if (!v->prefer_read_write) {
+         * with non-socket IO, hence fall back automatically.
+         *
+         * Use a local variable to help gcc figure out that we set 'n' in all cases. */
+        bool prefer_write = v->prefer_read_write;
+        if (!prefer_write) {
                 n = send(v->fd, v->output_buffer + v->output_buffer_index, v->output_buffer_size, MSG_DONTWAIT|MSG_NOSIGNAL);
                 if (n < 0 && errno == ENOTSOCK)
-                        v->prefer_read_write = true;
+                        prefer_write = v->prefer_read_write = true;
         }
-        if (v->prefer_read_write)
+        if (prefer_write)
                 n = write(v->fd, v->output_buffer + v->output_buffer_index, v->output_buffer_size);
         if (n < 0) {
                 if (errno == EAGAIN)
@@ -531,12 +534,13 @@ static int varlink_read(Varlink *v) {
 
         rs = v->input_buffer_allocated - (v->input_buffer_index + v->input_buffer_size);
 
-        if (!v->prefer_read_write) {
+        bool prefer_read = v->prefer_read_write;
+        if (!prefer_read) {
                 n = recv(v->fd, v->input_buffer + v->input_buffer_index + v->input_buffer_size, rs, MSG_DONTWAIT);
                 if (n < 0 && errno == ENOTSOCK)
-                        v->prefer_read_write = true;
+                        prefer_read = v->prefer_read_write = true;
         }
-        if (v->prefer_read_write)
+        if (prefer_read)
                 n = read(v->fd, v->input_buffer + v->input_buffer_index + v->input_buffer_size, rs);
         if (n < 0) {
                 if (errno == EAGAIN)
index 35940ad02ee62f3adc9aba43716d1338e1f2d6f2..b05e1aa0df184c07ef375120b176d98568b03710 100644 (file)
@@ -30,7 +30,7 @@ int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftyp
         if (r < 0)
                 return log_debug_errno(r, "Failed to request information about wifi interface %d: %m", ifindex);
         if (!reply) {
-                log_debug_errno(r, "No reply received to request for information about wifi interface %d, ignoring.", ifindex);
+                log_debug("No reply received to request for information about wifi interface %d, ignoring.", ifindex);
                 goto nodata;
         }
 
@@ -98,7 +98,7 @@ int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
         if (r < 0)
                 return log_debug_errno(r, "Failed to request information about wifi station: %m");
         if (!reply) {
-                log_debug_errno(r, "No reply received to request for information about wifi station, ignoring.");
+                log_debug("No reply received to request for information about wifi station, ignoring.");
                 goto nodata;
         }
 
index d2b162994c9fc9e605fb65cc2364851ee4c128d1..29b24906a6fb52452255b78dcd33c771f929fa00 100644 (file)
@@ -322,6 +322,9 @@ int main(int argc, char *argv[]) {
         log_set_prohibit_ipc(true);
         log_parse_environment();
 
+        if (getpid_cached() == 1)
+                log_set_always_reopen_console(true);
+
         r = parse_argv(argc, argv);
         if (r < 0)
                 goto error;
@@ -556,8 +559,10 @@ int main(int argc, char *argv[]) {
                 sync_with_progress();
 
         if (streq(arg_verb, "exit")) {
-                if (in_container)
+                if (in_container) {
+                        log_info("Exiting container.");
                         return arg_exit_code;
+                }
 
                 cmd = RB_POWER_OFF; /* We cannot exit() on the host, fallback on another method. */
         }
index 262d4cea66a290aa71e49419113d78b786c42c36..8aeaa1a5434514befd34a760528baae64abca3a8 100644 (file)
@@ -163,10 +163,10 @@ static int lock_all_homes(void) {
                 if (!bus_error_is_unknown_service(&error))
                         return log_error_errno(r, "Failed to lock home directories: %s", bus_error_message(&error, r));
 
-                return log_debug("systemd-homed is not running, locking of home directories skipped.");
-        }
-
-        return log_debug("Successfully requested locking of all home directories.");
+                log_debug("systemd-homed is not running, locking of home directories skipped.");
+        } else
+                log_debug("Successfully requested locking of all home directories.");
+        return 0;
 }
 
 static int execute(char **modes, char **states, const char *action) {
index 7c04072d42d2f8f66db968fa153f973b6e767f8d..174f5ea3e8b0b01c8d013aa4f508fd895c0c4a45 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Entries in this file show the compile time defaults. Local configuration
 # should be created by either modifying this file, or by creating "drop-ins" in
-# the system.conf.d/ subdirectory. The latter is generally recommended.
+# the sleep.conf.d/ subdirectory. The latter is generally recommended.
 # Defaults can be restored by simply deleting this file and all drop-ins.
 #
 # See systemd-sleep.conf(5) for details.
index 217bd97ea5e4049acab607b1104b9a4b7ab12d66..b45f7912cbedf90442d818e3e0bb5b15da4a18cb 100644 (file)
@@ -10,7 +10,6 @@
 #include "sd-daemon.h"
 
 #include "alloc-util.h"
-#include "build.h"
 #include "bus-internal.h"
 #include "bus-util.h"
 #include "errno-util.h"
@@ -18,6 +17,7 @@
 #include "log.h"
 #include "main-func.h"
 #include "util.h"
+#include "version.h"
 
 #define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
 
index 15b68b7d2ef9c72d54b547d636a354d87ccd947e..458a91be29c8e21c901c068dd4e0ff0a08c30544 100644 (file)
@@ -182,12 +182,13 @@ static int apply_all(OrderedHashmap *sysctl_options) {
 
 static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ignore_enoent) {
         _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_free_ char *pp = NULL;
         unsigned c = 0;
         int r;
 
         assert(path);
 
-        r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("sysctl.d"), &f);
+        r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("sysctl.d"), &f, &pp);
         if (r < 0) {
                 if (ignore_enoent && r == -ENOENT)
                         return 0;
@@ -195,7 +196,7 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig
                 return log_error_errno(r, "Failed to open file '%s', ignoring: %m", path);
         }
 
-        log_debug("Parsing %s", path);
+        log_debug("Parsing %s", pp);
         for (;;) {
                 _cleanup_(option_freep) Option *new_option = NULL;
                 _cleanup_free_ char *l = NULL;
@@ -208,7 +209,7 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig
                 if (k == 0)
                         break;
                 if (k < 0)
-                        return log_error_errno(k, "Failed to read file '%s', ignoring: %m", path);
+                        return log_error_errno(k, "Failed to read file '%s', ignoring: %m", pp);
 
                 c++;
 
@@ -235,7 +236,7 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig
                                 /* We have a "negative match" option. Let's continue with value==NULL. */
                                 p++;
                         else {
-                                log_syntax(NULL, LOG_WARNING, path, c, 0,
+                                log_syntax(NULL, LOG_WARNING, pp, c, 0,
                                            "Line is not an assignment, ignoring: %s", p);
                                 if (r == 0)
                                         r = -EINVAL;
@@ -261,7 +262,7 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig
                                 continue;
                         }
 
-                        log_debug("Overwriting earlier assignment of %s at '%s:%u'.", p, path, c);
+                        log_debug("Overwriting earlier assignment of %s at '%s:%u'.", p, pp, c);
                         option_free(ordered_hashmap_remove(*sysctl_options, p));
                 }
 
index 9b1c4908a40c189e246b0d0a6f7bb6bd7727aa8b..76a21afea619451d7d1f434d3ba1410b4cf3aacb 100644 (file)
@@ -509,7 +509,12 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
                         _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
                         _cleanup_(decrypted_image_unrefp) DecryptedImage *di = NULL;
                         _cleanup_(verity_settings_done) VeritySettings verity_settings = VERITY_SETTINGS_DEFAULT;
-                        DissectImageFlags flags = DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_MOUNT_ROOT_ONLY;
+                        DissectImageFlags flags =
+                                DISSECT_IMAGE_READ_ONLY |
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_MOUNT_ROOT_ONLY |
+                                DISSECT_IMAGE_USR_NO_ROOT;
 
                         r = verity_settings_load(&verity_settings, img->path, NULL, NULL);
                         if (r < 0)
@@ -520,13 +525,15 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
 
                         r = loop_device_make_by_path(img->path, O_RDONLY, 0, &d);
                         if (r < 0)
-                                return log_error_errno(r, "Failed to set up loopback device: %m");
+                                return log_error_errno(r, "Failed to set up loopback device for %s: %m", img->path);
 
                         r = dissect_image_and_warn(
                                         d->fd,
                                         img->path,
                                         &verity_settings,
                                         NULL,
+                                        d->uevent_seqnum_not_before,
+                                        d->timestamp_not_before,
                                         flags,
                                         &m);
                         if (r < 0)
index 82cb3df6cdd332acdc6ce8a85d2a78798c63d4d2..51a89ae4a737db7e8c6d9333408dc422a8c87b66 100644 (file)
@@ -161,7 +161,7 @@ int halt_main(void) {
 
                 /* Try logind if we are a normal user and no special mode applies. Maybe polkit allows us to
                  * shutdown the machine. */
-                if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT, ACTION_HALT)) {
+                if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT, ACTION_KEXEC, ACTION_HALT)) {
                         r = logind_reboot(arg_action);
                         if (r >= 0)
                                 return r;
index 314962ac69fb87af3e60d625c13407f4dae5408a..6e7c67ef2f27b54fe82a5b755e56bc8db5d5d934 100644 (file)
@@ -576,7 +576,7 @@ end:
 
                 /* Removing empty dropin dirs */
                 if (!arg_full) {
-                        _cleanup_free_ char *dir;
+                        _cleanup_free_ char *dir = NULL;
 
                         dir = dirname_malloc(*original);
                         if (!dir)
index e02a7608feef5d0a18a1d3c07fb6fab689058b73..135d8388a3ffd1b152f9a1890974d543b9922fe4 100644 (file)
@@ -24,7 +24,7 @@ static int get_unit_list_recursive(
                 char ***ret_machines) {
 
         _cleanup_free_ UnitInfo *unit_infos = NULL;
-        _cleanup_(message_set_freep) Set *replies;
+        _cleanup_(message_set_freep) Set *replies = NULL;
         sd_bus_message *reply;
         int c, r;
 
index 103f81647d26e5f5d52bd19d2cbb0a8e7220c276..28dd25b523dffb5e6d0887e39cbaaef9be1aa775 100644 (file)
@@ -50,6 +50,7 @@ int logind_reboot(enum action a) {
         } actions[_ACTION_MAX] = {
                 [ACTION_POWEROFF]               = { "PowerOff",             "power off system"                },
                 [ACTION_REBOOT]                 = { "Reboot",               "reboot system"                   },
+                [ACTION_KEXEC]                  = { "Reboot",               "kexec reboot system"             },
                 [ACTION_HALT]                   = { "Halt",                 "halt system"                     },
                 [ACTION_SUSPEND]                = { "Suspend",              "suspend system"                  },
                 [ACTION_HIBERNATE]              = { "Hibernate",            "hibernate system"                },
@@ -79,6 +80,7 @@ int logind_reboot(enum action a) {
                 return 0;
 
         SET_FLAG(flags, SD_LOGIND_ROOT_CHECK_INHIBITORS, arg_check_inhibitors > 0);
+        SET_FLAG(flags, SD_LOGIND_REBOOT_VIA_KEXEC, a == ACTION_KEXEC);
 
         method_with_flags = strjoina(actions[a].method, "WithFlags");
 
index c3c81f03fbd0b1241ed7a3fa43f0fecb51cdcbe9..2df05464c6106dd55f81fc4ae736f6b93b70ae89 100644 (file)
@@ -39,7 +39,7 @@
 
 static OutputFlags get_output_flags(void) {
         return
-                arg_all * OUTPUT_SHOW_ALL |
+                FLAGS_SET(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) * OUTPUT_SHOW_ALL |
                 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
                 colors_enabled() * OUTPUT_COLOR |
                 !arg_quiet * OUTPUT_WARN_CUTOFF;
@@ -955,7 +955,7 @@ static int map_exec(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_e
         return 0;
 }
 
-static int print_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) {
+static int print_property(const char *name, const char *expected_value, sd_bus_message *m, BusPrintPropertyFlags flags) {
         char bus_type;
         const char *contents;
         int r;
@@ -980,9 +980,9 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return r;
 
                         if (i >= 0 && i <= 255)
-                                bus_print_property_valuef(name, expected_value, value, "%"PRIi32, i);
-                        else if (all)
-                                bus_print_property_value(name, expected_value, value, "[not set]");
+                                bus_print_property_valuef(name, expected_value, flags, "%"PRIi32, i);
+                        else if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY))
+                                bus_print_property_value(name, expected_value, flags, "[not set]");
 
                         return 1;
                 } else if (streq(name, "NUMAPolicy")) {
@@ -992,7 +992,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (r < 0)
                                 return r;
 
-                        bus_print_property_valuef(name, expected_value, value, "%s", strna(mpol_to_string(i)));
+                        bus_print_property_valuef(name, expected_value, flags, "%s", strna(mpol_to_string(i)));
 
                         return 1;
                 }
@@ -1008,9 +1008,9 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         if (u > 0)
-                                bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
-                        else if (all)
-                                bus_print_property_value(name, expected_value, value, "");
+                                bus_print_property_valuef(name, expected_value, flags, "%"PRIu32, u);
+                        else
+                                bus_print_property_value(name, expected_value, flags, NULL);
 
                         return 1;
 
@@ -1021,8 +1021,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
-                        if (all || !isempty(s))
-                                bus_print_property_value(name, expected_value, value, s);
+                        bus_print_property_value(name, expected_value, flags, s);
 
                         return 1;
 
@@ -1034,9 +1033,9 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         if (!isempty(a) || !isempty(b))
-                                bus_print_property_valuef(name, expected_value, value, "%s \"%s\"", strempty(a), strempty(b));
-                        else if (all)
-                                bus_print_property_value(name, expected_value, value, "");
+                                bus_print_property_valuef(name, expected_value, flags, "%s \"%s\"", strempty(a), strempty(b));
+                        else
+                                bus_print_property_value(name, expected_value, flags, NULL);
 
                         return 1;
 
@@ -1060,11 +1059,11 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
-                        if (all || allow_list || !strv_isempty(l)) {
+                        if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) || allow_list || !strv_isempty(l)) {
                                 bool first = true;
                                 char **i;
 
-                                if (!value) {
+                                if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE)) {
                                         fputs(name, stdout);
                                         fputc('=', stdout);
                                 }
@@ -1094,9 +1093,9 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         if (!isempty(s))
-                                bus_print_property_valuef(name, expected_value, value, "%s%s", ignore ? "-" : "", s);
-                        else if (all)
-                                bus_print_property_value(name, expected_value, value, "");
+                                bus_print_property_valuef(name, expected_value, flags, "%s%s", ignore ? "-" : "", s);
+                        else
+                                bus_print_property_value(name, expected_value, flags, NULL);
 
                         return 1;
 
@@ -1123,10 +1122,10 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         n_status /= sizeof(int32_t);
                         n_signal /= sizeof(int32_t);
 
-                        if (all || n_status > 0 || n_signal > 0) {
+                        if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) || n_status > 0 || n_signal > 0) {
                                 bool first = true;
 
-                                if (!value) {
+                                if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE)) {
                                         fputs(name, stdout);
                                         fputc('=', stdout);
                                 }
@@ -1174,8 +1173,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
-                                bus_print_property_valuef(name, expected_value, value, "%s (ignore_errors=%s)", path, yes_no(ignore));
-
+                                bus_print_property_valuef(name, expected_value, flags, "%s (ignore_errors=%s)", path, yes_no(ignore));
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
@@ -1193,7 +1191,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
-                                bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type);
+                                bus_print_property_valuef(name, expected_value, flags, "%s (%s)", path, type);
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
@@ -1211,7 +1209,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
-                                bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type);
+                                bus_print_property_valuef(name, expected_value, flags, "%s (%s)", path, type);
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
@@ -1235,7 +1233,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 (void) format_timespan(timespan1, sizeof timespan1, v, 0);
                                 (void) format_timespan(timespan2, sizeof timespan2, next_elapse, 0);
 
-                                bus_print_property_valuef(name, expected_value, value,
+                                bus_print_property_valuef(name, expected_value, flags,
                                                           "{ %s=%s ; next_elapse=%s }", base, timespan1, timespan2);
                         }
                         if (r < 0)
@@ -1259,7 +1257,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 char timestamp[FORMAT_TIMESTAMP_MAX] = "n/a";
 
                                 (void) format_timestamp_style(timestamp, sizeof(timestamp), next_elapse, arg_timestamp_style);
-                                bus_print_property_valuef(name, expected_value, value,
+                                bus_print_property_valuef(name, expected_value, flags,
                                                           "{ %s=%s ; next_elapse=%s }", base, spec, timestamp);
                         }
                         if (r < 0)
@@ -1282,7 +1280,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         while ((r = exec_status_info_deserialize(m, &info, is_ex_prop)) > 0) {
                                 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
                                 _cleanup_strv_free_ char **optv = NULL;
-                                _cleanup_free_ char *tt, *o = NULL;
+                                _cleanup_free_ char *tt = NULL, *o = NULL;
 
                                 tt = strv_join(info.argv, " ");
 
@@ -1293,7 +1291,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
 
                                         o = strv_join(optv, " ");
 
-                                        bus_print_property_valuef(name, expected_value, value,
+                                        bus_print_property_valuef(name, expected_value, flags,
                                                                   "{ path=%s ; argv[]=%s ; flags=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
                                                                   strna(info.path),
                                                                   strna(tt),
@@ -1306,7 +1304,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                                                   info.code == CLD_EXITED ? "" : "/",
                                                                   strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
                                 } else
-                                        bus_print_property_valuef(name, expected_value, value,
+                                        bus_print_property_valuef(name, expected_value, flags,
                                                                   "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
                                                                   strna(info.path),
                                                                   strna(tt),
@@ -1338,7 +1336,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
-                                bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path), strna(rwm));
+                                bus_print_property_valuef(name, expected_value, flags, "%s %s", strna(path), strna(rwm));
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
@@ -1358,7 +1356,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
-                                bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), weight);
+                                bus_print_property_valuef(name, expected_value, flags, "%s %"PRIu64, strna(path), weight);
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
@@ -1379,7 +1377,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
-                                bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), bandwidth);
+                                bus_print_property_valuef(name, expected_value, flags, "%s %"PRIu64, strna(path), bandwidth);
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
@@ -1400,7 +1398,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(st)", &path, &target)) > 0)
-                                bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path),
+                                bus_print_property_valuef(name, expected_value, flags, "%s %s", strna(path),
                                                           format_timespan(ts, sizeof(ts), target, 1));
                         if (r < 0)
                                 return bus_log_parse_error(r);
@@ -1425,7 +1423,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (n < 0)
                                 return log_oom();
 
-                        bus_print_property_value(name, expected_value, value, h);
+                        bus_print_property_value(name, expected_value, flags, h);
 
                         return 1;
 
@@ -1485,8 +1483,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
-                        if (all || !isempty(addresses))
-                                bus_print_property_value(name, expected_value, value, strempty(addresses));
+                        bus_print_property_value(name, expected_value, flags, addresses);
 
                         return 1;
 
@@ -1524,8 +1521,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
-                        if (all || !isempty(paths))
-                                bus_print_property_value(name, expected_value, value, strempty(paths));
+                        bus_print_property_value(name, expected_value, flags, paths);
 
                         return 1;
 
@@ -1556,8 +1552,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
-                        if (all || !isempty(paths))
-                                bus_print_property_value(name, expected_value, value, strempty(paths));
+                        bus_print_property_value(name, expected_value, flags, paths);
 
                         return 1;
 
@@ -1604,11 +1599,14 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
-                        if (all || !isempty(fields))
-                                bus_print_property_value(name, expected_value, value, strempty(fields));
+                        bus_print_property_value(name, expected_value, flags, fields);
 
                         return 1;
-                } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "CPUAffinity", "NUMAMask", "AllowedCPUs", "AllowedMemoryNodes", "EffectiveCPUs", "EffectiveMemoryNodes")) {
+                } else if (contents[0] == SD_BUS_TYPE_BYTE &&
+                           STR_IN_SET(name,
+                                      "CPUAffinity", "NUMAMask", "AllowedCPUs", "AllowedMemoryNodes",
+                                      "EffectiveCPUs", "EffectiveMemoryNodes")) {
+
                         _cleanup_free_ char *affinity = NULL;
                         _cleanup_(cpu_set_reset) CPUSet set = {};
                         const void *a;
@@ -1626,7 +1624,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (!affinity)
                                 return log_oom();
 
-                        bus_print_property_value(name, expected_value, value, affinity);
+                        bus_print_property_value(name, expected_value, flags, affinity);
 
                         return 1;
                 } else if (streq(name, "MountImages")) {
@@ -1689,11 +1687,55 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
-                        if (all || !isempty(paths))
-                                bus_print_property_value(name, expected_value, value, strempty(paths));
+                        bus_print_property_value(name, expected_value, flags, paths);
+
+                        return 1;
+
+                } else if (streq(name, "BPFProgram")) {
+                        const char *a, *p;
+
+                        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)", &a, &p)) > 0)
+                                bus_print_property_valuef(name, expected_value, flags, "%s:%s", a, p);
+                        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 1;
+                } else if (STR_IN_SET(name, "SocketBindAllow", "SocketBindDeny")) {
+                        uint16_t nr_ports, port_min;
+                        const char *family;
+                        int af;
 
+                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(iqq)");
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+                        while ((r = sd_bus_message_read(m, "(iqq)", &af, &nr_ports, &port_min)) > 0) {
+                                family = af == AF_INET ? "IPv4:" : af == AF_INET6 ? "IPv6:" : "";
+                                if (nr_ports == 0)
+                                        bus_print_property_valuef(name, expected_value, flags, "%sany", family);
+                                else if (nr_ports == 1)
+                                        bus_print_property_valuef(
+                                                        name, expected_value, flags, "%s%hu", family, port_min);
+                                else
+                                        bus_print_property_valuef(
+                                                        name, expected_value, flags, "%s%hu-%hu", family, port_min,
+                                                        (uint16_t) (port_min + nr_ports - 1));
+                        }
+                        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 1;
                 }
 
                 break;
@@ -1888,7 +1930,7 @@ static int show_one(
         if (r < 0)
                 return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
 
-        r = bus_message_print_all_properties(reply, print_property, arg_properties, arg_value, arg_all, &found_properties);
+        r = bus_message_print_all_properties(reply, print_property, arg_properties, arg_print_flags, &found_properties);
         if (r < 0)
                 return bus_log_parse_error(r);
 
@@ -2112,7 +2154,7 @@ int show(int argc, char *argv[], void *userdata) {
                                 return r;
 
                         STRV_FOREACH(name, names) {
-                                _cleanup_free_ char *path;
+                                _cleanup_free_ char *path = NULL;
 
                                 path = unit_dbus_path_from_name(*name);
                                 if (!path)
index 15d2ea7941f84b3a57447a761c999da847a2c2d0..3edb65be617181b3b879ced38ad0fd69d99fb141 100644 (file)
@@ -201,6 +201,7 @@ int start_special(int argc, char *argv[], void *userdata) {
                 if (IN_SET(a,
                            ACTION_POWEROFF,
                            ACTION_REBOOT,
+                           ACTION_KEXEC,
                            ACTION_HALT,
                            ACTION_SUSPEND,
                            ACTION_HIBERNATE,
@@ -220,9 +221,9 @@ int start_special(int argc, char *argv[], void *userdata) {
 
                         arg_no_block = true;
 
-                } else if (IN_SET(a, ACTION_EXIT, ACTION_KEXEC))
-                        /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make
-                         * them asynchronous, in order to not confuse the user needlessly with unexpected
+                } else if (IN_SET(a, ACTION_EXIT))
+                        /* Since exit is so close in behaviour to power-off/reboot, let's also make
+                         * it asynchronous, in order to not confuse the user needlessly with unexpected
                          * behaviour. */
                         arg_no_block = true;
 
index c40e807212d9d48bddd41ee929bc74e410307069..096b8ada200e9cb9b47dd7114ee05d35f148076e 100644 (file)
@@ -307,7 +307,9 @@ int start_unit(int argc, char *argv[], void *userdata) {
                                 method = verb_to_method(argv[0]);
                                 job_type = verb_to_job_type(argv[0]);
                                 mode = arg_job_mode;
-                        }
+                        } else
+                                method = job_type = mode = NULL;
+
                         one_name = NULL;
                 }
         } else {
index bcc5f896b9acc8a901cfa5ecbcfa95adb43d4409..16c1f394407faf847d5e4fd7dca31dab5deee111 100644 (file)
@@ -75,7 +75,7 @@ bool arg_no_wtmp = false;
 bool arg_no_sync = false;
 bool arg_no_wall = false;
 bool arg_no_reload = false;
-bool arg_value = false;
+BusPrintPropertyFlags arg_print_flags = 0;
 bool arg_show_types = false;
 int arg_check_inhibitors = -1;
 bool arg_dry_run = false;
@@ -541,7 +541,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'P':
-                        arg_value = true;
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_ONLY_VALUE, true);
                         _fallthrough_;
 
                 case 'p':
@@ -566,11 +566,12 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                                 }
 
                         /* If the user asked for a particular property, show it, even if it is empty. */
-                        arg_all = true;
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
 
                         break;
 
                 case 'a':
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
                         arg_all = true;
                         break;
 
@@ -593,7 +594,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_VALUE:
-                        arg_value = true;
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_ONLY_VALUE, true);
                         break;
 
                 case ARG_JOB_MODE:
index 3a3ff9ac107d1b40b37c462bf67ef9d2eec68efa..ed8152e3dd8e48d5c65a1bd8be44aa98ebd63f00 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <stdbool.h>
 
+#include "bus-print-properties.h"
 #include "bus-util.h"
 #include "install.h"
 #include "output-mode.h"
@@ -58,7 +59,7 @@ extern bool arg_no_wtmp;
 extern bool arg_no_sync;
 extern bool arg_no_wall;
 extern bool arg_no_reload;
-extern bool arg_value;
+extern BusPrintPropertyFlags arg_print_flags;
 extern bool arg_show_types;
 extern int arg_check_inhibitors;
 extern bool arg_dry_run;
index ef57efd59593fe58e00dcb09c73acf2face8f92d..75f884836036def30f09efe5d2a7d0ed0da9f444 100644 (file)
@@ -191,119 +191,151 @@ struct sd_bus_vtable {
 #define _SD_ECHO(X) X
 #define _SD_CONCAT(X) #X "\0"
 
-#define _SD_VARARGS_FOREACH_EVEN_01(FN, X, ...)
-#define _SD_VARARGS_FOREACH_EVEN_02(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_01(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_03(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_02(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_04(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_03(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_05(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_04(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_06(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_05(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_07(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_06(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_08(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_07(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_09(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_08(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_10(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_09(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_11(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_10(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_12(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_11(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_13(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_12(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_14(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_13(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_15(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_14(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_16(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_15(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_17(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_16(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_18(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_17(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_19(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_18(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_20(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_19(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_21(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_20(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_22(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_21(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_23(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_22(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_24(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_23(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_25(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_24(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_26(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_25(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_27(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_26(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_28(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_27(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_29(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_28(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_30(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_29(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_31(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_30(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_32(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_31(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_33(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_32(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_34(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_33(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_35(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_34(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_36(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_35(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_37(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_36(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_38(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_37(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_39(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_38(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_40(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_39(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_41(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_40(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_42(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_41(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_43(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_42(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_44(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_43(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_45(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_44(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_46(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_45(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_47(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_46(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_48(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_47(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_49(FN, X, ...)       _SD_VARARGS_FOREACH_EVEN_48(FN, __VA_ARGS__)
-#define _SD_VARARGS_FOREACH_EVEN_50(FN, X, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_49(FN, __VA_ARGS__)
-
-#define _SD_VARARGS_FOREACH_EVEN_SEQ(_01, _02, _03, _04, _05, _06, _07, _08, _09, _10, \
-                                     _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
-                                     _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
-                                     _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
-                                     _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
-                                     NAME, ...) NAME
-
-#define _SD_VARARGS_FOREACH_EVEN(FN, ...)                                                      \
-        _SD_VARARGS_FOREACH_EVEN_SEQ(__VA_ARGS__,                                              \
-                                     _SD_VARARGS_FOREACH_EVEN_50, _SD_VARARGS_FOREACH_EVEN_49, \
-                                     _SD_VARARGS_FOREACH_EVEN_48, _SD_VARARGS_FOREACH_EVEN_47, \
-                                     _SD_VARARGS_FOREACH_EVEN_46, _SD_VARARGS_FOREACH_EVEN_45, \
-                                     _SD_VARARGS_FOREACH_EVEN_44, _SD_VARARGS_FOREACH_EVEN_43, \
-                                     _SD_VARARGS_FOREACH_EVEN_42, _SD_VARARGS_FOREACH_EVEN_41, \
-                                     _SD_VARARGS_FOREACH_EVEN_40, _SD_VARARGS_FOREACH_EVEN_39, \
-                                     _SD_VARARGS_FOREACH_EVEN_38, _SD_VARARGS_FOREACH_EVEN_37, \
-                                     _SD_VARARGS_FOREACH_EVEN_36, _SD_VARARGS_FOREACH_EVEN_35, \
-                                     _SD_VARARGS_FOREACH_EVEN_34, _SD_VARARGS_FOREACH_EVEN_33, \
-                                     _SD_VARARGS_FOREACH_EVEN_32, _SD_VARARGS_FOREACH_EVEN_31, \
-                                     _SD_VARARGS_FOREACH_EVEN_30, _SD_VARARGS_FOREACH_EVEN_29, \
-                                     _SD_VARARGS_FOREACH_EVEN_28, _SD_VARARGS_FOREACH_EVEN_27, \
-                                     _SD_VARARGS_FOREACH_EVEN_26, _SD_VARARGS_FOREACH_EVEN_25, \
-                                     _SD_VARARGS_FOREACH_EVEN_24, _SD_VARARGS_FOREACH_EVEN_23, \
-                                     _SD_VARARGS_FOREACH_EVEN_22, _SD_VARARGS_FOREACH_EVEN_21, \
-                                     _SD_VARARGS_FOREACH_EVEN_20, _SD_VARARGS_FOREACH_EVEN_19, \
-                                     _SD_VARARGS_FOREACH_EVEN_18, _SD_VARARGS_FOREACH_EVEN_17, \
-                                     _SD_VARARGS_FOREACH_EVEN_16, _SD_VARARGS_FOREACH_EVEN_15, \
-                                     _SD_VARARGS_FOREACH_EVEN_14, _SD_VARARGS_FOREACH_EVEN_13, \
-                                     _SD_VARARGS_FOREACH_EVEN_12, _SD_VARARGS_FOREACH_EVEN_11, \
-                                     _SD_VARARGS_FOREACH_EVEN_10, _SD_VARARGS_FOREACH_EVEN_09, \
-                                     _SD_VARARGS_FOREACH_EVEN_08, _SD_VARARGS_FOREACH_EVEN_07, \
-                                     _SD_VARARGS_FOREACH_EVEN_06, _SD_VARARGS_FOREACH_EVEN_05, \
-                                     _SD_VARARGS_FOREACH_EVEN_04, _SD_VARARGS_FOREACH_EVEN_03, \
-                                     _SD_VARARGS_FOREACH_EVEN_02, _SD_VARARGS_FOREACH_EVEN_01) \
-                                     (FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_SEQ(_01, _02, _03, _04, _05, _06, _07, _08, _09, _10, \
+                                _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
+                                _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
+                                _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
+                                _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
+                                NAME, ...) NAME
+
+#define _SD_VARARGS_FOREACH_EVEN_01(FN, X)         FN(X)
+#define _SD_VARARGS_FOREACH_EVEN_02(FN, X, Y)      FN(X)
+#define _SD_VARARGS_FOREACH_EVEN_04(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_02(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_06(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_04(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_08(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_06(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_10(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_08(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_12(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_10(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_14(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_12(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_16(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_14(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_18(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_16(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_20(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_18(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_22(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_20(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_24(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_22(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_26(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_24(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_28(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_26(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_30(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_28(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_32(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_30(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_34(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_32(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_36(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_34(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_38(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_36(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_40(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_38(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_42(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_40(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_44(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_42(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_46(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_44(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_48(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_46(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_EVEN_50(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_48(FN, __VA_ARGS__)
+
+#define _SD_VARARGS_FOREACH_EVEN(FN, ...)                                                 \
+        _SD_VARARGS_FOREACH_SEQ(__VA_ARGS__,                                              \
+                                _SD_VARARGS_FOREACH_EVEN_50, _SD_VARARGS_FOREACH_EVEN_49, \
+                                _SD_VARARGS_FOREACH_EVEN_48, _SD_VARARGS_FOREACH_EVEN_47, \
+                                _SD_VARARGS_FOREACH_EVEN_46, _SD_VARARGS_FOREACH_EVEN_45, \
+                                _SD_VARARGS_FOREACH_EVEN_44, _SD_VARARGS_FOREACH_EVEN_43, \
+                                _SD_VARARGS_FOREACH_EVEN_42, _SD_VARARGS_FOREACH_EVEN_41, \
+                                _SD_VARARGS_FOREACH_EVEN_40, _SD_VARARGS_FOREACH_EVEN_39, \
+                                _SD_VARARGS_FOREACH_EVEN_38, _SD_VARARGS_FOREACH_EVEN_37, \
+                                _SD_VARARGS_FOREACH_EVEN_36, _SD_VARARGS_FOREACH_EVEN_35, \
+                                _SD_VARARGS_FOREACH_EVEN_34, _SD_VARARGS_FOREACH_EVEN_33, \
+                                _SD_VARARGS_FOREACH_EVEN_32, _SD_VARARGS_FOREACH_EVEN_31, \
+                                _SD_VARARGS_FOREACH_EVEN_30, _SD_VARARGS_FOREACH_EVEN_29, \
+                                _SD_VARARGS_FOREACH_EVEN_28, _SD_VARARGS_FOREACH_EVEN_27, \
+                                _SD_VARARGS_FOREACH_EVEN_26, _SD_VARARGS_FOREACH_EVEN_25, \
+                                _SD_VARARGS_FOREACH_EVEN_24, _SD_VARARGS_FOREACH_EVEN_23, \
+                                _SD_VARARGS_FOREACH_EVEN_22, _SD_VARARGS_FOREACH_EVEN_21, \
+                                _SD_VARARGS_FOREACH_EVEN_20, _SD_VARARGS_FOREACH_EVEN_19, \
+                                _SD_VARARGS_FOREACH_EVEN_18, _SD_VARARGS_FOREACH_EVEN_17, \
+                                _SD_VARARGS_FOREACH_EVEN_16, _SD_VARARGS_FOREACH_EVEN_15, \
+                                _SD_VARARGS_FOREACH_EVEN_14, _SD_VARARGS_FOREACH_EVEN_13, \
+                                _SD_VARARGS_FOREACH_EVEN_12, _SD_VARARGS_FOREACH_EVEN_11, \
+                                _SD_VARARGS_FOREACH_EVEN_10, _SD_VARARGS_FOREACH_EVEN_09, \
+                                _SD_VARARGS_FOREACH_EVEN_08, _SD_VARARGS_FOREACH_EVEN_07, \
+                                _SD_VARARGS_FOREACH_EVEN_06, _SD_VARARGS_FOREACH_EVEN_05, \
+                                _SD_VARARGS_FOREACH_EVEN_04, _SD_VARARGS_FOREACH_EVEN_03, \
+                                _SD_VARARGS_FOREACH_EVEN_02, _SD_VARARGS_FOREACH_EVEN_01) \
+                                (FN, __VA_ARGS__)
+
+#define _SD_VARARGS_FOREACH_ODD_01(FN, X)
+#define _SD_VARARGS_FOREACH_ODD_02(FN, X, Y)      FN(Y)
+#define _SD_VARARGS_FOREACH_ODD_04(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_02(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_06(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_04(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_08(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_06(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_10(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_08(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_12(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_10(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_14(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_12(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_16(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_14(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_18(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_16(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_20(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_18(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_22(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_20(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_24(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_22(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_26(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_24(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_28(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_26(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_30(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_28(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_32(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_30(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_34(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_32(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_36(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_34(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_38(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_36(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_40(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_38(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_42(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_40(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_44(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_42(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_46(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_44(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_48(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_46(FN, __VA_ARGS__)
+#define _SD_VARARGS_FOREACH_ODD_50(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_48(FN, __VA_ARGS__)
+
+#define _SD_VARARGS_FOREACH_ODD(FN, ...)                                                \
+        _SD_VARARGS_FOREACH_SEQ(__VA_ARGS__,                                            \
+                                _SD_VARARGS_FOREACH_ODD_50, _SD_VARARGS_FOREACH_ODD_49, \
+                                _SD_VARARGS_FOREACH_ODD_48, _SD_VARARGS_FOREACH_ODD_47, \
+                                _SD_VARARGS_FOREACH_ODD_46, _SD_VARARGS_FOREACH_ODD_45, \
+                                _SD_VARARGS_FOREACH_ODD_44, _SD_VARARGS_FOREACH_ODD_43, \
+                                _SD_VARARGS_FOREACH_ODD_42, _SD_VARARGS_FOREACH_ODD_41, \
+                                _SD_VARARGS_FOREACH_ODD_40, _SD_VARARGS_FOREACH_ODD_39, \
+                                _SD_VARARGS_FOREACH_ODD_38, _SD_VARARGS_FOREACH_ODD_37, \
+                                _SD_VARARGS_FOREACH_ODD_36, _SD_VARARGS_FOREACH_ODD_35, \
+                                _SD_VARARGS_FOREACH_ODD_34, _SD_VARARGS_FOREACH_ODD_33, \
+                                _SD_VARARGS_FOREACH_ODD_32, _SD_VARARGS_FOREACH_ODD_31, \
+                                _SD_VARARGS_FOREACH_ODD_30, _SD_VARARGS_FOREACH_ODD_29, \
+                                _SD_VARARGS_FOREACH_ODD_28, _SD_VARARGS_FOREACH_ODD_27, \
+                                _SD_VARARGS_FOREACH_ODD_26, _SD_VARARGS_FOREACH_ODD_25, \
+                                _SD_VARARGS_FOREACH_ODD_24, _SD_VARARGS_FOREACH_ODD_23, \
+                                _SD_VARARGS_FOREACH_ODD_22, _SD_VARARGS_FOREACH_ODD_21, \
+                                _SD_VARARGS_FOREACH_ODD_20, _SD_VARARGS_FOREACH_ODD_19, \
+                                _SD_VARARGS_FOREACH_ODD_18, _SD_VARARGS_FOREACH_ODD_17, \
+                                _SD_VARARGS_FOREACH_ODD_16, _SD_VARARGS_FOREACH_ODD_15, \
+                                _SD_VARARGS_FOREACH_ODD_14, _SD_VARARGS_FOREACH_ODD_13, \
+                                _SD_VARARGS_FOREACH_ODD_12, _SD_VARARGS_FOREACH_ODD_11, \
+                                _SD_VARARGS_FOREACH_ODD_10, _SD_VARARGS_FOREACH_ODD_09, \
+                                _SD_VARARGS_FOREACH_ODD_08, _SD_VARARGS_FOREACH_ODD_07, \
+                                _SD_VARARGS_FOREACH_ODD_06, _SD_VARARGS_FOREACH_ODD_05, \
+                                _SD_VARARGS_FOREACH_ODD_04, _SD_VARARGS_FOREACH_ODD_03, \
+                                _SD_VARARGS_FOREACH_ODD_02, _SD_VARARGS_FOREACH_ODD_01) \
+                                (FN, __VA_ARGS__)
 
 #define SD_BUS_ARGS(...) __VA_ARGS__
 #define SD_BUS_RESULT(...) __VA_ARGS__
 
-#define SD_BUS_NO_ARGS SD_BUS_ARGS(NULL,)
-#define SD_BUS_NO_RESULT SD_BUS_RESULT(NULL,)
+#define SD_BUS_NO_ARGS SD_BUS_ARGS(NULL)
+#define SD_BUS_NO_RESULT SD_BUS_RESULT(NULL)
 
 #define SD_BUS_METHOD_WITH_ARGS(_member, _args, _result, _handler, _flags)                 \
         SD_BUS_METHOD_WITH_NAMES(_member,                                                  \
-                                _SD_VARARGS_FOREACH_EVEN(_SD_ECHO, _args),                 \
-                                _SD_VARARGS_FOREACH_EVEN(_SD_CONCAT, _args, ""),           \
-                                _SD_VARARGS_FOREACH_EVEN(_SD_ECHO, _result),               \
-                                _SD_VARARGS_FOREACH_EVEN(_SD_CONCAT, _result, ""),         \
-                                _handler, _flags)
+                                 _SD_VARARGS_FOREACH_EVEN(_SD_ECHO, _args),                \
+                                 _SD_VARARGS_FOREACH_ODD(_SD_CONCAT, _args),               \
+                                 _SD_VARARGS_FOREACH_EVEN(_SD_ECHO, _result),              \
+                                 _SD_VARARGS_FOREACH_ODD(_SD_CONCAT, _result) "\0",        \
+                                 _handler, _flags)
 
 #define SD_BUS_METHOD_WITH_ARGS_OFFSET(_member, _args, _result, _handler, _offset, _flags) \
         SD_BUS_METHOD_WITH_NAMES_OFFSET(_member,                                           \
                                         _SD_VARARGS_FOREACH_EVEN(_SD_ECHO, _args),         \
-                                        _SD_VARARGS_FOREACH_EVEN(_SD_CONCAT, _args, ""),   \
+                                        _SD_VARARGS_FOREACH_ODD(_SD_CONCAT, _args),        \
                                         _SD_VARARGS_FOREACH_EVEN(_SD_ECHO, _result),       \
-                                        _SD_VARARGS_FOREACH_EVEN(_SD_CONCAT, _result, ""), \
+                                        _SD_VARARGS_FOREACH_ODD(_SD_CONCAT, _result) "\0", \
                                         _handler, _offset, _flags)
 
 #define SD_BUS_SIGNAL_WITH_ARGS(_member, _args, _flags)                                    \
         SD_BUS_SIGNAL_WITH_NAMES(_member,                                                  \
                                  _SD_VARARGS_FOREACH_EVEN(_SD_ECHO, _args),                \
-                                 _SD_VARARGS_FOREACH_EVEN(_SD_CONCAT, _args, ""),          \
+                                 _SD_VARARGS_FOREACH_ODD(_SD_CONCAT, _args) "\0",          \
                                  _flags)
 
 _SD_END_DECLARATIONS;
index 310fcaa278a62dae6396c16830e64d631c4679fa..8b7b361295ecc9d023247850f07bf85b7278e2b9 100644 (file)
@@ -79,6 +79,7 @@ int sd_device_get_action(sd_device *device, sd_device_action_t *ret);
 int sd_device_get_seqnum(sd_device *device, uint64_t *ret);
 
 int sd_device_get_is_initialized(sd_device *device);
+int sd_device_get_usec_initialized(sd_device *device, uint64_t *usec);
 int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec);
 
 const char *sd_device_get_tag_first(sd_device *device);
@@ -136,6 +137,8 @@ int sd_device_monitor_stop(sd_device_monitor *m);
 
 int sd_device_monitor_filter_add_match_subsystem_devtype(sd_device_monitor *m, const char *subsystem, const char *devtype);
 int sd_device_monitor_filter_add_match_tag(sd_device_monitor *m, const char *tag);
+int sd_device_monitor_filter_add_match_sysattr(sd_device_monitor *m, const char *sysattr, const char *value, int match);
+int sd_device_monitor_filter_add_match_parent(sd_device_monitor *m, sd_device *device, int match);
 int sd_device_monitor_filter_update(sd_device_monitor *m);
 int sd_device_monitor_filter_remove(sd_device_monitor *m);
 
index 822286919ea9c29657801c62f45062c279da1e29..da0a5a7ac4771168a6f566e04fdbcbeedfae7610 100644 (file)
@@ -125,6 +125,10 @@ int sd_dhcp_client_set_request_broadcast(
 int sd_dhcp_client_set_ifindex(
                 sd_dhcp_client *client,
                 int interface_index);
+int sd_dhcp_client_set_ifname(
+                sd_dhcp_client *client,
+                const char *interface_name);
+const char *sd_dhcp_client_get_ifname(sd_dhcp_client *client);
 int sd_dhcp_client_set_mac(
                 sd_dhcp_client *client,
                 const uint8_t *addr,
@@ -195,6 +199,7 @@ int sd_dhcp_client_set_fallback_lease_lifetime(
 int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v);
 int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v);
 
+int sd_dhcp_client_is_running(const sd_dhcp_client *client);
 int sd_dhcp_client_stop(sd_dhcp_client *client);
 int sd_dhcp_client_start(sd_dhcp_client *client);
 int sd_dhcp_client_send_release(sd_dhcp_client *client);
index 5abf9a406c07aa3f152fcf3911cc36a2f945cbc1..9cf36d896b28aa6be6d31d26850dc89b0b38047a 100644 (file)
@@ -46,36 +46,36 @@ typedef enum sd_dhcp_lease_server_type_t {
         _SD_ENUM_FORCE_S64(DHCP_LEASE_SERVER_TYPE),
 } sd_dhcp_lease_server_type_t;
 
-int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr);
-int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime);
-int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1);
-int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2);
-int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr);
-int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr);
-int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr);
-int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr);
-int sd_dhcp_lease_get_servers(sd_dhcp_lease *lease, sd_dhcp_lease_server_type_t what, const struct in_addr **addr);
-int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_pop3(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_smtp(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_lpr(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu);
-int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);
-int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains);
-int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname);
-int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path);
-int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes);
-int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len);
-int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len);
-int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone);
+int sd_dhcp_lease_get_address(const sd_dhcp_lease *lease, struct in_addr *addr);
+int sd_dhcp_lease_get_lifetime(const sd_dhcp_lease *lease, uint32_t *lifetime);
+int sd_dhcp_lease_get_t1(const sd_dhcp_lease *lease, uint32_t *t1);
+int sd_dhcp_lease_get_t2(const sd_dhcp_lease *lease, uint32_t *t2);
+int sd_dhcp_lease_get_broadcast(const sd_dhcp_lease *lease, struct in_addr *addr);
+int sd_dhcp_lease_get_netmask(const sd_dhcp_lease *lease, struct in_addr *addr);
+int sd_dhcp_lease_get_router(const sd_dhcp_lease *lease, const struct in_addr **addr);
+int sd_dhcp_lease_get_next_server(const sd_dhcp_lease *lease, struct in_addr *addr);
+int sd_dhcp_lease_get_server_identifier(const sd_dhcp_lease *lease, struct in_addr *addr);
+int sd_dhcp_lease_get_servers(const sd_dhcp_lease *lease, sd_dhcp_lease_server_type_t what, const struct in_addr **addr);
+int sd_dhcp_lease_get_dns(const sd_dhcp_lease *lease, const struct in_addr **addr);
+int sd_dhcp_lease_get_ntp(const sd_dhcp_lease *lease, const struct in_addr **addr);
+int sd_dhcp_lease_get_sip(const sd_dhcp_lease *lease, const struct in_addr **addr);
+int sd_dhcp_lease_get_pop3(const sd_dhcp_lease *lease, const struct in_addr **addr);
+int sd_dhcp_lease_get_smtp(const sd_dhcp_lease *lease, const struct in_addr **addr);
+int sd_dhcp_lease_get_lpr(const sd_dhcp_lease *lease, const struct in_addr **addr);
+int sd_dhcp_lease_get_mtu(const sd_dhcp_lease *lease, uint16_t *mtu);
+int sd_dhcp_lease_get_domainname(const sd_dhcp_lease *lease, const char **domainname);
+int sd_dhcp_lease_get_search_domains(const sd_dhcp_lease *lease, char ***domains);
+int sd_dhcp_lease_get_hostname(const sd_dhcp_lease *lease, const char **hostname);
+int sd_dhcp_lease_get_root_path(const sd_dhcp_lease *lease, const char **root_path);
+int sd_dhcp_lease_get_routes(const sd_dhcp_lease *lease, sd_dhcp_route ***routes);
+int sd_dhcp_lease_get_vendor_specific(const sd_dhcp_lease *lease, const void **data, size_t *data_len);
+int sd_dhcp_lease_get_client_id(const sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len);
+int sd_dhcp_lease_get_timezone(const sd_dhcp_lease *lease, const char **timezone);
 
-int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination);
-int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length);
-int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway);
-int sd_dhcp_route_get_option(sd_dhcp_route *route);
+int sd_dhcp_route_get_destination(const sd_dhcp_route *route, struct in_addr *destination);
+int sd_dhcp_route_get_destination_prefix_length(const sd_dhcp_route *route, uint8_t *length);
+int sd_dhcp_route_get_gateway(const sd_dhcp_route *route, struct in_addr *gateway);
+int sd_dhcp_route_get_option(const sd_dhcp_route *route);
 
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_lease, sd_dhcp_lease_unref);
 
index aa49a7434c37a12cb0e7920f9c4f8e0be7f6bd93..3cee2c2b062645879ee249aa43af10adeab93223 100644 (file)
@@ -37,6 +37,9 @@ enum {
 
 int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex);
 
+int sd_dhcp_server_set_ifname(sd_dhcp_server *server, const char *ifname);
+const char *sd_dhcp_server_get_ifname(sd_dhcp_server *server);
+
 sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server);
 sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server);
 
@@ -55,6 +58,7 @@ int sd_dhcp_server_stop(sd_dhcp_server *server);
 
 int sd_dhcp_server_configure_pool(sd_dhcp_server *server, const struct in_addr *address, unsigned char prefixlen, uint32_t offset, uint32_t size);
 
+int sd_dhcp_server_set_bind_to_interface(sd_dhcp_server *server, int enabled);
 int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone);
 int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled);
 
@@ -79,6 +83,8 @@ int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t);
 
 int sd_dhcp_server_forcerenew(sd_dhcp_server *server);
 
+int sd_dhcp_server_is_in_relay_mode(sd_dhcp_server *server);
+int sd_dhcp_server_set_relay_target(sd_dhcp_server *server, const struct in_addr* address);
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_server, sd_dhcp_server_unref);
 
 _SD_END_DECLARATIONS;
index 84e31701303c39cba454709dc21b43a7b98df03f..e02d67632a102f7f84d9d3cab6103d87a8b3067f 100644 (file)
@@ -91,6 +91,10 @@ int sd_dhcp6_client_set_callback(
 int sd_dhcp6_client_set_ifindex(
                 sd_dhcp6_client *client,
                 int interface_index);
+int sd_dhcp6_client_set_ifname(
+                sd_dhcp6_client *client,
+                const char *interface_name);
+const char * sd_dhcp6_client_get_ifname(sd_dhcp6_client *client);
 int sd_dhcp6_client_set_local_address(
                 sd_dhcp6_client *client,
                 const struct in6_addr *local_address);
index 02aa318a06082ebf7be74f20ecf5b992bcda7f36..ab209c8c7daf0db155c4c383a4e296cdcc2b7236 100644 (file)
@@ -18,6 +18,7 @@
 ***/
 
 #include <inttypes.h>
+#include <stdarg.h>
 #include <string.h>
 
 #include "_sd-common.h"
@@ -119,6 +120,32 @@ _sd_pure_ static __inline__ int sd_id128_is_allf(sd_id128_t a) {
 #define SD_ID128_NULL ((const sd_id128_t) { .qwords = { 0, 0 }})
 #define SD_ID128_ALLF ((const sd_id128_t) { .qwords = { UINT64_C(0xFFFFFFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF) }})
 
+_sd_pure_ static __inline__ int sd_id128_in_setv(sd_id128_t a, va_list ap) {
+        for (;;) {
+                sd_id128_t b = va_arg(ap, sd_id128_t);
+
+                if (sd_id128_is_null(b))
+                        return 0;
+
+                if (sd_id128_equal(a, b))
+                        return 1;
+        }
+}
+
+_sd_pure_ static __inline__ int sd_id128_in_set_sentinel(sd_id128_t a, ...) {
+        va_list ap;
+        int r;
+
+        va_start(ap, a);
+        r = sd_id128_in_setv(a, ap);
+        va_end(ap);
+
+        return r;
+}
+
+#define sd_id128_in_set(a, ...) \
+        sd_id128_in_set_sentinel(a, ##__VA_ARGS__, SD_ID128_NULL)
+
 _SD_END_DECLARATIONS;
 
 #endif
index 2809d8748bd7ea1ef154017f5efa488faebab28e..1e89a81b31516e0ca99907b5fdd94d33f4d27aa0 100644 (file)
@@ -44,6 +44,7 @@ int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *use
 int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr);
 int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int interface_index);
 int sd_ipv4acd_get_ifindex(sd_ipv4acd *acd);
+int sd_ipv4acd_set_ifname(sd_ipv4acd *acd, const char *interface_name);
 const char *sd_ipv4acd_get_ifname(sd_ipv4acd *acd);
 int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address);
 int sd_ipv4acd_is_running(sd_ipv4acd *acd);
index aa4d174e4b795f877238ffdff3ddc1fb170e61c6..bf5596ab613c8391a701342e2a8445e062a522a9 100644 (file)
@@ -44,6 +44,7 @@ int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdat
 int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr);
 int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int interface_index);
 int sd_ipv4ll_get_ifindex(sd_ipv4ll *ll);
+int sd_ipv4ll_set_ifname(sd_ipv4ll *ll, const char *interface_name);
 const char *sd_ipv4ll_get_ifname(sd_ipv4ll *ll);
 int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address);
 int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed);
index e48e29fbc05b0e83c1375e8b95ed1320e8676251..64047ee81716ce1cb96a90e2967b96fa6bf462d4 100644 (file)
@@ -147,6 +147,8 @@ sd_event *sd_lldp_get_event(sd_lldp *lldp);
 
 int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata);
 int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex);
+int sd_lldp_set_ifname(sd_lldp *lldp, const char *ifname);
+const char *sd_lldp_get_ifname(sd_lldp *lldp);
 
 /* Controls how much and what to store in the neighbors database */
 int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t n);
index 6958d99a1e8f86d2ee91bc18906ec2d208fbd90a..d3ad6abef12ea05d713a9ab12aee49748027dbec 100644 (file)
@@ -110,7 +110,7 @@ int sd_peer_get_machine_name(int fd, char **machine);
 
 /* Similar to sd_pid_get_cgroup(), but retrieves data about the peer
  * of a connected AF_UNIX socket. */
-int sd_peer_get_cgroup(pid_t pid, char **cgroup);
+int sd_peer_get_cgroup(int fd, char **cgroup);
 
 /* Get state from UID. Possible states: offline, lingering, online, active, closing */
 int sd_uid_get_state(uid_t uid, char **state);
index 49b127c01817af95a257420f6710527a5c4774cd..6088def1b61d257582ca1412a529ef87fe9b48bf 100644 (file)
@@ -78,6 +78,8 @@ sd_event *sd_ndisc_get_event(sd_ndisc *nd);
 
 int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_callback_t cb, void *userdata);
 int sd_ndisc_set_ifindex(sd_ndisc *nd, int interface_index);
+int sd_ndisc_set_ifname(sd_ndisc *nd, const char *interface_name);
+const char *sd_ndisc_get_ifname(sd_ndisc *nd);
 int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr);
 
 int sd_ndisc_get_mtu(sd_ndisc *nd, uint32_t *ret);
index 884dba81b9b750a1f128cc716d19ee1019396b02..3f4ccf19087ab2a4105282998b3410b134c29374 100644 (file)
@@ -51,6 +51,8 @@ _SD_BEGIN_DECLARATIONS;
 int sd_network_get_operational_state(char **state);
 int sd_network_get_carrier_state(char **state);
 int sd_network_get_address_state(char **state);
+int sd_network_get_ipv4_address_state(char **state);
+int sd_network_get_ipv6_address_state(char **state);
 
 /* Get DNS entries for all links. These are string representations of
  * IP addresses */
@@ -92,8 +94,11 @@ int sd_network_link_get_setup_state(int ifindex, char **state);
  */
 int sd_network_link_get_operational_state(int ifindex, char **state);
 int sd_network_link_get_required_operstate_for_online(int ifindex, char **state);
+int sd_network_link_get_required_family_for_online(int ifindex, char **state);
 int sd_network_link_get_carrier_state(int ifindex, char **state);
 int sd_network_link_get_address_state(int ifindex, char **state);
+int sd_network_link_get_ipv4_address_state(int ifindex, char **state);
+int sd_network_link_get_ipv6_address_state(int ifindex, char **state);
 
 /* Indicates whether the network is relevant to being online.
  * Possible return codes:
index 3f6c149d5e259daba08b92da1799b184195c9893..be5cf1b94e65d867d87b20f4d7a1ed14ba77b66e 100644 (file)
@@ -53,6 +53,8 @@ int sd_radv_stop(sd_radv *ra);
 int sd_radv_is_running(sd_radv *ra);
 
 int sd_radv_set_ifindex(sd_radv *ra, int interface_index);
+int sd_radv_set_ifname(sd_radv *ra, const char *interface_name);
+const char *sd_radv_get_ifname(sd_radv *ra);
 int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr);
 int sd_radv_set_mtu(sd_radv *ra, uint32_t mtu);
 int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit);
index b098eb27cd46468fbeb711f2433a82d247da7ed5..848e5e867c7017d428a693ee60e338cff9e97735 100644 (file)
@@ -6,6 +6,7 @@
 #include "alloc-util.h"
 #include "conf-files.h"
 #include "copy.h"
+#include "creds-util.h"
 #include "def.h"
 #include "dissect-image.h"
 #include "fd-util.h"
@@ -13,7 +14,9 @@
 #include "format-util.h"
 #include "fs-util.h"
 #include "hashmap.h"
+#include "libcrypt-util.h"
 #include "main-func.h"
+#include "memory-util.h"
 #include "mount-util.h"
 #include "nscd-flush.h"
 #include "pager.h"
@@ -429,6 +432,8 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char
         }
 
         ORDERED_HASHMAP_FOREACH(i, todo_uids) {
+                _cleanup_free_ char *creds_shell = NULL, *cn = NULL;
+
                 struct passwd n = {
                         .pw_name = i->name,
                         .pw_uid = i->uid,
@@ -436,7 +441,7 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char
                         .pw_gecos = i->description,
 
                         /* "x" means the password is stored in the shadow file */
-                        .pw_passwd = (char*) "x",
+                        .pw_passwd = (char*) PASSWORD_SEE_SHADOW,
 
                         /* We default to the root directory as home */
                         .pw_dir = i->home ?: (char*) "/",
@@ -446,6 +451,17 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char
                         .pw_shell = i->shell ?: (char*) default_shell(i->uid),
                 };
 
+                /* Try to pick up the shell for this account via the credentials logic */
+                cn = strjoin("passwd.shell.", i->name);
+                if (!cn)
+                        return -ENOMEM;
+
+                r = read_credential(cn, (void**) &creds_shell, NULL);
+                if (r < 0)
+                        log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
+                else
+                        n.pw_shell = creds_shell;
+
                 r = putpwent_sane(&n, passwd);
                 if (r < 0)
                         return r;
@@ -530,9 +546,12 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
         }
 
         ORDERED_HASHMAP_FOREACH(i, todo_uids) {
+                _cleanup_(erase_and_freep) char *creds_password = NULL;
+                _cleanup_free_ char *cn = NULL;
+
                 struct spwd n = {
                         .sp_namp = i->name,
-                        .sp_pwdp = (char*) "!*", /* lock this password, and make it invalid */
+                        .sp_pwdp = (char*) PASSWORD_LOCKED_AND_INVALID,
                         .sp_lstchg = lstchg,
                         .sp_min = -1,
                         .sp_max = -1,
@@ -542,6 +561,34 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
                         .sp_flag = ULONG_MAX, /* this appears to be what everybody does ... */
                 };
 
+                /* Try to pick up the password for this account via the credentials logic */
+                cn = strjoin("passwd.hashed-password.", i->name);
+                if (!cn)
+                        return -ENOMEM;
+
+                r = read_credential(cn, (void**) &creds_password, NULL);
+                if (r == -ENOENT) {
+                        _cleanup_(erase_and_freep) char *plaintext_password = NULL;
+
+                        free(cn);
+                        cn = strjoin("passwd.plaintext-password.", i->name);
+                        if (!cn)
+                                return -ENOMEM;
+
+                        r = read_credential(cn, (void**) &plaintext_password, NULL);
+                        if (r < 0)
+                                log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
+                        else {
+                                r = hash_password(plaintext_password, &creds_password);
+                                if (r < 0)
+                                        return log_debug_errno(r, "Failed to hash password: %m");
+                        }
+                } else if (r < 0)
+                        log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
+
+                if (creds_password)
+                        n.sp_pwdp = creds_password;
+
                 r = putspent_sane(&n, shadow);
                 if (r < 0)
                         return r;
@@ -635,7 +682,7 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char **
                 struct group n = {
                         .gr_name = i->name,
                         .gr_gid = i->gid,
-                        .gr_passwd = (char*) "x",
+                        .gr_passwd = (char*) PASSWORD_SEE_SHADOW,
                 };
 
                 r = putgrent_with_members(&n, group);
@@ -719,7 +766,7 @@ static int write_temporary_gshadow(const char * gshadow_path, FILE **tmpfile, ch
         ORDERED_HASHMAP_FOREACH(i, todo_gids) {
                 struct sgrp n = {
                         .sg_namp = i->name,
-                        .sg_passwd = (char*) "!*",
+                        .sg_passwd = (char*) PASSWORD_LOCKED_AND_INVALID,
                 };
 
                 r = putsgent_with_members(&n, gshadow);
@@ -1681,6 +1728,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
 
 static int read_config_file(const char *fn, bool ignore_enoent) {
         _cleanup_fclose_ FILE *rf = NULL;
+        _cleanup_free_ char *pp = NULL;
         FILE *f = NULL;
         unsigned v = 0;
         int r = 0;
@@ -1690,7 +1738,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
         if (streq(fn, "-"))
                 f = stdin;
         else {
-                r = search_and_fopen(fn, "re", arg_root, (const char**) CONF_PATHS_STRV("sysusers.d"), &rf);
+                r = search_and_fopen(fn, "re", arg_root, (const char**) CONF_PATHS_STRV("sysusers.d"), &rf, &pp);
                 if (r < 0) {
                         if (ignore_enoent && r == -ENOENT)
                                 return 0;
@@ -1699,6 +1747,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
                 }
 
                 f = rf;
+                fn = pp;
         }
 
         for (;;) {
@@ -1946,7 +1995,12 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
-                                DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_VALIDATE_OS |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                DISSECT_IMAGE_FSCK |
+                                DISSECT_IMAGE_GROWFS,
                                 &unlink_dir,
                                 &loop_device,
                                 &decrypted_image);
index 8c7aef23c33c640dad1cfc12c13372e1116b13f7..cef141fbacbcb7912c98496bb324aedaae1c9265 100644 (file)
@@ -137,7 +137,7 @@ static int generate_unit_file(SysvStub *s) {
                 path_escaped);
 
         if (s->description) {
-                _cleanup_free_ char *t;
+                _cleanup_free_ char *t = NULL;
 
                 t = specifier_escape(s->description);
                 if (!t)
@@ -165,7 +165,7 @@ static int generate_unit_file(SysvStub *s) {
                 yes_no(!s->pid_file));
 
         if (s->pid_file) {
-                _cleanup_free_ char *t;
+                _cleanup_free_ char *t = NULL;
 
                 t = specifier_escape(s->pid_file);
                 if (!t)
@@ -419,7 +419,7 @@ static int handle_dependencies(SysvStub *s, unsigned line, const char *full_text
 }
 
 static int load_sysv(SysvStub *s) {
-        _cleanup_fclose_ FILE *f;
+        _cleanup_fclose_ FILE *f = NULL;
         unsigned line = 0;
         int r;
         enum {
index ff40a8d10ddd0452db642b953d53b2aecc4d0485..2b8bdcc0645f89cb6458fef58ce0e77c1076232f 100644 (file)
@@ -133,6 +133,17 @@ tests += [
 
         [['src/test/test-serialize.c']],
 
+        [['src/test/test-unit-serialize.c'],
+         [libcore,
+          libshared],
+         [threads,
+          librt,
+          libseccomp,
+          libselinux,
+          libmount,
+          libblkid],
+         core_includes],
+
         [['src/test/test-utf8.c']],
 
         [['src/test/test-dev-setup.c']],
@@ -158,7 +169,10 @@ tests += [
 
         [['src/test/test-fstab-util.c']],
 
-        [['src/test/test-random-util.c']],
+        [['src/test/test-random-util.c'],
+         [],
+         [libm],
+         [], '', 'timeout=120'],
 
         [['src/test/test-format-table.c']],
 
@@ -321,6 +335,12 @@ tests += [
           libblkid],
          core_includes],
 
+        [['src/test/test-bpf-foreign-programs.c'],
+         [libcore,
+          libshared],
+         [],
+         core_includes],
+
         [['src/test/test-watch-pid.c'],
          [libcore,
           libshared],
@@ -540,7 +560,16 @@ tests += [
         [['src/test/test-gcrypt-util.c'],
          [], [], [], 'HAVE_GCRYPT'],
 
-        [['src/test/test-nss.c'],
+        [['src/test/test-nss-hosts.c',
+          'src/test/nss-test-util.c',
+          'src/test/nss-test-util.h'],
+         [],
+         [libdl],
+         [], 'ENABLE_NSS', 'manual'],
+
+        [['src/test/test-nss-users.c',
+          'src/test/nss-test-util.c',
+          'src/test/nss-test-util.h'],
          [],
          [libdl],
          [], 'ENABLE_NSS', 'manual'],
@@ -582,3 +611,12 @@ tests += [
          [libudev],
          [threads]],
 ]
+
+tests += [
+         [['src/test/test-socket-bind.c'],
+          [libcore,
+          libshared],
+         [libbpf],
+         core_includes,
+         'BPF_FRAMEWORK'],
+]
diff --git a/src/test/nss-test-util.c b/src/test/nss-test-util.c
new file mode 100644 (file)
index 0000000..fc1d724
--- /dev/null
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "nss-test-util.h"
+#include "string-util.h"
+
+const char* nss_status_to_string(enum nss_status status, char *buf, size_t buf_len) {
+        switch (status) {
+        case NSS_STATUS_TRYAGAIN:
+                return "NSS_STATUS_TRYAGAIN";
+        case NSS_STATUS_UNAVAIL:
+                return "NSS_STATUS_UNAVAIL";
+        case NSS_STATUS_NOTFOUND:
+                return "NSS_STATUS_NOTFOUND";
+        case NSS_STATUS_SUCCESS:
+                return "NSS_STATUS_SUCCESS";
+        case NSS_STATUS_RETURN:
+                return "NSS_STATUS_RETURN";
+        default:
+                snprintf(buf, buf_len, "%i", status);
+                return buf;
+        }
+};
+
+void* nss_open_handle(const char *dir, const char *module, int flags) {
+        const char *path = NULL;
+        void *handle;
+
+        if (dir)
+                path = strjoina(dir, "/libnss_", module, ".so.2");
+        if (!path || access(path, F_OK) < 0)
+                path = strjoina("libnss_", module, ".so.2");
+
+        log_debug("Using %s", path);
+        handle = dlopen(path, flags);
+        if (!handle)
+                log_error("Failed to load module %s: %s", module, dlerror());
+        return handle;
+}
diff --git a/src/test/nss-test-util.h b/src/test/nss-test-util.h
new file mode 100644 (file)
index 0000000..f081e64
--- /dev/null
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <nss.h>
+#include <stdint.h>
+
+const char* nss_status_to_string(enum nss_status status, char *buf, size_t buf_len);
+void* nss_open_handle(const char *dir, const char *module, int flags);
diff --git a/src/test/test-bpf-foreign-programs.c b/src/test/test-bpf-foreign-programs.c
new file mode 100644 (file)
index 0000000..666317e
--- /dev/null
@@ -0,0 +1,332 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <fcntl.h>
+#include <linux/bpf_insn.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "bpf-foreign.h"
+#include "load-fragment.h"
+#include "manager.h"
+#include "process-util.h"
+#include "rlimit-util.h"
+#include "rm-rf.h"
+#include "service.h"
+#include "tests.h"
+#include "unit.h"
+#include "virt.h"
+
+struct Test {
+        const char *option_name;
+        enum bpf_prog_type prog_type;
+        enum bpf_attach_type attach_type;
+        const char *bpffs_path;
+};
+
+typedef struct Test Test;
+
+#define BPFFS_PATH(prog_suffix) ("/sys/fs/bpf/test-bpf-foreing-" # prog_suffix)
+static const Test single_prog[] = {
+        {
+                .option_name = "BPFProgram",
+                .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+                .attach_type = BPF_CGROUP_INET_INGRESS,
+                .bpffs_path = BPFFS_PATH("trivial-skb"),
+        },
+};
+static const Test path_split_test[] = {
+        {
+                .option_name = "BPFProgram",
+                .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+                .attach_type = BPF_CGROUP_INET_INGRESS,
+                .bpffs_path = BPFFS_PATH("path:split:test"),
+        },
+};
+
+static const Test same_prog_same_hook[] = {
+        {
+                .option_name = "BPFProgram",
+                .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
+                .attach_type = BPF_CGROUP_INET_SOCK_CREATE,
+                .bpffs_path = BPFFS_PATH("trivial-sock"),
+        },
+        {
+                .option_name = "BPFProgram",
+                .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
+                .attach_type = BPF_CGROUP_INET_SOCK_CREATE,
+                .bpffs_path = BPFFS_PATH("trivial-sock"),
+        }
+};
+
+static const Test multi_prog_same_hook[] = {
+        {
+                .option_name = "BPFProgram",
+                .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
+                .attach_type = BPF_CGROUP_INET_SOCK_CREATE,
+                .bpffs_path = BPFFS_PATH("trivial-sock-0"),
+        },
+        {
+                .option_name = "BPFProgram",
+                .prog_type = BPF_PROG_TYPE_CGROUP_SOCK,
+                .attach_type = BPF_CGROUP_INET_SOCK_CREATE,
+                .bpffs_path = BPFFS_PATH("trivial-sock-1"),
+        }
+};
+
+static const Test same_prog_multi_hook[] = {
+        {
+                .option_name = "BPFProgram",
+                .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+                .attach_type = BPF_CGROUP_INET_INGRESS,
+                .bpffs_path = BPFFS_PATH("trivial-skb"),
+        },
+        {
+                .option_name = "BPFProgram",
+                .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+                .attach_type = BPF_CGROUP_INET_EGRESS,
+                .bpffs_path = BPFFS_PATH("trivial-skb"),
+        }
+};
+
+static const Test same_prog_multi_option_0[] = {
+        {
+                .option_name = "BPFProgram",
+                .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+                .attach_type = BPF_CGROUP_INET_INGRESS,
+                .bpffs_path = BPFFS_PATH("trivial-skb"),
+        },
+        {
+                .option_name = "IPIngressFilterPath",
+                .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+                .attach_type = BPF_CGROUP_INET_INGRESS,
+                .bpffs_path = BPFFS_PATH("trivial-skb"),
+        }
+};
+
+static const Test same_prog_multi_option_1[] = {
+        {
+                .option_name = "IPEgressFilterPath",
+                .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+                .attach_type = BPF_CGROUP_INET_EGRESS,
+                .bpffs_path = BPFFS_PATH("trivial-skb"),
+        },
+        {
+                .option_name = "BPFProgram",
+                .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+                .attach_type = BPF_CGROUP_INET_EGRESS,
+                .bpffs_path = BPFFS_PATH("trivial-skb"),
+        }
+};
+#undef BPFFS_PATH
+
+static int bpf_foreign_test_to_string(enum bpf_attach_type attach_type, const char *bpffs_path, char **ret_str) {
+        const char *s = NULL;
+
+        assert_se(bpffs_path);
+        assert_se(ret_str);
+
+        assert_se(s = bpf_cgroup_attach_type_to_string(attach_type));
+        assert_se(*ret_str = strjoin(s, ":", bpffs_path));
+
+        return 0;
+}
+
+static char **unlink_paths_and_free(char **paths) {
+        char **i;
+
+        STRV_FOREACH(i, paths)
+                (void) unlink(*i);
+
+        return strv_free(paths);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(char **, unlink_paths_and_free);
+
+static int pin_programs(Unit *u, CGroupContext *cc, const Test *test_suite, size_t test_suite_size, char ***paths_ret) {
+        _cleanup_(unlink_paths_and_freep) char **bpffs_paths = NULL;
+        static const struct bpf_insn trivial[] = {
+                BPF_MOV64_IMM(BPF_REG_0, 0),
+                BPF_EXIT_INSN()
+        };
+        char log_buf[0xffff];
+        int r;
+
+        assert_se(paths_ret);
+
+        for (size_t i = 0; i < test_suite_size; i++) {
+                _cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL;
+                _cleanup_free_ char *str = NULL;
+
+                r = bpf_foreign_test_to_string(test_suite[i].attach_type, test_suite[i].bpffs_path, &str);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to convert program to string");
+
+                r = bpf_program_new(test_suite[i].prog_type, &prog);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to create program '%s'", str);
+
+                r = bpf_program_add_instructions(prog, trivial, ELEMENTSOF(trivial));
+                if (r < 0)
+                        return log_error_errno(r, "Failed to add trivial instructions for '%s'", str);
+
+                r = bpf_program_load_kernel(prog, log_buf, ELEMENTSOF(log_buf));
+                if (r < 0)
+                        return log_error_errno(r, "Failed to load BPF program '%s'", str);
+
+                if (strv_contains(bpffs_paths, test_suite[i].bpffs_path))
+                        continue;
+
+                r = strv_extend(&bpffs_paths, test_suite[i].bpffs_path);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to put path into a vector: %m");
+
+                r = bpf_program_pin(prog->kernel_fd, test_suite[i].bpffs_path);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to pin BPF program '%s'", str);
+        }
+
+        *paths_ret = TAKE_PTR(bpffs_paths);
+        return 0;
+}
+
+static int test_bpf_cgroup_programs(Manager *m, const char *unit_name, const Test *test_suite, size_t test_suite_size) {
+        _cleanup_(unlink_paths_and_freep) char **bpffs_paths = NULL;
+        _cleanup_(unit_freep) Unit *u = NULL;
+        CGroupContext *cc = NULL;
+        int cld_code, r;
+
+        assert_se(u = unit_new(m, sizeof(Service)));
+        assert_se(unit_add_name(u, unit_name) == 0);
+        assert_se(cc = unit_get_cgroup_context(u));
+
+        r = pin_programs(u, cc, test_suite, test_suite_size, &bpffs_paths);
+        if (r < 0)
+                return log_error_errno(r, "Failed to pin programs: %m");
+
+        for (size_t i = 0; i < test_suite_size; i++) {
+                if (streq(test_suite[i].option_name, "BPFProgram")) {
+                        _cleanup_free_ char *option = NULL;
+                        r = bpf_foreign_test_to_string(test_suite[i].attach_type, test_suite[i].bpffs_path, &option);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to compose option string: %m");
+                        r = config_parse_bpf_foreign_program(
+                                        u->id, "filename", 1, "Service", 1, test_suite[i].option_name, 0, option, cc, u);
+
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse option string '%s': %m", option);
+                } else if (STR_IN_SET(test_suite[i].option_name, "IPIngressFilterPath", "IPEgressFilterPath")) {
+                        const char *option = test_suite[i].bpffs_path;
+                        void *paths = NULL;
+
+                        if (streq(test_suite[i].option_name, "IPIngressFilterPath"))
+                                paths = &cc->ip_filters_ingress;
+                        else
+                                paths = &cc->ip_filters_egress;
+
+                        r = config_parse_ip_filter_bpf_progs(
+                                        u->id, "filename", 1, "Service", 1, test_suite[i].option_name, 0, option, paths, u);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse option string '%s': %m", option);
+                }
+        }
+
+        r = config_parse_exec(
+                        u->id,
+                        "filename",
+                        1,
+                        "Service",
+                        1,
+                        "ExecStart",
+                        SERVICE_EXEC_START,
+                        "-/bin/ping -c 5 127.0.0.1 -W 1",
+                        SERVICE(u)->exec_command,
+                        u);
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse ExecStart");
+
+        SERVICE(u)->type = SERVICE_ONESHOT;
+        u->load_state = UNIT_LOADED;
+
+        r = unit_start(u);
+        if (r < 0)
+                return log_error_errno(r, "Unit start failed %m");
+
+        while (!IN_SET(SERVICE(u)->state, SERVICE_DEAD, SERVICE_FAILED)) {
+                r = sd_event_run(m->event, UINT64_MAX);
+                if (r < 0)
+                        return log_error_errno(errno, "Event run failed %m");
+        }
+
+        cld_code = SERVICE(u)->exec_command[SERVICE_EXEC_START]->exec_status.code;
+        if (cld_code != CLD_EXITED)
+                return log_error_errno(SYNTHETIC_ERRNO(EBUSY),
+                                "ExecStart didn't exited, code='%s'", sigchld_code_to_string(cld_code));
+
+        if (SERVICE(u)->state != SERVICE_DEAD)
+                return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Service is not dead");
+
+        return r;
+}
+
+int main(int argc, char *argv[]) {
+        _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
+        _cleanup_(manager_freep) Manager *m = NULL;
+        _cleanup_free_ char *unit_dir = NULL;
+        struct rlimit rl;
+        int r;
+
+        test_setup_logging(LOG_DEBUG);
+
+        if (detect_container() > 0)
+                return log_tests_skipped("test-bpf fails inside LXC and Docker containers: https://github.com/systemd/systemd/issues/9666");
+
+        if (getuid() != 0)
+                return log_tests_skipped("not running as root");
+
+        assert_se(getrlimit(RLIMIT_MEMLOCK, &rl) >= 0);
+        rl.rlim_cur = rl.rlim_max = MAX(rl.rlim_max, CAN_MEMLOCK_SIZE);
+        (void) setrlimit_closest(RLIMIT_MEMLOCK, &rl);
+
+        if (!can_memlock())
+                return log_tests_skipped("Can't use mlock(), skipping.");
+
+        r = cg_all_unified();
+        if (r <= 0)
+                return log_tests_skipped("Unified hierarchy is required, skipping.");
+
+        r = enter_cgroup_subroot(NULL);
+        if (r == -ENOMEDIUM)
+                return log_tests_skipped("cgroupfs not available");
+
+        assert_se(get_testdata_dir("units", &unit_dir) >= 0);
+        assert_se(set_unit_path(unit_dir) >= 0);
+        assert_se(runtime_dir = setup_fake_runtime_dir());
+
+        assert_se(manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m) >= 0);
+        assert_se(manager_startup(m, NULL, NULL) >= 0);
+
+        assert_se(test_bpf_cgroup_programs(m,
+                                "single_prog.service", single_prog, ELEMENTSOF(single_prog)) >= 0);
+        assert_se(test_bpf_cgroup_programs(m,
+                                "multi_prog_same_hook.service",
+                                multi_prog_same_hook, ELEMENTSOF(multi_prog_same_hook)) >= 0);
+        assert_se(test_bpf_cgroup_programs(m,
+                                "same_prog_multi_hook.service",
+                                same_prog_multi_hook, ELEMENTSOF(same_prog_multi_hook)) >= 0);
+        assert_se(test_bpf_cgroup_programs(m,
+                                "same_prog_multi_option_0.service",
+                                same_prog_multi_option_0, ELEMENTSOF(same_prog_multi_option_0)) >= 0);
+        assert_se(test_bpf_cgroup_programs(m,
+                                "same_prog_multi_option_1.service",
+                                same_prog_multi_option_1, ELEMENTSOF(same_prog_multi_option_1)) >= 0);
+        assert_se(test_bpf_cgroup_programs(m,
+                                "same_prog_same_hook.service",
+                                same_prog_same_hook,
+                                ELEMENTSOF(same_prog_same_hook)) >= 0);
+        assert_se(test_bpf_cgroup_programs(m,
+                                "path_split_test.service",
+                                path_split_test,
+                                ELEMENTSOF(path_split_test)) >= 0);
+        return 0;
+}
index 0ff56070b163fb25b4f1188641f826f135bbc25f..5fa8fe242ef4ee11f2cd8a6641dbcad65c7d3451 100644 (file)
@@ -103,22 +103,15 @@ static int setup_tests(bool *run_ambient) {
 
         nobody = getpwnam(NOBODY_USER_NAME);
         if (!nobody)
-                return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Could not find nobody user: %m");
+                return log_warning_errno(SYNTHETIC_ERRNO(ENOENT), "Couldn't find 'nobody' user: %m");
 
         test_uid = nobody->pw_uid;
         test_gid = nobody->pw_gid;
 
-        *run_ambient = false;
-
         r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
-
-        /* There's support for PR_CAP_AMBIENT if the prctl() call
-         * succeeded or error code was something else than EINVAL. The
-         * EINVAL check should be good enough to rule out false
-         * positives. */
-
-        if (r >= 0 || errno != EINVAL)
-                *run_ambient = true;
+        /* There's support for PR_CAP_AMBIENT if the prctl() call succeeded or error code was something else
+         * than EINVAL. The EINVAL check should be good enough to rule out false positives. */
+        *run_ambient = r >= 0 || errno != EINVAL;
 
         return 0;
 }
@@ -249,7 +242,7 @@ static void test_ensure_cap_64bit(void) {
 }
 
 int main(int argc, char *argv[]) {
-        bool run_ambient;
+        bool run_ambient = false;  /* avoid false maybe-uninitialized warning */
 
         test_setup_logging(LOG_INFO);
 
index b53e327c63d302e5d6937e5aaae073a0777e1ee8..3edc2754e1e697bc8ce78afdffff936de45fac3b 100644 (file)
@@ -140,7 +140,7 @@ static void test_cg_mask_to_string_one(CGroupMask mask, const char *t) {
 
 static void test_cg_mask_to_string(void) {
         test_cg_mask_to_string_one(0, NULL);
-        test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct cpuset io blkio memory devices pids bpf-firewall bpf-devices");
+        test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct cpuset io blkio memory devices pids bpf-firewall bpf-devices bpf-foreign bpf-socket-bind");
         test_cg_mask_to_string_one(CGROUP_MASK_CPU, "cpu");
         test_cg_mask_to_string_one(CGROUP_MASK_CPUACCT, "cpuacct");
         test_cg_mask_to_string_one(CGROUP_MASK_CPUSET, "cpuset");
index 4978a92e4632beb4652cc0eb0ea08ab01aecd8df..37ef66b0fd873b83342a7d325eafd70f3cac0af0 100644 (file)
@@ -3,13 +3,13 @@
 #include <unistd.h>
 
 #include "alloc-util.h"
-#include "build.h"
 #include "cgroup-setup.h"
 #include "errno-util.h"
 #include "log.h"
 #include "proc-cmdline.h"
 #include "string-util.h"
 #include "tests.h"
+#include "version.h"
 
 static void test_is_wanted_print(bool header) {
         _cleanup_free_ char *cmdline = NULL;
index f95832acf61582b1b5234dfcef49444a3f997693..c2adfa07ce02cc6eab869e36e254d014605ca15e 100644 (file)
@@ -1,7 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include "alloc-util.h"
-#include "build.h"
 #include "cgroup-util.h"
 #include "dirent-util.h"
 #include "errno-util.h"
@@ -17,6 +16,7 @@
 #include "tests.h"
 #include "user-util.h"
 #include "util.h"
+#include "version.h"
 
 static void check_p_d_u(const char *path, int code, const char *result) {
         _cleanup_free_ char *unit = NULL;
index db15fe3136ce64f45bcf49c7e3d53ff8181e8efa..adba383fddbc2556c0215406549984e07b4379df 100644 (file)
@@ -575,6 +575,7 @@ static void test_condition_test_virtualization(void) {
 
         NULSTR_FOREACH(virt,
                        "kvm\0"
+                       "amazon\0"
                        "qemu\0"
                        "bochs\0"
                        "xen\0"
index f1085266df23c80babb8b848b3a5e13656348a85..391968463f26df24369b6771d21b1df03855dbcd 100644 (file)
@@ -428,6 +428,20 @@ static void test_extract_first_word(void) {
         assert_se(streq(t, "c"));
         free(t);
         assert_se(p == NULL);
+
+        p = original = "foobar=\"waldo\"maldo, baldo";
+        assert_se(extract_first_word(&p, &t, "=\", ", 0) > 0);
+        assert_se(streq(t, "foobar"));
+        free(t);
+        assert_se(extract_first_word(&p, &t, "=\", ", 0) > 0);
+        assert_se(streq(t, "waldo"));
+        free(t);
+        assert_se(extract_first_word(&p, &t, "=\", ", 0) > 0);
+        assert_se(streq(t, "maldo"));
+        free(t);
+        assert_se(extract_first_word(&p, &t, "=\", ", 0) > 0);
+        assert_se(streq(t, "baldo"));
+        free(t);
 }
 
 static void test_extract_first_word_and_warn(void) {
index bf763d7dd322b1f2ff48bd59346e7ad7a3205e4c..51ae6652797eab99ecd82a76e301feb2fa54cfe0 100644 (file)
@@ -15,6 +15,7 @@
 #include "fs-util.h"
 #include "io-util.h"
 #include "parse-util.h"
+#include "path-util.h"
 #include "process-util.h"
 #include "random-util.h"
 #include "rm-rf.h"
@@ -539,73 +540,97 @@ static void test_load_env_file_pairs(void) {
 }
 
 static void test_search_and_fopen(void) {
-        const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
-
+        static const char* const dirs[] = {
+                "/tmp/foo/bar",
+                "/tmp",
+                NULL
+        };
         char name[] = "/tmp/test-search_and_fopen.XXXXXX";
-        int fd, r;
-        FILE *f;
+        _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_free_ char *p = NULL;
+        _cleanup_close_ int fd = -1;
+        const char *e;
+        int r;
 
         log_info("/* %s */", __func__);
 
         fd = mkostemp_safe(name);
         assert_se(fd >= 0);
-        close(fd);
+        fd = safe_close(fd);
 
-        r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
+        r = search_and_fopen(basename(name), "re", NULL, (const char**) dirs, &f, &p);
         assert_se(r >= 0);
-        fclose(f);
+        assert_se(e = path_startswith(p, "/tmp/"));
+        assert_se(streq(basename(name), e));
+        f = safe_fclose(f);
+        p = mfree(p);
 
-        r = search_and_fopen(name, "r", NULL, dirs, &f);
+        r = search_and_fopen(name, "re", NULL, (const char**) dirs, &f, &p);
         assert_se(r >= 0);
-        fclose(f);
+        assert_se(path_equal(name, p));
+        f = safe_fclose(f);
+        p = mfree(p);
 
-        r = search_and_fopen(basename(name), "r", "/", dirs, &f);
+        r = search_and_fopen(basename(name), "re", "/", (const char**) dirs, &f, &p);
         assert_se(r >= 0);
-        fclose(f);
+        assert_se(e = path_startswith(p, "/tmp/"));
+        assert_se(streq(basename(name), e));
+        f = safe_fclose(f);
+        p = mfree(p);
 
-        r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
-        assert_se(r < 0);
-        r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
-        assert_se(r < 0);
+        r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, (const char**) dirs, &f, &p);
+        assert_se(r == -ENOENT);
+        r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, (const char**) dirs, &f, &p);
+        assert_se(r == -ENOENT);
 
         r = unlink(name);
         assert_se(r == 0);
 
-        r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
-        assert_se(r < 0);
+        r = search_and_fopen(basename(name), "r", NULL, (const char**) dirs, &f, &p);
+        assert_se(r == -ENOENT);
 }
 
 static void test_search_and_fopen_nulstr(void) {
-        const char dirs[] = "/tmp/foo/bar\0/tmp\0";
+        static const char dirs[] =
+                "/tmp/foo/bar\0"
+                "/tmp\0";
 
         log_info("/* %s */", __func__);
 
         _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-search_and_fopen.XXXXXX";
-        int fd, r;
-        FILE *f;
+        _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_free_ char *p = NULL;
+        _cleanup_close_ int fd = -1;
+        const char *e;
+        int r;
 
         fd = mkostemp_safe(name);
         assert_se(fd >= 0);
-        close(fd);
+        fd = safe_close(fd);
 
-        r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
+        r = search_and_fopen_nulstr(basename(name), "re", NULL, dirs, &f, &p);
         assert_se(r >= 0);
-        fclose(f);
+        assert_se(e = path_startswith(p, "/tmp/"));
+        assert_se(streq(basename(name), e));
+        f = safe_fclose(f);
+        p = mfree(p);
 
-        r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
+        r = search_and_fopen_nulstr(name, "re", NULL, dirs, &f, &p);
         assert_se(r >= 0);
-        fclose(f);
+        assert_se(path_equal(name, p));
+        f = safe_fclose(f);
+        p = mfree(p);
 
-        r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
-        assert_se(r < 0);
-        r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
-        assert_se(r < 0);
+        r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f, &p);
+        assert_se(r == -ENOENT);
+        r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f, &p);
+        assert_se(r == -ENOENT);
 
         r = unlink(name);
         assert_se(r == 0);
 
-        r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
-        assert_se(r < 0);
+        r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f, &p);
+        assert_se(r == -ENOENT);
 }
 
 static void test_writing_tmpfile(void) {
index dfde01a678899a4fc3b22a68afb0c51cce5df99a..d2843cfab73da20a52234a7f98f53e327f9efad8 100644 (file)
@@ -61,6 +61,13 @@ static bool test_v4(FirewallContext *ctx) {
 
         log_info("/* %s(backend=%s) */", __func__, firewall_backend_to_string(ctx->backend));
 
+#if HAVE_LIBIPTC
+        if (ctx->backend == FW_BACKEND_IPTABLES && fw_iptables_init_nat(NULL) < 0) {
+                log_debug("iptables backend is used, but nat table is not enabled, skipping tests");
+                return false;
+        }
+#endif
+
         assert_se(fw_add_masquerade(&ctx, true, AF_INET, NULL, 0) == -EINVAL);
         assert_se(fw_add_masquerade(&ctx, true, AF_INET, parse_addr("10.1.2.0", &u), 0) == -EINVAL);
 
index a0649b9deb08a453d1ea4b27fe188056eab86fd9..a61b35b9a3367a9fd071463fb655f19bc83e80ed 100644 (file)
@@ -31,6 +31,13 @@ int main(int argc, char *argv[]) {
 
         assert_se(sd_id128_from_string(t, &id2) == 0);
         assert_se(sd_id128_equal(id, id2));
+        assert_se(sd_id128_in_set(id, id));
+        assert_se(sd_id128_in_set(id, id2));
+        assert_se(sd_id128_in_set(id, id2, id));
+        assert_se(sd_id128_in_set(id, ID128_WALDI, id));
+        assert_se(!sd_id128_in_set(id));
+        assert_se(!sd_id128_in_set(id, ID128_WALDI));
+        assert_se(!sd_id128_in_set(id, ID128_WALDI, ID128_WALDI));
 
         if (sd_booted() > 0) {
                 assert_se(sd_id128_get_machine(&id) == 0);
index bea196c0cecc2ca10b4c7b0750fb4e19f05944ee..50ed23a4ee3eaa9ab4a8b71e8c6d87ad47e65b92 100644 (file)
@@ -25,6 +25,7 @@ static void test_basic_mask_and_enable(const char *root) {
         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT);
         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT);
         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", NULL) == -ENOENT);
+        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "f.service", NULL) == -ENOENT);
 
         p = strjoina(root, "/usr/lib/systemd/system/a.service");
         assert_se(write_string_file(p,
@@ -168,6 +169,31 @@ static void test_basic_mask_and_enable(const char *root) {
         assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", &state) >= 0 && state == UNIT_FILE_MASKED);
 
         assert_se(unlink(p) == 0);
+
+        /* Test enabling with unknown dependency target */
+
+        p = strjoina(root, "/usr/lib/systemd/system/f.service");
+        assert_se(write_string_file(p,
+                                    "[Install]\n"
+                                    "WantedBy=x.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "f.service", NULL) >= 0);
+        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "f.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+        assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("f.service"), &changes, &n_changes) == 1);
+        assert_se(n_changes == 2);
+        assert_se(changes[0].type_or_errno == UNIT_FILE_SYMLINK);
+        assert_se(streq(changes[0].source, "/usr/lib/systemd/system/f.service"));
+        p = strjoina(root, SYSTEM_CONFIG_UNIT_DIR"/x.target.wants/f.service");
+        assert_se(streq(changes[0].path, p));
+        assert_se(changes[1].type_or_errno == UNIT_FILE_DESTINATION_NOT_PRESENT);
+        p = strjoina(root, "/usr/lib/systemd/system/f.service");
+        assert_se(streq(changes[1].source, p));
+        assert_se(streq(changes[1].path, "x.target"));
+        unit_file_changes_free(changes, n_changes);
+        changes = NULL; n_changes = 0;
+
+        assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "f.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
 }
 
 static void test_linked_units(const char *root) {
@@ -1244,6 +1270,12 @@ int main(int argc, char *argv[]) {
         p = strjoina(root, "/usr/lib/systemd/system-preset/");
         assert_se(mkdir_p(p, 0755) >= 0);
 
+        p = strjoina(root, "/usr/lib/systemd/system/multi-user.target");
+        assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
+
+        p = strjoina(root, "/usr/lib/systemd/system/graphical.target");
+        assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
+
         test_basic_mask_and_enable(root);
         test_linked_units(root);
         test_default(root);
index 7eeddd28f44e418b8ffe24d8fe8abbaa86ff7828..7b75132e1826febc9b5874993362c45ebc5e2a9d 100644 (file)
@@ -40,5 +40,12 @@ int main(int argc, char *argv[]) {
         print_local_addresses(a, (unsigned) n);
         free(a);
 
+        n = local_outbounds(NULL, 0, AF_UNSPEC, &a);
+        assert_se(n >= 0);
+
+        printf("Local Outbounds:\n");
+        print_local_addresses(a, (unsigned) n);
+        free(a);
+
         return 0;
 }
index 93f2da70e77502537f28fbf8efc9e1c9c927129c..ba44b5f3f91829506accff80c11374b2a4fc8053 100644 (file)
@@ -51,7 +51,7 @@ static void* thread_func(void *ptr) {
 
                 log_notice("Acquired loop device %s, will mount on %s", loop->node, mounted);
 
-                r = dissect_image(loop->fd, NULL, NULL, DISSECT_IMAGE_READ_ONLY, &dissected);
+                r = dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, loop->timestamp_not_before, DISSECT_IMAGE_READ_ONLY, &dissected);
                 if (r < 0)
                         log_error_errno(r, "Failed dissect loopback device %s: %m", loop->node);
                 assert_se(r >= 0);
@@ -188,7 +188,7 @@ int main(int argc, char *argv[]) {
         sfdisk = NULL;
 
         assert_se(loop_device_make(fd, O_RDWR, 0, UINT64_MAX, LO_FLAGS_PARTSCAN, &loop) >= 0);
-        assert_se(dissect_image(loop->fd, NULL, NULL, 0, &dissected) >= 0);
+        assert_se(dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, loop->timestamp_not_before, 0, &dissected) >= 0);
 
         assert_se(dissected->partitions[PARTITION_ESP].found);
         assert_se(dissected->partitions[PARTITION_ESP].node);
@@ -212,7 +212,7 @@ int main(int argc, char *argv[]) {
         assert_se(make_filesystem(dissected->partitions[PARTITION_HOME].node, "ext4", "home", id, true) >= 0);
 
         dissected = dissected_image_unref(dissected);
-        assert_se(dissect_image(loop->fd, NULL, NULL, 0, &dissected) >= 0);
+        assert_se(dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, loop->timestamp_not_before, 0, &dissected) >= 0);
 
         assert_se(mkdtemp_malloc(NULL, &mounted) >= 0);
 
index 41df5588d082948a11a15a1951c1fa6a6ba8bcbc..2e9116d359dbeb9306f99a75a844541dd70d5753 100644 (file)
@@ -1,11 +1,20 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <sys/mount.h>
+#include <sys/statvfs.h>
 
 #include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
 #include "mount-util.h"
+#include "namespace-util.h"
+#include "path-util.h"
+#include "process-util.h"
+#include "rm-rf.h"
 #include "string-util.h"
+#include "strv.h"
 #include "tests.h"
+#include "tmpfile-util.h"
 
 static void test_mount_option_mangle(void) {
         char *opts = NULL;
@@ -61,10 +70,98 @@ static void test_mount_option_mangle(void) {
         assert_se(mount_option_mangle("rw,relatime,fmask=0022,dmask=0022,\"hogehoge", MS_RDONLY, &f, &opts) < 0);
 }
 
+static void test_bind_remount_recursive(void) {
+        _cleanup_(rm_rf_physical_and_freep) char *tmp = NULL;
+        _cleanup_free_ char *subdir = NULL;
+        const char *p;
+
+        if (geteuid() != 0) {
+                (void) log_tests_skipped("not running as root");
+                return;
+        }
+
+        assert_se(mkdtemp_malloc("/tmp/XXXXXX", &tmp) >= 0);
+        subdir = path_join(tmp, "subdir");
+        assert_se(subdir);
+        assert_se(mkdir(subdir, 0755) >= 0);
+
+        FOREACH_STRING(p, "/usr", "/sys", "/", tmp) {
+                pid_t pid;
+
+                pid = fork();
+                assert_se(pid >= 0);
+
+                if (pid == 0) {
+                        struct statvfs svfs;
+                        /* child */
+                        assert_se(detach_mount_namespace() >= 0);
+
+                        /* Check that the subdir is writable (it must be because it's in /tmp) */
+                        assert_se(statvfs(subdir, &svfs) >= 0);
+                        assert_se(!FLAGS_SET(svfs.f_flag, ST_RDONLY));
+
+                        /* Make the subdir a bind mount */
+                        assert_se(mount_nofollow(subdir, subdir, NULL, MS_BIND|MS_REC, NULL) >= 0);
+
+                        /* Ensure it's still writable */
+                        assert_se(statvfs(subdir, &svfs) >= 0);
+                        assert_se(!FLAGS_SET(svfs.f_flag, ST_RDONLY));
+
+                        /* Now mark the path we currently run for read-only */
+                        assert_se(bind_remount_recursive(p, MS_RDONLY, MS_RDONLY, STRV_MAKE("/sys/kernel")) >= 0);
+
+                        /* Ensure that this worked on the top-level */
+                        assert_se(statvfs(p, &svfs) >= 0);
+                        assert_se(FLAGS_SET(svfs.f_flag, ST_RDONLY));
+
+                        /* And ensure this had an effect on the subdir exactly if we are talking about a path above the subdir */
+                        assert_se(statvfs(subdir, &svfs) >= 0);
+                        assert_se(FLAGS_SET(svfs.f_flag, ST_RDONLY) == !!path_startswith(subdir, p));
+
+                        _exit(EXIT_SUCCESS);
+                }
+
+                assert_se(wait_for_terminate_and_check("test-remount-rec", pid, WAIT_LOG) == EXIT_SUCCESS);
+        }
+}
+
+static void test_bind_remount_one(void) {
+        pid_t pid;
+
+        if (geteuid() != 0) {
+                (void) log_tests_skipped("not running as root");
+                return;
+        }
+
+        pid = fork();
+        assert_se(pid >= 0);
+
+        if (pid == 0) {
+                /* child */
+
+                _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
+
+                assert_se(detach_mount_namespace() >= 0);
+
+                assert_se(fopen_unlocked("/proc/self/mountinfo", "re", &proc_self_mountinfo) >= 0);
+
+                assert_se(bind_remount_one_with_mountinfo("/run", MS_RDONLY, MS_RDONLY, proc_self_mountinfo) >= 0);
+                assert_se(bind_remount_one_with_mountinfo("/proc/idontexist", MS_RDONLY, MS_RDONLY, proc_self_mountinfo) == -ENOENT);
+                assert_se(bind_remount_one_with_mountinfo("/proc/self", MS_RDONLY, MS_RDONLY, proc_self_mountinfo) == -EINVAL);
+                assert_se(bind_remount_one_with_mountinfo("/", MS_RDONLY, MS_RDONLY, proc_self_mountinfo) >= 0);
+
+                _exit(EXIT_SUCCESS);
+        }
+
+        assert_se(wait_for_terminate_and_check("test-remount-one", pid, WAIT_LOG) == EXIT_SUCCESS);
+}
+
 int main(int argc, char *argv[]) {
         test_setup_logging(LOG_DEBUG);
 
         test_mount_option_mangle();
+        test_bind_remount_recursive();
+        test_bind_remount_one();
 
         return 0;
 }
index bf4b87e8a678d72d4d89826fa18b9155f28c8cf5..cfa46b00b5beff48a4072370740436e6563b49bf 100644 (file)
@@ -147,7 +147,6 @@ static void test_protect_kernel_logs(void) {
                 return;
         }
 
-
         pid = fork();
         assert_se(pid >= 0);
 
@@ -187,7 +186,6 @@ static void test_protect_kernel_logs(void) {
                                     NULL,
                                     NULL,
                                     NULL,
-                                    0,
                                     NULL);
                 assert_se(r == 0);
 
index 761ee5da866d5dc8c9eaa064bd89c5316b5282c0..ae666a3019a9aedd4dff7336719257b62211b75a 100644 (file)
@@ -107,7 +107,6 @@ int main(int argc, char *argv[]) {
                             NULL,
                             NULL,
                             NULL,
-                            0,
                             NULL);
         if (r < 0) {
                 log_error_errno(r, "Failed to set up namespace: %m");
similarity index 87%
rename from src/test/test-nss.c
rename to src/test/test-nss-hosts.c
index 2e9414d16d54eea127f5baf5dd34a743bc3f65f7..42ed53adc35b70bb13d8e0f71cd758ef2dae6682 100644 (file)
@@ -1,12 +1,12 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
-#include <dlfcn.h>
 #include <net/if.h>
 #include <stdlib.h>
 #include <unistd.h>
 
 #include "af-list.h"
 #include "alloc-util.h"
+#include "dlfcn-util.h"
 #include "errno-list.h"
 #include "format-util.h"
 #include "hexdecoct.h"
 #include "local-addresses.h"
 #include "log.h"
 #include "main-func.h"
+#include "nss-test-util.h"
 #include "nss-util.h"
+#include "parse-util.h"
 #include "path-util.h"
 #include "stdio-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "tests.h"
 
-static const char* nss_status_to_string(enum nss_status status, char *buf, size_t buf_len) {
-        switch (status) {
-        case NSS_STATUS_TRYAGAIN:
-                return "NSS_STATUS_TRYAGAIN";
-        case NSS_STATUS_UNAVAIL:
-                return "NSS_STATUS_UNAVAIL";
-        case NSS_STATUS_NOTFOUND:
-                return "NSS_STATUS_NOTFOUND";
-        case NSS_STATUS_SUCCESS:
-                return "NSS_STATUS_SUCCESS";
-        case NSS_STATUS_RETURN:
-                return "NSS_STATUS_RETURN";
-        default:
-                snprintf(buf, buf_len, "%i", status);
-                return buf;
-        }
-};
+static size_t arg_bufsize = 1024;
 
 static const char* af_to_string(int family, char *buf, size_t buf_len) {
         const char *name;
@@ -54,22 +40,6 @@ static const char* af_to_string(int family, char *buf, size_t buf_len) {
         return buf;
 }
 
-static void* open_handle(const char *dir, const char *module, int flags) {
-        const char *path = NULL;
-        void *handle;
-
-        if (dir)
-                path = strjoina(dir, "/libnss_", module, ".so.2");
-        if (!path || access(path, F_OK) < 0)
-                path = strjoina("libnss_", module, ".so.2");
-
-        log_debug("Using %s", path);
-        handle = dlopen(path, flags);
-        if (!handle)
-                log_error("Failed to load module %s: %s", module, dlerror());
-        return handle;
-}
-
 static int print_gaih_addrtuples(const struct gaih_addrtuple *tuples) {
         int n = 0;
 
@@ -132,7 +102,7 @@ static void print_struct_hostent(struct hostent *host, const char *canon) {
 static void test_gethostbyname4_r(void *handle, const char *module, const char *name) {
         const char *fname;
         _nss_gethostbyname4_r_t f;
-        char buffer[2000];
+        char buffer[arg_bufsize];
         struct gaih_addrtuple *pat = NULL;
         int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */
         int32_t ttl = INT32_MAX; /* nss-dns wants to return the lowest ttl,
@@ -184,7 +154,7 @@ 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;
-        char buffer[2000];
+        char buffer[arg_bufsize];
         int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */
         int32_t ttl = INT32_MAX; /* nss-dns wants to return the lowest ttl,
                                     and will access this variable through *ttlp,
@@ -219,7 +189,7 @@ static void test_gethostbyname3_r(void *handle, const char *module, const char *
 static void test_gethostbyname2_r(void *handle, const char *module, const char *name, int af) {
         const char *fname;
         _nss_gethostbyname2_r_t f;
-        char buffer[2000];
+        char buffer[arg_bufsize];
         int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */
         enum nss_status status;
         char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
@@ -247,7 +217,7 @@ static void test_gethostbyname2_r(void *handle, const char *module, const char *
 static void test_gethostbyname_r(void *handle, const char *module, const char *name) {
         const char *fname;
         _nss_gethostbyname_r_t f;
-        char buffer[2000];
+        char buffer[arg_bufsize];
         int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */
         enum nss_status status;
         char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
@@ -278,7 +248,7 @@ static void test_gethostbyaddr2_r(void *handle,
 
         const char *fname;
         _nss_gethostbyaddr2_r_t f;
-        char buffer[2000];
+        char buffer[arg_bufsize];
         int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */
         enum nss_status status;
         char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
@@ -316,7 +286,7 @@ static void test_gethostbyaddr_r(void *handle,
 
         const char *fname;
         _nss_gethostbyaddr_r_t f;
-        char buffer[2000];
+        char buffer[arg_bufsize];
         int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */
         enum nss_status status;
         char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
@@ -392,8 +362,7 @@ static int make_addresses(struct local_address **addresses) {
                 log_info_errno(n, "Failed to query local addresses: %m");
 
         n_alloc = n; /* we _can_ do that */
-        if (!GREEDY_REALLOC(addrs, n_alloc, n + 3))
-                return log_oom();
+        assert_se(GREEDY_REALLOC(addrs, n_alloc, n + 3));
 
         addrs[n++] = (struct local_address) { .family = AF_INET,
                                               .address.in = { htobe32(0x7F000001) } };
@@ -409,15 +378,14 @@ static int test_one_module(const char *dir,
                            char **names,
                            struct local_address *addresses,
                            int n_addresses) {
-        void *handle;
-        char **name;
 
         log_info("======== %s ========", module);
 
-        handle = open_handle(dir, module, RTLD_LAZY|RTLD_NODELETE);
+        _cleanup_(dlclosep) void *handle = nss_open_handle(dir, module, RTLD_LAZY|RTLD_NODELETE);
         if (!handle)
                 return -EINVAL;
 
+        char **name;
         STRV_FOREACH(name, names)
                 test_byname(handle, module, *name);
 
@@ -428,7 +396,6 @@ static int test_one_module(const char *dir,
                             addresses[i].family);
 
         log_info(" ");
-        dlclose(handle);
         return 0;
 }
 
@@ -437,10 +404,18 @@ static int parse_argv(int argc, char **argv,
                       char ***the_names,
                       struct local_address **the_addresses, int *n_addresses) {
 
-        int r, n = 0;
         _cleanup_strv_free_ char **modules = NULL, **names = NULL;
         _cleanup_free_ struct local_address *addrs = NULL;
         size_t n_allocated = 0;
+        const char *p;
+        int r, n = 0;
+
+        p = getenv("SYSTEMD_TEST_NSS_BUFSIZE");
+        if (p) {
+                r = safe_atozu(p, &arg_bufsize);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse $SYSTEMD_TEST_NSS_BUFSIZE");
+        }
 
         if (argc > 1)
                 modules = strv_new(argv[1]);
@@ -456,8 +431,7 @@ static int parse_argv(int argc, char **argv,
                                 "mymachines",
 #endif
                                 "dns");
-        if (!modules)
-                return -ENOMEM;
+        assert_se(modules);
 
         if (argc > 2) {
                 char **name;
@@ -472,8 +446,7 @@ static int parse_argv(int argc, char **argv,
                                 if (r < 0)
                                         return r;
                         } else {
-                                if (!GREEDY_REALLOC0(addrs, n_allocated, n + 1))
-                                        return -ENOMEM;
+                                assert_se(GREEDY_REALLOC0(addrs, n_allocated, n + 1));
 
                                 addrs[n++] = (struct local_address) { .family = family,
                                                                       .address = address };
@@ -481,26 +454,17 @@ static int parse_argv(int argc, char **argv,
                 }
         } else {
                 _cleanup_free_ char *hostname;
-
-                hostname = gethostname_malloc();
-                if (!hostname)
-                        return -ENOMEM;
-
-                names = strv_new("localhost", "_gateway", "foo_no_such_host", hostname);
-                if (!names)
-                        return -ENOMEM;
+                assert_se(hostname = gethostname_malloc());
+                assert_se(names = strv_new("localhost", "_gateway", "_outbound", "foo_no_such_host", hostname));
 
                 n = make_addresses(&addrs);
-                if (n < 0)
-                        return n;
+                assert_se(n >= 0);
         }
 
-        *the_modules = modules;
-        *the_names = names;
-        modules = names = NULL;
-        *the_addresses = addrs;
+        *the_modules = TAKE_PTR(modules);
+        *the_names = TAKE_PTR(names);
+        *the_addresses = TAKE_PTR(addrs);
         *n_addresses = n;
-        addrs = NULL;
         return 0;
 }
 
@@ -515,14 +479,10 @@ static int run(int argc, char **argv) {
         test_setup_logging(LOG_INFO);
 
         r = parse_argv(argc, argv, &modules, &names, &addresses, &n_addresses);
-        if (r < 0) {
-                log_error_errno(r, "Failed to parse arguments: %m");
-                return EXIT_FAILURE;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse arguments: %m");
 
-        dir = dirname_malloc(argv[0]);
-        if (!dir)
-                return log_oom();
+        assert_se(path_extract_directory(argv[0], &dir) >= 0);
 
         STRV_FOREACH(module, modules) {
                 r = test_one_module(dir, *module, names, addresses, n_addresses);
diff --git a/src/test/test-nss-users.c b/src/test/test-nss-users.c
new file mode 100644 (file)
index 0000000..c415c0c
--- /dev/null
@@ -0,0 +1,258 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <pwd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "dlfcn-util.h"
+#include "errno-list.h"
+#include "format-util.h"
+#include "log.h"
+#include "main-func.h"
+#include "nss-test-util.h"
+#include "nss-util.h"
+#include "path-util.h"
+#include "parse-util.h"
+#include "stdio-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "tests.h"
+#include "user-util.h"
+
+static size_t arg_bufsize = 1024;
+
+static void print_struct_passwd(const struct passwd *pwd) {
+        log_info("        \"%s\" / "UID_FMT":"GID_FMT,
+                 pwd->pw_name, pwd->pw_uid, pwd->pw_gid);
+        log_info("        passwd=\"%s\"", pwd->pw_passwd);
+        log_info("        gecos=\"%s\"", pwd->pw_gecos);
+        log_info("        dir=\"%s\"", pwd->pw_dir);
+        log_info("        shell=\"%s\"", pwd->pw_shell);
+}
+
+static void print_struct_group(const struct group *gr) {
+        _cleanup_free_ char *members = NULL;
+
+        log_info("        \"%s\" / "GID_FMT,
+                 gr->gr_name, gr->gr_gid);
+        log_info("        passwd=\"%s\"", gr->gr_passwd);
+
+        assert_se(members = strv_join(gr->gr_mem, ", "));
+        // FIXME: use shell_maybe_quote(SHELL_ESCAPE_EMPTY) when it becomes available
+        log_info("        members=%s", members);
+}
+
+static void test_getpwnam_r(void *handle, const char *module, const char *name) {
+        const char *fname;
+        _nss_getpwnam_r_t f;
+        char buffer[arg_bufsize];
+        int errno1 = 999; /* nss-dns doesn't set those */
+        enum nss_status status;
+        char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
+        struct passwd pwd;
+
+        fname = strjoina("_nss_", module, "_getpwnam_r");
+        f = dlsym(handle, fname);
+        log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f);
+        if (!f) {
+                log_info("%s not defined", fname);
+                return;
+        }
+
+        status = f(name, &pwd, buffer, sizeof buffer, &errno1);
+        log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s",
+                 fname, name,
+                 nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n",
+                 errno1, errno_to_name(errno1) ?: "---");
+        if (status == NSS_STATUS_SUCCESS)
+                print_struct_passwd(&pwd);
+}
+
+static void test_getgrnam_r(void *handle, const char *module, const char *name) {
+        const char *fname;
+        _nss_getgrnam_r_t f;
+        char buffer[arg_bufsize];
+        int errno1 = 999; /* nss-dns doesn't set those */
+        enum nss_status status;
+        char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
+        struct group gr;
+
+        fname = strjoina("_nss_", module, "_getgrnam_r");
+        f = dlsym(handle, fname);
+        log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f);
+        if (!f) {
+                log_info("%s not defined", fname);
+                return;
+        }
+
+        status = f(name, &gr, buffer, sizeof buffer, &errno1);
+        log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s",
+                 fname, name,
+                 nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n",
+                 errno1, errno_to_name(errno1) ?: "---");
+        if (status == NSS_STATUS_SUCCESS)
+                print_struct_group(&gr);
+}
+
+static void test_getpwuid_r(void *handle, const char *module, uid_t uid) {
+        const char *fname;
+        _nss_getpwuid_r_t f;
+        char buffer[arg_bufsize];
+        int errno1 = 999; /* nss-dns doesn't set those */
+        enum nss_status status;
+        char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
+        struct passwd pwd;
+
+        fname = strjoina("_nss_", module, "_getpwuid_r");
+        f = dlsym(handle, fname);
+        log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f);
+        if (!f) {
+                log_info("%s not defined", fname);
+                return;
+        }
+
+        status = f(uid, &pwd, buffer, sizeof buffer, &errno1);
+        log_info("%s("UID_FMT") → status=%s%-20serrno=%d/%s",
+                 fname, uid,
+                 nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n",
+                 errno1, errno_to_name(errno1) ?: "---");
+        if (status == NSS_STATUS_SUCCESS)
+                print_struct_passwd(&pwd);
+}
+
+static void test_getgrgid_r(void *handle, const char *module, gid_t gid) {
+        const char *fname;
+        _nss_getgrgid_r_t f;
+        char buffer[arg_bufsize];
+        int errno1 = 999; /* nss-dns doesn't set those */
+        enum nss_status status;
+        char pretty_status[DECIMAL_STR_MAX(enum nss_status)];
+        struct group gr;
+
+        fname = strjoina("_nss_", module, "_getgrgid_r");
+        f = dlsym(handle, fname);
+        log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f);
+        if (!f) {
+                log_info("%s not defined", fname);
+                return;
+        }
+
+        status = f(gid, &gr, buffer, sizeof buffer, &errno1);
+        log_info("%s("GID_FMT") → status=%s%-20serrno=%d/%s",
+                 fname, gid,
+                 nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n",
+                 errno1, errno_to_name(errno1) ?: "---");
+        if (status == NSS_STATUS_SUCCESS)
+                print_struct_group(&gr);
+}
+
+static void test_byname(void *handle, const char *module, const char *name) {
+        test_getpwnam_r(handle, module, name);
+        test_getgrnam_r(handle, module, name);
+        puts("");
+}
+
+static void test_byuid(void *handle, const char *module, uid_t uid) {
+        test_getpwuid_r(handle, module, uid);
+        test_getgrgid_r(handle, module, uid);
+        puts("");
+}
+
+static int test_one_module(const char *dir,
+                           const char *module,
+                           char **names) {
+
+        log_info("======== %s ========", module);
+
+        _cleanup_(dlclosep) void *handle = nss_open_handle(dir, module, RTLD_LAZY|RTLD_NODELETE);
+        if (!handle)
+                return -EINVAL;
+
+        char **name;
+        STRV_FOREACH(name, names)
+                test_byname(handle, module, *name);
+
+        STRV_FOREACH(name, names) {
+                uid_t uid;
+
+                assert_cc(sizeof(uid_t) == sizeof(uint32_t));
+                /* We use safe_atou32 because we don't want to refuse invalid uids. */
+                if (safe_atou32(*name, &uid) < 0)
+                        continue;
+
+                test_byuid(handle, module, uid);
+        }
+
+        log_info(" ");
+        return 0;
+}
+
+static int parse_argv(int argc, char **argv,
+                      char ***the_modules,
+                      char ***the_names) {
+
+        _cleanup_strv_free_ char **modules = NULL, **names = NULL;
+        const char *p;
+        int r;
+
+        p = getenv("SYSTEMD_TEST_NSS_BUFSIZE");
+        if (p) {
+                r = safe_atozu(p, &arg_bufsize);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse $SYSTEMD_TEST_NSS_BUFSIZE");
+        }
+
+        if (argc > 1)
+                modules = strv_new(argv[1]);
+        else
+                modules = strv_new(
+#if ENABLE_NSS_SYSTEMD
+                                "systemd",
+#endif
+#if ENABLE_NSS_MYMACHINES
+                                "mymachines",
+#endif
+                                "files");
+        assert_se(modules);
+
+        if (argc > 2)
+                names = strv_copy(strv_skip(argv, 2));
+        else
+                names = strv_new("root",
+                                 NOBODY_USER_NAME,
+                                 "foo_no_such_user",
+                                 "0",
+                                 "65534");
+        assert_se(names);
+
+        *the_modules = TAKE_PTR(modules);
+        *the_names = TAKE_PTR(names);
+        return 0;
+}
+
+static int run(int argc, char **argv) {
+        _cleanup_free_ char *dir = NULL;
+        _cleanup_strv_free_ char **modules = NULL, **names = NULL;
+        char **module;
+        int r;
+
+        test_setup_logging(LOG_INFO);
+
+        r = parse_argv(argc, argv, &modules, &names);
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse arguments: %m");
+
+        assert_se(path_extract_directory(argv[0], &dir) >= 0);
+
+        STRV_FOREACH(module, modules) {
+                r = test_one_module(dir, *module, names);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+DEFINE_MAIN_FUNCTION(run);
index 0fbdd9706f69590d3e8d9cad74fe38f73d4df28b..8d3c5b0d8c71ecab3b30d0d1c3db0147b572d0f8 100644 (file)
@@ -95,31 +95,20 @@ static void test_set_put(void) {
 }
 
 static void test_set_put_string_set(void) {
-        _cleanup_ordered_set_free_free_ OrderedSet *m = NULL;
-        _cleanup_ordered_set_free_ OrderedSet *q = NULL;
+        _cleanup_ordered_set_free_ OrderedSet *m = NULL, *q = NULL;
         _cleanup_free_ char **final = NULL; /* "just free" because the strings are in the set */
-        void *t;
 
         log_info("/* %s */", __func__);
 
-        m = ordered_set_new(&string_hash_ops);
-        assert_se(m);
-
-        q = ordered_set_new(&string_hash_ops);
-        assert_se(q);
-
-        assert_se(t = strdup("1"));
-        assert_se(ordered_set_put(m, t) == 1);
-        assert_se(t = strdup("22"));
-        assert_se(ordered_set_put(m, t) == 1);
-        assert_se(t = strdup("333"));
-        assert_se(ordered_set_put(m, t) == 1);
+        assert_se(ordered_set_put_strdup(&m, "1") == 1);
+        assert_se(ordered_set_put_strdup(&m, "22") == 1);
+        assert_se(ordered_set_put_strdup(&m, "333") == 1);
 
-        assert_se(ordered_set_put(q, (void*) "11") == 1);
-        assert_se(ordered_set_put(q, (void*) "22") == 1);
-        assert_se(ordered_set_put(q, (void*) "33") == 1);
+        assert_se(ordered_set_put_strdup(&q, "11") == 1);
+        assert_se(ordered_set_put_strdup(&q, "22") == 1);
+        assert_se(ordered_set_put_strdup(&q, "33") == 1);
 
-        assert_se(ordered_set_put_string_set(m, q) == 2);
+        assert_se(ordered_set_put_string_set(&m, q) == 2);
 
         assert_se(final = ordered_set_get_strv(m));
         assert_se(strv_equal(final, STRV_MAKE("1", "22", "333", "11", "33")));
index b49b0ae9081691cdcfb559e1bdd32e4ad0d93c14..1572483602c38dfcf21074b1964213b90f954deb 100644 (file)
@@ -113,6 +113,11 @@ static void test_path(void) {
         assert_se(!path_equal_ptr("/a", "/b"));
         assert_se(!path_equal_ptr("/a", NULL));
         assert_se(!path_equal_ptr(NULL, "/a"));
+
+        assert_se(path_equal_filename("/a/c", "/b/c"));
+        assert_se(path_equal_filename("/a", "/a"));
+        assert_se(!path_equal_filename("/a/b", "/a/c"));
+        assert_se(!path_equal_filename("/b", "/c"));
 }
 
 static void test_path_equal_root(void) {
index 44103efa62a24a6fd3eb45486b68bf75b491c037..42d7a746da6965a13a8f1e589f107dae4c3a56f9 100644 (file)
@@ -68,7 +68,6 @@ static void test_random_u64_range_one(unsigned mod) {
 
                 x = random_u64_range(mod);
 
-                log_trace("%05u: %"PRIu64, i, x);
                 count[x]++;
                 max = MAX(max, count[x]);
         }
index d141735320a2f3a169b1a9a94f5610ea8c48656a..5262947c087e450202ebd73756f8231ccee0be5f 100644 (file)
@@ -9,6 +9,7 @@
 #endif
 
 #include "fd-util.h"
+#include "fs-util.h"
 #include "memory-util.h"
 #include "sigbus.h"
 #include "tests.h"
@@ -35,7 +36,7 @@ int main(int argc, char *argv[]) {
 
         assert_se((fd = mkostemp(template, O_RDWR|O_CREAT|O_EXCL)) >= 0);
         assert_se(unlink(template) >= 0);
-        assert_se(posix_fallocate(fd, 0, page_size() * 8) >= 0);
+        assert_se(posix_fallocate_loop(fd, 0, page_size() * 8) >= 0);
 
         p = mmap(NULL, page_size() * 16, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
         assert_se(p != MAP_FAILED);
diff --git a/src/test/test-socket-bind.c b/src/test/test-socket-bind.c
new file mode 100644 (file)
index 0000000..bfe5072
--- /dev/null
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "load-fragment.h"
+#include "manager.h"
+#include "process-util.h"
+#include "rlimit-util.h"
+#include "rm-rf.h"
+#include "service.h"
+#include "socket-bind.h"
+#include "strv.h"
+#include "tests.h"
+#include "unit.h"
+#include "virt.h"
+
+static int find_netcat_executable(char **ret_path) {
+        char **candidates = STRV_MAKE("ncat", "nc", "netcat"), **c;
+        int r = 0;
+
+        STRV_FOREACH(c, candidates) {
+                r = find_executable(*c, ret_path);
+                if (r == 0)
+                        break;
+        }
+
+        return r;
+}
+
+static int test_socket_bind(
+                Manager *m,
+                const char *unit_name,
+                const char *netcat_path,
+                const char *port,
+                char **allow_rules,
+                char **deny_rules) {
+        _cleanup_free_ char *exec_start = NULL;
+        _cleanup_(unit_freep) Unit *u = NULL;
+        CGroupSocketBindItem *bi;
+        CGroupContext *cc = NULL;
+        char **rule;
+        int cld_code, r;
+
+        assert_se(u = unit_new(m, sizeof(Service)));
+        assert_se(unit_add_name(u, unit_name) == 0);
+        assert_se(cc = unit_get_cgroup_context(u));
+
+        STRV_FOREACH(rule, allow_rules) {
+                r = config_parse_cgroup_socket_bind(
+                                u->id, "filename", 1, "Service", 1, "SocketBindAllow", 0,
+                                *rule, &cc->socket_bind_allow, u);
+                if (r < 0)
+                        return log_unit_error_errno(u, r, "Failed to parse SocketBindAllow: %m");
+        }
+
+        fprintf(stderr, "SocketBindAllow:");
+        LIST_FOREACH(socket_bind_items, bi, cc->socket_bind_allow)
+                cgroup_context_dump_socket_bind_item(bi, stderr);
+        fputc('\n', stderr);
+
+        STRV_FOREACH(rule, deny_rules) {
+                r = config_parse_cgroup_socket_bind(
+                                u->id, "filename", 1, "Service", 1, "SocketBindDeny", 0,
+                                *rule, &cc->socket_bind_deny, u);
+                if (r < 0)
+                        return log_unit_error_errno(u, r, "Failed to parse SocketBindDeny: %m");
+        }
+
+        fprintf(stderr, "SocketBindDeny:");
+        LIST_FOREACH(socket_bind_items, bi, cc->socket_bind_deny)
+                cgroup_context_dump_socket_bind_item(bi, stderr);
+        fputc('\n', stderr);
+
+        exec_start = strjoin("-timeout --preserve-status -sSIGTERM 1s ", netcat_path, " -l ", port, " -vv");
+        assert_se(exec_start != NULL);
+
+        r = config_parse_exec(u->id, "filename", 1, "Service", 1, "ExecStart",
+                        SERVICE_EXEC_START, exec_start, SERVICE(u)->exec_command, u);
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse ExecStart");
+
+        SERVICE(u)->type = SERVICE_ONESHOT;
+        u->load_state = UNIT_LOADED;
+
+        r = unit_start(u);
+        if (r < 0)
+                return log_error_errno(r, "Unit start failed %m");
+
+        while (!IN_SET(SERVICE(u)->state, SERVICE_DEAD, SERVICE_FAILED)) {
+                r = sd_event_run(m->event, UINT64_MAX);
+                if (r < 0)
+                        return log_error_errno(errno, "Event run failed %m");
+        }
+
+        cld_code = SERVICE(u)->exec_command[SERVICE_EXEC_START]->exec_status.code;
+        if (cld_code != CLD_EXITED)
+                return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "ExecStart didn't exited, code='%s'", sigchld_code_to_string(cld_code));
+
+        if (SERVICE(u)->state != SERVICE_DEAD)
+                return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Service is not dead");
+
+        return 0;
+}
+
+int main(int argc, char *argv[]) {
+        _cleanup_free_ char *unit_dir = NULL, *netcat_path = NULL;
+        _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
+        _cleanup_(manager_freep) Manager *m = NULL;
+        struct rlimit rl;
+        int r;
+
+        test_setup_logging(LOG_DEBUG);
+
+        if (detect_container() > 0)
+                return log_tests_skipped("test-bpf fails inside LXC and Docker containers: https://github.com/systemd/systemd/issues/9666");
+
+        if (getuid() != 0)
+                return log_tests_skipped("not running as root");
+
+        assert_se(getrlimit(RLIMIT_MEMLOCK, &rl) >= 0);
+        rl.rlim_cur = rl.rlim_max = MAX(rl.rlim_max, CAN_MEMLOCK_SIZE);
+        (void) setrlimit_closest(RLIMIT_MEMLOCK, &rl);
+
+        if (!can_memlock())
+                return log_tests_skipped("Can't use mlock(), skipping.");
+
+        r = socket_bind_supported();
+        if (r <= 0)
+                return log_tests_skipped("socket-bind is not supported, skipping.");
+
+        if (find_netcat_executable(&netcat_path) != 0)
+                return log_tests_skipped("Can not find netcat executable, skipping.");
+
+        r = enter_cgroup_subroot(NULL);
+        if (r == -ENOMEDIUM)
+                return log_tests_skipped("cgroupfs not available");
+
+        assert_se(get_testdata_dir("units", &unit_dir) >= 0);
+        assert_se(set_unit_path(unit_dir) >= 0);
+        assert_se(runtime_dir = setup_fake_runtime_dir());
+
+        assert_se(manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m) >= 0);
+        assert_se(manager_startup(m, NULL, NULL) >= 0);
+
+        assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "2000", STRV_MAKE("2000"), STRV_MAKE("any")) >= 0);
+        assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "2000", STRV_MAKE("IPv6:2001-2002"), STRV_MAKE("any")) >= 0);
+        assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("IPv4:6666", "6667"), STRV_MAKE("any")) >= 0);
+        assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("6667", "6668", ""), STRV_MAKE("any")) >= 0);
+        assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "7777", STRV_MAKE_EMPTY, STRV_MAKE_EMPTY) >= 0);
+        assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "8888", STRV_MAKE("any"), STRV_MAKE("any")) >= 0);
+
+        return 0;
+}
index 15ea24ae4bec2f80de03ee5beb2568cc8f85fdb6..8174b1283707dd781602deedd2a121442e20a91a 100644 (file)
@@ -970,6 +970,22 @@ static void test_strverscmp_improved(void) {
         assert_se(strverscmp_improved("123_aa2-67.89", "123aa+2-67.89") == 0);
 }
 
+static void test_strextendf(void) {
+        _cleanup_free_ char *p = NULL;
+
+        assert_se(strextendf(&p, "<%i>", 77) >= 0);
+        assert_se(streq(p, "<77>"));
+
+        assert_se(strextendf(&p, "<%i>", 99) >= 0);
+        assert_se(streq(p, "<77><99>"));
+
+        assert_se(strextendf(&p, "<%80i>", 88) >= 0);
+        assert_se(streq(p, "<77><99><                                                                              88>"));
+
+        assert_se(strextendf(&p, "<%08x>", 0x1234) >= 0);
+        assert_se(streq(p, "<77><99><                                                                              88><00001234>"));
+}
+
 int main(int argc, char *argv[]) {
         test_setup_logging(LOG_DEBUG);
 
@@ -1008,6 +1024,7 @@ int main(int argc, char *argv[]) {
         test_string_contains_word_strv();
         test_string_contains_word();
         test_strverscmp_improved();
+        test_strextendf();
 
         return 0;
 }
index 488b965c822b7663de965de5c197e5df92f079d4..c2c63cc679c2bf3c55fd3aaddbeb8a90e707a0cb 100644 (file)
@@ -11,7 +11,6 @@
 #include <sys/signalfd.h>
 #include <unistd.h>
 
-#include "build.h"
 #include "device-private.h"
 #include "fs-util.h"
 #include "log.h"
@@ -24,6 +23,7 @@
 #include "string-util.h"
 #include "tests.h"
 #include "udev-event.h"
+#include "version.h"
 
 static int fake_filesystems(void) {
         static const struct fakefs {
@@ -130,7 +130,7 @@ static int run(int argc, char *argv[]) {
                 }
         }
 
-        udev_event_execute_rules(event, 3 * USEC_PER_SEC, SIGKILL, NULL, rules);
+        udev_event_execute_rules(event, -1, 3 * USEC_PER_SEC, SIGKILL, NULL, rules);
         udev_event_execute_run(event, 3 * USEC_PER_SEC, SIGKILL);
 
         return 0;
index 8f9679051daaca6c3990bbb651537f3803c440f2..477ae03a0231fe8a62c432267c342a189d813a96 100644 (file)
@@ -92,6 +92,7 @@ static void test_runlevel_to_target(void) {
 }
 
 int main(int argc, char **argv) {
+        log_show_color(true);
         test_setup_logging(LOG_DEBUG);
 
         test_unit_validate_alias_symlink_and_warn();
index ece78aa5486b21c2efe1ec028b3dd19f9b3ed22d..dc4dc7529d31b887ae5a07f7ab29787658962d3a 100644 (file)
@@ -471,8 +471,8 @@ static void test_build_parent_slice(void) {
 }
 
 static void test_unit_name_to_instance(void) {
+        UnitNameFlags r;
         char *instance;
-        int r;
 
         log_info("/* %s */", __func__);
 
diff --git a/src/test/test-unit-serialize.c b/src/test/test-unit-serialize.c
new file mode 100644 (file)
index 0000000..58a0d9d
--- /dev/null
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "rm-rf.h"
+#include "service.h"
+#include "tests.h"
+
+#define EXEC_START_ABSOLUTE \
+        "ExecStart 0 /bin/sh \"sh\" \"-e\" \"-x\" \"-c\" \"systemctl --state=failed --no-legend --no-pager >/failed ; systemctl daemon-reload ; echo OK >/testok\""
+#define EXEC_START_RELATIVE \
+        "ExecStart 0 sh \"sh\" \"-e\" \"-x\" \"-c\" \"systemctl --state=failed --no-legend --no-pager >/failed ; systemctl daemon-reload ; echo OK >/testok\""
+
+static void test_deserialize_exec_command_one(Manager *m, const char *key, const char *line, int expected) {
+        _cleanup_(unit_freep) Unit *u = NULL;
+        int r;
+
+        assert_se(unit_new_for_name(m, sizeof(Service), "test.service", &u) >= 0);
+
+        r = service_deserialize_exec_command(u, key, line);
+        log_debug("[%s] → %d (expected: %d)", line, r, expected);
+        assert(r == expected);
+
+        /* Note that the command doesn't match any command in the empty list of commands in 's', so it is
+         * always rejected with "Current command vanished from the unit file", and we don't leak anything. */
+}
+
+static void test_deserialize_exec_command(void) {
+        _cleanup_(manager_freep) Manager *m = NULL;
+        int r;
+
+        log_info("/* %s */", __func__);
+
+        r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
+        if (manager_errno_skip_test(r)) {
+                log_notice_errno(r, "Skipping test: manager_new: %m");
+                return;
+        }
+
+        assert_se(r >= 0);
+
+        test_deserialize_exec_command_one(m, "main-command", EXEC_START_ABSOLUTE, 0);
+        test_deserialize_exec_command_one(m, "main-command", EXEC_START_RELATIVE, 0);
+        test_deserialize_exec_command_one(m, "control-command", EXEC_START_ABSOLUTE, 0);
+        test_deserialize_exec_command_one(m, "control-command", EXEC_START_RELATIVE, 0);
+
+        test_deserialize_exec_command_one(m, "control-command", "ExecStart 0 /bin/sh \"sh\"", 0);
+        test_deserialize_exec_command_one(m, "control-command", "ExecStart 0 /no/command ", -EINVAL);
+        test_deserialize_exec_command_one(m, "control-command", "ExecStart 0 /bad/quote \"", -EINVAL);
+        test_deserialize_exec_command_one(m, "control-command", "ExecStart s /bad/id x y z", -EINVAL);
+        test_deserialize_exec_command_one(m, "control-command", "ExecStart 11", -EINVAL);
+        test_deserialize_exec_command_one(m, "control-command", "ExecWhat 11 /a/b c d e", -EINVAL);
+}
+
+int main(int argc, char *argv[]) {
+        _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
+        int r;
+
+        test_setup_logging(LOG_DEBUG);
+
+        r = enter_cgroup_subroot(NULL);
+        if (r == -ENOMEDIUM)
+                return log_tests_skipped("cgroupfs not available");
+
+        assert_se(runtime_dir = setup_fake_runtime_dir());
+
+        test_deserialize_exec_command();
+
+        return EXIT_SUCCESS;
+}
index fb08f9ad260867ec101e1bb1632657665e9e329a..d31f67f4cb3e4877c77a60220753b0567088476c 100644 (file)
@@ -34,8 +34,7 @@ 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;
+static BusPrintPropertyFlags arg_print_flags = 0;
 
 typedef struct StatusInfo {
         usec_t time;
@@ -96,21 +95,17 @@ static int print_status_info(const StatusInfo *i) {
         } else
                 log_warning("Could not get time from timedated and not operating locally, ignoring.");
 
-        if (have_time)
-                n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm));
-
+        n = have_time ? strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)) : 0;
         r = table_add_many(table,
                            TABLE_STRING, "Local time:",
-                           TABLE_STRING, have_time && n > 0 ? a : "n/a");
+                           TABLE_STRING, n > 0 ? a : "n/a");
         if (r < 0)
                 return table_log_add_error(r);
 
-        if (have_time)
-                n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm));
-
+        n = have_time ? strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)) : 0;
         r = table_add_many(table,
                            TABLE_STRING, "Universal time:",
-                           TABLE_STRING, have_time && n > 0 ? a : "n/a");
+                           TABLE_STRING, n > 0 ? a : "n/a");
         if (r < 0)
                 return table_log_add_error(r);
 
@@ -119,26 +114,23 @@ static int 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));
-        }
-
+        } else
+                n = 0;
         r = table_add_many(table,
                            TABLE_STRING, "RTC time:",
-                           TABLE_STRING, i->rtc_time > 0 && n > 0 ? a : "n/a");
+                           TABLE_STRING, n > 0 ? a : "n/a");
         if (r < 0)
                 return table_log_add_error(r);
 
-        if (have_time)
-                n = strftime(a, sizeof a, "%Z, %z", localtime_r(&sec, &tm));
-
         r = table_add_cell(table, NULL, TABLE_STRING, "Time zone:");
         if (r < 0)
                 return table_log_add_error(r);
 
-        r = table_add_cell_stringf(table, NULL, "%s (%s)", strna(i->timezone), have_time && n > 0 ? a : "n/a");
+        n = have_time ? strftime(a, sizeof a, "%Z, %z", localtime_r(&sec, &tm)) : 0;
+        r = table_add_cell_stringf(table, NULL, "%s (%s)", strna(i->timezone), n > 0 ? a : "n/a");
         if (r < 0)
                 return table_log_add_error(r);
 
-
         /* Restore the $TZ */
         r = set_unset_env("TZ", old_tz, true);
         if (r < 0)
@@ -217,8 +209,7 @@ static int show_properties(int argc, char **argv, void *userdata) {
                                      "/org/freedesktop/timedate1",
                                      NULL,
                                      arg_property,
-                                     arg_value,
-                                     arg_all,
+                                     arg_print_flags,
                                      NULL);
         if (r < 0)
                 return bus_log_parse_error(r);
@@ -709,7 +700,7 @@ static int show_timesync_status(int argc, char **argv, void *userdata) {
         return 0;
 }
 
-static int print_timesync_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) {
+static int print_timesync_property(const char *name, const char *expected_value, sd_bus_message *m, BusPrintPropertyFlags flags) {
         char type;
         const char *contents;
         int r;
@@ -735,7 +726,7 @@ static int print_timesync_property(const char *name, const char *expected_value,
                         if (i.packet_count == 0)
                                 return 1;
 
-                        if (!value) {
+                        if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE)) {
                                 fputs(name, stdout);
                                 fputc('=', stdout);
                         }
@@ -774,8 +765,7 @@ static int print_timesync_property(const char *name, const char *expected_value,
                         if (r < 0)
                                 return r;
 
-                        if (arg_all || !isempty(str))
-                                bus_print_property_value(name, expected_value, value, str);
+                        bus_print_property_value(name, expected_value, flags, str);
 
                         return 1;
                 }
@@ -796,8 +786,7 @@ static int show_timesync(int argc, char **argv, void *userdata) {
                                      "/org/freedesktop/timesync1",
                                      print_timesync_property,
                                      arg_property,
-                                     arg_value,
-                                     arg_all,
+                                     arg_print_flags,
                                      NULL);
         if (r < 0)
                 return bus_log_parse_error(r);
@@ -1004,16 +993,16 @@ static int parse_argv(int argc, char *argv[]) {
                         /* If the user asked for a particular
                          * property, show it to them, even if it is
                          * empty. */
-                        arg_all = true;
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
                         break;
                 }
 
                 case 'a':
-                        arg_all = true;
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
                         break;
 
                 case ARG_VALUE:
-                        arg_value = true;
+                        SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_ONLY_VALUE, true);
                         break;
 
                 case '?':
index 567244dc244ede65bc89285c27dd7ef85ba2e0a9..6e0f91dec47ddff9f948d5964695bf1f9ce63a1f 100644 (file)
@@ -65,24 +65,33 @@ typedef struct Context {
         LIST_HEAD(UnitStatusInfo, units);
 } Context;
 
-#define log_unit_full(unit, level, error, ...)                          \
+#define log_unit_full_errno_zerook(unit, level, error, ...)             \
         ({                                                              \
                 const UnitStatusInfo *_u = (unit);                      \
-                log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, \
-                                    "UNIT=", _u->name, NULL, NULL, ##__VA_ARGS__); \
+                _u ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "UNIT=", _u->name, NULL, NULL, ##__VA_ARGS__) : \
+                        log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
         })
 
-#define log_unit_debug(unit, ...)   log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__)
-#define log_unit_info(unit, ...)    log_unit_full(unit, LOG_INFO, 0, ##__VA_ARGS__)
-#define log_unit_notice(unit, ...)  log_unit_full(unit, LOG_NOTICE, 0, ##__VA_ARGS__)
-#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, 0, ##__VA_ARGS__)
-#define log_unit_error(unit, ...)   log_unit_full(unit, LOG_ERR, 0, ##__VA_ARGS__)
+#define log_unit_full_errno(unit, level, error, ...) \
+        ({                                                              \
+                int _error = (error);                                   \
+                ASSERT_NON_ZERO(_error);                                \
+                log_unit_full_errno_zerook(unit, level, _error, ##__VA_ARGS__); \
+        })
+
+#define log_unit_full(unit, level, ...) (void) log_unit_full_errno_zerook(unit, level, 0, ##__VA_ARGS__)
+
+#define log_unit_debug(unit, ...)   log_unit_full(unit, LOG_DEBUG, ##__VA_ARGS__)
+#define log_unit_info(unit, ...)    log_unit_full(unit, LOG_INFO, ##__VA_ARGS__)
+#define log_unit_notice(unit, ...)  log_unit_full(unit, LOG_NOTICE, ##__VA_ARGS__)
+#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, ##__VA_ARGS__)
+#define log_unit_error(unit, ...)   log_unit_full(unit, LOG_ERR, ##__VA_ARGS__)
 
-#define log_unit_debug_errno(unit, error, ...)   log_unit_full(unit, LOG_DEBUG, error, ##__VA_ARGS__)
-#define log_unit_info_errno(unit, error, ...)    log_unit_full(unit, LOG_INFO, error, ##__VA_ARGS__)
-#define log_unit_notice_errno(unit, error, ...)  log_unit_full(unit, LOG_NOTICE, error, ##__VA_ARGS__)
-#define log_unit_warning_errno(unit, error, ...) log_unit_full(unit, LOG_WARNING, error, ##__VA_ARGS__)
-#define log_unit_error_errno(unit, error, ...)   log_unit_full(unit, LOG_ERR, error, ##__VA_ARGS__)
+#define log_unit_debug_errno(unit, error, ...)   log_unit_full_errno(unit, LOG_DEBUG, error, ##__VA_ARGS__)
+#define log_unit_info_errno(unit, error, ...)    log_unit_full_errno(unit, LOG_INFO, error, ##__VA_ARGS__)
+#define log_unit_notice_errno(unit, error, ...)  log_unit_full_errno(unit, LOG_NOTICE, error, ##__VA_ARGS__)
+#define log_unit_warning_errno(unit, error, ...) log_unit_full_errno(unit, LOG_WARNING, error, ##__VA_ARGS__)
+#define log_unit_error_errno(unit, error, ...)   log_unit_full_errno(unit, LOG_ERR, error, ##__VA_ARGS__)
 
 static void unit_status_info_clear(UnitStatusInfo *p) {
         assert(p);
@@ -485,8 +494,8 @@ static int unit_start_or_stop(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *erro
                 "ss",
                 u->name,
                 "replace");
-        log_unit_full(u, r < 0 ? LOG_WARNING : LOG_DEBUG, r,
-                      "%s unit: %m", start ? "Starting" : "Stopping");
+        log_unit_full_errno_zerook(u, r < 0 ? LOG_WARNING : LOG_DEBUG, r,
+                                   "%s unit: %m", start ? "Starting" : "Stopping");
         if (r < 0)
                 return r;
 
@@ -801,6 +810,7 @@ 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) {
         sd_bus *bus = sd_bus_message_get_bus(m);
+        char buf[FORMAT_TIMESTAMP_MAX];
         int relative, interactive, r;
         Context *c = userdata;
         int64_t utc;
@@ -886,7 +896,7 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro
         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)));
+                   LOG_MESSAGE("Changed local time to %s", strnull(format_timestamp(buf, sizeof(buf), timespec_load(&ts)))));
 
         return sd_bus_reply_method_return(m, NULL);
 }
index 8a9a14cf0c7d6941bcc11e58e3d5161fdb2e6c44..8a2c33e17cd4e876ecec3af0f50f06cc2d867301 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Entries in this file show the compile time defaults. Local configuration
 # should be created by either modifying this file, or by creating "drop-ins" in
-# the system.conf.d/ subdirectory. The latter is generally recommended.
+# the timesyncd.conf.d/ subdirectory. The latter is generally recommended.
 # Defaults can be restored by simply deleting this file and all drop-ins.
 #
 # See timesyncd.conf(5) for details.
index df34541bf702ce6bf45912cab726afd251cfb0e3..2a9b113ff484128840d6b090666826b3a8926ea3 100644 (file)
@@ -179,7 +179,7 @@ static int clock_state_update(
 }
 
 static int run(int argc, char * argv[]) {
-        _cleanup_(sd_event_unrefp) sd_event *event;
+        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         _cleanup_(clock_state_release) ClockState state = {
                 .timerfd_fd = -1,
                 .inotify_fd = -1,
index 846e456551ee66d7e1822f09725e5be2a7669f2a..9529b09b3f3ef56a5275d423889203c103c77dab 100644 (file)
@@ -1656,10 +1656,9 @@ static int create_directory_or_subvolume(const char *path, mode_t mode, bool sub
                         return log_error_errno(r, "%s does not exist and cannot be created as the file system is read-only.", path);
                 if (k < 0)
                         return log_error_errno(k, "Failed to check if %s exists: %m", path);
-                if (!k) {
-                        log_warning("\"%s\" already exists and is not a directory.", path);
-                        return -EEXIST;
-                }
+                if (!k)
+                        return log_warning_errno(SYNTHETIC_ERRNO(EEXIST),
+                                                 "\"%s\" already exists and is not a directory.", path);
 
                 *creation = CREATION_EXISTING;
         } else
@@ -1742,10 +1741,10 @@ static int empty_directory(Item *i, const char *path) {
         }
         if (r < 0)
                 return log_error_errno(r, "is_dir() failed on path %s: %m", path);
-        if (r == 0)
-                return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
-                                       "'%s' already exists and is not a directory.",
-                                       path);
+        if (r == 0) {
+                log_warning("\"%s\" already exists and is not a directory.", path);
+                return 0;
+        }
 
         return path_set_perms(i, path);
 }
@@ -1804,7 +1803,7 @@ static int create_device(Item *i, mode_t file_type) {
                                         return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
                                 creation = CREATION_FORCE;
                         } else {
-                                log_debug("%s is not a device node.", i->path);
+                                log_warning("\"%s\" already exists is not a device node.", i->path);
                                 return 0;
                         }
                 } else
@@ -2575,7 +2574,9 @@ static int patch_var_run(const char *fname, unsigned line, char **path) {
         /* 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_syntax(NULL, LOG_NOTICE, fname, line, 0, "Line references path below legacy directory /var/run/, updating %s → %s; please update the tmpfiles.d/ drop-in file accordingly.", *path, n);
+        log_syntax(NULL, LOG_NOTICE, fname, line, 0,
+                   "Line references path below legacy directory /var/run/, updating %s → %s; please update the tmpfiles.d/ drop-in file accordingly.",
+                   *path, n);
 
         free_and_replace(*path, n);
 
@@ -3184,9 +3185,10 @@ static int parse_argv(int argc, char *argv[]) {
 static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoent, bool *invalid_config) {
         _cleanup_(hashmap_freep) Hashmap *uid_cache = NULL, *gid_cache = NULL;
         _cleanup_fclose_ FILE *_f = NULL;
+        _cleanup_free_ char *pp = NULL;
         unsigned v = 0;
         FILE *f;
-        Item *i;
+        ItemArray *ia;
         int r = 0;
 
         assert(fn);
@@ -3196,7 +3198,7 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe
                 fn = "<stdin>";
                 f = stdin;
         } else {
-                r = search_and_fopen(fn, "re", arg_root, (const char**) config_dirs, &_f);
+                r = search_and_fopen(fn, "re", arg_root, (const char**) config_dirs, &_f, &pp);
                 if (r < 0) {
                         if (ignore_enoent && r == -ENOENT) {
                                 log_debug_errno(r, "Failed to open \"%s\", ignoring: %m", fn);
@@ -3205,7 +3207,9 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe
 
                         return log_error_errno(r, "Failed to open '%s': %m", fn);
                 }
-                log_debug("Reading config file \"%s\"…", fn);
+
+                log_debug("Reading config file \"%s\"…", pp);
+                fn = pp;
                 f = _f;
         }
 
@@ -3239,31 +3243,41 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe
         }
 
         /* we have to determine age parameter for each entry of type X */
-        ORDERED_HASHMAP_FOREACH(i, globs) {
-                Item *j, *candidate_item = NULL;
-
-                if (i->type != IGNORE_DIRECTORY_PATH)
-                        continue;
+        ORDERED_HASHMAP_FOREACH(ia, globs)
+                for (size_t ni = 0; ni < ia->n_items; ni++) {
+                        ItemArray *ja;
+                        Item *i = ia->items + ni, *candidate_item = NULL;
 
-                ORDERED_HASHMAP_FOREACH(j, items) {
-                        if (!IN_SET(j->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA))
+                        if (i->type != IGNORE_DIRECTORY_PATH)
                                 continue;
 
-                        if (path_equal(j->path, i->path)) {
-                                candidate_item = j;
-                                break;
-                        }
+                        ORDERED_HASHMAP_FOREACH(ja, items)
+                                for (size_t nj = 0; nj < ja->n_items; nj++) {
+                                        Item *j = ja->items + nj;
 
-                        if ((!candidate_item && path_startswith(i->path, j->path)) ||
-                            (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
-                                candidate_item = j;
-                }
+                                        if (!IN_SET(j->type, CREATE_DIRECTORY,
+                                                             TRUNCATE_DIRECTORY,
+                                                             CREATE_SUBVOLUME,
+                                                             CREATE_SUBVOLUME_INHERIT_QUOTA,
+                                                             CREATE_SUBVOLUME_NEW_QUOTA))
+                                                continue;
+
+                                        if (path_equal(j->path, i->path)) {
+                                                candidate_item = j;
+                                                break;
+                                        }
 
-                if (candidate_item && candidate_item->age_set) {
-                        i->age = candidate_item->age;
-                        i->age_set = true;
+                                        if (candidate_item
+                                            ? (path_startswith(j->path, candidate_item->path) && fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)
+                                            : path_startswith(i->path, j->path) != NULL)
+                                                candidate_item = j;
+                                }
+
+                        if (candidate_item && candidate_item->age_set) {
+                                i->age = candidate_item->age;
+                                i->age_set = true;
+                        }
                 }
-        }
 
         if (ferror(f)) {
                 log_error_errno(errno, "Failed to read from file %s: %m", fn);
@@ -3431,7 +3445,12 @@ static int run(int argc, char *argv[]) {
 
                 r = mount_image_privately_interactively(
                                 arg_image,
-                                DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
+                                DISSECT_IMAGE_GENERIC_ROOT |
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_VALIDATE_OS |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                DISSECT_IMAGE_FSCK |
+                                DISSECT_IMAGE_GROWFS,
                                 &unlink_dir,
                                 &loop_device,
                                 &decrypted_image);
index 5ee82c708b709ab36f93579b3fce3d86729ede10..ceacb61bf14b92365ef13a216db92e9414da3277 100644 (file)
@@ -289,7 +289,7 @@ static int wall_tty_block(void) {
 }
 
 static int process_password_files(void) {
-        _cleanup_closedir_ DIR *d;
+        _cleanup_closedir_ DIR *d = NULL;
         struct dirent *de;
         int r = 0;
 
index 60c7b4922cacc71276c9427d4ce35a01283fd85c..f2d54b297dad91ed3ec9103f5e4fb0414729175e 100644 (file)
@@ -302,10 +302,22 @@ static int cd_capability_compat(Context *c) {
 }
 
 static int cd_media_compat(Context *c) {
+        int r;
+
         assert(c);
 
-        if (ioctl(c->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK)
-                return log_debug_errno(errno, "CDROM_DRIVE_STATUS != CDS_DISC_OK");
+        r = ioctl(c->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
+        if (r < 0)
+                return log_debug_errno(errno, "ioctl(CDROM_DRIVE_STATUS) failed: %m");
+        if (r != CDS_DISC_OK)
+                return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM),
+                                       "ioctl(CDROM_DRIVE_STATUS) → %d (%s), ignoring.",
+                                       r,
+                                       r == CDS_NO_INFO ? "no info" :
+                                       r == CDS_NO_DISC ? "no disc" :
+                                       r == CDS_TRAY_OPEN ? "tray open" :
+                                       r == CDS_DRIVE_NOT_READY ? "drive not ready" :
+                                       "unknown status");
 
         c->has_media = true;
         return 0;
@@ -327,7 +339,7 @@ static int cd_inquiry(Context *c) {
                 return r;
 
         if ((inq[0] & 0x1F) != 5)
-                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Not an MMC unit");
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Not an MMC unit.");
 
         log_debug("INQUIRY: [%.8s][%.16s][%.4s]", inq + 8, inq + 16, inq + 32);
         return 0;
@@ -437,7 +449,7 @@ static int cd_profiles(Context *c) {
         log_debug("GET CONFIGURATION: size of features buffer %zu", len);
 
         if (len > sizeof(features)) {
-                log_debug("cannot get features in a single query, truncating");
+                log_debug("Cannot get features in a single query, truncating.");
                 len = sizeof(features);
         } else if (len <= 8)
                 len = sizeof(features);
@@ -457,7 +469,7 @@ static int cd_profiles(Context *c) {
         log_debug("GET CONFIGURATION: size of features buffer %zu", len);
 
         if (len > sizeof(features)) {
-                log_debug("cannot get features in a single query, truncating");
+                log_debug("Cannot get features in a single query, truncating.");
                 len = sizeof(features);
         }
 
@@ -516,7 +528,7 @@ static int dvd_ram_media_update_state(Context *c) {
 
         if (dvdstruct[4] & 0x02) {
                 c->media_state = MEDIA_STATE_COMPLETE;
-                log_debug("write-protected DVD-RAM media inserted");
+                log_debug("Write-protected DVD-RAM media inserted");
                 return 1;
         }
 
@@ -532,24 +544,24 @@ static int dvd_ram_media_update_state(Context *c) {
         len = format[3];
         if (len & 7 || len < 16)
                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "invalid format capacities length");
+                                       "Invalid format capacities length.");
 
         switch(format[8] & 3) {
         case 1:
                 /* This means that last format was interrupted or failed, blank dvd-ram discs are
                  * factory formatted. Take no action here as it takes quite a while to reformat a
                  * dvd-ram and it's not automatically started. */
-                log_debug("unformatted DVD-RAM media inserted");
+                log_debug("Unformatted DVD-RAM media inserted.");
                 return 1;
 
         case 2:
-                log_debug("formatted DVD-RAM media inserted");
+                log_debug("Formatted DVD-RAM media inserted.");
                 return 0;
 
         case 3:
                 c->has_media = false;
                 return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM),
-                                       "format capacities returned no media");
+                                       "Format capacities returned no media.");
         }
 
         return 0;
@@ -586,17 +598,17 @@ static int dvd_media_update_state(Context *c) {
 
         for (size_t offset = 32768; offset < 32768 + 2048; offset++)
                 if (buffer[offset] != 0) {
-                        log_debug("data in block 16, assuming complete");
+                        log_debug("Data in block 16, assuming complete.");
                         return 0;
                 }
 
         for (size_t offset = 0; offset < 2048; offset++)
                 if (buffer[offset] != 0) {
-                        log_debug("data in block 0, assuming complete");
+                        log_debug("Data in block 0, assuming complete.");
                         return 0;
                 }
 
-        log_debug("no data in blocks 0 or 16, assuming blank");
+        log_debug("No data in blocks 0 or 16, assuming blank.");
         c->media_state = MEDIA_STATE_BLANK;
         return 0;
 }
@@ -730,25 +742,23 @@ static int cd_media_toc(Context *c) {
 }
 
 static int open_drive(Context *c) {
-        _cleanup_close_ int fd = -1;
+        int fd;
 
         assert(c);
         assert(c->fd < 0);
 
-        for (int cnt = 0; cnt < 20; cnt++) {
-                if (cnt != 0)
-                        (void) usleep(100 * USEC_PER_MSEC + random_u64() % (100 * USEC_PER_MSEC));
-
+        for (int cnt = 0;; cnt++) {
                 fd = open(arg_node, O_RDONLY|O_NONBLOCK|O_CLOEXEC);
-                if (fd >= 0 || errno != EBUSY)
+                if (fd >= 0)
                         break;
+                if (++cnt >= 20 || errno != EBUSY)
+                        return log_debug_errno(errno, "Unable to open '%s': %m", arg_node);
+
+                (void) usleep(100 * USEC_PER_MSEC + random_u64_range(100 * USEC_PER_MSEC));
         }
-        if (fd < 0)
-                return log_debug_errno(errno, "Unable to open '%s'", arg_node);
 
         log_debug("probing: '%s'", arg_node);
-
-        c->fd = TAKE_FD(fd);
+        c->fd = fd;
         return 0;
 }
 
@@ -820,7 +830,7 @@ static void print_feature(Feature feature, const char *prefix) {
 
         found = typesafe_bsearch(&in, feature_to_string, ELEMENTSOF(feature_to_string), feature_to_string_compare_func);
         if (!found)
-                return (void) log_debug("Unknown feature 0x%02x, ignoring", (unsigned) feature);
+                return (void) log_debug("Unknown feature 0x%02x, ignoring.", (unsigned) feature);
 
         printf("%s_%s=1\n", prefix, found->str);
 }
@@ -939,7 +949,7 @@ static int parse_argv(int argc, char *argv[]) {
 
         arg_node = argv[optind];
         if (!arg_node)
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No device is specified.");
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No device specified.");
 
         return 1;
 }
index c5bea8c9a8080100bd2f75880cd5e0d62bc44a2a..64eba0d314e34d203920aa8dff5f81672fe6f20c 100644 (file)
 #include <getopt.h>
 
 #include "alloc-util.h"
-#include "build.h"
 #include "fileio.h"
 #include "main-func.h"
 #include "string-util.h"
 #include "udev-util.h"
 #include "unaligned.h"
+#include "version.h"
 
 #define SUPPORTED_SMBIOS_VER 0x030300
 
index d417da22fd4831eba872f7966cc5c27954a73e8f..1db4cbe47de5ae5ad367bd4d58a1b6dd707be8e1 100755 (executable)
@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
 
+# shellcheck disable=SC1004
 awk '
     BEGIN {
         print "%{\n\
@@ -16,4 +17,4 @@ _Pragma(\"GCC diagnostic ignored \\\"-Wimplicit-fallthrough\\\"\")\n\
 
     /^KEY_/ { print tolower(substr($1 ,5)) ", " $1 }
     { print tolower($1) ", " $1 }
-' < "$1"
+' < "${1:?}"
index b40368467ba22ac5a95f3e07a96d3432250ac30a..d4f9a7d0e10a1721a71bdca6d4581221a3b1fb8b 100755 (executable)
@@ -1,8 +1,9 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
+set -o pipefail
 
-$1 -dM -include linux/input.h - </dev/null | awk '
+${1:?} -dM -include linux/input.h - </dev/null | awk '
     /\<(KEY_(MAX|MIN_INTERESTING))|(BTN_(MISC|MOUSE|JOYSTICK|GAMEPAD|DIGI|WHEEL|TRIGGER_HAPPY))\>/  { next }
     /^#define[ \t]+(KEY|BTN)_[^ ]+[ \t]+[0-9BK]/                                                    { print $2 }
 '
index 31e5d0cd673f94baf9cbe02aab333bb8e96aa160..87afe8383ad17d6fc48427bd2a5c61912ecce8db 100644 (file)
@@ -364,9 +364,11 @@ static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr
                 return r;
         switch (addr_type) {
         case NET_ADDR_SET:
-                return log_device_debug(device, "MAC on the device already set by userspace");
+                log_device_debug(device, "MAC on the device already set by userspace");
+                return 0;
         case NET_ADDR_STOLEN:
-                return log_device_debug(device, "MAC on the device already set based on another device");
+                log_device_debug(device, "MAC on the device already set based on another device");
+                return 0;
         case NET_ADDR_RANDOM:
         case NET_ADDR_PERM:
                 break;
@@ -375,9 +377,11 @@ static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr
                 return 0;
         }
 
-        if (want_random == (addr_type == NET_ADDR_RANDOM))
-                return log_device_debug(device, "MAC on the device already matches policy *%s*",
-                                        mac_address_policy_to_string(policy));
+        if (want_random == (addr_type == NET_ADDR_RANDOM)) {
+                log_device_debug(device, "MAC on the device already matches policy *%s*",
+                                 mac_address_policy_to_string(policy));
+                return 0;
+        }
 
         if (want_random) {
                 log_device_debug(device, "Using random bytes to generate MAC");
index 0c4a17c456d15f3b1f79fd8605114d36eb9d953f..41f92b68beaa1b4347c1c0d785d979e10b80fd2a 100644 (file)
 #include <unistd.h>
 
 #include "alloc-util.h"
-#include "build.h"
 #include "device-nodes.h"
+#include "extract-word.h"
 #include "fd-util.h"
+#include "fileio.h"
 #include "scsi_id.h"
 #include "string-util.h"
+#include "strv.h"
 #include "strxcpyx.h"
 #include "udev-util.h"
+#include "version.h"
 
 static const struct option options[] = {
         { "device",             required_argument, NULL, 'd' },
@@ -90,50 +93,6 @@ static void set_type(const char *from, char *to, size_t len) {
         strscpy(to, len, type);
 }
 
-/*
- * get_value:
- *
- * buf points to an '=' followed by a quoted string ("foo") or a string ending
- * with a space or ','.
- *
- * Return a pointer to the NUL terminated string, returns NULL if no
- * matches.
- */
-static char *get_value(char **buffer) {
-        static const char *quote_string = "\"\n";
-        static const char *comma_string = ",\n";
-        char *val;
-        const char *end;
-
-        if (**buffer == '"') {
-                /*
-                 * skip leading quote, terminate when quote seen
-                 */
-                (*buffer)++;
-                end = quote_string;
-        } else
-                end = comma_string;
-        val = strsep(buffer, end);
-        if (val && end == quote_string)
-                /*
-                 * skip trailing quote
-                 */
-                (*buffer)++;
-
-        while (isspace(**buffer))
-                (*buffer)++;
-
-        return val;
-}
-
-static int argc_count(char *opts) {
-        int i = 0;
-        while (*opts != '\0')
-                if (*opts++ == ' ')
-                        i++;
-        return i;
-}
-
 /*
  * get_file_options:
  *
@@ -145,14 +104,10 @@ static int argc_count(char *opts) {
  */
 static int get_file_options(const char *vendor, const char *model,
                             int *argc, char ***newargv) {
-        _cleanup_free_ char *buffer = NULL;
-        _cleanup_fclose_ FILE *f;
-        char *buf;
-        char *str1;
-        char *vendor_in, *model_in, *options_in; /* read in from file */
-        int lineno;
-        int c;
-        int retval = 0;
+        _cleanup_free_ char *vendor_in = NULL, *model_in = NULL, *options_in = NULL; /* read in from file */
+        _cleanup_strv_free_ char **options_argv = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        int lineno, r;
 
         f = fopen(config_file, "re");
         if (!f) {
@@ -164,28 +119,21 @@ static int get_file_options(const char *vendor, const char *model,
                 }
         }
 
-        /*
-         * Allocate a buffer rather than put it on the stack so we can
-         * keep it around to parse any options (any allocated newargv
-         * points into this buffer for its strings).
-         */
-        buffer = malloc(MAX_BUFFER_LEN);
-        if (!buffer)
-                return log_oom();
-
         *newargv = NULL;
         lineno = 0;
         for (;;) {
+                _cleanup_free_ char *buffer = NULL, *key = NULL, *value = NULL;
+                const char *buf;
+
                 vendor_in = model_in = options_in = NULL;
 
-                buf = fgets(buffer, MAX_BUFFER_LEN, f);
-                if (!buf)
+                r = read_line(f, MAX_BUFFER_LEN, &buffer);
+                if (r < 0)
+                        return log_error_errno(r, "read_line() on line %d of %s failed: %m", lineno, config_file);
+                if (r == 0)
                         break;
+                buf = buffer;
                 lineno++;
-                if (buf[strlen(buffer) - 1] != '\n') {
-                        log_error("Config file line %d too long", lineno);
-                        break;
-                }
 
                 while (isspace(*buf))
                         buf++;
@@ -198,44 +146,36 @@ static int get_file_options(const char *vendor, const char *model,
                 if (*buf == '#')
                         continue;
 
-                str1 = strsep(&buf, "=");
-                if (str1 && strcaseeq(str1, "VENDOR")) {
-                        str1 = get_value(&buf);
-                        if (!str1) {
-                                retval = log_oom();
-                                break;
-                        }
-                        vendor_in = str1;
-
-                        str1 = strsep(&buf, "=");
-                        if (str1 && strcaseeq(str1, "MODEL")) {
-                                str1 = get_value(&buf);
-                                if (!str1) {
-                                        retval = log_oom();
-                                        break;
-                                }
-                                model_in = str1;
-                                str1 = strsep(&buf, "=");
-                        }
-                }
+                r = extract_many_words(&buf, "=\",\n", 0, &key, &value, NULL);
+                if (r < 2)
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Error parsing config file line %d '%s'", lineno, buffer);
 
-                if (str1 && strcaseeq(str1, "OPTIONS")) {
-                        str1 = get_value(&buf);
-                        if (!str1) {
-                                retval = log_oom();
-                                break;
+                if (strcaseeq(key, "VENDOR")) {
+                        vendor_in = TAKE_PTR(value);
+
+                        key = mfree(key);
+                        r = extract_many_words(&buf, "=\",\n", 0, &key, &value, NULL);
+                        if (r < 2)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Error parsing config file line %d '%s'", lineno, buffer);
+
+                        if (strcaseeq(key, "MODEL")) {
+                                model_in = TAKE_PTR(value);
+
+                                key = mfree(key);
+                                r = extract_many_words(&buf, "=\",\n", 0, &key, &value, NULL);
+                                if (r < 2)
+                                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Error parsing config file line %d '%s'", lineno, buffer);
                         }
-                        options_in = str1;
                 }
 
+                if (strcaseeq(key, "OPTIONS"))
+                        options_in = TAKE_PTR(value);
+
                 /*
                  * Only allow: [vendor=foo[,model=bar]]options=stuff
                  */
-                if (!options_in || (!vendor_in && model_in)) {
-                        log_error("Error parsing config file line %d '%s'", lineno, buffer);
-                        retval = -1;
-                        break;
-                }
+                if (!options_in || (!vendor_in && model_in))
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Error parsing config file line %d '%s'", lineno, buffer);
                 if (!vendor) {
                         if (!vendor_in)
                                 break;
@@ -251,39 +191,30 @@ static int get_file_options(const char *vendor, const char *model,
                                  */
                                 break;
                 }
-        }
 
-        if (retval == 0) {
-                if (vendor_in != NULL || model_in != NULL ||
-                    options_in != NULL) {
-                        /*
-                         * Something matched. Allocate newargv, and store
-                         * values found in options_in.
-                         */
-                        strcpy(buffer, options_in);
-                        c = argc_count(buffer) + 2;
-                        *newargv = calloc(c, sizeof(**newargv));
-                        if (!*newargv)
-                                retval = log_oom();
-                        else {
-                                *argc = c;
-                                c = 0;
-                                /*
-                                 * argv[0] at 0 is skipped by getopt, but
-                                 * store the buffer address there for
-                                 * later freeing
-                                 */
-                                (*newargv)[c] = buffer;
-                                for (c = 1; c < *argc; c++)
-                                        (*newargv)[c] = strsep(&buffer, " \t");
-                                buffer = NULL;
-                        }
-                } else {
-                        /* No matches  */
-                        retval = 1;
-                }
+                vendor_in = mfree(vendor_in);
+                model_in = mfree(model_in);
+                options_in = mfree(options_in);
+
         }
-        return retval;
+
+        if (vendor_in == NULL && model_in == NULL && options_in == NULL)
+                return 1; /* No matches  */
+
+        /*
+        * Something matched. Allocate newargv, and store
+        * values found in options_in.
+        */
+        options_argv = strv_split(options_in, " \t");
+        if (!options_argv)
+                return log_oom();
+        r = strv_prepend(&options_argv, ""); /* getopt skips over argv[0] */
+        if (r < 0)
+                return r;
+        *newargv = TAKE_PTR(options_argv);
+        *argc = strv_length(*newargv);
+
+        return 0;
 }
 
 static void help(void) {
@@ -391,9 +322,9 @@ static int set_options(int argc, char **argv,
 }
 
 static int per_dev_options(struct scsi_id_device *dev_scsi, int *good_bad, int *page_code) {
+        _cleanup_strv_free_ char **newargv = NULL;
         int retval;
         int newargc;
-        char **newargv = NULL;
         int option;
 
         *good_bad = all_good;
@@ -436,10 +367,6 @@ static int per_dev_options(struct scsi_id_device *dev_scsi, int *good_bad, int *
                 }
         }
 
-        if (newargv) {
-                free(newargv[0]);
-                free(newargv);
-        }
         return retval;
 }
 
@@ -543,10 +470,10 @@ out:
 }
 
 int main(int argc, char **argv) {
+        _cleanup_strv_free_ char **newargv = NULL;
         int retval = 0;
         char maj_min_dev[MAX_PATH_LEN];
         int newargc;
-        char **newargv = NULL;
 
         log_set_target(LOG_TARGET_AUTO);
         udev_parse_config();
@@ -585,10 +512,6 @@ int main(int argc, char **argv) {
         retval = scsi_id(maj_min_dev);
 
 exit:
-        if (newargv) {
-                free(newargv[0]);
-                free(newargv);
-        }
         log_close();
         return retval;
 }
index 872833ebbc17a256feac8a1c5139e8bbd5862581..33601151a6fc3a931490b4d8d2bc2f5d2dfeec9c 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/pci_regs.h>
 
 #include "alloc-util.h"
+#include "device-util.h"
 #include "dirent-util.h"
 #include "fd-util.h"
 #include "fileio.h"
@@ -36,7 +37,8 @@
 #include "strxcpyx.h"
 #include "udev-builtin.h"
 
-#define ONBOARD_INDEX_MAX (16*1024-1)
+#define ONBOARD_14BIT_INDEX_MAX ((1U << 14) - 1)
+#define ONBOARD_16BIT_INDEX_MAX ((1U << 16) - 1)
 
 enum netname_type{
         NET_UNDEF,
@@ -161,6 +163,16 @@ static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn
         return 0;
 }
 
+static bool is_valid_onboard_index(unsigned long idx) {
+        /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to
+         * report for example). Let's define a cut-off where we don't consider the index reliable anymore. We
+         * pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network
+         * interface a system might have. Ideally the kernel would already filter this crap for us, but it
+         * doesn't currently. The initial cut-off value (2^14-1) was too conservative for s390 PCI which
+         * allows for index values up 2^16-1 which is now enabled with the NAMING_16BIT_INDEX naming flag. */
+        return idx <= (naming_scheme_has(NAMING_16BIT_INDEX) ? ONBOARD_16BIT_INDEX_MAX : ONBOARD_14BIT_INDEX_MAX);
+}
+
 /* retrieve on-board index number and label from firmware */
 static int dev_pci_onboard(sd_device *dev, struct netnames *names) {
         unsigned long idx, dev_port = 0;
@@ -183,12 +195,7 @@ static int dev_pci_onboard(sd_device *dev, struct netnames *names) {
         if (idx == 0 && !naming_scheme_has(NAMING_ZERO_ACPI_INDEX))
                 return -EINVAL;
 
-        /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to
-         * report for example). Let's define a cut-off where we don't consider the index reliable anymore. We
-         * pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network
-         * interface a system might have. Ideally the kernel would already filter this crap for us, but it
-         * doesn't currently. */
-        if (idx > ONBOARD_INDEX_MAX)
+        if (!is_valid_onboard_index(idx))
                 return -ENOENT;
 
         /* kernel provided port index for multiple ports on a single PCI function */
@@ -262,18 +269,60 @@ static bool is_pci_bridge(sd_device *dev) {
         return strneq(p + 2, "04", 2);
 }
 
+static int parse_hotplug_slot_from_function_id(sd_device *dev, const char *slots, uint32_t *ret) {
+        uint64_t function_id;
+        char path[PATH_MAX];
+        const char *attr;
+        int r;
+
+        /* The <sysname>/function_id attribute is unique to the s390 PCI driver. If present, we know
+         * that the slot's directory name for this device is /sys/bus/pci/XXXXXXXX/ where XXXXXXXX is
+         * the fixed length 8 hexadecimal character string representation of function_id. Therefore we
+         * can short cut here and just check for the existence of the slot directory. As this directory
+         * has to exist, we're emitting a debug message for the unlikely case it's not found. Note that
+         * the domain part doesn't belong to the slot name here because there's a 1-to-1 relationship
+         * between PCI function and its hotplug slot. */
+
+        assert(dev);
+        assert(slots);
+        assert(ret);
+
+        if (!naming_scheme_has(NAMING_SLOT_FUNCTION_ID))
+                return 0;
+
+        if (sd_device_get_sysattr_value(dev, "function_id", &attr) < 0)
+                return 0;
+
+        r = safe_atou64(attr, &function_id);
+        if (r < 0)
+                return log_device_debug_errno(dev, r, "Failed to parse function_id, ignoring: %s", attr);
+
+        if (function_id <= 0 || function_id > UINT32_MAX)
+                return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
+                                              "Invalid function id (0x%"PRIx64"), ignoring.",
+                                              function_id);
+
+        if (!snprintf_ok(path, sizeof path, "%s/%08"PRIx64, slots, function_id))
+                return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENAMETOOLONG),
+                                              "PCI slot path is too long, ignoring.");
+
+        if (access(path, F_OK) < 0)
+                return log_device_debug_errno(dev, errno, "Cannot access %s, ignoring: %m", path);
+
+        *ret = (uint32_t) function_id;
+        return 1;
+}
+
 static int dev_pci_slot(sd_device *dev, struct netnames *names) {
-        unsigned long dev_port = 0;
-        unsigned domain, bus, slot, func;
-        int hotplug_slot = -1;
-        size_t l;
-        char *s;
         const char *sysname, *attr, *port_name = NULL, *syspath;
         _cleanup_(sd_device_unrefp) sd_device *pci = NULL;
-        sd_device *hotplug_slot_dev;
-        char slots[PATH_MAX];
         _cleanup_closedir_ DIR *dir = NULL;
-        struct dirent *dent;
+        unsigned domain, bus, slot, func;
+        sd_device *hotplug_slot_dev;
+        unsigned long dev_port = 0;
+        uint32_t hotplug_slot = 0;
+        char slots[PATH_MAX], *s;
+        size_t l;
         int r;
 
         r = sd_device_get_sysname(names->pcidev, &sysname);
@@ -342,18 +391,29 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
 
         hotplug_slot_dev = names->pcidev;
         while (hotplug_slot_dev) {
-                if (sd_device_get_sysname(hotplug_slot_dev, &sysname) < 0)
-                        continue;
+                struct dirent *dent;
+
+                r = parse_hotplug_slot_from_function_id(hotplug_slot_dev, slots, &hotplug_slot);
+                if (r < 0)
+                        return 0;
+                if (r > 0) {
+                        domain = 0; /* See comments in parse_hotplug_slot_from_function_id(). */
+                        break;
+                }
+
+                r = sd_device_get_sysname(hotplug_slot_dev, &sysname);
+                if (r < 0)
+                        return log_device_debug_errno(hotplug_slot_dev, r, "Failed to get sysname: %m");
 
                 FOREACH_DIRENT_ALL(dent, dir, break) {
-                        int i;
-                        char str[PATH_MAX];
                         _cleanup_free_ char *address = NULL;
+                        char str[PATH_MAX];
+                        uint32_t i;
 
                         if (dot_or_dot_dot(dent->d_name))
                                 continue;
 
-                        r = safe_atoi(dent->d_name, &i);
+                        r = safe_atou32(dent->d_name, &i);
                         if (r < 0 || i <= 0)
                                 continue;
 
@@ -368,12 +428,12 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
                                  * devices that will try to claim the same index and that would create name
                                  * collision. */
                                 if (naming_scheme_has(NAMING_BRIDGE_NO_SLOT) && is_pci_bridge(hotplug_slot_dev))
-                                        hotplug_slot = 0;
+                                        return 0;
 
                                 break;
                         }
                 }
-                if (hotplug_slot >= 0)
+                if (hotplug_slot > 0)
                         break;
                 if (sd_device_get_parent_with_subsystem_devtype(hotplug_slot_dev, "pci", NULL, &hotplug_slot_dev) < 0)
                         break;
@@ -385,7 +445,7 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
                 l = sizeof(names->pci_slot);
                 if (domain > 0)
                         l = strpcpyf(&s, l, "P%d", domain);
-                l = strpcpyf(&s, l, "s%d", hotplug_slot);
+                l = strpcpyf(&s, l, "s%"PRIu32, hotplug_slot);
                 if (func > 0 || is_pci_multifunction(names->pcidev))
                         l = strpcpyf(&s, l, "f%d", func);
                 if (port_name)
@@ -945,7 +1005,7 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
                         udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
 
                 if (names.pci_slot[0] &&
-                    snprintf(str, sizeof str, "%s%s%s", prefix, names.pci_slot, names.bcma_core))
+                    snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_slot, names.bcma_core))
                         udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
                 return 0;
         }
index 12597194a91d7e2f64a385d5985da16c99371639..f40b3120ca5bce297efe9370a919779ebfbdef17 100644 (file)
@@ -911,8 +911,9 @@ static int update_devnode(UdevEvent *event) {
         return udev_node_add(dev, apply_mac, event->mode, event->uid, event->gid, event->seclabel_list);
 }
 
-static void event_execute_rules_on_remove(
+static int event_execute_rules_on_remove(
                 UdevEvent *event,
+                int inotify_fd,
                 usec_t timeout_usec,
                 int timeout_signal,
                 Hashmap *properties_list,
@@ -933,13 +934,14 @@ static void event_execute_rules_on_remove(
         if (r < 0)
                 log_device_debug_errno(dev, r, "Failed to delete database under /run/udev/data/, ignoring: %m");
 
-        if (sd_device_get_devnum(dev, NULL) >= 0)
-                (void) udev_watch_end(dev);
+        (void) udev_watch_end(inotify_fd, dev);
 
-        (void) udev_rules_apply_to_event(rules, event, timeout_usec, timeout_signal, properties_list);
+        r = udev_rules_apply_to_event(rules, event, timeout_usec, timeout_signal, properties_list);
 
         if (sd_device_get_devnum(dev, NULL) >= 0)
                 (void) udev_node_remove(dev);
+
+        return r;
 }
 
 static int udev_event_on_move(sd_device *dev) {
@@ -971,12 +973,14 @@ static int copy_all_tags(sd_device *d, sd_device *s) {
         return 0;
 }
 
-int udev_event_execute_rules(UdevEvent *event,
-                             usec_t timeout_usec,
-                             int timeout_signal,
-                             Hashmap *properties_list,
-                             UdevRules *rules) {
-        const char *subsystem;
+int udev_event_execute_rules(
+                UdevEvent *event,
+                int inotify_fd, /* This may be negative */
+                usec_t timeout_usec,
+                int timeout_signal,
+                Hashmap *properties_list,
+                UdevRules *rules) {
+
         sd_device_action_t action;
         sd_device *dev;
         int r;
@@ -986,18 +990,15 @@ int udev_event_execute_rules(UdevEvent *event,
 
         dev = event->dev;
 
-        r = sd_device_get_subsystem(dev, &subsystem);
-        if (r < 0)
-                return log_device_error_errno(dev, r, "Failed to get subsystem: %m");
-
         r = sd_device_get_action(dev, &action);
         if (r < 0)
                 return log_device_error_errno(dev, r, "Failed to get ACTION: %m");
 
-        if (action == SD_DEVICE_REMOVE) {
-                event_execute_rules_on_remove(event, timeout_usec, timeout_signal, properties_list, rules);
-                return 0;
-        }
+        if (action == SD_DEVICE_REMOVE)
+                return event_execute_rules_on_remove(event, inotify_fd, timeout_usec, timeout_signal, properties_list, rules);
+
+        /* Disable watch during event processing. */
+        (void) udev_watch_end(inotify_fd, event->dev);
 
         r = device_clone_with_db(dev, &event->dev_db_clone);
         if (r < 0)
@@ -1007,10 +1008,6 @@ int udev_event_execute_rules(UdevEvent *event,
         if (r < 0)
                 log_device_warning_errno(dev, r, "Failed to copy all tags from old database entry, ignoring: %m");
 
-        if (sd_device_get_devnum(dev, NULL) >= 0)
-                /* Disable watch during event processing. */
-                (void) udev_watch_end(event->dev_db_clone);
-
         if (action == SD_DEVICE_MOVE) {
                 r = udev_event_on_move(event->dev);
                 if (r < 0)
@@ -1048,11 +1045,7 @@ int udev_event_execute_rules(UdevEvent *event,
         /* Yes, we run update_devnode() twice, because in the first invocation, that is before update of udev database,
          * it could happen that two contenders are replacing each other's symlink. Hence we run it again to make sure
          * symlinks point to devices that claim them with the highest priority. */
-        r = update_devnode(event);
-        if (r < 0)
-                return r;
-
-        return 0;
+        return update_devnode(event);
 }
 
 void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_signal) {
@@ -1087,3 +1080,24 @@ void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_s
                 }
         }
 }
+
+int udev_event_process_inotify_watch(UdevEvent *event, int inotify_fd) {
+        sd_device *dev;
+
+        assert(event);
+        assert(inotify_fd >= 0);
+
+        dev = event->dev;
+
+        assert(dev);
+
+        if (device_for_action(dev, SD_DEVICE_REMOVE))
+                return 0;
+
+        if (event->inotify_watch)
+                (void) udev_watch_begin(inotify_fd, dev);
+        else
+                (void) udev_watch_end(inotify_fd, dev);
+
+        return 0;
+}
index ecbe957b4f6affdeb7ea5ed4f8d1cb0a1e95ce5b..2067909fde4c61391620b0f54462b7df216d1d4d 100644 (file)
@@ -51,21 +51,30 @@ UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rt
 UdevEvent *udev_event_free(UdevEvent *event);
 DEFINE_TRIVIAL_CLEANUP_FUNC(UdevEvent*, udev_event_free);
 
-size_t udev_event_apply_format(UdevEvent *event,
-                               const char *src, char *dest, size_t size,
-                               bool replace_whitespace);
+size_t udev_event_apply_format(
+                UdevEvent *event,
+                const char *src,
+                char *dest,
+                size_t size,
+                bool replace_whitespace);
 int udev_check_format(const char *value, size_t *offset, const char **hint);
-int udev_event_spawn(UdevEvent *event,
-                     usec_t timeout_usec,
-                     int timeout_signal,
-                     bool accept_failure,
-                     const char *cmd, char *result, size_t ressize);
-int udev_event_execute_rules(UdevEvent *event,
-                             usec_t timeout_usec,
-                             int timeout_signal,
-                             Hashmap *properties_list,
-                             UdevRules *rules);
+int udev_event_spawn(
+                UdevEvent *event,
+                usec_t timeout_usec,
+                int timeout_signal,
+                bool accept_failure,
+                const char *cmd,
+                char *result,
+                size_t ressize);
+int udev_event_execute_rules(
+                UdevEvent *event,
+                int inotify_fd,
+                usec_t timeout_usec,
+                int timeout_signal,
+                Hashmap *properties_list,
+                UdevRules *rules);
 void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_signal);
+int udev_event_process_inotify_watch(UdevEvent *event, int inotify_fd);
 
 static inline usec_t udev_warn_timeout(usec_t timeout_usec) {
         return DIV_ROUND_UP(timeout_usec, 3);
index 96963a4343ef5cc2a9cd424eaeb94803242d507e..5dc205e36406e3afa29669c47b2d1c06b1977d93 100644 (file)
@@ -30,7 +30,7 @@
 
 static int node_symlink(sd_device *dev, const char *node, const char *slink) {
         _cleanup_free_ char *slink_dirname = NULL, *target = NULL;
-        const char *id_filename, *slink_tmp;
+        const char *id, *slink_tmp;
         struct stat stats;
         int r;
 
@@ -81,10 +81,10 @@ static int node_symlink(sd_device *dev, const char *node, const char *slink) {
         }
 
         log_device_debug(dev, "Atomically replace '%s'", slink);
-        r = device_get_id_filename(dev, &id_filename);
+        r = device_get_device_id(dev, &id);
         if (r < 0)
-                return log_device_error_errno(dev, r, "Failed to get id_filename: %m");
-        slink_tmp = strjoina(slink, ".tmp-", id_filename);
+                return log_device_error_errno(dev, r, "Failed to get device id: %m");
+        slink_tmp = strjoina(slink, ".tmp-", id);
         (void) unlink(slink_tmp);
         do {
                 r = mkdir_parents_label(slink_tmp, 0755);
@@ -147,7 +147,7 @@ static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir,
 
         FOREACH_DIRENT_ALL(dent, dir, break) {
                 _cleanup_(sd_device_unrefp) sd_device *dev_db = NULL;
-                const char *devnode, *id_filename;
+                const char *devnode, *id;
                 int db_prio = 0;
 
                 if (dent->d_name[0] == '\0')
@@ -157,11 +157,11 @@ static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir,
 
                 log_device_debug(dev, "Found '%s' claiming '%s'", dent->d_name, stackdir);
 
-                if (device_get_id_filename(dev, &id_filename) < 0)
+                if (device_get_device_id(dev, &id) < 0)
                         continue;
 
                 /* did we find ourself? */
-                if (streq(dent->d_name, id_filename))
+                if (streq(dent->d_name, id))
                         continue;
 
                 if (sd_device_new_from_device_id(&dev_db, dent->d_name) < 0)
@@ -229,21 +229,21 @@ static size_t escape_path(const char *src, char *dest, size_t size) {
 static int link_update(sd_device *dev, const char *slink, bool add) {
         _cleanup_free_ char *filename = NULL, *dirname = NULL;
         char name_enc[PATH_MAX];
-        const char *id_filename;
+        const char *id;
         int i, r, retries;
 
         assert(dev);
         assert(slink);
 
-        r = device_get_id_filename(dev, &id_filename);
+        r = device_get_device_id(dev, &id);
         if (r < 0)
-                return log_device_debug_errno(dev, r, "Failed to get id_filename: %m");
+                return log_device_debug_errno(dev, r, "Failed to get device id: %m");
 
         escape_path(slink + STRLEN("/dev"), name_enc, sizeof(name_enc));
         dirname = path_join("/run/udev/links/", name_enc);
         if (!dirname)
                 return log_oom();
-        filename = path_join(dirname, id_filename);
+        filename = path_join(dirname, id);
         if (!filename)
                 return log_oom();
 
@@ -348,7 +348,7 @@ int udev_node_update_old_links(sd_device *dev, sd_device *dev_old) {
 static int node_permissions_apply(sd_device *dev, bool apply_mac,
                                   mode_t mode, uid_t uid, gid_t gid,
                                   OrderedHashmap *seclabel_list) {
-        const char *devnode, *subsystem, *id_filename = NULL;
+        const char *devnode, *subsystem, *id = NULL;
         bool apply_mode, apply_uid, apply_gid;
         _cleanup_close_ int node_fd = -1;
         struct stat stats;
@@ -366,7 +366,7 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
         r = sd_device_get_devnum(dev, &devnum);
         if (r < 0)
                 return log_device_debug_errno(dev, r, "Failed to get devnum: %m");
-        (void) device_get_id_filename(dev, &id_filename);
+        (void) device_get_device_id(dev, &id);
 
         if (streq(subsystem, "block"))
                 mode |= S_IFBLK;
@@ -388,7 +388,7 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
 
         if ((mode != MODE_INVALID && (stats.st_mode & S_IFMT) != (mode & S_IFMT)) || stats.st_rdev != devnum) {
                 log_device_debug(dev, "Found node '%s' with non-matching devnum %s, skipping handling.",
-                                 devnode, id_filename);
+                                 devnode, strna(id));
                 return 0; /* We might process a device that already got replaced by the time we have a look
                            * at it, handle this gracefully and step away. */
         }
@@ -509,10 +509,10 @@ int udev_node_add(sd_device *dev, bool apply,
                 return log_device_debug_errno(dev, r, "Failed to get devnode: %m");
 
         if (DEBUG_LOGGING) {
-                const char *id_filename = NULL;
+                const char *id = NULL;
 
-                (void) device_get_id_filename(dev, &id_filename);
-                log_device_debug(dev, "Handling device node '%s', devnum=%s", devnode, strnull(id_filename));
+                (void) device_get_device_id(dev, &id);
+                log_device_debug(dev, "Handling device node '%s', devnum=%s", devnode, strna(id));
         }
 
         r = node_permissions_apply(dev, apply, mode, uid, gid, seclabel_list);
index 57ede6a197f6dffef867b835fb11f4de8c1dd35f..edf2c385bd4ec2834ea898589915cfe2040a7ebc 100644 (file)
@@ -184,21 +184,30 @@ struct UdevRules {
 
 /*** Logging helpers ***/
 
-#define log_rule_full_errno(device, rules, level, error, fmt, ...)      \
+#define log_rule_full_errno_zerook(device, rules, level, error, fmt, ...) \
         ({                                                              \
                 UdevRules *_r = (rules);                                \
                 UdevRuleFile *_f = _r ? _r->current_file : NULL;        \
                 UdevRuleLine *_l = _f ? _f->current_line : NULL;        \
                 const char *_n = _f ? _f->filename : NULL;              \
                                                                         \
-                log_device_full_errno(device, level, error, "%s:%u " fmt, \
-                                      strna(_n), _l ? _l->line_number : 0, \
-                                      ##__VA_ARGS__);                   \
+                log_device_full_errno_zerook(                           \
+                                device, level, error, "%s:%u " fmt,     \
+                                strna(_n), _l ? _l->line_number : 0,    \
+                                ##__VA_ARGS__);                         \
+        })
+
+#define log_rule_full_errno(device, rules, level, error, fmt, ...)      \
+        ({                                                              \
+                int _error = (error);                                   \
+                ASSERT_NON_ZERO(_error);                                \
+                log_rule_full_errno_zerook(                             \
+                    device, rules, level, _error, fmt, ##__VA_ARGS__);  \
         })
 
-#define log_rule_full(device, rules, level, ...)   (void) log_rule_full_errno(device, rules, level, 0, __VA_ARGS__)
+#define log_rule_full(device, rules, level, ...)   (void) log_rule_full_errno_zerook(device, rules, level, 0, __VA_ARGS__)
 
-#define log_rule_debug(device, rules, ...)   log_rule_full_errno(device, rules, LOG_DEBUG, 0, __VA_ARGS__)
+#define log_rule_debug(device, rules, ...)   log_rule_full(device, rules, LOG_DEBUG, __VA_ARGS__)
 #define log_rule_info(device, rules, ...)    log_rule_full(device, rules, LOG_INFO, __VA_ARGS__)
 #define log_rule_notice(device, rules, ...)  log_rule_full(device, rules, LOG_NOTICE, __VA_ARGS__)
 #define log_rule_warning(device, rules, ...) log_rule_full(device, rules, LOG_WARNING, __VA_ARGS__)
@@ -210,10 +219,11 @@ struct UdevRules {
 #define log_rule_warning_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_WARNING, error, __VA_ARGS__)
 #define log_rule_error_errno(device, rules, error, ...)   log_rule_full_errno(device, rules, LOG_ERR, error, __VA_ARGS__)
 
+#define log_token_full_errno_zerook(rules, level, error, ...) log_rule_full_errno_zerook(NULL, rules, level, error, __VA_ARGS__)
 #define log_token_full_errno(rules, level, error, ...) log_rule_full_errno(NULL, rules, level, error, __VA_ARGS__)
-#define log_token_full(rules, level, ...)  (void) log_token_full_errno(rules, level, 0, __VA_ARGS__)
+#define log_token_full(rules, level, ...)  (void) log_token_full_errno_zerook(rules, level, 0, __VA_ARGS__)
 
-#define log_token_debug(rules, ...)   log_token_full_errno(rules, LOG_DEBUG, 0, __VA_ARGS__)
+#define log_token_debug(rules, ...)   log_token_full(rules, LOG_DEBUG, __VA_ARGS__)
 #define log_token_info(rules, ...)    log_token_full(rules, LOG_INFO, __VA_ARGS__)
 #define log_token_notice(rules, ...)  log_token_full(rules, LOG_NOTICE, __VA_ARGS__)
 #define log_token_warning(rules, ...) log_token_full(rules, LOG_WARNING, __VA_ARGS__)
@@ -2123,7 +2133,11 @@ static int udev_rule_apply_token_to_event(
                 (void) udev_event_apply_format(event, token->value, value, sizeof(value), false);
 
                 log_rule_debug(dev, rules, "ATTR '%s' writing '%s'", buf, value);
-                r = write_string_file(buf, value, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER | WRITE_STRING_FILE_AVOID_NEWLINE);
+                r = write_string_file(buf, value,
+                                      WRITE_STRING_FILE_VERIFY_ON_FAILURE |
+                                      WRITE_STRING_FILE_DISABLE_BUFFER |
+                                      WRITE_STRING_FILE_AVOID_NEWLINE |
+                                      WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE);
                 if (r < 0)
                         log_rule_error_errno(dev, rules, r, "Failed to write ATTR{%s}, ignoring: %m", buf);
                 break;
index 8656fb0076dc4b7c39553bc0a55f8633b929a43a..7f15c87870e8b745d73d047a2cb5cb071e886c23 100644 (file)
@@ -5,72 +5,60 @@
  */
 
 #include <sys/inotify.h>
-#include <unistd.h>
 
 #include "alloc-util.h"
 #include "device-private.h"
 #include "device-util.h"
 #include "dirent-util.h"
 #include "fs-util.h"
-#include "mkdir.h"
-#include "stdio-util.h"
+#include "parse-util.h"
 #include "udev-watch.h"
 
-static int inotify_fd = -1;
-
-/* inotify descriptor, will be shared with rules directory;
- * set to cloexec since we need our children to be able to add
- * watches for us. */
-int udev_watch_init(void) {
-        inotify_fd = inotify_init1(IN_CLOEXEC);
-        if (inotify_fd < 0)
-                return -errno;
-
-        return inotify_fd;
-}
-
-/* Move any old watches directory out of the way, and then restore the watches. */
-int udev_watch_restore(void) {
+int udev_watch_restore(int inotify_fd) {
         struct dirent *ent;
         DIR *dir;
         int r;
 
-        if (inotify_fd < 0)
-                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "Invalid inotify descriptor.");
+        /* Move any old watches directory out of the way, and then restore the watches. */
+
+        assert(inotify_fd >= 0);
 
         if (rename("/run/udev/watch", "/run/udev/watch.old") < 0) {
                 if (errno != ENOENT)
-                        return log_warning_errno(errno, "Failed to move watches directory /run/udev/watch. Old watches will not be restored: %m");
+                        return log_warning_errno(errno, "Failed to move watches directory /run/udev/watch. "
+                                                 "Old watches will not be restored: %m");
 
                 return 0;
         }
 
         dir = opendir("/run/udev/watch.old");
         if (!dir)
-                return log_warning_errno(errno, "Failed to open old watches directory /run/udev/watch.old. Old watches will not be restored: %m");
+                return log_warning_errno(errno, "Failed to open old watches directory /run/udev/watch.old. "
+                                         "Old watches will not be restored: %m");
 
         FOREACH_DIRENT_ALL(ent, dir, break) {
                 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
-                _cleanup_free_ char *device = NULL;
+                int wd;
 
                 if (ent->d_name[0] == '.')
                         continue;
 
-                r = readlinkat_malloc(dirfd(dir), ent->d_name, &device);
-                if (r < 0) {
-                        log_debug_errno(r, "Failed to read link '/run/udev/watch.old/%s', ignoring: %m", ent->d_name);
+                /* For backward compatibility, read symlink from watch handle to device id, and ignore
+                 * the opposite direction symlink. */
+
+                if (safe_atoi(ent->d_name, &wd) < 0)
                         goto unlink;
-                }
 
-                r = sd_device_new_from_device_id(&dev, device);
+                r = device_new_from_watch_handle_at(&dev, dirfd(dir), wd);
                 if (r < 0) {
-                        log_debug_errno(r, "Failed to create sd_device object for '%s', ignoring: %m", device);
+                        log_full_errno(r == -ENODEV ? LOG_DEBUG : LOG_WARNING, r,
+                                       "Failed to create sd_device object from saved watch handle '%s', ignoring: %m",
+                                       ent->d_name);
                         goto unlink;
                 }
 
                 log_device_debug(dev, "Restoring old watch");
-                (void) udev_watch_begin(dev);
+                (void) udev_watch_begin(inotify_fd, dev);
 unlink:
                 (void) unlinkat(dirfd(dir), ent->d_name, 0);
         }
@@ -81,94 +69,54 @@ unlink:
         return 0;
 }
 
-int udev_watch_begin(sd_device *dev) {
-        char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
-        const char *devnode, *id_filename;
+int udev_watch_begin(int inotify_fd, sd_device *dev) {
+        const char *devnode;
         int wd, r;
 
-        if (inotify_fd < 0)
-                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "Invalid inotify descriptor.");
+        assert(inotify_fd >= 0);
+        assert(dev);
 
         r = sd_device_get_devname(dev, &devnode);
         if (r < 0)
-                return log_device_error_errno(dev, r, "Failed to get device name: %m");
+                return log_device_debug_errno(dev, r, "Failed to get device name: %m");
 
         log_device_debug(dev, "Adding watch on '%s'", devnode);
         wd = inotify_add_watch(inotify_fd, devnode, IN_CLOSE_WRITE);
-        if (wd < 0)
-                return log_device_full_errno(dev, errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
-                                             "Failed to add device '%s' to watch: %m", devnode);
-
-        device_set_watch_handle(dev, wd);
-
-        xsprintf(filename, "/run/udev/watch/%d", wd);
-        r = mkdir_parents(filename, 0755);
-        if (r < 0)
-                return log_device_error_errno(dev, r, "Failed to create parent directory of '%s': %m", filename);
-        (void) unlink(filename);
+        if (wd < 0) {
+                r = log_device_full_errno(dev, errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
+                                          errno, "Failed to add device '%s' to watch: %m", devnode);
 
-        r = device_get_id_filename(dev, &id_filename);
-        if (r < 0)
-                return log_device_error_errno(dev, r, "Failed to get device id-filename: %m");
-
-        if (symlink(id_filename, filename) < 0)
-                return log_device_error_errno(dev, errno, "Failed to create symlink %s: %m", filename);
-
-        return 0;
-}
-
-int udev_watch_end(sd_device *dev) {
-        char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
-        int wd, r;
-
-        if (inotify_fd < 0)
-                return 0; /* Nothing to do. */
+                (void) device_set_watch_handle(dev, -1);
+                return r;
+        }
 
-        r = device_get_watch_handle(dev, &wd);
-        if (r == -ENOENT)
-                return 0;
+        r = device_set_watch_handle(dev, wd);
         if (r < 0)
-                return log_device_debug_errno(dev, r, "Failed to get watch handle, ignoring: %m");
-
-        log_device_debug(dev, "Removing watch");
-        (void) inotify_rm_watch(inotify_fd, wd);
-
-        xsprintf(filename, "/run/udev/watch/%d", wd);
-        (void) unlink(filename);
-
-        device_set_watch_handle(dev, -1);
+                return log_device_warning_errno(dev, r, "Failed to save watch handle in /run/udev/watch: %m");
 
         return 0;
 }
 
-int udev_watch_lookup(int wd, sd_device **ret) {
-        char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
-        _cleanup_free_ char *device = NULL;
-        int r;
+int udev_watch_end(int inotify_fd, sd_device *dev) {
+        int wd;
 
-        assert(ret);
+        assert(dev);
 
+        /* This may be called by 'udevadm test'. In that case, inotify_fd is not initialized. */
         if (inotify_fd < 0)
-                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "Invalid inotify descriptor.");
-
-        if (wd < 0)
-                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "Invalid watch handle.");
-
-        xsprintf(filename, "/run/udev/watch/%d", wd);
-        r = readlink_malloc(filename, &device);
-        if (r == -ENOENT)
                 return 0;
-        if (r < 0)
-                return log_debug_errno(r, "Failed to read link '%s': %m", filename);
 
-        r = sd_device_new_from_device_id(ret, device);
-        if (r == -ENODEV)
+        if (sd_device_get_devname(dev, NULL) < 0)
                 return 0;
-        if (r < 0)
-                return log_debug_errno(r, "Failed to create sd_device object for '%s': %m", device);
 
-        return 1;
+        wd = device_get_watch_handle(dev);
+        if (wd < 0)
+                log_device_debug_errno(dev, wd, "Failed to get watch handle, ignoring: %m");
+        else {
+                log_device_debug(dev, "Removing watch");
+                (void) inotify_rm_watch(inotify_fd, wd);
+        }
+        (void) device_set_watch_handle(dev, -1);
+
+        return 0;
 }
index a15fa2767e836379fca6e5df6fea43d7ce355c79..d211d99f49de7937d629e99575eb4b5ae97c07cb 100644 (file)
@@ -3,8 +3,6 @@
 
 #include "sd-device.h"
 
-int udev_watch_init(void);
-int udev_watch_restore(void);
-int udev_watch_begin(sd_device *dev);
-int udev_watch_end(sd_device *dev);
-int udev_watch_lookup(int wd, sd_device **ret);
+int udev_watch_restore(int inotify_fd);
+int udev_watch_begin(int inotify_fd, sd_device *dev);
+int udev_watch_end(int inotify_fd, sd_device *dev);
index 71cc0d2d9b87eb479516e4b8490dd24c32923a5b..33fdecca50eeec1356dde4e932df66b95af6a643 100644 (file)
@@ -249,8 +249,6 @@ static void cleanup_dir(DIR *dir, mode_t mask, int depth) {
 static void cleanup_db(void) {
         _cleanup_closedir_ DIR *dir1 = NULL, *dir2 = NULL, *dir3 = NULL, *dir4 = NULL, *dir5 = NULL;
 
-        (void) unlink("/run/udev/queue.bin");
-
         dir1 = opendir("/run/udev/data");
         if (dir1)
                 cleanup_dir(dir1, S_ISVTX, 1);
index 7a30e25135c5dad6976b8d4cc2d59bda7115a19c..fbac719fa066a1955a6c97cc6883b41691bd7c05 100644 (file)
@@ -141,7 +141,7 @@ int test_main(int argc, char *argv[], void *userdata) {
         assert_se(sigfillset(&mask) >= 0);
         assert_se(sigprocmask(SIG_SETMASK, &mask, &sigmask_orig) >= 0);
 
-        udev_event_execute_rules(event, 60 * USEC_PER_SEC, SIGKILL, NULL, rules);
+        udev_event_execute_rules(event, -1, 60 * USEC_PER_SEC, SIGKILL, NULL, rules);
 
         FOREACH_DEVICE_PROPERTY(dev, key, value)
                 printf("%s=%s\n", key, value);
index 162bbb9a43616154ab162a1ce06d57fc3d10383b..75ce633632bf663098aecbf3ca947ebed4dd6bdb 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <stdio.h>
 
-#include "build.h"
 #include "macro.h"
 
 int info_main(int argc, char *argv[], void *userdata);
index 6fffd8407b74567b3a53037cd96fb6277f09b074..5574abce9d67b9000ea3d4f6eb8b82f118e78506 100644 (file)
@@ -28,7 +28,6 @@
 #include "sd-event.h"
 
 #include "alloc-util.h"
-#include "build.h"
 #include "cgroup-util.h"
 #include "cpu-set-util.h"
 #include "dev-setup.h"
@@ -65,6 +64,7 @@
 #include "udev-util.h"
 #include "udev-watch.h"
 #include "user-util.h"
+#include "version.h"
 
 #define WORKER_NUM_MAX 2048U
 
@@ -92,10 +92,12 @@ typedef struct Manager {
 
         sd_device_monitor *monitor;
         struct udev_ctrl *ctrl;
-        int fd_inotify;
         int worker_watch[2];
 
+        /* used by udev-watch */
+        int inotify_fd;
         sd_event_source *inotify_event;
+
         sd_event_source *kill_workers_event;
 
         usec_t last_usec;
@@ -134,6 +136,7 @@ enum worker_state {
         WORKER_RUNNING,
         WORKER_IDLE,
         WORKER_KILLED,
+        WORKER_KILLING,
 };
 
 struct worker {
@@ -303,7 +306,7 @@ static Manager* manager_free(Manager *manager) {
         hashmap_free_free_free(manager->properties);
         udev_rules_free(manager->rules);
 
-        safe_close(manager->fd_inotify);
+        safe_close(manager->inotify_fd);
         safe_close_pair(manager->worker_watch);
 
         return mfree(manager);
@@ -472,7 +475,7 @@ static int worker_process_device(Manager *manager, sd_device *dev) {
                  * degree — they go hand-in-hand after all. */
 
                 log_device_debug(dev, "Block device is currently locked, installing watch to wait until the lock is released.");
-                (void) udev_watch_begin(dev);
+                (void) udev_watch_begin(manager->inotify_fd, dev);
 
                 /* Now the watch is installed, let's lock the device again, maybe in the meantime things changed */
                 r = worker_lock_block_device(dev, &fd_lock);
@@ -483,7 +486,13 @@ static int worker_process_device(Manager *manager, sd_device *dev) {
         (void) worker_mark_block_device_read_only(dev);
 
         /* apply rules, create node, symlinks */
-        r = udev_event_execute_rules(udev_event, arg_event_timeout_usec, arg_timeout_signal, manager->properties, manager->rules);
+        r = udev_event_execute_rules(
+                          udev_event,
+                          manager->inotify_fd,
+                          arg_event_timeout_usec,
+                          arg_timeout_signal,
+                          manager->properties,
+                          manager->rules);
         if (r < 0)
                 return r;
 
@@ -493,14 +502,9 @@ static int worker_process_device(Manager *manager, sd_device *dev) {
                 /* in case rtnl was initialized */
                 manager->rtnl = sd_netlink_ref(udev_event->rtnl);
 
-        /* apply/restore/end inotify watch */
-        if (udev_event->inotify_watch) {
-                (void) udev_watch_begin(dev);
-                r = device_update_db(dev);
-                if (r < 0)
-                        return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
-        } else
-                (void) udev_watch_end(dev);
+        r = udev_event_process_inotify_watch(udev_event, manager->inotify_fd);
+        if (r < 0)
+                return r;
 
         log_device_uevent(dev, "Device processed");
         return 0;
@@ -728,7 +732,7 @@ static int event_queue_insert(Manager *manager, sd_device *dev) {
         return 0;
 }
 
-static void manager_kill_workers(Manager *manager) {
+static void manager_kill_workers(Manager *manager, bool force) {
         struct worker *worker;
 
         assert(manager);
@@ -737,6 +741,11 @@ static void manager_kill_workers(Manager *manager) {
                 if (worker->state == WORKER_KILLED)
                         continue;
 
+                if (worker->state == WORKER_RUNNING && !force) {
+                        worker->state = WORKER_KILLING;
+                        continue;
+                }
+
                 worker->state = WORKER_KILLED;
                 (void) kill(worker->pid, SIGTERM);
         }
@@ -866,13 +875,13 @@ static void manager_exit(Manager *manager) {
         manager->ctrl = udev_ctrl_unref(manager->ctrl);
 
         manager->inotify_event = sd_event_source_unref(manager->inotify_event);
-        manager->fd_inotify = safe_close(manager->fd_inotify);
+        manager->inotify_fd = safe_close(manager->inotify_fd);
 
         manager->monitor = sd_device_monitor_unref(manager->monitor);
 
         /* discard queued events and kill workers */
         event_queue_cleanup(manager, EVENT_QUEUED);
-        manager_kill_workers(manager);
+        manager_kill_workers(manager, true);
 }
 
 /* reload requested, HUP signal received, rules changed, builtin changed */
@@ -884,7 +893,7 @@ static void manager_reload(Manager *manager) {
                   "RELOADING=1\n"
                   "STATUS=Flushing configuration...");
 
-        manager_kill_workers(manager);
+        manager_kill_workers(manager, false);
         manager->rules = udev_rules_free(manager->rules);
         udev_builtin_exit();
 
@@ -899,7 +908,7 @@ static int on_kill_workers_event(sd_event_source *s, uint64_t usec, void *userda
         assert(manager);
 
         log_debug("Cleanup idle workers");
-        manager_kill_workers(manager);
+        manager_kill_workers(manager, false);
 
         return 1;
 }
@@ -1014,7 +1023,10 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
                         continue;
                 }
 
-                if (worker->state != WORKER_KILLED)
+                if (worker->state == WORKER_KILLING) {
+                        worker->state = WORKER_KILLED;
+                        (void) kill(worker->pid, SIGTERM);
+                } else if (worker->state != WORKER_KILLED)
                         worker->state = WORKER_IDLE;
 
                 /* worker returned */
@@ -1060,7 +1072,7 @@ static int on_ctrl_msg(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, co
                 log_debug("Received udev control message (SET_LOG_LEVEL), setting log_level=%i", value->intval);
                 log_set_max_level(value->intval);
                 manager->log_level = value->intval;
-                manager_kill_workers(manager);
+                manager_kill_workers(manager, false);
                 break;
         case UDEV_CTRL_STOP_EXEC_QUEUE:
                 log_debug("Received udev control message (STOP_EXEC_QUEUE)");
@@ -1125,7 +1137,7 @@ static int on_ctrl_msg(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, co
                 }
 
                 key = val = NULL;
-                manager_kill_workers(manager);
+                manager_kill_workers(manager, false);
                 break;
         }
         case UDEV_CTRL_SET_CHILDREN_MAX:
@@ -1290,17 +1302,21 @@ static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userda
                 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
                 const char *devnode;
 
-                if (udev_watch_lookup(e->wd, &dev) <= 0)
+                r = device_new_from_watch_handle(&dev, e->wd);
+                if (r < 0) {
+                        log_debug_errno(r, "Failed to create sd_device object from watch handle, ignoring: %m");
                         continue;
+                }
 
                 if (sd_device_get_devname(dev, &devnode) < 0)
                         continue;
 
                 log_device_debug(dev, "Inotify event: %x for %s", e->mask, devnode);
                 if (e->mask & IN_CLOSE_WRITE)
-                        synthesize_change(dev);
-                else if (e->mask & IN_IGNORED)
-                        udev_watch_end(dev);
+                        (void) synthesize_change(dev);
+
+                /* Do not handle IN_IGNORED here. It should be handled by worker in 'remove' uevent;
+                 * udev_event_execute_rules() -> event_execute_rules_on_remove() -> udev_watch_end(). */
         }
 
         return 1;
@@ -1660,7 +1676,7 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
                 return log_oom();
 
         *manager = (Manager) {
-                .fd_inotify = -1,
+                .inotify_fd = -1,
                 .worker_watch = { -1, -1 },
                 .cgroup = cgroup,
         };
@@ -1713,12 +1729,11 @@ static int main_loop(Manager *manager) {
         if (r < 0)
                 return log_error_errno(r, "Failed to enable SO_PASSCRED: %m");
 
-        r = udev_watch_init();
-        if (r < 0)
-                return log_error_errno(r, "Failed to create inotify descriptor: %m");
-        manager->fd_inotify = r;
+        manager->inotify_fd = inotify_init1(IN_CLOEXEC);
+        if (manager->inotify_fd < 0)
+                return log_error_errno(errno, "Failed to create inotify descriptor: %m");
 
-        udev_watch_restore();
+        udev_watch_restore(manager->inotify_fd);
 
         /* block and listen to all signals on signalfd */
         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);
@@ -1763,7 +1778,7 @@ static int main_loop(Manager *manager) {
         if (r < 0)
                 return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m");
 
-        r = sd_event_add_io(manager->event, &manager->inotify_event, manager->fd_inotify, EPOLLIN, on_inotify, manager);
+        r = sd_event_add_io(manager->event, &manager->inotify_event, manager->inotify_fd, EPOLLIN, on_inotify, manager);
         if (r < 0)
                 return log_error_errno(r, "Failed to create inotify event source: %m");
 
index 38df4cddf085eaee6b732b8329161d7b10151997..0995e3557ebef867cce9ab5b3d03416470839e53 100644 (file)
@@ -44,7 +44,7 @@ static void context_clear(Context *c) {
 #endif
 }
 
-static usec_t get_startup_time(Context *c) {
+static usec_t get_startup_monotonic_time(Context *c) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         usec_t t = 0;
         int r;
@@ -56,7 +56,7 @@ static usec_t get_startup_time(Context *c) {
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
                         "org.freedesktop.systemd1.Manager",
-                        "UserspaceTimestamp",
+                        "UserspaceTimestampMonotonic",
                         &error,
                         't', &t);
         if (r < 0) {
@@ -115,6 +115,7 @@ static int get_current_runlevel(Context *c) {
 static int on_reboot(Context *c) {
         int r = 0, q;
         usec_t t;
+        usec_t boottime;
 
         assert(c);
 
@@ -130,9 +131,15 @@ static int on_reboot(Context *c) {
 
         /* If this call fails it will return 0, which
          * utmp_put_reboot() will then fix to the current time */
-        t = get_startup_time(c);
-
-        q = utmp_put_reboot(t);
+        t = get_startup_monotonic_time(c);
+        boottime = map_clock_usec(t, CLOCK_MONOTONIC, CLOCK_REALTIME);
+        /* We query the recorded monotonic time here (instead of the system clock CLOCK_REALTIME),
+         * even though we actually want the system clock time. That's because there's a likely
+         * chance that the system clock wasn't set right during early boot. By manually converting
+         * the monotonic clock to the system clock here we can compensate
+         * for incorrectly set clocks during early boot. */
+
+        q = utmp_put_reboot(boottime);
         if (q < 0)
                 r = log_error_errno(q, "Failed to write utmp record: %m");
 
index f8d315ce2de3b2d6015dcaa9b6f76a4073390b4b..3fd82255ac63b099a311083b05ca808399f4191a 100644 (file)
@@ -267,7 +267,7 @@ int manager_startup(Manager *m) {
         else {
                 union sockaddr_union sockaddr = {
                         .un.sun_family = AF_UNIX,
-                        .un.sun_path = "/run/systemd/userdb/io.systemd.NameServiceSwitch",
+                        .un.sun_path = "/run/systemd/userdb/io.systemd.Multiplexer",
                 };
 
                 r = mkdir_p("/run/systemd/userdb", 0755);
@@ -284,7 +284,8 @@ int manager_startup(Manager *m) {
                         if (bind(m->listen_fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0)
                                 return log_error_errno(errno, "Failed to bind socket: %m");
 
-                r = symlink_idempotent("io.systemd.NameServiceSwitch", "/run/systemd/userdb/io.systemd.Multiplexer", false);
+                r = symlink_idempotent("io.systemd.Multiplexer",
+                                       "/run/systemd/userdb/io.systemd.NameServiceSwitch", false);
                 if (r < 0)
                         return log_error_errno(r, "Failed to bind io.systemd.Multiplexer: %m");
 
index 45915ef853bfb54a5f090c070f6d224823132229..d1c3febdd5bb95ac91d0b9ac28b4cb72d296266e 100644 (file)
@@ -146,7 +146,7 @@ static int keyboard_load_and_wait(const char *vc, const char *map, const char *m
         args[i++] = NULL;
 
         if (DEBUG_LOGGING) {
-                _cleanup_free_ char *cmd;
+                _cleanup_free_ char *cmd = NULL;
 
                 cmd = strv_join((char**) args, " ");
                 log_debug("Executing \"%s\"...", strnull(cmd));
@@ -189,7 +189,7 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map,
         args[i++] = NULL;
 
         if (DEBUG_LOGGING) {
-                _cleanup_free_ char *cmd;
+                _cleanup_free_ char *cmd = NULL;
 
                 cmd = strv_join((char**) args, " ");
                 log_debug("Executing \"%s\"...", strnull(cmd));
index 1528432f43329fa9edeeb59bb1f089e531ba609b..00d8b76539844a0ab218c7e8db454c9acd59192c 100644 (file)
@@ -599,6 +599,7 @@ int xdg_autostart_service_generate_unit(
         fprintf(f,
                 "\n[Service]\n"
                 "Type=exec\n"
+                "ExitType=cgroup\n"
                 "ExecStart=:%s\n"
                 "Restart=no\n"
                 "TimeoutSec=5s\n"
index 66c35fe2b723a176955924745cea0c186069da6e..d42c0df9a02948f90171779d57d030d961b5772f 100755 (executable)
@@ -1,17 +1,19 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="Basic systemd setup"
 IMAGE_NAME="basic"
 RUN_IN_UNPRIVILEGED_CONTAINER=${RUN_IN_UNPRIVILEGED_CONTAINER:-yes}
 TEST_REQUIRE_INSTALL_TESTS=0
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
 test_append_files() {
     # install tests manually so the test is functional even when -Dinstall-tests=false
-    local dst="$1/usr/lib/systemd/tests/testdata/units/"
+    local dst="${1:?}/usr/lib/systemd/tests/testdata/units/"
     mkdir -p "$dst"
-    cp -v $TEST_UNITS_DIR/{testsuite-01,end}.service $TEST_UNITS_DIR/testsuite.target "$dst"
+    cp -v "$TEST_UNITS_DIR"/{testsuite-01,end}.service "$TEST_UNITS_DIR/testsuite.target" "$dst"
 }
 
-do_test "$@" 01
+do_test "$@"
index 6143d3352b01ba56c46574ace65145b3173e5202..906d7cacd489fca358f9dbc8e6f789e685cbff53 100755 (executable)
@@ -1,5 +1,6 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="Run unit tests under containers"
 RUN_IN_UNPRIVILEGED_CONTAINER=yes
 
@@ -11,53 +12,63 @@ frobnicate!
 $KERNEL_APPEND
 "
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
 check_result_nspawn() {
-    local _ret=1
-    [[ -e $1/testok ]] && _ret=0
-    if [[ -s $1/failed ]]; then
-        _ret=$(($_ret+1))
+    local workspace="${1:?}"
+    local ret=1
+
+    [[ -e "$workspace/testok" ]] && ret=0
+
+    if [[ -s "$workspace/failed" ]]; then
+        ret=$((ret + 1))
         echo "=== Failed test log ==="
-        cat $1/failed
+        cat "$workspace/failed"
     else
-        if [[ -s $1/skipped ]]; then
+        if [[ -s "$workspace/skipped" ]]; then
             echo "=== Skipped test log =="
-            cat $1/skipped
+            cat "$workspace/skipped"
         fi
-        if [[ -s $1/testok ]]; then
+        if [[ -s "$workspace/testok" ]]; then
             echo "=== Passed tests ==="
-            cat $1/testok
+            cat "$workspace/testok"
         fi
     fi
-    save_journal $1/var/log/journal
-    _umount_dir $initdir
-    [[ -n "$TIMED_OUT" ]] && _ret=$(($_ret+1))
-    return $_ret
+
+    save_journal "$workspace/var/log/journal"
+    _umount_dir "${initdir:?}"
+
+    [[ -n "${TIMED_OUT:=}" ]] && ret=1
+    return $ret
 }
 
 check_result_qemu() {
-    local _ret=1
+    local ret=1
+
     mount_initdir
-    [[ -e $initdir/testok ]] && _ret=0
-    if [[ -s $initdir/failed ]]; then
-        _ret=$(($_ret+1))
+    [[ -e "${initdir:?}/testok" ]] && ret=0
+
+    if [[ -s "$initdir/failed" ]]; then
+        ret=$((ret + 1))
         echo "=== Failed test log ==="
-        cat $initdir/failed
+        cat "$initdir/failed"
     else
-        if [[ -s $initdir/skipped ]]; then
+        if [[ -s "$initdir/skipped" ]]; then
             echo "=== Skipped test log =="
-            cat $initdir/skipped
+            cat "$initdir/skipped"
         fi
-        if [[ -s $initdir/testok ]]; then
+        if [[ -s "$initdir/testok" ]]; then
             echo "=== Passed tests ==="
-            cat $initdir/testok
+            cat "$initdir/testok"
         fi
     fi
-    save_journal $initdir/var/log/journal
-    _umount_dir $initdir
-    [[ -n "$TIMED_OUT" ]] && _ret=$(($_ret+1))
-    return $_ret
+
+    save_journal "$initdir/var/log/journal"
+    _umount_dir "$initdir"
+
+    [[ -n "${TIMED_OUT:=}" ]] && ret=1
+    return $ret
 }
 
-do_test "$@" 02
+do_test "$@"
index 221a18682a9f90820db8357ee837716c7b13bdbe..4ffa1bd6f4f9f02424a1665ac90f52be69c72e95 100755 (executable)
@@ -1,9 +1,11 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="Job-related tests"
 TEST_NO_QEMU=1
 IMAGE_NAME="default"
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 03
+do_test "$@"
index f16543c2b44b7ebd7076357af9f2d6f8c7d674d9..3d7dff976bcaadfd9233c58cab41c6d4e02eb27c 100755 (executable)
@@ -1,7 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="Journal-related tests"
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 04
+do_test "$@"
index 463fe42a7cf200f78ae5c6d8dc8c540128b682c1..12b4530dd4504d2ccbe097b7cc1e70d88a282b74 100755 (executable)
@@ -1,7 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="Resource limits-related tests"
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 05
+do_test "$@"
index f05cd355938bfa1ba9ab5af05e55daa6d6d87a48..978c930b71ac00872fec3a9a36f4d18c40f124e4 100755 (executable)
@@ -1,5 +1,6 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="SELinux tests"
 IMAGE_NAME="selinux"
 TEST_NO_NSPAWN=1
@@ -12,32 +13,39 @@ TEST_NO_NSPAWN=1
 # 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
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
 SETUP_SELINUX=yes
-KERNEL_APPEND="$KERNEL_APPEND selinux=1 security=selinux"
+KERNEL_APPEND="${KERNEL_APPEND:=} selinux=1 security=selinux"
 
 test_append_files() {
     (
+        local workspace="${1:?}"
+        local policy_headers_dir=/usr/share/selinux/devel
+        local modules_dir=/var/lib/selinux
+
         setup_selinux
-        local _modules_dir=/var/lib/selinux
-        rm -rf $1/$_modules_dir
-        if ! cp -ar $_modules_dir $1/$_modules_dir; then
-            dfatal "Failed to copy $_modules_dir"
+        # Make sure we never expand this to "/..."
+        rm -rf "${workspace:?}/$modules_dir"
+
+        if ! cp -ar "$modules_dir" "$workspace/$modules_dir"; then
+            dfatal "Failed to copy $modules_dir"
             exit 1
         fi
 
-        local _policy_headers_dir=/usr/share/selinux/devel
-        rm -rf $1/$_policy_headers_dir
+        rm -rf "${workspace:?}/$policy_headers_dir"
         inst_dir /usr/share/selinux
-        if ! cp -ar $_policy_headers_dir $1/$_policy_headers_dir; then
-            dfatal "Failed to copy $_policy_headers_dir"
+
+        if ! cp -ar "$policy_headers_dir" "$workspace/$policy_headers_dir"; then
+            dfatal "Failed to copy $policy_headers_dir"
             exit 1
         fi
 
-        mkdir $1/systemd-test-module
-        cp systemd_test.te $1/systemd-test-module
-        cp systemd_test.if $1/systemd-test-module
-        cp systemd_test.fc $1/systemd-test-module
+        mkdir "$workspace/systemd-test-module"
+        cp systemd_test.te "$workspace/systemd-test-module"
+        cp systemd_test.if "$workspace/systemd-test-module"
+        cp systemd_test.fc "$workspace/systemd-test-module"
         dracut_install -o sesearch
         dracut_install runcon
         dracut_install checkmodule semodule semodule_package m4 make load_policy sefcontext_compile
@@ -46,4 +54,4 @@ test_append_files() {
     )
 }
 
-do_test "$@" 06
+do_test "$@"
index 5da24a987ce5d5933e555dd99164983a4c492ac1..d195dcf184a25c640ab16f2855044b1bae3fce0d 100755 (executable)
@@ -1,10 +1,12 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/1981"
 TEST_NO_QEMU=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
 NSPAWN_TIMEOUT=30
 
-do_test "$@" 07
+do_test "$@"
index 34d68835d8fee92283b7742ddd23db0acb6e6038..76927be429108e64bdafb5c6b5500ffc39b04546 100755 (executable)
@@ -1,12 +1,15 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/2730"
 IMAGE_NAME="test08"
 TEST_NO_NSPAWN=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
 QEMU_TIMEOUT=300
 FSTYPE=ext4
 TEST_FORCE_NEWIMAGE=1
 
-do_test "$@" 08
+do_test "$@"
index a4d155be1db3443b5de823671ba57d017eb9e069..3c92efbcc2b81a8a11d3d94bddd504a6b3ac57a3 100755 (executable)
@@ -1,9 +1,12 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/2691"
 TEST_NO_NSPAWN=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
 QEMU_TIMEOUT=300
 
-do_test "$@" 09
+do_test "$@"
index 14ded56ba15c938a4bfb84bb1d7396062b5dadb3..2a16ff3baabb52a967b6e9eb1a5a6c23fe775013 100755 (executable)
@@ -1,7 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/2467"
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 10
+do_test "$@"
index da003c90d512dc4d0e68468a29dbdea0f4f9fafa..15ecbe51a31223fbdd818422bccb50065439d0cb 100755 (executable)
@@ -1,8 +1,10 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/3166"
 TEST_NO_NSPAWN=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 11
+do_test "$@"
index c8abefbd866641e0df6206920c241435308d3a36..6e250b76690c57ed4108c9cc0a939ebd0d6aa7d1 100755 (executable)
@@ -1,8 +1,10 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/3171"
 TEST_NO_QEMU=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 12
+do_test "$@"
index 0f6bf587a65916f8d4122a5867b1e5b1fe427d25..18db8d4284f319627c86f2e6cfd13dd546cf3062 100755 (executable)
@@ -1,16 +1,20 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="systemd-nspawn smoke test"
 IMAGE_NAME="nspawn"
 TEST_NO_NSPAWN=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
 test_append_files() {
     (
-        ../create-busybox-container $1/testsuite-13.nc-container
-        initdir="$1/testsuite-13.nc-container" dracut_install nc ip md5sum
+        local workspace="${1:?}"
+
+        "$TEST_BASE_DIR/create-busybox-container" "$workspace/testsuite-13.nc-container"
+        initdir="$workspace/testsuite-13.nc-container" dracut_install nc ip md5sum
     )
 }
 
-do_test "$@" 13
+do_test "$@"
index 87abe2e439a64e2cb093f7d5a3bd51588670ac4d..14d30ec1e11f044e2d76ac39a4bf03977ae0bfcd 100755 (executable)
@@ -1,13 +1,15 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="/etc/machine-id testing"
 IMAGE_NAME="badid"
 TEST_NO_NSPAWN=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
 test_append_files() {
-    printf "556f48e837bc4424a710fa2e2c9d3e3c\ne3d\n" >$1/etc/machine-id
+    printf "556f48e837bc4424a710fa2e2c9d3e3c\ne3d\n" >"${1:?}/etc/machine-id"
 }
 
-do_test "$@" 14
+do_test "$@"
index 1540e2e1f115dd1803226a367d52444ba8b7939d..f4422d4c7f313e3356d732174c06b4a5e0ae1ec2 100755 (executable)
@@ -1,8 +1,10 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="Dropin tests"
 TEST_NO_QEMU=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 15
+do_test "$@"
index e1e2a68fa9e009dd651c09f0b6d93d47c0ee1f96..dd43902967fd2e27df0927d5772786a32773f406 100755 (executable)
@@ -1,9 +1,11 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="EXTEND_TIMEOUT_USEC=usec start/runtime/stop tests"
 SKIP_INITRD=yes
 TEST_NO_QEMU=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 16
+do_test "$@"
index b13ae0aa78267ff69c644207aba541fbd8a6babd..446f4a83db5defac6ea1f6a857ee53aaa5c96955 100755 (executable)
@@ -1,11 +1,14 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="UDEV"
 IMAGE_NAME="udev"
 TEST_NO_NSPAWN=1
 
-. $TEST_BASE_DIR/test-functions
-QEMU_TIMEOUT=500
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+QEMU_TIMEOUT=800
 
 test_append_files() {
     (
@@ -14,4 +17,4 @@ test_append_files() {
     )
 }
 
-do_test "$@" 17
+do_test "$@"
index 5c386b8ea209aae9079510d15a44bc91fd8ec89a..2e7ed0c2d65321c98bd27b30991198ace4818118 100755 (executable)
@@ -1,8 +1,11 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="FailureAction= operation"
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
 QEMU_TIMEOUT=600
 
-do_test "$@" 18
+do_test "$@"
index 03c7760bfd14d099ded8f87fd97383a6e68c36c2..165b31f7877572022e170768a2734e84db705010 100755 (executable)
@@ -1,10 +1,13 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="test cgroup delegation in the unified hierarchy"
 TEST_NO_NSPAWN=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
 QEMU_TIMEOUT=600
 UNIFIED_CGROUP_HIERARCHY=yes
 
-do_test "$@" 19
+do_test "$@"
index 50724b3f3c0bca3aa19e185ba1167ea5c8211bf5..bb9ddcde228d567b478f6356e1d63dff14837730 100755 (executable)
@@ -1,7 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="test changing main PID"
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 20
+do_test "$@"
index e4874b4d230ee328627aa5c43b4489880fdb9fb2..2d4d4d92c995555367d0dd7a62c76920c433bcc3 100755 (executable)
@@ -1,12 +1,15 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="Tmpfiles related tests"
 TEST_NO_QEMU=1
-. $TEST_BASE_DIR/test-functions
+
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
 test_append_files() {
-    if [[ "$IS_BUILT_WITH_ASAN" == "yes" ]]; then
-        if [[ -z "$initdir" ]]; then
+    if [[ "${IS_BUILT_WITH_ASAN:=}" == "yes" ]]; then
+        if [[ -z "${initdir:=}" ]]; then
             echo >&2 "\$initdir is not defined, can't continue"
             exit 1
         fi
@@ -15,4 +18,4 @@ test_append_files() {
     fi
 }
 
-do_test "$@" 22
+do_test "$@"
index 1b0d25a721ba9dbb091575f3edea4b982ff4eeef..fb77dc7ab3283576dd95a48a88733e16aa10dd90 100755 (executable)
@@ -1,6 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="test Type=exec"
-. $TEST_BASE_DIR/test-functions
 
-do_test "$@" 23
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
index d7b338c7f0f388cbf6e5d9169f85eb6cf2628c61..2c13126a436db54c5ee16019d8275b1f94866c67 100755 (executable)
@@ -1,68 +1,77 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="cryptsetup systemd setup"
 IMAGE_NAME="cryptsetup"
 TEST_NO_NSPAWN=1
 TEST_FORCE_NEWIMAGE=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
 check_result_qemu() {
-    ret=1
+    local ret=1
+
     mount_initdir
-    [[ -e $initdir/testok ]] && ret=0
-    [[ -f $initdir/failed ]] && cp -a $initdir/failed $TESTDIR
-    cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile
-    mount /dev/mapper/varcrypt $initdir/var
-    save_journal $initdir/var/log/journal
-    _umount_dir $initdir/var
-    _umount_dir $initdir
+    [[ -e "${initdir:?}/testok" ]] && ret=0
+    [[ -f "$initdir/failed" ]] && cp -a "$initdir/failed" "${TESTDIR:?}"
+
+    cryptsetup luksOpen "${LOOPDEV:?}p2" varcrypt <"$TESTDIR/keyfile"
+    mount /dev/mapper/varcrypt "$initdir/var"
+    save_journal "$initdir/var/log/journal"
+    _umount_dir "$initdir/var"
+    _umount_dir "$initdir"
     cryptsetup luksClose /dev/mapper/varcrypt
-    [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
-    echo $JOURNAL_LIST
-    test -s $TESTDIR/failed && ret=$(($ret+1))
+
+    [[ -f "$TESTDIR/failed" ]] && cat "$TESTDIR/failed"
+    echo "${JOURNAL_LIST:-No journals were saved}"
+
+    test -s "$TESTDIR/failed" && ret=1
     return $ret
 }
 
 test_create_image() {
     create_empty_image_rootdir
-    echo -n test >$TESTDIR/keyfile
-    cryptsetup -q luksFormat --pbkdf pbkdf2 --pbkdf-force-iterations 1000 ${LOOPDEV}p2 $TESTDIR/keyfile
-    cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile
+
+    echo -n test >"${TESTDIR:?}/keyfile"
+    cryptsetup -q luksFormat --pbkdf pbkdf2 --pbkdf-force-iterations 1000 "${LOOPDEV:?}p2" "$TESTDIR/keyfile"
+    cryptsetup luksOpen "${LOOPDEV}p2" varcrypt <"$TESTDIR/keyfile"
     mkfs.ext4 -L var /dev/mapper/varcrypt
-    mkdir -p $initdir/var
-    mount /dev/mapper/varcrypt $initdir/var
+    mkdir -p "${initdir:?}/var"
+    mount /dev/mapper/varcrypt "$initdir/var"
 
     # Create what will eventually be our root filesystem onto an overlay
     (
         LOG_LEVEL=5
-        eval $(udevadm info --export --query=env --name=/dev/mapper/varcrypt)
-        eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
+        # shellcheck source=/dev/null
+        source <(udevadm info --export --query=env --name=/dev/mapper/varcrypt)
+        # shellcheck source=/dev/null
+        source <(udevadm info --export --query=env --name="${LOOPDEV}p2")
 
         setup_basic_environment
         mask_supporting_services
 
         install_dmevent
         generate_module_dependencies
-        cat >$initdir/etc/crypttab <<EOF
+        cat >"$initdir/etc/crypttab" <<EOF
 $DM_NAME UUID=$ID_FS_UUID /etc/varkey
 EOF
-        echo -n test >$initdir/etc/varkey
-        cat $initdir/etc/crypttab | ddebug
+        echo -n test >"$initdir/etc/varkey"
+        ddebug <"$initdir/etc/crypttab"
 
-        cat >>$initdir/etc/fstab <<EOF
+        cat >>"$initdir/etc/fstab" <<EOF
 /dev/mapper/varcrypt    /var    ext4    defaults 0 1
 EOF
 
         # Forward journal messages to the console, so we have something
         # to investigate even if we fail to mount the encrypted /var
-        echo ForwardToConsole=yes >> $initdir/etc/systemd/journald.conf
+        echo ForwardToConsole=yes >> "$initdir/etc/systemd/journald.conf"
     )
 }
 
 cleanup_root_var() {
-    ddebug "umount $initdir/var"
-    mountpoint $initdir/var && umount $initdir/var
+    ddebug "umount ${initdir:?}/var"
+    mountpoint "$initdir/var" && umount "$initdir/var"
     [[ -b /dev/mapper/varcrypt ]] && cryptsetup luksClose /dev/mapper/varcrypt
 }
 
@@ -77,4 +86,4 @@ test_setup_cleanup() {
     cleanup_initdir
 }
 
-do_test "$@" 24
+do_test "$@"
index 034b94ca7992515df260a9c62331a94943a7b0a9..6fff9e51083b534ed658d80e1d2e4f96b23dc1b8 100755 (executable)
@@ -1,7 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="test importd"
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 25
+do_test "$@"
index 158fa6fdc04ac05330256ce1a5358818c0397650..fe4c517895cb811710f471d198c8ed0b76e615d0 100755 (executable)
@@ -1,7 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="test setenv"
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 26
+do_test "$@"
index 23aadf314e11554327833d95a4823acbdb81e413..144b88fa309c485235c9ece17785310725c40875 100755 (executable)
@@ -1,7 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="test StandardOutput=file:"
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 27
+do_test "$@"
index 09baf2277683a02e67ef67340e5a14339de2e89f..d535c416845e7774661259d65c7b85a0ad506d4e 100755 (executable)
@@ -1,8 +1,10 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="Ensure %j Wants directives work"
 RUN_IN_UNPRIVILEGED_CONTAINER=yes
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 28
+do_test "$@"
index 801e74c13d828a4e109fc065ea1e8c69811dad9d..579e04dbf5071e41a4236366acdc1f6c4deccb75 100755 (executable)
@@ -2,12 +2,14 @@
 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
 # ex: ts=8 sw=4 sts=4 et filetype=sh
 set -e
+
 TEST_DESCRIPTION="test systemd-portabled"
 IMAGE_NAME="portabled"
 TEST_NO_NSPAWN=1
 TEST_INSTALL_VERITY_MINIMAL=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
 # Need loop devices for mounting images
 test_append_files() {
@@ -15,6 +17,7 @@ test_append_files() {
         instmods loop =block
         instmods squashfs =squashfs
         instmods dm_verity =md
+        instmods overlay =overlayfs
         install_dmevent
         generate_module_dependencies
         inst_binary losetup
@@ -24,4 +27,4 @@ test_append_files() {
     )
 }
 
-do_test "$@" 29
+do_test "$@"
index 4723e7b0be81921cb3b9edfcefb59d40f8844a4e..aefe4bb00d74140e492a3b1902da35c11b9f8ea2 100755 (executable)
@@ -1,7 +1,10 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="test OnClockChange= + OnTimezoneChange="
 TEST_NO_NSPAWN=1
-. $TEST_BASE_DIR/test-functions
 
-do_test "$@" 30
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
index 4fbd38d2d0dadf520dfcd5315952c86e547dfb6b..809f7fdca786581c9023b4834a2d0eee17f9b811 100755 (executable)
@@ -1,9 +1,12 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="plugged -> dead -> plugged issue #11997"
 TEST_NO_NSPAWN=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
 QEMU_TIMEOUT=300
 
-do_test "$@" 31
+do_test "$@"
index 6f2955cf62c303552d5c3b47fe33a518034a9b88..299bfe443af87c2ca8ca9b45711d95ea83d19ca9 100755 (executable)
@@ -1,9 +1,12 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="test OOM killer logic"
 TEST_NO_NSPAWN=1
-. $TEST_BASE_DIR/test-functions
+
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
 UNIFIED_CGROUP_HIERARCHY=yes
 
-do_test "$@" 32
+do_test "$@"
index 64cb6aee5938b4e9b548185cfba711dbaa2dc18c..d49a85828cc0c124e2f2b7c8ffb9c88087bfc6c9 100755 (executable)
@@ -2,7 +2,10 @@
 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
 # ex: ts=8 sw=4 sts=4 et filetype=sh
 set -e
+
 TEST_DESCRIPTION="test CleanUnit"
-. $TEST_BASE_DIR/test-functions
 
-do_test "$@" 33
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
index 0b2174a894b0b15a0c0dd6d889420f042e5afb0a..4d5ca336f15a72414c3d34c60f3b4fa8bc7f4739 100755 (executable)
@@ -1,6 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="test migrating state directory from DynamicUser=1 to DynamicUser=0 and back"
-. $TEST_BASE_DIR/test-functions
 
-do_test "$@" 34
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
index cec8b699202bf58ea373285042224a7107815a63..f1c36b3d6b64d069b1850698a31f819341447f9a 100755 (executable)
@@ -3,11 +3,14 @@ set -e
 
 TEST_DESCRIPTION="test NUMAPolicy= and NUMAMask= options"
 TEST_NO_NSPAWN=1
-. $TEST_BASE_DIR/test-functions
+
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
 if qemu_min_version "5.2.0"; then
     QEMU_OPTIONS="-object memory-backend-ram,id=mem0,size=512M -numa node,memdev=mem0,nodeid=0"
 else
     QEMU_OPTIONS="-numa node,nodeid=0"
 fi
 
-do_test "$@" 36
+do_test "$@"
index b5806c429f91aae4b18b820370fb72e477559283..ebe4c4f1b5172b3a20a47934f1fc6d7e6af9700a 100755 (executable)
@@ -2,7 +2,10 @@
 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
 # ex: ts=8 sw=4 sts=4 et filetype=sh
 set -e
+
 TEST_DESCRIPTION="test RuntimeDirectoryPreserve=yes"
-. $TEST_BASE_DIR/test-functions
 
-do_test "$@" 37
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
index 3821db9f0023c13c5e5854a511f7f8b98cfcfe50..dab05022bebfd64b4ee662ad7eb69213f8c814da 100755 (executable)
@@ -1,7 +1,10 @@
 #!/bin/bash
 set -e
+
 TEST_DESCRIPTION="test unit freezing and thawing via DBus and systemctl"
 TEST_NO_NSPAWN=1
-. $TEST_BASE_DIR/test-functions
 
-do_test "$@" 38
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
index e38a9902ce072b8d4d186ecb452fd1a17d7dbbae..653aee13ab5578bc4736d7e50d6ac2c1a0bc5934 100755 (executable)
@@ -1,6 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="Test ExecReload= (PR #13098)"
-. $TEST_BASE_DIR/test-functions
 
-do_test "$@" 39
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
index 4ee84d4d35ddf7d0c9c167a6545fab482b3f0833..bbbbad70647416a36720557a49d361c4ec63d841 100755 (executable)
@@ -1,6 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="test ExecXYZEx= service unit dbus hookups"
-. $TEST_BASE_DIR/test-functions
 
-do_test "$@" 40
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
index d3f96ae1071a9ffe5020ed72fe6d0e0c7df67d70..aced44314bd637576c543a889d03beca09cc80d5 100755 (executable)
@@ -1,6 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="Test oneshot unit restart on failure"
-. $TEST_BASE_DIR/test-functions
 
-do_test "$@" 41
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
index 53e6fa3dd01da5ea040bb28816c1c211f0e83e03..59f8868af27f43d40781df64ebb551e3fe3a7085 100755 (executable)
@@ -1,7 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="test that ExecStopPost= is always run"
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 42
+do_test "$@"
index 4749150ff125a448f38050741e7526d0ca21b3a3..9a7aa401bfa005ccaa52df630f44b21799a4f1e1 100755 (executable)
@@ -1,8 +1,11 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="Test PrivateUsers=yes on user manager"
-. $TEST_BASE_DIR/test-functions
+
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
 has_user_dbus_socket || exit 0
 
-do_test "$@" 43
+do_test "$@"
index 26d863708e85833115b666f9898139f8c7d8dbea..3caa76cecfbf15898a72dac731212aa9c594b589 100755 (executable)
@@ -1,7 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="test log namespaces"
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 44
+do_test "$@"
index 877cbfefd035d02bce12f5037d93588bc32f6dd0..dea7e43876db1c1198d16b83d891f4813a3f68d8 100755 (executable)
@@ -1,8 +1,10 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="testing homed"
 TEST_NO_QEMU=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 46
+do_test "$@"
index 4e80ec76ff58a4ce593075b348960070c709464b..c275770d4b745b99d09ee900fb4f60bd4ceb546b 100755 (executable)
@@ -1,6 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="Test that KillMode=mixed does not leave left over processes with ExecStopPost="
-. $TEST_BASE_DIR/test-functions
 
-do_test "$@" 47
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
index f6638b3241c3c7f56033647632bdcdcd6ce5bb0f..d1abc8aeebf552291279ab3a32afa55300e10985 100755 (executable)
@@ -2,7 +2,10 @@
 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
 # ex: ts=8 sw=4 sts=4 et filetype=sh
 set -e
+
 TEST_DESCRIPTION="test StartStopNoReload"
-. $TEST_BASE_DIR/test-functions
 
-do_test "$@" 48
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
index ff24a4f254efc7afc2a043225ccfcbb9b632f814..297b22d4eea0373b5a561b5667d0e538e29d900b 100755 (executable)
@@ -2,6 +2,8 @@
 set -e
 
 TEST_DESCRIPTION="test adding new BindPaths while unit is already running"
-. $TEST_BASE_DIR/test-functions
 
-do_test "$@" 49
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
diff --git a/test/TEST-50-DISSECT/deny-list-ubuntu-ci b/test/TEST-50-DISSECT/deny-list-ubuntu-ci
deleted file mode 100644 (file)
index e7585d7..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Skip this test due to issue #17469
-https://github.com/systemd/systemd/issues/17469
index 9d42e4891c18ddc3429b69b0e4966e0b5375c9c4..67f68a39ecb16558c694a50f02b57276539b3ffd 100755 (executable)
@@ -2,12 +2,14 @@
 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
 # ex: ts=8 sw=4 sts=4 et filetype=sh
 set -e
+
 TEST_DESCRIPTION="test systemd-dissect"
 IMAGE_NAME="dissect"
 TEST_NO_NSPAWN=1
 TEST_INSTALL_VERITY_MINIMAL=1
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
 command -v mksquashfs >/dev/null 2>&1 || exit 0
 command -v veritysetup >/dev/null 2>&1 || exit 0
@@ -23,8 +25,9 @@ test_append_files() {
         install_dmevent
         generate_module_dependencies
         inst_binary losetup
+        inst_binary wc
         install_verity_minimal
     )
 }
 
-do_test "$@" 50
+do_test "$@"
index eca235c0a647467888d4e3ccbc8cfef0a6385ddd..5a0498e0667095f6c2a46653c61a0c02f0806bb0 100755 (executable)
@@ -1,6 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="Test ExecCondition= does not restart on abnormal or failure"
-. $TEST_BASE_DIR/test-functions
 
-do_test "$@" 51
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
deleted file mode 100644 (file)
index 71487d707608f24b6fa8d7d6c0cd1fe6371ff543..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,14 +0,0 @@
-all setup run clean clean-again:
-       @TEST_BASE_DIR=../ ./test.sh --$@
-
-# finish option is used to run checks that can only be run outside of
-# the test execution. Example case, honor first shutdown, proof is obtained
-# from the console output as the image shuts down. This does not show up in
-# the journal so the output from the do_test is captured in a file in /tmp.
-# Without the use of finish the test will still pass because if it fails
-# the test will loop and will be terminated via a command timeout.
-# This just provides concrete confirmation.
-finish:
-       @TEST_BASE_DIR=../ ./fini.sh --$@
-
-.PHONY: all setup run clean clean-again finish
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..e9f93b1104cd21161bfe11fb1b3b534ce2ae82b5
--- /dev/null
@@ -0,0 +1 @@
+../TEST-01-BASIC/Makefile
\ No newline at end of file
diff --git a/test/TEST-52-HONORFIRSTSHUTDOWN/fini.sh b/test/TEST-52-HONORFIRSTSHUTDOWN/fini.sh
deleted file mode 100755 (executable)
index 993ada0..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-TEST_DESCRIPTION="test honor first shutdown"
-
-if grep -q "Shutdown is already active. Skipping emergency action request" /tmp/honorfirstshutdown.log; then
-    echo "$TEST_DESCRIPTION [pass]"
-    exit 0
-else
-    echo "$TEST_DESCRIPTION [fail]"
-    exit 1
-fi
index a0848ef6723deea89c9cf30b24424b266a797a06..41c7e91917c560d25c13dc388190809007e3750e 100755 (executable)
@@ -1,19 +1,27 @@
 #!/bin/bash
 set -e
-. $TEST_BASE_DIR/test-functions
+
 TEST_REQUIRE_INSTALL_TESTS=0
 TEST_DESCRIPTION="testing honor first shutdown"
-#INTERACTIVE_DEBUG=1
 TEST_NO_QEMU=1
 
-#Using timeout because if the test fails it can loop.
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+# Using timeout because if the test fails it can loop.
 # The reason is because the poweroff executed by end.service
 # could turn into a reboot if the test fails.
 NSPAWN_TIMEOUT=20
 
-#Remove this file if it exists. this is used along with
-# the make target "finish". Since concrete confirmaion is
+# Remove this file if it exists. This is used along with
+# the make target "finish". Since concrete confirmation is
 # only found from the console during the poweroff.
 rm -f /tmp/honorfirstshutdown.log >/dev/null
 
-do_test "$@" 52 > /tmp/honorfirstshutdown.log
+check_result_nspawn_hook() {
+    grep -q "Shutdown is already active. Skipping emergency action request" /tmp/honorfirstshutdown.log
+}
+
+# Note: don't use a pipe in the following expression, as it breaks the trap
+#       handlers we have defined in test/test-functions.
+do_test "$@" > >(tee /tmp/honorfirstshutdown.log)
index 089768e8ddb391b34cd5b94c0aebbe78cdae59cd..699b7b65d81b54dfd1f6bbb31be874e6c35517ea 100755 (executable)
@@ -4,8 +4,9 @@ set -e
 TEST_DESCRIPTION="test timer units when initial clock is ahead"
 TEST_NO_NSPAWN=1
 
-future_date=$(date -u +%Y-%m-%dT%H:%M:%S -d '+3 days')
-QEMU_OPTIONS="-rtc base=${future_date}"
-. $TEST_BASE_DIR/test-functions
+QEMU_OPTIONS="-rtc base=$(date -u +%Y-%m-%dT%H:%M:%S -d '+3 days')"
 
-do_test "$@" 53
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
index 5feb15e7f131ccb678b567b3827f90834aa2730a..28333d38d87622759a2a53ef6549a4d29d329b5d 100755 (executable)
@@ -1,7 +1,9 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="test credentials"
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-do_test "$@" 54
+do_test "$@"
index 121aa8d56e9393d1cb615354f6239f76375c353f..6f7e776c3c994062b85e7dc09e7442f226f44aa9 100755 (executable)
@@ -1,48 +1,22 @@
 #!/usr/bin/env bash
 set -e
+
 TEST_DESCRIPTION="systemd-oomd Memory Pressure Test"
+IMAGE_NAME="oomd"
 
-. $TEST_BASE_DIR/test-functions
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
 
-check_result_nspawn() {
-    local ret=1
-    local journald_report=""
-    local pids=""
-    [[ -e $1/testok ]] && ret=0
-    if [[ -e $1/skipped ]]; then
-        echo "TEST-56-OOMD was skipped:"
-        cat $1/skipped
-        ret=0
-    fi
-    [[ -f $1/failed ]] && cp -a $1/failed $TESTDIR
-    save_journal $1/var/log/journal
-    [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
-    echo $JOURNAL_LIST
-    test -s $TESTDIR/failed && ret=$(($ret+1))
-    [ -n "$TIMED_OUT" ] && ret=$(($ret+1))
-    check_asan_reports "$1" || ret=$(($ret+1))
-    _umount_dir $initdir
-    return $ret
-}
+test_append_files() {
+    # Create a swap device
+    (
+        mkswap "${LOOPDEV:?}p2"
+        dracut_install swapon swapoff
 
-check_result_qemu() {
-    local ret=1
-    mount_initdir
-    [[ -e $initdir/testok ]] && ret=0
-    if [[ -e $initdir/skipped ]]; then
-        echo "TEST-56-OOMD was skipped:"
-        cat $initdir/skipped
-        ret=0
-    fi
-    [[ -f $initdir/failed ]] && cp -a $initdir/failed $TESTDIR
-    save_journal $initdir/var/log/journal
-    check_asan_reports "$initdir" || ret=$(($ret+1))
-    _umount_dir $initdir
-    [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
-    echo $JOURNAL_LIST
-    test -s $TESTDIR/failed && ret=$(($ret+1))
-    [ -n "$TIMED_OUT" ] && ret=$(($ret+1))
-    return $ret
+        cat >>"${initdir:?}/etc/fstab" <<EOF
+UUID=$(blkid -o value -s UUID "${LOOPDEV}p2")    none    swap    defaults 0 0
+EOF
+    )
 }
 
 do_test "$@" 55
diff --git a/test/TEST-56-EXIT-TYPE/Makefile b/test/TEST-56-EXIT-TYPE/Makefile
new file mode 120000 (symlink)
index 0000000..e9f93b1
--- /dev/null
@@ -0,0 +1 @@
+../TEST-01-BASIC/Makefile
\ No newline at end of file
diff --git a/test/TEST-56-EXIT-TYPE/test.sh b/test/TEST-56-EXIT-TYPE/test.sh
new file mode 100755 (executable)
index 0000000..0f84dca
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+set -e
+
+TEST_DESCRIPTION="test ExitType=cgroup"
+
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
diff --git a/test/TEST-58-REPART/Makefile b/test/TEST-58-REPART/Makefile
new file mode 120000 (symlink)
index 0000000..e9f93b1
--- /dev/null
@@ -0,0 +1 @@
+../TEST-01-BASIC/Makefile
\ No newline at end of file
diff --git a/test/TEST-58-REPART/test.sh b/test/TEST-58-REPART/test.sh
new file mode 100755 (executable)
index 0000000..3a3c33f
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+set -e
+TEST_DESCRIPTION="test systemd-repart"
+TEST_NO_NSPAWN=1
+. $TEST_BASE_DIR/test-functions
+
+do_test "$@"
diff --git a/test/TEST-59-RELOADING-RESTART/Makefile b/test/TEST-59-RELOADING-RESTART/Makefile
new file mode 120000 (symlink)
index 0000000..e9f93b1
--- /dev/null
@@ -0,0 +1 @@
+../TEST-01-BASIC/Makefile
\ No newline at end of file
diff --git a/test/TEST-59-RELOADING-RESTART/test.sh b/test/TEST-59-RELOADING-RESTART/test.sh
new file mode 100755 (executable)
index 0000000..9232d78
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+set -e
+TEST_DESCRIPTION="Test auto restart of exited services which are stuck in reloading state"
+
+TEST_NO_QEMU=1
+
+. $TEST_BASE_DIR/test-functions
+
+do_test "$@"
diff --git a/test/fuzz/fuzz-journald-kmsg/oss-fuzz-33881 b/test/fuzz/fuzz-journald-kmsg/oss-fuzz-33881
new file mode 100644 (file)
index 0000000..ad4f3f0
--- /dev/null
@@ -0,0 +1,4 @@
+8,0,1;2,0,7;
+ DEVICE=+subsystem:tty/t0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000Ï000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000#00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8cè\ 5K\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f\8f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000subsys000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000åååååååååååååååååååååå0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000/drivers/000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000º000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000q00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018446744073709551615@0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ííííííííííííííííííííííííí000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000!00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ä00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\17ë000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000p0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000q00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018446744073709551615@0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ííííííííííííííííííííííííí0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000tyS1/../..
+DD0\U03;
+ D D D 
\ No newline at end of file
index d4e5598409c2148a31f3d3d5edbecee353f42ac4..8373ac7e89dd04943a82ea628cfddd3f6e3f444a 100644 (file)
@@ -22,6 +22,7 @@ Mode=
 SourceMACAddress=
 [Match]
 Architecture=
+Firmware=
 Host=
 KernelVersion=
 Virtualization=
index 8352ecb563d360e8a81f07a0d9bc56a49c07c83b..12d3e3cfcdf0f00ef4eb30326483ef6983f5bc13 100644 (file)
@@ -18,6 +18,7 @@ KernelVersion=
 Type=
 Driver=
 Architecture=
+Firmware=
 Path=
 WLANInterfaceType=
 SSID=
@@ -32,6 +33,7 @@ PermanentMACAddress=
 [Link]
 ActivationPolicy=
 RequiredForOnline=
+RequiredFamilyForOnline=
 ARP=
 AllMulticast=
 Unmanaged=
@@ -93,6 +95,7 @@ UseGateway=
 IAID=
 UserClass=
 UseNTP=
+RoutesToNTP=
 UseSIP=
 UseMTU=
 UseDomainName=
@@ -128,6 +131,7 @@ UseAddress=
 UseNTP=
 UseDNS=
 UseHostname=
+UseDomains=
 RapidCommit=
 ForceDHCPv6PDOtherInformation=
 PrefixDelegationHint=
@@ -139,12 +143,16 @@ UserClass=
 VendorClass=
 SendVendorOption=
 RouteMetric=
+IAID=
+DUIDType=
+DUIDRawData=
 [DHCPv6PrefixDelegation]
 SubnetId=
 Announce=
 Assign=
 ManageTemporaryAddress=
 Token=
+RouteMetric=
 [Route]
 Destination=
 Protocol=
@@ -234,6 +242,7 @@ PreferredLifetimeSec=
 AddressAutoconfiguration=
 ValidLifetimeSec=
 Assign=
+RouteMetric=
 [IPv6RoutePrefix]
 Route=
 LifetimeSec=
@@ -268,6 +277,7 @@ ManageTemporaryAddress=
 Broadcast=
 Peer=
 Label=
+RouteMetric=
 [RoutingPolicyRule]
 Table=
 IncomingInterface=
@@ -315,6 +325,7 @@ Prefix=
 [IPv6AcceptRA]
 UseDomains=
 RouteTable=
+RouteMetric=
 UseDNS=
 DHCPv6Client=
 UseAutonomousPrefix=
@@ -349,6 +360,8 @@ EmitTimezone=
 DNS=
 SendOption=
 SendVendorOption=
+BindToInterface=
+RelayTarget=
 [NextHop]
 Id=
 Gateway=
diff --git a/test/fuzz/fuzz-unit-file/directives-all.service b/test/fuzz/fuzz-unit-file/directives-all.service
new file mode 100644 (file)
index 0000000..a152beb
--- /dev/null
@@ -0,0 +1,950 @@
+service
+Accept=
+AccuracySec=
+After=
+Alias=
+AllowedCPUs=
+AllowedMemoryNodes=
+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=
+CoredumpFilter=
+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=
+ExecPaths=
+ExecReload=
+ExecCondition=
+ExecStart=
+ExecStartPost=
+ExecStartPre=
+ExecStop=
+ExecStopPost=
+ExecStopPre=
+ExitType=
+FailureAction=
+FileDescriptorName=
+FileDescriptorStoreMax=
+ForceUnmount=
+FreeBind=
+Group=
+GuessMainPID=
+IOAccounting=
+IODeviceWeight=
+IOReadBandwidthMax=
+IOReadIOPSMax=
+IOWeight=
+IOWriteBandwidthMax=
+IOWriteIOPSMax=
+IPAccounting=
+IPAddressAllow=
+IPAddressDeny=
+IPCNamespacePath=
+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=
+ManagedOOMSwap=
+ManagedOOMMemoryPressure=
+ManagedOOMMemoryPressureLimitPercent=
+ManagedOOMPreference=
+MemoryAccounting=
+MemoryHigh=
+MemoryLimit=
+MemoryLow=
+MemoryMax=
+MemorySwapMax=
+MessageQueueMaxMessages=
+MessageQueueMessageSize=
+MountAPIVFS=
+NetworkNamespacePath=
+NoDelay=
+NoExecPaths=
+NoNewPrivileges=
+NonBlocking=
+NotifyAccess=
+OnActiveSec=
+OnBootSec=
+OnCalendar=
+OnFailure=
+OnFailureJobMode=
+OnStartupSec=
+OnUnitActiveSec=
+OnUnitInactiveSec=
+Options=
+PAMName=
+PIDFile=
+PartOf=
+PassCredentials=
+PassSecurity=
+PassPacketInfo=
+PathChanged=
+PathExists=
+PathExistsGlob=
+PathModified=
+PermissionsStartOnly=
+Persistent=
+PipeSize=
+Priority=
+PropagatesReloadTo=
+RandomizedDelaySec=
+FixedRandomDelay=
+RebootArgument=
+ReceiveBuffer=
+RefuseManualStart=
+RefuseManualStop=
+ReloadPropagatedFrom=
+RemainAfterElapse=
+RemainAfterExit=
+RemoveOnStop=
+RequiredBy=
+Requires=
+RequiresMountsFor=
+Requisite=
+Restart=
+RestartForceExitStatus=
+RestartKillSignal=
+RestartPreventExitStatus=
+RestartSec=
+ReusePort=
+RootDirectory=
+RootDirectoryStartOnly=
+RootImage=
+RootHash=
+RootHashSignature=
+RootVerity=
+ExtensionImages=
+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=
+TimeoutAbortSec=
+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_level=
+resume=
+resumeflags=
+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.verity_root_options=
+systemd.volatile=
+systemd.wants=
+systemd.watchdog_device=
+udev.children_max=
+udev.event_timeout=
+udev.exec_delay=
+udev.log_level=
+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=
+CacheFromLocalhost=
+ClientIdentifier=
+ConfigureWithoutCarrier=
+CopyDSCP=
+Cost=
+CriticalConnection=
+DHCP=
+DHCPServer=
+DNS=
+DNSLifetimeSec=
+DNSSEC=
+DNSSECNegativeTrustAnchors=
+DNSStubListener=
+DNSStubListenerExtra=
+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=
+MulticastToUnicast=
+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=
+InvertRule=
+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=
+RequiredFamilyForOnline=
+RequiredForOnline=
+ResendIGMP=
+RootDistanceMaxSec=
+RouteMetric=
+RouteShortCircuit=
+RouteTable=
+RouterLifetimeSec=
+RouterPreference=
+STP=
+Scope=
+SendHostname=
+Source=
+SuppressPrefixLength=
+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=
+DefaultTimeoutAbortSec=
+DefaultTimerAccuracySec=
+DumpCore=
+HibernateMode=
+HibernateState=
+HybridSleepMode=
+HybridSleepState=
+LogColor=
+LogLevel=
+LogLocation=
+LogTarget=
+RuntimeWatchdogSec=
+ShowStatus=
+RebootWatchdogSec=
+ShutdownWatchdogSec=
+KExecWatchdogSec=
+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=
+ProtectProc=
+ProcSubset=
+KillExcludeUsers=
+KillOnlyUsers=
+KillSignal=
+WatchdogSignal=
+KillUserProcesses=
+LOCATION=
+LidSwitchIgnoreInhibited=
+LimitAS=
+LimitCORE=
+LimitCPU=
+LimitDATA=
+LimitFSIZE=
+LimitLOCKS=
+LimitMEMLOCK=
+LimitMSGQUEUE=
+LimitNICE=
+LimitNOFILE=
+LimitNPROC=
+LimitRSS=
+LimitRTPRIO=
+LimitRTTIME=
+LimitSIGPENDING=
+LimitSTACK=
+LineMax=
+LockPersonality=
+LogExtraFields=
+LogLevelMax=
+LogRateLimitIntervalSec=
+LogRateLimitBurst=
+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=
+PrivateIPC=
+PrivateDevices=
+PrivateNetwork=
+PrivateTmp=
+PrivateUsers=
+PrivateUsersChown=
+ProcessSizeMax=
+ProcessTwo=
+ProtectControlGroups=
+ProtectHome=
+ProtectKernelModules=
+ProtectKernelTunables=
+ProtectSystem=
+RateLimitBurst=
+RateLimitIntervalSec=
+ReadKMsg=
+ReadOnly=
+ReadOnlyPaths=
+ReadWriteOnly=
+ReadWritePaths=
+RemoveIPC=
+ReserveVT=
+RestrictAddressFamilies=
+RestrictNamespaces=
+RestrictRealtime=
+RestrictSUIDSGID=
+RuntimeDirectory=
+RuntimeDirectoryInodesMax=
+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/fuzz-unit-file/directives.automount b/test/fuzz/fuzz-unit-file/directives.automount
new file mode 100644 (file)
index 0000000..70772ba
--- /dev/null
@@ -0,0 +1,5 @@
+automount
+[Automount]
+DirectoryMode=
+TimeoutIdleSec=
+Where=
diff --git a/test/fuzz/fuzz-unit-file/directives.mount b/test/fuzz/fuzz-unit-file/directives.mount
new file mode 100644 (file)
index 0000000..451f291
--- /dev/null
@@ -0,0 +1,206 @@
+mount
+[Mount]
+AllowedCPUs=
+AllowedMemoryNodes=
+AmbientCapabilities=
+AppArmorProfile=
+BPFProgram=
+BindPaths=
+BindReadOnlyPaths=
+BlockIOAccounting=
+BlockIODeviceWeight=
+BlockIOReadBandwidth=
+BlockIOWeight=
+BlockIOWriteBandwidth=
+CPUAccounting=
+CPUAffinity=
+CPUQuota=
+CPUQuotaPeriodSec=
+CPUSchedulingPolicy=
+CPUSchedulingPriority=
+CPUSchedulingResetOnFork=
+CPUShares=
+CPUWeight=
+CacheDirectory=
+CacheDirectoryMode=
+Capabilities=
+CapabilityBoundingSet=
+ConfigurationDirectory=
+ConfigurationDirectoryMode=
+CoredumpFilter=
+DefaultMemoryLow=
+DefaultMemoryMin=
+Delegate=
+DeviceAllow=
+DevicePolicy=
+DirectoryMode=
+DisableControllers=
+DynamicUser=
+Environment=
+EnvironmentFile=
+ExecPaths=
+ExtensionImages=
+FinalKillSignal=
+ForceUnmount=
+Group=
+IOAccounting=
+IODeviceLatencyTargetSec=
+IODeviceWeight=
+IOReadBandwidthMax=
+IOReadIOPSMax=
+IOSchedulingClass=
+IOSchedulingPriority=
+IOWeight=
+IOWriteBandwidthMax=
+IOWriteIOPSMax=
+IPAccounting=
+IPAddressAllow=
+IPAddressDeny=
+IPCNamespacePath=
+IPEgressFilterPath=
+IPIngressFilterPath=
+IgnoreSIGPIPE=
+InaccessibleDirectories=
+InaccessiblePaths=
+KeyringMode=
+KillMode=
+KillSignal=
+LazyUnmount=
+LimitAS=
+LimitCORE=
+LimitCPU=
+LimitDATA=
+LimitFSIZE=
+LimitLOCKS=
+LimitMEMLOCK=
+LimitMSGQUEUE=
+LimitNICE=
+LimitNOFILE=
+LimitNPROC=
+LimitRSS=
+LimitRTPRIO=
+LimitRTTIME=
+LimitSIGPENDING=
+LimitSTACK=
+LoadCredential=
+LockPersonality=
+LogExtraFields=
+LogLevelMax=
+LogNamespace=
+LogRateLimitBurst=
+LogRateLimitIntervalSec=
+LogsDirectory=
+LogsDirectoryMode=
+ManagedOOMMemoryPressure=
+ManagedOOMMemoryPressureLimit=
+ManagedOOMPreference=
+ManagedOOMSwap=
+MemoryAccounting=
+MemoryDenyWriteExecute=
+MemoryHigh=
+MemoryLimit=
+MemoryLow=
+MemoryMax=
+MemoryMin=
+MemorySwapMax=
+MountAPIVFS=
+MountFlags=
+MountImages=
+NUMAMask=
+NUMAPolicy=
+NetClass=
+NetworkNamespacePath=
+Nice=
+NoExecPaths=
+NoNewPrivileges=
+OOMScoreAdjust=
+Options=
+PAMName=
+PassEnvironment=
+Personality=
+PrivateDevices=
+PrivateIPC=
+PrivateMounts=
+PrivateNetwork=
+PrivateTmp=
+PrivateUsers=
+ProcSubset=
+ProtectClock=
+ProtectControlGroups=
+ProtectHome=
+ProtectHostname=
+ProtectKernelLogs=
+ProtectKernelModules=
+ProtectKernelTunables=
+ProtectProc=
+ProtectSystem=
+ReadOnlyDirectories=
+ReadOnlyPaths=
+ReadWriteDirectories=
+ReadWriteOnly=
+ReadWritePaths=
+RemoveIPC=
+RestartKillSignal=
+RestrictAddressFamilies=
+RestrictNamespaces=
+RestrictRealtime=
+RestrictSUIDSGID=
+RootDirectory=
+RootHash=
+RootHashSignature=
+RootImage=
+RootImageOptions=
+RootVerity=
+RuntimeDirectory=
+RuntimeDirectoryMode=
+RuntimeDirectoryPreserve=
+SELinuxContext=
+SecureBits=
+SendSIGHUP=
+SendSIGKILL=
+SetCredential=
+Slice=
+SloppyOptions=
+SmackProcessLabel=
+SocketBindAllow=
+SocketBindDeny=
+StandardError=
+StandardInput=
+StandardInputData=
+StandardInputText=
+StandardOutput=
+StartupBlockIOWeight=
+StartupCPUShares=
+StartupCPUWeight=
+StartupIOWeight=
+StateDirectory=
+StateDirectoryMode=
+SupplementaryGroups=
+SyslogFacility=
+SyslogIdentifier=
+SyslogLevel=
+SyslogLevelPrefix=
+SystemCallArchitectures=
+SystemCallErrorNumber=
+SystemCallFilter=
+SystemCallLog=
+TTYPath=
+TTYReset=
+TTYVHangup=
+TTYVTDisallocate=
+TasksAccounting=
+TasksMax=
+TemporaryFileSystem=
+TimeoutCleanSec=
+TimeoutSec=
+TimerSlackNSec=
+Type=
+UMask=
+UnsetEnvironment=
+User=
+UtmpIdentifier=
+UtmpMode=
+WatchdogSignal=
+What=
+Where=
+WorkingDirectory=
diff --git a/test/fuzz/fuzz-unit-file/directives.path b/test/fuzz/fuzz-unit-file/directives.path
new file mode 100644 (file)
index 0000000..213beff
--- /dev/null
@@ -0,0 +1,10 @@
+path
+[Path]
+DirectoryMode=
+DirectoryNotEmpty=
+MakeDirectory=
+PathChanged=
+PathExists=
+PathExistsGlob=
+PathModified=
+Unit=
index d0e194c3715be51691814816dd4ff4e3da001922..7e69cf816b6a2dfedb63de7ca39b2ff184760671 100644 (file)
@@ -1,2 +1,64 @@
 scope
+[Scope]
+AllowedCPUs=
+AllowedMemoryNodes=
+BPFProgram=
+BlockIOAccounting=
+BlockIODeviceWeight=
+BlockIOReadBandwidth=
+BlockIOWeight=
+BlockIOWriteBandwidth=
+CPUAccounting=
+CPUQuota=
+CPUQuotaPeriodSec=
+CPUShares=
+CPUWeight=
+DefaultMemoryLow=
+DefaultMemoryMin=
+Delegate=
+DeviceAllow=
+DevicePolicy=
+DisableControllers=
+FinalKillSignal=
+IOAccounting=
+IODeviceLatencyTargetSec=
+IODeviceWeight=
+IOReadBandwidthMax=
+IOReadIOPSMax=
+IOWeight=
+IOWriteBandwidthMax=
+IOWriteIOPSMax=
+IPAccounting=
+IPAddressAllow=
+IPAddressDeny=
+IPEgressFilterPath=
+IPIngressFilterPath=
+KillMode=
+KillSignal=
+ManagedOOMMemoryPressure=
+ManagedOOMMemoryPressureLimit=
+ManagedOOMPreference=
+ManagedOOMSwap=
+MemoryAccounting=
+MemoryHigh=
+MemoryLimit=
+MemoryLow=
+MemoryMax=
+MemoryMin=
+MemorySwapMax=
+NetClass=
+RestartKillSignal=
 RuntimeMaxSec=
+SendSIGHUP=
+SendSIGKILL=
+Slice=
+SocketBindAllow=
+SocketBindDeny=
+StartupBlockIOWeight=
+StartupCPUShares=
+StartupCPUWeight=
+StartupIOWeight=
+TasksAccounting=
+TasksMax=
+TimeoutStopSec=
+WatchdogSignal=
index 55204463c8d31f253f9a7e4e6dd8d81ba5124e12..73e1707c5c03fe3cddd9f4030ecb8770b6fcf981 100644 (file)
@@ -1,18 +1,14 @@
 service
-Accept=
-AccuracySec=
+[Unit]
 After=
-Alias=
-AllowedCPUs=
-AllowedMemoryNodes=
 AllowIsolate=
-Also=
-AmbientCapabilities=
 AssertACPower=
 AssertArchitecture=
+AssertCPUs=
 AssertCapability=
 AssertControlGroupController=
 AssertDirectoryNotEmpty=
+AssertEnvironment=
 AssertFileIsExecutable=
 AssertFileNotEmpty=
 AssertFirstBoot=
@@ -20,42 +16,31 @@ AssertGroup=
 AssertHost=
 AssertKernelCommandLine=
 AssertKernelVersion=
+AssertMemory=
 AssertNeedsUpdate=
 AssertPathExists=
 AssertPathExistsGlob=
 AssertPathIsDirectory=
+AssertPathIsEncrypted=
 AssertPathIsMountPoint=
 AssertPathIsReadWrite=
 AssertPathIsSymbolicLink=
 AssertSecurity=
 AssertUser=
 AssertVirtualization=
-Backlog=
+BPFProgram=
 Before=
-BindIPv6Only=
-BindPaths=
-BindReadOnlyPaths=
-BindToDevice=
+BindTo=
 BindsTo=
-BlockIOAccounting=
-BlockIODeviceWeight=
-BlockIOReadBandwidth=
-BlockIOWeight=
-BlockIOWriteBandwidth=
-Broadcast=
-BusName=
-CoredumpFilter=
-CPUAccounting=
-CPUQuota=
-CPUShares=
-CPUWeight=
-CapabilityBoundingSet=
 CollectMode=
 ConditionACPower=
 ConditionArchitecture=
+ConditionCPUs=
+ConditionFirmware=
 ConditionCapability=
 ConditionControlGroupController=
 ConditionDirectoryNotEmpty=
+ConditionEnvironment=
 ConditionFileIsExecutable=
 ConditionFileNotEmpty=
 ConditionFirstBoot=
@@ -63,10 +48,12 @@ ConditionGroup=
 ConditionHost=
 ConditionKernelCommandLine=
 ConditionKernelVersion=
+ConditionMemory=
 ConditionNeedsUpdate=
 ConditionPathExists=
 ConditionPathExistsGlob=
 ConditionPathIsDirectory=
+ConditionPathIsEncrypted=
 ConditionPathIsMountPoint=
 ConditionPathIsReadWrite=
 ConditionPathIsSymbolicLink=
@@ -75,735 +62,126 @@ ConditionUser=
 ConditionVirtualization=
 Conflicts=
 DefaultDependencies=
-DefaultInstance=
-DeferAcceptSec=
-Delegate=
 Description=
-DeviceAllow=
-DevicePolicy=
-DirectoryMode=
-DirectoryNotEmpty=
 Documentation=
-DynamicUser=
-ExecPaths=
-ExecReload=
-ExecCondition=
-ExecStart=
-ExecStartPost=
-ExecStartPre=
-ExecStop=
-ExecStopPost=
-ExecStopPre=
 FailureAction=
-FileDescriptorName=
-FileDescriptorStoreMax=
-ForceUnmount=
-FreeBind=
-Group=
-GuessMainPID=
-IOAccounting=
-IODeviceWeight=
-IOReadBandwidthMax=
-IOReadIOPSMax=
-IOWeight=
-IOWriteBandwidthMax=
-IOWriteIOPSMax=
-IPAccounting=
-IPAddressAllow=
-IPAddressDeny=
-IPCNamespacePath=
-IPTOS=
-IPTTL=
+FailureActionExitStatus=
 IgnoreOnIsolate=
+IgnoreOnSnapshot=
 JobRunningTimeoutSec=
 JobTimeoutAction=
 JobTimeoutRebootArgument=
 JobTimeoutSec=
 JoinsNamespaceOf=
-KeepAlive=
-KeepAliveIntervalSec=
-KeepAliveProbes=
-KeepAliveTimeSec=
-KillMode=
-KillSignal=
-LazyUnmount=
-ListenDatagram=
-ListenFIFO=
-ListenMessageQueue=
-#ListenNetlink=
-ListenSequentialPacket=
-ListenSpecial=
-ListenStream=
-ListenUSBFunction=
-MakeDirectory=
-Mark=
-MaxConnections=
-MaxConnectionsPerSource=
-ManagedOOMSwap=
-ManagedOOMMemoryPressure=
-ManagedOOMMemoryPressureLimitPercent=
-ManagedOOMPreference=
-MemoryAccounting=
-MemoryHigh=
-MemoryLimit=
-MemoryLow=
-MemoryMax=
-MemorySwapMax=
-MessageQueueMaxMessages=
-MessageQueueMessageSize=
-MountAPIVFS=
-NetworkNamespacePath=
-NoDelay=
-NoExecPaths=
-NoNewPrivileges=
-NonBlocking=
-NotifyAccess=
-OnActiveSec=
-OnBootSec=
-OnCalendar=
 OnFailure=
+OnFailureIsolate=
 OnFailureJobMode=
-OnStartupSec=
-OnUnitActiveSec=
-OnUnitInactiveSec=
-Options=
-PAMName=
-PIDFile=
 PartOf=
-PassCredentials=
-PassSecurity=
-PassPacketInfo=
-PathChanged=
-PathExists=
-PathExistsGlob=
-PathModified=
-PermissionsStartOnly=
-Persistent=
-PipeSize=
-Priority=
+PropagateReloadFrom=
+PropagateReloadTo=
 PropagatesReloadTo=
-RandomizedDelaySec=
-FixedRandomDelay=
 RebootArgument=
-ReceiveBuffer=
 RefuseManualStart=
 RefuseManualStop=
 ReloadPropagatedFrom=
-RemainAfterElapse=
-RemainAfterExit=
-RemoveOnStop=
-RequiredBy=
 Requires=
 RequiresMountsFor=
+RequiresOverridable=
 Requisite=
-Restart=
-RestartForceExitStatus=
-RestartKillSignal=
-RestartPreventExitStatus=
-RestartSec=
-ReusePort=
-RootDirectory=
-RootDirectoryStartOnly=
-RootImage=
-RootHash=
-RootHashSignature=
-RootVerity=
-ExtensionImages=
-RuntimeMaxSec=
-SELinuxContextFromNet=
-SecureBits=
-SendBuffer=
-SendSIGHUP=
-SendSIGKILL=
-Service=
-Slice=
-SloppyOptions=
-SmackLabel=
-SmackLabelIPIn=
-SmackLabelIPOut=
-SocketGroup=
-SocketMode=
-SocketProtocol=
-SocketUser=
-Sockets=
+RequisiteOverridable=
+SocketBindAllow=
+SocketBindDeny=
 SourcePath=
 StartLimitAction=
 StartLimitBurst=
+StartLimitInterval=
 StartLimitIntervalSec=
-StartupBlockIOWeight=
-StartupCPUShares=
-StartupCPUWeight=
-StartupIOWeight=
 StopWhenUnneeded=
 SuccessAction=
-SuccessExitStatus=
-SupplementaryGroups=
-Symlinks=
-TCPCongestion=
-TasksAccounting=
-TasksMax=
-TimeoutIdleSec=
-TimeoutSec=
-TimeoutStartSec=
-TimeoutStopSec=
-TimeoutAbortSec=
-Transparent=
-TriggerLimitBurst=
-TriggerLimitIntervalSec=
-Type=
-USBFunctionDescriptors=
-USBFunctionStrings=
-Unit=
-User=
-WakeSystem=
-WantedBy=
+SuccessActionExitStatus=
 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_level=
-resume=
-resumeflags=
-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.verity_root_options=
-systemd.volatile=
-systemd.wants=
-systemd.watchdog_device=
-udev.children_max=
-udev.event_timeout=
-udev.exec_delay=
-udev.log_level=
-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=
+[Install]
 Alias=
-AllSlavesActive=
-AllowLocalRemote=
-AllowPortToBeRoot=
-AllowedIPs=
-Anonymize=
-Architecture=
-AutoJoin=
-AutoNegotiation=
-BindCarrier=
-BitsPerSecond=
-Bond=
-Bridge=
-Broadcast=
-Cache=
-CacheFromLocalhost=
-ClientIdentifier=
-ConfigureWithoutCarrier=
-CopyDSCP=
-Cost=
-CriticalConnection=
-DHCP=
-DHCPServer=
-DNS=
-DNSLifetimeSec=
-DNSSEC=
-DNSSECNegativeTrustAnchors=
-DNSStubListener=
-DNSStubListenerExtra=
-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=
-MulticastToUnicast=
-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=
-InvertRule=
-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=
-SuppressPrefixLength=
-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=
-DefaultTimeoutAbortSec=
-DefaultTimerAccuracySec=
-DumpCore=
-HibernateMode=
-HibernateState=
-HybridSleepMode=
-HybridSleepState=
-LogColor=
-LogLevel=
-LogLocation=
-LogTarget=
-RuntimeWatchdogSec=
-ShowStatus=
-RebootWatchdogSec=
-ShutdownWatchdogSec=
-KExecWatchdogSec=
-SuspendMode=
-SuspendState=
-SystemCallArchitectures=
-TimerSlackNSec=
-WatchdogDevice=
--N=
--c=
--e=
--t=
-ANSI_COLOR=
+Also=
+DefaultInstance=
+RequiredBy=
+WantedBy=
+[Service]
+AllowedCPUs=
+AllowedMemoryNodes=
+AmbientCapabilities=
 AppArmorProfile=
-BUG_REPORT_URL=
-BUILD_ID=
-Bind=
-BindReadOnly=
-Boot=
-Bridge=
-CHASSIS=
-CPE_NAME=
+BindPaths=
+BindReadOnlyPaths=
+BlockIOAccounting=
+BlockIODeviceWeight=
+BlockIOReadBandwidth=
+BlockIOWeight=
+BlockIOWriteBandwidth=
+BusName=
+BusPolicy=
+CPUAccounting=
 CPUAffinity=
+CPUQuota=
+CPUQuotaPeriodSec=
 CPUSchedulingPolicy=
 CPUSchedulingPriority=
 CPUSchedulingResetOnFork=
+CPUShares=
+CPUWeight=
 CacheDirectory=
 CacheDirectoryMode=
-Capability=
-Compress=
+Capabilities=
+CapabilityBoundingSet=
 ConfigurationDirectory=
 ConfigurationDirectoryMode=
-DEPLOYMENT=
-DropCapability=
+CoredumpFilter=
+DefaultMemoryLow=
+DefaultMemoryMin=
+Delegate=
+DeviceAllow=
+DevicePolicy=
+DisableControllers=
+DynamicUser=
 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=
+ExecCondition=
+ExecPaths=
+ExecReload=
+ExecStart=
+ExecStartPost=
+ExecStartPre=
+ExecStop=
+ExecStopPost=
+ExitType=
+ExtensionImages=
+FailureAction=
+FileDescriptorStoreMax=
+FinalKillSignal=
+Group=
+GuessMainPID=
+IOAccounting=
+IODeviceLatencyTargetSec=
+IODeviceWeight=
+IOReadBandwidthMax=
+IOReadIOPSMax=
 IOSchedulingClass=
 IOSchedulingPriority=
-IPVLAN=
-IdleAction=
-IdleActionSec=
+IOWeight=
+IOWriteBandwidthMax=
+IOWriteIOPSMax=
+IPAccounting=
+IPAddressAllow=
+IPAddressDeny=
+IPCNamespacePath=
+IPEgressFilterPath=
+IPIngressFilterPath=
 IgnoreSIGPIPE=
+InaccessibleDirectories=
 InaccessiblePaths=
-InhibitDelayMaxSec=
-InhibitorsMax=
-Interface=
-JournalSizeMax=
-KEYMAP=
-KEYMAP_TOGGLE=
-KeepFree=
 KeyringMode=
-ProtectProc=
-ProcSubset=
-KillExcludeUsers=
-KillOnlyUsers=
+KillMode=
 KillSignal=
-WatchdogSignal=
-KillUserProcesses=
-LOCATION=
-LidSwitchIgnoreInhibited=
 LimitAS=
 LimitCORE=
 LimitCPU=
@@ -820,97 +198,114 @@ LimitRTPRIO=
 LimitRTTIME=
 LimitSIGPENDING=
 LimitSTACK=
-LineMax=
+LoadCredential=
 LockPersonality=
 LogExtraFields=
 LogLevelMax=
-LogRateLimitIntervalSec=
+LogNamespace=
 LogRateLimitBurst=
+LogRateLimitIntervalSec=
 LogsDirectory=
 LogsDirectoryMode=
-MACVLAN=
-MachineID=
-MaxFileSec=
-MaxLevelConsole=
-MaxLevelKMsg=
-MaxLevelStore=
-MaxLevelSyslog=
-MaxLevelWall=
-MaxRetentionSec=
-MaxUse=
+ManagedOOMMemoryPressure=
+ManagedOOMMemoryPressureLimit=
+ManagedOOMPreference=
+ManagedOOMSwap=
+MemoryAccounting=
 MemoryDenyWriteExecute=
+MemoryHigh=
+MemoryLimit=
+MemoryLow=
+MemoryMax=
+MemoryMin=
+MemorySwapMax=
+MountAPIVFS=
 MountFlags=
-NAME=
-NAutoVTs=
+MountImages=
+NUMAMask=
+NUMAPolicy=
+NetClass=
+NetworkNamespacePath=
 Nice=
+NoExecPaths=
 NoNewPrivileges=
-NotifyReady=
+NonBlocking=
+NotifyAccess=
+OOMPolicy=
 OOMScoreAdjust=
-Overlay=
-OverlayReadOnly=
-PRETTY_HOSTNAME=
-PRETTY_NAME=
-PRIVACY_POLICY_URL=
-Parameters=
+PAMName=
+PIDFile=
 PassEnvironment=
+PermissionsStartOnly=
 Personality=
-PivotRoot=
-Port=
-PowerKeyIgnoreInhibited=
-Private=
-PrivateIPC=
 PrivateDevices=
+PrivateIPC=
+PrivateMounts=
 PrivateNetwork=
 PrivateTmp=
 PrivateUsers=
-PrivateUsersChown=
-ProcessSizeMax=
-ProcessTwo=
+ProcSubset=
+ProtectClock=
 ProtectControlGroups=
 ProtectHome=
+ProtectHostname=
+ProtectKernelLogs=
 ProtectKernelModules=
 ProtectKernelTunables=
+ProtectProc=
 ProtectSystem=
-RateLimitBurst=
-RateLimitIntervalSec=
-ReadKMsg=
-ReadOnly=
+ReadOnlyDirectories=
 ReadOnlyPaths=
-ReadWriteOnly=
+ReadWriteDirectories=
 ReadWritePaths=
+RebootArgument=
+RemainAfterExit=
 RemoveIPC=
-ReserveVT=
+Restart=
+RestartForceExitStatus=
+RestartKillSignal=
+RestartPreventExitStatus=
+RestartSec=
 RestrictAddressFamilies=
 RestrictNamespaces=
 RestrictRealtime=
 RestrictSUIDSGID=
+RootDirectory=
+RootDirectoryStartOnly=
+RootHash=
+RootHashSignature=
+RootImage=
+RootImageOptions=
+RootVerity=
 RuntimeDirectory=
-RuntimeDirectoryInodesMax=
 RuntimeDirectoryMode=
 RuntimeDirectoryPreserve=
-RuntimeDirectorySize=
-RuntimeKeepFree=
-RuntimeMaxFileSize=
-RuntimeMaxFiles=
-RuntimeMaxUse=
+RuntimeMaxSec=
 SELinuxContext=
-SUPPORT_URL=
-Seal=
-ServerCertificateFile=
-ServerKeyFile=
-SessionsMax=
+SecureBits=
+SendSIGHUP=
+SendSIGKILL=
+SetCredential=
+Slice=
 SmackProcessLabel=
-SplitMode=
+Sockets=
 StandardError=
 StandardInput=
 StandardInputData=
 StandardInputText=
 StandardOutput=
+StartLimitAction=
+StartLimitBurst=
+StartLimitInterval=
+StartupBlockIOWeight=
+StartupCPUShares=
+StartupCPUWeight=
+StartupIOWeight=
 StateDirectory=
 StateDirectoryMode=
-Storage=
-SuspendKeyIgnoreInhibited=
-SyncIntervalSec=
+SuccessExitStatus=
+SupplementaryGroups=
+SysVStartPriority=
 SyslogFacility=
 SyslogIdentifier=
 SyslogLevel=
@@ -918,31 +313,30 @@ SyslogLevelPrefix=
 SystemCallArchitectures=
 SystemCallErrorNumber=
 SystemCallFilter=
-SystemKeepFree=
-SystemMaxFileSize=
-SystemMaxFiles=
-SystemMaxUse=
+SystemCallLog=
 TTYPath=
 TTYReset=
 TTYVHangup=
 TTYVTDisallocate=
+TasksAccounting=
+TasksMax=
 TemporaryFileSystem=
+TimeoutAbortSec=
+TimeoutCleanSec=
+TimeoutSec=
+TimeoutStartFailureMode=
+TimeoutStartSec=
+TimeoutStopFailureMode=
+TimeoutStopSec=
 TimerSlackNSec=
-TrustedCertificateFile=
+Type=
 UMask=
-URL=
+USBFunctionDescriptors=
+USBFunctionStrings=
 UnsetEnvironment=
 User=
-UserTasksMax=
 UtmpIdentifier=
 UtmpMode=
-VARIANT=
-VARIANT_ID=
-VERSION=
-VERSION_CODENAME=
-VERSION_ID=
-VirtualEthernet=
-VirtualEthernetExtra=
-Volatile=
+WatchdogSec=
+WatchdogSignal=
 WorkingDirectory=
-Zone=
diff --git a/test/fuzz/fuzz-unit-file/directives.slice b/test/fuzz/fuzz-unit-file/directives.slice
new file mode 100644 (file)
index 0000000..789ac8f
--- /dev/null
@@ -0,0 +1,55 @@
+slice
+[Slice]
+AllowedCPUs=
+AllowedMemoryNodes=
+BPFProgram=
+BlockIOAccounting=
+BlockIODeviceWeight=
+BlockIOReadBandwidth=
+BlockIOWeight=
+BlockIOWriteBandwidth=
+CPUAccounting=
+CPUQuota=
+CPUQuotaPeriodSec=
+CPUShares=
+CPUWeight=
+DefaultMemoryLow=
+DefaultMemoryMin=
+Delegate=
+DeviceAllow=
+DevicePolicy=
+DisableControllers=
+IOAccounting=
+IODeviceLatencyTargetSec=
+IODeviceWeight=
+IOReadBandwidthMax=
+IOReadIOPSMax=
+IOWeight=
+IOWriteBandwidthMax=
+IOWriteIOPSMax=
+IPAccounting=
+IPAddressAllow=
+IPAddressDeny=
+IPEgressFilterPath=
+IPIngressFilterPath=
+ManagedOOMMemoryPressure=
+ManagedOOMMemoryPressureLimit=
+ManagedOOMPreference=
+ManagedOOMSwap=
+MemoryAccounting=
+MemoryHigh=
+MemoryLimit=
+MemoryLow=
+MemoryMax=
+MemoryMin=
+MemorySwapMax=
+NetClass=
+Slice=
+SocketBindAllow=
+SocketBindDeny=
+StartupBlockIOWeight=
+StartupCPUShares=
+StartupCPUWeight=
+StartupIOWeight=
+TasksAccounting=
+TasksMax=
diff --git a/test/fuzz/fuzz-unit-file/directives.socket b/test/fuzz/fuzz-unit-file/directives.socket
new file mode 100644 (file)
index 0000000..11f589e
--- /dev/null
@@ -0,0 +1,256 @@
+socket
+[Socket]
+Accept=
+AllowedCPUs=
+AllowedMemoryNodes=
+AmbientCapabilities=
+AppArmorProfile=
+BPFProgram=
+Backlog=
+BindIPv6Only=
+BindPaths=
+BindReadOnlyPaths=
+BindToDevice=
+BlockIOAccounting=
+BlockIODeviceWeight=
+BlockIOReadBandwidth=
+BlockIOWeight=
+BlockIOWriteBandwidth=
+Broadcast=
+CPUAccounting=
+CPUAffinity=
+CPUQuota=
+CPUQuotaPeriodSec=
+CPUSchedulingPolicy=
+CPUSchedulingPriority=
+CPUSchedulingResetOnFork=
+CPUShares=
+CPUWeight=
+CacheDirectory=
+CacheDirectoryMode=
+Capabilities=
+CapabilityBoundingSet=
+ConfigurationDirectory=
+ConfigurationDirectoryMode=
+CoredumpFilter=
+DefaultMemoryLow=
+DefaultMemoryMin=
+DeferAcceptSec=
+Delegate=
+DeviceAllow=
+DevicePolicy=
+DirectoryMode=
+DisableControllers=
+DynamicUser=
+Environment=
+EnvironmentFile=
+ExecPaths=
+ExecStartPost=
+ExecStartPre=
+ExecStopPost=
+ExecStopPre=
+ExtensionImages=
+FileDescriptorName=
+FinalKillSignal=
+FlushPending=
+FreeBind=
+Group=
+IOAccounting=
+IODeviceLatencyTargetSec=
+IODeviceWeight=
+IOReadBandwidthMax=
+IOReadIOPSMax=
+IOSchedulingClass=
+IOSchedulingPriority=
+IOWeight=
+IOWriteBandwidthMax=
+IOWriteIOPSMax=
+IPAccounting=
+IPAddressAllow=
+IPAddressDeny=
+IPCNamespacePath=
+IPEgressFilterPath=
+IPIngressFilterPath=
+IPTOS=
+IPTTL=
+IgnoreSIGPIPE=
+InaccessibleDirectories=
+InaccessiblePaths=
+KeepAlive=
+KeepAliveIntervalSec=
+KeepAliveProbes=
+KeepAliveTimeSec=
+KeyringMode=
+KillMode=
+KillSignal=
+LimitAS=
+LimitCORE=
+LimitCPU=
+LimitDATA=
+LimitFSIZE=
+LimitLOCKS=
+LimitMEMLOCK=
+LimitMSGQUEUE=
+LimitNICE=
+LimitNOFILE=
+LimitNPROC=
+LimitRSS=
+LimitRTPRIO=
+LimitRTTIME=
+LimitSIGPENDING=
+LimitSTACK=
+ListenDatagram=
+ListenFIFO=
+ListenMessageQueue=
+ListenNetlink=
+ListenSequentialPacket=
+ListenSpecial=
+ListenStream=
+ListenUSBFunction=
+LoadCredential=
+LockPersonality=
+LogExtraFields=
+LogLevelMax=
+LogNamespace=
+LogRateLimitBurst=
+LogRateLimitIntervalSec=
+LogsDirectory=
+LogsDirectoryMode=
+ManagedOOMMemoryPressure=
+ManagedOOMMemoryPressureLimit=
+ManagedOOMPreference=
+ManagedOOMSwap=
+Mark=
+MaxConnections=
+MaxConnectionsPerSource=
+MemoryAccounting=
+MemoryDenyWriteExecute=
+MemoryHigh=
+MemoryLimit=
+MemoryLow=
+MemoryMax=
+MemoryMin=
+MemorySwapMax=
+MessageQueueMaxMessages=
+MessageQueueMessageSize=
+MountAPIVFS=
+MountFlags=
+MountImages=
+NUMAMask=
+NUMAPolicy=
+NetClass=
+NetworkNamespacePath=
+Nice=
+NoDelay=
+NoExecPaths=
+NoNewPrivileges=
+OOMScoreAdjust=
+PAMName=
+PassCredentials=
+PassEnvironment=
+PassPacketInfo=
+PassSecurity=
+Personality=
+PipeSize=
+Priority=
+PrivateDevices=
+PrivateIPC=
+PrivateMounts=
+PrivateNetwork=
+PrivateTmp=
+PrivateUsers=
+ProcSubset=
+ProtectClock=
+ProtectControlGroups=
+ProtectHome=
+ProtectHostname=
+ProtectKernelLogs=
+ProtectKernelModules=
+ProtectKernelTunables=
+ProtectProc=
+ProtectSystem=
+ReadOnlyDirectories=
+ReadOnlyPaths=
+ReadWriteDirectories=
+ReadWritePaths=
+ReceiveBuffer=
+RemoveIPC=
+RemoveOnStop=
+RestartKillSignal=
+RestrictAddressFamilies=
+RestrictNamespaces=
+RestrictRealtime=
+RestrictSUIDSGID=
+ReusePort=
+RootDirectory=
+RootHash=
+RootHashSignature=
+RootImage=
+RootImageOptions=
+RootVerity=
+RuntimeDirectory=
+RuntimeDirectoryMode=
+RuntimeDirectoryPreserve=
+SELinuxContext=
+SELinuxContextFromNet=
+SecureBits=
+SendBuffer=
+SendSIGHUP=
+SendSIGKILL=
+Service=
+SetCredential=
+Slice=
+SmackLabel=
+SmackLabelIPIn=
+SmackLabelIPOut=
+SmackProcessLabel=
+SocketBindAllow=
+SocketBindDeny=
+SocketGroup=
+SocketMode=
+SocketProtocol=
+SocketUser=
+StandardError=
+StandardInput=
+StandardInputData=
+StandardInputText=
+StandardOutput=
+StartupBlockIOWeight=
+StartupCPUShares=
+StartupCPUWeight=
+StartupIOWeight=
+StateDirectory=
+StateDirectoryMode=
+SupplementaryGroups=
+Symlinks=
+SyslogFacility=
+SyslogIdentifier=
+SyslogLevel=
+SyslogLevelPrefix=
+SystemCallArchitectures=
+SystemCallErrorNumber=
+SystemCallFilter=
+SystemCallLog=
+TCPCongestion=
+TTYPath=
+TTYReset=
+TTYVHangup=
+TTYVTDisallocate=
+TasksAccounting=
+TasksMax=
+TemporaryFileSystem=
+TimeoutCleanSec=
+TimeoutSec=
+TimerSlackNSec=
+Timestamping=
+Transparent=
+TriggerLimitBurst=
+TriggerLimitIntervalSec=
+UMask=
+UnsetEnvironment=
+User=
+UtmpIdentifier=
+UtmpMode=
+WatchdogSignal=
+WorkingDirectory=
+Writable=
diff --git a/test/fuzz/fuzz-unit-file/directives.swap b/test/fuzz/fuzz-unit-file/directives.swap
new file mode 100644 (file)
index 0000000..582a136
--- /dev/null
@@ -0,0 +1,200 @@
+swap
+[Swap]
+AllowedCPUs=
+AllowedMemoryNodes=
+AmbientCapabilities=
+AppArmorProfile=
+BPFProgram=
+BindPaths=
+BindReadOnlyPaths=
+BlockIOAccounting=
+BlockIODeviceWeight=
+BlockIOReadBandwidth=
+BlockIOWeight=
+BlockIOWriteBandwidth=
+CPUAccounting=
+CPUAffinity=
+CPUQuota=
+CPUQuotaPeriodSec=
+CPUSchedulingPolicy=
+CPUSchedulingPriority=
+CPUSchedulingResetOnFork=
+CPUShares=
+CPUWeight=
+CacheDirectory=
+CacheDirectoryMode=
+Capabilities=
+CapabilityBoundingSet=
+ConfigurationDirectory=
+ConfigurationDirectoryMode=
+CoredumpFilter=
+DefaultMemoryLow=
+DefaultMemoryMin=
+Delegate=
+DeviceAllow=
+DevicePolicy=
+DisableControllers=
+DynamicUser=
+Environment=
+EnvironmentFile=
+ExecPaths=
+ExtensionImages=
+FinalKillSignal=
+Group=
+IOAccounting=
+IODeviceLatencyTargetSec=
+IODeviceWeight=
+IOReadBandwidthMax=
+IOReadIOPSMax=
+IOSchedulingClass=
+IOSchedulingPriority=
+IOWeight=
+IOWriteBandwidthMax=
+IOWriteIOPSMax=
+IPAccounting=
+IPAddressAllow=
+IPAddressDeny=
+IPCNamespacePath=
+IPEgressFilterPath=
+IPIngressFilterPath=
+IgnoreSIGPIPE=
+InaccessibleDirectories=
+InaccessiblePaths=
+KeyringMode=
+KillMode=
+KillSignal=
+LimitAS=
+LimitCORE=
+LimitCPU=
+LimitDATA=
+LimitFSIZE=
+LimitLOCKS=
+LimitMEMLOCK=
+LimitMSGQUEUE=
+LimitNICE=
+LimitNOFILE=
+LimitNPROC=
+LimitRSS=
+LimitRTPRIO=
+LimitRTTIME=
+LimitSIGPENDING=
+LimitSTACK=
+LoadCredential=
+LockPersonality=
+LogExtraFields=
+LogLevelMax=
+LogNamespace=
+LogRateLimitBurst=
+LogRateLimitIntervalSec=
+LogsDirectory=
+LogsDirectoryMode=
+ManagedOOMMemoryPressure=
+ManagedOOMMemoryPressureLimit=
+ManagedOOMPreference=
+ManagedOOMSwap=
+MemoryAccounting=
+MemoryDenyWriteExecute=
+MemoryHigh=
+MemoryLimit=
+MemoryLow=
+MemoryMax=
+MemoryMin=
+MemorySwapMax=
+MountAPIVFS=
+MountFlags=
+MountImages=
+NUMAMask=
+NUMAPolicy=
+NetClass=
+NetworkNamespacePath=
+Nice=
+NoExecPaths=
+NoNewPrivileges=
+OOMScoreAdjust=
+Options=
+PAMName=
+PassEnvironment=
+Personality=
+Priority=
+PrivateDevices=
+PrivateIPC=
+PrivateMounts=
+PrivateNetwork=
+PrivateTmp=
+PrivateUsers=
+ProcSubset=
+ProtectClock=
+ProtectControlGroups=
+ProtectHome=
+ProtectHostname=
+ProtectKernelLogs=
+ProtectKernelModules=
+ProtectKernelTunables=
+ProtectProc=
+ProtectSystem=
+ReadOnlyDirectories=
+ReadOnlyPaths=
+ReadWriteDirectories=
+ReadWritePaths=
+RemoveIPC=
+RestartKillSignal=
+RestrictAddressFamilies=
+RestrictNamespaces=
+RestrictRealtime=
+RestrictSUIDSGID=
+RootDirectory=
+RootHash=
+RootHashSignature=
+RootImage=
+RootImageOptions=
+RootVerity=
+RuntimeDirectory=
+RuntimeDirectoryMode=
+RuntimeDirectoryPreserve=
+SELinuxContext=
+SecureBits=
+SendSIGHUP=
+SendSIGKILL=
+SetCredential=
+Slice=
+SmackProcessLabel=
+SocketBindAllow=
+SocketBindDeny=
+StandardError=
+StandardInput=
+StandardInputData=
+StandardInputText=
+StandardOutput=
+StartupBlockIOWeight=
+StartupCPUShares=
+StartupCPUWeight=
+StartupIOWeight=
+StateDirectory=
+StateDirectoryMode=
+SupplementaryGroups=
+SyslogFacility=
+SyslogIdentifier=
+SyslogLevel=
+SyslogLevelPrefix=
+SystemCallArchitectures=
+SystemCallErrorNumber=
+SystemCallFilter=
+SystemCallLog=
+TTYPath=
+TTYReset=
+TTYVHangup=
+TTYVTDisallocate=
+TasksAccounting=
+TasksMax=
+TemporaryFileSystem=
+TimeoutCleanSec=
+TimeoutSec=
+TimerSlackNSec=
+UMask=
+UnsetEnvironment=
+User=
+UtmpIdentifier=
+UtmpMode=
+WatchdogSignal=
+What=
+WorkingDirectory=
diff --git a/test/fuzz/fuzz-unit-file/directives.timer b/test/fuzz/fuzz-unit-file/directives.timer
new file mode 100644 (file)
index 0000000..40075cf
--- /dev/null
@@ -0,0 +1,17 @@
+timer
+[Timer]
+AccuracySec=
+FixedRandomDelay=
+OnActiveSec=
+OnBootSec=
+OnCalendar=
+OnClockChange=
+OnStartupSec=
+OnTimezoneChange=
+OnUnitActiveSec=
+OnUnitInactiveSec=
+Persistent=
+RandomizedDelaySec=
+RemainAfterElapse=
+Unit=
+WakeSystem=
diff --git a/test/fuzz/fuzz-unit-file/github-19178 b/test/fuzz/fuzz-unit-file/github-19178
new file mode 100644 (file)
index 0000000..982c344
--- /dev/null
@@ -0,0 +1,3 @@
+service
+[Service]
+LoadCredential=passwd.hashed-password.root
diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-32991 b/test/fuzz/fuzz-unit-file/oss-fuzz-32991
new file mode 100644 (file)
index 0000000..6305b2a
Binary files /dev/null and b/test/fuzz/fuzz-unit-file/oss-fuzz-32991 differ
diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-33270 b/test/fuzz/fuzz-unit-file/oss-fuzz-33270
new file mode 100644 (file)
index 0000000..84f1da4
Binary files /dev/null and b/test/fuzz/fuzz-unit-file/oss-fuzz-33270 differ
diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-33876 b/test/fuzz/fuzz-unit-file/oss-fuzz-33876
new file mode 100644 (file)
index 0000000..00b3858
Binary files /dev/null and b/test/fuzz/fuzz-unit-file/oss-fuzz-33876 differ
index 2b54a0e70fcf0652dc8086d7a4a631ca785ed998..57d98e513bf57c44e55ca10a5a525099cc5c2f42 100755 (executable)
@@ -11,10 +11,10 @@ set -e
 
 export SYSTEMD_LOG_LEVEL=info
 ROOTDIR=$(dirname $(dirname $(readlink -f $0)))
-SYSTEMD_HWDB=./systemd-hwdb
+SYSTEMD_HWDB="${1:?missing argument}"
 
 if [ ! -x "$SYSTEMD_HWDB" ]; then
-    echo "$SYSTEMD_HWDB does not exist, please build first"
+    echo "$SYSTEMD_HWDB is not executable" >&2
     exit 1
 fi
 
index 4d7b929a80947263c871eb919a58ace82842d147..ee6733fca4b5a32617adf5eda58debe3406ad3d1 100644 (file)
@@ -57,10 +57,8 @@ if install_tests
 endif
 
 test_network_generator_conversion_sh = find_program('test-network-generator-conversion.sh')
-
-############################################################
-
 test_systemd_tmpfiles_py = find_program('test-systemd-tmpfiles.py')
+hwdb_test_sh = find_program('hwdb-test.sh')
 
 ############################################################
 
@@ -128,17 +126,6 @@ endif
 
 ############################################################
 
-if conf.get('ENABLE_HWDB') == 1
-        hwdb_test_sh = find_program('hwdb-test.sh')
-        if want_tests != 'false'
-                test('hwdb-test',
-                     hwdb_test_sh,
-                     timeout : 90)
-        endif
-endif
-
-############################################################
-
 if want_tests != 'false' and dmi_arches.contains(host_machine.cpu_family())
         udev_dmi_memory_id_test = find_program('udev-dmi-memory-id-test.sh')
 
index 8983bb056b23457d6ff0891ab5f44f86f1d690ac..2118bfc2a661c0f022f2489b007f9b23a740a7a1 100644 (file)
@@ -2,8 +2,8 @@
 Description=Test for StandardOutput=append:
 
 [Service]
-ExecStartPre=sh -c 'printf "hello\n" > /tmp/test-exec-standardoutput-output'
-ExecStartPre=sh -c 'printf "hello\nhello\n" > /tmp/test-exec-standardoutput-expected'
+ExecStartPre=sh -c 'printf "hello\n" >/tmp/test-exec-standardoutput-output'
+ExecStartPre=sh -c 'printf "hello\nhello\n" >/tmp/test-exec-standardoutput-expected'
 StandardInput=data
 StandardInputText=hello
 StandardOutput=append:/tmp/test-exec-standardoutput-output
index 71e2604b942ca26b8a742e7e6dd42036a9a4d140..8d484a456e6b4eec1901de9b9969b213d329d067 100644 (file)
@@ -2,8 +2,8 @@
 Description=Test for StandardOutput=file:
 
 [Service]
-ExecStartPre=sh -c 'printf "nooo\nhello\n" > /tmp/test-exec-standardoutput-output'
-ExecStartPre=sh -c 'printf "hello\nello\n" > /tmp/test-exec-standardoutput-expected'
+ExecStartPre=sh -c 'printf "nooo\nhello\n" >/tmp/test-exec-standardoutput-output'
+ExecStartPre=sh -c 'printf "hello\nello\n" >/tmp/test-exec-standardoutput-expected'
 StandardInput=data
 StandardInputText=hello
 StandardOutput=file:/tmp/test-exec-standardoutput-output
index 4b4bb87b758bb97a4ba2ba68fe58ee8c05dfe313..8d6ea2769fed3fa9e80db45a8fe04eb0a608fb9e 100644 (file)
@@ -2,8 +2,8 @@
 Description=Test for StandardOutput=truncate:
 
 [Service]
-ExecStartPre=sh -c 'printf "hello\n" > /tmp/test-exec-standardoutput-output'
-ExecStartPre=sh -c 'printf "hi\n" > /tmp/test-exec-standardoutput-expected'
+ExecStartPre=sh -c 'printf "hello\n" >/tmp/test-exec-standardoutput-output'
+ExecStartPre=sh -c 'printf "hi\n" >/tmp/test-exec-standardoutput-expected'
 StandardInput=data
 StandardInputText=hi
 StandardOutput=truncate:/tmp/test-exec-standardoutput-output
index 6b94058fd366a989544f5acf97b1406d70162389..64accfc29ea98c47925965396dea4331ae84b1a7 100644 (file)
@@ -1,15 +1,27 @@
 #!/usr/bin/env bash
+# shellcheck disable=SC2031
 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
-# ex: ts=8 sw=4 sts=4 et filetype=sh
+# ex: ts=8 sw=4 sts=4 et filetype=sh tw=180
+# Note: the shellcheck line above disables warning for variables which were
+#       modified in a subshell. In our case this behavior is expected, but
+#       `shellcheck` can't distinguish this because of poor variable tracking,
+#       which results in warning for every instance of such variable used
+#       throughout this file.
+#       See:
+#           * comment in function install_verity_minimal()
+#           * koalaman/shellcheck#280
+set -o pipefail
+
 PATH=/sbin:/bin:/usr/sbin:/usr/bin
 export PATH
 
 os_release=$(test -e /etc/os-release && echo /etc/os-release || echo /usr/lib/os-release)
-LOOKS_LIKE_DEBIAN=$(source $os_release && [[ "$ID" = "debian" || " $ID_LIKE " = *" debian "* ]] && echo yes || :)
-LOOKS_LIKE_ARCH=$(source $os_release && [[ "$ID" = "arch" || " $ID_LIKE " = *" arch "* ]] && echo yes || :)
-LOOKS_LIKE_SUSE=$(source $os_release && [[ " $ID_LIKE " = *" suse "* ]] && echo yes || :)
-KERNEL_VER=${KERNEL_VER-$(uname -r)}
-KERNEL_MODS="/lib/modules/$KERNEL_VER/"
+# shellcheck source=/dev/null
+source "$os_release"
+[[ "$ID" = "debian" || " $ID_LIKE " = *" debian "* ]] && LOOKS_LIKE_DEBIAN=yes || LOOKS_LIKE_DEBIAN=""
+[[ "$ID" = "arch" || " $ID_LIKE " = *" arch "* ]] && LOOKS_LIKE_ARCH=yes || LOOKS_LIKE_ARCH=""
+[[ " $ID_LIKE " = *" suse "* ]] && LOOKS_LIKE_SUSE=yes || LOOKS_LIKE_SUSE=""
+KERNEL_VER="${KERNEL_VER-$(uname -r)}"
 QEMU_TIMEOUT="${QEMU_TIMEOUT:-infinity}"
 NSPAWN_TIMEOUT="${NSPAWN_TIMEOUT:-infinity}"
 TIMED_OUT=  # will be 1 after run_* if *_TIMEOUT is set and test timed out
@@ -32,7 +44,7 @@ LOOPDEV=
 # check if it's not explicitly disabled (TEST_NO_KVM) and we're not already
 # running under KVM. If these conditions are met, enable KVM (and possibly
 # nested KVM), otherwise disable it.
-if [[ -n "$TEST_NESTED_KVM" || ( -z "$TEST_NO_KVM" && $(systemd-detect-virt -v) != kvm ) ]]; then
+if [[ -n "${TEST_NESTED_KVM:=}" || ( -z "${TEST_NO_KVM:=}" && $(systemd-detect-virt -v) != kvm ) ]]; then
     QEMU_KVM=yes
 else
     QEMU_KVM=no
@@ -44,39 +56,52 @@ if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then
 fi
 
 # The calling test.sh scripts have TEST_BASE_DIR set via their Makefile, but we don't need them to provide it
-TEST_BASE_DIR=${TEST_BASE_DIR:-$(realpath $(dirname "$BASH_SOURCE"))}
-TEST_UNITS_DIR="$TEST_BASE_DIR/units"
+TEST_BASE_DIR=${TEST_BASE_DIR:-$(realpath "$(dirname "${BASH_SOURCE[0]}")")}
+TEST_UNITS_DIR="$(realpath "$TEST_BASE_DIR/units")"
 SOURCE_DIR=$(realpath "$TEST_BASE_DIR/..")
 TOOLS_DIR="$SOURCE_DIR/tools"
+# These variables are used by test scripts
+export TEST_BASE_DIR TEST_UNITS_DIR SOURCE_DIR TOOLS_DIR
 
 # note that find-build-dir.sh will return $BUILD_DIR if provided, else it will try to find it
-if ! BUILD_DIR=$($TOOLS_DIR/find-build-dir.sh); then
+if ! BUILD_DIR="$("$TOOLS_DIR"/find-build-dir.sh)"; then
     if [ "$NO_BUILD" ]; then
-        BUILD_DIR=$SOURCE_DIR
+        BUILD_DIR="$SOURCE_DIR"
     else
         echo "ERROR: no build found, please set BUILD_DIR or use NO_BUILD" >&2
         exit 1
     fi
 fi
 
-PATH_TO_INIT=$ROOTLIBDIR/systemd
-[ "$SYSTEMD_JOURNALD" ] || SYSTEMD_JOURNALD=$(which -a $BUILD_DIR/systemd-journald $ROOTLIBDIR/systemd-journald 2>/dev/null | grep '^/' -m1)
-[ "$SYSTEMD_JOURNAL_REMOTE" ] || SYSTEMD_JOURNAL_REMOTE=$(which -a $BUILD_DIR/systemd-journal-remote $ROOTLIBDIR/systemd-journal-remote 2>/dev/null | grep '^/' -m1)
-[ "$SYSTEMD" ] || SYSTEMD=$(which -a $BUILD_DIR/systemd $ROOTLIBDIR/systemd 2>/dev/null | grep '^/' -m1)
-[ "$SYSTEMD_NSPAWN" ] || SYSTEMD_NSPAWN=$(which -a $BUILD_DIR/systemd-nspawn systemd-nspawn 2>/dev/null | grep '^/' -m1)
-[ "$JOURNALCTL" ] || JOURNALCTL=$(which -a $BUILD_DIR/journalctl journalctl 2>/dev/null | grep '^/' -m1)
+PATH_TO_INIT="$ROOTLIBDIR/systemd"
+SYSTEMD_JOURNALD="${SYSTEMD_JOURNALD:-$(command -v "$BUILD_DIR/systemd-journald" || command -v "$ROOTLIBDIR/systemd-journald")}"
+SYSTEMD_JOURNAL_REMOTE="${SYSTEMD_JOURNAL_REMOTE:-$(command -v "$BUILD_DIR/systemd-journal-remote" || command -v "$ROOTLIBDIR/systemd-journal-remote")}"
+SYSTEMD="${SYSTEMD:-$(command -v "$BUILD_DIR/systemd" || command -v "$ROOTLIBDIR/systemd")}"
+SYSTEMD_NSPAWN="${SYSTEMD_NSPAWN:-$(command -v "$BUILD_DIR/systemd-nspawn" || command -v systemd-nspawn)}"
+JOURNALCTL="${JOURNALCTL:-$(command -v "$BUILD_DIR/journalctl" || command -v journalctl)}"
 
-TESTFILE=${BASH_SOURCE[1]}
+TESTFILE="${BASH_SOURCE[1]}"
 if [ -z "$TESTFILE" ]; then
     echo "ERROR: test-functions must be sourced from one of the TEST-*/test.sh scripts" >&2
     exit 1
 fi
-TESTNAME=$(basename $(dirname $(realpath $TESTFILE)))
+TESTNAME="$(basename "$(dirname "$(realpath "$TESTFILE")")")"
 STATEDIR="$BUILD_DIR/test/$TESTNAME"
 STATEFILE="$STATEDIR/.testdir"
 IMAGESTATEDIR="$STATEDIR/.."
 TESTLOG="$STATEDIR/test.log"
 
+if ! [[ "$TESTNAME" =~ ^TEST\-([0-9]+)\-.+$ ]]; then
+    echo "ERROR: Test name '$TESTNAME' is not in the expected format: TEST-[0-9]+-*" >&2
+    exit 1
+fi
+TESTID="${BASH_REMATCH[1]:?}"
+
+if [[ ! -f "$TEST_UNITS_DIR/testsuite-$TESTID.service" ]]; then
+    echo "ERROR: Test '$TESTNAME' is missing its service file '$TEST_UNITS_DIR/testsuite-$TESTID.service" >&2
+    exit 1
+fi
+
 BASICTOOLS=(
     awk
     basename
@@ -183,8 +208,9 @@ is_built_with_asan() {
     fi
 
     # Borrowed from https://github.com/google/oss-fuzz/blob/cd9acd02f9d3f6e80011cc1e9549be526ce5f270/infra/base-images/base-runner/bad_build_check#L182
-    local _asan_calls=$(objdump -dC $SYSTEMD_JOURNALD | egrep "callq?\s+[0-9a-f]+\s+<__asan" -c)
-    if (( $_asan_calls < 1000 )); then
+    local _asan_calls
+    _asan_calls="$(objdump -dC "$SYSTEMD_JOURNALD" | grep -E "callq?\s+[0-9a-f]+\s+<__asan" -c)"
+    if ((_asan_calls < 1000)); then
         return 1
     else
         return 0
@@ -201,10 +227,10 @@ if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
     QEMU_SMP="${QEMU_SMP:-4}"
 
     # We need to correctly distinguish between gcc's and clang's ASan DSOs.
-    if ASAN_RT_NAME="$(ldd "$SYSTEMD" | awk '/libasan.so/ {x=$1; exit} END {print x; exit x==""}')"; then
+    if ASAN_RT_NAME="$(awk '/libasan.so/ {x=$1; exit} END {print x; exit x==""}' < <(ldd "$SYSTEMD"))"; then
         ASAN_COMPILER=gcc
         ASAN_RT_PATH="$(readlink -f "$(${CC:-gcc} --print-file-name "$ASAN_RT_NAME")")"
-    elif ASAN_RT_NAME="$(ldd "$SYSTEMD" | awk '/libclang_rt.asan/ {x=$1; exit} END {print x; exit x==""}')"; then
+    elif ASAN_RT_NAME="$(awk '/libclang_rt.asan/ {x=$1; exit} END {print x; exit x==""}' < <(ldd "$SYSTEMD"))"; then
         ASAN_COMPILER=clang
         ASAN_RT_PATH="$(readlink -f "$(${CC:-clang} --print-file-name "$ASAN_RT_NAME")")"
 
@@ -227,31 +253,32 @@ if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
     echo "Detected ASan RT '$ASAN_RT_NAME' located at '$ASAN_RT_PATH'"
 fi
 
-function find_qemu_bin() {
+find_qemu_bin() {
+    QEMU_BIN="${QEMU_BIN:-""}"
     # SUSE and Red Hat call the binary qemu-kvm. Debian and Gentoo call it kvm.
     if [[ $QEMU_KVM == "yes" ]]; then
-        [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a kvm qemu-kvm 2>/dev/null | grep '^/' -m1)
+        [[ -n "$QEMU_BIN" ]] || QEMU_BIN="$(command -v kvm qemu-kvm 2>/dev/null | grep '^/' -m1)"
     fi
 
-    [ "$ARCH" ] || ARCH=$(uname -m)
+    [[ -n "$ARCH" ]] || ARCH="$(uname -m)"
     case $ARCH in
     x86_64)
         # QEMU's own build system calls it qemu-system-x86_64
-        [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-x86_64 2>/dev/null | grep '^/' -m1)
+        [[ -n "$QEMU_BIN" ]] || QEMU_BIN="$(command -v qemu-system-x86_64 2>/dev/null | grep '^/' -m1)"
         ;;
     i*86)
         # new i386 version of QEMU
-        [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-i386 2>/dev/null | grep '^/' -m1)
+        [[ -n "$QEMU_BIN" ]] || QEMU_BIN="$(command -v qemu-system-i386 2>/dev/null | grep '^/' -m1)"
 
         # i386 version of QEMU
-        [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu 2>/dev/null | grep '^/' -m1)
+        [[ -n "$QEMU_BIN" ]] || QEMU_BIN="$(command -v qemu 2>/dev/null | grep '^/' -m1)"
         ;;
     ppc64*)
-        [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-ppc64 2>/dev/null | grep '^/' -m1)
+        [[ -n "$QEMU_BIN" ]] || QEMU_BIN="$(command -v qemu-system-ppc64 2>/dev/null | grep '^/' -m1)"
         ;;
     esac
 
-    if [ ! -e "$QEMU_BIN" ]; then
+    if [[ ! -e "$QEMU_BIN" ]]; then
         echo "Could not find a suitable QEMU binary" >&2
         return 1
     fi
@@ -261,11 +288,12 @@ function find_qemu_bin() {
 # returns 0 if newer or equal
 # returns 1 if older
 # returns 2 if failing
-function qemu_min_version() {
+qemu_min_version() {
     find_qemu_bin || return 2
 
     # get version from binary
-    qemu_ver=$($QEMU_BIN --version | awk '/^QEMU emulator version ([0-9]*\.[0-9]*\.[0-9]*)/ {print $4}')
+    local qemu_ver
+    qemu_ver="$("$QEMU_BIN" --version | awk '/^QEMU emulator version ([0-9]*\.[0-9]*\.[0-9]*)/ {print $4}')"
 
     # Check version string format
     echo "$qemu_ver" | grep -q '^[0-9]*\.[0-9]*\.[0-9]*$' || return 2
@@ -279,14 +307,14 @@ function qemu_min_version() {
 # success), or 1 if QEMU is not available.
 run_qemu() {
     if [ -f /etc/machine-id ]; then
-        read MACHINE_ID < /etc/machine-id
+        read -r MACHINE_ID </etc/machine-id
         [ -z "$INITRD" ] && [ -e "$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/initrd" ] \
             && INITRD="$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/initrd"
         [ -z "$KERNEL_BIN" ] && [ -e "$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/linux" ] \
             && KERNEL_BIN="$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/linux"
     fi
 
-    CONSOLE=ttyS0
+    local CONSOLE=ttyS0
 
     rm -f "$initdir"/{testok,failed,skipped}
     # make sure the initdir is not mounted to avoid concurrent access
@@ -300,20 +328,20 @@ run_qemu() {
             [ "$ARCH" ] || ARCH=$(uname -m)
             case $ARCH in
                 ppc64*)
-                KERNEL_BIN=/boot/vmlinux-$KERNEL_VER
+                KERNEL_BIN="/boot/vmlinux-$KERNEL_VER"
                 CONSOLE=hvc0
                 ;;
                 *)
-                KERNEL_BIN=/boot/vmlinuz-$KERNEL_VER
+                KERNEL_BIN="/boot/vmlinuz-$KERNEL_VER"
                 ;;
             esac
         fi
     fi
 
-    default_fedora_initrd=/boot/initramfs-${KERNEL_VER}.img
-    default_debian_initrd=/boot/initrd.img-${KERNEL_VER}
-    default_arch_initrd=/boot/initramfs-linux-fallback.img
-    default_suse_initrd=/boot/initrd-${KERNEL_VER}
+    local default_fedora_initrd="/boot/initramfs-${KERNEL_VER}.img"
+    local default_debian_initrd="/boot/initrd.img-${KERNEL_VER}"
+    local default_arch_initrd="/boot/initramfs-linux-fallback.img"
+    local default_suse_initrd="/boot/initrd-${KERNEL_VER}"
     if [[ ! "$INITRD" ]]; then
         if [[ -e "$default_fedora_initrd" ]]; then
             INITRD="$default_fedora_initrd"
@@ -330,7 +358,7 @@ run_qemu() {
     # i.e. use the number of online CPUs on the host machine. If the nproc utility
     # is not installed or there's some other error when calling it, fall back
     # to the original value (QEMU_SMP=1).
-    if ! [ "$QEMU_SMP" ]; then
+    if [[ -z "${QEMU_SMP:=}" ]]; then
         if ! QEMU_SMP=$(nproc); then
             dwarn "nproc utility is not installed, falling back to QEMU_SMP=1"
             QEMU_SMP=1
@@ -340,70 +368,81 @@ run_qemu() {
     find_qemu_bin || return 1
 
     # Umount initdir to avoid concurrent access to the filesystem
-    _umount_dir $initdir
+    _umount_dir "$initdir"
+
+    local kernel_params=()
+    local qemu_options=()
+    local qemu_cmd=("$QEMU_BIN")
 
-    local _cgroup_args
     if [[ "$UNIFIED_CGROUP_HIERARCHY" = "yes" ]]; then
-        _cgroup_args="systemd.unified_cgroup_hierarchy=yes"
+        kernel_params+=("systemd.unified_cgroup_hierarchy=yes")
     elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "no" ]]; then
-        _cgroup_args="systemd.unified_cgroup_hierarchy=no systemd.legacy_systemd_cgroup_controller=yes"
+        kernel_params+=("systemd.unified_cgroup_hierarchy=no" "systemd.legacy_systemd_cgroup_controller=yes")
     elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "hybrid" ]]; then
-        _cgroup_args="systemd.unified_cgroup_hierarchy=no systemd.legacy_systemd_cgroup_controller=no"
+        kernel_params+=("systemd.unified_cgroup_hierarchy=no" "systemd.legacy_systemd_cgroup_controller=no")
     elif [[ "$UNIFIED_CGROUP_HIERARCHY" != "default" ]]; then
         dfatal "Unknown UNIFIED_CGROUP_HIERARCHY. Got $UNIFIED_CGROUP_HIERARCHY, expected [yes|no|hybrid|default]"
         exit 1
     fi
 
     if [[ "$LOOKS_LIKE_SUSE" ]]; then
-        PARAMS+="rd.hostonly=0"
-    fi
+        kernel_params+=("rd.hostonly=0")
+    fi
+
+    kernel_params+=(
+        "root=/dev/sda1"
+        "rw"
+        "raid=noautodetect"
+        "rd.luks=0"
+        "loglevel=2"
+        "init=$PATH_TO_INIT"
+        "console=$CONSOLE"
+        "selinux=0"
+        "SYSTEMD_UNIT_PATH=/usr/lib/systemd/tests/testdata/testsuite-$1.units:/usr/lib/systemd/tests/testdata/units:"
+        "systemd.unit=testsuite.target"
+        "systemd.wants=testsuite-$1.service"
+    )
 
-    local _end
     if [[ ! "$INTERACTIVE_DEBUG" ]]; then
-        _end="systemd.wants=end.service"
-    else
-        _end=""
-    fi
-
-    KERNEL_APPEND="$PARAMS \
-root=/dev/sda1 \
-rw \
-raid=noautodetect \
-rd.luks=0 \
-loglevel=2 \
-init=$PATH_TO_INIT \
-console=$CONSOLE \
-selinux=0 \
-$_cgroup_args \
-SYSTEMD_UNIT_PATH=/usr/lib/systemd/tests/testdata/testsuite-$1.units:/usr/lib/systemd/tests/testdata/units: \
-systemd.unit=testsuite.target \
-systemd.wants=testsuite-$1.service ${_end} \
-$KERNEL_APPEND \
-"
+        kernel_params+=("systemd.wants=end.service")
+    fi
 
     [ -e "$IMAGE_PRIVATE" ] && image="$IMAGE_PRIVATE" || image="$IMAGE_PUBLIC"
-    QEMU_OPTIONS="-smp $QEMU_SMP \
--net none \
--m $QEMU_MEM \
--nographic \
--kernel $KERNEL_BIN \
--drive format=raw,cache=unsafe,file=$image \
-$QEMU_OPTIONS \
-"
+    qemu_options+=(
+        -smp "$QEMU_SMP"
+        -net none
+        -m "$QEMU_MEM"
+        -nographic
+        -kernel "$KERNEL_BIN"
+        -drive "format=raw,cache=unsafe,file=$image"
+    )
+
+    if [[ -n "${QEMU_OPTIONS:=}" ]]; then
+        local user_qemu_options
+        read -ra user_qemu_options <<< "$QEMU_OPTIONS"
+        qemu_options+=("${user_qemu_options[@]}")
+    fi
+
+    if [[ -n "${KERNEL_APPEND:=}" ]]; then
+        local user_kernel_append
+        read -ra user_kernel_append <<< "$KERNEL_APPEND"
+        kernel_params+=("${user_kernel_append[@]}")
+    fi
 
     if [[ "$INITRD" && "$SKIP_INITRD" != "yes" ]]; then
-        QEMU_OPTIONS="$QEMU_OPTIONS -initrd $INITRD"
+        qemu_options+=(-initrd "$INITRD")
     fi
 
     # Let's use KVM if possible
     if [[ -c /dev/kvm && $QEMU_KVM == "yes" ]]; then
-        QEMU_OPTIONS="$QEMU_OPTIONS -machine accel=kvm -enable-kvm -cpu host"
+        qemu_options+=(-machine "accel=kvm" -enable-kvm -cpu host)
     fi
 
     if [[ "$QEMU_TIMEOUT" != "infinity" ]]; then
-        QEMU_BIN="timeout --foreground $QEMU_TIMEOUT $QEMU_BIN"
+        qemu_cmd=(timeout --foreground "$QEMU_TIMEOUT" "$QEMU_BIN")
     fi
-    (set -x; $QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND")
+
+    (set -x; "${qemu_cmd[@]}" "${qemu_options[@]}" -append "${kernel_params[*]}")
     rc=$?
     if [ "$rc" = 124 ] && [ "$QEMU_TIMEOUT" != "infinity" ]; then
         derror "test timed out after $QEMU_TIMEOUT s"
@@ -418,43 +457,56 @@ $QEMU_OPTIONS \
 # success), or 1 if nspawn is not available.
 run_nspawn() {
     [[ -d /run/systemd/system ]] || return 1
-    rm -f "$initdir"/{testok,failed,skipped}
-
-    local _nspawn_cmd=(
-        --register=no
-        --kill-signal=SIGKILL
-        --directory=$1
-        --setenv=SYSTEMD_UNIT_PATH=/usr/lib/systemd/tests/testdata/testsuite-$2.units:/usr/lib/systemd/tests/testdata/units:
-        $PATH_TO_INIT
-        $KERNEL_APPEND
-        systemd.unit=testsuite.target
-        systemd.wants=testsuite-$2.service
+    rm -f "${initdir:?}"/{testok,failed,skipped}
+
+    local nspawn_cmd=()
+    local nspawn_options=(
+        "--register=no"
+        "--kill-signal=SIGKILL"
+        "--directory=${1:?}"
+        "--setenv=SYSTEMD_UNIT_PATH=/usr/lib/systemd/tests/testdata/testsuite-$2.units:/usr/lib/systemd/tests/testdata/units:"
+    )
+    local kernel_params=(
+        "$PATH_TO_INIT"
+        "systemd.unit=testsuite.target"
+        "systemd.wants=testsuite-$2.service"
     )
 
     if [[ ! "$INTERACTIVE_DEBUG" ]]; then
-        _nspawn_cmd+=( systemd.wants=end.service )
+        kernel_params+=("systemd.wants=end.service")
     fi
 
-    local _nspawn_pre
-    if [[ "$NSPAWN_TIMEOUT" != "infinity" ]]; then
-        _nspawn_pre=(timeout --foreground $NSPAWN_TIMEOUT)
-    else
-        _nspawn_pre=()
+    if [[ -n "${NSPAWN_ARGUMENTS:=}" ]]; then
+        local user_nspawn_arguments
+        read -ra user_nspawn_arguments <<< "$NSPAWN_ARGUMENTS"
+        nspawn_options+=("${user_nspawn_arguments[@]}")
+    fi
+
+    if [[ -n "${KERNEL_APPEND:=}" ]]; then
+        local user_kernel_append
+        read -ra user_kernel_append <<< "$KERNEL_APPEND"
+        kernel_params+=("${user_kernel_append[@]}")
     fi
 
     if [[ "$UNIFIED_CGROUP_HIERARCHY" = "hybrid" ]]; then
         dwarn "nspawn doesn't support SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=hybrid, skipping"
         exit
     elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "yes" || "$UNIFIED_CGROUP_HIERARCHY" = "no" ]]; then
-        _nspawn_pre=("${_nspawn_pre[@]}" env SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=$UNIFIED_CGROUP_HIERARCHY)
+        nspawn_cmd+=(env "SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=$UNIFIED_CGROUP_HIERARCHY")
     elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "default" ]]; then
-        _nspawn_pre=("${_nspawn_pre[@]}" env --unset=UNIFIED_CGROUP_HIERARCHY --unset=SYSTEMD_NSPAWN_UNIFIED_HIERARCHY)
+        nspawn_cmd+=(env "--unset=UNIFIED_CGROUP_HIERARCHY" "--unset=SYSTEMD_NSPAWN_UNIFIED_HIERARCHY")
     else
         dfatal "Unknown UNIFIED_CGROUP_HIERARCHY. Got $UNIFIED_CGROUP_HIERARCHY, expected [yes|no|hybrid|default]"
         exit 1
     fi
 
-    (set -x; "${_nspawn_pre[@]}" "$SYSTEMD_NSPAWN" $NSPAWN_ARGUMENTS "${_nspawn_cmd[@]}")
+    if [[ "$NSPAWN_TIMEOUT" != "infinity" ]]; then
+        nspawn_cmd+=(timeout --foreground "$NSPAWN_TIMEOUT" "$SYSTEMD_NSPAWN")
+    else
+        nspawn_cmd+=("$SYSTEMD_NSPAWN")
+    fi
+
+    (set -x; "${nspawn_cmd[@]}" "${nspawn_options[@]}" "${kernel_params[@]}")
     rc=$?
     if [ "$rc" = 124 ] && [ "$NSPAWN_TIMEOUT" != "infinity" ]; then
         derror "test timed out after $NSPAWN_TIMEOUT s"
@@ -467,7 +519,8 @@ run_nspawn() {
 
 # Build two very minimal root images, with two units, one is the same and one is different across them
 install_verity_minimal() {
-    if [ -e $initdir/usr/share/minimal.raw ]; then
+    dinfo "Set up a set of minimal images for verity verification"
+    if [ -e "$initdir/usr/share/minimal.raw" ]; then
         return
     fi
     if ! command -v mksquashfs >/dev/null 2>&1; then
@@ -478,6 +531,9 @@ install_verity_minimal() {
         dfatal "veritysetup not found"
         exit 1
     fi
+    # Local modifications of some global variables is intentional in this
+    # subshell (SC2030)
+    # shellcheck disable=SC2030
     (
         BASICTOOLS=(
             bash
@@ -486,12 +542,15 @@ install_verity_minimal() {
             mount
             sleep
         )
-        oldinitdir=$initdir
-        rm -rfv $TESTDIR/minimal
-        export initdir=$TESTDIR/minimal
-        mkdir -p $initdir/usr/lib/systemd/system $initdir/usr/lib/extension-release.d $initdir/etc $initdir/var/tmp $initdir/opt
+        oldinitdir="$initdir"
+        rm -rfv "$TESTDIR/minimal"
+        export initdir="$TESTDIR/minimal"
+        mkdir -p "$initdir/usr/lib/systemd/system" "$initdir/usr/lib/extension-release.d" "$initdir/etc" "$initdir/var/tmp" "$initdir/opt"
         setup_basic_dirs
         install_basic_tools
+        # Shellcheck treats [[ -v VAR ]] as an assignment to avoid a different
+        # issue, thus falsely triggering SC2030 in this case
+        # See: koalaman/shellcheck#1409
         if [[ -v ASAN_RT_PATH ]]; then
             # If we're compiled with ASan, install the ASan RT (and its dependencies)
             # into the verity images to get rid of the annoying errors about
@@ -499,71 +558,71 @@ install_verity_minimal() {
             inst_libs "$ASAN_RT_PATH"
             inst_library "$ASAN_RT_PATH"
         fi
-        cp $os_release $initdir/usr/lib/os-release
-        ln -s ../usr/lib/os-release $initdir/etc/os-release
-        touch $initdir/etc/machine-id $initdir/etc/resolv.conf
-        touch $initdir/opt/some_file
-        echo MARKER=1 >> $initdir/usr/lib/os-release
-        echo -e "[Service]\nExecStartPre=cat /usr/lib/os-release\nExecStart=sleep 120" > $initdir/usr/lib/systemd/system/app0.service
-        cp $initdir/usr/lib/systemd/system/app0.service $initdir/usr/lib/systemd/system/app0-foo.service
-
-        mksquashfs $initdir $oldinitdir/usr/share/minimal_0.raw
-        veritysetup format $oldinitdir/usr/share/minimal_0.raw $oldinitdir/usr/share/minimal_0.verity | \
-            grep '^Root hash:' | cut -f2 | tr -d '\n' > $oldinitdir/usr/share/minimal_0.roothash
-
-        sed -i "s/MARKER=1/MARKER=2/g" $initdir/usr/lib/os-release
-        rm $initdir/usr/lib/systemd/system/app0-foo.service
-        cp $initdir/usr/lib/systemd/system/app0.service $initdir/usr/lib/systemd/system/app0-bar.service
-
-        mksquashfs $initdir $oldinitdir/usr/share/minimal_1.raw
-        veritysetup format $oldinitdir/usr/share/minimal_1.raw $oldinitdir/usr/share/minimal_1.verity | \
-            grep '^Root hash:' | cut -f2 | tr -d '\n' > $oldinitdir/usr/share/minimal_1.roothash
+        cp "$os_release" "$initdir/usr/lib/os-release"
+        ln -s ../usr/lib/os-release "$initdir/etc/os-release"
+        touch "$initdir/etc/machine-id" "$initdir/etc/resolv.conf"
+        touch "$initdir/opt/some_file"
+        echo MARKER=1 >>"$initdir/usr/lib/os-release"
+        echo -e "[Service]\nExecStartPre=cat /usr/lib/os-release\nExecStart=sleep 120" >"$initdir/usr/lib/systemd/system/app0.service"
+        cp "$initdir/usr/lib/systemd/system/app0.service" "$initdir/usr/lib/systemd/system/app0-foo.service"
+
+        mksquashfs "$initdir" "$oldinitdir/usr/share/minimal_0.raw"
+        veritysetup format "$oldinitdir/usr/share/minimal_0.raw" "$oldinitdir/usr/share/minimal_0.verity" | \
+            grep '^Root hash:' | cut -f2 | tr -d '\n' >"$oldinitdir/usr/share/minimal_0.roothash"
+
+        sed -i "s/MARKER=1/MARKER=2/g" "$initdir/usr/lib/os-release"
+        rm "$initdir/usr/lib/systemd/system/app0-foo.service"
+        cp "$initdir/usr/lib/systemd/system/app0.service" "$initdir/usr/lib/systemd/system/app0-bar.service"
+
+        mksquashfs "$initdir" "$oldinitdir/usr/share/minimal_1.raw"
+        veritysetup format "$oldinitdir/usr/share/minimal_1.raw" "$oldinitdir/usr/share/minimal_1.verity" | \
+            grep '^Root hash:' | cut -f2 | tr -d '\n' >"$oldinitdir/usr/share/minimal_1.roothash"
 
         # Rolling distros like Arch do not set VERSION_ID
         local version_id=""
-        if grep -q "^VERSION_ID=" $os_release; then
-            version_id="$(grep "^VERSION_ID=" $os_release)"
+        if grep -q "^VERSION_ID=" "$os_release"; then
+            version_id="$(grep "^VERSION_ID=" "$os_release")"
         fi
 
-        export initdir=$TESTDIR/app0
-        mkdir -p $initdir/usr/lib/extension-release.d $initdir/usr/lib/systemd/system $initdir/opt
-        grep "^ID=" $os_release > $initdir/usr/lib/extension-release.d/extension-release.app0
-        echo "${version_id}" >> $initdir/usr/lib/extension-release.d/extension-release.app0
-        cat <<EOF > $initdir/usr/lib/systemd/system/app0.service
+        export initdir="$TESTDIR/app0"
+        mkdir -p "$initdir/usr/lib/extension-release.d" "$initdir/usr/lib/systemd/system" "$initdir/opt"
+        grep "^ID=" "$os_release" >"$initdir/usr/lib/extension-release.d/extension-release.app0"
+        echo "${version_id}" >>"$initdir/usr/lib/extension-release.d/extension-release.app0"
+        cat >"$initdir/usr/lib/systemd/system/app0.service" <<EOF
 [Service]
 Type=oneshot
 RemainAfterExit=yes
 ExecStart=/opt/script0.sh
 EOF
-        cat <<EOF > $initdir/opt/script0.sh
+        cat >"$initdir/opt/script0.sh" <<EOF
 #!/bin/bash
 set -e
 test -e /usr/lib/os-release
 cat /usr/lib/extension-release.d/extension-release.app0
 EOF
-        chmod +x $initdir/opt/script0.sh
-        echo MARKER=1 > $initdir/usr/lib/systemd/system/some_file
-        mksquashfs $initdir $oldinitdir/usr/share/app0.raw
-
-        export initdir=$TESTDIR/app1
-        mkdir -p $initdir/usr/lib/extension-release.d $initdir/usr/lib/systemd/system $initdir/opt
-        grep "^ID=" $os_release > $initdir/usr/lib/extension-release.d/extension-release.app1
-        echo "${version_id}" >> $initdir/usr/lib/extension-release.d/extension-release.app1
-        cat <<EOF > $initdir/usr/lib/systemd/system/app1.service
+        chmod +x "$initdir/opt/script0.sh"
+        echo MARKER=1 >"$initdir/usr/lib/systemd/system/some_file"
+        mksquashfs "$initdir" "$oldinitdir/usr/share/app0.raw"
+
+        export initdir="$TESTDIR/app1"
+        mkdir -p "$initdir/usr/lib/extension-release.d" "$initdir/usr/lib/systemd/system" "$initdir/opt"
+        grep "^ID=" "$os_release" >"$initdir/usr/lib/extension-release.d/extension-release.app1"
+        echo "${version_id}" >>"$initdir/usr/lib/extension-release.d/extension-release.app1"
+        cat >"$initdir/usr/lib/systemd/system/app1.service" <<EOF
 [Service]
 Type=oneshot
 RemainAfterExit=yes
 ExecStart=/opt/script1.sh
 EOF
-        cat <<EOF > $initdir/opt/script1.sh
+        cat >"$initdir/opt/script1.sh" <<EOF
 #!/bin/bash
 set -e
 test -e /usr/lib/os-release
 cat /usr/lib/extension-release.d/extension-release.app1
 EOF
-        chmod +x $initdir/opt/script1.sh
-        echo MARKER=1 > $initdir/usr/lib/systemd/system/other_file
-        mksquashfs $initdir $oldinitdir/usr/share/app1.raw
+        chmod +x "$initdir/opt/script1.sh"
+        echo MARKER=1 >"$initdir/usr/lib/systemd/system/other_file"
+        mksquashfs "$initdir" "$oldinitdir/usr/share/app1.raw"
     )
 }
 
@@ -584,7 +643,8 @@ setup_basic_environment() {
     install_keymaps
     install_terminfo
     install_execs
-    install_fsck
+    install_fs_tools
+    install_modules
     install_plymouth
     install_debug_tools
     install_ld_so_conf
@@ -603,26 +663,29 @@ setup_basic_environment() {
 }
 
 setup_selinux() {
+    dinfo "Setup SELinux"
     # don't forget KERNEL_APPEND='... selinux=1 ...'
     if [[ "$SETUP_SELINUX" != "yes" ]]; then
-        ddebug "Don't setup SELinux"
+        dinfo "SETUP_SELINUX != yes, skipping SELinux configuration"
         return 0
     fi
-    ddebug "Setup SELinux"
-    local _conf_dir=/etc/selinux
-    local _fixfiles_tools="bash uname cat sort uniq awk grep egrep head expr find rm secon setfiles"
 
-    rm -rf $initdir/$_conf_dir
-    if ! cp -ar $_conf_dir $initdir/$_conf_dir; then
-        dfatal "Failed to copy $_conf_dir"
+    local conf_dir=/etc/selinux
+    local fixfiles_tools=(bash uname cat sort uniq awk grep egrep head expr find rm secon setfiles)
+
+    # Make sure the following statement can't expand to "/" to prevent
+    # a potential where-are-my-backups situation
+    rm -rf "${initdir:?}/$conf_dir"
+    if ! cp -ar "$conf_dir" "$initdir/$conf_dir"; then
+        dfatal "Failed to copy $conf_dir"
         exit 1
     fi
 
-    touch $initdir/.autorelabel
-    mkdir -p $initdir/usr/lib/systemd/tests/testdata/units/basic.target.wants
-    ln -sf ../autorelabel.service $initdir/usr/lib/systemd/tests/testdata/units/basic.target.wants/
+    touch "$initdir/.autorelabel"
+    mkdir -p "$initdir/usr/lib/systemd/tests/testdata/units/basic.target.wants"
+    ln -sf ../autorelabel.service "$initdir/usr/lib/systemd/tests/testdata/units/basic.target.wants/"
 
-    dracut_install $_fixfiles_tools
+    dracut_install "${fixfiles_tools[@]}"
     dracut_install fixfiles
     dracut_install sestatus
 }
@@ -633,35 +696,36 @@ install_valgrind() {
         exit 1
     fi
 
-    local _valgrind_bins=$(strace -e execve valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if /^execve\("([^"]+)"/')
-    dracut_install $_valgrind_bins
+    local valgrind_bins valgrind_libs valgrind_dbg_and_supp
 
-    local _valgrind_libs=$(LD_DEBUG=files valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if m{calling init: (/.*vgpreload_.*)}')
-    dracut_install $_valgrind_libs
+    valgrind_bins="$(strace -e execve valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if /^execve\("([^"]+)"/')"
+    dracut_install "$valgrind_bins"
 
-    local _valgrind_dbg_and_supp=$(
+    valgrind_libs="$(LD_DEBUG=files valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if m{calling init: (/.*vgpreload_.*)}')"
+    dracut_install "$valgrind_libs"
+
+    valgrind_dbg_and_supp="$(
         strace -e open valgrind /bin/true 2>&1 >/dev/null |
         perl -lne 'if (my ($fname) = /^open\("([^"]+).*= (?!-)\d+/) { print $fname if $fname =~ /debug|\.supp$/ }'
-    )
-    dracut_install $_valgrind_dbg_and_supp
+    )"
+    dracut_install "$valgrind_dbg_and_supp"
 }
 
 create_valgrind_wrapper() {
-    local _valgrind_wrapper=$initdir/$ROOTLIBDIR/systemd-under-valgrind
-    ddebug "Create $_valgrind_wrapper"
-    cat >$_valgrind_wrapper <<EOF
+    local valgrind_wrapper="$initdir/$ROOTLIBDIR/systemd-under-valgrind"
+    ddebug "Create $valgrind_wrapper"
+    cat >"$valgrind_wrapper" <<EOF
 #!/usr/bin/env bash
 
 mount -t proc proc /proc
 exec valgrind --leak-check=full --log-file=/valgrind.out $ROOTLIBDIR/systemd "\$@"
 EOF
-    chmod 0755 $_valgrind_wrapper
+    chmod 0755 "$valgrind_wrapper"
 }
 
 create_asan_wrapper() {
-    local _asan_wrapper=$initdir/$ROOTLIBDIR/systemd-under-asan
-    local _asan_rt_pattern
-    ddebug "Create $_asan_wrapper"
+    local asan_wrapper="$initdir/$ROOTLIBDIR/systemd-under-asan"
+    dinfo "Create ASan wrapper as '$asan_wrapper'"
 
     [[ -z "$ASAN_RT_PATH" ]] && dfatal "ASAN_RT_PATH is empty, but it shouldn't be"
 
@@ -669,7 +733,7 @@ create_asan_wrapper() {
     # See: https://clang.llvm.org/docs/AddressSanitizer.html#symbolizing-the-reports
     [[ "$ASAN_COMPILER" == "clang" ]] && dracut_install "llvm-symbolizer"
 
-    cat >$_asan_wrapper <<EOF
+    cat >"$asan_wrapper" <<EOF
 #!/usr/bin/env bash
 
 set -x
@@ -700,7 +764,7 @@ if [[ "$ASAN_COMPILER" == "clang" ]]; then
   # Let's add the ASan DSO's path to the dynamic linker's cache. This is pretty
   # unnecessary for gcc & libasan, however, for clang this is crucial, as its
   # runtime ASan DSO is in a non-standard (library) path.
-  echo "${ASAN_RT_PATH%/*}" > /etc/ld.so.conf.d/asan-path-override.conf
+  echo "${ASAN_RT_PATH%/*}" >/etc/ld.so.conf.d/asan-path-override.conf
   ldconfig
 fi
 echo DefaultEnvironment=\$DEFAULT_ENVIRONMENT >>/etc/systemd/system.conf
@@ -741,7 +805,7 @@ printf "[Service]\nEnvironment=ASAN_OPTIONS=leak_check_at_exit=false\n" >/etc/sy
 # they're uninstrumented (like dmsetup). Let's add a simple rule which sets
 # LD_PRELOAD to the ASan RT library to fix this.
 mkdir -p /etc/udev/rules.d
-cat > /etc/udev/rules.d/00-set-LD_PRELOAD.rules << INNER_EOF
+cat >/etc/udev/rules.d/00-set-LD_PRELOAD.rules <<INNER_EOF
 SUBSYSTEM=="block", ENV{LD_PRELOAD}="$ASAN_RT_PATH"
 INNER_EOF
 chmod 0644 /etc/udev/rules.d/00-set-LD_PRELOAD.rules
@@ -764,29 +828,45 @@ unset_ld_preload systemd-remount-fs
 unset_ld_preload testsuite-
 
 export ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS
-exec  $ROOTLIBDIR/systemd "\$@"
+exec "$ROOTLIBDIR/systemd" "\$@"
 EOF
 
-    chmod 0755 $_asan_wrapper
+    chmod 0755 "$asan_wrapper"
 }
 
 create_strace_wrapper() {
-    local _strace_wrapper=$initdir/$ROOTLIBDIR/systemd-under-strace
-    ddebug "Create $_strace_wrapper"
-    cat >$_strace_wrapper <<EOF
+    local strace_wrapper="$initdir/$ROOTLIBDIR/systemd-under-strace"
+    ddebug "Create $strace_wrapper"
+    cat >"$strace_wrapper" <<EOF
 #!/usr/bin/env bash
 
-exec strace -f -D -o /strace.out $ROOTLIBDIR/systemd "\$@"
+exec strace -f -D -o /strace.out "$ROOTLIBDIR/systemd" "\$@"
 EOF
-    chmod 0755 $_strace_wrapper
+    chmod 0755 "$strace_wrapper"
 }
 
-install_fsck() {
+install_fs_tools() {
+    dinfo "Install fsck"
     dracut_install /sbin/fsck*
     dracut_install -o /bin/fsck*
 
     # fskc.reiserfs calls reiserfsck. so, install it
     dracut_install -o reiserfsck
+
+    # we use mkfs in system-repart tests
+    dracut_install /sbin/mkfs.ext4
+    dracut_install /sbin/mkfs.vfat
+}
+
+install_modules() {
+    dinfo "Install modules"
+
+    instmods loop
+    instmods vfat
+
+    if [[ "$LOOKS_LIKE_SUSE" ]]; then
+        instmods ext4
+    fi
 }
 
 install_dmevent() {
@@ -806,34 +886,35 @@ install_dmevent() {
 }
 
 install_compiled_systemd() {
-    ddebug "Install compiled systemd"
+    dinfo "Install compiled systemd"
 
-    local _ninja_bin=$(type -P ninja || type -P ninja-build)
-    if [[ -z "$_ninja_bin" ]]; then
+    local ninja_bin
+    ninja_bin="$(type -P ninja || type -P ninja-build)"
+    if [[ -z "$ninja_bin" ]]; then
         dfatal "ninja was not found"
         exit 1
     fi
-    (set -x; DESTDIR=$initdir "$_ninja_bin" -C $BUILD_DIR install)
+    (set -x; DESTDIR="$initdir" "$ninja_bin" -C "$BUILD_DIR" install)
 }
 
 install_debian_systemd() {
-    ddebug "Install debian systemd"
+    dinfo "Install debian systemd"
+
+    local files
 
-    local _systemd_pkgs=$(grep -E '^Package:' ${SOURCE_DIR}/debian/control | cut -d ':' -f 2)
-    local _files=""
-    for deb in $_systemd_pkgs; do
-        _files=$(dpkg-query -L $deb 2>/dev/null) || continue
+    while read -r deb; do
+        files="$(dpkg-query -L "$deb" 2>/dev/null)" || continue
         ddebug "Install debian files from package $deb"
-        for file in $_files; do
+        for file in $files; do
             [ -e "$file" ] || continue
             [ -d "$file" ] && continue
-            inst $file
+            inst "$file"
         done
-    done
+    done < <(grep -E '^Package:' "${SOURCE_DIR}/debian/control" | cut -d ':' -f 2)
 }
 
 install_distro_systemd() {
-    ddebug "Install distro systemd"
+    dinfo "Install distro systemd"
 
     if [ "$LOOKS_LIKE_DEBIAN" ]; then
         install_debian_systemd
@@ -844,6 +925,7 @@ install_distro_systemd() {
 }
 
 install_systemd() {
+    dinfo "Install systemd"
     if [ "$NO_BUILD" ]; then
         install_distro_systemd
     else
@@ -851,39 +933,41 @@ install_systemd() {
     fi
 
     # remove unneeded documentation
-    rm -fr $initdir/usr/share/{man,doc}
+    rm -fr "$initdir"/usr/share/{man,doc}
 
     [[ "$LOOKS_LIKE_SUSE" ]] && setup_suse
 
     # enable debug logging in PID1
-    echo LogLevel=debug >> $initdir/etc/systemd/system.conf
+    echo LogLevel=debug >>"$initdir/etc/systemd/system.conf"
     # store coredumps in journal
-    echo Storage=journal >> $initdir/etc/systemd/coredump.conf
+    echo Storage=journal >>"$initdir/etc/systemd/coredump.conf"
 }
 
 get_ldpath() {
-    local _bin="$1"
-    local rpath=$(objdump -p "$_bin" 2>/dev/null | awk "/R(UN)?PATH/ { print \"$initdir\" \$2 }" | paste -sd :)
+    local rpath
+    rpath="$(objdump -p "${1:?}" 2>/dev/null | awk "/R(UN)?PATH/ { print \"$initdir\" \$2 }" | paste -sd :)"
 
     if [ -z "$rpath" ] ; then
-        echo $BUILD_DIR
+        echo "$BUILD_DIR"
     else
-        echo $rpath
+        echo "$rpath"
     fi
 }
 
 install_missing_libraries() {
+    dinfo "Install missing libraries"
     # install possible missing libraries
-    for i in $initdir{,/usr}/{sbin,bin}/* $initdir{,/usr}/lib/systemd/{,tests/{,manual/,unsafe/}}*; do
-        LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$(get_ldpath $i)" inst_libs $i
+    for i in "${initdir:?}"{,/usr}/{sbin,bin}/* "$initdir"{,/usr}/lib/systemd/{,tests/{,manual/,unsafe/}}*; do
+        LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$(get_ldpath "$i")" inst_libs "$i"
     done
 
+    local lib path
     # A number of dependencies is now optional via dlopen, so the install
     # script will not pick them up, since it looks at linkage.
     for lib in libcryptsetup libidn libidn2 pwquality libqrencode tss2-esys tss2-rc tss2-mu libfido2; do
         ddebug "Searching for $lib via pkg-config"
-        if pkg-config --exists ${lib}; then
-                path=$(pkg-config --variable=libdir ${lib})
+        if pkg-config --exists "$lib"; then
+                path="$(pkg-config --variable=libdir "$lib")"
                 if [ -z "${path}" ]; then
                     ddebug "$lib.pc does not contain a libdir variable, skipping"
                     continue
@@ -904,7 +988,7 @@ install_missing_libraries() {
 }
 
 cleanup_loopdev() {
-    if [ -n "${LOOPDEV}" ]; then
+    if [ -n "${LOOPDEV:=}" ]; then
         ddebug "losetup -d $LOOPDEV"
         losetup -d "${LOOPDEV}"
         unset LOOPDEV
@@ -914,66 +998,71 @@ cleanup_loopdev() {
 trap cleanup_loopdev EXIT INT QUIT PIPE
 
 create_empty_image() {
-    if [ -z "$IMAGE_NAME" ]; then
+    if [ -z "${IMAGE_NAME:=}" ]; then
         echo "create_empty_image: \$IMAGE_NAME not set"
         exit 1
     fi
 
-    local _size=500
+    local size=500
+    if meson configure "${BUILD_DIR:?}" | grep 'static-lib\|standalone-binaries' | awk '{ print $2 }' | grep -q 'true'; then
+        size=$((size+=200))
+    fi
+    if meson configure "${BUILD_DIR:?}" | grep 'link-.*-shared' | awk '{ print $2 }' | grep -q 'false'; then
+        size=$((size+=200))
+    fi
     if [[ "$STRIP_BINARIES" = "no" ]]; then
-        _size=$((4*_size))
+        size=$((4 * size))
     fi
 
-    echo "Setting up $IMAGE_PUBLIC (${_size} MB)"
-    rm -f "$IMAGE_PRIVATE" "$IMAGE_PUBLIC"
+    echo "Setting up ${IMAGE_PUBLIC:?} (${size} MB)"
+    rm -f "${IMAGE_PRIVATE:?}" "$IMAGE_PUBLIC"
 
     # Create the blank file to use as a root filesystem
-    truncate -s "${_size}M" "$IMAGE_PUBLIC"
+    truncate -s "${size}M" "$IMAGE_PUBLIC"
 
     LOOPDEV=$(losetup --show -P -f "$IMAGE_PUBLIC")
     [ -b "$LOOPDEV" ] || return 1
     sfdisk "$LOOPDEV" <<EOF
-,$((_size-50))M
+,$((size - 50))M
 ,
 EOF
 
     udevadm settle
 
-    local _label="-L systemd.${name}"
+    local label=(-L systemd)
     # mkfs.reiserfs doesn't know -L. so, use --label instead
-    [[ "$FSTYPE" == "reiserfs" ]] && _label="--label systemd.${name}"
-    mkfs -t "${FSTYPE}" ${_label} "${LOOPDEV}p1" -q; ret=$?
-    if [ $ret -ne 0 ] ; then
+    [[ "$FSTYPE" == "reiserfs" ]] && label=(--label systemd)
+    if ! mkfs -t "${FSTYPE}" "${label[@]}" "${LOOPDEV}p1" -q; then
         dfatal "Failed to mkfs -t ${FSTYPE}"
         exit 1
     fi
 }
 
 mount_initdir() {
-    if [ -z "${LOOPDEV}" ]; then
-        [ -e "$IMAGE_PRIVATE" ] && image="$IMAGE_PRIVATE" || image="$IMAGE_PUBLIC"
-        LOOPDEV=$(losetup --show -P -f "$image")
+    if [ -z "${LOOPDEV:=}" ]; then
+        [ -e "${IMAGE_PRIVATE:?}" ] && image="$IMAGE_PRIVATE" || image="${IMAGE_PUBLIC:?}"
+        LOOPDEV="$(losetup --show -P -f "$image")"
         [ -b "$LOOPDEV" ] || return 1
 
         udevadm settle
     fi
 
-    if ! mountpoint -q $initdir; then
-        mkdir -p $initdir
-        mount ${LOOPDEV}p1 $initdir
+    if ! mountpoint -q "${initdir:?}"; then
+        mkdir -p "$initdir"
+        mount "${LOOPDEV}p1" "$initdir"
         TEST_SETUP_CLEANUP_ROOTDIR=1
     fi
 }
 
 cleanup_initdir() {
     # only umount if create_empty_image_rootdir() was called to mount it
-    [[ -z $TEST_SETUP_CLEANUP_ROOTDIR ]] || _umount_dir $initdir
+    [[ -z $TEST_SETUP_CLEANUP_ROOTDIR ]] || _umount_dir "${initdir:?}"
 }
 
 umount_loopback() {
     # unmount the loopback device from all places. Otherwise we risk file
     # system corruption.
-    for device in $(losetup -l | awk '$6=="'"$IMAGE_PUBLIC"'" {print $1}'); do
+    for device in $(losetup -l | awk '$6=="'"${IMAGE_PUBLIC:?}"'" {print $1}'); do
         ddebug "Unmounting all uses of $device"
         mount | awk '/^'"${device}"'p/{print $1}' | xargs --no-run-if-empty umount -v
     done
@@ -986,23 +1075,23 @@ create_empty_image_rootdir() {
 
 check_asan_reports() {
     local ret=0
-    local root="$1"
+    local root="${1:?}"
 
     if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
         ls -l "$root"
         if [[ -e "$root/systemd.asan.log.1" ]]; then
             cat "$root/systemd.asan.log.1"
-            ret=$(($ret+1))
+            ret=$((ret+1))
         fi
 
-        journald_report=$(find "$root" -name "systemd-journald.*san.log*" -exec cat {} \;)
-        if [[ ! -z "$journald_report" ]]; then
+        journald_report="$(find "$root" -name "systemd-journald.*san.log*" -exec cat {} \;)"
+        if [[ -n "$journald_report" ]]; then
             printf "%s\n" "$journald_report"
             cat "$root/systemd-journald.out" || :
-            ret=$(($ret+1))
+            ret=$((ret+1))
         fi
 
-        pids=$(
+        pids="$(
             "$JOURNALCTL" -D "$root/var/log/journal" | perl -alne '
                  BEGIN {
                      %services_to_ignore = (
@@ -1010,11 +1099,11 @@ check_asan_reports() {
                      );
                  }
                  print $2 if /\s(\S*)\[(\d+)\]:\s*SUMMARY:\s+\w+Sanitizer/ && !exists $services_to_ignore{$1}'
-        )
-        if [[ ! -z "$pids" ]]; then
-            ret=$(($ret+1))
+        )"
+        if [[ -n "$pids" ]]; then
+            ret=$((ret+1))
             for pid in $pids; do
-                "$JOURNALCTL" -D "$root/var/log/journal" _PID=$pid --no-pager
+                "$JOURNALCTL" -D "$root/var/log/journal" _PID="$pid" --no-pager
             done
         fi
     fi
@@ -1024,145 +1113,202 @@ check_asan_reports() {
 
 save_journal() {
     if [ -n "${ARTIFACT_DIRECTORY}" ]; then
-        dest="${ARTIFACT_DIRECTORY}/${testname}.journal"
+        dest="${ARTIFACT_DIRECTORY}/${testname:?}.journal"
     else
-        dest="$TESTDIR/system.journal"
+        dest="${TESTDIR:?}/system.journal"
     fi
 
-    for j in $1/*; do
-        $SYSTEMD_JOURNAL_REMOTE \
-            -o $dest \
+    for j in "${1:?}"/*; do
+        "$SYSTEMD_JOURNAL_REMOTE" \
+            -o "$dest" \
             --getter="$JOURNALCTL -o export -D $j"
 
         if [ -n "${TEST_SHOW_JOURNAL}" ]; then
             echo "---- $j ----"
-            $JOURNALCTL --no-pager -o short-monotonic --no-hostname --priority=${TEST_SHOW_JOURNAL} -D $j
+            "$JOURNALCTL" --no-pager -o short-monotonic --no-hostname --priority="${TEST_SHOW_JOURNAL}" -D "$j"
         fi
 
-        rm -r $j
+        rm -r "$j"
     done
 
+    if [ -n "${SUDO_USER}" ]; then
+        setfacl -m "user:${SUDO_USER:?}:r-X" "$dest"*
+    fi
+
     # we want to print this sometime later, so save this in a variable
-    JOURNAL_LIST="$(ls -l $dest*)"
+    JOURNAL_LIST="$(ls -l "$dest"*)"
+}
+
+check_result_common() {
+    local workspace="${1:?}"
+    local ret
+
+    if [ -s "$workspace/failed" ]; then
+        # Non-empty …/failed has highest priority
+        cp -a "$workspace/failed" "${TESTDIR:?}/"
+        if [ -n "${SUDO_USER}" ]; then
+            setfacl -m "user:${SUDO_USER:?}:r-X" "${TESTDIR:?}/"failed
+        fi
+        ret=1
+    elif [ -e "$workspace/testok" ]; then
+        # …/testok always counts (but with lower priority than …/failed)
+        ret=0
+    elif [ -e "$workspace/skipped" ]; then
+        # …/skipped always counts (a message is expected)
+        echo "${TESTNAME:?} was skipped:"
+        cat "$workspace/skipped"
+        ret=0
+    elif [ -n "$TIMED_OUT" ]; then
+        echo "(timeout)" >"${TESTDIR:?}/failed"
+        ret=2
+    else
+        echo "(failed; see logs)" >"${TESTDIR:?}/failed"
+        ret=3
+    fi
+
+    save_journal "$workspace/var/log/journal"
+
+    check_asan_reports "$workspace" || ret=4
+
+    if [ -d "${ARTIFACT_DIRECTORY}" ] && [ -f "$workspace/strace.out" ]; then
+        cp "$workspace/strace.out" "${ARTIFACT_DIRECTORY}/"
+    fi
+
+    if [ ${ret:?} != 0 ] && [ -f "$TESTDIR/failed" ]; then
+        echo -n "${TESTNAME:?}: "
+        cat "$TESTDIR/failed"
+    fi
+    echo "${JOURNAL_LIST:-"No journals were saved"}"
+
+    return ${ret:?}
 }
 
 check_result_nspawn() {
-    local ret=1
-    local journald_report=""
-    local pids=""
-    [[ -e $1/testok ]] && ret=0
-    [[ -f $1/failed ]] && cp -a $1/failed $TESTDIR
-    save_journal $1/var/log/journal
-    [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
-    echo $JOURNAL_LIST
-    test -s $TESTDIR/failed && ret=$(($ret+1))
-    [ -n "$TIMED_OUT" ] && ret=$(($ret+1))
-    check_asan_reports "$1" || ret=$(($ret+1))
-    if [ -d "${ARTIFACT_DIRECTORY}" ] && [ -f $1/strace.out ]; then
-        cp $1/strace.out "${ARTIFACT_DIRECTORY}/"
-    fi
-    _umount_dir $initdir
+    local workspace="${1:?}"
+    local ret
+
+    check_result_common "${workspace}"
+    ret=$?
+
+    # Run additional test-specific checks if defined by check_result_nspawn_hook()
+    if declare -F check_result_nspawn_hook >/dev/null; then
+        if ! check_result_nspawn_hook; then
+            derror "check_result_nspawn_hook() returned with EC > 0"
+            ret=4
+        fi
+    fi
+
+    _umount_dir "${initdir:?}"
+
     return $ret
 }
 
 # can be overridden in specific test
 check_result_qemu() {
-    local ret=1
+    local ret
     mount_initdir
-    [[ -e $initdir/testok ]] && ret=0
-    [[ -f $initdir/failed ]] && cp -a $initdir/failed $TESTDIR
-    save_journal $initdir/var/log/journal
-    check_asan_reports "$initdir" || ret=$(($ret+1))
-    if [ -d "${ARTIFACT_DIRECTORY}" ] && [ -f $initdir/strace.out ]; then
-        cp $initdir/strace.out "${ARTIFACT_DIRECTORY}/"
-    fi
-    _umount_dir $initdir
-    [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
-    echo $JOURNAL_LIST
-    test -s $TESTDIR/failed && ret=$(($ret+1))
-    [ -n "$TIMED_OUT" ] && ret=$(($ret+1))
+
+    check_result_common "${initdir:?}"
+    ret=$?
+
+    _umount_dir "${initdir:?}"
+
+    # Run additional test-specific checks if defined by check_result_qemu_hook()
+    if declare -F check_result_qemu_hook >/dev/null; then
+        if ! check_result_qemu_hook; then
+            derror "check_result_qemu_hook() returned with EC > 0"
+            ret=4
+        fi
+    fi
+
     return $ret
 }
 
 strip_binaries() {
+    dinfo "Strip binaries"
     if [[ "$STRIP_BINARIES" = "no" ]]; then
-        ddebug "Don't strip binaries"
+        dinfo "STRIP_BINARIES == no, keeping binaries unstripped"
         return 0
     fi
-    ddebug "Strip binaries"
-    find "$initdir" -executable -not -path '*/lib/modules/*.ko' -type f | \
-        xargs strip --strip-unneeded |& \
-        grep -vi 'file format not recognized' | \
-        ddebug
+    while read -r bin; do
+        strip --strip-unneeded "$bin" |& grep -vi 'file format not recognized' | ddebug || :
+    done < <(find "${initdir:?}" -executable -not -path '*/lib/modules/*.ko' -type f)
 }
 
 create_rc_local() {
-    mkdir -p $initdir/etc/rc.d
-    cat >$initdir/etc/rc.d/rc.local <<EOF
+    dinfo "Create rc.local"
+    mkdir -p "${initdir:?}/etc/rc.d"
+    cat >"$initdir/etc/rc.d/rc.local" <<EOF
 #!/usr/bin/env bash
 exit 0
 EOF
-    chmod 0755 $initdir/etc/rc.d/rc.local
+    chmod 0755 "$initdir/etc/rc.d/rc.local"
 }
 
 install_execs() {
-    ddebug "install any Execs from the service files"
-    (
-    export PKG_CONFIG_PATH=$BUILD_DIR/src/core/
-    systemdsystemunitdir=$(pkg-config --variable=systemdsystemunitdir systemd)
-    systemduserunitdir=$(pkg-config --variable=systemduserunitdir systemd)
-    sed -r -n 's|^Exec[a-zA-Z]*=[@+!-]*([^ ]+).*|\1|gp' $initdir/{$systemdsystemunitdir,$systemduserunitdir}/*.service \
-         | sort -u | while read i; do
-         # some {rc,halt}.local scripts and programs are okay to not exist, the rest should
-         # also, plymouth is pulled in by rescue.service, but even there the exit code
-         # is ignored; as it's not present on some distros, don't fail if it doesn't exist
-         dinfo "Attempting to install $i (based on unit file reference)"
-         inst $i || [ "${i%.local}" != "$i" ] || [ "${i%systemd-update-done}" != "$i" ] || [ "${i##*/}" == "plymouth" ]
-     done
-    )
+    ddebug "Install executables from the service files"
+
+    local pkg_config_path="${BUILD_DIR:?}/src/core/"
+    local systemunitdir userunitdir exe
+    systemunitdir="$(PKG_CONFIG_PATH="$pkg_config_path" pkg-config --variable=systemdsystemunitdir systemd)"
+    userunitdir="$(PKG_CONFIG_PATH="$pkg_config_path" pkg-config --variable=systemduserunitdir systemd)"
+    while read -r exe; do
+        # some {rc,halt}.local scripts and programs are okay to not exist, the rest should
+        # also, plymouth is pulled in by rescue.service, but even there the exit code
+        # is ignored; as it's not present on some distros, don't fail if it doesn't exist
+        dinfo "Attempting to install $exe (based on unit file reference)"
+        inst "$exe" || [ "${exe%.local}" != "$exe" ] || [ "${exe%systemd-update-done}" != "$exe" ] || [ "${exe##*/}" == "plymouth" ]
+    done < <(sed -r -n 's|^Exec[a-zA-Z]*=[@+!-]*([^ ]+).*|\1|gp' "${initdir:?}"/{"$systemunitdir","$userunitdir"}/*.service | sort -u)
 }
 
 generate_module_dependencies() {
-    if [[ -d $initdir/lib/modules/$KERNEL_VER ]] && \
-        ! depmod -a -b "$initdir" $KERNEL_VER; then
+    dinfo "Generate modules dependencies"
+    if [[ -d "${initdir:?}/lib/modules/${KERNEL_VER:?}" ]] && \
+        ! depmod -a -b "$initdir" "$KERNEL_VER"; then
             dfatal "\"depmod -a $KERNEL_VER\" failed."
             exit 1
     fi
 }
 
 install_depmod_files() {
-    inst /lib/modules/$KERNEL_VER/modules.order
-    inst /lib/modules/$KERNEL_VER/modules.builtin
+    dinfo "Install depmod files"
+    inst "/lib/modules/${KERNEL_VER:?}/modules.order"
+    inst "/lib/modules/$KERNEL_VER/modules.builtin"
 }
 
 install_plymouth() {
+    dinfo "Install plymouth"
     # install plymouth, if found... else remove plymouth service files
     # if [ -x /usr/libexec/plymouth/plymouth-populate-initrd ]; then
     #     PLYMOUTH_POPULATE_SOURCE_FUNCTIONS="$TEST_BASE_DIR/test-functions" \
     #         /usr/libexec/plymouth/plymouth-populate-initrd -t $initdir
     #         dracut_install plymouth plymouthd
     # else
-        rm -f $initdir/{usr/lib,lib,etc}/systemd/system/plymouth* $initdir/{usr/lib,lib,etc}/systemd/system/*/plymouth*
+        rm -f "${initdir:?}"/{usr/lib,lib,etc}/systemd/system/plymouth* "$initdir"/{usr/lib,lib,etc}/systemd/system/*/plymouth*
     # fi
 }
 
 install_ld_so_conf() {
-    cp -a /etc/ld.so.conf* $initdir/etc
+    dinfo "Install /etc/ld.so.conf*"
+    cp -a /etc/ld.so.conf* "${initdir:?}/etc"
     ldconfig -r "$initdir"
 }
 
 install_testuser() {
+    dinfo "Set up a test user"
     # create unprivileged user for user manager tests
-    mkdir -p $initdir/etc/sysusers.d
-    cat >$initdir/etc/sysusers.d/testuser.conf <<EOF
+    mkdir -p "${initdir:?}/etc/sysusers.d"
+    cat >"$initdir/etc/sysusers.d/testuser.conf" <<EOF
 u testuser    4711     "Test User" /home/testuser
 EOF
 
-    mkdir -p $initdir/home/testuser -m 0700
-    chown 4711:4711 $initdir/home/testuser
+    mkdir -p "$initdir/home/testuser"
+    chmod 0700 "$initdir/home/testuser"
+    chown 4711:4711 "$initdir/home/testuser"
 }
 
 install_config_files() {
+    dinfo "Install config files"
     inst /etc/sysconfig/init || :
     inst /etc/passwd
     inst /etc/shadow
@@ -1174,21 +1320,22 @@ install_config_files() {
     inst_any /etc/os-release /usr/lib/os-release
     inst /etc/localtime
     # we want an empty environment
-    > $initdir/etc/environment
-    > $initdir/etc/machine-id
-    > $initdir/etc/resolv.conf
+    : >"${initdir:?}/etc/environment"
+    : >"$initdir/etc/machine-id"
+    : >"$initdir/etc/resolv.conf"
 
     # set the hostname
-    echo systemd-testsuite > $initdir/etc/hostname
+    echo 'H' >"$initdir/etc/hostname"
 
     # let's set up just one image with the traditional verbose output
-    if [ ${IMAGE_NAME} != "basic" ]; then
-        mkdir -p $initdir/etc/systemd/system.conf.d
-        echo -e '[Manager]\nStatusUnitFormat=name' >$initdir/etc/systemd/system.conf.d/status.conf
+    if [ "${IMAGE_NAME:?}" != "basic" ]; then
+        mkdir -p "$initdir/etc/systemd/system.conf.d"
+        echo -e '[Manager]\nStatusUnitFormat=name' >"$initdir/etc/systemd/system.conf.d/status.conf"
     fi
 }
 
 install_basic_tools() {
+    dinfo "Install basic tools"
     dracut_install "${BASICTOOLS[@]}"
     dracut_install -o sushell
     # in Debian ldconfig is just a shell script wrapper around ldconfig.real
@@ -1196,15 +1343,16 @@ install_basic_tools() {
 }
 
 install_debug_tools() {
+    dinfo "Install debug tools"
     dracut_install "${DEBUGTOOLS[@]}"
 
     if [[ $INTERACTIVE_DEBUG ]]; then
         # Set default TERM from vt220 to linux, so at least basic key shortcuts work
-        local _getty_override="$initdir/etc/systemd/system/serial-getty@.service.d"
-        mkdir -p "$_getty_override"
-        echo -e "[Service]\nEnvironment=TERM=linux" > "$_getty_override/default-TERM.conf"
+        local getty_override="${initdir:?}/etc/systemd/system/serial-getty@.service.d"
+        mkdir -p "$getty_override"
+        echo -e "[Service]\nEnvironment=TERM=linux" >"$getty_override/default-TERM.conf"
 
-        cat > "$initdir/etc/motd" << EOF
+        cat >"$initdir/etc/motd" <<EOF
 To adjust the terminal size use:
     export COLUMNS=xx
     export LINES=yy
@@ -1215,38 +1363,39 @@ EOF
 }
 
 install_libnss() {
+    dinfo "Install libnss"
     # install libnss_files for login
-    NSS_LIBS=$(LD_DEBUG=files getent passwd 2>&1 >/dev/null |sed -n '/calling init: .*libnss_/ {s!^.* /!/!; p}')
-    dracut_install $NSS_LIBS
+    local NSS_LIBS
+    mapfile -t NSS_LIBS < <(LD_DEBUG=files getent passwd 2>&1 >/dev/null | sed -n '/calling init: .*libnss_/ {s!^.* /!/!; p}')
+    dracut_install "${NSS_LIBS[@]}"
 }
 
 install_dbus() {
-    inst $ROOTLIBDIR/system/dbus.socket
+    dinfo "Install dbus"
+    inst "${ROOTLIBDIR:?}/system/dbus.socket"
 
     # Newer Fedora versions use dbus-broker by default. Let's install it if it's available.
-    if [ -f $ROOTLIBDIR/system/dbus-broker.service ]; then
-        inst $ROOTLIBDIR/system/dbus-broker.service
+    if [ -f "$ROOTLIBDIR/system/dbus-broker.service" ]; then
+        inst "$ROOTLIBDIR/system/dbus-broker.service"
         inst_symlink /etc/systemd/system/dbus.service
         inst /usr/bin/dbus-broker
         inst /usr/bin/dbus-broker-launch
-    elif [ -f $ROOTLIBDIR/system/dbus-daemon.service ]; then
+    elif [ -f "$ROOTLIBDIR/system/dbus-daemon.service" ]; then
         # Fedora rawhide replaced dbus.service with dbus-daemon.service
-        inst $ROOTLIBDIR/system/dbus-daemon.service
+        inst "$ROOTLIBDIR/system/dbus-daemon.service"
         # Alias symlink
         inst_symlink /etc/systemd/system/dbus.service
     else
-        inst $ROOTLIBDIR/system/dbus.service
+        inst "$ROOTLIBDIR/system/dbus.service"
     fi
 
-    find \
-        /etc/dbus-1 /usr/share/dbus-1 -xtype f \
-        | while read file; do
-        inst $file
-    done
+    while read -r file; do
+        inst "$file"
+    done < <(find /etc/dbus-1 /usr/share/dbus-1 -xtype f 2>/dev/null)
 
     # setup policy for Type=dbus test
-    mkdir -p $initdir/etc/dbus-1/system.d
-    cat > $initdir/etc/dbus-1/system.d/systemd.test.ExecStopPost.conf <<EOF
+    mkdir -p "${initdir:?}/etc/dbus-1/system.d"
+    cat >"$initdir/etc/dbus-1/system.d/systemd.test.ExecStopPost.conf" <<EOF
 <?xml version="1.0"?>
 <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
         "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
@@ -1259,59 +1408,65 @@ EOF
 }
 
 install_user_dbus() {
+    dinfo "Install user dbus"
     local userunitdir
-    if ! userunitdir=$(pkg-config --variable=systemduserunitdir systemd); then
-        echo "WARNING! Cannot determine userunitdir from pkg-config, assuming /usr/lib/systemd/user" >&2
-        local userunitdir=/usr/lib/systemd/user
+    if ! userunitdir="$(pkg-config --variable=systemduserunitdir systemd)"; then
+        dwarn "WARNING! Cannot determine userunitdir from pkg-config, assuming /usr/lib/systemd/user"
+        userunitdir=/usr/lib/systemd/user
     fi
 
-    inst $userunitdir/dbus.socket
-    inst_symlink $userunitdir/sockets.target.wants/dbus.socket || inst_symlink /etc/systemd/user/sockets.target.wants/dbus.socket
+    inst "$userunitdir/dbus.socket"
+    inst_symlink "$userunitdir/sockets.target.wants/dbus.socket" || inst_symlink /etc/systemd/user/sockets.target.wants/dbus.socket
 
     # Append the After= dependency on dbus in case it isn't already set up
-    mkdir -p "$initdir/etc/systemd/system/user@.service.d/"
-    cat <<EOF >"$initdir/etc/systemd/system/user@.service.d/dbus.conf"
+    mkdir -p "${initdir:?}/etc/systemd/system/user@.service.d/"
+    cat >"$initdir/etc/systemd/system/user@.service.d/dbus.conf" <<EOF
 [Unit]
 After=dbus.service
 EOF
 
     # Newer Fedora versions use dbus-broker by default. Let's install it if it's available.
-    if [ -f $userunitdir/dbus-broker.service ]; then
-        inst $userunitdir/dbus-broker.service
+    if [ -f "$userunitdir/dbus-broker.service" ]; then
+        inst "$userunitdir/dbus-broker.service"
         inst_symlink /etc/systemd/user/dbus.service
-    elif [ -f $ROOTLIBDIR/system/dbus-daemon.service ]; then
+    elif [ -f "${ROOTLIBDIR:?}/system/dbus-daemon.service" ]; then
         # Fedora rawhide replaced dbus.service with dbus-daemon.service
-        inst $userunitdir/dbus-daemon.service
+        inst "$userunitdir/dbus-daemon.service"
         # Alias symlink
         inst_symlink /etc/systemd/user/dbus.service
     else
-        inst $userunitdir/dbus.service
+        inst "$userunitdir/dbus.service"
     fi
 }
 
 install_pam() {
-    (
+    dinfo "Install PAM"
+    local paths=()
+
     if [[ "$LOOKS_LIKE_DEBIAN" ]] && type -p dpkg-architecture &>/dev/null; then
-        find "/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/security" -xtype f
+        paths+=("/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/security")
     else
-        find /lib*/security -xtype f
+        paths+=(/lib*/security)
     fi
+
     for d in /etc/pam.d /etc/security /usr/lib/pam.d; do
-        [ -d "$d" ] && find $d -xtype f
-    done
-    ) | while read file; do
-        inst $file
+        [ -d "$d" ] && paths+=("$d")
     done
 
+    while read -r file; do
+        inst "$file"
+    done < <(find "${paths[@]}" -xtype f)
+
     # pam_unix depends on unix_chkpwd.
     # see http://www.linux-pam.org/Linux-PAM-html/sag-pam_unix.html
     dracut_install -o unix_chkpwd
 
     # set empty root password for easy debugging
-    sed -i 's/^root:x:/root::/' $initdir/etc/passwd
+    sed -i 's/^root:x:/root::/' "${initdir:?}/etc/passwd"
 }
 
 install_keymaps() {
+    dinfo "Install keymaps"
     # The first three paths may be deprecated.
     # It seems now the last two paths are used by many distributions.
     for i in \
@@ -1320,22 +1475,23 @@ install_keymaps() {
         /usr/lib/kbd/keymaps/i386/qwerty/us.* \
         /usr/lib/kbd/keymaps/legacy/include/* \
         /usr/lib/kbd/keymaps/legacy/i386/qwerty/us.*; do
-            [[ -f $i ]] || continue
-            inst $i
+            [[ -f "$i" ]] || continue
+            inst "$i"
     done
 
     # When it takes any argument, then install more keymaps.
-    if [[ -n $1 ]]; then
+    if [[ $# -gt 1 ]]; then
         for i in \
         /usr/lib/kbd/keymaps/i386/*/* \
         /usr/lib/kbd/keymaps/legacy/i386/*/*; do
-            [[ -f $i ]] || continue
-            inst $i
+            [[ -f "$i" ]] || continue
+            inst "$i"
         done
     fi
 }
 
 install_zoneinfo() {
+    dinfo "Install time zones"
     inst_any /usr/share/zoneinfo/Asia/Seoul
     inst_any /usr/share/zoneinfo/Asia/Vladivostok
     inst_any /usr/share/zoneinfo/Australia/Sydney
@@ -1350,19 +1506,22 @@ install_zoneinfo() {
 }
 
 install_fonts() {
+    dinfo "Install system fonts"
     for i in \
         /usr/lib/kbd/consolefonts/eurlatgr* \
         /usr/lib/kbd/consolefonts/latarcyrheb-sun16*; do
-            [[ -f $i ]] || continue
-            inst $i
+            [[ -f "$i" ]] || continue
+            inst "$i"
     done
 }
 
 install_terminfo() {
-    for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do
-        [ -f ${_terminfodir}/l/linux ] && break
+    dinfo "Install terminfo files"
+    local terminfodir
+    for terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do
+        [ -f "${terminfodir}/l/linux" ] && break
     done
-    dracut_install -o ${_terminfodir}/l/linux
+    dracut_install -o "${terminfodir}/l/linux"
 }
 
 has_user_dbus_socket() {
@@ -1380,20 +1539,21 @@ setup_nspawn_root() {
         exit 1
     fi
 
-    rm -rf "$TESTDIR/unprivileged-nspawn-root"
+    rm -rf "${TESTDIR:?}/unprivileged-nspawn-root"
 
     if [[ "$RUN_IN_UNPRIVILEGED_CONTAINER" = "yes" ]]; then
         ddebug "cp -ar $initdir $TESTDIR/unprivileged-nspawn-root"
-        cp -ar $initdir $TESTDIR/unprivileged-nspawn-root
+        cp -ar "$initdir" "$TESTDIR/unprivileged-nspawn-root"
     fi
 }
 
 setup_basic_dirs() {
-    mkdir -p $initdir/run
-    mkdir -p $initdir/etc/systemd/system
-    mkdir -p $initdir/var/log/journal
+    mkdir -p "${initdir:?}/run"
+    mkdir -p "$initdir/etc/systemd/system"
+    mkdir -p "$initdir/var/log/journal"
+
 
-    for d in usr/bin usr/sbin bin etc lib "$libdir" sbin tmp usr var var/log var/tmp dev proc sys sysroot root run run/lock run/initramfs; do
+    for d in usr/bin usr/sbin bin etc lib "${libdir:?}" sbin tmp usr var var/log var/tmp dev proc sys sysroot root run run/lock run/initramfs; do
         if [ -L "/$d" ]; then
             inst_symlink "/$d"
         else
@@ -1407,63 +1567,65 @@ setup_basic_dirs() {
 
 mask_supporting_services() {
     # mask some services that we do not want to run in these tests
-    ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
-    ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
-    ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service
-    ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
-    ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service
+    ln -fsv /dev/null "${initdir:?}/etc/systemd/system/systemd-hwdb-update.service"
+    ln -fsv /dev/null "$initdir/etc/systemd/system/systemd-journal-catalog-update.service"
+    ln -fsv /dev/null "$initdir/etc/systemd/system/systemd-networkd.service"
+    ln -fsv /dev/null "$initdir/etc/systemd/system/systemd-networkd.socket"
+    ln -fsv /dev/null "$initdir/etc/systemd/system/systemd-resolved.service"
 }
 
 inst_libs() {
-    local _bin=$1
-    local _so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
-    local _file _line
+    local bin="${1:?}"
+    local so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
+    local file line
 
-    LC_ALL=C ldd "$_bin" 2>/dev/null | while read _line; do
-        [[ $_line = 'not a dynamic executable' ]] && break
+    while read -r line; do
+        [[ "$line" = 'not a dynamic executable' ]] && break
 
-        if [[ $_line =~ $_so_regex ]]; then
-            _file=${BASH_REMATCH[1]}
-            [[ -e ${initdir}/$_file ]] && continue
-            inst_library "$_file"
+        if [[ "$line" =~ $so_regex ]]; then
+            file="${BASH_REMATCH[1]}"
+            [[ -e "${initdir:?}/$file" ]] && continue
+            inst_library "$file"
             continue
         fi
 
-        if [[ $_line =~ not\ found ]]; then
-            dfatal "Missing a shared library required by $_bin."
-            dfatal "Run \"ldd $_bin\" to find out what it is."
-            dfatal "$_line"
+        if [[ "$line" =~ not\ found ]]; then
+            dfatal "Missing a shared library required by $bin."
+            dfatal "Run \"ldd $bin\" to find out what it is."
+            dfatal "$line"
             dfatal "dracut cannot create an initrd."
             exit 1
         fi
-    done
+    done < <(LC_ALL=C ldd "$bin" 2>/dev/null)
 }
 
 import_testdir() {
     # make sure we don't get a stale LOOPDEV value from old times
-    __LOOPDEV=$LOOPDEV
-    [[ -e $STATEFILE ]] && . $STATEFILE
-    LOOPDEV=$__LOOPDEV
+    local _LOOPDEV="${LOOPDEV:=}"
+    # We don't want shellcheck to follow & check the $STATEFILE
+    # shellcheck source=/dev/null
+    [[ -e "$STATEFILE" ]] && . "$STATEFILE"
+    LOOPDEV="$_LOOPDEV"
     if [[ ! -d "$TESTDIR" ]]; then
         if [[ -z "$TESTDIR" ]]; then
-            TESTDIR=$(mktemp --tmpdir=/var/tmp -d -t systemd-test.XXXXXX)
+            TESTDIR="$(mktemp --tmpdir=/var/tmp -d -t systemd-test.XXXXXX)"
         else
             mkdir -p "$TESTDIR"
         fi
 
-        cat >$STATEFILE<<EOF
+        cat >"$STATEFILE" <<EOF
 TESTDIR="$TESTDIR"
 EOF
         export TESTDIR
     fi
 
-    IMAGE_PRIVATE="${TESTDIR}/${IMAGE_NAME}.img"
-    IMAGE_PUBLIC="${IMAGESTATEDIR}/${IMAGE_NAME}.img"
+    IMAGE_PRIVATE="${TESTDIR}/${IMAGE_NAME:?}.img"
+    IMAGE_PUBLIC="${IMAGESTATEDIR:?}/${IMAGE_NAME}.img"
 }
 
 import_initdir() {
-    initdir=$TESTDIR/root
-    mkdir -p $initdir
+    initdir="${TESTDIR:?}/root"
+    mkdir -p "$initdir"
     export initdir
 }
 
@@ -1501,18 +1663,20 @@ _lvl2char() {
 # This enables:
 # dwarn "This is a warning"
 # echo "This is a warning" | dwarn
-LOG_LEVEL=${LOG_LEVEL:-4}
+LOG_LEVEL="${LOG_LEVEL:-4}"
 
 dlog() {
+    local lvl lvlc
+
     [ -z "$LOG_LEVEL" ] && return 0
-    [ $1 -le $LOG_LEVEL ] || return 0
-    local lvl="$1"; shift
-    local lvlc=$(_lvl2char "$lvl") || return 0
+    lvl="${1:?}"; shift
+    [ "$lvl" -le "$LOG_LEVEL" ] || return 0
+    lvlc="$(_lvl2char "$lvl")" || return 0
 
     if [ $# -ge 1 ]; then
         echo "$lvlc: $*"
     else
-        while read line; do
+        while read -r line; do
             echo "$lvlc: " "$line"
         done
     fi
@@ -1525,7 +1689,9 @@ dlog() {
 dtrace() {
     set +x
     dlog 6 "$@"
-    [ -n "$debug" ] && set -x || :
+    if [[ "${debug:=}" ]]; then
+        set -x
+    fi
 }
 
 ## @brief Logs message at DEBUG level (5)
@@ -1533,9 +1699,7 @@ dtrace() {
 # @param msg Message.
 # @retval 0 It's always returned, even if logging failed.
 ddebug() {
-#    set +x
     dlog 5 "$@"
-#    [ -n "$debug" ] && set -x || :
 }
 
 ## @brief Logs message at INFO level (4)
@@ -1545,7 +1709,9 @@ ddebug() {
 dinfo() {
     set +x
     dlog 4 "$@"
-    [ -n "$debug" ] && set -x || :
+    if [[ "${debug:=}" ]]; then
+        set -x
+    fi
 }
 
 ## @brief Logs message at WARN level (3)
@@ -1555,7 +1721,9 @@ dinfo() {
 dwarn() {
     set +x
     dlog 3 "$@"
-    [ -n "$debug" ] && set -x || :
+    if [[ "${debug:=}" ]]; then
+        set -x
+    fi
 }
 
 ## @brief Logs message at ERROR level (2)
@@ -1563,9 +1731,7 @@ dwarn() {
 # @param msg Message.
 # @retval 0 It's always returned, even if logging failed.
 derror() {
-#    set +x
     dlog 2 "$@"
-#    [ -n "$debug" ] && set -x || :
 }
 
 ## @brief Logs message at FATAL level (1)
@@ -1575,7 +1741,9 @@ derror() {
 dfatal() {
     set +x
     dlog 1 "$@"
-    [ -n "$debug" ] && set -x || :
+    if [[ "${debug:=}" ]]; then
+        set -x
+    fi
 }
 
 
@@ -1605,7 +1773,7 @@ convert_abs_rel() {
     local __current __absolute __abssize __cursize __newpath
     local -i __i __level
 
-    set -- "$(normalize_path "$1")" "$(normalize_path "$2")"
+    set -- "$(normalize_path "${1:?}")" "$(normalize_path "${2:?}")"
 
     # corner case #1 - self looping link
     [[ "$1" == "$2" ]] && { echo "${1##*/}"; return; }
@@ -1613,13 +1781,13 @@ convert_abs_rel() {
     # corner case #2 - own dir link
     [[ "${1%/*}" == "$2" ]] && { echo "."; return; }
 
-    IFS="/" __current=($1)
-    IFS="/" __absolute=($2)
+    IFS="/" read -ra __current <<< "$1"
+    IFS="/" read -ra __absolute <<< "$2"
 
     __abssize=${#__absolute[@]}
     __cursize=${#__current[@]}
 
-    while [[ ${__absolute[__level]} == ${__current[__level]} ]]
+    while [[ "${__absolute[__level]}" == "${__current[__level]}" ]]
     do
         (( __level++ ))
         if (( __level > __abssize || __level > __cursize ))
@@ -1655,24 +1823,27 @@ convert_abs_rel() {
 # will create ${initdir}/lib64, ${initdir}/lib64/file,
 # and a symlink ${initdir}/lib -> lib64.
 inst_dir() {
-    [[ -e ${initdir}/"$1" ]] && return 0  # already there
+    local dir="${1:?}"
+    local part="${dir%/*}"
+    local file
 
-    local _dir="$1" _part="${1%/*}" _file
-    while [[ "$_part" != "${_part%/*}" ]] && ! [[ -e "${initdir}/${_part}" ]]; do
-        _dir="$_part $_dir"
-        _part=${_part%/*}
+    [[ -e "${initdir:?}/${dir}" ]] && return 0  # already there
+
+    while [[ "$part" != "${part%/*}" ]] && ! [[ -e "${initdir}/${part}" ]]; do
+        dir="$part $dir"
+        part="${part%/*}"
     done
 
     # iterate over parent directories
-    for _file in $_dir; do
-        [[ -e "${initdir}/$_file" ]] && continue
-        if [[ -L $_file ]]; then
-            inst_symlink "$_file"
+    for file in $dir; do
+        [[ -e "${initdir}/$file" ]] && continue
+        if [[ -L $file ]]; then
+            inst_symlink "$file"
         else
             # create directory
-            mkdir -m 0755 -p "${initdir}/$_file" || return 1
-            [[ -e "$_file" ]] && chmod --reference="$_file" "${initdir}/$_file"
-            chmod u+w "${initdir}/$_file"
+            mkdir -m 0755 "${initdir}/$file" || return 1
+            [[ -e "$file" ]] && chmod --reference="$file" "${initdir}/$file"
+            chmod u+w "${initdir}/$file"
         fi
     done
 }
@@ -1682,21 +1853,22 @@ inst_dir() {
 # Location of the image dir is assumed to be $initdir
 # We never overwrite the target if it exists.
 inst_simple() {
-    [[ -f "$1" ]] || return 1
+    [[ -f "${1:?}" ]] || return 1
     strstr "$1" "/" || return 1
 
-    local _src=$1 target="${2:-$1}"
-    if ! [[ -d ${initdir}/$target ]]; then
+    local src="$1"
+    local target="${2:-$1}"
+    if ! [[ -d ${initdir:?}/$target ]]; then
         [[ -e ${initdir}/$target ]] && return 0
         [[ -L ${initdir}/$target ]] && return 0
         [[ -d "${initdir}/${target%/*}" ]] || inst_dir "${target%/*}"
     fi
     # install checksum files also
-    if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then
-        inst "${_src%/*}/.${_src##*/}.hmac" "${target%/*}/.${target##*/}.hmac"
+    if [[ -e "${src%/*}/.${src##*/}.hmac" ]]; then
+        inst "${src%/*}/.${src##*/}.hmac" "${target%/*}/.${target##*/}.hmac"
     fi
-    ddebug "Installing $_src"
-    cp --sparse=always -pfL "$_src" "${initdir}/$target"
+    ddebug "Installing $src"
+    cp --sparse=always -pfL "$src" "${initdir}/$target"
 }
 
 # find symlinks linked to given library file
@@ -1710,15 +1882,16 @@ inst_simple() {
 # output: libfoo.so.8 libfoo.so
 # (Only if libfoo.so.8 and libfoo.so exists on host system.)
 rev_lib_symlinks() {
-    [[ ! $1 ]] && return 0
-
-    local fn="$1" orig="$(readlink -f "$1")" links=''
+    local fn="${1:?}"
+    local links=""
+    local orig
+    orig="$(readlink -f "$1")"
 
-    [[ ${fn} =~ .*\.so\..* ]] || return 1
+    [[ "${fn}" =~ .*\.so\..* ]] || return 1
 
-    until [[ ${fn##*.} == so ]]; do
+    until [[ "${fn##*.}" == so ]]; do
         fn="${fn%.*}"
-        [[ -L ${fn} && $(readlink -f "${fn}") == ${orig} ]] && links+=" ${fn}"
+        [[ -L "${fn}" && "$(readlink -f "${fn}")" == "${orig}" ]] && links+=" ${fn}"
     done
 
     echo "${links}"
@@ -1728,185 +1901,204 @@ rev_lib_symlinks() {
 # It handles making symlinks according to how the original library
 # is referenced.
 inst_library() {
-    local _src="$1" _dest=${2:-$1} _lib _reallib _symlink
+    local src="${1:?}"
+    local dest="${2:-$1}"
+    local reallib symlink
+
     strstr "$1" "/" || return 1
-    [[ -e $initdir/$_dest ]] && return 0
-    if [[ -L $_src ]]; then
+    [[ -e ${initdir:?}/$dest ]] && return 0
+    if [[ -L $src ]]; then
         # install checksum files also
-        if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then
-            inst "${_src%/*}/.${_src##*/}.hmac" "${_dest%/*}/.${_dest##*/}.hmac"
+        if [[ -e "${src%/*}/.${src##*/}.hmac" ]]; then
+            inst "${src%/*}/.${src##*/}.hmac" "${dest%/*}/.${dest##*/}.hmac"
         fi
-        _reallib=$(readlink -f "$_src")
-        inst_simple "$_reallib" "$_reallib"
-        inst_dir "${_dest%/*}"
-        [[ -d "${_dest%/*}" ]] && _dest=$(readlink -f "${_dest%/*}")/${_dest##*/}
-        ln -sfn $(convert_abs_rel "${_dest}" "${_reallib}") "${initdir}/${_dest}"
+        reallib="$(readlink -f "$src")"
+        inst_simple "$reallib" "$reallib"
+        inst_dir "${dest%/*}"
+        [[ -d "${dest%/*}" ]] && dest="$(readlink -f "${dest%/*}")/${dest##*/}"
+        ln -sfn -- "$(convert_abs_rel "${dest}" "${reallib}")" "${initdir}/${dest}"
     else
-        inst_simple "$_src" "$_dest"
+        inst_simple "$src" "$dest"
     fi
 
     # Create additional symlinks.  See rev_symlinks description.
-    for _symlink in $(rev_lib_symlinks $_src) $(rev_lib_symlinks $_reallib); do
-        [[ -e $initdir/$_symlink ]] || {
-            ddebug "Creating extra symlink: $_symlink"
-            inst_symlink $_symlink
-        }
+    for symlink in $(rev_lib_symlinks "$src") ${reallib:+$(rev_lib_symlinks "$reallib")}; do
+        if [[ ! -e "$initdir/$symlink" ]]; then
+            ddebug "Creating extra symlink: $symlink"
+            inst_symlink "$symlink"
+        fi
     done
 }
 
 # find a binary.  If we were not passed the full path directly,
 # search in the usual places to find the binary.
 find_binary() {
-    if [[ -z ${1##/*} ]]; then
-        if [[ -x $1 ]] || { strstr "$1" ".so" && ldd $1 &>/dev/null; };  then
-            echo $1
+    local bin="${1:?}"
+    if [[ -z ${bin##/*} ]]; then
+        if [[ -x "$bin" ]] || { strstr "$bin" ".so" && ldd "$bin" &>/dev/null; }; then
+            echo "$bin"
             return 0
         fi
     fi
 
-    type -P $1
+    type -P "$bin"
 }
 
 # Same as above, but specialized to install binary executables.
 # Install binary executable, and all shared library dependencies, if any.
 inst_binary() {
-    local _bin _target
+    local bin="${1:?}"
+    local path target
 
     # In certain cases we might attempt to install a binary which is already
     # present in the test image, yet it's missing from the host system.
     # In such cases, let's check if the binary indeed exists in the image
     # before doing any other chcecks. If it does, immediately return with
     # success.
-    [[ $# -eq 1 && -e $initdir/$1 || -e $initdir/bin/$1 || -e $initdir/sbin/$1 || -e $initdir/usr/bin/$1 || -e $initdir/usr/sbin/$1 ]] && return 0
-
-    _bin=$(find_binary "$1") || return 1
-    _target=${2:-$_bin}
-    [[ -e $initdir/$_target ]] && return 0
-    [[ -L $_bin ]] && inst_symlink $_bin $_target && return 0
-    local _file _line
-    local _so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
+    if [[ $# -eq 1 ]]; then
+        for path in "" bin sbin usr/bin usr/sbin; do
+            [[ -e "${initdir:?}${path:+/$path}/${bin}" ]] && return 0
+        done
+    fi
+
+    bin="$(find_binary "$bin")" || return 1
+    target="${2:-$bin}"
+    [[ -e "${initdir:?}/$target" ]] && return 0
+    [[ -L "$bin" ]] && inst_symlink "$bin" "$target" && return 0
+
+    local file line
+    local so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
     # I love bash!
-    LC_ALL=C ldd "$_bin" 2>/dev/null | while read _line; do
-        [[ $_line = 'not a dynamic executable' ]] && break
+    while read -r line; do
+        [[ "$line" = 'not a dynamic executable' ]] && break
 
-        if [[ $_line =~ $_so_regex ]]; then
-            _file=${BASH_REMATCH[1]}
-            [[ -e ${initdir}/$_file ]] && continue
-            inst_library "$_file"
+        if [[ "$line" =~ $so_regex ]]; then
+            file="${BASH_REMATCH[1]}"
+            [[ -e "${initdir}/$file" ]] && continue
+            inst_library "$file"
             continue
         fi
 
-        if [[ $_line =~ not\ found ]]; then
-            dfatal "Missing a shared library required by $_bin."
-            dfatal "Run \"ldd $_bin\" to find out what it is."
-            dfatal "$_line"
+        if [[ "$line" =~ not\ found ]]; then
+            dfatal "Missing a shared library required by $bin."
+            dfatal "Run \"ldd $bin\" to find out what it is."
+            dfatal "$line"
             dfatal "dracut cannot create an initrd."
             exit 1
         fi
-    done
-    inst_simple "$_bin" "$_target"
+    done < <(LC_ALL=C ldd "$bin" 2>/dev/null)
+    inst_simple "$bin" "$target"
 }
 
 # same as above, except for shell scripts.
 # If your shell script does not start with shebang, it is not a shell script.
 inst_script() {
-    local _bin
-    _bin=$(find_binary "$1") || return 1
+    local bin line shebang_regex
+    bin="$(find_binary "${1:?}")" || return 1
     shift
-    local _line _shebang_regex
-    read -r -n 80 _line <"$_bin"
+
+    read -r -n 80 line <"$bin"
     # If debug is set, clean unprintable chars to prevent messing up the term
-    [[ $debug ]] && _line=$(echo -n "$_line" | tr -c -d '[:print:][:space:]')
-    _shebang_regex='(#! *)(/[^ ]+).*'
-    [[ $_line =~ $_shebang_regex ]] || return 1
-    inst "${BASH_REMATCH[2]}" && inst_simple "$_bin" "$@"
+    [[ "${debug:=}" ]] && line="$(echo -n "$line" | tr -c -d '[:print:][:space:]')"
+    shebang_regex='(#! *)(/[^ ]+).*'
+    [[ "$line" =~ $shebang_regex ]] || return 1
+    inst "${BASH_REMATCH[2]}" && inst_simple "$bin" "$@"
 }
 
 # same as above, but specialized for symlinks
 inst_symlink() {
-    local _src=$1 _target=${2:-$1} _realsrc
-    strstr "$1" "/" || return 1
-    [[ -L $1 ]] || return 1
-    [[ -L $initdir/$_target ]] && return 0
-    _realsrc=$(readlink -f "$_src")
-    if ! [[ -e $initdir/$_realsrc ]]; then
-        if [[ -d $_realsrc ]]; then
-            inst_dir "$_realsrc"
+    local src="${1:?}"
+    local target="${2:-$src}"
+    local realsrc
+
+    strstr "$src" "/" || return 1
+    [[ -L "$src" ]] || return 1
+    [[ -L "${initdir:?}/$target" ]] && return 0
+    realsrc="$(readlink -f "$src")"
+    if ! [[ -e "$initdir/$realsrc" ]]; then
+        if [[ -d "$realsrc" ]]; then
+            inst_dir "$realsrc"
         else
-            inst "$_realsrc"
+            inst "$realsrc"
         fi
     fi
-    [[ ! -e $initdir/${_target%/*} ]] && inst_dir "${_target%/*}"
-    [[ -d ${_target%/*} ]] && _target=$(readlink -f ${_target%/*})/${_target##*/}
-    ln -sfn $(convert_abs_rel "${_target}" "${_realsrc}") "$initdir/$_target"
+    [[ ! -e "$initdir/${target%/*}" ]] && inst_dir "${target%/*}"
+    [[ -d "${target%/*}" ]] && target="$(readlink -f "${target%/*}")/${target##*/}"
+    ln -sfn -- "$(convert_abs_rel "${target}" "${realsrc}")" "$initdir/$target"
 }
 
 # attempt to install any programs specified in a udev rule
 inst_rule_programs() {
-    local _prog _bin
+    local rule="${1:?}"
+    local prog bin
 
-    if grep -qE 'PROGRAM==?"[^ "]+' "$1"; then
-        for _prog in $(grep -E 'PROGRAM==?"[^ "]+' "$1" | sed -r 's/.*PROGRAM==?"([^ "]+).*/\1/'); do
-            if [ -x /lib/udev/$_prog ]; then
-                _bin=/lib/udev/$_prog
-            else
-                _bin=$(find_binary "$_prog") || {
-                    dinfo "Skipping program $_prog using in udev rule $(basename $1) as it cannot be found"
-                    continue;
-                }
+    awk 'match($0, /PROGRAM==?"([^ "]+)/, m) { print m[1]; }' "$rule" | while read -r prog; do
+        if [ -x "/lib/udev/$prog" ]; then
+            bin="/lib/udev/$prog"
+        else
+            if ! bin="$(find_binary "$prog")"; then
+                dinfo "Skipping program $prog used in udev rule $(basename "$rule") as it cannot be found"
+                continue
             fi
+        fi
 
-            #dinfo "Installing $_bin due to it's use in the udev rule $(basename $1)"
-            dracut_install "$_bin"
-        done
-    fi
+        #dinfo "Installing $_bin due to it's use in the udev rule $(basename $1)"
+        dracut_install "$bin"
+    done
 }
 
 # udev rules always get installed in the same place, so
 # create a function to install them to make life simpler.
 inst_rules() {
-    local _target=/etc/udev/rules.d _rule _found
+    local target=/etc/udev/rules.d
+    local found rule
 
     inst_dir "/lib/udev/rules.d"
-    inst_dir "$_target"
-    for _rule in "$@"; do
+    inst_dir "$target"
+    for rule in "$@"; do
         if [ "${rule#/}" = "$rule" ]; then
             for r in /lib/udev/rules.d /etc/udev/rules.d; do
-                if [[ -f $r/$_rule ]]; then
-                    _found="$r/$_rule"
-                    inst_simple "$_found"
-                    inst_rule_programs "$_found"
+                if [[ -f "$r/$rule" ]]; then
+                    found="$r/$rule"
+                    inst_simple "$found"
+                    inst_rule_programs "$found"
                 fi
             done
         fi
-        for r in '' ./ $dracutbasedir/rules.d/; do
-            if [[ -f ${r}$_rule ]]; then
-                _found="${r}$_rule"
-                inst_simple "$_found" "$_target/${_found##*/}"
-                inst_rule_programs "$_found"
+        for r in '' ./; do
+            if [[ -f "${r}${rule}" ]]; then
+                found="${r}${rule}"
+                inst_simple "$found" "$target/${found##*/}"
+                inst_rule_programs "$found"
             fi
         done
-        [[ $_found ]] || dinfo "Skipping udev rule: $_rule"
-        _found=
+        [[ $found ]] || dinfo "Skipping udev rule: $rule"
+        found=
     done
 }
 
 # general purpose installation function
 # Same args as above.
 inst() {
-    local _x
-
     case $# in
         1) ;;
-        2) [[ ! $initdir && -d $2 ]] && export initdir=$2
-            [[ $initdir = $2 ]] && set $1;;
-        3) [[ -z $initdir ]] && export initdir=$2
-            set $1 $3;;
-        *) dfatal "inst only takes 1 or 2 or 3 arguments"
-            exit 1;;
+        2)
+            [[ ! "$initdir" && -d "$2" ]] && export initdir="$2"
+            [[ "$initdir" = "$2" ]] && set "$1"
+            ;;
+        3)
+            [[ -z "$initdir" ]] && export initdir="$2"
+            set "$1" "$3"
+            ;;
+        *)
+            dfatal "inst only takes 1 or 2 or 3 arguments"
+            exit 1
+            ;;
     esac
-    for _x in inst_symlink inst_script inst_binary inst_simple; do
-        $_x "$@" && return 0
+
+    local fun
+    for fun in inst_symlink inst_script inst_binary inst_simple; do
+        "$fun" "$@" && return 0
     done
     return 1
 }
@@ -1925,14 +2117,14 @@ inst() {
 # Lets assume that /bin/baz exists, so it will be installed as /bin/foo in
 # initramfs.
 inst_any() {
-    local to f
+    local dest file
 
-    [[ $1 = '-d' ]] && to="$2" && shift 2
+    [[ "${1:?}" = '-d' ]] && dest="${2:?}" && shift 2
 
-    for f in "$@"; do
-        if [[ -e $f ]]; then
-            [[ $to ]] && inst "$f" "$to" && return 0
-            inst "$f" && return 0
+    for file in "$@"; do
+        if [[ -e "$file" ]]; then
+            [[ -n "$dest" ]] && inst "$file" "$dest" && return 0
+            inst "$file" && return 0
         fi
     done
 
@@ -1943,75 +2135,61 @@ inst_any() {
 # Install <file> to the initramfs image
 # -o optionally install the <file> and don't fail, if it is not there
 dracut_install() {
-    local _optional=no
-    if [[ $1 = '-o' ]]; then
-        _optional=yes
+    local optional=no
+    local prog="${1:?}"
+
+    if [[ "$prog" = '-o' ]]; then
+        optional=yes
         shift
     fi
-    while (($# > 0)); do
-        if ! inst "$1" ; then
-            if [[ $_optional = yes ]]; then
-                dinfo "Skipping program $1 as it cannot be found and is" \
+
+    for prog in "$@"; do
+        if ! inst "$prog" ; then
+            if [[ "$optional" = yes ]]; then
+                dinfo "Skipping program $prog as it cannot be found and is" \
                     "flagged to be optional"
             else
-                dfatal "Failed to install $1"
+                dfatal "Failed to install $prog"
                 exit 1
             fi
         fi
-        shift
     done
 }
 
 # Install a single kernel module along with any firmware it may require.
 # $1 = full path to kernel module to install
 install_kmod_with_fw() {
+    local module="${1:?}"
     # no need to go further if the module is already installed
+    [[ -e "${initdir:?}/lib/modules/${KERNEL_VER:?}/${module##*/lib/modules/$KERNEL_VER/}" ]] && return 0
+    [[ -e "$initdir/.kernelmodseen/${module##*/}" ]] && return 0
 
-    [[ -e "${initdir}/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" ]] \
-        && return 0
-
-    [[ -e "$initdir/.kernelmodseen/${1##*/}" ]] && return 0
-
-    if [[ $omit_drivers ]]; then
-        local _kmod=${1##*/}
-        _kmod=${_kmod%.ko}
-        _kmod=${_kmod/-/_}
-        if [[ "$_kmod" =~ $omit_drivers ]]; then
-            dinfo "Omitting driver $_kmod"
-            return 1
-        fi
-        if [[ "${1##*/lib/modules/$KERNEL_VER/}" =~ $omit_drivers ]]; then
-            dinfo "Omitting driver $_kmod"
-            return 1
-        fi
-    fi
+    [ -d "$initdir/.kernelmodseen" ] && : >"$initdir/.kernelmodseen/${module##*/}"
 
-    [ -d "$initdir/.kernelmodseen" ] && \
-        > "$initdir/.kernelmodseen/${1##*/}"
+    inst_simple "$module" "/lib/modules/$KERNEL_VER/${module##*/lib/modules/$KERNEL_VER/}" || return $?
 
-    inst_simple "$1" "/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" \
-        || return $?
+    local modname="${module##*/}"
+    local fwdir found fw
+    modname="${modname%.ko*}"
 
-    local _modname=${1##*/} _fwdir _found _fw
-    _modname=${_modname%.ko*}
-    for _fw in $(modinfo -k $KERNEL_VER -F firmware $1 2>/dev/null); do
-        _found=''
-        for _fwdir in $fw_dir; do
-            if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then
-                inst_simple "$_fwdir/$_fw" "/lib/firmware/$_fw"
-                _found=yes
+    while read -r fw; do
+        found=
+        for fwdir in /lib/firmware/updates /lib/firmware; do
+            if [[ -d "$fwdir" && -f "$fwdir/$fw" ]]; then
+                inst_simple "$fwdir/$fw" "/lib/firmware/$fw"
+                found=yes
             fi
         done
-        if [[ $_found != yes ]]; then
-            if ! grep -qe "\<${_modname//-/_}\>" /proc/modules; then
-                dinfo "Possible missing firmware \"${_fw}\" for kernel module" \
-                    "\"${_modname}.ko\""
+        if [[ $found != yes ]]; then
+            if ! grep -qe "\<${modname//-/_}\>" /proc/modules; then
+                dinfo "Possible missing firmware \"${fw}\" for kernel module" \
+                    "\"${modname}.ko\""
             else
-                dwarn "Possible missing firmware \"${_fw}\" for kernel module" \
-                    "\"${_modname}.ko\""
+                dwarn "Possible missing firmware \"${fw}\" for kernel module" \
+                    "\"${modname}.ko\""
             fi
         fi
-    done
+    done < <(modinfo -k "$KERNEL_VER" -F firmware "$module" 2>/dev/null)
     return 0
 }
 
@@ -2021,181 +2199,117 @@ install_kmod_with_fw() {
 #      It will be passed the full path to the found kernel module
 # $2 = module to get dependencies for
 # rest of args = arguments to modprobe
-# _fderr specifies FD passed from surrounding scope
 for_each_kmod_dep() {
-    local _func=$1 _kmod=$2 _cmd _modpath _options _found=0
+    local func="${1:?}"
+    local kmod="${2:?}"
+    local found=0
+    local cmd modpath
     shift 2
-    modprobe "$@" --ignore-install --show-depends $_kmod 2>&${_fderr} | (
-        while read _cmd _modpath _options; do
-            [[ $_cmd = insmod ]] || continue
-            $_func ${_modpath} || exit $?
-            _found=1
-        done
-        [[ $_found -eq 0 ]] && exit 1
-        exit 0
-    )
-}
-
-# filter kernel modules to install certain modules that meet specific
-# requirements.
-# $1 = search only in subdirectory of /kernel/$1
-# $2 = function to call with module name to filter.
-#      This function will be passed the full path to the module to test.
-# The behavior of this function can vary depending on whether $hostonly is set.
-# If it is, we will only look at modules that are already in memory.
-# If it is not, we will look at all kernel modules
-# This function returns the full filenames of modules that match $1
-filter_kernel_modules_by_path () (
-    local _modname _filtercmd
-    if ! [[ $hostonly ]]; then
-        _filtercmd='find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra"'
-        _filtercmd+=' "$KERNEL_MODS/weak-updates" -name "*.ko" -o -name "*.ko.gz"'
-        _filtercmd+=' -o -name "*.ko.xz"'
-        _filtercmd+=' 2>/dev/null'
-    else
-        _filtercmd='cut -d " " -f 1 </proc/modules|xargs modinfo -F filename '
-        _filtercmd+='-k $KERNEL_VER 2>/dev/null'
-    fi
-    for _modname in $(eval $_filtercmd); do
-        case $_modname in
-            *.ko) "$2" "$_modname" && echo "$_modname";;
-            *.ko.gz) gzip -dc "$_modname" > $initdir/$$.ko
-                $2 $initdir/$$.ko && echo "$_modname"
-                rm -f $initdir/$$.ko
-                ;;
-            *.ko.xz) xz -dc "$_modname" > $initdir/$$.ko
-                $2 $initdir/$$.ko && echo "$_modname"
-                rm -f $initdir/$$.ko
-                ;;
-        esac
-    done
-)
-find_kernel_modules_by_path () (
-    if ! [[ $hostonly ]]; then
-        find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra" "$KERNEL_MODS/weak-updates" \
-          -name "*.ko" -o -name "*.ko.gz" -o -name "*.ko.xz" 2>/dev/null
-    else
-        cut -d " " -f 1 </proc/modules \
-        | xargs modinfo -F filename -k $KERNEL_VER 2>/dev/null
-    fi
-)
 
-filter_kernel_modules () {
-    filter_kernel_modules_by_path  drivers  "$1"
-}
+    while read -r cmd modpath _; do
+        [[ "$cmd" = insmod ]] || continue
+        "$func" "$modpath" || return $?
+        found=1
+    done < <(modprobe "$@" --ignore-install --show-depends "$kmod")
 
-find_kernel_modules () {
-    find_kernel_modules_by_path  drivers
+    [[ $found -eq 0 ]] && return 1
+    return 0
 }
 
 # instmods [-c] <kernel module> [<kernel module> ... ]
 # instmods [-c] <kernel subsystem>
 # install kernel modules along with all their dependencies.
 # <kernel subsystem> can be e.g. "=block" or "=drivers/usb/storage"
+# FIXME(?): dracutdevs/dracut@f4e38c0da8d6bf3764c1ad753d9d52aef63050e5
 instmods() {
-    [[ $no_kernel = yes ]] && return
-    # called [sub]functions inherit _fderr
-    local _fderr=9
-    local _check=no
-    if [[ $1 = '-c' ]]; then
-        _check=yes
+    local check=no
+    if [[ $# -ge 0 && "$1" = '-c' ]]; then
+        check=yes
         shift
     fi
 
-    function inst1mod() {
-        local _ret=0 _mod="$1"
-        case $_mod in
+    inst1mod() {
+        local mod="${1:?}"
+        local ret=0
+        local mod_dir="/lib/modules/${KERNEL_VER:?}/"
+
+        case "$mod" in
             =*)
-                if [ -f $KERNEL_MODS/modules.${_mod#=} ]; then
-                    ( [[ "$_mpargs" ]] && echo $_mpargs
-                      cat "${KERNEL_MODS}/modules.${_mod#=}" ) \
-                    | instmods
+                if [ -f "${mod_dir}/modules.${mod#=}" ]; then
+                    (
+                        [[ "$mpargs" ]] && echo "$mpargs"
+                        cat "${mod_dir}/modules.${mod#=}"
+                    ) | instmods
                 else
-                    ( [[ "$_mpargs" ]] && echo $_mpargs
-                      find "$KERNEL_MODS" -path "*/${_mod#=}/*" -type f -printf '%f\n' ) \
-                    | instmods
+                    (
+                        [[ "$mpargs" ]] && echo "$mpargs"
+                        find "$mod_dir" -path "*/${mod#=}/*" -type f -printf '%f\n'
+                    ) | instmods
                 fi
                 ;;
-            --*) _mpargs+=" $_mod" ;;
-            i2o_scsi) return ;; # Do not load this diagnostic-only module
+            --*)
+                mpargs+=" $mod"
+                ;;
+            i2o_scsi)
+                # Do not load this diagnostic-only module
+                return
+                ;;
             *)
-                _mod=${_mod##*/}
+                mod=${mod##*/}
                 # if we are already installed, skip this module and go on
                 # to the next one.
-                [[ -f "$initdir/.kernelmodseen/${_mod%.ko}.ko" ]] && return
-
-                if [[ $omit_drivers ]] && [[ "$1" =~ $omit_drivers ]]; then
-                    dinfo "Omitting driver ${_mod##$KERNEL_MODS}"
-                    return
-                fi
-                # If we are building a host-specific initramfs and this
-                # module is not already loaded, move on to the next one.
-                [[ $hostonly ]] && ! grep -qe "\<${_mod//-/_}\>" /proc/modules \
-                    && ! echo $add_drivers | grep -qe "\<${_mod}\>" \
-                    && return
+                [[ -f "${initdir:?}/.kernelmodseen/${mod%.ko}.ko" ]] && return
 
                 # We use '-d' option in modprobe only if modules prefix path
                 # differs from default '/'.  This allows us to use Dracut with
                 # old version of modprobe which doesn't have '-d' option.
-                local _moddirname=${KERNEL_MODS%%/lib/modules/*}
-                [[ -n ${_moddirname} ]] && _moddirname="-d ${_moddirname}/"
+                local mod_dirname=${mod_dir%%/lib/modules/*}
+                [[ -n ${mod_dirname} ]] && mod_dirname="-d ${mod_dirname}/"
 
                 # ok, load the module, all its dependencies, and any firmware
                 # it may require
-                for_each_kmod_dep install_kmod_with_fw $_mod \
-                    --set-version $KERNEL_VER ${_moddirname} $_mpargs
-                ((_ret+=$?))
+                for_each_kmod_dep install_kmod_with_fw "$mod" \
+                    --set-version "$KERNEL_VER" \
+                    ${mod_dirname:+"$mod_dirname"} \
+                    ${mpargs:+"$mpargs"}
+                ((ret+=$?))
                 ;;
         esac
-        return $_ret
+        return "$ret"
     }
 
-    function instmods_1() {
-        local _mod _mpargs
-        if (($# == 0)); then  # filenames from stdin
-            while read _mod; do
-                inst1mod "${_mod%.ko*}" || {
-                    if [ "$_check" = "yes" ]; then
-                        dfatal "Failed to install $_mod"
-                        return 1
-                    fi
-                }
-            done
-        fi
-        while (($# > 0)); do  # filenames as arguments
-            inst1mod ${1%.ko*} || {
-                if [ "$_check" = "yes" ]; then
-                    dfatal "Failed to install $1"
-                    return 1
-                fi
-            }
-            shift
+    local mod mpargs
+
+    if [[ $# -eq 0 ]]; then  # filenames from stdin
+        while read -r mod; do
+            if ! inst1mod "${mod%.ko*}" && [ "$check" = "yes" ]; then
+                dfatal "Failed to install $mod"
+                return 1
+            fi
         done
-        return 0
-    }
+    fi
 
-    local _ret _filter_not_found='FATAL: Module .* not found.'
-    set -o pipefail
-    # Capture all stderr from modprobe to _fderr. We could use {var}>...
-    # redirections, but that would make dracut require bash4 at least.
-    eval "( instmods_1 \"\$@\" ) ${_fderr}>&1" \
-    | while read line; do [[ "$line" =~ $_filter_not_found ]] && echo $line || echo $line >&2 ;done | derror
-    _ret=$?
-    set +o pipefail
-    return $_ret
+    for mod in "$@"; do # filenames as arguments
+        if ! inst1mod "${mod%.ko*}" && [ "$check" = "yes" ]; then
+            dfatal "Failed to install $mod"
+            return 1
+        fi
+    done
+
+    return 0
 }
 
 setup_suse() {
-    ln -fs ../usr/bin/systemctl $initdir/bin/
-    ln -fs ../usr/lib/systemd $initdir/lib/
+    ln -fs ../usr/bin/systemctl "${initdir:?}/bin/"
+    ln -fs ../usr/lib/systemd "$initdir/lib/"
     inst_simple "/usr/lib/systemd/system/haveged.service"
-    instmods ext4
 }
 
 _umount_dir() {
-    if mountpoint -q $1; then
-        ddebug "umount $1"
-        umount $1
+    local mountpoint="${1:?}"
+    if mountpoint -q "$mountpoint"; then
+        ddebug "umount $mountpoint"
+        umount "$mountpoint"
     fi
 }
 
@@ -2208,14 +2322,14 @@ _test_cleanup() {
     # (post-test) cleanup should always ignore failure and cleanup as much as possible
     (
         set +e
-        _umount_dir $initdir
-        rm -vf "$IMAGE_PUBLIC"
+        [[ -n "$initdir" ]] && _umount_dir "$initdir"
+        [[ -n "$IMAGE_PUBLIC" ]] && rm -vf "$IMAGE_PUBLIC"
         # If multiple setups/cleans are ran in parallel, this can cause a race
-        if [ ${TEST_PARALLELIZE} -ne 1 ]; then
+        if [[ -n "$IMAGESTATEDIR" &&  $TEST_PARALLELIZE -ne 1 ]]; then
             rm -vf "${IMAGESTATEDIR}/default.img"
         fi
-        rm -vfr "$TESTDIR"
-        rm -vf "$STATEFILE"
+        [[ -n "$TESTDIR" ]] && rm -vfr "$TESTDIR"
+        [[ -n "$STATEFILE" ]] && rm -vf "$STATEFILE"
     ) || :
 }
 
@@ -2227,7 +2341,7 @@ test_cleanup() {
 test_cleanup_again() {
     [ -n "$TESTDIR" ] || return
     rm -rf "$TESTDIR/unprivileged-nspawn-root"
-    _umount_dir $initdir
+    [[ -n "$initdir" ]] && _umount_dir "$initdir"
 }
 
 test_create_image() {
@@ -2237,30 +2351,36 @@ test_create_image() {
     (
         LOG_LEVEL=5
         setup_basic_environment
-        mask_supporting_services
+
+        # We want to test all services in TEST-01-BASIC, but mask them in
+        # all other tests
+        if [[ "$TESTID" != "01" ]]; then
+            dinfo "Masking supporting services"
+            mask_supporting_services
+        fi
     )
 }
 
 test_setup() {
-    if [ ${TEST_REQUIRE_INSTALL_TESTS} -ne 0 ] && \
-            type -P meson >/dev/null && \
-            [[ "$(meson configure $BUILD_DIR | grep install-tests | awk '{ print $2 }')" != "true" ]]; then
+    if [ "${TEST_REQUIRE_INSTALL_TESTS:?}" -ne 0 ] && \
+            command -v meson >/dev/null && \
+            [[ "$(meson configure "${BUILD_DIR:?}" | grep install-tests | awk '{ print $2 }')" != "true" ]]; then
         dfatal "$BUILD_DIR needs to be built with -Dinstall-tests=true"
         exit 1
     fi
 
-    if [ -e "$IMAGE_PRIVATE" ]; then
-        echo "Reusing existing image $IMAGE_PRIVATE → $(realpath $IMAGE_PRIVATE)"
+    if [ -e "${IMAGE_PRIVATE:?}" ]; then
+        echo "Reusing existing image $IMAGE_PRIVATE → $(realpath "$IMAGE_PRIVATE")"
         mount_initdir
     else
-        if [ ! -e "$IMAGE_PUBLIC" ]; then
+        if [ ! -e "${IMAGE_PUBLIC:?}" ]; then
             # default.img is the base that every test uses and optionally appends to
-            if [ ! -e "${IMAGESTATEDIR}/default.img" ] || [ -n "${TEST_FORCE_NEWIMAGE}" ]; then
+            if [ ! -e "${IMAGESTATEDIR:?}/default.img" ] || [ -n "${TEST_FORCE_NEWIMAGE:=}" ]; then
                 # Create the backing public image, but then completely unmount
                 # it and drop the loopback device responsible for it, since we're
                 # going to symlink/copy the image and mount it again from
                 # elsewhere.
-                local image_old=${IMAGE_PUBLIC}
+                local image_old="${IMAGE_PUBLIC}"
                 if [ -z "${TEST_FORCE_NEWIMAGE}" ]; then
                     IMAGE_PUBLIC="${IMAGESTATEDIR}/default.img"
                 fi
@@ -2270,26 +2390,26 @@ test_setup() {
                 cleanup_loopdev
                 IMAGE_PUBLIC="${image_old}"
             fi
-            if [ "${IMAGE_NAME}" != "default" ] && [ -z "${TEST_FORCE_NEWIMAGE}" ]; then
+            if [ "${IMAGE_NAME:?}" != "default" ] && [ -z "${TEST_FORCE_NEWIMAGE}" ]; then
                 cp -v "$(realpath "${IMAGESTATEDIR}/default.img")" "$IMAGE_PUBLIC"
             fi
         fi
 
         local hook_defined=1
-        if declare -f -F test_append_files > /dev/null; then
+        if declare -f -F test_append_files >/dev/null; then
             hook_defined=$?
         fi
 
-        echo "Reusing existing cached image $IMAGE_PUBLIC → $(realpath $IMAGE_PUBLIC)"
-        if [ ${TEST_PARALLELIZE} -ne 0 ] || [ ${hook_defined} -eq 0 ]; then
-            cp -v "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE"
+        echo "Reusing existing cached image $IMAGE_PUBLIC → $(realpath "$IMAGE_PUBLIC")"
+        if [ "$TEST_PARALLELIZE" -ne 0 ] || [ "$hook_defined" -eq 0 ]; then
+            cp -v -- "$(realpath "$IMAGE_PUBLIC")" "$IMAGE_PRIVATE"
         else
-            ln -sv "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE"
+            ln -sv -- "$(realpath "$IMAGE_PUBLIC")" "$IMAGE_PRIVATE"
         fi
 
         mount_initdir
-        if [ ${hook_defined} -eq 0 ]; then
-            test_append_files "$initdir"
+        if [ "$hook_defined" -eq 0 ]; then
+            test_append_files "${initdir:?}"
         fi
     fi
 
@@ -2297,26 +2417,27 @@ test_setup() {
 }
 
 test_run() {
+    local test_id="${1:?}"
     mount_initdir
 
-    if [ -z "$TEST_NO_QEMU" ]; then
-        if run_qemu "$1"; then
+    if [ -z "${TEST_NO_QEMU:=}" ]; then
+        if run_qemu "$test_id"; then
             check_result_qemu || { echo "QEMU test failed"; return 1; }
         else
             dwarn "can't run QEMU, skipping"
         fi
     fi
-    if [ -z "$TEST_NO_NSPAWN" ]; then
+    if [ -z "${TEST_NO_NSPAWN:=}" ]; then
         mount_initdir
-        if run_nspawn "$initdir" "$1"; then
+        if run_nspawn "${initdir:?}" "$test_id"; then
             check_result_nspawn "$initdir" || { echo "nspawn-root test failed"; return 1; }
         else
             dwarn "can't run systemd-nspawn, skipping"
         fi
 
-        if [[ "$RUN_IN_UNPRIVILEGED_CONTAINER" = "yes" ]]; then
+        if [[ "${RUN_IN_UNPRIVILEGED_CONTAINER:=}" = "yes" ]]; then
             dir="$TESTDIR/unprivileged-nspawn-root"
-            if NSPAWN_ARGUMENTS="-U --private-network $NSPAWN_ARGUMENTS" run_nspawn "$dir" "$1"; then
+            if NSPAWN_ARGUMENTS="-U --private-network ${NSPAWN_ARGUMENTS:-}" run_nspawn "$dir" "$test_id"; then
                 check_result_nspawn "$dir" || { echo "unprivileged-nspawn-root test failed"; return 1; }
             else
                 dwarn "can't run systemd-nspawn, skipping"
@@ -2332,26 +2453,26 @@ do_test() {
         exit 0
     fi
 
-    if [ -n "$TEST_NO_QEMU" ] && [ -n "$TEST_NO_NSPAWN" ]; then
+    if [ -n "${TEST_NO_QEMU:=}" ] && [ -n "${TEST_NO_NSPAWN:=}" ]; then
         echo "TEST: $TEST_DESCRIPTION [SKIPPED]: both QEMU and nspawn disabled" >&2
         exit 0
     fi
 
-    if [ -n "$TEST_QEMU_ONLY" ] && [ -z "$TEST_NO_NSPAWN" ]; then
+    if [ -n "${TEST_QEMU_ONLY:=}" ] && [ -z "$TEST_NO_NSPAWN" ]; then
         echo "TEST: $TEST_DESCRIPTION [SKIPPED]: QEMU-only tests requested" >&2
         exit 0
     fi
 
-    if [ -n "$TEST_PREFER_NSPAWN" ] && [ -z "$TEST_NO_NSPAWN" ]; then
+    if [ -n "${TEST_PREFER_NSPAWN:=}" ] && [ -z "$TEST_NO_NSPAWN" ]; then
         TEST_NO_QEMU=1
     fi
 
     # Detect lib paths
-    [[ $libdir ]] || for libdir in /lib64 /lib; do
+    [[ "$libdir" ]] || for libdir in /lib64 /lib; do
         [[ -d $libdir ]] && libdirs+=" $libdir" && break
     done
 
-    [[ $usrlibdir ]] || for usrlibdir in /usr/lib64 /usr/lib; do
+    [[ "$usrlibdir" ]] || for usrlibdir in /usr/lib64 /usr/lib; do
         [[ -d $usrlibdir ]] && libdirs+=" $usrlibdir" && break
     done
 
@@ -2360,15 +2481,20 @@ do_test() {
     import_testdir
     import_initdir
 
-    testname="$(basename $PWD)"
+    if [ -n "${SUDO_USER}" ]; then
+        ddebug "Making ${TESTDIR:?} readable for ${SUDO_USER} (acquired from sudo)"
+        setfacl -m "user:${SUDO_USER:?}:r-X" "${TESTDIR:?}"
+    fi
+
+    testname="$(basename "$PWD")"
 
     while (($# > 0)); do
         case $1 in
             --run)
                 echo "${testname} RUN: $TEST_DESCRIPTION"
-                test_run "$2"
+                test_run "$TESTID"
                 ret=$?
-                if (( $ret == 0 )); then
+                if [ $ret -eq 0 ]; then
                     echo "${testname} RUN: $TEST_DESCRIPTION [OK]"
                 else
                     echo "${testname} RUN: $TEST_DESCRIPTION [FAILED]"
@@ -2397,7 +2523,7 @@ do_test() {
                     test_setup_cleanup </dev/null >>"$TESTLOG" 2>&1 || ret=$?
                 fi
                 if [ $ret -eq 0 ]; then
-                    test_run "$2" </dev/null >>"$TESTLOG" 2>&1 || ret=$?
+                    test_run "$TESTID" </dev/null >>"$TESTLOG" 2>&1 || ret=$?
                 fi
                 test_cleanup
                 if [ $ret -eq 0 ]; then
diff --git a/test/test-network/conf/agent-client-peer.network b/test/test-network/conf/agent-client-peer.network
new file mode 100644 (file)
index 0000000..0db83dc
--- /dev/null
@@ -0,0 +1,9 @@
+[Match]
+Name=client-peer
+[Network]
+Address=192.168.6.2/24
+DHCPServer=yes
+IPForward=ipv4
+[DHCPServer]
+RelayTarget=192.168.5.1
+BindToInterface=no
diff --git a/test/test-network/conf/agent-client.network b/test/test-network/conf/agent-client.network
new file mode 100644 (file)
index 0000000..773dc8a
--- /dev/null
@@ -0,0 +1,5 @@
+[Match]
+Name=client
+[Network]
+DHCP=yes
+IPForward=ipv4
diff --git a/test/test-network/conf/agent-server-peer.network b/test/test-network/conf/agent-server-peer.network
new file mode 100644 (file)
index 0000000..fdb235e
--- /dev/null
@@ -0,0 +1,5 @@
+[Match]
+Name=server-peer
+[Network]
+Address=192.168.5.2/24
+IPForward=ipv4
diff --git a/test/test-network/conf/agent-server.network b/test/test-network/conf/agent-server.network
new file mode 100644 (file)
index 0000000..65bcc54
--- /dev/null
@@ -0,0 +1,13 @@
+[Match]
+Name=server
+[Network]
+Address=192.168.5.1/24
+IPForward=ipv4
+DHCPServer=yes
+
+[DHCPServer]
+BindToInterface=no
+PoolOffset=150
+PoolSize=1
+DNS=192.168.5.1
+NTP=192.168.5.1
diff --git a/test/test-network/conf/agent-veth-client.netdev b/test/test-network/conf/agent-veth-client.netdev
new file mode 100644 (file)
index 0000000..ace785f
--- /dev/null
@@ -0,0 +1,8 @@
+[NetDev]
+Name=client
+Kind=veth
+MACAddress=12:34:56:78:9a:bc
+
+[Peer]
+Name=client-peer
+MACAddress=12:34:56:78:9a:bd
diff --git a/test/test-network/conf/agent-veth-server.netdev b/test/test-network/conf/agent-veth-server.netdev
new file mode 100644 (file)
index 0000000..3a3d393
--- /dev/null
@@ -0,0 +1,8 @@
+[NetDev]
+Name=server
+Kind=veth
+MACAddress=12:34:56:78:9b:bc
+
+[Peer]
+Name=server-peer
+MACAddress=12:34:56:78:9b:bd
diff --git a/test/test-network/conf/dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network b/test/test-network/conf/dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network
new file mode 100644 (file)
index 0000000..448cfb0
--- /dev/null
@@ -0,0 +1,9 @@
+[Match]
+Name=veth99
+
+[NetworkEmulator]
+DelaySec=9
+
+[Network]
+DHCP=ipv4
+IPv6AcceptRA=true
index 3ebbf05d3e35278a60c5e19076c575bdeeb3bdd9..34e2d737ce8ce2bbaffc92e06530b3661532ae25 100644 (file)
@@ -11,3 +11,5 @@ PoolOffset=10
 PoolSize=50
 EmitRouter=yes
 Timezone=Europe/Berlin
+DNS=192.168.5.1
+NTP=192.168.5.1
diff --git a/test/test-network/conf/dhcp-server-with-ipv6-prefix.network b/test/test-network/conf/dhcp-server-with-ipv6-prefix.network
new file mode 100644 (file)
index 0000000..7a1cfc6
--- /dev/null
@@ -0,0 +1,15 @@
+[Match]
+Name=veth-peer
+
+[Network]
+Address=192.168.5.1/24
+IPv6AcceptRA=no
+DHCPServer=yes
+IPv6SendRA=yes
+
+[IPv6Prefix]
+Prefix=2002:da8:1:0::/64
+
+[DHCPServer]
+DNS=192.168.5.1
+NTP=192.168.5.1
diff --git a/test/test-network/conf/ipv6-prefix-with-delay.network b/test/test-network/conf/ipv6-prefix-with-delay.network
new file mode 100644 (file)
index 0000000..4fe3c9a
--- /dev/null
@@ -0,0 +1,12 @@
+[Match]
+Name=veth-peer
+
+[NetworkEmulator]
+DelaySec=15
+
+[Network]
+IPv6AcceptRA=no
+IPv6SendRA=yes
+
+[IPv6Prefix]
+Prefix=2002:da8:1:0::/64
diff --git a/test/test-network/conf/ipv6ra-prefix-client-with-static-ipv4-address.network b/test/test-network/conf/ipv6ra-prefix-client-with-static-ipv4-address.network
new file mode 100644 (file)
index 0000000..13fd0ad
--- /dev/null
@@ -0,0 +1,6 @@
+[Match]
+Name=veth99
+
+[Network]
+IPv6AcceptRA=true
+Address=192.168.5.1/24
index 1f7e7d16f01556a95116efe06245b17c257a9544..d9db9a9ab96f8ae331b26c38b06694e857ed280f 100644 (file)
@@ -3,6 +3,7 @@ Name=dummy98
 
 [Link]
 RequiredForOnline=routable
+RequiredFamilyForOnline=both
 
 [Network]
 IPv6AcceptRA=no
@@ -14,3 +15,4 @@ MulticastDNS=yes
 DNSSEC=no
 Address=192.168.10.10/24
 Address=192.168.12.12/24
+Address=2002:da8:1:0:1034:56ff:fe78:9abc/64
index fc88fefd0f0875666106127d9f883e9650b6a5fe..bf8add778bbbaf5da0ae4aaaee3e2dc5ac183eb2 100755 (executable)
@@ -461,7 +461,7 @@ def remove_unit_from_networkd_path(units):
                 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
 
 def start_dnsmasq(additional_options='', ipv4_range='192.168.5.10,192.168.5.200', ipv6_range='2600::10,2600::20', lease_time='1h'):
-    dnsmasq_command = f'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range={ipv6_range},{lease_time} --dhcp-range={ipv4_range},{lease_time} -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5 --port=0 ' + additional_options
+    dnsmasq_command = f'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range={ipv6_range},{lease_time} --dhcp-range={ipv4_range},{lease_time} -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --port=0 ' + additional_options
     check_output(dnsmasq_command)
 
 def stop_dnsmasq(pid_file):
@@ -555,7 +555,7 @@ class Utilities():
             self.fail(f'Timed out waiting for {link} to reach state {operstate}/{setup_state}')
         return False
 
-    def wait_online(self, links_with_operstate, timeout='20s', bool_any=False, setup_state='configured', setup_timeout=5):
+    def wait_online(self, links_with_operstate, timeout='20s', bool_any=False, ipv4=False, ipv6=False, setup_state='configured', setup_timeout=5):
         """Wait for the link(s) to reach the specified operstate and/or setup state.
 
         This is similar to wait_operstate() but can be used for multiple links,
@@ -569,6 +569,9 @@ class Utilities():
         Set 'bool_any' to True to wait for any (instead of all) of the given links.
         If this is set, no setup_state checks are done.
 
+        Set 'ipv4' or 'ipv6' to True to wait for IPv4 address or IPv6 address, respectively, of each of the given links.
+        This is applied only for the operational state 'degraded' or above.
+
         Note that this function waits for the link(s) to reach *or exceed* the given operstate.
         However, the setup_state, if specified, must be matched *exactly*.
 
@@ -578,6 +581,10 @@ class Utilities():
         args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
         if bool_any:
             args += ['--any']
+        if ipv4:
+            args += ['--ipv4']
+        if ipv6:
+            args += ['--ipv6']
         try:
             check_output(*args, env=env)
         except subprocess.CalledProcessError:
@@ -1781,6 +1788,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
         'gretun97',
         'ip6gretun97',
         'test1',
+        'veth-peer',
         'veth99',
         'vrf99',
     ]
@@ -1842,6 +1850,10 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
         '25-vrf.netdev',
         '25-vrf.network',
         '26-link-local-addressing-ipv6.network',
+        'dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network',
+        'dhcp-server-with-ipv6-prefix.network',
+        'ipv6ra-prefix-client-with-static-ipv4-address.network',
+        'ipv6-prefix-with-delay.network',
         'routing-policy-rule-dummy98.network',
         'routing-policy-rule-test1.network',
         'routing-policy-rule-reconfigure1.network',
@@ -3099,6 +3111,22 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
 
         call('rmmod netdevsim', stderr=subprocess.DEVNULL)
 
+    def test_wait_online_ipv4(self):
+        copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-with-ipv6-prefix.network', 'dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network')
+        start_networkd()
+
+        self.wait_online(['veth99:routable'], ipv4=True)
+
+        self.wait_address('veth99', r'192.168.5.[0-9]+', ipv='-4', timeout_sec=1)
+
+    def test_wait_online_ipv6(self):
+        copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix-with-delay.network', 'ipv6ra-prefix-client-with-static-ipv4-address.network')
+        start_networkd()
+
+        self.wait_online(['veth99:routable'], ipv6=True)
+
+        self.wait_address('veth99', r'2002:da8:1:0:1034:56ff:fe78:9abc', ipv='-6', timeout_sec=1)
+
 class NetworkdStateFileTests(unittest.TestCase, Utilities):
     links = [
         'dummy98',
@@ -3135,10 +3163,13 @@ class NetworkdStateFileTests(unittest.TestCase, Utilities):
 
         with open(path) as f:
             data = f.read()
+            self.assertRegex(data, r'IPV4_ADDRESS_STATE=routable')
+            self.assertRegex(data, r'IPV6_ADDRESS_STATE=routable')
             self.assertRegex(data, r'ADMIN_STATE=configured')
             self.assertRegex(data, r'OPER_STATE=routable')
             self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes')
             self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
+            self.assertRegex(data, r'REQUIRED_FAMILY_FOR_ONLINE=both')
             self.assertRegex(data, r'ACTIVATION_POLICY=up')
             self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
             self.assertRegex(data, r'DNS=10.10.10.10#aaa.com 10.10.10.11:1111#bbb.com \[1111:2222::3333\]:1234#ccc.com')
@@ -3658,6 +3689,43 @@ class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
         self.assertRegex(output, '192.168.5.*')
         self.assertRegex(output, 'Europe/Berlin')
 
+class NetworkdDHCPServerRelayAgentTests(unittest.TestCase, Utilities):
+    links = [
+        'client',
+        'server',
+        'client-peer',
+        'server-peer',
+        ]
+
+    units = [
+        'agent-veth-client.netdev',
+        'agent-veth-server.netdev',
+        'agent-client.network',
+        'agent-server.network',
+        'agent-client-peer.network',
+        'agent-server-peer.network',
+        ]
+
+    def setUp(self):
+        remove_links(self.links)
+        stop_networkd(show_logs=False)
+
+    def tearDown(self):
+        remove_links(self.links)
+        remove_unit_from_networkd_path(self.units)
+        stop_networkd(show_logs=True)
+
+    def test_relay_agent(self):
+        copy_unit_to_networkd_unit_path(*self.units)
+        start_networkd()
+
+        #Test is disabled until BindToInterface DHCP server configuration option is supported
+        self.wait_online(['client:routable'])
+
+        output = check_output(*networkctl_cmd, '-n', '0', 'status', 'client', env=env)
+        print(output)
+        self.assertRegex(output, 'Address: 192.168.5.150 \(DHCP4 via 192.168.5.1\)')
+
 class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
     links = [
         'veth99',
@@ -3784,55 +3852,77 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
 
     def test_dhcp_client_ipv4_use_routes_gateway(self):
-        for (routes, gateway, dnsroutes) in itertools.product([True, False, None], repeat=3):
+        for (routes, gateway, dns_and_ntp_routes, classless) in itertools.product([True, False], repeat=4):
             self.setUp()
-            with self.subTest(routes=routes, gateway=gateway, dnsroutes=dnsroutes):
-                self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway, dnsroutes)
+            with self.subTest(routes=routes, gateway=gateway, dns_and_ntp_routes=dns_and_ntp_routes, classless=classless):
+                self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway, dns_and_ntp_routes, classless)
             self.tearDown()
 
-    def _test_dhcp_client_ipv4_use_routes_gateway(self, routes, gateway, dnsroutes):
+    def _test_dhcp_client_ipv4_use_routes_gateway(self, use_routes, use_gateway, dns_and_ntp_routes, classless):
         testunit = 'dhcp-client-ipv4-use-routes-use-gateway.network'
         testunits = ['25-veth.netdev', 'dhcp-server-veth-peer.network', testunit]
-        if routes != None:
-            testunits.append(f'{testunit}.d/use-routes-{routes}.conf');
-        if gateway != None:
-            testunits.append(f'{testunit}.d/use-gateway-{gateway}.conf');
-        if dnsroutes != None:
-            testunits.append(f'{testunit}.d/use-dns-routes-{dnsroutes}.conf');
+        testunits.append(f'{testunit}.d/use-routes-{use_routes}.conf');
+        testunits.append(f'{testunit}.d/use-gateway-{use_gateway}.conf');
+        testunits.append(f'{testunit}.d/use-dns-and-ntp-routes-{dns_and_ntp_routes}.conf');
         copy_unit_to_networkd_unit_path(*testunits, dropins=False)
 
         start_networkd()
         self.wait_online(['veth-peer:carrier'])
-        start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
+        additional_options = '--dhcp-option=option:dns-server,192.168.5.10,8.8.8.8 --dhcp-option=option:ntp-server,192.168.5.11,9.9.9.9 --dhcp-option=option:static-route,192.168.5.100,192.168.5.2,8.8.8.8,192.168.5.3'
+        if classless:
+            additional_options += ' --dhcp-option=option:classless-static-route,0.0.0.0/0,192.168.5.4,8.0.0.0/8,192.168.5.5'
+        start_dnsmasq(additional_options=additional_options, lease_time='2m')
         self.wait_online(['veth99:routable', 'veth-peer:routable'])
 
-        output = check_output('ip route show dev veth99')
+        output = check_output('ip -4 route show dev veth99')
         print(output)
 
-        # UseRoutes= defaults to true
-        useroutes = routes in [True, None]
-        # UseGateway= defaults to useroutes
-        usegateway = useroutes if gateway == None else gateway
-
         # Check UseRoutes=
-        if useroutes:
-            self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.181 metric 1024')
+        if use_routes:
+            if classless:
+                self.assertRegex(output, r'default via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
+                self.assertRegex(output, r'8.0.0.0/8 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
+                self.assertRegex(output, r'192.168.5.4 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
+                self.assertRegex(output, r'192.168.5.5 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
+            else:
+                self.assertRegex(output, r'192.168.5.0/24 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
+                self.assertRegex(output, r'8.0.0.0/8 via 192.168.5.3 proto dhcp src 192.168.5.[0-9]* metric 1024')
+                self.assertRegex(output, r'192.168.5.3 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
         else:
-            self.assertNotRegex(output, r'192.168.5.5')
+            self.assertNotRegex(output, r'default via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
+            self.assertNotRegex(output, r'8.0.0.0/8 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
+            self.assertNotRegex(output, r'192.168.5.4 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
+            self.assertNotRegex(output, r'192.168.5.5 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
+            self.assertNotRegex(output, r'192.168.5.0/24 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
+            self.assertNotRegex(output, r'8.0.0.0/8 via 192.168.5.3 proto dhcp src 192.168.5.[0-9]* metric 1024')
+            self.assertNotRegex(output, r'192.168.5.3 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
 
         # Check UseGateway=
-        if usegateway:
-            self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 1024')
+        if use_gateway and (not classless or not use_routes):
+            self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
+            self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
         else:
-            self.assertNotRegex(output, r'default via 192.168.5.1')
-
-        # Check RoutesToDNS=, which defaults to false
-        if dnsroutes:
-            self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
-            self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
+            self.assertNotRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
+            self.assertNotRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
+
+        # Check RoutesToDNS= and RoutesToNTP=
+        if dns_and_ntp_routes:
+            self.assertRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
+            self.assertRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
+            if classless and use_routes:
+                self.assertRegex(output, r'8.8.8.8 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
+                self.assertRegex(output, r'9.9.9.9 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
+            elif use_gateway:
+                self.assertRegex(output, r'8.8.8.8 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
+                self.assertRegex(output, r'9.9.9.9 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
+            else:
+                self.assertNotRegex(output, r'8.8.8.8 via 192.168.5.[0-9]* proto dhcp src 192.168.5.[0-9]* metric 1024')
+                self.assertNotRegex(output, r'9.9.9.9 via 192.168.5.[0-9]* proto dhcp src 192.168.5.[0-9]* metric 1024')
         else:
-            self.assertNotRegex(output, r'192.168.5.6')
-            self.assertNotRegex(output, r'192.168.5.7')
+            self.assertNotRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
+            self.assertNotRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
+            self.assertNotRegex(output, r'8.8.8.8 via 192.168.5.[0-9]* proto dhcp src 192.168.5.[0-9]* metric 1024')
+            self.assertNotRegex(output, r'9.9.9.9 via 192.168.5.[0-9]* proto dhcp src 192.168.5.[0-9]* metric 1024')
 
     def test_dhcp_client_ipv4_ipv6(self):
         copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
@@ -3843,7 +3933,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         self.wait_online(['veth99:routable', 'veth-peer:routable'])
 
         # link become 'routable' when at least one protocol provide an valid address.
-        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
+        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
         self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
 
         output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
@@ -3880,7 +3970,6 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
         if main_table_is_empty:
             self.assertRegex(output, '192.168.5.0/24 proto dhcp')
-        self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
         self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
 
         print('## dnsmasq log')
@@ -3946,13 +4035,12 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         output = check_output('ip address show dev veth99 scope global')
         print(output)
         self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
-        self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
+        self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global secondary dynamic veth99')
 
         output = check_output('ip route show dev veth99')
         print(output)
         self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
         self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
-        self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
         self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
 
     def test_dhcp_route_table_id(self):
@@ -3976,7 +4064,9 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
 
         output = check_output('ip route show dev veth99')
         print(output)
-        self.assertRegex(output, 'metric 24')
+        self.assertIn('default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 24', output)
+        self.assertIn('192.168.5.0/24 proto kernel scope link src 192.168.5.181 metric 24', output)
+        self.assertIn('192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 24', output)
 
     def test_dhcp_client_reassign_static_routes_ipv4(self):
         copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
@@ -3988,7 +4078,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
 
         output = check_output('ip address show dev veth99 scope global')
         print(output)
-        self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
+        self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
 
         output = check_output('ip route show dev veth99')
         print(output)
@@ -4133,7 +4223,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         self.wait_online(['veth99:routable', 'veth-peer:routable'])
 
         # link become 'routable' when at least one protocol provide an valid address.
-        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
+        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
         self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
 
         output = check_output('ip address show dev veth99 scope global')
@@ -4176,7 +4266,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
 
         # link become 'routable' when at least one protocol provide an valid address.
-        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
+        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
         self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
 
         print('## ip -d link show dev vrf99')
@@ -4187,14 +4277,14 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         print('## ip address show vrf vrf99')
         output = check_output('ip address show vrf vrf99')
         print(output)
-        self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
+        self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
         self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
         self.assertRegex(output, 'inet6 .* scope link')
 
         print('## ip address show dev veth99')
         output = check_output('ip address show dev veth99')
         print(output)
-        self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
+        self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
         self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
         self.assertRegex(output, 'inet6 .* scope link')
 
@@ -4203,7 +4293,6 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         print(output)
         self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
         self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
-        self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
         self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
 
         print('## ip route show table main dev veth99')
@@ -4270,9 +4359,9 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         output = check_output('ip -6 address show dev veth99 scope link')
         self.assertRegex(output, r'inet6 .* scope link')
         output = check_output('ip -4 address show dev veth99 scope global dynamic')
-        self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99')
+        self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
         output = check_output('ip -4 address show dev veth99 scope link')
-        self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link')
+        self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
 
         print('Wait for the dynamic address to be expired')
         time.sleep(130)
@@ -4285,9 +4374,9 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         output = check_output('ip -6 address show dev veth99 scope link')
         self.assertRegex(output, r'inet6 .* scope link')
         output = check_output('ip -4 address show dev veth99 scope global dynamic')
-        self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99')
+        self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
         output = check_output('ip -4 address show dev veth99 scope link')
-        self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link')
+        self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
 
         search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
 
@@ -4307,13 +4396,13 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         output = check_output('ip -6 address show dev veth99 scope link')
         self.assertRegex(output, r'inet6 .* scope link')
         output = check_output('ip -4 address show dev veth99 scope global dynamic')
-        self.assertNotRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99')
+        self.assertNotRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
         output = check_output('ip -4 address show dev veth99 scope link')
-        self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link')
+        self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
 
         start_dnsmasq(lease_time='2m')
-        self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic', ipv='-4')
-        self.wait_address_dropped('veth99', r'inet 169\.254\.\d+\.\d+/16 brd 169\.255\.255\.255 scope link', scope='link', ipv='-4')
+        self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic', ipv='-4')
+        self.wait_address_dropped('veth99', r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.255\.255\.255 scope link', scope='link', ipv='-4')
 
     def test_dhcp_client_route_remove_on_renew(self):
         copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
@@ -4327,7 +4416,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
 
         output = check_output('ip -4 address show dev veth99 scope global dynamic')
         print(output)
-        self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
+        self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
         address1=None
         for line in output.splitlines():
             if 'brd 192.168.5.255 scope global dynamic veth99' in line:
@@ -4347,10 +4436,10 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
 
         output = check_output('ip -4 address show dev veth99 scope global dynamic')
         print(output)
-        self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
+        self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
         address2=None
         for line in output.splitlines():
-            if 'brd 192.168.5.255 scope global dynamic veth99' in line:
+            if 'metric 1024 brd 192.168.5.255 scope global dynamic veth99' in line:
                 address2 = line.split()[1].split('/')[0]
                 break
 
@@ -4372,7 +4461,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         self.wait_online(['veth99:routable', 'veth-peer:routable'])
 
         # link become 'routable' when at least one protocol provide an valid address.
-        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
+        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
         self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
 
         time.sleep(3)
@@ -4390,7 +4479,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         self.wait_online(['veth99:routable', 'veth-peer:routable'])
 
         # link become 'routable' when at least one protocol provide an valid address.
-        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
+        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
         self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
 
         time.sleep(3)
@@ -4408,7 +4497,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         self.wait_online(['veth99:routable', 'veth-peer:routable'])
 
         # link become 'routable' when at least one protocol provide an valid address.
-        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
+        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
         self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
 
         time.sleep(3)
@@ -4426,7 +4515,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         self.wait_online(['veth99:routable', 'veth-peer:routable'])
 
         # link become 'routable' when at least one protocol provide an valid address.
-        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
+        self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
         self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
 
         time.sleep(3)
diff --git a/test/testsuite-04.units/silent-success.service b/test/testsuite-04.units/silent-success.service
new file mode 100644 (file)
index 0000000..a9f7137
--- /dev/null
@@ -0,0 +1,6 @@
+[Unit]
+Description=Silent successful service
+
+[Service]
+LogLevelMax=notice
+ExecStart=/bin/true
index facf5577be10ba31d8e5887c6b8eb1b648bf6880..766a454d6a2e66aec54c5b61b23c385243067893 100644 (file)
@@ -7,4 +7,4 @@ After=testsuite-28-pre.service
 [Service]
 Type=oneshot
 ExecStart=test -f /tmp/test-specifier-j-%j
-ExecStart=sh -c 'echo OK > /testok'
+ExecStart=sh -c 'echo OK >/testok'
similarity index 72%
rename from test/units/test-honor-first-shutdown.service
rename to test/testsuite-52.units/test-honor-first-shutdown.service
index 3170f979e258ecb4fc3c5c0a07a04efab6487c1b..3b6927c0d13ddd31587c265c4de602de8cbc8d16 100644 (file)
@@ -3,7 +3,7 @@ Description=Honor First Shutdown feature
 After=multi-user.target
 
 [Service]
-ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
+ExecStart=/usr/lib/systemd/tests/testdata/testsuite-52.units/%N.sh
 ExecStop=sh -c 'kill -KILL $MAINPID'
 FailureAction=reboot
 
index 85b9cf5a9695e7ca415760d26547754850a8cac4..cdd6b3436224131b82f56e678b108135b27e83f8 100644 (file)
@@ -1,6 +1,7 @@
 [Unit]
 Description=TEST-01-BASIC
 After=multi-user.target
+Wants=systemd-resolved.service systemd-networkd.service
 
 [Service]
 ExecStartPre=rm -f /failed /testok
index 1ff1c3347b2c04c7b78591a3fd58b76bf7733151..da02304a32a2577e711c83c7bdc69e304b0ab860 100755 (executable)
@@ -1,13 +1,13 @@
 #!/usr/bin/env bash
-#set -ex
-#set -o pipefail
+set -eux
+set -o pipefail
 
 NPROC=$(nproc)
 MAX_QUEUE_SIZE=${NPROC:-2}
-IFS=$'\n' TEST_LIST=($(ls /usr/lib/systemd/tests/test-*))
+mapfile -t TEST_LIST < <(find /usr/lib/systemd/tests/ -maxdepth 1 -type f -name "test-*")
 
 # reset state
-rm /failed-tests /skipped-tests /skipped
+rm -fv /failed-tests /skipped-tests /skipped
 
 # Check & report test results
 # Arguments:
@@ -54,10 +54,9 @@ for task in "${TEST_LIST[@]}"; do
     # until one of the tasks finishes, so we can replace it.
     while [[ ${#running[@]} -ge $MAX_QUEUE_SIZE ]]; do
         for key in "${!running[@]}"; do
-            if ! kill -0 ${running[$key]} &>/dev/null; then
+            if ! kill -0 "${running[$key]}" &>/dev/null; then
                 # Task has finished, report its result and drop it from the queue
-                wait ${running[$key]}
-                ec=$?
+                wait "${running[$key]}" && ec=0 || ec=$?
                 report_result "$key" $ec
                 unset running["$key"]
                 # Break from inner for loop and outer while loop to skip
index 85efeeb741c3428736606145841984f1f569ccb6..8a8ba870e8c4cb54da4b5560277a3cf50ce9a009 100755 (executable)
@@ -1,14 +1,15 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
+set -o pipefail
 
 # Test merging of a --job-mode=ignore-dependencies job into a previously
 # installed job.
 
 systemctl start --no-block hello-after-sleep.target
 
-systemctl list-jobs > /root/list-jobs.txt
+systemctl list-jobs >/root/list-jobs.txt
 while ! grep 'sleep\.service.*running' /root/list-jobs.txt; do
-    systemctl list-jobs > /root/list-jobs.txt
+    systemctl list-jobs >/root/list-jobs.txt
 done
 
 grep 'hello\.service.*waiting' /root/list-jobs.txt
@@ -17,22 +18,22 @@ grep 'hello\.service.*waiting' /root/list-jobs.txt
 START_SEC=$(date -u '+%s')
 systemctl start --job-mode=ignore-dependencies hello
 END_SEC=$(date -u '+%s')
-ELAPSED=$(($END_SEC-$START_SEC))
+ELAPSED=$((END_SEC-START_SEC))
 
-[ "$ELAPSED" -lt 3 ]
+test "$ELAPSED" -lt 3
 
 # sleep should still be running, hello not.
-systemctl list-jobs > /root/list-jobs.txt
+systemctl list-jobs >/root/list-jobs.txt
 grep 'sleep\.service.*running' /root/list-jobs.txt
 grep 'hello\.service' /root/list-jobs.txt && exit 1
 systemctl stop sleep.service hello-after-sleep.target
 
 # Some basic testing that --show-transaction does something useful
-! systemctl is-active systemd-importd
+systemctl is-active systemd-importd && { echo 'unexpected success'; exit 1; }
 systemctl -T start systemd-importd
 systemctl is-active systemd-importd
 systemctl --show-transaction stop systemd-importd
-! systemctl is-active systemd-importd
+systemctl is-active systemd-importd && { echo 'unexpected success'; exit 1; }
 
 # Test for a crash when enqueuing a JOB_NOP when other job already exists
 systemctl start --no-block hello-after-sleep.target
@@ -58,13 +59,13 @@ systemctl stop --job-mode=replace-irreversibly unstoppable.service
 systemctl start unstoppable.service
 
 # Test waiting for a started unit(s) to terminate again
-cat <<EOF >  /run/systemd/system/wait2.service
+cat <<EOF >/run/systemd/system/wait2.service
 [Unit]
 Description=Wait for 2 seconds
 [Service]
 ExecStart=/bin/sh -ec 'sleep 2'
 EOF
-cat <<EOF >  /run/systemd/system/wait5fail.service
+cat <<EOF >/run/systemd/system/wait5fail.service
 [Unit]
 Description=Wait for 5 seconds and fail
 [Service]
@@ -75,14 +76,14 @@ EOF
 START_SEC=$(date -u '+%s')
 systemctl start --wait wait2.service
 END_SEC=$(date -u '+%s')
-ELAPSED=$(($END_SEC-$START_SEC))
+ELAPSED=$((END_SEC-START_SEC))
 [[ "$ELAPSED" -ge 2 ]] && [[ "$ELAPSED" -le 4 ]] || exit 1
 
 # wait5fail fails, so systemctl should fail
 START_SEC=$(date -u '+%s')
-! systemctl start --wait wait2.service wait5fail.service || exit 1
+systemctl start --wait wait2.service wait5fail.service && { echo 'unexpected success'; exit 1; }
 END_SEC=$(date -u '+%s')
-ELAPSED=$(($END_SEC-$START_SEC))
+ELAPSED=$((END_SEC-START_SEC))
 [[ "$ELAPSED" -ge 5 ]] && [[ "$ELAPSED" -le 7 ]] || exit 1
 
 # Test time-limited scopes
@@ -91,7 +92,7 @@ set +e
 systemd-run --scope --property=RuntimeMaxSec=3s sleep 10
 RESULT=$?
 END_SEC=$(date -u '+%s')
-ELAPSED=$(($END_SEC-$START_SEC))
+ELAPSED=$((END_SEC-START_SEC))
 [[ "$ELAPSED" -ge 3 ]] && [[ "$ELAPSED" -le 5 ]] || exit 1
 [[ "$RESULT" -ne 0 ]] || exit 1
 
index 3dce73b778250854dbde499123242101931540c5..7a17e086114d441bcc79ddac2242b05c396b7595 100755 (executable)
@@ -1,20 +1,19 @@
 #!/usr/bin/env bash
-set -x
-set -e
+set -eux
 set -o pipefail
 
 # Test stdout stream
 
 # Skip empty lines
 ID=$(journalctl --new-id128 | sed -n 2p)
->/expected
+>/expected
 printf $'\n\n\n' | systemd-cat -t "$ID" --level-prefix false
 journalctl --sync
 journalctl -b -o cat -t "$ID" >/output
 cmp /expected /output
 
 ID=$(journalctl --new-id128 | sed -n 2p)
->/expected
+>/expected
 printf $'<5>\n<6>\n<7>\n' | systemd-cat -t "$ID" --level-prefix true
 journalctl --sync
 journalctl -b -o cat -t "$ID" >/output
@@ -55,23 +54,23 @@ ID=$(journalctl --new-id128 | sed -n 2p)
 printf $'foo' | systemd-cat -t "$ID" --level-prefix false
 journalctl --sync
 journalctl -b -o export --output-fields=MESSAGE,FOO --output-fields=PRIORITY,MESSAGE -t "$ID" >/output
-[[ `grep -c . /output` -eq 6 ]]
+[[ $(grep -c . /output) -eq 6 ]]
 grep -q '^__CURSOR=' /output
 grep -q '^MESSAGE=foo$' /output
 grep -q '^PRIORITY=6$' /output
-! grep -q '^FOO=' /output
-! grep -q '^SYSLOG_FACILITY=' /output
+grep '^FOO=' /output && { echo 'unexpected success'; exit 1; }
+grep '^SYSLOG_FACILITY=' /output && { echo 'unexpected success'; exit 1; }
 
 # `-b all` negates earlier use of -b (-b and -m are otherwise exclusive)
-journalctl -b -1 -b all -m > /dev/null
+journalctl -b -1 -b all -m >/dev/null
 
 # -b always behaves like -b0
-journalctl -q -b-1 -b0 | head -1 > /expected
-journalctl -q -b-1 -b  | head -1 > /output
+journalctl -q -b-1 -b0 | head -1 >/expected
+journalctl -q -b-1 -b  | head -1 >/output
 cmp /expected /output
 # ... even when another option follows (both of these should fail due to -m)
-{ journalctl -ball -b0 -m 2>&1 || :; } | head -1 > /expected
-{ journalctl -ball -b  -m 2>&1 || :; } | head -1 > /output
+{ journalctl -ball -b0 -m 2>&1 || :; } | head -1 >/expected
+{ journalctl -ball -b  -m 2>&1 || :; } | head -1 >/output
 cmp /expected /output
 
 # https://github.com/systemd/systemd/issues/13708
@@ -83,7 +82,7 @@ journalctl --sync
 # We can drop this grep when https://github.com/systemd/systemd/issues/13937
 # has a fix.
 journalctl -b -o export -t "$ID" --output-fields=_PID | grep '^_PID=' >/output
-[[ `grep -c . /output` -eq 2 ]]
+[[ $(grep -c . /output) -eq 2 ]]
 grep -q "^_PID=$PID" /output
 grep -vq "^_PID=$PID" /output
 
@@ -99,6 +98,11 @@ cmp /expected /output
 [[ $(journalctl -b -o cat -t "$ID" --output-fields=_PID | sort -u | grep -c "^.*$") -eq 3 ]]
 [[ $(journalctl -b -o cat -t "$ID" --output-fields=MESSAGE | grep -Pc "^(This will|usually fail|and be truncated)$") -eq 3 ]]
 
+# test that LogLevelMax can also suppress logging about services, not only by services
+systemctl start silent-success
+journalctl --sync
+[[ -z `journalctl -b -q -u silent-success.service` ]]
+
 # Add new tests before here, the journald restarts below
 # may make tests flappy.
 
index 9168e7279972cbc8efe408d21da842994e14d605..c98d849b08aa0004be48ae3a37a7495f6a209c97 100755 (executable)
@@ -1,6 +1,5 @@
 #!/usr/bin/env bash
-set -x
-set -e
+set -eux
 set -o pipefail
 
 P=/run/systemd/system.conf.d
@@ -19,7 +18,9 @@ systemctl daemon-reload
 [[ "$(systemctl show -P LimitNOFILESoft testsuite-05.service)" = "10000" ]]
 [[ "$(systemctl show -P LimitNOFILE testsuite-05.service)" = "16384" ]]
 
+# shellcheck disable=SC2016
 systemd-run --wait -t bash -c '[[ "$(ulimit -n -S)" = "10000" ]]'
+# shellcheck disable=SC2016
 systemd-run --wait -t bash -c '[[ "$(ulimit -n -H)" = "16384" ]]'
 
 touch /testok
index f9b106da7bdeaaa23f12d8982ca07cd117082c93..f89698ded4171e4ae1b0a45c12b028cce38ce73a 100755 (executable)
@@ -1,6 +1,5 @@
 #!/usr/bin/env bash
-set -x
-set -e
+set -eux
 set -o pipefail
 
 echo 1 >/sys/fs/selinux/enforce || {
index fbb2d1d30a17a813f6ad68f9962bdf25dbc8fa3c..bd1da341acb67b8bf4cef915182d4e06982b0590 100755 (executable)
@@ -1,31 +1,31 @@
 #!/usr/bin/env bash
-set -x
-set -e
+set -eux
+set -o pipefail
 
->/failed
+>/failed
 
-cat <<'EOL' >/lib/systemd/system/my.service
+cat >/lib/systemd/system/my.service <<EOF
 [Service]
 Type=oneshot
 ExecStart=/bin/echo Timer runs me
-EOL
+EOF
 
-cat <<'EOL' >/lib/systemd/system/my.timer
+cat >/lib/systemd/system/my.timer <<EOF
 [Timer]
 OnBootSec=10s
 OnUnitInactiveSec=1h
-EOL
+EOF
 
 systemctl unmask my.timer
 
 systemctl start my.timer
 
 mkdir -p /etc/systemd/system/my.timer.d/
-cat <<'EOL' >/etc/systemd/system/my.timer.d/override.conf
+cat >/etc/systemd/system/my.timer.d/override.conf <<EOF
 [Timer]
 OnBootSec=10s
 OnUnitInactiveSec=1h
-EOL
+EOF
 
 systemctl daemon-reload
 
index 708c7cebb7dea6458206fb8dbbd3543c958b07a3..97ab8be7574e4a342747c38dce71d3f9b5b6b885 100755 (executable)
@@ -1,7 +1,8 @@
 #!/usr/bin/env bash
-set -x
+set -eux
+set -o pipefail
 
-systemctl start fail-on-restart.service
+systemctl --no-block start fail-on-restart.service
 active_state=$(systemctl show --value --property ActiveState fail-on-restart.service)
 while [[ "$active_state" == "activating" || "$active_state" == "active" ]]; do
     sleep 1
index b5888a255bca165f8dd94917342987a19f2e2d3a..c4ee600abe1c96f692e16c92ea66e0a7bbd405d5 100755 (executable)
@@ -1,10 +1,9 @@
 #!/usr/bin/env bash
-set -x
-set -e
+set -eux
 set -o pipefail
 
 U=/run/systemd/system/test12.socket
-cat <<'EOF' >$U
+cat >$U <<EOF
 [Unit]
 Description=Test 12 socket
 [Socket]
@@ -14,7 +13,7 @@ SocketGroup=adm
 SocketMode=0660
 EOF
 
-cat <<'EOF' > /run/systemd/system/test12@.service
+cat >/run/systemd/system/test12@.service <<EOF
 [Unit]
 Description=Test service
 [Service]
index 1844323d2f17f40ac5e339f1190a4ef9be71fd6c..0d468b2db1748ec74b8a0ab773062f2f1e0814c8 100755 (executable)
@@ -1,7 +1,6 @@
 #!/usr/bin/env bash
-set -x
-set -e
-set -u
+# shellcheck disable=SC2016
+set -eux
 set -o pipefail
 
 export SYSTEMD_LOG_LEVEL=debug
@@ -31,10 +30,10 @@ if unshare -U sh -c :; then
     is_user_ns_supported=yes
 fi
 
-SUSE_OPTS=""
+SUSE_OPTS=()
 ID_LIKE=$(awk -F= '$1=="ID_LIKE" { print $2 ;}' /etc/os-release)
 if [[ "$ID_LIKE" = *"suse"* ]]; then
-    SUSE_OPTS="--bind /lib64 --bind /usr/lib64 "
+    SUSE_OPTS+=(--bind /lib64 --bind /usr/lib64)
 fi
 
 function check_bind_tmp_path {
@@ -42,8 +41,8 @@ function check_bind_tmp_path {
     local _root="/var/lib/machines/testsuite-13.bind-tmp-path"
     rm -rf "$_root"
     /usr/lib/systemd/tests/testdata/create-busybox-container "$_root"
-    >/tmp/bind
-    systemd-nspawn $SUSE_OPTS--register=no -D "$_root" --bind=/tmp/bind /bin/sh -c 'test -e /tmp/bind'
+    >/tmp/bind
+    systemd-nspawn "${SUSE_OPTS[@]}" --register=no -D "$_root" --bind=/tmp/bind /bin/sh -c 'test -e /tmp/bind'
 }
 
 function check_norbind {
@@ -51,19 +50,19 @@ function check_norbind {
     local _root="/var/lib/machines/testsuite-13.norbind-path"
     rm -rf "$_root"
     mkdir -p /tmp/binddir/subdir
-    echo -n "outer" > /tmp/binddir/subdir/file
+    echo -n "outer" >/tmp/binddir/subdir/file
     mount -t tmpfs tmpfs /tmp/binddir/subdir
-    echo -n "inner" > /tmp/binddir/subdir/file
+    echo -n "inner" >/tmp/binddir/subdir/file
     /usr/lib/systemd/tests/testdata/create-busybox-container "$_root"
-    systemd-nspawn $SUSE_OPTS--register=no -D "$_root" --bind=/tmp/binddir:/mnt:norbind /bin/sh -c 'CONTENT=$(cat /mnt/subdir/file); if [[ $CONTENT != "outer" ]]; then echo "*** unexpected content: $CONTENT"; return 1; fi'
+    systemd-nspawn "${SUSE_OPTS[@]}" --register=no -D "$_root" --bind=/tmp/binddir:/mnt:norbind /bin/sh -c 'CONTENT=$(cat /mnt/subdir/file); if [[ $CONTENT != "outer" ]]; then echo "*** unexpected content: $CONTENT"; return 1; fi'
 }
 
 function check_notification_socket {
     # https://github.com/systemd/systemd/issues/4944
     local _cmd='echo a | $(busybox which nc) -U -u -w 1 /run/host/notify'
     # /testsuite-13.nc-container is prepared by test.sh
-    systemd-nspawn $SUSE_OPTS--register=no -D /testsuite-13.nc-container /bin/sh -x -c "$_cmd"
-    systemd-nspawn $SUSE_OPTS--register=no -D /testsuite-13.nc-container -U /bin/sh -x -c "$_cmd"
+    systemd-nspawn "${SUSE_OPTS[@]}" --register=no -D /testsuite-13.nc-container /bin/sh -x -c "$_cmd"
+    systemd-nspawn "${SUSE_OPTS[@]}" --register=no -D /testsuite-13.nc-container -U /bin/sh -x -c "$_cmd"
 }
 
 function check_os_release {
@@ -73,19 +72,19 @@ if [ -n "${VERSION_ID:+set}" ] && [ "${VERSION_ID}" != "${container_host_version
 if [ -n "${BUILD_ID:+set}" ] && [ "${BUILD_ID}" != "${container_host_build_id}" ]; then exit 1; fi
 if [ -n "${VARIANT_ID:+set}" ] && [ "${VARIANT_ID}" != "${container_host_variant_id}" ]; then exit 1; fi
 cd /tmp; (cd /run/host; md5sum os-release) | md5sum -c
-if echo test >> /run/host/os-release; then exit 1; fi
+if echo test >>/run/host/os-release; then exit 1; fi
 '
 
     local _os_release_source="/etc/os-release"
-    if [ ! -r "${_os_release_source}" ]; then
+    if [[ ! -r "${_os_release_source}" ]]; then
         _os_release_source="/usr/lib/os-release"
-    elif [ -L "${_os_release_source}" ] && rm /etc/os-release; then
+    elif [[ -L "${_os_release_source}" ]] && rm /etc/os-release; then
         # Ensure that /etc always wins if available
         cp /usr/lib/os-release /etc
-        echo MARKER=1 >> /etc/os-release
+        echo MARKER=1 >>/etc/os-release
     fi
 
-    systemd-nspawn $SUSE_OPTS--register=no -D /testsuite-13.nc-container --bind="${_os_release_source}":/tmp/os-release /bin/sh -x -e -c "$_cmd"
+    systemd-nspawn "${SUSE_OPTS[@]}" --register=no -D /testsuite-13.nc-container --bind="${_os_release_source}":/tmp/os-release /bin/sh -x -e -c "$_cmd"
 
     if grep -q MARKER /etc/os-release; then
         rm /etc/os-release
@@ -96,10 +95,10 @@ if echo test >> /run/host/os-release; then exit 1; fi
 function check_machinectl_bind {
     local _cmd='for i in $(seq 1 20); do if test -f /tmp/marker; then exit 0; fi; sleep 0.5; done; exit 1;'
 
-    cat <<EOF > /run/systemd/system/nspawn_machinectl_bind.service
+    cat >/run/systemd/system/nspawn_machinectl_bind.service <<EOF
 [Service]
 Type=notify
-ExecStart=systemd-nspawn $SUSE_OPTS -D /testsuite-13.nc-container --notify-ready=no /bin/sh -x -e -c "$_cmd"
+ExecStart=systemd-nspawn ${SUSE_OPTS[@]} -D /testsuite-13.nc-container --notify-ready=no /bin/sh -x -e -c "$_cmd"
 EOF
 
     systemctl start nspawn_machinectl_bind.service
@@ -113,7 +112,7 @@ EOF
         sleep 0.1
     done
 
-    return $(systemctl show -P ExecMainStatus nspawn_machinectl_bind.service)
+    return "$(systemctl show -P ExecMainStatus nspawn_machinectl_bind.service)"
 }
 
 function run {
@@ -129,65 +128,54 @@ function run {
     local _root="/var/lib/machines/testsuite-13.unified-$1-cgns-$2-api-vfs-writable-$3"
     rm -rf "$_root"
     /usr/lib/systemd/tests/testdata/create-busybox-container "$_root"
-    SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" -b
-    SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" --private-network -b
+    SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn "${SUSE_OPTS[@]}" --register=no -D "$_root" -b
+    SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn "${SUSE_OPTS[@]}" --register=no -D "$_root" --private-network -b
 
-    if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" -U -b; then
+    if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn "${SUSE_OPTS[@]}" --register=no -D "$_root" -U -b; then
         [[ "$is_user_ns_supported" = "yes" && "$3" = "network" ]] && return 1
     else
         [[ "$is_user_ns_supported" = "no" && "$3" = "network" ]] && return 1
     fi
 
-    if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" --private-network -U -b; then
+    if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn "${SUSE_OPTS[@]}" --register=no -D "$_root" --private-network -U -b; then
         [[ "$is_user_ns_supported" = "yes" && "$3" = "yes" ]] && return 1
     else
         [[ "$is_user_ns_supported" = "no" && "$3" = "yes" ]] && return 1
     fi
 
     local _netns_opt="--network-namespace-path=/proc/self/ns/net"
+    local _net_opts=(
+        "--network-bridge=lo"
+        "--network-interface=lo"
+        "--network-ipvlan=lo"
+        "--network-macvlan=lo"
+        "--network-veth"
+        "--network-veth-extra=lo"
+        "--network-zone=zone"
+    )
 
     # --network-namespace-path and network-related options cannot be used together
-    if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-interface=lo -b; then
-        return 1
-    fi
-
-    if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-macvlan=lo -b; then
-        return 1
-    fi
-
-    if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-ipvlan=lo -b; then
-        return 1
-    fi
-
-    if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-veth -b; then
-        return 1
-    fi
-
-    if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-veth-extra=lo -b; then
-        return 1
-    fi
-
-    if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-bridge=lo -b; then
-        return 1
-    fi
-
-    if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-zone=zone -b; then
-        return 1
-    fi
+    for netopt in "${_net_opts[@]}"; do
+        echo "$_netns_opt in combination with $netopt should fail"
+        if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn "${SUSE_OPTS[@]}" --register=no -D "$_root" -b "$_netns_opt" "$netopt"; then
+            echo >&2 "unexpected pass"
+            return 1
+        fi
+    done
 
     # allow combination of --network-namespace-path and --private-network
-    if ! SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --private-network -b; then
+    if ! SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn "${SUSE_OPTS[@]}" --register=no -D "$_root" -b "$_netns_opt" --private-network; then
         return 1
     fi
 
     # test --network-namespace-path works with a network namespace created by "ip netns"
     ip netns add nspawn_test
     _netns_opt="--network-namespace-path=/run/netns/nspawn_test"
-    SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" /bin/ip a | grep -v -E '^1: lo.*UP'
+    SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn "${SUSE_OPTS[@]}" --register=no -D "$_root" "$_netns_opt" /bin/ip a | grep -v -E '^1: lo.*UP'
     local r=$?
     ip netns del nspawn_test
 
-    if [ $r -ne 0 ]; then
+    if [[ $r -ne 0 ]]; then
         return 1
     fi
 
index 95ac9b65aee779cf684724183a8f2e1049abeed5..7a64d937361916441c8c842be497e388ad5338d4 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
-set -e
-set -x
+set -eux
+set -o pipefail
 
 function setup_root {
     local _root="$1"
@@ -21,18 +21,18 @@ r="$(pwd)/overwrite-broken-machine-id"
 setup_root "$r"
 systemd-machine-id-setup --print --root "$r"
 echo abc >>"$r/etc/machine-id"
-id=$(systemd-machine-id-setup --print --root "$r")
-echo $id >expected
+id="$(systemd-machine-id-setup --print --root "$r")"
+echo "$id" >expected
 check expected "$r/etc/machine-id"
 
-r="$(pwd)/transient-machine-id"
+r="$PWD/transient-machine-id"
 setup_root "$r"
 systemd-machine-id-setup --print --root "$r"
 echo abc >>"$r/etc/machine-id"
 mount -o remount,ro "$r"
 mount -t tmpfs tmpfs "$r/run"
-transient_id=$(systemd-machine-id-setup --print --root "$r")
+transient_id="$(systemd-machine-id-setup --print --root "$r")"
 mount -o remount,rw "$r"
-commited_id=$(systemd-machine-id-setup --print --commit --root "$r")
+commited_id="$(systemd-machine-id-setup --print --commit --root "$r")"
 [[ "$transient_id" = "$commited_id" ]]
 check "$r/etc/machine-id" "$r/run/machine-id"
index 23a39bf09014cd1721a25b83c88d9cda0940dce7..c3784e299d5c8689bc8faa6d31a40075cebba8de 100755 (executable)
@@ -1,56 +1,53 @@
-#! /bin/bash
-set -e
-set -x
+#!/bin/bash
+set -eux
+set -o pipefail
 
 _clear_service () {
-    systemctl stop $1.service 2>/dev/null || :
-    rm -f  /{etc,run,usr/lib}/systemd/system/$1.service
-    rm -fr /{etc,run,usr/lib}/systemd/system/$1.service.d
-    rm -fr /{etc,run,usr/lib}/systemd/system/$1.service.{wants,requires}
-    if [[ $1 == *@ ]]; then
-        systemctl stop $1*.service 2>/dev/null || :
-        rm -f  /{etc,run,usr/lib}/systemd/system/$1*.service
-        rm -fr /{etc,run,usr/lib}/systemd/system/$1*.service.d
-        rm -fr /{etc,run,usr/lib}/systemd/system/$1*.service.{wants,requires}
+    local SERVICE_NAME="${1:?_clear_service: missing argument}"
+    systemctl stop "$SERVICE_NAME.service" 2>/dev/null || :
+    rm -f  /{etc,run,usr/lib}/systemd/system/"$SERVICE_NAME".service
+    rm -fr /{etc,run,usr/lib}/systemd/system/"$SERVICE_NAME".service.d
+    rm -fr /{etc,run,usr/lib}/systemd/system/"$SERVICE_NAME".service.{wants,requires}
+    if [[ $SERVICE_NAME == *@ ]]; then
+        systemctl stop "$SERVICE_NAME"*.service 2>/dev/null || :
+        rm -f  /{etc,run,usr/lib}/systemd/system/"$SERVICE_NAME"*.service
+        rm -fr /{etc,run,usr/lib}/systemd/system/"$SERVICE_NAME"*.service.d
+        rm -fr /{etc,run,usr/lib}/systemd/system/"$SERVICE_NAME"*.service.{wants,requires}
     fi
 }
 
 clear_services () {
-    for u in $*; do
-        _clear_service $u
+    for u in "$@"; do
+        _clear_service "$u"
     done
     systemctl daemon-reload
 }
 
 create_service () {
-    clear_services $1
+    local SERVICE_NAME="${1:?create_service: missing argument}"
+    clear_services "$SERVICE_NAME"
 
-    cat >/etc/systemd/system/$1.service<<EOF
+    cat >/etc/systemd/system/"$SERVICE_NAME".service <<EOF
 [Unit]
-Description=$1 unit
+Description=$SERVICE_NAME unit
 
 [Service]
-ExecStart=/bin/sleep 100000
+ExecStart=sleep 100000
 EOF
-    mkdir -p /{etc,run,usr/lib}/systemd/system/$1.service.d
-    mkdir -p /etc/systemd/system/$1.service.{wants,requires}
-    mkdir -p /run/systemd/system/$1.service.{wants,requires}
-    mkdir -p /usr/lib/systemd/system/$1.service.{wants,requires}
+    mkdir -p /{etc,run,usr/lib}/systemd/system/"$SERVICE_NAME".service.{d,wants,requires}
 }
 
 create_services () {
-    for u in $*; do
-        create_service $u
+    for u in "$@"; do
+        create_service "$u"
     done
 }
 
 check_ok () {
-    [ $# -eq 3 ] || return
-
-    x="$(systemctl show --value -p $2 $1)"
+    x="$(systemctl show --value -p "${2:?}" "${1:?}")"
     case "$x" in
-        *$3*) return 0 ;;
-        *)    return 1 ;;
+        *${3:?}*) return 0 ;;
+        *)        return 1 ;;
     esac
 }
 
@@ -121,7 +118,7 @@ EOF
     check_ok test15-b ExecCondition "/bin/echo test15-b"
     rm -rf /usr/lib/systemd/system/service.d
 
-    clear_services test15-a test15-b test15-c
+    clear_services test15-a test15-b test15-c test15-c1
 }
 
 test_linked_units () {
@@ -151,6 +148,32 @@ test_linked_units () {
     clear_services test15-a test15-b
 }
 
+test_template_alias() {
+    echo "Testing instance alias..."
+    echo "*** forward"
+
+    create_service test15-a@
+    ln -s test15-a@inst.service /etc/systemd/system/test15-b@inst.service  # alias
+
+    check_ok test15-a@inst Names test15-a@inst.service
+    check_ok test15-a@inst Names test15-b@inst.service
+
+    check_ok test15-a@other Names test15-a@other.service
+    check_ko test15-a@other Names test15-b@other.service
+
+    echo "*** reverse"
+
+    systemctl daemon-reload
+
+    check_ok test15-b@inst Names test15-a@inst.service
+    check_ok test15-b@inst Names test15-b@inst.service
+
+    check_ko test15-b@other Names test15-a@other.service
+    check_ok test15-b@other Names test15-b@other.service
+
+    clear_services test15-a@ test15-b@
+}
+
 test_hierarchical_dropins () {
     echo "Testing hierarchical dropins..."
     echo "*** test service.d/ top level drop-in"
@@ -165,7 +188,7 @@ test_hierarchical_dropins () {
         echo "
 [Service]
 ExecCondition=/bin/echo $dropin
-        " > /usr/lib/systemd/system/$dropin/override.conf
+        " >/usr/lib/systemd/system/$dropin/override.conf
         systemctl daemon-reload
         check_ok a-b-c ExecCondition "/bin/echo $dropin"
     done
@@ -493,6 +516,7 @@ test_invalid_dropins () {
 
 test_basic_dropins
 test_linked_units
+test_template_alias
 test_hierarchical_dropins
 test_template_dropins
 test_alias_dropins
index 8388ef7a5d2e3682032235dda5d4e9fc280cdec7..9f3a843da612be21326379a36a74114352ac9b8c 100755 (executable)
@@ -1,25 +1,24 @@
 #!/usr/bin/env bash
-set -v -x
+set -eux
+set -o pipefail
 
 rm -f /test.log
 
-TL=/test.log.XXXXXXXX
+TESTLOG=/test.log.XXXXXXXX
 
 function wait_for()
 {
-    service=${1}
-    result=${2:-success}
-    time=${3:-45}
+    local service="${1:-wait_for: missing service argument}"
+    local result="${2:-success}"
+    local time="${3:-45}"
 
-    while [[ ! -f /${service}.terminated && ! -f /${service}.success && $time -gt 0  ]]
-    do
+    while [[ ! -f /${service}.terminated && ! -f /${service}.success && $time -gt 0 ]]; do
         sleep 1
-        time=$(( $time - 1 ))
+        time=$((time - 1))
     done
 
-    if [[ ! -f /${service}.${result} ]]
-    then
-        journalctl -u ${service/_/-}.service >> "${TL}"
+    if [[ ! -f /${service}.${result} ]]; then
+        journalctl -u "${service/_/-}.service" >>"$TESTLOG"
     fi
 }
 
@@ -44,12 +43,11 @@ wait_for fail_start startfail
 wait_for fail_stop stopfail
 wait_for fail_runtime runtimefail
 
-if [[ -f "${TL}" ]]
-then
+if [[ -f "$TESTLOG" ]]; then
     # no mv
-    cp "${TL}" /test.log
+    cp "$TESTLOG" /test.log
     exit 1
-else
-    touch /testok
-    exit 0
 fi
+
+touch /testok
+exit 0
index 573ad4107916b84ce20b2658fc3c1011c83f4271..3b099fc2a4819901cd82919149c4ed6b104e2e02 100755 (executable)
@@ -19,7 +19,8 @@ while : ; do
     sleep .5
 done
 
-cat > /run/udev/rules.d/50-testsuite.rules <<EOF
+cat >/run/udev/rules.d/50-testsuite.rules <<EOF
+SUBSYSTEM=="block", KERNEL=="sda", OPTIONS="log_level=debug"
 ACTION!="remove", SUBSYSTEM=="block", KERNEL=="sda", ENV{SYSTEMD_WANTS}="foobar.service"
 EOF
 udevadm control --reload
@@ -36,7 +37,8 @@ while : ; do
     sleep .5
 done
 
-cat > /run/udev/rules.d/50-testsuite.rules <<EOF
+cat >/run/udev/rules.d/50-testsuite.rules <<EOF
+SUBSYSTEM=="block", KERNEL=="sda", OPTIONS="log_level=debug"
 ACTION!="remove", SUBSYSTEM=="block", KERNEL=="sda", ENV{SYSTEMD_WANTS}="waldo.service"
 EOF
 udevadm control --reload
index c21fcc781b29af7ed8387103d6059510e9decc7f..b73bd977022f3f5a378d843386760356f8d33c45 100755 (executable)
@@ -4,9 +4,10 @@ set -o pipefail
 
 mkdir -p /run/udev/rules.d/
 
-cat > /run/udev/rules.d/50-testsuite.rules <<EOF
+cat >/run/udev/rules.d/50-testsuite.rules <<EOF
 ACTION=="remove", GOTO="lo_end"
 
+SUBSYSTEM=="net", KERNEL=="lo", OPTIONS="log_level=debug"
 SUBSYSTEM=="net", KERNEL=="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/net/devices/lo"
 
 ACTION!="change", GOTO="lo_end"
index 02ac2176b5ad944d3367a3222cd0fb63ecc50689..fb43aa11f0bdc74e4354129ecf78fd1fe1c9482b 100755 (executable)
@@ -7,9 +7,12 @@ test_rule="/run/udev/rules.d/49-test.rules"
 setup() {
     mkdir -p "${test_rule%/*}"
     cp -f /etc/udev/udev.conf /etc/udev/udev.conf.bckp
-    echo 'KERNEL=="lo", SUBSYSTEM=="net", PROGRAM=="/bin/sleep 60"' > "${test_rule}"
-    echo "event_timeout=30" >> /etc/udev/udev.conf
-    echo "timeout_signal=SIGABRT" >> /etc/udev/udev.conf
+    cat >"${test_rule}" <<EOF
+SUBSYSTEM=="net", KERNEL=="lo", OPTIONS="log_level=debug"
+SUBSYSTEM=="net", KERNEL=="lo", PROGRAM=="/bin/sleep 60"
+EOF
+    echo "event_timeout=30" >>/etc/udev/udev.conf
+    echo "timeout_signal=SIGABRT" >>/etc/udev/udev.conf
 
     systemctl restart systemd-udevd.service
 }
@@ -25,9 +28,9 @@ teardown() {
 run_test() {
     since="$(date +%T)"
 
-    echo add > /sys/class/net/lo/uevent
+    echo add >/sys/class/net/lo/uevent
 
-    for n in {1..20}; do
+    for _ in {1..20}; do
         sleep 5
         if coredumpctl --since "$since" --no-legend --no-pager | grep /bin/udevadm ; then
             return 0
index c799936c0a3b04c61e1f1788f1d83aeba16d39e4..fbe8971732ec58b14a2d0bdf2c2dabd2cee79d60 100755 (executable)
@@ -4,14 +4,12 @@ set -o pipefail
 
 mkdir -p /run/udev/rules.d/
 
-! test -f /run/udev/tags/added/c1:3 &&
-    ! test -f /run/udev/tags/changed/c1:3 &&
-    udevadm info /dev/null | grep -q -v 'E: TAGS=.*:added:.*' &&
-    udevadm info /dev/null | grep -q -v 'E: CURRENT_TAGS=.*:added:.*' &&
-    udevadm info /dev/null | grep -q -v 'E: TAGS=.*:changed:.*' &&
-    udevadm info /dev/null | grep -q -v 'E: CURRENT_TAGS=.*:changed:.*'
+test ! -f /run/udev/tags/added/c1:3
+test ! -f /run/udev/tags/changed/c1:3
+udevadm info /dev/null | grep -E 'E: (TAGS|CURRENT_TAGS)=.*:(added|changed):' && exit 1
 
-cat > /run/udev/rules.d/50-testsuite.rules <<EOF
+cat >/run/udev/rules.d/50-testsuite.rules <<EOF
+SUBSYSTEM=="mem", KERNEL=="null", OPTIONS="log_level=debug"
 ACTION=="add", SUBSYSTEM=="mem", KERNEL=="null", TAG+="added"
 ACTION=="change", SUBSYSTEM=="mem", KERNEL=="null", TAG+="changed"
 EOF
@@ -19,45 +17,39 @@ EOF
 udevadm control --reload
 udevadm trigger -c add /dev/null
 
-while : ; do
-    test -f /run/udev/tags/added/c1:3 &&
-        ! test -f /run/udev/tags/changed/c1:3 &&
-        udevadm info /dev/null | grep -q 'E: TAGS=.*:added:.*' &&
-        udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:added:.*' &&
-        udevadm info /dev/null | grep -q -v 'E: TAGS=.*:changed:.*' &&
-        udevadm info /dev/null | grep -q -v 'E: CURRENT_TAGS=.*:changed:.*' &&
-        break
-
+while   test ! -f /run/udev/tags/added/c1:3 ||
+        test -f /run/udev/tags/changed/c1:3 ||
+        ! udevadm info /dev/null | grep -q 'E: TAGS=.*:added:.*' ||
+        ! udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:added:.*' ||
+        udevadm info /dev/null | grep -q 'E: TAGS=.*:changed:.*' ||
+        udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:changed:.*'
+do
     sleep .5
 done
 
 udevadm control --reload
 udevadm trigger -c change /dev/null
 
-while : ; do
-    test -f /run/udev/tags/added/c1:3 &&
-        test -f /run/udev/tags/changed/c1:3 &&
-        udevadm info /dev/null | grep -q 'E: TAGS=.*:added:.*' &&
-        udevadm info /dev/null | grep -q -v 'E: CURRENT_TAGS=.*:added:.*' &&
-        udevadm info /dev/null | grep -q 'E: TAGS=.*:changed:.*' &&
-        udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:changed:.*' &&
-        break
-
+while   test ! -f /run/udev/tags/added/c1:3 ||
+        test ! -f /run/udev/tags/changed/c1:3 ||
+        ! udevadm info /dev/null | grep -q 'E: TAGS=.*:added:.*' ||
+        udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:added:.*' ||
+        ! udevadm info /dev/null | grep -q 'E: TAGS=.*:changed:.*' ||
+        ! udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:changed:.*'
+do
     sleep .5
 done
 
 udevadm control --reload
 udevadm trigger -c add /dev/null
 
-while : ; do
-    test -f /run/udev/tags/added/c1:3 &&
-        test -f /run/udev/tags/changed/c1:3 &&
-        udevadm info /dev/null | grep -q 'E: TAGS=.*:added:.*' &&
-        udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:added:.*' &&
-        udevadm info /dev/null | grep -q 'E: TAGS=.*:changed:.*' &&
-        udevadm info /dev/null | grep -q -v 'E: CURRENT_TAGS=.*:changed:.*' &&
-        break
-
+while   test ! -f /run/udev/tags/added/c1:3 ||
+        test ! -f /run/udev/tags/changed/c1:3 ||
+        ! udevadm info /dev/null | grep -q 'E: TAGS=.*:added:.*' ||
+        ! udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:added:.*' ||
+        ! udevadm info /dev/null | grep -q 'E: TAGS=.*:changed:.*' ||
+        udevadm info /dev/null | grep -q 'E: CURRENT_TAGS=.*:changed:.*'
+do
     sleep .5
 done
 
index 0991ec9d590d71d26d32284a793b998e2bc4aea5..1e7f7f41b0a5d0de7f4fa95d540e802a7bc0ab1f 100755 (executable)
@@ -4,7 +4,7 @@ set -o pipefail
 
 mkdir -p /run/udev/rules.d/
 
-cat > /run/udev/rules.d/50-testsuite.rules <<EOF
+cat >/run/udev/rules.d/50-testsuite.rules <<EOF
 SUBSYSTEM=="mem", KERNEL=="null", OPTIONS="log_level=debug"
 ACTION=="add", SUBSYSTEM=="mem", KERNEL=="null", IMPORT{program}="/bin/echo -e HOGE=aa\\\\x20\\\\x20\\\\x20bb\nFOO=\\\\x20aaa\\\\x20\n\n\n"
 EOF
diff --git a/test/units/testsuite-17.06.sh b/test/units/testsuite-17.06.sh
new file mode 100755 (executable)
index 0000000..68c1f7b
--- /dev/null
@@ -0,0 +1,75 @@
+#!/bin/bash
+set -ex
+set -o pipefail
+
+# tests for udev watch
+
+function check_validity() {
+    local f ID_OR_HANDLE
+
+    for f in /run/udev/watch/*; do
+        ID_OR_HANDLE=$(readlink $f)
+        test -L /run/udev/watch/${ID_OR_HANDLE}
+        test $(readlink /run/udev/watch/${ID_OR_HANDLE}) = $(basename $f)
+    done
+}
+
+function check() {
+    local i j
+
+    for ((i=0;i<2;i++)); do
+        systemctl restart systemd-udevd.service
+        udevadm control --ping
+        udevadm settle
+        sleep 1
+        check_validity
+
+        for ((j=0;j<2;j++)); do
+            udevadm trigger -w --action add --subsystem-match=block
+            udevadm settle
+            sleep 1
+            check_validity
+        done
+
+        for ((j=0;j<2;j++)); do
+            udevadm trigger -w --action change --subsystem-match=block
+            udevadm settle
+            sleep 1
+            check_validity
+        done
+    done
+}
+
+mkdir -p /run/udev/rules.d/
+
+cat >/run/udev/rules.d/00-debug.rules <<EOF
+SUBSYSTEM=="block", KERNEL=="sda*", OPTIONS="log_level=debug"
+EOF
+
+cat >/run/udev/rules.d/50-testsuite.rules <<EOF
+ACTION=="add", SUBSYSTEM=="block", KERNEL=="sda", OPTIONS:="watch"
+EOF
+
+check
+
+MAJOR=$(udevadm info /dev/sda | grep -e '^E: MAJOR=' | sed -e 's/^E: MAJOR=//')
+MINOR=$(udevadm info /dev/sda | grep -e '^E: MINOR=' | sed -e 's/^E: MINOR=//')
+test -L /run/udev/watch/b${MAJOR}:${MINOR}
+
+cat >/run/udev/rules.d/50-testsuite.rules <<EOF
+ACTION=="change", SUBSYSTEM=="block", KERNEL=="sda", OPTIONS:="nowatch"
+EOF
+
+check
+
+MAJOR=$(udevadm info /dev/sda | grep -e '^E: MAJOR=' | sed -e 's/^E: MAJOR=//')
+MINOR=$(udevadm info /dev/sda | grep -e '^E: MINOR=' | sed -e 's/^E: MINOR=//')
+test ! -e /run/udev/watch/b${MAJOR}:${MINOR}
+
+rm /run/udev/rules.d/00-debug.rules
+rm /run/udev/rules.d/50-testsuite.rules
+
+udevadm control --reload
+udevadm trigger -w --action add --subsystem-match=block
+
+exit 0
index afce85aceb9bcf11cc3f671538ef4fdf93daf3f1..92ff7b56a6b5fe9a8aba913f407631ffd8f1ff81 100755 (executable)
@@ -1,12 +1,14 @@
 #!/usr/bin/env bash
 
-set -x
-set -e
+set -eux
+set -o pipefail
 
->/failed
+>/failed
 
-for t in ${0%.sh}.*.sh; do
-    echo "Running $t"; ./$t
+udevadm settle
+
+for t in "${0%.sh}".*.sh; do
+    echo "Running $t"; ./"$t"
 done
 
 touch /testok
index e471cda51b58e46940c25cc6e17757919483c7f1..fe4f9ce5e0eda055d8fb4f5519a2bb204dac2adc 100755 (executable)
@@ -1,15 +1,15 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 systemd-run --wait -p FailureAction=poweroff true
-! systemd-run --wait -p SuccessAction=poweroff false
+systemd-run --wait -p SuccessAction=poweroff false && { echo 'unexpected success'; exit 1; }
 
 if ! test -f /firstphase ; then
-    echo OK > /firstphase
+    echo OK >/firstphase
     systemd-run --wait -p SuccessAction=reboot true
 else
-    echo OK > /testok
+    echo OK >/testok
     systemd-run --wait -p FailureAction=poweroff false
 fi
 
index 57831c267f6d976237913c2c1229a7fdb1c559d7..8ea89e6cfe8d5ef09f68c99cf9166813e9646aa7 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 if grep -q cgroup2 /proc/filesystems ; then
@@ -34,6 +34,6 @@ else
     echo "Skipping TEST-19-DELEGATE, as the kernel doesn't actually support cgroup v2" >&2
 fi
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index d94f6b2afbcbbfcb22cc4c89624215ad738eaa46..7876a9d10c3b4171076f164f48eb272e5ab2395f 100755 (executable)
@@ -1,11 +1,11 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 systemd-analyze log-level debug
 systemd-analyze log-target console
 
-test `systemctl show -P MainPID testsuite-20.service` -eq $$
+test "$(systemctl show -P MainPID testsuite-20.service)" -eq $$
 
 # Start a test process inside of our own cgroup
 sleep infinity &
@@ -14,45 +14,45 @@ disown
 
 # Start a test process outside of our own cgroup
 systemd-run -p DynamicUser=1 --unit=test20-sleep.service /bin/sleep infinity
-EXTERNALPID=`systemctl show -P MainPID test20-sleep.service`
+EXTERNALPID="$(systemctl show -P MainPID test20-sleep.service)"
 
 # Update our own main PID to the external test PID, this should work
-systemd-notify MAINPID=$EXTERNALPID
-test `systemctl show -P MainPID testsuite-20.service` -eq $EXTERNALPID
+systemd-notify MAINPID="$EXTERNALPID"
+test "$(systemctl show -P MainPID testsuite-20.service)" -eq "$EXTERNALPID"
 
 # Update our own main PID to the internal test PID, this should work, too
 systemd-notify MAINPID=$INTERNALPID
-test `systemctl show -P MainPID testsuite-20.service` -eq $INTERNALPID
+test "$(systemctl show -P MainPID testsuite-20.service)" -eq "$INTERNALPID"
 
 # Update it back to our own PID, this should also work
 systemd-notify MAINPID=$$
-test `systemctl show -P MainPID testsuite-20.service` -eq $$
+test "$(systemctl show -P MainPID testsuite-20.service)" -eq $$
 
 # Try to set it to PID 1, which it should ignore, because that's the manager
 systemd-notify MAINPID=1
-test `systemctl show -P MainPID testsuite-20.service` -eq $$
+test "$(systemctl show -P MainPID testsuite-20.service)" -eq $$
 
 # Try to set it to PID 0, which is invalid and should be ignored
 systemd-notify MAINPID=0
-test `systemctl show -P MainPID testsuite-20.service` -eq $$
+test "$(systemctl show -P MainPID testsuite-20.service)" -eq $$
 
 # Try to set it to a valid but non-existing PID, which should be ignored. (Note
 # that we set the PID to a value well above any known /proc/sys/kernel/pid_max,
 # which means we can be pretty sure it doesn't exist by coincidence)
 systemd-notify MAINPID=1073741824
-test `systemctl show -P MainPID testsuite-20.service` -eq $$
+test "$(systemctl show -P MainPID testsuite-20.service)" -eq $$
 
 # Change it again to the external PID, without privileges this time. This should be ignored, because the PID is from outside of our cgroup and we lack privileges.
-systemd-notify --uid=1000 MAINPID=$EXTERNALPID
-test `systemctl show -P MainPID testsuite-20.service` -eq $$
+systemd-notify --uid=1000 MAINPID="$EXTERNALPID"
+test "$(systemctl show -P MainPID testsuite-20.service)" -eq $$
 
 # Change it again to the internal PID, without privileges this time. This should work, as the process is on our cgroup, and that's enough even if we lack privileges.
-systemd-notify --uid=1000 MAINPID=$INTERNALPID
-test `systemctl show -P MainPID testsuite-20.service` -eq $INTERNALPID
+systemd-notify --uid=1000 MAINPID="$INTERNALPID"
+test "$(systemctl show -P MainPID testsuite-20.service)" -eq "$INTERNALPID"
 
 # Update it back to our own PID, this should also work
 systemd-notify --uid=1000 MAINPID=$$
-test `systemctl show -P MainPID testsuite-20.service` -eq $$
+test "$(systemctl show -P MainPID testsuite-20.service)" -eq $$
 
 cat >/tmp/test20-mainpid.sh <<EOF
 #!/usr/bin/env bash
@@ -71,12 +71,12 @@ disown
 sleep infinity &
 disown
 
-echo \$MAINPID > /run/mainpidsh/pid
+echo \$MAINPID >/run/mainpidsh/pid
 EOF
 chmod +x /tmp/test20-mainpid.sh
 
 systemd-run --unit=test20-mainpidsh.service -p StandardOutput=tty -p StandardError=tty -p Type=forking -p RuntimeDirectory=mainpidsh -p PIDFile=/run/mainpidsh/pid /tmp/test20-mainpid.sh
-test `systemctl show -P MainPID test20-mainpidsh.service` -eq `cat /run/mainpidsh/pid`
+test "$(systemctl show -P MainPID test20-mainpidsh.service)" -eq "$(cat /run/mainpidsh/pid)"
 
 cat >/tmp/test20-mainpid2.sh <<EOF
 #!/usr/bin/env bash
@@ -95,13 +95,13 @@ disown
 sleep infinity &
 disown
 
-echo \$MAINPID > /run/mainpidsh2/pid
+echo \$MAINPID >/run/mainpidsh2/pid
 chown 1001:1001 /run/mainpidsh2/pid
 EOF
 chmod +x /tmp/test20-mainpid2.sh
 
 systemd-run --unit=test20-mainpidsh2.service -p StandardOutput=tty -p StandardError=tty -p Type=forking -p RuntimeDirectory=mainpidsh2 -p PIDFile=/run/mainpidsh2/pid /tmp/test20-mainpid2.sh
-test `systemctl show -P MainPID test20-mainpidsh2.service` -eq `cat /run/mainpidsh2/pid`
+test "$(systemctl show -P MainPID test20-mainpidsh2.service)" -eq "$(cat /run/mainpidsh2/pid)"
 
 cat >/dev/shm/test20-mainpid3.sh <<EOF
 #!/usr/bin/env bash
@@ -126,14 +126,24 @@ test -f /run/mainpidsh3/pid
 EOF
 chmod 755 /dev/shm/test20-mainpid3.sh
 
-# This has to fail, as we shouldn't accept the dangerous PID file, and then inotify-wait on it to be corrected which we never do
-! systemd-run --unit=test20-mainpidsh3.service -p StandardOutput=tty -p StandardError=tty -p Type=forking -p RuntimeDirectory=mainpidsh3 -p PIDFile=/run/mainpidsh3/pid -p DynamicUser=1 -p TimeoutStartSec=2s /dev/shm/test20-mainpid3.sh
+# This has to fail, as we shouldn't accept the dangerous PID file, and then
+# inotify-wait on it to be corrected which we never do.
+systemd-run --unit=test20-mainpidsh3.service \
+            -p StandardOutput=tty \
+            -p StandardError=tty \
+            -p Type=forking \
+            -p RuntimeDirectory=mainpidsh3 \
+            -p PIDFile=/run/mainpidsh3/pid \
+            -p DynamicUser=1 \
+            -p TimeoutStartSec=2s \
+            /dev/shm/test20-mainpid3.sh \
+    && { echo 'unexpected success'; exit 1; }
 
 # Test that this failed due to timeout, and not some other error
-test `systemctl show -P Result test20-mainpidsh3.service` = timeout
+test "$(systemctl show -P Result test20-mainpidsh3.service)" = timeout
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index d233e37fb2177c39cdff4fb86d71fd2ddf621d09..7975980799611bf3167f8810b8ae5631db0fa41b 100755 (executable)
@@ -1,13 +1,14 @@
-#! /bin/bash
+#!/bin/bash
 #
 # With "e" don't attempt to set permissions when file doesn't exist, see
 # https://github.com/systemd/systemd/pull/6682.
 #
 
-set -e
+set -eux
+set -o pipefail
 
 rm -fr /tmp/test
 
 echo "e /tmp/test - root root 1d" | systemd-tmpfiles --create -
 
-! test -e /tmp/test
+test ! -e /tmp/test
index d1bf1ea04b9d77c8a12b54443c524a3c45cd3c0e..94fa11ba8861e239a244a859b95ecd1218203b78 100755 (executable)
@@ -1,10 +1,10 @@
-#! /bin/bash
+#!/bin/bash
 #
 # Basic tests for types creating directories
 #
 
-set -e
-set -x
+set -eux
+set -o pipefail
 
 rm -fr /tmp/{C,d,D,e}
 mkdir  /tmp/{C,d,D,e}
@@ -21,10 +21,10 @@ d     /tmp/d/2    0755 daemon daemon - -
 EOF
 
 test -d /tmp/d/1
-test $(stat -c %U:%G:%a /tmp/d/1) = "daemon:daemon:755"
+test "$(stat -c %U:%G:%a /tmp/d/1)" = "daemon:daemon:755"
 
 test -d /tmp/d/2
-test $(stat -c %U:%G:%a /tmp/d/2) = "daemon:daemon:755"
+test "$(stat -c %U:%G:%a /tmp/d/2)" = "daemon:daemon:755"
 
 #
 # 'D'
@@ -39,10 +39,10 @@ D     /tmp/D/2    0755 daemon daemon - -
 EOF
 
 test -d /tmp/D/1
-test $(stat -c %U:%G:%a /tmp/D/1) = "daemon:daemon:755"
+test "$(stat -c %U:%G:%a /tmp/D/1)" = "daemon:daemon:755"
 
 test -d /tmp/D/2
-test $(stat -c %U:%G:%a /tmp/D/2) = "daemon:daemon:755"
+test "$(stat -c %U:%G:%a /tmp/D/2)" = "daemon:daemon:755"
 
 systemd-tmpfiles --remove - <<EOF
 D     /tmp/D/2    0755 daemon daemon - -
@@ -63,15 +63,15 @@ e     /tmp/e/1     0755 daemon daemon - -
 e     /tmp/e/2/*   0755 daemon daemon - -
 EOF
 
-! test -d /tmp/e/1
+test ! -d /tmp/e/1
 
 test -d /tmp/e/2
-test $(stat -c %U:%G:%a /tmp/e/2) = "root:root:777"
+test "$(stat -c %U:%G:%a /tmp/e/2)" = "root:root:777"
 
 test -d /tmp/e/2/d1
-test $(stat -c %U:%G:%a /tmp/e/2/d1) = "daemon:daemon:755"
+test "$(stat -c %U:%G:%a /tmp/e/2/d1)" = "daemon:daemon:755"
 test -d /tmp/e/2/d2
-test $(stat -c %U:%G:%a /tmp/e/2/d2) = "daemon:daemon:755"
+test "$(stat -c %U:%G:%a /tmp/e/2/d2)" = "daemon:daemon:755"
 
 # 'e' operates on directories only
 mkdir -p /tmp/e/3/{d1,d2}
@@ -80,19 +80,19 @@ chmod 777 /tmp/e/3/d*
 touch /tmp/e/3/f1
 chmod 644 /tmp/e/3/f1
 
-systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF
 e     /tmp/e/3/*   0755 daemon daemon - -
 EOF
 
 # the directories should have been processed although systemd-tmpfiles failed
 # previously due to the presence of a file.
 test -d /tmp/e/3/d1
-test $(stat -c %U:%G:%a /tmp/e/3/d1) = "daemon:daemon:755"
+test "$(stat -c %U:%G:%a /tmp/e/3/d1)" = "daemon:daemon:755"
 test -d /tmp/e/3/d2
-test $(stat -c %U:%G:%a /tmp/e/3/d2) = "daemon:daemon:755"
+test "$(stat -c %U:%G:%a /tmp/e/3/d2)" = "daemon:daemon:755"
 
 test -f /tmp/e/3/f1
-test $(stat -c %U:%G:%a /tmp/e/3/f1) = "root:root:644"
+test "$(stat -c %U:%G:%a /tmp/e/3/f1)" = "root:root:644"
 
 #
 # 'C'
@@ -111,12 +111,12 @@ C     /tmp/C/2    0755 daemon daemon - /tmp/C/2-origin
 EOF
 
 test -d /tmp/C/1
-test $(stat -c %U:%G:%a /tmp/C/1/f1) = "daemon:daemon:755"
+test "$(stat -c %U:%G:%a /tmp/C/1/f1)" = "daemon:daemon:755"
 test -d /tmp/C/2
-test $(stat -c %U:%G:%a /tmp/C/2/f1) = "daemon:daemon:755"
+test "$(stat -c %U:%G:%a /tmp/C/2/f1)" = "daemon:daemon:755"
 
-systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF
 C     /tmp/C/3    0755 daemon daemon - /tmp/C/3-origin
 EOF
 
-test $(stat -c %U:%G:%a /tmp/C/3/f1) = "root:root:644"
+test "$(stat -c %U:%G:%a /tmp/C/3/f1)" = "root:root:644"
index 8d009fb5bb96bde6e73d39fa73e101033951d171..1ed026eb709d324edc8af53a209623603eaf350a 100755 (executable)
@@ -1,10 +1,10 @@
-#! /bin/bash
+#!/bin/bash
 #
 # Basic tests for types creating/writing files
 #
 
-set -e
-set -x
+set -eux
+set -o pipefail
 
 rm -fr /tmp/{f,F,w}
 mkdir  /tmp/{f,F,w}
@@ -19,10 +19,10 @@ f     /tmp/f/2    0644 - - - This string should be written
 EOF
 
 ### '1' should exist and be empty
-test -f /tmp/f/1; ! test -s /tmp/f/1
-test $(stat -c %U:%G:%a /tmp/f/1) = "root:root:644"
+test -f /tmp/f/1; test ! -s /tmp/f/1
+test "$(stat -c %U:%G:%a /tmp/f/1)" = "root:root:644"
 
-test $(stat -c %U:%G:%a /tmp/f/2) = "root:root:644"
+test "$(stat -c %U:%G:%a /tmp/f/2)" = "root:root:644"
 test "$(< /tmp/f/2)" = "This string should be written"
 
 ### The perms are supposed to be updated even if the file already exists.
@@ -31,31 +31,31 @@ f     /tmp/f/1    0666 daemon daemon - This string should not be written
 EOF
 
 # file should be empty
-! test -s /tmp/f/1
-test $(stat -c %U:%G:%a /tmp/f/1) = "daemon:daemon:666"
+test ! -s /tmp/f/1
+test "$(stat -c %U:%G:%a /tmp/f/1)" = "daemon:daemon:666"
 
 ### But we shouldn't try to set perms on an existing file which is not a
 ### regular one.
 mkfifo /tmp/f/fifo
 chmod 644 /tmp/f/fifo
 
-! systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 f     /tmp/f/fifo    0666 daemon daemon - This string should not be written
 EOF
 
 test -p /tmp/f/fifo
-test $(stat -c %U:%G:%a /tmp/f/fifo) = "root:root:644"
+test "$(stat -c %U:%G:%a /tmp/f/fifo)" = "root:root:644"
 
 ### 'f' should not follow symlinks.
 ln -s missing /tmp/f/dangling
 ln -s /tmp/file-owned-by-root /tmp/f/symlink
 
-! systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 f     /tmp/f/dangling    0644 daemon daemon - -
 f     /tmp/f/symlink     0644 daemon daemon - -
 EOF
-! test -e /tmp/f/missing
-test $(stat -c %U:%G:%a /tmp/file-owned-by-root) = "root:root:644"
+test ! -e /tmp/f/missing
+test "$(stat -c %U:%G:%a /tmp/file-owned-by-root)" = "root:root:644"
 
 ### Handle read-only filesystem gracefully: we shouldn't fail if the target
 ### already exists and have the correct perms.
@@ -70,27 +70,27 @@ mount -o bind,ro /tmp/f/rw-fs /tmp/f/ro-fs
 systemd-tmpfiles --create - <<EOF
 f     /tmp/f/ro-fs/foo    0644 - - - - This string should not be written
 EOF
-test -f /tmp/f/ro-fs/foo; ! test -s /tmp/f/ro-fs/foo
+test -f /tmp/f/ro-fs/foo; test ! -s /tmp/f/ro-fs/foo
 
-! systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 f     /tmp/f/ro-fs/foo    0666 - - - -
 EOF
-test $(stat -c %U:%G:%a /tmp/f/fifo) = "root:root:644"
+test "$(stat -c %U:%G:%a /tmp/f/fifo)" = "root:root:644"
 
-! systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 f     /tmp/f/ro-fs/bar    0644 - - - -
 EOF
-! test -e /tmp/f/ro-fs/bar
+test ! -e /tmp/f/ro-fs/bar
 
 ### 'f' shouldn't follow unsafe paths.
 mkdir /tmp/f/daemon
 ln -s /root /tmp/f/daemon/unsafe-symlink
 chown -R --no-dereference daemon:daemon /tmp/f/daemon
 
-! systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 f     /tmp/f/daemon/unsafe-symlink/exploit    0644 daemon daemon - -
 EOF
-! test -e /tmp/f/daemon/unsafe-symlink/exploit
+test ! -e /tmp/f/daemon/unsafe-symlink/exploit
 
 #
 # 'F'
@@ -105,19 +105,19 @@ F     /tmp/F/truncated              0666 daemon daemon - -
 F     /tmp/F/truncated-with-content 0666 daemon daemon - new content
 EOF
 
-test -f /tmp/F/created; ! test -s /tmp/F/created
+test -f /tmp/F/created; test ! -s /tmp/F/created
 test -f /tmp/F/created-with-content
 test "$(< /tmp/F/created-with-content)" = "new content"
-test -f /tmp/F/truncated; ! test -s /tmp/F/truncated
-test $(stat -c %U:%G:%a /tmp/F/truncated) = "daemon:daemon:666"
+test -f /tmp/F/truncated; test ! -s /tmp/F/truncated
+test "$(stat -c %U:%G:%a /tmp/F/truncated)" = "daemon:daemon:666"
 test -s /tmp/F/truncated-with-content
-test $(stat -c %U:%G:%a /tmp/F/truncated-with-content) = "daemon:daemon:666"
+test "$(stat -c %U:%G:%a /tmp/F/truncated-with-content)" = "daemon:daemon:666"
 
 ### We shouldn't try to truncate anything but regular files since the behavior is
 ### unspecified in the other cases.
 mkfifo /tmp/F/fifo
 
-! systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 F     /tmp/F/fifo                0644 - - - -
 EOF
 
@@ -127,12 +127,12 @@ test -p /tmp/F/fifo
 ln -s missing /tmp/F/dangling
 ln -s /tmp/file-owned-by-root /tmp/F/symlink
 
-! systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 f     /tmp/F/dangling    0644 daemon daemon - -
 f     /tmp/F/symlink     0644 daemon daemon - -
 EOF
-! test -e /tmp/F/missing
-test $(stat -c %U:%G:%a /tmp/file-owned-by-root) = "root:root:644"
+test ! -e /tmp/F/missing
+test "$(stat -c %U:%G:%a /tmp/file-owned-by-root)" = "root:root:644"
 
 ### Handle read-only filesystem gracefully: we shouldn't fail if the target
 ### already exists and is empty.
@@ -147,40 +147,41 @@ mount -o bind,ro /tmp/F/rw-fs /tmp/F/ro-fs
 systemd-tmpfiles --create - <<EOF
 F     /tmp/F/ro-fs/foo    0644 - - - -
 EOF
-test -f /tmp/F/ro-fs/foo; ! test -s /tmp/F/ro-fs/foo
+test -f /tmp/F/ro-fs/foo; test ! -s /tmp/F/ro-fs/foo
 
 echo "truncating is not allowed anymore" >/tmp/F/rw-fs/foo
-! systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 F     /tmp/F/ro-fs/foo    0644 - - - -
 EOF
 
-! systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 F     /tmp/F/ro-fs/foo    0644 - - - - This string should not be written
 EOF
-test -f /tmp/F/ro-fs/foo; ! test -s /tmp/F/ro-fs/foo
+test -f /tmp/F/ro-fs/foo
+grep -q 'truncating is not allowed' /tmp/F/ro-fs/foo
 
 # Trying to change the perms should fail.
->/tmp/F/rw-fs/foo
-! systemd-tmpfiles --create - <<EOF
+>/tmp/F/rw-fs/foo
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 F     /tmp/F/ro-fs/foo    0666 - - - -
 EOF
-test $(stat -c %U:%G:%a /tmp/F/ro-fs/foo) = "root:root:644"
+test "$(stat -c %U:%G:%a /tmp/F/ro-fs/foo)" = "root:root:644"
 
 ### Try to create a new file.
-! systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 F     /tmp/F/ro-fs/bar    0644 - - - -
 EOF
-! test -e /tmp/F/ro-fs/bar
+test ! -e /tmp/F/ro-fs/bar
 
 ### 'F' shouldn't follow unsafe paths.
 mkdir /tmp/F/daemon
 ln -s /root /tmp/F/daemon/unsafe-symlink
 chown -R --no-dereference daemon:daemon /tmp/F/daemon
 
-! systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 F     /tmp/F/daemon/unsafe-symlink/exploit    0644 daemon daemon - -
 EOF
-! test -e /tmp/F/daemon/unsafe-symlink/exploit
+test ! -e /tmp/F/daemon/unsafe-symlink/exploit
 
 #
 # 'w'
@@ -191,10 +192,10 @@ touch /tmp/w/overwritten
 systemd-tmpfiles --create - <<EOF
 w     /tmp/w/unexistent    0644 - - - new content
 EOF
-! test -e /tmp/w/unexistent
+test ! -e /tmp/w/unexistent
 
 ### no argument given -> fails.
-! systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 w     /tmp/w/unexistent    0644 - - - -
 EOF
 
@@ -230,7 +231,7 @@ mkdir /tmp/w/daemon
 ln -s /root /tmp/w/daemon/unsafe-symlink
 chown -R --no-dereference daemon:daemon /tmp/w/daemon
 
-! systemd-tmpfiles --create - <<EOF
+systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
 f     /tmp/w/daemon/unsafe-symlink/exploit    0644 daemon daemon - -
 EOF
-! test -e /tmp/w/daemon/unsafe-symlink/exploit
+test ! -e /tmp/w/daemon/unsafe-symlink/exploit
index f916086b1edf47f59e82a5887cfa42282b411bc5..d814ed87867308d1453a8fa33169be73a490beb2 100755 (executable)
@@ -1,10 +1,10 @@
-#! /bin/bash
+#!/bin/bash
 #
 # Basic tests for types creating fifos
 #
 
-set -e
-set -x
+set -eux
+set -o pipefail
 
 rm -fr /tmp/p
 mkdir  /tmp/p
@@ -15,10 +15,10 @@ p     /tmp/p/fifo1    0666 - - - -
 EOF
 
 test -p /tmp/p/fifo1
-test $(stat -c %U:%G:%a /tmp/p/fifo1) = "root:root:666"
+test "$(stat -c %U:%G:%a /tmp/p/fifo1)" = "root:root:666"
 
-# it should refuse to overwrite an existing file
-systemd-tmpfiles --create - <<EOF
+# Refuse to overwrite an existing file. Error is not propagated.
+systemd-tmpfiles --create - <<EOF
 p     /tmp/p/f1    0666 - - - -
 EOF
 
@@ -30,7 +30,7 @@ p+     /tmp/p/f1    0666 - - - -
 EOF
 
 test -p /tmp/p/f1
-test $(stat -c %U:%G:%a /tmp/p/f1) = "root:root:666"
+test "$(stat -c %U:%G:%a /tmp/p/f1)" = "root:root:666"
 
 #
 # Must be fixed
index 13c4ac80fc4f15c1ab1b5f214a573467519e5f84..eaabbc4517c8e59ece250e9efcd370b81ac43378 100755 (executable)
@@ -1,7 +1,7 @@
 #! /bin/bash
 
-set -e
-set -x
+set -eux
+set -o pipefail
 
 rm -fr /tmp/{z,Z}
 mkdir  /tmp/{z,Z}
@@ -17,15 +17,15 @@ z     /tmp/z/f1    0755 daemon daemon - -
 z     /tmp/z/d1    0755 daemon daemon - -
 EOF
 
-test $(stat -c %U:%G /tmp/z/f1) = "daemon:daemon"
-test $(stat -c %U:%G /tmp/z/d1) = "daemon:daemon"
-test $(stat -c %U:%G /tmp/z/d1/f11) = "root:root"
+test "$(stat -c %U:%G /tmp/z/f1)" = "daemon:daemon"
+test "$(stat -c %U:%G /tmp/z/d1)" = "daemon:daemon"
+test "$(stat -c %U:%G /tmp/z/d1/f11)" = "root:root"
 
 systemd-tmpfiles --create - <<EOF
 z     /tmp/z/d2/*    0755 daemon daemon - -
 EOF
 
-test $(stat -c %U:%G /tmp/z/d2/f21) = "daemon:daemon"
+test "$(stat -c %U:%G /tmp/z/d2/f21)" = "daemon:daemon"
 
 #
 # 'Z'
@@ -38,8 +38,8 @@ Z     /tmp/Z/f1    0755 daemon daemon - -
 Z     /tmp/Z/d1    0755 daemon daemon - -
 EOF
 
-test $(stat -c %U:%G /tmp/Z/f1) = "daemon:daemon"
-test $(stat -c %U:%G /tmp/Z/d1) = "daemon:daemon"
-test $(stat -c %U:%G /tmp/Z/d1/d11) = "daemon:daemon"
-test $(stat -c %U:%G /tmp/Z/d1/f11) = "daemon:daemon"
-test $(stat -c %U:%G /tmp/Z/d1/d11/f111) = "daemon:daemon"
+test "$(stat -c %U:%G /tmp/Z/f1)" = "daemon:daemon"
+test "$(stat -c %U:%G /tmp/Z/d1)" = "daemon:daemon"
+test "$(stat -c %U:%G /tmp/Z/d1/d11)" = "daemon:daemon"
+test "$(stat -c %U:%G /tmp/Z/d1/f11)" = "daemon:daemon"
+test "$(stat -c %U:%G /tmp/Z/d1/d11/f111)" = "daemon:daemon"
index cd65ba6726508ef4ee8de1c072956f8f12c49148..ce5b1bf69813d0bdf1727d7ffbbe2654b884eb26 100755 (executable)
@@ -1,9 +1,10 @@
-#! /bin/bash
+#!/bin/bash
 #
 # Inspired by https://github.com/systemd/systemd/issues/9508
 #
 
-set -e
+set -eux
+set -o pipefail
 
 test_snippet() {
         systemd-tmpfiles "$@" - <<EOF
@@ -18,8 +19,8 @@ test -d /var/tmp/foobar-test-06
 test -d /var/tmp/foobar-test-06/important
 
 test_snippet --remove
-! test -f /var/tmp/foobar-test-06
-! test -f /var/tmp/foobar-test-06/important
+test ! -f /var/tmp/foobar-test-06
+test ! -f /var/tmp/foobar-test-06/important
 
 test_snippet --create
 test -d /var/tmp/foobar-test-06
@@ -35,4 +36,4 @@ test -f /var/tmp/foobar-test-06/something-else
 test_snippet --create --remove
 test -d /var/tmp/foobar-test-06
 test -d /var/tmp/foobar-test-06/important
-! test -f /var/tmp/foobar-test-06/something-else
+test ! -f /var/tmp/foobar-test-06/something-else
index 39c04b925cf67645ca32fb7dcd4f7ddd8328af90..8d61032d277bf7d3866d3d69f4b59c7f152fb713 100755 (executable)
@@ -1,10 +1,10 @@
-#! /bin/bash
+#!/bin/bash
 #
 # Verifies the issues described by https://github.com/systemd/systemd/issues/10191
 #
 
-set -e
-set -x
+set -eux
+set -o pipefail
 
 rm -rf /tmp/test-prefix
 
@@ -16,8 +16,8 @@ r /tmp/test-prefix
 r /tmp/test-prefix/file
 EOF
 
-! test -f /tmp/test-prefix/file
-! test -f /tmp/test-prefix
+test ! -f /tmp/test-prefix/file
+test ! -f /tmp/test-prefix
 
 mkdir /tmp/test-prefix
 touch /tmp/test-prefix/file
@@ -27,5 +27,5 @@ r /tmp/test-prefix/file
 r /tmp/test-prefix
 EOF
 
-! test -f /tmp/test-prefix/file
-! test -f /tmp/test-prefix
+test ! -f /tmp/test-prefix/file
+test ! -f /tmp/test-prefix
index e7bf0447839fefdbe11957b1fa70ea16cc2a07c0..e4272f8ea3ae7e4de75f9deb088ff38088bb8316 100755 (executable)
@@ -1,4 +1,4 @@
-#! /bin/bash
+#!/bin/bash
 #
 # Verify tmpfiles can run in a root directory under a path prefix that contains
 # directories owned by unprivileged users, for example when a root file system
@@ -7,7 +7,8 @@
 # https://github.com/systemd/systemd/pull/11820
 #
 
-set -e
+set -eux
+set -o pipefail
 
 rm -fr /tmp/root /tmp/user
 mkdir -p /tmp/root /tmp/user/root
@@ -22,10 +23,12 @@ test -d /tmp/root/test2
 # Verify the command fails to write to a root-owned subdirectory under an
 # unprivileged user's directory when it's not part of the prefix, as expected
 # by the unsafe_transition function.
-! echo 'd /tmp/user/root/test' | systemd-tmpfiles --create -
-! test -e /tmp/user/root/test
-! echo 'd /user/root/test' | systemd-tmpfiles --root=/tmp --create -
-! test -e /tmp/user/root/test
+echo 'd /tmp/user/root/test' | systemd-tmpfiles --create - \
+    && { echo 'unexpected success'; exit 1; }
+test ! -e /tmp/user/root/test
+echo 'd /user/root/test' | systemd-tmpfiles --root=/tmp --create - \
+    && { echo 'unexpected success'; exit 1; }
+test ! -e /tmp/user/root/test
 
 # Verify the above works when all user-owned directories are in the prefix.
 echo 'd /test' | systemd-tmpfiles --root=/tmp/user/root --create -
index c558dfd4db370855b5fd5d3c66e31bad16f86421..c852f778efaa1e8dc8982a58a9f5924f66d17fc2 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 
-set -e
-set -x
+set -eux
+set -o pipefail
 
 # Make sure that the "stat" output is not locale dependent.
 export LANG=C LC_ALL=C
index 5ec297fbf87c7f90ea43bbdd6eb192bdd3a96790..d650b2145c20b61342a5fc3831bb4554a4eed08d 100755 (executable)
@@ -1,7 +1,6 @@
 #!/usr/bin/env bash
 
-set -e
-set -x
+set -eux
 set -o pipefail
 
 systemd-tmpfiles --create - <<EOF
diff --git a/test/units/testsuite-22.11.sh b/test/units/testsuite-22.11.sh
new file mode 100755 (executable)
index 0000000..21ef210
--- /dev/null
@@ -0,0 +1,141 @@
+#! /bin/bash
+
+set -e
+set -x
+
+rm -fr /tmp/x
+mkdir  /tmp/x
+
+#
+# 'x'
+#
+mkdir -p /tmp/x/{1,2}
+touch /tmp/x/1/{x1,x2} /tmp/x/2/{y1,y2} /tmp/x/{z1,z2}
+
+systemd-tmpfiles --clean - <<EOF
+d /tmp/x - - - 0
+x /tmp/x/1
+EOF
+
+find /tmp/x | sort
+test -d /tmp/x/1
+test -f /tmp/x/1/x1
+test -f /tmp/x/1/x2
+test ! -d /tmp/x/2
+test ! -f /tmp/x/2/x1
+test ! -f /tmp/x/2/x2
+test ! -f /tmp/x/z1
+test ! -f /tmp/x/z2
+
+#
+# 'X'
+#
+
+mkdir -p /tmp/x/{1,2}
+touch /tmp/x/1/{x1,x2} /tmp/x/2/{y1,y2} /tmp/x/{z1,z2}
+
+systemd-tmpfiles --clean - <<EOF
+d /tmp/x - - - 0
+X /tmp/x/1
+EOF
+
+find /tmp/x | sort
+test -d /tmp/x/1
+test ! -f /tmp/x/1/x1
+test ! -f /tmp/x/1/x2
+test ! -d /tmp/x/2
+test ! -f /tmp/x/2/x1
+test ! -f /tmp/x/2/x2
+test ! -f /tmp/x/z1
+test ! -f /tmp/x/z2
+
+#
+# 'x' with glob
+#
+
+mkdir -p /tmp/x/{1,2}
+touch /tmp/x/1/{x1,x2} /tmp/x/2/{y1,y2} /tmp/x/{z1,z2}
+
+systemd-tmpfiles --clean - <<EOF
+d /tmp/x - - - 0
+x /tmp/x/[1345]
+x /tmp/x/z*
+EOF
+
+find /tmp/x | sort
+test -d /tmp/x/1
+test -f /tmp/x/1/x1
+test -f /tmp/x/1/x2
+test ! -d /tmp/x/2
+test ! -f /tmp/x/2/x1
+test ! -f /tmp/x/2/x2
+test -f /tmp/x/z1
+test -f /tmp/x/z2
+
+#
+# 'X' with glob
+#
+
+mkdir -p /tmp/x/{1,2}
+touch /tmp/x/1/{x1,x2} /tmp/x/2/{y1,y2} /tmp/x/{z1,z2}
+
+systemd-tmpfiles --clean - <<EOF
+d /tmp/x - - - 0
+X /tmp/x/[1345]
+X /tmp/x/?[12]
+EOF
+
+find /tmp/x | sort
+test -d /tmp/x/1
+test ! -f /tmp/x/1/x1
+test ! -f /tmp/x/1/x2
+test ! -d /tmp/x/2
+test ! -f /tmp/x/2/x1
+test ! -f /tmp/x/2/x2
+test -f /tmp/x/z1
+test -f /tmp/x/z2
+
+#
+# 'x' with 'r'
+#
+
+mkdir -p /tmp/x/{1,2}/a
+touch /tmp/x/1/a/{x1,x2} /tmp/x/2/a/{y1,y2}
+
+systemd-tmpfiles --clean - <<EOF
+# x/X is not supposed to influence r
+x /tmp/x/1/a
+X /tmp/x/2/a
+r /tmp/x/1
+r /tmp/x/2
+EOF
+
+find /tmp/x | sort
+test -d /tmp/x/1
+test -d /tmp/x/1/a
+test -f /tmp/x/1/a/x1
+test -f /tmp/x/1/a/x2
+test -f /tmp/x/2/a/y1
+test -f /tmp/x/2/a/y2
+
+#
+# 'x' with 'R'
+#
+
+mkdir -p /tmp/x/{1,2}/a
+touch /tmp/x/1/a/{x1,x2} /tmp/x/2/a/{y1,y2}
+
+systemd-tmpfiles --remove - <<EOF
+# X is not supposed to influence R
+X /tmp/x/1/a
+X /tmp/x/2/a
+R /tmp/x/1
+EOF
+
+find /tmp/x | sort
+test ! -d /tmp/x/1
+test ! -d /tmp/x/1/a
+test ! -f /tmp/x/1/a/x1
+test ! -f /tmp/x/1/a/x2
+test -f /tmp/x/2/a/y1
+test -f /tmp/x/2/a/y2
index afce85aceb9bcf11cc3f671538ef4fdf93daf3f1..65d08029690420d70440997124df781255dbaa8e 100755 (executable)
@@ -1,12 +1,12 @@
 #!/usr/bin/env bash
 
-set -x
-set -e
+set -eux
+set -o pipefail
 
->/failed
+>/failed
 
-for t in ${0%.sh}.*.sh; do
-    echo "Running $t"; ./$t
+for t in "${0%.sh}".*.sh; do
+    echo "Running $t"; ./"$t"
 done
 
 touch /testok
index 5e2966f848e0cd60013146a4400023455794cc1c..4ef7c878a83151cb117ab66a12d5fec5daa1407a 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 systemd-analyze log-level debug
@@ -16,19 +16,19 @@ systemd-run --unit=three -p Type=simple /tmp/brokenbinary
 
 # And now, do the same with Type=exec, where the latter two should fail
 systemd-run --unit=four -p Type=exec /bin/sleep infinity
-! systemd-run --unit=five -p Type=exec -p User=idontexist /bin/sleep infinity
-! systemd-run --unit=six -p Type=exec /tmp/brokenbinary
+systemd-run --unit=five -p Type=exec -p User=idontexist /bin/sleep infinity && { echo 'unexpected success'; exit 1; }
+systemd-run --unit=six -p Type=exec /tmp/brokenbinary && { echo 'unexpected success'; exit 1; }
 
 systemd-run --unit=seven -p KillSignal=SIGTERM -p RestartKillSignal=SIGINT -p Type=exec /bin/sleep infinity
 # Both TERM and SIGINT happen to have the same number on all architectures
-test $(systemctl show --value -p KillSignal seven.service) -eq 15
-test $(systemctl show --value -p RestartKillSignal seven.service) -eq 2
+test "$(systemctl show --value -p KillSignal seven.service)" -eq 15
+test "$(systemctl show --value -p RestartKillSignal seven.service)" -eq 2
 
 systemctl restart seven.service
 systemctl stop seven.service
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index e3dd43add38d95d6e891a47afd5ab7d35e586b6c..fbe2d0b1d4d9965906ffed22b68862a3d78ff0f6 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 export SYSTEMD_PAGER=cat
@@ -34,8 +34,8 @@ cmp /var/tmp/testimage.raw /var/lib/machines/testimage3.raw
 
 # Test removal
 machinectl remove testimage
-! test -f /var/lib/machines/testimage.raw
-! machinectl image-status testimage
+test ! -f /var/lib/machines/testimage.raw
+machinectl image-status testimage && { echo 'unexpected success'; exit 1; }
 
 # Test export of clone
 machinectl export-raw testimage3 /var/tmp/testimage3.raw
@@ -46,8 +46,8 @@ rm /var/tmp/testimage3.raw
 machinectl rename testimage3 testimage4
 test -f /var/lib/machines/testimage4.raw
 machinectl image-status testimage4
-! test -f /var/lib/machines/testimage3.raw
-! machinectl image-status testimage3
+test ! -f /var/lib/machines/testimage3.raw
+machinectl image-status testimage3 && { echo 'unexpected success'; exit 1; }
 cmp /var/tmp/testimage.raw /var/lib/machines/testimage4.raw
 
 # Test export of rename
@@ -57,8 +57,8 @@ rm /var/tmp/testimage4.raw
 
 # Test removal
 machinectl remove testimage4
-! test -f /var/lib/machines/testimage4.raw
-! machinectl image-status testimage4
+test ! -f /var/lib/machines/testimage4.raw
+machinectl image-status testimage4 && { echo 'unexpected success'; exit 1; }
 
 # → And now, let's test directory trees ← #
 
@@ -67,7 +67,7 @@ mkdir /var/tmp/scratch
 mv /var/tmp/testimage.raw /var/tmp/scratch/
 touch /var/tmp/scratch/anotherfile
 mkdir /var/tmp/scratch/adirectory
-echo "piep" > /var/tmp/scratch/adirectory/athirdfile
+echo "piep" >/var/tmp/scratch/adirectory/athirdfile
 
 # Test import-fs
 machinectl import-fs /var/tmp/scratch/
@@ -90,8 +90,8 @@ diff -r /var/tmp/scratch/ /var/lib/machines/scratch2
 
 # Test removal
 machinectl remove scratch
-! test -f /var/lib/machines/scratch
-! machinectl image-status scratch
+test ! -f /var/lib/machines/scratch
+machinectl image-status scratchi && { echo 'unexpected success'; exit 1; }
 
 # Test clone
 machinectl clone scratch2 scratch3
@@ -103,23 +103,24 @@ diff -r /var/tmp/scratch/ /var/lib/machines/scratch3
 
 # Test removal
 machinectl remove scratch2
-! test -f /var/lib/machines/scratch2
-! machinectl image-status scratch2
+test ! -f /var/lib/machines/scratch2
+machinectl image-status scratch2 && { echo 'unexpected success'; exit 1; }
 
 # Test rename
 machinectl rename scratch3 scratch4
 test -d /var/lib/machines/scratch4
 machinectl image-status scratch4
-! test -f /var/lib/machines/scratch3
-! machinectl image-status scratch3
+test ! -f /var/lib/machines/scratch3
+machinectl image-status scratch3 && { echo 'unexpected success'; exit 1; }
 diff -r /var/tmp/scratch/ /var/lib/machines/scratch4
 
 # Test removal
 machinectl remove scratch4
-! test -f /var/lib/machines/scratch4
-! machinectl image-status scratch4
+test ! -f /var/lib/machines/scratch4
+machinectl image-status scratch4 && { echo 'unexpected success'; exit 1; }
 
 # Test import-tar hyphen/stdin pipe behavior
+# shellcheck disable=SC2002
 cat /var/tmp/scratch.tar.gz | machinectl import-tar - scratch5
 test -d /var/lib/machines/scratch5
 machinectl image-status scratch5
@@ -135,9 +136,9 @@ rm -rf /var/tmp/scratch
 
 # Test removal
 machinectl remove scratch5
-! test -f /var/lib/machines/scratch5
-! machinectl image-status scratch5
+test ! -f /var/lib/machines/scratch5
+machinectl image-status scratch5 && { echo 'unexpected success'; exit 1; }
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 89c0937c8dafc7dbba060a787c3db1749ab9b982..79820993074eccbe6cf118640479c0e748c2e8e6 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 # Make sure PATH is set
@@ -22,10 +22,10 @@ systemctl show-environment | grep -q '^FOO=BAR$'
 systemctl unset-environment FOO PATH
 
 # Check that one is gone and the other reverted to the built-in
-! (systemctl show-environment | grep -q '^FOO=$')
-! (systemctl show-environment | grep -q '^PATH=.*testaddition$')
+systemctl show-environment | grep '^FOO=$' && exit 1
+systemctl show-environment | grep '^PATH=.*testaddition$' && exit 1
 systemctl show-environment | grep -q '^PATH='
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 0e9ffe118927aa2c7ed6554123e907e9febc29d3..2248380351a7a99ad88ddb59264c3972718207b7 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 systemd-analyze log-level debug
index b5b05b42d9bf40c13a64bb6abf438e19c2fa996b..3408e6d71acb86167fae93e97caf84667035a920 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
 # ex: ts=8 sw=4 sts=4 et filetype=sh
-set -ex
+set -eux
 set -o pipefail
 
 export SYSTEMD_LOG_LEVEL=debug
@@ -63,6 +63,36 @@ portablectl detach --now --enable --runtime /tmp/minimal_1 app0
 
 portablectl list | grep -q -F "No images."
 
-echo OK > /testok
+root="/usr/share/minimal_0.raw"
+app1="/usr/share/app1.raw"
+
+portablectl attach --now --runtime --extension ${app1} ${root} app1
+
+systemctl is-active app1.service
+
+portablectl reattach --now --runtime --extension ${app1} ${root} app1
+
+systemctl is-active app1.service
+
+portablectl detach --now --runtime --extension ${app1} ${root} app1
+
+# portablectl also works with directory paths rather than images
+
+mkdir /tmp/rootdir /tmp/app1 /tmp/overlay
+mount ${app1} /tmp/app1
+mount ${root} /tmp/rootdir
+mount -t overlay overlay -o lowerdir=/tmp/app1:/tmp/rootdir /tmp/overlay
+
+portablectl attach --copy=symlink --now --runtime /tmp/overlay app1
+
+systemctl is-active app1.service
+
+portablectl detach --now --runtime overlay app1
+
+umount /tmp/overlay
+umount /tmp/rootdir
+umount /tmp/app1
+
+echo OK >/testok
 
 exit 0
index a507ffcd7bcee21ecc33617ebb0faeba39ac1c9f..ac8a3e06cf561863847e9f843f1ba318e277487b 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 systemd-analyze log-level debug
@@ -13,19 +13,19 @@ timedatectl set-time 1980-10-15
 systemd-run --on-timezone-change touch /tmp/timezone-changed
 systemd-run --on-clock-change touch /tmp/clock-changed
 
-! test -f /tmp/timezone-changed
-! test -f /tmp/clock-changed
+test ! -f /tmp/timezone-changed
+test ! -f /tmp/clock-changed
 
 timedatectl set-timezone Europe/Kiev
 
-while ! test -f /tmp/timezone-changed ; do sleep .5 ; done
+while test ! -f /tmp/timezone-changed ; do sleep .5 ; done
 
 timedatectl set-time 2018-1-1
 
-while ! test -f /tmp/clock-changed ; do sleep .5 ; done
+while test ! -f /tmp/clock-changed ; do sleep .5 ; done
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index fcff82d804804673f5fb4b5013c7d14e019e4b30..a9a50e1470b02a6764b1d6c1ccb79e284c1f3858 100755 (executable)
@@ -1,10 +1,10 @@
 #!/usr/bin/env bash
-set -e
+set -eux
 set -o pipefail
 
 if journalctl -b -t systemd --grep '\.device: Changed plugged -> dead'; then
     exit 1
 fi
 
-echo OK > /testok
+echo OK >/testok
 exit 0
index c1704ab34e31f20d9c531ae292eddae987dca22f..2393601a007ff8932895d83351aa21b6a652483e 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 # Let's run this test only if the "memory.oom.group" cgroupfs attribute
@@ -9,7 +9,6 @@ set -o pipefail
 # kernels where the concept was still new.
 
 if test -f /sys/fs/cgroup/system.slice/testsuite-32.service/memory.oom.group; then
-
     systemd-analyze log-level debug
     systemd-analyze log-target console
 
@@ -23,12 +22,12 @@ if test -f /sys/fs/cgroup/system.slice/testsuite-32.service/memory.oom.group; th
     echo f >/proc/sysrq-trigger
 
     while : ; do
-        STATE=`systemctl show -P ActiveState oomtest.service`
+        STATE="$(systemctl show -P ActiveState oomtest.service)"
         [ "$STATE" = "failed" ] && break
         sleep .5
     done
 
-    RESULT=`systemctl show -P Result oomtest.service`
+    RESULT="$(systemctl show -P Result oomtest.service)"
     test "$RESULT" = "oom-kill"
 
     systemd-analyze log-level info
index 0a6ee57b99867cfa7f62c7a8c20d824073cf145e..6e750f63a3817a2f1b2a70cf817ecf4bfaaabd5a 100755 (executable)
@@ -1,10 +1,10 @@
 #!/usr/bin/env bash
 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
 # ex: ts=8 sw=4 sts=4 et filetype=sh
-set -ex
+set -eux
 set -o pipefail
 
-cat > /etc/systemd/system/testservice.service <<EOF
+cat >/etc/systemd/system/testservice.service <<EOF
 [Service]
 ConfigurationDirectory=testservice
 RuntimeDirectory=testservice
@@ -18,11 +18,11 @@ EOF
 
 systemctl daemon-reload
 
-! test -e /etc/testservice
-! test -e /run/testservice
-! test -e /var/lib/testservice
-! test -e /var/cache/testservice
-! test -e /var/log/testservice
+test ! -e /etc/testservice
+test ! -e /run/testservice
+test ! -e /var/lib/testservice
+test ! -e /var/cache/testservice
+test ! -e /var/log/testservice
 
 systemctl start testservice
 
@@ -32,7 +32,7 @@ test -d /var/lib/testservice
 test -d /var/cache/testservice
 test -d /var/log/testservice
 
-! systemctl clean testservice
+systemctl clean testservice && { echo 'unexpected success'; exit 1; }
 
 systemctl stop testservice
 
@@ -44,7 +44,7 @@ test -d /var/log/testservice
 
 systemctl clean testservice --what=configuration
 
-! test -e /etc/testservice
+test ! -e /etc/testservice
 test -d /run/testservice
 test -d /var/lib/testservice
 test -d /var/cache/testservice
@@ -52,29 +52,29 @@ test -d /var/log/testservice
 
 systemctl clean testservice
 
-! test -e /etc/testservice
-! test -e /run/testservice
+test ! -e /etc/testservice
+test ! -e /run/testservice
 test -d /var/lib/testservice
-! test -e /var/cache/testservice
+test ! -e /var/cache/testservice
 test -d /var/log/testservice
 
 systemctl clean testservice --what=logs
 
-! test -e /etc/testservice
-! test -e /run/testservice
+test ! -e /etc/testservice
+test ! -e /run/testservice
 test -d /var/lib/testservice
-! test -e /var/cache/testservice
-! test -e /var/log/testservice
+test ! -e /var/cache/testservice
+test ! -e /var/log/testservice
 
 systemctl clean testservice --what=all
 
-! test -e /etc/testservice
-! test -e /run/testservice
-! test -e /var/lib/testservice
-! test -e /var/cache/testservice
-! test -e /var/log/testservice
+test ! -e /etc/testservice
+test ! -e /run/testservice
+test ! -e /var/lib/testservice
+test ! -e /var/cache/testservice
+test ! -e /var/log/testservice
 
-cat > /etc/systemd/system/testservice.service <<EOF
+cat >/etc/systemd/system/testservice.service <<EOF
 [Service]
 DynamicUser=yes
 ConfigurationDirectory=testservice
@@ -89,11 +89,11 @@ EOF
 
 systemctl daemon-reload
 
-! test -e /etc/testservice
-! test -e /run/testservice
-! test -e /var/lib/testservice
-! test -e /var/cache/testservice
-! test -e /var/log/testservice
+test ! -e /etc/testservice
+test ! -e /run/testservice
+test ! -e /var/lib/testservice
+test ! -e /var/cache/testservice
+test ! -e /var/log/testservice
 
 systemctl restart testservice
 
@@ -107,7 +107,7 @@ test -L /var/lib/testservice
 test -L /var/cache/testservice
 test -L /var/log/testservice
 
-! systemctl clean testservice
+systemctl clean testservice && { echo 'unexpected success'; exit 1; }
 
 systemctl stop testservice
 
@@ -123,7 +123,7 @@ test -L /var/log/testservice
 
 systemctl clean testservice --what=configuration
 
-! test -d /etc/testservice
+test ! -d /etc/testservice
 test -d /run/private/testservice
 test -d /var/lib/private/testservice
 test -d /var/cache/private/testservice
@@ -135,41 +135,41 @@ test -L /var/log/testservice
 
 systemctl clean testservice
 
-! test -d /etc/testservice
-! test -d /run/private/testservice
+test ! -d /etc/testservice
+test ! -d /run/private/testservice
 test -d /var/lib/private/testservice
-! test -d /var/cache/private/testservice
+test ! -d /var/cache/private/testservice
 test -d /var/log/private/testservice
-! test -L /run/testservice
+test ! -L /run/testservice
 test -L /var/lib/testservice
-! test -L /var/cache/testservice
+test ! -L /var/cache/testservice
 test -L /var/log/testservice
 
 systemctl clean testservice --what=logs
 
-! test -d /etc/testservice
-! test -d /run/private/testservice
+test ! -d /etc/testservice
+test ! -d /run/private/testservice
 test -d /var/lib/private/testservice
-! test -d /var/cache/private/testservice
-! test -d /var/log/private/testservice
-! test -L /run/testservice
+test ! -d /var/cache/private/testservice
+test ! -d /var/log/private/testservice
+test ! -L /run/testservice
 test -L /var/lib/testservice
-! test -L /var/cache/testservice
-! test -L /var/log/testservice
+test ! -L /var/cache/testservice
+test ! -L /var/log/testservice
 
 systemctl clean testservice --what=all
 
-! test -d /etc/testservice
-! test -d /run/private/testservice
-! test -d /var/lib/private/testservice
-! test -d /var/cache/private/testservice
-! test -d /var/log/private/testservice
-! test -L /run/testservice
-! test -L /var/lib/testservice
-! test -L /var/cache/testservice
-! test -L /var/log/testservice
-
-cat > /etc/systemd/system/tmp-hoge.mount <<EOF
+test ! -d /etc/testservice
+test ! -d /run/private/testservice
+test ! -d /var/lib/private/testservice
+test ! -d /var/cache/private/testservice
+test ! -d /var/log/private/testservice
+test ! -L /run/testservice
+test ! -L /var/lib/testservice
+test ! -L /var/cache/testservice
+test ! -L /var/log/testservice
+
+cat >/etc/systemd/system/tmp-hoge.mount <<EOF
 [Mount]
 What=tmpfs
 Type=tmpfs
@@ -182,11 +182,11 @@ EOF
 
 systemctl daemon-reload
 
-! test -e /etc/hoge
-! test -e /run/hoge
-! test -e /var/lib/hoge
-! test -e /var/cache/hoge
-! test -e /var/log/hoge
+test ! -e /etc/hoge
+test ! -e /run/hoge
+test ! -e /var/lib/hoge
+test ! -e /var/cache/hoge
+test ! -e /var/log/hoge
 
 systemctl start tmp-hoge.mount
 
@@ -196,7 +196,7 @@ test -d /var/lib/hoge
 test -d /var/cache/hoge
 test -d /var/log/hoge
 
-! systemctl clean tmp-hoge.mount
+systemctl clean tmp-hoge.mount && { echo 'unexpected success'; exit 1; }
 
 test -d /etc/hoge
 test -d /run/hoge
@@ -207,44 +207,44 @@ test -d /var/log/hoge
 systemctl stop tmp-hoge.mount
 
 test -d /etc/hoge
-! test -d /run/hoge
+test ! -d /run/hoge
 test -d /var/lib/hoge
 test -d /var/cache/hoge
 test -d /var/log/hoge
 
 systemctl clean tmp-hoge.mount --what=configuration
 
-! test -d /etc/hoge
-! test -d /run/hoge
+test ! -d /etc/hoge
+test ! -d /run/hoge
 test -d /var/lib/hoge
 test -d /var/cache/hoge
 test -d /var/log/hoge
 
 systemctl clean tmp-hoge.mount
 
-! test -d /etc/hoge
-! test -d /run/hoge
+test ! -d /etc/hoge
+test ! -d /run/hoge
 test -d /var/lib/hoge
-! test -d /var/cache/hoge
+test ! -d /var/cache/hoge
 test -d /var/log/hoge
 
 systemctl clean tmp-hoge.mount --what=logs
 
-! test -d /etc/hoge
-! test -d /run/hoge
+test ! -d /etc/hoge
+test ! -d /run/hoge
 test -d /var/lib/hoge
-! test -d /var/cache/hoge
-! test -d /var/log/hoge
+test ! -d /var/cache/hoge
+test ! -d /var/log/hoge
 
 systemctl clean tmp-hoge.mount --what=all
 
-! test -d /etc/hoge
-! test -d /run/hoge
-! test -d /var/lib/hoge
-! test -d /var/cache/hoge
-! test -d /var/log/hoge
+test ! -d /etc/hoge
+test ! -d /run/hoge
+test ! -d /var/lib/hoge
+test ! -d /var/cache/hoge
+test ! -d /var/log/hoge
 
-cat > /etc/systemd/system/testservice.socket <<EOF
+cat >/etc/systemd/system/testservice.socket <<EOF
 [Socket]
 ListenSequentialPacket=/run/testservice.socket
 RemoveOnStop=yes
@@ -258,62 +258,62 @@ EOF
 
 systemctl daemon-reload
 
-! test -e /etc/testsocket
-! test -e /run/testsocket
-! test -e /var/lib/testsocket
-! test -e /var/cache/testsocket
-! test -e /var/log/testsocket
+test ! -e /etc/testsocket
+test ! -e /run/testsocket
+test ! -e /var/lib/testsocket
+test ! -e /var/cache/testsocket
+test ! -e /var/log/testsocket
 
 systemctl start testservice.socket
 
 test -d /etc/testsocket
-test -d /run/testsocket
+test -d /run/testsocket
 test -d /var/lib/testsocket
 test -d /var/cache/testsocket
 test -d /var/log/testsocket
 
-! systemctl clean testservice.socket
+systemctl clean testservice.socket && { echo 'unexpected success'; exit 1; }
 
 systemctl stop testservice.socket
 
 test -d /etc/testsocket
-! test -d /run/testsocket
+test ! -d /run/testsocket
 test -d /var/lib/testsocket
 test -d /var/cache/testsocket
 test -d /var/log/testsocket
 
 systemctl clean testservice.socket --what=configuration
 
-! test -e /etc/testsocket
-! test -d /run/testsocket
+test ! -e /etc/testsocket
+test ! -d /run/testsocket
 test -d /var/lib/testsocket
 test -d /var/cache/testsocket
 test -d /var/log/testsocket
 
 systemctl clean testservice.socket
 
-! test -e /etc/testsocket
-! test -e /run/testsocket
+test ! -e /etc/testsocket
+test ! -e /run/testsocket
 test -d /var/lib/testsocket
-! test -e /var/cache/testsocket
+test ! -e /var/cache/testsocket
 test -d /var/log/testsocket
 
 systemctl clean testservice.socket --what=logs
 
-! test -e /etc/testsocket
-! test -e /run/testsocket
+test ! -e /etc/testsocket
+test ! -e /run/testsocket
 test -d /var/lib/testsocket
-! test -e /var/cache/testsocket
-! test -e /var/log/testsocket
+test ! -e /var/cache/testsocket
+test ! -e /var/log/testsocket
 
 systemctl clean testservice.socket --what=all
 
-! test -e /etc/testsocket
-! test -e /run/testsocket
-! test -e /var/lib/testsocket
-! test -e /var/cache/testsocket
-! test -e /var/log/testsocket
+test ! -e /etc/testsocket
+test ! -e /run/testsocket
+test ! -e /var/lib/testsocket
+test ! -e /var/cache/testsocket
+test ! -e /var/log/testsocket
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 6d9488688a1bb4554923154641e6e98e65a714fa..394b220d60a31f02d5b4b6f6b9b1d9d6cd6c6a9c 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 systemd-analyze log-level debug
@@ -9,38 +9,41 @@ systemd-analyze log-target console
 
 systemd-run --wait -p DynamicUser=0 -p StateDirectory=zzz touch /var/lib/zzz/test
 systemd-run --wait -p DynamicUser=0 -p StateDirectory=zzz test -f /var/lib/zzz/test
-! systemd-run --wait -p DynamicUser=0 -p StateDirectory=zzz test -f /var/lib/zzz/test-missing
+systemd-run --wait -p DynamicUser=0 -p StateDirectory=zzz test -f /var/lib/zzz/test-missing \
+    && { echo 'unexpected success'; exit 1; }
 
 test -d /var/lib/zzz
-! test -L /var/lib/zzz
-! test -e /var/lib/private/zzz
+test ! -L /var/lib/zzz
+test ! -e /var/lib/private/zzz
 test -f /var/lib/zzz/test
-! test -f /var/lib/zzz/test-missing
+test ! -f /var/lib/zzz/test-missing
 
 # Convert to DynamicUser=1
 
 systemd-run --wait -p DynamicUser=1 -p StateDirectory=zzz test -f /var/lib/zzz/test
-! systemd-run --wait -p DynamicUser=1 -p StateDirectory=zzz test -f /var/lib/zzz/test-missing
+systemd-run --wait -p DynamicUser=1 -p StateDirectory=zzz test -f /var/lib/zzz/test-missing \
+    && { echo 'unexpected success'; exit 1; }
 
 test -L /var/lib/zzz
 test -d /var/lib/private/zzz
 
 test -f /var/lib/zzz/test
-! test -f /var/lib/zzz/test-missing
+test ! -f /var/lib/zzz/test-missing
 
 # Convert back
 
 systemd-run --wait -p DynamicUser=0 -p StateDirectory=zzz test -f /var/lib/zzz/test
-! systemd-run --wait -p DynamicUser=0 -p StateDirectory=zzz test -f /var/lib/zzz/test-missing
+systemd-run --wait -p DynamicUser=0 -p StateDirectory=zzz test -f /var/lib/zzz/test-missing \
+    && { echo 'unexpected success'; exit 1; }
 
 test -d /var/lib/zzz
-! test -L /var/lib/zzz
-! test -e /var/lib/private/zzz
+test ! -L /var/lib/zzz
+test ! -e /var/lib/private/zzz
 test -f /var/lib/zzz/test
-! test -f /var/lib/zzz/test-missing
+test ! -f /var/lib/zzz/test-missing
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index f5579ce8255ff21997db22f3df9cc5cf23cf6f73..94fd927a5d13c16446ea2cecda574f3f1df2e33e 100755 (executable)
@@ -1,13 +1,14 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 at_exit() {
-    if [ $? -ne 0 ]; then
+    # shellcheck disable=SC2181
+    if [[ $? -ne 0 ]]; then
         # We're exiting with a non-zero EC, let's dump test artifacts
         # for easier debugging
-        [ -f "$straceLog" ] && cat "$straceLog"
-        [ -f "$journalLog" ] && cat "$journalLog"
+        [[ -v straceLog && -f "$straceLog" ]] && cat "$straceLog"
+        [[ -v journalLog && -f "$journalLog" ]] && cat "$journalLog"
     fi
 }
 
@@ -26,25 +27,28 @@ testUnitFile="/run/systemd/system/$testUnit"
 testUnitNUMAConf="$testUnitFile.d/numa.conf"
 
 # Sleep constants (we should probably figure out something better but nothing comes to mind)
-journalSleep=5
 sleepAfterStart=1
 
 # Journal cursor for easier navigation
 journalCursorFile="jounalCursorFile"
 
 startStrace() {
-    coproc strace -qq -p 1 -o $straceLog -e set_mempolicy -s 1024 $1
+    coproc strace -qq -p 1 -o "$straceLog" -e set_mempolicy -s 1024 ${1:+"$1"}
     # Wait for strace to properly "initialize"
     sleep $sleepAfterStart
 }
 
 stopStrace() {
-    kill -s TERM $COPROC_PID
+    [[ -v COPROC_PID ]] || return
+
+    local PID=$COPROC_PID
+    kill -s TERM "$PID"
     # Make sure the strace process is indeed dead
-    while kill -0 $COPROC_PID 2>/dev/null; do sleep 0.1; done
+    while kill -0 "$PID" 2>/dev/null; do sleep 0.1; done
 }
 
 startJournalctl() {
+    : >"$journalCursorFile"
     # Save journal's cursor for later navigation
     journalctl --no-pager --cursor-file="$journalCursorFile" -n0 -ocat
 }
@@ -55,7 +59,7 @@ stopJournalctl() {
     # the --sync wait until the synchronization is complete
     echo "Force journald to write all queued messages"
     journalctl --sync
-    journalctl -u $unit --cursor-file="$journalCursorFile" > "$journalLog"
+    journalctl -u "$unit" --cursor-file="$journalCursorFile" >"$journalLog"
 }
 
 checkNUMA() {
@@ -64,21 +68,24 @@ checkNUMA() {
 }
 
 writePID1NUMAPolicy() {
-    echo [Manager] > $confDir/numa.conf
-    echo NUMAPolicy=$1 >> $confDir/numa.conf
-    echo NUMAMask=$2>> $confDir/numa.conf
+    cat >"$confDir/numa.conf" <<EOF
+[Manager]
+NUMAPolicy=${1:?missing argument: NUMAPolicy}
+NUMAMask=${2:-""}
+EOF
 }
 
 writeTestUnit() {
-    mkdir -p $testUnitFile.d/
-    echo [Service] > $testUnitFile
-    echo ExecStart=/bin/sleep 3600 >> $testUnitFile
+    mkdir -p "$testUnitFile.d/"
+    printf "[Service]\nExecStart=/bin/sleep 3600\n" >"$testUnitFile"
 }
 
 writeTestUnitNUMAPolicy() {
-    echo [Service] > $testUnitNUMAConf
-    echo NUMAPolicy=$1 >> $testUnitNUMAConf
-    echo NUMAMask=$2>> $testUnitNUMAConf
+    cat >"$testUnitNUMAConf" <<EOF
+[Service]
+NUMAPolicy=${1:?missing argument: NUMAPolicy}
+NUMAMask=${2:-""}
+EOF
     systemctl daemon-reload
 }
 
@@ -97,32 +104,38 @@ pid1ReloadWithJournal() {
 
 pid1StartUnitWithStrace() {
     startStrace '-f'
-    systemctl start $1
+    systemctl start "${1:?missing unit name}"
     sleep $sleepAfterStart
     stopStrace
 }
 
 pid1StartUnitWithJournal() {
     startJournalctl
-    systemctl start $1
+    systemctl start "${1:?missing unit name}"
     sleep $sleepAfterStart
     stopJournalctl
 }
 
 pid1StopUnit() {
-    systemctl stop $1
+    systemctl stop "${1:?missing unit name}"
 }
 
 systemctlCheckNUMAProperties() {
-    local LOGFILE="$(mktemp)"
-    systemctl show -p NUMAPolicy $1 > "$LOGFILE"
-    grep "NUMAPolicy=$2" "$LOGFILE"
+    local UNIT_NAME="${1:?missing unit name}"
+    local NUMA_POLICY="${2:?missing NUMAPolicy}"
+    local NUMA_MASK="${3:-""}"
+    local LOGFILE
+
+    LOGFILE="$(mktemp)"
 
-    > "$LOGFILE"
+    systemctl show -p NUMAPolicy "$UNIT_NAME" >"$LOGFILE"
+    grep "NUMAPolicy=$NUMA_POLICY" "$LOGFILE"
 
-    if [ -n "$3" ]; then
-        systemctl show -p NUMAMask $1 > "$LOGFILE"
-        grep "NUMAMask=$3" "$LOGFILE"
+    : >"$LOGFILE"
+
+    if [ -n "$NUMA_MASK" ]; then
+        systemctl show -p NUMAMask "$UNIT_NAME" >"$LOGFILE"
+        grep "NUMAMask=$NUMA_MASK" "$LOGFILE"
     fi
 }
 
@@ -145,10 +158,10 @@ if ! checkNUMA; then
     echo "systemd-run NUMAPolicy=default && NUMAMask=0 check without NUMA support"
     runUnit='numa-systemd-run-test.service'
     startJournalctl
-    systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000
+    systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit "$runUnit" sleep 1000
     sleep $sleepAfterStart
-    pid1StopUnit $runUnit
-    stopJournalctl $runUnit
+    pid1StopUnit "$runUnit"
+    stopJournalctl "$runUnit"
     grep "NUMA support not available, ignoring" "$journalLog"
 
 else
@@ -156,43 +169,43 @@ else
     writePID1NUMAPolicy "default"
     pid1ReloadWithStrace
     # Kernel requires that nodemask argument is set to NULL when setting default policy
-    grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
+    grep "set_mempolicy(MPOL_DEFAULT, NULL" "$straceLog"
 
     echo "PID1 NUMAPolicy support - Default policy w/ mask"
     writePID1NUMAPolicy "default" "0"
     pid1ReloadWithStrace
-    grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
+    grep "set_mempolicy(MPOL_DEFAULT, NULL" "$straceLog"
 
     echo "PID1 NUMAPolicy support - Bind policy w/o mask"
     writePID1NUMAPolicy "bind"
     pid1ReloadWithJournal
-    grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
+    grep "Failed to set NUMA memory policy: Invalid argument" "$journalLog"
 
     echo "PID1 NUMAPolicy support - Bind policy w/ mask"
     writePID1NUMAPolicy "bind" "0"
     pid1ReloadWithStrace
-    grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog
+    grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" "$straceLog"
 
     echo "PID1 NUMAPolicy support - Interleave policy w/o mask"
     writePID1NUMAPolicy "interleave"
     pid1ReloadWithJournal
-    grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
+    grep "Failed to set NUMA memory policy: Invalid argument" "$journalLog"
 
     echo "PID1 NUMAPolicy support - Interleave policy w/ mask"
     writePID1NUMAPolicy "interleave" "0"
     pid1ReloadWithStrace
-    grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog
+    grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" "$straceLog"
 
     echo "PID1 NUMAPolicy support - Preferred policy w/o mask"
     writePID1NUMAPolicy "preferred"
     pid1ReloadWithJournal
     # Preferred policy with empty node mask is actually allowed and should reset allocation policy to default
-    ! grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
+    grep "Failed to set NUMA memory policy: Invalid argument" "$journalLog" && { echo >&2 "unexpected pass"; exit 1; }
 
     echo "PID1 NUMAPolicy support - Preferred policy w/ mask"
     writePID1NUMAPolicy "preferred" "0"
     pid1ReloadWithStrace
-    grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog
+    grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" "$straceLog"
 
     echo "PID1 NUMAPolicy support - Local policy w/o mask"
     writePID1NUMAPolicy "local"
@@ -202,140 +215,137 @@ else
     # return a numerical constant instead (with a comment):
     #   set_mempolicy(0x4 /* MPOL_??? */, NULL, 0) = 0
     # Let's cover this scenario as well
-    grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
+    grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" "$straceLog"
 
     echo "PID1 NUMAPolicy support - Local policy w/ mask"
     writePID1NUMAPolicy "local" "0"
     pid1ReloadWithStrace
-    grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
+    grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" "$straceLog"
 
     echo "Unit file NUMAPolicy support - Default policy w/o mask"
     writeTestUnitNUMAPolicy "default"
-    pid1StartUnitWithStrace $testUnit
-    systemctlCheckNUMAProperties $testUnit "default"
-    pid1StopUnit $testUnit
-    grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
+    pid1StartUnitWithStrace "$testUnit"
+    systemctlCheckNUMAProperties "$testUnit" "default"
+    pid1StopUnit "$testUnit"
+    grep "set_mempolicy(MPOL_DEFAULT, NULL" "$straceLog"
 
     echo "Unit file NUMAPolicy support - Default policy w/ mask"
     writeTestUnitNUMAPolicy "default" "0"
-    pid1StartUnitWithStrace $testUnit
-    systemctlCheckNUMAProperties $testUnit "default" "0"
+    pid1StartUnitWithStrace "$testUnit"
+    systemctlCheckNUMAProperties "$testUnit" "default" "0"
     pid1StopUnit $testUnit
     # Mask must be ignored
-    grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
+    grep "set_mempolicy(MPOL_DEFAULT, NULL" "$straceLog"
 
     echo "Unit file NUMAPolicy support - Bind policy w/o mask"
     writeTestUnitNUMAPolicy "bind"
-    pid1StartUnitWithJournal $testUnit
-    pid1StopUnit $testUnit
-    grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
+    pid1StartUnitWithJournal "$testUnit"
+    pid1StopUnit "$testUnit"
+    grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" "$journalLog"
 
     echo "Unit file NUMAPolicy support - Bind policy w/ mask"
     writeTestUnitNUMAPolicy "bind" "0"
-    pid1StartUnitWithStrace $testUnit
-    systemctlCheckNUMAProperties $testUnit "bind" "0"
-    pid1StopUnit $testUnit
-    grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog
+    pid1StartUnitWithStrace "$testUnit"
+    systemctlCheckNUMAProperties "$testUnit" "bind" "0"
+    pid1StopUnit "$testUnit"
+    grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" "$straceLog"
 
     echo "Unit file NUMAPolicy support - Interleave policy w/o mask"
     writeTestUnitNUMAPolicy "interleave"
-    pid1StartUnitWithStrace $testUnit
-    pid1StopUnit $testUnit
-    grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
+    pid1StartUnitWithStrace "$testUnit"
+    pid1StopUnit "$testUnit"
+    grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" "$journalLog"
 
     echo "Unit file NUMAPolicy support - Interleave policy w/ mask"
     writeTestUnitNUMAPolicy "interleave" "0"
-    pid1StartUnitWithStrace $testUnit
-    systemctlCheckNUMAProperties $testUnit "interleave" "0"
-    pid1StopUnit $testUnit
-    grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog
+    pid1StartUnitWithStrace "$testUnit"
+    systemctlCheckNUMAProperties "$testUnit" "interleave" "0"
+    pid1StopUnit "$testUnit"
+    grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" "$straceLog"
 
     echo "Unit file NUMAPolicy support - Preferred policy w/o mask"
     writeTestUnitNUMAPolicy "preferred"
-    pid1StartUnitWithJournal $testUnit
-    systemctlCheckNUMAProperties $testUnit "preferred"
-    pid1StopUnit $testUnit
-    ! grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
+    pid1StartUnitWithJournal "$testUnit"
+    systemctlCheckNUMAProperties "$testUnit" "preferred"
+    pid1StopUnit "$testUnit"
+    grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" "$journalLog" && { echo >&2 "unexpected pass"; exit 1; }
 
     echo "Unit file NUMAPolicy support - Preferred policy w/ mask"
     writeTestUnitNUMAPolicy "preferred" "0"
-    pid1StartUnitWithStrace $testUnit
-    systemctlCheckNUMAProperties $testUnit "preferred" "0"
-    pid1StopUnit $testUnit
-    grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog
+    pid1StartUnitWithStrace "$testUnit"
+    systemctlCheckNUMAProperties "$testUnit" "preferred" "0"
+    pid1StopUnit "$testUnit"
+    grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" "$straceLog"
 
     echo "Unit file NUMAPolicy support - Local policy w/o mask"
     writeTestUnitNUMAPolicy "local"
-    pid1StartUnitWithStrace $testUnit
-    systemctlCheckNUMAProperties $testUnit "local"
-    pid1StopUnit $testUnit
-    grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
+    pid1StartUnitWithStrace "$testUnit"
+    systemctlCheckNUMAProperties "$testUnit" "local"
+    pid1StopUnit "$testUnit"
+    grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" "$straceLog"
 
     echo "Unit file NUMAPolicy support - Local policy w/ mask"
     writeTestUnitNUMAPolicy "local" "0"
-    pid1StartUnitWithStrace $testUnit
-    systemctlCheckNUMAProperties $testUnit "local" "0"
-    pid1StopUnit $testUnit
+    pid1StartUnitWithStrace "$testUnit"
+    systemctlCheckNUMAProperties "$testUnit" "local" "0"
+    pid1StopUnit "$testUnit"
     # Mask must be ignored
-    grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
+    grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" "$straceLog"
 
     echo "Unit file CPUAffinity=NUMA support"
     writeTestUnitNUMAPolicy "bind" "0"
-    echo "CPUAffinity=numa" >> $testUnitNUMAConf
+    echo "CPUAffinity=numa" >>"$testUnitNUMAConf"
     systemctl daemon-reload
-    systemctl start $testUnit
-    systemctlCheckNUMAProperties $testUnit "bind" "0"
-    pid=$(systemctl show --value -p MainPID $testUnit)
-    cpulist=$(cat /sys/devices/system/node/node0/cpulist)
-    affinity_systemd=$(systemctl show --value -p CPUAffinity $testUnit)
-    [ $cpulist = $affinity_systemd ]
-    pid1StopUnit $testUnit
+    systemctl start "$testUnit"
+    systemctlCheckNUMAProperties "$testUnit" "bind" "0"
+    cpulist="$(cat /sys/devices/system/node/node0/cpulist)"
+    affinity_systemd="$(systemctl show --value -p CPUAffinity "$testUnit")"
+    [ "$cpulist" = "$affinity_systemd" ]
+    pid1StopUnit "$testUnit"
 
     echo "systemd-run NUMAPolicy support"
     runUnit='numa-systemd-run-test.service'
 
-    systemd-run -p NUMAPolicy=default --unit $runUnit sleep 1000
-    systemctlCheckNUMAProperties $runUnit "default"
-    pid1StopUnit $runUnit
-
-    systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000
-    systemctlCheckNUMAProperties $runUnit "default" ""
-    pid1StopUnit $runUnit
+    systemd-run -p NUMAPolicy=default --unit "$runUnit" sleep 1000
+    systemctlCheckNUMAProperties "$runUnit" "default"
+    pid1StopUnit "$runUnit"
 
-    systemd-run -p NUMAPolicy=bind -p NUMAMask=0 --unit $runUnit sleep 1000
-    systemctlCheckNUMAProperties $runUnit "bind" "0"
-    pid1StopUnit $runUnit
+    systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit "$runUnit" sleep 1000
+    systemctlCheckNUMAProperties "$runUnit" "default" ""
+    pid1StopUnit "$runUnit"
 
-    systemd-run -p NUMAPolicy=interleave -p NUMAMask=0 --unit $runUnit sleep 1000
-    systemctlCheckNUMAProperties $runUnit "interleave" "0"
-    pid1StopUnit $runUnit
+    systemd-run -p NUMAPolicy=bind -p NUMAMask=0 --unit "$runUnit" sleep 1000
+    systemctlCheckNUMAProperties "$runUnit" "bind" "0"
+    pid1StopUnit "$runUnit"
 
-    systemd-run -p NUMAPolicy=preferred -p NUMAMask=0 --unit $runUnit sleep 1000
-    systemctlCheckNUMAProperties $runUnit "preferred" "0"
-    pid1StopUnit $runUnit
+    systemd-run -p NUMAPolicy=interleave -p NUMAMask=0 --unit "$runUnit" sleep 1000
+    systemctlCheckNUMAProperties "$runUnit" "interleave" "0"
+    pid1StopUnit "$runUnit"
 
-    systemd-run -p NUMAPolicy=local --unit $runUnit sleep 1000
-    systemctlCheckNUMAProperties $runUnit "local"
-    pid1StopUnit $runUnit
+    systemd-run -p NUMAPolicy=preferred -p NUMAMask=0 --unit "$runUnit" sleep 1000
+    systemctlCheckNUMAProperties "$runUnit" "preferred" "0"
+    pid1StopUnit "$runUnit"
 
-    systemd-run -p NUMAPolicy=local -p NUMAMask=0 --unit $runUnit sleep 1000
-    systemctlCheckNUMAProperties $runUnit "local" ""
-    pid1StopUnit $runUnit
+    systemd-run -p NUMAPolicy=local --unit "$runUnit" sleep 1000
+    systemctlCheckNUMAProperties "$runUnit" "local"
+    pid1StopUnit "$runUnit"
 
-    systemd-run -p NUMAPolicy=local -p NUMAMask=0 -p CPUAffinity=numa --unit $runUnit sleep 1000
-    systemctlCheckNUMAProperties $runUnit "local" ""
-    systemctl cat $runUnit | grep -q 'CPUAffinity=numa'
-    pid1StopUnit $runUnit
+    systemd-run -p NUMAPolicy=local -p NUMAMask=0 --unit "$runUnit" sleep 1000
+    systemctlCheckNUMAProperties "$runUnit" "local" ""
+    pid1StopUnit "$runUnit"
 
+    systemd-run -p NUMAPolicy=local -p NUMAMask=0 -p CPUAffinity=numa --unit "$runUnit" sleep 1000
+    systemctlCheckNUMAProperties "$runUnit" "local" ""
+    systemctl cat "$runUnit" | grep -q 'CPUAffinity=numa'
+    pid1StopUnit "$runUnit"
 fi
 
 # Cleanup
-rm -rf $testDir
-rm -rf $confDir
+rm -rf "$confDir"
 systemctl daemon-reload
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 32a9dd8694e03c7bfe5f5a16eacba6f38a439980..c3eb5344d1163808005b2bf46de9d1c1d8e261c7 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
 # ex: ts=8 sw=4 sts=4 et filetype=sh
-set -ex
+set -eux
 set -o pipefail
 
 systemd-mount -p RuntimeDirectory=hoge -p RuntimeDirectoryPreserve=yes -t tmpfs tmpfs /tmp/aaa
@@ -12,8 +12,8 @@ touch /tmp/aaa/bbb
 systemctl restart tmp-aaa.mount
 
 test -e /run/hoge/foo
-! test -e /tmp/aaa/bbb
+test ! -e /tmp/aaa/bbb
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 18b7bd6dcee27b0b8f3c8564f20c1747cf927461..818f69bc63553bc3e84f9ca434f0de634918cfbf 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 
-set -ex
+set -eux
 set -o pipefail
 
 systemd-analyze log-level debug
@@ -14,11 +14,11 @@ start_test_service() {
 }
 
 dbus_freeze() {
-    local suffix=
-    suffix="${1##*.}"
+    local name object_path suffix
 
-    local name="$(echo ${1%.$suffix} | sed s/-/_2d/g)"
-    local object_path="/org/freedesktop/systemd1/unit/${name}_2e${suffix}"
+    suffix="${1##*.}"
+    name="${1%.$suffix}"
+    object_path="/org/freedesktop/systemd1/unit/${name//-/_2d}_2e${suffix}"
 
     busctl call \
            org.freedesktop.systemd1 \
@@ -28,11 +28,11 @@ dbus_freeze() {
 }
 
 dbus_thaw() {
-    local suffix=
-    suffix="${1##*.}"
+    local name object_path suffix
 
-    local name="$(echo ${1%.$suffix} | sed s/-/_2d/g)"
-    local object_path="/org/freedesktop/systemd1/unit/${name}_2e${suffix}"
+    suffix="${1##*.}"
+    name="${1%.$suffix}"
+    object_path="/org/freedesktop/systemd1/unit/${name//-/_2d}_2e${suffix}"
 
     busctl call \
            org.freedesktop.systemd1 \
@@ -62,11 +62,11 @@ dbus_thaw_unit() {
 }
 
 dbus_can_freeze() {
-    local suffix=
-    suffix="${1##*.}"
+    local name object_path suffix
 
-    local name="$(echo ${1%.$suffix} | sed s/-/_2d/g)"
-    local object_path="/org/freedesktop/systemd1/unit/${name}_2e${suffix}"
+    suffix="${1##*.}"
+    name="${1%.$suffix}"
+    object_path="/org/freedesktop/systemd1/unit/${name//-/_2d}_2e${suffix}"
 
     busctl get-property \
            org.freedesktop.systemd1 \
@@ -76,11 +76,11 @@ dbus_can_freeze() {
 }
 
 check_freezer_state() {
-    local suffix=
-    suffix="${1##*.}"
+    local name object_path suffix
 
-    local name="$(echo ${1%.$suffix} | sed s/-/_2d/g)"
-    local object_path="/org/freedesktop/systemd1/unit/${name}_2e${suffix}"
+    suffix="${1##*.}"
+    name="${1%.$suffix}"
+    object_path="/org/freedesktop/systemd1/unit/${name//-/_2d}_2e${suffix}"
 
     state=$(busctl get-property \
                    org.freedesktop.systemd1 \
@@ -245,7 +245,7 @@ test_preserve_state() {
     echo "Test that freezer state is preserved when recursive freezing is initiated from outside (e.g. by manager up the tree):"
 
     echo -n "  - freeze from outside: "
-    echo 1 > /sys/fs/cgroup/"${slice}"/cgroup.freeze
+    echo 1 >/sys/fs/cgroup/"${slice}"/cgroup.freeze
     # Give kernel some time to freeze the slice
     sleep 1
 
@@ -259,7 +259,7 @@ test_preserve_state() {
     echo "[ OK ]"
 
     echo -n "  - thaw from outside: "
-    echo 0 > /sys/fs/cgroup/"${slice}"/cgroup.freeze
+    echo 0 >/sys/fs/cgroup/"${slice}"/cgroup.freeze
     sleep 1
 
     check_freezer_state "${unit}" "running"
@@ -271,8 +271,8 @@ test_preserve_state() {
     echo -n "  - thaw from outside while inner service is frozen: "
     systemctl freeze "$unit"
     check_freezer_state "${unit}" "frozen"
-    echo 1 > /sys/fs/cgroup/"${slice}"/cgroup.freeze
-    echo 0 > /sys/fs/cgroup/"${slice}"/cgroup.freeze
+    echo 1 >/sys/fs/cgroup/"${slice}"/cgroup.freeze
+    echo 0 >/sys/fs/cgroup/"${slice}"/cgroup.freeze
     check_freezer_state "${slice}" "running"
     check_freezer_state "${unit}" "frozen"
     echo "[ OK ]"
@@ -293,5 +293,5 @@ test -e /sys/fs/cgroup/system.slice/cgroup.freeze && {
     test_preserve_state
 }
 
-echo OK > /testok
+echo OK >/testok
 exit 0
index eb7363fa6a2bb182998dc9b92b60763e3069eb6c..3b0d893a4c0bc9b779bf778ea83504e3bbb4d119 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 
-set -ex
+set -eux
 set -o pipefail
 
 systemd-analyze log-level debug
@@ -11,23 +11,23 @@ SERVICE_PATH="$(mktemp /etc/systemd/system/execreloadXXX.service)"
 SERVICE_NAME="${SERVICE_PATH##*/}"
 
 echo "[#1] Failing ExecReload= should not kill the service"
-cat > "$SERVICE_PATH" << EOF
+cat >"$SERVICE_PATH" <<EOF
 [Service]
 ExecStart=/bin/sleep infinity
 ExecReload=/bin/false
 EOF
 
 systemctl daemon-reload
-systemctl start $SERVICE_NAME
-systemctl status $SERVICE_NAME
+systemctl start "$SERVICE_NAME"
+systemctl status "$SERVICE_NAME"
 # The reload SHOULD fail but SHOULD NOT affect the service state
-! systemctl reload $SERVICE_NAME
-systemctl status $SERVICE_NAME
-systemctl stop $SERVICE_NAME
+systemctl reload "$SERVICE_NAME" && { echo 'unexpected success'; exit 1; }
+systemctl status "$SERVICE_NAME"
+systemctl stop "$SERVICE_NAME"
 
 
 echo "[#2] Failing ExecReload= should not kill the service (multiple ExecReload=)"
-cat > "$SERVICE_PATH" << EOF
+cat >"$SERVICE_PATH" <<EOF
 [Service]
 ExecStart=/bin/sleep infinity
 ExecReload=/bin/true
@@ -36,29 +36,29 @@ ExecReload=/bin/true
 EOF
 
 systemctl daemon-reload
-systemctl start $SERVICE_NAME
-systemctl status $SERVICE_NAME
+systemctl start "$SERVICE_NAME"
+systemctl status "$SERVICE_NAME"
 # The reload SHOULD fail but SHOULD NOT affect the service state
-! systemctl reload $SERVICE_NAME
-systemctl status $SERVICE_NAME
-systemctl stop $SERVICE_NAME
+systemctl reload "$SERVICE_NAME" && { echo 'unexpected success'; exit 1; }
+systemctl status "$SERVICE_NAME"
+systemctl stop "$SERVICE_NAME"
 
 echo "[#3] Failing ExecReload=- should not affect reload's exit code"
-cat > "$SERVICE_PATH" << EOF
+cat >"$SERVICE_PATH" <<EOF
 [Service]
 ExecStart=/bin/sleep infinity
 ExecReload=-/bin/false
 EOF
 
 systemctl daemon-reload
-systemctl start $SERVICE_NAME
-systemctl status $SERVICE_NAME
-systemctl reload $SERVICE_NAME
-systemctl status $SERVICE_NAME
-systemctl stop $SERVICE_NAME
+systemctl start "$SERVICE_NAME"
+systemctl status "$SERVICE_NAME"
+systemctl reload "$SERVICE_NAME"
+systemctl status "$SERVICE_NAME"
+systemctl stop "$SERVICE_NAME"
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 957d22031a9416a94e293901ee375845bc9482e9..fdb052c39ca7a48ba121fea5fd5ac73d58fb2423 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 systemd-analyze log-level debug
@@ -41,6 +41,6 @@ done
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 81fa1716f14bbf749ae811a0a76ead4696dd01f0..e7993e8df789eff1e88197cb402c2d97125b5670 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 # wait this many secs for each test service to succeed in what is being tested
@@ -9,9 +9,10 @@ systemd-analyze log-level debug
 systemd-analyze log-target console
 
 # test one: Restart=on-failure should restart the service
-! systemd-run --unit=one -p Type=oneshot -p Restart=on-failure /bin/bash -c "exit 1"
+systemd-run --unit=one -p Type=oneshot -p Restart=on-failure /bin/bash -c "exit 1" \
+    && { echo 'unexpected success'; exit 1; }
 
-for ((secs=0; secs<$MAX_SECS; secs++)); do
+for ((secs = 0; secs < MAX_SECS; secs++)); do
   [[ "$(systemctl show one.service -P NRestarts)" -le 0 ]] || break
   sleep 1
 done
@@ -25,10 +26,16 @@ TMP_FILE="/tmp/test-41-oneshot-restart-test"
 
 # test two: make sure StartLimitBurst correctly limits the number of restarts
 # and restarts execution of the unit from the first ExecStart=
-! systemd-run --unit=two -p StartLimitIntervalSec=120 -p StartLimitBurst=3 -p Type=oneshot -p Restart=on-failure -p ExecStart="/bin/bash -c \"printf a >>  $TMP_FILE\"" /bin/bash -c "exit 1"
+systemd-run --unit=two \
+            -p StartLimitIntervalSec=120 \
+            -p StartLimitBurst=3 \
+            -p Type=oneshot \
+            -p Restart=on-failure \
+            -p ExecStart="/bin/bash -c \"printf a >>  $TMP_FILE\"" /bin/bash -c "exit 1" \
+    && { echo 'unexpected success'; exit 1; }
 
 # wait for at least 3 restarts
-for ((secs=0; secs<$MAX_SECS; secs++)); do
+for ((secs = 0; secs < MAX_SECS; secs++)); do
   [[ $(cat $TMP_FILE) != "aaa" ]] || break
   sleep 1
 done
@@ -44,6 +51,6 @@ fi
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 154398dd662e8a68c4c0b7823eb47403d5229515..e47fab46e6e3cef2c73705a30fe7c61baba54479 100755 (executable)
@@ -1,21 +1,23 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 
 systemd-analyze log-level debug
 
 systemd-run --unit=simple1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=simple -p ExecStopPost='/bin/touch /run/simple1' true
 test -f /run/simple1
 
-! systemd-run --unit=simple2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=simple -p ExecStopPost='/bin/touch /run/simple2' false
+systemd-run --unit=simple2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=simple -p ExecStopPost='/bin/touch /run/simple2' false \
+    && { echo 'unexpected success'; exit 1; }
 test -f /run/simple2
 
 systemd-run --unit=exec1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=exec -p ExecStopPost='/bin/touch /run/exec1' sleep 1
 test -f /run/exec1
 
-! systemd-run --unit=exec2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=exec -p ExecStopPost='/bin/touch /run/exec2' sh -c 'sleep 1; false'
+systemd-run --unit=exec2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=exec -p ExecStopPost='/bin/touch /run/exec2' sh -c 'sleep 1; false' \
+    && { echo 'unexpected success'; exit 1; }
 test -f /run/exec2
 
-cat > /tmp/forking1.sh <<EOF
+cat >/tmp/forking1.sh <<EOF
 #!/usr/bin/env bash
 
 set -eux
@@ -31,7 +33,7 @@ chmod +x /tmp/forking1.sh
 systemd-run --unit=forking1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=forking -p NotifyAccess=exec -p ExecStopPost='/bin/touch /run/forking1' /tmp/forking1.sh
 test -f /run/forking1
 
-cat > /tmp/forking2.sh <<EOF
+cat >/tmp/forking2.sh <<EOF
 #!/usr/bin/env bash
 
 set -eux
@@ -44,13 +46,15 @@ systemd-notify MAINPID=\$MAINPID
 EOF
 chmod +x /tmp/forking2.sh
 
-! systemd-run --unit=forking2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=forking -p NotifyAccess=exec -p ExecStopPost='/bin/touch /run/forking2' /tmp/forking2.sh
+systemd-run --unit=forking2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=forking -p NotifyAccess=exec -p ExecStopPost='/bin/touch /run/forking2' /tmp/forking2.sh \
+    && { echo 'unexpected success'; exit 1; }
 test -f /run/forking2
 
 systemd-run --unit=oneshot1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=oneshot -p ExecStopPost='/bin/touch /run/oneshot1' true
 test -f /run/oneshot1
 
-! systemd-run --unit=oneshot2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=oneshot -p ExecStopPost='/bin/touch /run/oneshot2' false
+systemd-run --unit=oneshot2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=oneshot -p ExecStopPost='/bin/touch /run/oneshot2' false \
+    && { echo 'unexpected success'; exit 1; }
 test -f /run/oneshot2
 
 systemd-run --unit=dbus1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=dbus -p BusName=systemd.test.ExecStopPost -p ExecStopPost='/bin/touch /run/dbus1' \
@@ -58,10 +62,10 @@ systemd-run --unit=dbus1.service --wait -p StandardOutput=tty -p StandardError=t
     || :
 test -f /run/dbus1
 
-systemd-run --unit=dbus2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=dbus -p BusName=systemd.test.ExecStopPost -p ExecStopPost='/bin/touch /run/dbus2' true
+systemd-run --unit=dbus2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=dbus -p BusName=systemd.test.ExecStopPost -p ExecStopPost='/bin/touch /run/dbus2' true
 test -f /run/dbus2
 
-cat > /tmp/notify1.sh <<EOF
+cat >/tmp/notify1.sh <<EOF
 #!/usr/bin/env bash
 
 set -eux
@@ -73,17 +77,19 @@ chmod +x /tmp/notify1.sh
 systemd-run --unit=notify1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=notify -p ExecStopPost='/bin/touch /run/notify1' /tmp/notify1.sh
 test -f /run/notify1
 
-! systemd-run --unit=notify2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=notify -p ExecStopPost='/bin/touch /run/notify2' true
+systemd-run --unit=notify2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=notify -p ExecStopPost='/bin/touch /run/notify2' true \
+    && { echo 'unexpected success'; exit 1; }
 test -f /run/notify2
 
 systemd-run --unit=idle1.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=idle -p ExecStopPost='/bin/touch /run/idle1' true
 test -f /run/idle1
 
-! systemd-run --unit=idle2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=idle -p ExecStopPost='/bin/touch /run/idle2' false
+systemd-run --unit=idle2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=idle -p ExecStopPost='/bin/touch /run/idle2' false \
+     && { echo 'unexpected success'; exit 1; }
 test -f /run/idle2
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index ec84868a21271cbc07591c636b359c286925cdb3..c6399f9920bb1882b20aa67992cbe1daf7325c75 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 systemd-analyze log-level debug
@@ -7,6 +7,7 @@ systemd-analyze log-level debug
 runas() {
     declare userid=$1
     shift
+    # shellcheck disable=SC2016
     su "$userid" -s /bin/sh -c 'XDG_RUNTIME_DIR=/run/user/$UID exec "$@"' -- sh "$@"
 }
 
@@ -34,9 +35,10 @@ test -e /home/testuser/works.txt
 runas testuser systemd-run --wait --user --unit=test-protect-home-read-only \
     -p PrivateUsers=yes -p ProtectHome=read-only \
     -P bash -c '
-        test -e /home/testuser/works.txt
-        ! touch /home/testuser/blocked.txt
-    '
+        test -e /home/testuser/works.txt || exit 10
+        touch /home/testuser/blocked.txt && exit 11
+    ' \
+        && { echo 'unexpected success'; exit 1; }
 test ! -e /home/testuser/blocked.txt
 
 # Check that tmpfs hides the whole directory
@@ -45,6 +47,7 @@ runas testuser systemd-run --wait --user --unit=test-protect-home-tmpfs \
     -P test ! -e /home/testuser
 
 # Confirm that home, /root, and /run/user are inaccessible under "yes"
+# shellcheck disable=SC2016
 runas testuser systemd-run --wait --user --unit=test-protect-home-yes \
     -p PrivateUsers=yes -p ProtectHome=yes \
     -P bash -c '
@@ -57,12 +60,13 @@ runas testuser systemd-run --wait --user --unit=test-protect-home-yes \
 # namespace (no CAP_SETGID in the parent namespace to write the additional
 # mapping of the user supplied group and thus cannot change groups to an
 # unmapped group ID)
-runas testuser systemd-run --wait --user --unit=test-group-fail \
+runas testuser systemd-run --wait --user --unit=test-group-fail \
     -p PrivateUsers=yes -p Group=daemon \
-    -P true
+    -P true \
+    && { echo 'unexpected success'; exit 1; }
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 97541634d05b8a816f234f1d4e79422c8bf175cb..0100b31b576978534ae20d3155e58bd7bb683b5f 100755 (executable)
@@ -1,19 +1,19 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 
 systemd-analyze log-level debug
 
-systemd-run -p LogNamespace=foobar echo "hello world"
+systemd-run --wait -p LogNamespace=foobar echo "hello world"
 
 journalctl --namespace=foobar --sync
-journalctl --namespace=foobar > /tmp/hello-world
-journalctl /tmp/no-hello-world
+journalctl -o cat --namespace=foobar >/tmp/hello-world
+journalctl -o cat >/tmp/no-hello-world
 
-grep "hello world" /tmp/hello-world
-! grep "hello world" /tmp/no-hello-world
+grep "^hello world$" /tmp/hello-world
+grep "^hello world$" /tmp/no-hello-world && { echo 'unexpected success'; exit 1; }
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 00bbdf507e62f79b4a4c2878dacbeebfe50fe2bd..808270f33d917dbe99b1a24d1a307f0d107269ce 100755 (executable)
@@ -1,25 +1,25 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 # Check if homectl is installed, and if it isn't bail out early instead of failing
 if ! test -x /usr/bin/homectl ; then
-        echo OK > /testok
+        echo OK >/testok
         exit 0
 fi
 
 inspect() {
-        # As updating disk-size-related attributes can take some time on
-        # some filesystems, let's drop these fields before comparing the
-        # outputs to avoid unexpected fails. To see the full outputs of both
-        # homectl & userdbctl (for debugging purposes) drop the fields just
-        # before the comparison.
-        homectl inspect $1 | tee /tmp/a
-        userdbctl user $1 | tee /tmp/b
-
-        local PATTERN='/^\s*Disk (Size|Free|Floor|Ceiling):/d'
-        diff <(sed -r "$PATTERN" /tmp/a) <(sed -r "$PATTERN" /tmp/b)
-        rm /tmp/a /tmp/b
+    # As updating disk-size-related attributes can take some time on some
+    # filesystems, let's drop these fields before comparing the outputs to
+    # avoid unexpected fails. To see the full outputs of both homectl &
+    # userdbctl (for debugging purposes) drop the fields just before the
+    # comparison.
+    local USERNAME="${1:?missing argument}"
+    homectl inspect "$USERNAME" | tee /tmp/a
+    userdbctl user "$USERNAME" | tee /tmp/b
+
+    diff -I '/^\s*Disk (Size|Free|Floor|Ceiling):/' /tmp/{a,b}
+    rm /tmp/{a,b}
 }
 
 systemd-analyze log-level debug
@@ -66,16 +66,20 @@ inspect test-user
 PASSWORD=xEhErW0ndafV4s homectl deactivate test-user
 inspect test-user
 
-! PASSWORD=xEhErW0ndafV4s homectl with test-user -- test -f /home/test-user/xyz
+PASSWORD=xEhErW0ndafV4s homectl with test-user -- test ! -f /home/test-user/xyz
+PASSWORD=xEhErW0ndafV4s homectl with test-user -- test -f /home/test-user/xyz \
+    && { echo 'unexpected success'; exit 1; }
 PASSWORD=xEhErW0ndafV4s homectl with test-user -- touch /home/test-user/xyz
 PASSWORD=xEhErW0ndafV4s homectl with test-user -- test -f /home/test-user/xyz
 PASSWORD=xEhErW0ndafV4s homectl with test-user -- rm /home/test-user/xyz
-! PASSWORD=xEhErW0ndafV4s homectl with test-user -- test -f /home/test-user/xyz
+PASSWORD=xEhErW0ndafV4s homectl with test-user -- test ! -f /home/test-user/xyz
+PASSWORD=xEhErW0ndafV4s homectl with test-user -- test -f /home/test-user/xyz \
+    && { echo 'unexpected success'; exit 1; }
 
 homectl remove test-user
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 8c34289c529602223d99fe854fb6d9e1232d28c7..b008f52e9521e33cd2c8988b026efa298e240fcd 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
 
 sleep infinity &
-echo $! > /leakedtestpid
+echo $! >/leakedtestpid
 wait $!
index 50034cf3d9a5e9af2c6ccfd1cfbcf60a79d21ebc..c1714d14d0e39a9b91291a0bae801f1ac9e2b5dd 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 systemd-analyze log-level debug
@@ -20,6 +20,6 @@ ps -p "$leaked_pid" && exit 42
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 03231e71b183b3f1f76fac1d1bd641ad9b98404e..147f6fa54fa8669da3aca629bf4bbbefe8c01ea2 100755 (executable)
@@ -1,9 +1,9 @@
 #!/usr/bin/env bash
 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
 # ex: ts=8 sw=4 sts=4 et filetype=sh
-set -ex
+set -eux
 
-cat > /run/systemd/system/testservice-48.target <<EOF
+cat >/run/systemd/system/testservice-48.target <<EOF
 [Unit]
 Wants=testservice-48.service
 EOF
@@ -16,14 +16,14 @@ systemctl start testservice-48.target
 # granularity of one second, which means the manager's unit cache won't be
 # marked as dirty when writing the unit file, unless we wait at least a full
 # second after the previous daemon-reload.
-# May 07 23:12:20 systemd-testsuite testsuite-48.sh[30]: + cat
-# May 07 23:12:20 systemd-testsuite testsuite-48.sh[30]: + ls -l --full-time /etc/systemd/system/testservice-48.service
-# May 07 23:12:20 systemd-testsuite testsuite-48.sh[52]: -rw-r--r-- 1 root root 50 2020-05-07 23:12:20.000000000 +0100 /
-# May 07 23:12:20 systemd-testsuite testsuite-48.sh[30]: + stat -f --format=%t /etc/systemd/system/testservice-48.servic
-# May 07 23:12:20 systemd-testsuite testsuite-48.sh[53]: ef53
+# May 07 23:12:20 H testsuite-48.sh[30]: + cat
+# May 07 23:12:20 H testsuite-48.sh[30]: + ls -l --full-time /etc/systemd/system/testservice-48.service
+# May 07 23:12:20 H testsuite-48.sh[52]: -rw-r--r-- 1 root root 50 2020-05-07 23:12:20.000000000 +0100 /
+# May 07 23:12:20 H testsuite-48.sh[30]: + stat -f --format=%t /etc/systemd/system/testservice-48.servic
+# May 07 23:12:20 H testsuite-48.sh[53]: ef53
 sleep 3.1
 
-cat > /run/systemd/system/testservice-48.service <<EOF
+cat >/run/systemd/system/testservice-48.service <<EOF
 [Service]
 ExecStart=/bin/sleep infinity
 EOF
@@ -39,7 +39,7 @@ systemctl daemon-reload
 
 sleep 3.1
 
-cat > /run/systemd/system/testservice-48.service <<EOF
+cat >/run/systemd/system/testservice-48.service <<EOF
 [Service]
 ExecStart=/bin/sleep infinity
 EOF
@@ -61,7 +61,7 @@ systemctl daemon-reload
 
 sleep 3.1
 
-cat > /run/systemd/system/testservice-48.target <<EOF
+cat >/run/systemd/system/testservice-48.target <<EOF
 [Unit]
 Conflicts=shutdown.target
 Wants=testservice-48.service
@@ -71,7 +71,7 @@ systemctl daemon-reload
 
 systemctl start testservice-48.target
 
-cat > /run/systemd/system/testservice-48.service <<EOF
+cat >/run/systemd/system/testservice-48.service <<EOF
 [Service]
 ExecStart=/bin/sleep infinity
 EOF
@@ -80,6 +80,6 @@ systemctl restart testservice-48.target
 
 systemctl is-active testservice-48.service
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 07bb20d99c67f5f39e77f62099bc9216e6ad85df..8e360b4951c4900ef0b28f2e2fdcbdebd9d0ae3b 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 
-echo "MARKER_FIXED" > /run/testservice-49-fixed
+echo "MARKER_FIXED" >/run/testservice-49-fixed
 mkdir -p /run/inaccessible
 
 systemctl start testsuite-49-namespaced.service
@@ -11,7 +11,7 @@ set +e
 systemctl bind --mkdir testsuite-49-namespaced.service /run/testservice-49-fixed /run/inaccessible/testfile_fixed && exit 1
 set -e
 
-echo "MARKER_RUNTIME" > /run/testservice-49-runtime
+echo "MARKER_RUNTIME" >/run/testservice-49-runtime
 
 systemctl bind --mkdir testsuite-49-namespaced.service /run/testservice-49-runtime /tmp/testfile_runtime
 
@@ -38,6 +38,6 @@ set +e
 systemctl is-active testsuite-49-non-namespaced.service && exit 1
 set -e
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index b4a5fee842eb0a83efeefd619205660ac4bf6ae9..081a8bcb953d2458bd3fd363fad320261c3de5f9 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
 # ex: ts=8 sw=4 sts=4 et filetype=sh
-set -ex
+set -eux
 set -o pipefail
 
 export SYSTEMD_LOG_LEVEL=debug
@@ -26,48 +26,48 @@ trap cleanup EXIT
 
 cp /usr/share/minimal* "${image_dir}/"
 image="${image_dir}/minimal_0"
-roothash="$(cat ${image}.roothash)"
-
-os_release=$(test -e /etc/os-release && echo /etc/os-release || echo /usr/lib/os-release)
-
-systemd-dissect --json=short ${image}.raw | grep -q -F '{"rw":"ro","designator":"root","partition_uuid":null,"fstype":"squashfs","architecture":null,"verity":"external"'
-systemd-dissect ${image}.raw | grep -q -F "MARKER=1"
-systemd-dissect ${image}.raw | grep -q -F -f $os_release
-
-mv ${image}.verity ${image}.fooverity
-mv ${image}.roothash ${image}.foohash
-systemd-dissect --json=short ${image}.raw --root-hash=${roothash} --verity-data=${image}.fooverity | grep -q -F '{"rw":"ro","designator":"root","partition_uuid":null,"fstype":"squashfs","architecture":null,"verity":"external"'
-systemd-dissect ${image}.raw --root-hash=${roothash} --verity-data=${image}.fooverity | grep -q -F "MARKER=1"
-systemd-dissect ${image}.raw --root-hash=${roothash} --verity-data=${image}.fooverity | grep -q -F -f $os_release
-mv ${image}.fooverity ${image}.verity
-mv ${image}.foohash ${image}.roothash
-
-mkdir -p ${image_dir}/mount ${image_dir}/mount2
-systemd-dissect --mount ${image}.raw ${image_dir}/mount
-cat ${image_dir}/mount/usr/lib/os-release | grep -q -F -f $os_release
-cat ${image_dir}/mount/etc/os-release | grep -q -F -f $os_release
-cat ${image_dir}/mount/usr/lib/os-release | grep -q -F "MARKER=1"
+roothash="$(cat "${image}.roothash")"
+
+os_release="$(test -e /etc/os-release && echo /etc/os-release || echo /usr/lib/os-release)"
+
+systemd-dissect --json=short "${image}.raw" | grep -q -F '{"rw":"ro","designator":"root","partition_uuid":null,"partition_label":null,"fstype":"squashfs","architecture":null,"verity":"external"'
+systemd-dissect "${image}.raw" | grep -q -F "MARKER=1"
+systemd-dissect "${image}.raw" | grep -q -F -f <(sed 's/"//g' "$os_release")
+
+mv "${image}.verity" "${image}.fooverity"
+mv "${image}.roothash" "${image}.foohash"
+systemd-dissect --json=short "${image}.raw" --root-hash="${roothash}" --verity-data="${image}.fooverity" | grep -q -F '{"rw":"ro","designator":"root","partition_uuid":null,"partition_label":null,"fstype":"squashfs","architecture":null,"verity":"external"'
+systemd-dissect "${image}.raw" --root-hash="${roothash}" --verity-data="${image}.fooverity" | grep -q -F "MARKER=1"
+systemd-dissect "${image}.raw" --root-hash="${roothash}" --verity-data="${image}.fooverity" | grep -q -F -f <(sed 's/"//g' "$os_release")
+mv "${image}.fooverity" "${image}.verity"
+mv "${image}.foohash" "${image}.roothash"
+
+mkdir -p "${image_dir}/mount" "${image_dir}/mount2"
+systemd-dissect --mount "${image}.raw" "${image_dir}/mount"
+grep -q -F -f "$os_release" "${image_dir}/mount/usr/lib/os-release"
+grep -q -F -f "$os_release" "${image_dir}/mount/etc/os-release"
+grep -q -F "MARKER=1" "${image_dir}/mount/usr/lib/os-release"
 # Verity volume should be shared (opened only once)
-systemd-dissect --mount ${image}.raw ${image_dir}/mount2
-verity_count=$(ls -1 /dev/mapper/ | grep -c verity)
+systemd-dissect --mount "${image}.raw" "${image_dir}/mount2"
+verity_count=$(find /dev/mapper/ -name "*verity*" | wc -l)
 # In theory we should check that count is exactly one. In practice, libdevmapper
 # randomly and unpredictably fails with an unhelpful EINVAL when a device is open
 # (and even mounted and in use), so best-effort is the most we can do for now
-if [ ${verity_count} -lt 1 ]; then
+if [ "${verity_count}" -lt 1 ]; then
     echo "Verity device ${image}.raw not found in /dev/mapper/"
     exit 1
 fi
-umount ${image_dir}/mount
-umount ${image_dir}/mount2
+umount "${image_dir}/mount"
+umount "${image_dir}/mount2"
 
-systemd-run -t -p RootImage=${image}.raw cat /usr/lib/os-release | grep -q -F "MARKER=1"
-mv ${image}.verity ${image}.fooverity
-mv ${image}.roothash ${image}.foohash
-systemd-run -t -p RootImage=${image}.raw -p RootHash=${image}.foohash -p RootVerity=${image}.fooverity cat /usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -P -p RootImage="${image}.raw" cat /usr/lib/os-release | grep -q -F "MARKER=1"
+mv "${image}.verity" "${image}.fooverity"
+mv "${image}.roothash" "${image}.foohash"
+systemd-run -P -p RootImage="${image}.raw" -p RootHash="${image}.foohash" -p RootVerity="${image}.fooverity" cat /usr/lib/os-release | grep -q -F "MARKER=1"
 # Let's use the long option name just here as a test
-systemd-run -t --property RootImage=${image}.raw --property RootHash=${roothash} --property RootVerity=${image}.fooverity cat /usr/lib/os-release | grep -q -F "MARKER=1"
-mv ${image}.fooverity ${image}.verity
-mv ${image}.foohash ${image}.roothash
+systemd-run -P --property RootImage="${image}.raw" --property RootHash="${roothash}" --property RootVerity="${image}.fooverity" cat /usr/lib/os-release | grep -q -F "MARKER=1"
+mv "${image}.fooverity" "${image}.verity"
+mv "${image}.foohash" "${image}.roothash"
 
 # Make a GPT disk on the fly, with the squashfs as partition 1 and the verity hash tree as partition 2
 machine="$(uname -m)"
@@ -100,51 +100,54 @@ else
     exit 1
 fi
 # du rounds up to block size, which is more helpful for partitioning
-root_size="$(du -k ${image}.raw | cut -f1)"
-verity_size="$(du -k ${image}.verity | cut -f1)"
+root_size="$(du -k "${image}.raw" | cut -f1)"
+verity_size="$(du -k "${image}.verity" | cut -f1)"
 # 4MB seems to be the minimum size blkid will accept, below that probing fails
-dd if=/dev/zero of=${image}.gpt bs=512 count=$((8192+${root_size}*2+${verity_size}*2))
+dd if=/dev/zero of="${image}.gpt" bs=512 count=$((8192+root_size*2+verity_size*2))
 # sfdisk seems unhappy if the size overflows into the next unit, eg: 1580KiB will be interpreted as 1MiB
 # so do some basic rounding up if the minimal image is more than 1 MB
-if [ ${root_size} -ge 1024 ]; then
-    root_size="$((${root_size}/1024 + 1))MiB"
+if [ "${root_size}" -ge 1024 ]; then
+    root_size="$((root_size/1024 + 1))MiB"
 else
     root_size="${root_size}KiB"
 fi
-verity_size="$((${verity_size} * 2))KiB"
-uuid="$(head -c 32 ${image}.roothash | cut -c -8)-$(head -c 32 ${image}.roothash | cut -c 9-12)-$(head -c 32 ${image}.roothash | cut -c 13-16)-$(head -c 32 ${image}.roothash | cut -c 17-20)-$(head -c 32 ${image}.roothash | cut -c 21-)"
-echo -e "label: gpt\nsize=${root_size}, type=${root_guid}, uuid=${uuid}" | sfdisk ${image}.gpt
-uuid="$(tail -c 32 ${image}.roothash | cut -c -8)-$(tail -c 32 ${image}.roothash | cut -c 9-12)-$(tail -c 32 ${image}.roothash | cut -c 13-16)-$(tail -c 32 ${image}.roothash | cut -c 17-20)-$(tail -c 32 ${image}.roothash | cut -c 21-)"
-echo -e "size=${verity_size}, type=${verity_guid}, uuid=${uuid}" | sfdisk ${image}.gpt --append
-sfdisk --part-label ${image}.gpt 1 "Root Partition"
-sfdisk --part-label ${image}.gpt 2 "Verity Partition"
-loop="$(losetup --show -P -f ${image}.gpt)"
-dd if=${image}.raw of=${loop}p1
-dd if=${image}.verity of=${loop}p2
-losetup -d ${loop}
+verity_size="$((verity_size * 2))KiB"
+# Construct a UUID from hash
+# input:  11111111222233334444555566667777
+# output: 11111111-2222-3333-4444-555566667777
+uuid="$(head -c 32 "${image}.roothash" | sed -r 's/(.{8})(.{4})(.{4})(.{4})(.+)/\1-\2-\3-\4-\5/')"
+echo -e "label: gpt\nsize=${root_size}, type=${root_guid}, uuid=${uuid}" | sfdisk "${image}.gpt"
+uuid="$(tail -c 32 "${image}.roothash" | sed -r 's/(.{8})(.{4})(.{4})(.{4})(.+)/\1-\2-\3-\4-\5/')"
+echo -e "size=${verity_size}, type=${verity_guid}, uuid=${uuid}" | sfdisk "${image}.gpt" --append
+sfdisk --part-label "${image}.gpt" 1 "Root Partition"
+sfdisk --part-label "${image}.gpt" 2 "Verity Partition"
+loop="$(losetup --show -P -f "${image}.gpt")"
+dd if="${image}.raw" of="${loop}p1"
+dd if="${image}.verity" of="${loop}p2"
+losetup -d "${loop}"
 
 # Derive partition UUIDs from root hash, in UUID syntax
-ROOT_UUID=$(systemd-id128 -u show $(head -c 32 ${image}.roothash) -u | tail -n 1 | cut -b 6-)
-VERITY_UUID=$(systemd-id128 -u show $(tail -c 32 ${image}.roothash) -u | tail -n 1 | cut -b 6-)
+ROOT_UUID="$(systemd-id128 -u show "$(head -c 32 "${image}.roothash")" -u | tail -n 1 | cut -b 6-)"
+VERITY_UUID="$(systemd-id128 -u show "$(tail -c 32 "${image}.roothash")" -u | tail -n 1 | cut -b 6-)"
 
-systemd-dissect --json=short --root-hash ${roothash} ${image}.gpt | grep -q '{"rw":"ro","designator":"root","partition_uuid":"'$ROOT_UUID'","fstype":"squashfs","architecture":"'$architecture'","verity":"yes","node":'
-systemd-dissect --json=short --root-hash ${roothash} ${image}.gpt | grep -q '{"rw":"ro","designator":"root-verity","partition_uuid":"'$VERITY_UUID'","fstype":"DM_verity_hash","architecture":"'$architecture'","verity":null,"node":'
-systemd-dissect --root-hash ${roothash} ${image}.gpt | grep -q -F "MARKER=1"
-systemd-dissect --root-hash ${roothash} ${image}.gpt | grep -q -F -f $os_release
+systemd-dissect --json=short --root-hash "${roothash}" "${image}.gpt" | grep -q '{"rw":"ro","designator":"root","partition_uuid":"'"$ROOT_UUID"'","partition_label":"Root Partition","fstype":"squashfs","architecture":"'"$architecture"'","verity":"yes",'
+systemd-dissect --json=short --root-hash "${roothash}" "${image}.gpt" | grep -q '{"rw":"ro","designator":"root-verity","partition_uuid":"'"$VERITY_UUID"'","partition_label":"Verity Partition","fstype":"DM_verity_hash","architecture":"'"$architecture"'","verity":null,'
+systemd-dissect --root-hash "${roothash}" "${image}.gpt" | grep -q -F "MARKER=1"
+systemd-dissect --root-hash "${roothash}" "${image}.gpt" | grep -q -F -f <(sed 's/"//g' "$os_release")
 
-systemd-dissect --root-hash ${roothash} --mount ${image}.gpt ${image_dir}/mount
-cat ${image_dir}/mount/usr/lib/os-release | grep -q -F -f $os_release
-cat ${image_dir}/mount/etc/os-release | grep -q -F -f $os_release
-cat ${image_dir}/mount/usr/lib/os-release | grep -q -F "MARKER=1"
-umount ${image_dir}/mount
+systemd-dissect --root-hash "${roothash}" --mount "${image}.gpt" "${image_dir}/mount"
+grep -q -F -f "$os_release" "${image_dir}/mount/usr/lib/os-release"
+grep -q -F -f "$os_release" "${image_dir}/mount/etc/os-release"
+grep -q -F "MARKER=1" "${image_dir}/mount/usr/lib/os-release"
+umount "${image_dir}/mount"
 
 # add explicit -p MountAPIVFS=yes once to test the parser
-systemd-run -t -p RootImage=${image}.gpt -p RootHash=${roothash} -p MountAPIVFS=yes cat /usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -P -p RootImage="${image}.gpt" -p RootHash="${roothash}" -p MountAPIVFS=yes cat /usr/lib/os-release | grep -q -F "MARKER=1"
 
-systemd-run -t -p RootImage=${image}.raw -p RootImageOptions="root:nosuid,dev home:ro,dev ro,noatime" mount | grep -F "squashfs" | grep -q -F "nosuid"
-systemd-run -t -p RootImage=${image}.gpt -p RootImageOptions="root:ro,noatime root:ro,dev" mount | grep -F "squashfs" | grep -q -F "noatime"
+systemd-run -P -p RootImage="${image}.raw" -p RootImageOptions="root:nosuid,dev home:ro,dev ro,noatime" mount | grep -F "squashfs" | grep -q -F "nosuid"
+systemd-run -P -p RootImage="${image}.gpt" -p RootImageOptions="root:ro,noatime root:ro,dev" mount | grep -F "squashfs" | grep -q -F "noatime"
 
-mkdir -p mkdir -p ${image_dir}/result
+mkdir -p "${image_dir}/result"
 cat >/run/systemd/system/testservice-50a.service <<EOF
 [Service]
 Type=oneshot
@@ -156,8 +159,8 @@ RootImageOptions=root:ro,noatime home:ro,dev relatime,dev
 RootImageOptions=nosuid,dev
 EOF
 systemctl start testservice-50a.service
-grep -F "squashfs" ${image_dir}/result/a | grep -q -F "noatime"
-grep -F "squashfs" ${image_dir}/result/a | grep -q -F -v "nosuid"
+grep -F "squashfs" "${image_dir}/result/a" | grep -q -F "noatime"
+grep -F "squashfs" "${image_dir}/result/a" | grep -q -F -v "nosuid"
 
 cat >/run/systemd/system/testservice-50b.service <<EOF
 [Service]
@@ -172,21 +175,21 @@ RootImageOptions=home:ro,dev nosuid,dev,%%foo
 MountAPIVFS=yes
 EOF
 systemctl start testservice-50b.service
-grep -F "squashfs" ${image_dir}/result/b | grep -q -F "noatime"
+grep -F "squashfs" "${image_dir}/result/b" | grep -q -F "noatime"
 
 # Check that specifier escape is applied %%foo → %foo
 busctl get-property org.freedesktop.systemd1 /org/freedesktop/systemd1/unit/testservice_2d50b_2eservice org.freedesktop.systemd1.Service RootImageOptions | grep -F "nosuid,dev,%foo"
 
 # Now do some checks with MountImages, both by itself, with options and in combination with RootImage, and as single FS or GPT image
-systemd-run -t -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /run/img1/usr/lib/os-release | grep -q -F "MARKER=1"
-systemd-run -t -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /run/img2/usr/lib/os-release | grep -q -F "MARKER=1"
-systemd-run -t -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2:nosuid,dev" mount | grep -F "squashfs" | grep -q -F "nosuid"
-systemd-run -t -p MountImages="${image}.gpt:/run/img1:root:nosuid ${image}.raw:/run/img2:home:suid" mount | grep -F "squashfs" | grep -q -F "nosuid"
-systemd-run -t -p MountImages="${image}.raw:/run/img2\:3" cat /run/img2:3/usr/lib/os-release | grep -q -F "MARKER=1"
-systemd-run -t -p MountImages="${image}.raw:/run/img2\:3:nosuid" mount | grep -F "squashfs" | grep -q -F "nosuid"
-systemd-run -t -p TemporaryFileSystem=/run -p RootImage=${image}.raw -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /usr/lib/os-release | grep -q -F "MARKER=1"
-systemd-run -t -p TemporaryFileSystem=/run -p RootImage=${image}.raw -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /run/img1/usr/lib/os-release | grep -q -F "MARKER=1"
-systemd-run -t -p TemporaryFileSystem=/run -p RootImage=${image}.gpt -p RootHash=${roothash} -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /run/img2/usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -P -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /run/img1/usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -P -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /run/img2/usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -P -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2:nosuid,dev" mount | grep -F "squashfs" | grep -q -F "nosuid"
+systemd-run -P -p MountImages="${image}.gpt:/run/img1:root:nosuid ${image}.raw:/run/img2:home:suid" mount | grep -F "squashfs" | grep -q -F "nosuid"
+systemd-run -P -p MountImages="${image}.raw:/run/img2\:3" cat /run/img2:3/usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -P -p MountImages="${image}.raw:/run/img2\:3:nosuid" mount | grep -F "squashfs" | grep -q -F "nosuid"
+systemd-run -P -p TemporaryFileSystem=/run -p RootImage="${image}.raw" -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -P -p TemporaryFileSystem=/run -p RootImage="${image}.raw" -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /run/img1/usr/lib/os-release | grep -q -F "MARKER=1"
+systemd-run -P -p TemporaryFileSystem=/run -p RootImage="${image}.gpt" -p RootHash="${roothash}" -p MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" cat /run/img2/usr/lib/os-release | grep -q -F "MARKER=1"
 cat >/run/systemd/system/testservice-50c.service <<EOF
 [Service]
 MountAPIVFS=yes
@@ -201,13 +204,13 @@ BindPaths=${image_dir}/result:/run/result
 Type=oneshot
 EOF
 systemctl start testservice-50c.service
-grep -q -F "MARKER=1" ${image_dir}/result/c
-grep -F "squashfs" ${image_dir}/result/c | grep -q -F "noatime"
-grep -F "squashfs" ${image_dir}/result/c | grep -q -F -v "nosuid"
+grep -q -F "MARKER=1" "${image_dir}/result/c"
+grep -F "squashfs" "${image_dir}/result/c" | grep -q -F "noatime"
+grep -F "squashfs" "${image_dir}/result/c" | grep -q -F -v "nosuid"
 
 # Adding a new mounts at runtime works if the unit is in the active state,
 # so use Type=notify to make sure there's no race condition in the test
-cat > /run/systemd/system/testservice-50d.service <<EOF
+cat >/run/systemd/system/testservice-50d.service <<EOF
 [Service]
 RuntimeMaxSec=300
 Type=notify
@@ -218,7 +221,7 @@ ExecStart=/bin/sh -c 'systemd-notify --ready; while ! grep -q -F MARKER /tmp/img
 EOF
 systemctl start testservice-50d.service
 
-systemctl mount-image --mkdir testservice-50d.service ${image}.raw /tmp/img root:nosuid
+systemctl mount-image --mkdir testservice-50d.service "${image}.raw" /tmp/img root:nosuid
 
 while systemctl show -P SubState testservice-50d.service | grep -q running
 do
@@ -228,12 +231,12 @@ done
 systemctl is-active testservice-50d.service
 
 # ExtensionImages will set up an overlay
-systemd-run -t --property ExtensionImages=/usr/share/app0.raw --property RootImage=${image}.raw cat /opt/script0.sh | grep -q -F "extension-release.app0"
-systemd-run -t --property ExtensionImages=/usr/share/app0.raw --property RootImage=${image}.raw cat /usr/lib/systemd/system/some_file | grep -q -F "MARKER=1"
-systemd-run -t --property ExtensionImages="/usr/share/app0.raw /usr/share/app1.raw" --property RootImage=${image}.raw cat /opt/script0.sh | grep -q -F "extension-release.app0"
-systemd-run -t --property ExtensionImages="/usr/share/app0.raw /usr/share/app1.raw" --property RootImage=${image}.raw cat /usr/lib/systemd/system/some_file | grep -q -F "MARKER=1"
-systemd-run -t --property ExtensionImages="/usr/share/app0.raw /usr/share/app1.raw" --property RootImage=${image}.raw cat /opt/script1.sh | grep -q -F "extension-release.app1"
-systemd-run -t --property ExtensionImages="/usr/share/app0.raw /usr/share/app1.raw" --property RootImage=${image}.raw cat /usr/lib/systemd/system/other_file | grep -q -F "MARKER=1"
+systemd-run -P --property ExtensionImages=/usr/share/app0.raw --property RootImage="${image}.raw" cat /opt/script0.sh | grep -q -F "extension-release.app0"
+systemd-run -P --property ExtensionImages=/usr/share/app0.raw --property RootImage="${image}.raw" cat /usr/lib/systemd/system/some_file | grep -q -F "MARKER=1"
+systemd-run -P --property ExtensionImages="/usr/share/app0.raw /usr/share/app1.raw" --property RootImage="${image}.raw" cat /opt/script0.sh | grep -q -F "extension-release.app0"
+systemd-run -P --property ExtensionImages="/usr/share/app0.raw /usr/share/app1.raw" --property RootImage="${image}.raw" cat /usr/lib/systemd/system/some_file | grep -q -F "MARKER=1"
+systemd-run -P --property ExtensionImages="/usr/share/app0.raw /usr/share/app1.raw" --property RootImage="${image}.raw" cat /opt/script1.sh | grep -q -F "extension-release.app1"
+systemd-run -P --property ExtensionImages="/usr/share/app0.raw /usr/share/app1.raw" --property RootImage="${image}.raw" cat /usr/lib/systemd/system/other_file | grep -q -F "MARKER=1"
 cat >/run/systemd/system/testservice-50e.service <<EOF
 [Service]
 MountAPIVFS=yes
index 246412a07986bbd31fff1ff405d9114637307820..06bc1602f874bfe69e487dea615f810fc460f976 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 systemctl start testsuite-51-repro-1
similarity index 51%
rename from test/testsuite-52.units/testsuite-52.service
rename to test/units/testsuite-52.service
index 93f847f0445beaf71db3bd29f2f518324758131d..bab540773a5a24cacff42c9371e35fee51ea8988 100644 (file)
@@ -2,5 +2,5 @@
 Description=Testsuite service
 
 [Service]
-ExecStart=/usr/lib/systemd/tests/testdata/%N.units/%N.sh
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
 Type=oneshot
similarity index 52%
rename from test/testsuite-52.units/testsuite-52.sh
rename to test/units/testsuite-52.sh
index 9cccf1b6c161ec5199a69cb14f19ab13cc4997fa..ea133dbaadf6a0fefb677882e1bea92b0225744a 100755 (executable)
@@ -2,17 +2,12 @@
 set -ex
 set -o pipefail
 
-if ! test -x /usr/lib/systemd/tests/testdata/units/test-honor-first-shutdown.sh ; then
-        echo "honor-first-shutdown script not found - FAIL" > /testok
-        exit 0
-fi
-
 systemd-analyze log-level debug
 systemd-analyze log-target console
 
 systemctl enable test-honor-first-shutdown.service
 systemctl start test-honor-first-shutdown.service
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index 3536c2427125ac4b7e931aac9d6bbcb29dda0e23..3eef94bc148fab082f0b62cd21bccad9752397c9 100755 (executable)
@@ -1,8 +1,8 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
->/failed
+>/failed
 
 # Reset host date to current time, 3 days in the past.
 date -s "-3 days"
index aabc56f3481fa6885cc8c44b69921ae5c8ed519b..f8ddff4a30567f437ceeec6ee7805a7560c4d74f 100755 (executable)
@@ -1,5 +1,6 @@
 #!/usr/bin/env bash
-set -ex
+# shellcheck disable=SC2016
+set -eux
 
 systemd-analyze log-level debug
 
@@ -10,22 +11,24 @@ systemd-run -p LoadCredential=passwd:/etc/passwd \
             -p DynamicUser=1 \
             --wait \
             --pipe \
-            cat '${CREDENTIALS_DIRECTORY}/passwd' '${CREDENTIALS_DIRECTORY}/shadow' '${CREDENTIALS_DIRECTORY}/dog' > /tmp/ts54-concat
+            cat '${CREDENTIALS_DIRECTORY}/passwd' '${CREDENTIALS_DIRECTORY}/shadow' '${CREDENTIALS_DIRECTORY}/dog' >/tmp/ts54-concat
 ( cat /etc/passwd /etc/shadow && echo -n wuff ) | cmp /tmp/ts54-concat
 rm /tmp/ts54-concat
 
 # Verify that the creds are immutable
-systemd-run -p LoadCredential=passwd:/etc/passwd \
+systemd-run -p LoadCredential=passwd:/etc/passwd \
             -p DynamicUser=1 \
             --wait \
-            touch '${CREDENTIALS_DIRECTORY}/passwd'
-! systemd-run -p LoadCredential=passwd:/etc/passwd \
+            touch '${CREDENTIALS_DIRECTORY}/passwd' \
+    && { echo 'unexpected success'; exit 1; }
+systemd-run -p LoadCredential=passwd:/etc/passwd \
             -p DynamicUser=1 \
             --wait \
-            rm '${CREDENTIALS_DIRECTORY}/passwd'
+            rm '${CREDENTIALS_DIRECTORY}/passwd' \
+    && { echo 'unexpected success'; exit 1; }
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
index ff5a74734827e494b5bb8a3b17ff7a642b1d9c55..d1595ad150297a18b8d9d51e6209a7804f7a5686 100755 (executable)
@@ -1,32 +1,37 @@
 #!/usr/bin/env bash
-set -eu -o pipefail
+# Don't use set -x here, since it generates a lot of output and slows
+# the script down, causing unexpected test fails.
+set -eu
+set -o pipefail
 
 PAGE_SIZE=$(getconf PAGE_SIZE)
-BLOAT_ITERATION_TARGET=$(( 100 << 20 )) # 100 MB
+BLOAT_ITERATION_TARGET=$((100 << 20)) # 100 MB
 BLOAT_HOLDER=()
 PID="$$"
 
 function bloat {
-        local set_size=$(cat "/proc/$PID/statm" | cut -d " " -f2)
-        local mem_usage=$(( "$set_size" * "$PAGE_SIZE" ))
-        local target_mem_size=$(( "$mem_usage" + "$1" ))
+        local set_size mem_usage target_mem_size
+
+        set_size=$(cut -d " " -f2 "/proc/$PID/statm")
+        mem_usage=$((set_size * PAGE_SIZE))
+        target_mem_size=$((mem_usage + $1))
 
         BLOAT_HOLDER=()
         while [[ "$mem_usage" -lt "$target_mem_size" ]]; do
                 echo "target $target_mem_size"
                 echo "mem usage $mem_usage"
-                BLOAT_HOLDER+=( $(printf "%0.sg" {1..1000000}) )
-                set_size=$(cat "/proc/$PID/statm" | cut -d " " -f2)
-                mem_usage=$(( "$set_size" * "$PAGE_SIZE" ))
+                BLOAT_HOLDER+=("$(printf "=%0.s" {1..1000000})")
+                set_size=$(cut -d " " -f2 "/proc/$PID/statm")
+                mem_usage=$((set_size * PAGE_SIZE))
         done
 }
 
 function run {
         local arr=()
 
-        while [[ true ]]; do
+        while :; do
                 bloat "$BLOAT_ITERATION_TARGET"
-                arr+=( "$BLOAT_HOLDER" )
+                arr+=("${BLOAT_HOLDER[@]}")
                 sleep 1
         done
 }
index f7896ada4274c3d53a5138b345acd121db6d66dd..63549c8a7850a5fec986e39d7007d1dd33fca1df 100755 (executable)
@@ -1,24 +1,27 @@
 #!/usr/bin/env bash
-set -ex
+set -eux
 set -o pipefail
 
 systemd-analyze log-level debug
 systemd-analyze log-target console
 
 # Loose checks to ensure the environment has the necessary features for systemd-oomd
-[[ -e /proc/pressure ]] || echo "no PSI" >> /skipped
-cgroup_type=$(stat -fc %T /sys/fs/cgroup/)
+[[ -e /proc/pressure ]] || echo "no PSI" >>/skipped
+cgroup_type="$(stat -fc %T /sys/fs/cgroup/)"
 if [[ "$cgroup_type" != *"cgroup2"* ]] && [[ "$cgroup_type" != *"0x63677270"* ]]; then
-    echo "no cgroup2" >> /skipped
+    echo "no cgroup2" >>/skipped
 fi
 if [ ! -f /usr/lib/systemd/systemd-oomd ] && [ ! -f /lib/systemd/systemd-oomd ]; then
-    echo "no oomd" >> /skipped
+    echo "no oomd" >>/skipped
+fi
+
+if [[ -e /skipped ]]; then
+    exit 0
 fi
-[[ -e /skipped ]] && exit 0 || true
 
 rm -rf /etc/systemd/system/testsuite-55-testbloat.service.d
 
-echo "DefaultMemoryPressureDurationSec=5s" >> /etc/systemd/oomd.conf
+echo "DefaultMemoryPressureDurationSec=5s" >>/etc/systemd/oomd.conf
 
 systemctl start testsuite-55-testchill.service
 systemctl start testsuite-55-testbloat.service
@@ -30,7 +33,7 @@ oomctl | grep "Default Memory Pressure Duration: 5s"
 
 # systemd-oomd watches for elevated pressure for 5 seconds before acting.
 # It can take time to build up pressure so either wait 2 minutes or for the service to fail.
-timeout=$(date -ud "2 minutes" +%s)
+timeout="$(date -ud "2 minutes" +%s)"
 while [[ $(date -u +%s) -le $timeout ]]; do
     if ! systemctl status testsuite-55-testbloat.service; then
         break
@@ -47,16 +50,16 @@ if setfattr -n user.xattr_test -v 1 /sys/fs/cgroup/; then
     sleep 120 # wait for systemd-oomd kill cool down and elevated memory pressure to come down
 
     mkdir -p /etc/systemd/system/testsuite-55-testbloat.service.d/
-    echo "[Service]" > /etc/systemd/system/testsuite-55-testbloat.service.d/override.conf
-    echo "ManagedOOMPreference=avoid" >> /etc/systemd/system/testsuite-55-testbloat.service.d/override.conf
+    echo "[Service]" >/etc/systemd/system/testsuite-55-testbloat.service.d/override.conf
+    echo "ManagedOOMPreference=avoid" >>/etc/systemd/system/testsuite-55-testbloat.service.d/override.conf
 
     systemctl daemon-reload
     systemctl start testsuite-55-testchill.service
     systemctl start testsuite-55-testmunch.service
     systemctl start testsuite-55-testbloat.service
 
-    timeout=$(date -ud "2 minutes" +%s)
-    while [[ $(date -u +%s) -le $timeout ]]; do
+    timeout="$(date -ud "2 minutes" +%s)"
+    while [[ "$(date -u +%s)" -le "$timeout" ]]; do
         if ! systemctl status testsuite-55-testmunch.service; then
             break
         fi
@@ -71,6 +74,6 @@ fi
 
 systemd-analyze log-level info
 
-echo OK > /testok
+echo OK >/testok
 
 exit 0
diff --git a/test/units/testsuite-56.service b/test/units/testsuite-56.service
new file mode 100644 (file)
index 0000000..d8ad589
--- /dev/null
@@ -0,0 +1,6 @@
+[Unit]
+Description=TEST-56-EXIT-TYPE
+
+[Service]
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
+Type=oneshot
diff --git a/test/units/testsuite-56.sh b/test/units/testsuite-56.sh
new file mode 100755 (executable)
index 0000000..27bd3ca
--- /dev/null
@@ -0,0 +1,98 @@
+#!/usr/bin/env bash
+set -eux
+
+systemd-analyze log-level debug
+
+# Multiple level process tree, parent process stays up
+cat >/tmp/test56-exit-cgroup.sh <<EOF
+#!/usr/bin/env bash
+set -eux
+
+# process tree: systemd -> sleep
+sleep infinity &
+disown
+
+# process tree: systemd -> bash -> bash -> sleep
+((sleep infinity); true) &
+
+# process tree: systemd -> bash -> sleep
+sleep infinity
+EOF
+chmod +x /tmp/test56-exit-cgroup.sh
+
+# service should be stopped cleanly
+(sleep 1; systemctl stop one) &
+systemd-run --wait --unit=one -p ExitType=cgroup /tmp/test56-exit-cgroup.sh
+
+# same thing with a truthy exec condition
+(sleep 1; systemctl stop two) &
+systemd-run --wait --unit=two -p ExitType=cgroup -p ExecCondition=true /tmp/test56-exit-cgroup.sh
+
+# false exec condition: systemd-run should exit immediately with status code: 1
+systemd-run --wait --unit=three -p ExitType=cgroup -p ExecCondition=false /tmp/test56-exit-cgroup.sh \
+    && { echo 'unexpected success'; exit 1; }
+
+# service should exit uncleanly
+(sleep 1; systemctl kill --signal 9 four) &
+systemd-run --wait --unit=four -p ExitType=cgroup /tmp/test56-exit-cgroup.sh \
+    && { echo 'unexpected success'; exit 1; }
+
+
+# Multiple level process tree, parent process exits quickly
+cat >/tmp/test56-exit-cgroup-parentless.sh <<EOF
+#!/usr/bin/env bash
+set -eux
+
+# process tree: systemd -> sleep
+sleep infinity &
+
+# process tree: systemd -> bash -> sleep
+((sleep infinity); true) &
+EOF
+chmod +x /tmp/test56-exit-cgroup-parentless.sh
+
+# service should be stopped cleanly
+(sleep 1; systemctl stop five) &
+systemd-run --wait --unit=five -p ExitType=cgroup /tmp/test56-exit-cgroup-parentless.sh
+
+# service should exit uncleanly
+(sleep 1; systemctl kill --signal 9 six) &
+systemd-run --wait --unit=six -p ExitType=cgroup /tmp/test56-exit-cgroup-parentless.sh \
+    && { echo 'unexpected success'; exit 1; }
+
+
+# Multiple level process tree, parent process exits uncleanly but last process exits cleanly
+cat >/tmp/test56-exit-cgroup-clean.sh <<EOF
+#!/usr/bin/env bash
+set -eux
+
+# process tree: systemd -> bash -> sleep
+(sleep 1; true) &
+
+exit 255
+EOF
+chmod +x /tmp/test56-exit-cgroup-clean.sh
+
+# service should exit cleanly and be garbage-collected
+systemd-run --wait --unit=seven -p ExitType=cgroup /tmp/test56-exit-cgroup-clean.sh
+
+
+# Multiple level process tree, parent process exits cleanly but last process exits uncleanly
+cat >/tmp/test56-exit-cgroup-unclean.sh <<EOF
+#!/usr/bin/env bash
+set -eux
+
+# process tree: systemd -> bash -> sleep
+(sleep 1; exit 255) &
+EOF
+chmod +x /tmp/test56-exit-cgroup-unclean.sh
+
+# service should exit uncleanly after 1 second
+systemd-run --wait --unit=eight -p ExitType=cgroup /tmp/test56-exit-cgroup-unclean.sh \
+    && { echo 'unexpected success'; exit 1; }
+
+systemd-analyze log-level info
+
+echo OK >/testok
+
+exit 0
diff --git a/test/units/testsuite-58.service b/test/units/testsuite-58.service
new file mode 100644 (file)
index 0000000..b962eb0
--- /dev/null
@@ -0,0 +1,6 @@
+[Unit]
+Description=TEST-58-REPART
+
+[Service]
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
+Type=oneshot
diff --git a/test/units/testsuite-58.sh b/test/units/testsuite-58.sh
new file mode 100755 (executable)
index 0000000..13f02f0
--- /dev/null
@@ -0,0 +1,88 @@
+#!/usr/bin/env bash
+set -eux
+set -o pipefail
+
+if ! command -v systemd-repart &>/dev/null; then
+    echo "no systemd-repart" >/skipped
+    exit 0
+fi
+
+export SYSTEMD_LOG_LEVEL=debug
+export PAGER=cat
+
+rm -f /var/tmp/testsuite-58.img /var/tmp/testsuite-58.2.img /tmp/testsuite-58.dump
+mkdir -p /tmp/testsuite-58-defs/
+
+# First part: create a disk image and verify its in order
+
+cat >/tmp/testsuite-58-defs/esp.conf <<EOF
+[Partition]
+Type=esp
+SizeMinBytes=10M
+Format=vfat
+EOF
+
+cat >/tmp/testsuite-58-defs/usr.conf <<EOF
+[Partition]
+Type=usr
+SizeMinBytes=10M
+Format=ext4
+ReadOnly=yes
+EOF
+
+cat >/tmp/testsuite-58-defs/root.conf <<EOF
+[Partition]
+Type=root
+SizeMinBytes=10M
+Format=ext4
+MakeDirectories=/usr /efi
+EOF
+
+systemd-repart --definitions=/tmp/testsuite-58-defs/ \
+               --empty=create \
+               --size=auto \
+               --seed=750b6cd5c4ae4012a15e7be3c29e6a47 \
+               /var/tmp/testsuite-58.img
+
+sfdisk --dump /var/tmp/testsuite-58.img >/tmp/testsuite-58.dump
+
+grep -qxF '/var/tmp/testsuite-58.img1 : start=        2048, size=       20480, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=39107B09-615D-48FB-BA37-C663885FCE67, name="esp"' /tmp/testsuite-58.dump
+grep -qxF '/var/tmp/testsuite-58.img2 : start=       22528, size=       20480, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=60F33797-1D71-4DCB-AA6F-20564F036CD0, name="root-x86-64"' /tmp/testsuite-58.dump
+grep -qxF '/var/tmp/testsuite-58.img3 : start=       43008, size=       20480, type=8484680C-9521-48C6-9C11-B0720656F69E, uuid=7E3369DD-D653-4513-ADF5-B993A9F20C16, name="usr-x86-64", attrs="GUID:60"' /tmp/testsuite-58.dump
+
+# Second part, duplicate it with CopyBlocks=auto
+
+cat >/tmp/testsuite-58-defs/esp.conf <<EOF
+[Partition]
+Type=esp
+CopyBlocks=auto
+EOF
+
+cat >/tmp/testsuite-58-defs/usr.conf <<EOF
+[Partition]
+Type=usr
+ReadOnly=yes
+CopyBlocks=auto
+EOF
+
+cat >/tmp/testsuite-58-defs/root.conf <<EOF
+[Partition]
+Type=root
+CopyBlocks=auto
+EOF
+
+systemd-repart --definitions=/tmp/testsuite-58-defs/ \
+               --empty=create \
+               --size=auto \
+               --seed=750b6cd5c4ae4012a15e7be3c29e6a47 \
+               --image=/var/tmp/testsuite-58.img \
+               /var/tmp/testsuite-58.2.img
+
+cmp /var/tmp/testsuite-58.img /var/tmp/testsuite-58.2.img
+
+rm /var/tmp/testsuite-58.img /var/tmp/testsuite-58.2.img /tmp/testsuite-58.dump
+rm -r /tmp/testsuite-58-defs/
+
+echo OK >/testok
+
+exit 0
diff --git a/test/units/testsuite-59.service b/test/units/testsuite-59.service
new file mode 100644 (file)
index 0000000..66d0686
--- /dev/null
@@ -0,0 +1,6 @@
+[Unit]
+Description=TEST-59-RELOADING-RESTART
+
+[Service]
+Type=oneshot
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
diff --git a/test/units/testsuite-59.sh b/test/units/testsuite-59.sh
new file mode 100755 (executable)
index 0000000..459d6e6
--- /dev/null
@@ -0,0 +1,90 @@
+#!/usr/bin/env bash
+set -eux
+set -o pipefail
+
+fail () {
+    systemd-analyze log-level info
+    exit 1
+}
+
+# Wait for a service to enter a state within a timeout period, if it doesn't
+# enter the desired state within the timeout period then this function will
+# exit the test case with a non zero exit code.
+wait_on_state_or_fail () {
+    service=$1
+    expected_state=$2
+    timeout=$3
+
+    state=$(systemctl show "$service" --property=ActiveState --value)
+    while [ "$state" != "$expected_state" ]; do
+        if [ "$timeout" = "0" ]; then
+            fail
+        fi
+        timeout=$((timeout - 1))
+        sleep 1
+        state=$(systemctl show "$service" --property=ActiveState --value)
+    done
+}
+
+systemd-analyze log-level debug
+systemd-analyze log-target console
+
+
+cat >/run/systemd/system/testservice-fail-59.service <<EOF
+[Unit]
+Description=TEST-59-RELOADING-RESTART Normal exit
+
+[Service]
+Type=notify
+ExecStart=/bin/bash -c "systemd-notify --ready; systemd-notify RELOADING=1; sleep 1; exit 1"
+EOF
+
+cat >/run/systemd/system/testservice-fail-restart-59.service <<EOF
+[Unit]
+Description=TEST-59-RELOADING-RESTART Restart=on-failure
+
+[Service]
+Type=notify
+ExecStart=/bin/bash -c "systemd-notify --ready; systemd-notify RELOADING=1; sleep 1; exit 1"
+Restart=on-failure
+StartLimitBurst=1
+EOF
+
+
+cat >/run/systemd/system/testservice-abort-restart-59.service <<EOF
+[Unit]
+Description=TEST-59-RELOADING-RESTART Restart=on-abort
+
+[Service]
+Type=notify
+ExecStart=/bin/bash -c "systemd-notify --ready; systemd-notify RELOADING=1; sleep 5; exit 1"
+Restart=on-abort
+EOF
+
+systemctl daemon-reload
+
+# This service sends a RELOADING=1 message then exits before it sends a
+# READY=1. Ensure it enters failed state and does not linger in reloading
+# state.
+systemctl start testservice-fail-59.service
+wait_on_state_or_fail "testservice-fail-59.service" "failed" "30"
+
+# This service sends a RELOADING=1 message then exits before it sends a
+# READY=1. It should automatically restart on failure. Ensure it enters failed
+# state and does not linger in reloading state.
+systemctl start testservice-fail-restart-59.service
+wait_on_state_or_fail "testservice-fail-restart-59.service" "failed" "30"
+
+# This service sends a RELOADING=1 message then exits before it sends a
+# READY=1. It should automatically restart on abort. It will sleep for 5s
+# to allow us to send it a SIGABRT. Ensure the service enters the failed state
+# and does not linger in reloading state.
+systemctl start testservice-abort-restart-59.service
+systemctl --signal=SIGABRT kill testservice-abort-restart-59.service
+wait_on_state_or_fail "testservice-abort-restart-59.service" "failed" "30"
+
+systemd-analyze log-level info
+
+echo OK >/testok
+
+exit 0
index 66bbcd64ead3a7ce1e9a2a054448af64d03d7b5a..8cff62e864da9c9a1733b775d1743fe2aa7ca95c 100755 (executable)
@@ -2,9 +2,9 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
 
-cd "$MESON_SOURCE_ROOT"
+cd "${MESON_SOURCE_ROOT:?}"
 
-if [ ! -f .git/hooks/pre-commit.sample -o -f .git/hooks/pre-commit ]; then
+if [ ! -f .git/hooks/pre-commit.sample ] || [ -f .git/hooks/pre-commit ]; then
     exit 2 # not needed
 fi
 
diff --git a/tools/build-bpf-skel.py b/tools/build-bpf-skel.py
new file mode 100755 (executable)
index 0000000..5506fdd
--- /dev/null
@@ -0,0 +1,123 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1+
+
+import argparse
+import logging
+import pathlib
+import subprocess
+import sys
+
+def clang_arch_flag(arch):
+    return '-D__{}__'.format(arch)
+
+
+def target_triplet():
+    gcc_exec = 'gcc'
+
+    try:
+        return subprocess.check_output([gcc_exec, '-dumpmachine'],
+                universal_newlines=True).strip()
+    except subprocess.CalledProcessError as e:
+        logging.error('Failed to get target triplet: {}'.format(e))
+    except FileNotFoundError:
+        logging.error('gcc not installed')
+    return None
+
+
+def clang_compile(clang_exec, clang_flags, src_c, out_file, target_arch,
+        target_triplet):
+    clang_args = [clang_exec, *clang_flags, target_arch, '-I.']
+
+    if target_triplet:
+        clang_args += [
+            '-isystem',
+            '/usr/include/{}'.format(target_triplet)]
+
+    clang_args += [
+        '-idirafter',
+        '/usr/local/include',
+        '-idirafter',
+        '/usr/include']
+
+    clang_args += [src_c, '-o', out_file]
+
+    logging.debug('{}'.format(' '.join(clang_args)))
+    subprocess.check_call(clang_args)
+
+
+def llvm_strip(llvm_strip_exec, in_file):
+    llvm_strip_args = [llvm_strip_exec, '-g', in_file]
+
+    logging.debug('Stripping useless DWARF info:')
+    logging.debug('{}'.format(' '.join(llvm_strip_args)))
+
+    subprocess.check_call(llvm_strip_args)
+
+
+def gen_bpf_skeleton(bpftool_exec, in_file, out_fd):
+    bpftool_args = [bpftool_exec, 'g', 's', in_file]
+
+    logging.debug('Generating BPF skeleton:')
+    logging.debug('{}'.format(' '.join(bpftool_args)))
+    subprocess.check_call(bpftool_args, stdout=out_fd)
+
+
+def bpf_build(args):
+    clang_flags = [
+            '-Wno-compare-distinct-pointer-types',
+            '-O2',
+            '-target',
+            'bpf',
+            '-g',
+            '-c',
+    ]
+
+    clang_out_path = pathlib.Path(args.bpf_src_c).with_suffix('.o')
+    with clang_out_path.open(mode='w') as clang_out, \
+            open(args.bpf_skel_h, mode='w') as bpf_skel_h:
+        clang_compile(clang_exec=args.clang_exec,
+                clang_flags=clang_flags,
+                src_c=args.bpf_src_c,
+                out_file=clang_out.name,
+                target_arch=clang_arch_flag(args.arch),
+                target_triplet=target_triplet())
+
+        llvm_strip(llvm_strip_exec=args.llvm_strip_exec, in_file=clang_out.name)
+
+        gen_bpf_skeleton(bpftool_exec=args.bpftool_exec,
+                in_file=clang_out.name,
+                out_fd=bpf_skel_h)
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser()
+
+    parser.add_argument(
+            'bpf_src_c',
+            help='Path to *.c source of BPF program in systemd source tree \
+                    relative to the work directory')
+
+    parser.add_argument(
+            'bpf_skel_h',
+            help='Path to C header file')
+
+    parser.add_argument(
+            '--clang_exec',
+            help='Path to clang exec')
+
+    parser.add_argument(
+            '--llvm_strip_exec',
+            help='Path to llvm-strip exec')
+
+    parser.add_argument(
+            '--bpftool_exec',
+            help='Path to bpftool exec')
+
+    parser.add_argument(
+            '--arch',
+            help='Target CPU architecture',
+            default='x86_64')
+
+    args = parser.parse_args();
+
+    logging.basicConfig(stream=sys.stderr, level=logging.WARNING)
+    bpf_build(args)
index 283e7a64d741a16d31289a761fb4df2387ff0d17..0bf053b5ffbf7155836800a93d6bb19533270aa0 100755 (executable)
@@ -1,31 +1,32 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
+set -o pipefail
 
 sd_good=0
 sd_total=0
 udev_good=0
 udev_total=0
 
-deprecated="
+deprecated=(
     -e sd_bus_try_close
     -e sd_bus_process_priority
     -e sd_bus_message_get_priority
     -e sd_bus_message_set_priority
     -e sd_seat_can_multi_session
     -e sd_journal_open_container
-"
+)
 
-for symbol in `nm -g --defined-only "$@" | grep " T " | cut -d" " -f3 | grep -wv $deprecated | sort -u` ; do
-    if test -f ${MESON_BUILD_ROOT}/man/$symbol.3 ; then
+for symbol in $(nm -g --defined-only "$@" | grep " T " | cut -d" " -f3 | grep -wv "${deprecated[@]}" | sort -u); do
+    if test -f "${MESON_BUILD_ROOT:?}/man/$symbol.3"; then
         echo "✓ Symbol $symbol() is documented."
         good=1
     else
-        printf "  \x1b[1;31mSymbol $symbol() lacks documentation.\x1b[0m\n"
+        echo -e "  \x1b[1;31mSymbol $symbol() lacks documentation.\x1b[0m"
         good=0
     fi
 
-    case $symbol in
+    case "$symbol" in
         sd_*)
             ((sd_good+=good))
             ((sd_total+=1))
index 1d11fa98a16f324ab7f1e790a3917049ea3b3d62..0661da4d3b2d69ad4106a4c5ea4c2fdde1861dae 100755 (executable)
@@ -1,37 +1,72 @@
 #!/usr/bin/env bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
-set -e
+set -eu
+set -o pipefail
 
-which perl &>/dev/null || exit 77
+SOURCE_ROOT="${1:?Missing argument: project source root}"
+BUILD_ROOT="${2:?Missing argument: project build root}"
+
+command -v gawk &>/dev/null || exit 77
 
 function generate_directives() {
-    perl -aF'/[\s,]+/' -ne '
-        if (my ($s, $d) = ($F[0] =~ /^([^\s\.]+)\.([^\s\.]+)$/)) { $d{$s}{"$d="} = 1; }
-        END { while (my ($key, $value) = each %d) {
-            printf "[%s]\n%s\n", $key, join("\n", keys(%$value))
-        }}' "$1"
+    gawk -v sec_rx="${2:-""}" -v unit_type="${3:-""}" '
+    match($0, /^([^ \t\.]+)\.([^ \t\.,]+)/, m) {
+        # res[section][directive] = 1
+        res[m[1]][m[2]] = 1;
+    }
+    END {
+        if (unit_type)
+            print unit_type
+
+        for (section in res) {
+            if (sec_rx && section !~ sec_rx)
+                continue
+
+            print "[" section "]";
+            for (directive in res[section]) {
+                print directive "=";
+            }
+        }
+    }
+    ' "$1"
 }
 
 ret=0
 if ! diff \
-     <(generate_directives "$1"/src/network/networkd-network-gperf.gperf | sort) \
-     <(cat "$1"/test/fuzz/fuzz-network-parser/directives.network | sort); then
+     <(generate_directives "$SOURCE_ROOT"/src/network/networkd-network-gperf.gperf | sort) \
+     <(sort "$SOURCE_ROOT"/test/fuzz/fuzz-network-parser/directives.network); then
     echo "Looks like test/fuzz/fuzz-network-parser/directives.network hasn't been updated"
     ret=1
 fi
 
 if ! diff \
-     <(generate_directives "$1"/src/network/netdev/netdev-gperf.gperf | sort) \
-     <(cat "$1"/test/fuzz/fuzz-netdev-parser/directives.netdev | sort); then
+     <(generate_directives "$SOURCE_ROOT"/src/network/netdev/netdev-gperf.gperf | sort) \
+     <(sort "$SOURCE_ROOT"/test/fuzz/fuzz-netdev-parser/directives.netdev); then
     echo "Looks like test/fuzz/fuzz-netdev-parser/directives.netdev hasn't been updated"
     ret=1
 fi
 
 if ! diff \
-     <(generate_directives "$1"/src/udev/net/link-config-gperf.gperf | sort) \
-     <(cat "$1"/test/fuzz/fuzz-link-parser/directives.link | sort) ; then
+     <(generate_directives "$SOURCE_ROOT"/src/udev/net/link-config-gperf.gperf | sort) \
+     <(sort "$SOURCE_ROOT"/test/fuzz/fuzz-link-parser/directives.link) ; then
     echo "Looks like test/fuzz/fuzz-link-parser/directives.link hasn't been updated"
     ret=1
 fi
 
+for section in Automount Mount Path Scope Slice Socket Swap Timer; do
+    if ! diff \
+         <(generate_directives "$BUILD_ROOT"/src/core/load-fragment-gperf.gperf "$section" "${section,,}" | sort) \
+         <(sort "$SOURCE_ROOT/test/fuzz/fuzz-unit-file/directives.${section,,}") ; then
+        echo "Looks like test/fuzz/fuzz-unit-file/directives.${section,,} hasn't been updated"
+        ret=1
+    fi
+done
+
+if ! diff \
+     <(generate_directives "$BUILD_ROOT"/src/core/load-fragment-gperf.gperf "(Service|Unit|Install)" "service" | sort) \
+     <(sort "$SOURCE_ROOT/test/fuzz/fuzz-unit-file/directives.service") ; then
+    echo "Looks like test/fuzz/fuzz-unit-file/directives.service hasn't been updated"
+    ret=1
+fi
+
 exit $ret
index 721dec4c64f93445e17d24bbadc5fa94bd32ef33..8e7d236dd9014873319f8a2c7251ff118005e80b 100755 (executable)
@@ -1,30 +1,41 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
+set -o pipefail
 
+# Note: `grep ... >/dev/null` instead of just `grep -q` is used intentionally
+#       here, since `grep -q` exits on the first match causing SIGPIPE being
+#       sent to the sender.
+
+BINARY="${1:?}"
 export SYSTEMD_LOG_LEVEL=info
 
+if [[ ! -x "$BINARY" ]]; then
+    echo "$BINARY is not an executable"
+    exit 1
+fi
+
 # output width
-if "$1"  --help | grep -v 'default:' | grep -E -q '.{80}.'; then
-    echo "$(basename "$1") --help output is too wide:"
-    "$1"  --help | awk 'length > 80' | grep -E --color=yes '.{80}'
+if "$BINARY" --help | grep -v 'default:' | grep -E '.{80}.' >/dev/null; then
+    echo "$(basename "$BINARY") --help output is too wide:"
+    "$BINARY" --help | awk 'length > 80' | grep -E --color=yes '.{80}'
     exit 1
 fi
 
 # --help prints something. Also catches case where args are ignored.
-if ! "$1"  --help | grep -q .; then
-    echo "$(basename "$1") --help output is empty."
+if ! "$BINARY" --help | grep . >/dev/null; then
+    echo "$(basename "$BINARY") --help output is empty."
     exit 2
 fi
 
 # no --help output to stdout
-if "$1" --help 2>&1 1>/dev/null | grep .; then
-    echo "$(basename "$1") --help prints to stderr"
+if "$BINARY" --help 2>&1 1>/dev/null | grep .; then
+    echo "$(basename "$BINARY") --help prints to stderr"
     exit 3
 fi
 
 # error output to stderr
-if ! "$1" --no-such-parameter 2>&1 1>/dev/null | grep -q .; then
-    echo "$(basename "$1") with an unknown parameter does not print to stderr"
+if ! ("$BINARY" --no-such-parameter 2>&1 1>/dev/null || :) | grep . >/dev/null; then
+    echo "$(basename "$BINARY") with an unknown parameter does not print to stderr"
     exit 4
 fi
index e449b6e8650aa66e051748b87b6b39160bcc2f33..79a79fcc58e4f866347e21e7c71f099173d83662 100755 (executable)
@@ -1,12 +1,12 @@
 #!/bin/sh
 # SPDX-License-Identifier: LGPL-2.1-or-later
-set -e
+set -eu
 
 # Try to guess the build directory:
 # we look for subdirectories of the parent directory that look like ninja build dirs.
 
-if [ -n "$BUILD_DIR" ]; then
-    echo "$(realpath "$BUILD_DIR")"
+if [ -n "${BUILD_DIR:=}" ]; then
+    realpath "$BUILD_DIR"
     exit 0
 fi
 
@@ -14,20 +14,20 @@ root="$(dirname "$(realpath "$0")")"
 
 found=
 for i in "$root"/../*/build.ninja; do
-    c="$(dirname $i)"
+    c="$(dirname "$i")"
     [ -d "$c" ] || continue
     [ "$(basename "$c")" != mkosi.builddir ] || continue
 
     if [ -n "$found" ]; then
-        echo 'Found multiple candidates, specify build directory with $BUILD_DIR' >&2
+        echo "Found multiple candidates, specify build directory with \$BUILD_DIR" >&2
         exit 2
     fi
     found="$c"
 done
 
 if [ -z "$found" ]; then
-    echo 'Specify build directory with $BUILD_DIR' >&2
+    echo "Specify build directory with \$BUILD_DIR" >&2
     exit 1
 fi
 
-echo "$(realpath $found)"
+realpath "$found"
index 7ea6de8311154cdc9218b7ffbdc22a99626ebf1f..2999a58c0b9d03eacdb568ada3e508fcadd4cdb5 100755 (executable)
@@ -1,38 +1,40 @@
 #!/bin/sh
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
-TOP=`git rev-parse --show-toplevel`
+set -eu
 
-case "$1" in
+TOP="$(git rev-parse --show-toplevel)"
+
+case "${1:-}" in
     recdiff)
-        if [ "$2" = "" ] ; then
+        if [ "${2:-}" = "" ] ; then
             DIR="$TOP"
         else
             DIR="$2"
         fi
 
-        find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 diff \{\} \;
+        find "$DIR" -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec "$0" diff \{\} \;
         ;;
 
     recpatch)
-        if [ "$2" = "" ] ; then
+        if [ "${2:-}" = "" ] ; then
             DIR="$TOP"
         else
             DIR="$2"
         fi
 
-        find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 patch \{\} \;
+        find "$DIR" -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec "$0" patch \{\} \;
         ;;
 
     diff)
-        T=`mktemp`
-        sed '/^$/N;/^\n$/D' < "$2" > "$T"
+        T="$(mktemp)"
+        sed '/^$/N;/^\n$/D' <"${2:?}" >"$T"
         diff -u "$2" "$T"
         rm -f "$T"
         ;;
 
     patch)
-        sed -i '/^$/N;/^\n$/D' "$2"
+        sed -i '/^$/N;/^\n$/D' "${2:?}"
         ;;
 
     *)
index 54d922975c3d0e9cb6945aac8ee0369767bec7bf..6cea339ac6278787cc79a604f6657da23bbd50b5 100755 (executable)
@@ -1,38 +1,40 @@
 #!/bin/sh
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
-TOP=`git rev-parse --show-toplevel`
+set -eu
 
-case "$1" in
+TOP="$(git rev-parse --show-toplevel)"
+
+case "${1:-}" in
     recdiff)
-        if [ "$2" = "" ] ; then
+        if [ "${2:-}" = "" ] ; then
             DIR="$TOP"
         else
             DIR="$2"
         fi
 
-        find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 diff \{\} \;
+        find "$DIR" -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec "$0" diff \{\} \;
         ;;
 
     recpatch)
-        if [ "$2" = "" ] ; then
+        if [ "${2:-}" = "" ] ; then
             DIR="$TOP"
         else
             DIR="$2"
         fi
 
-        find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 patch \{\} \;
+        find "$DIR" -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec "$0" patch \{\} \;
         ;;
 
     diff)
-        T=`mktemp`
-        sed 's/\t/        /g' < "$2" > "$T"
+        T="$(mktemp)"
+        sed 's/\t/        /g' <"${2:?}" >"$T"
         diff -u "$2" "$T"
         rm -f "$T"
         ;;
 
     patch)
-        sed -i 's/\t/        /g' "$2"
+        sed -i 's/\t/        /g' "${2:?}"
         ;;
 
     *)
index 7b4801ff94651e425a49d173e3ce6e167bf6f68d..35d8d159ef3a6a6c4631436e5b89e0cf09a6eaf4 100755 (executable)
@@ -1,25 +1,21 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
 
-CONFIG=$1
-TARGET=$2
+CONFIG="${1:?Missing path to config.h}"
+TARGET="${2:?Missing target m4 file}"
 
-if [ $# -ne 2 ]; then
-    echo 'Invalid number of arguments.'
-    exit 1
-fi
-
-if [ ! -f $CONFIG ]; then
+if [ ! -f "$CONFIG" ]; then
     echo "$CONFIG not found."
     exit 2
 fi
 
-if [ ! -f $TARGET ]; then
+if [ ! -f "$TARGET" ]; then
     echo "$TARGET not found."
     exit 3
 fi
 
-DEFINES=$(awk '$1 == "#define" && $3 == "1" { printf "-D%s ", $2 }' $CONFIG)
+DEFINES=()
+mapfile -t DEFINES < <(awk '$1 == "#define" && $3 == "1" { printf "-D%s\n", $2 }' "$CONFIG")
 
-m4 -P $DEFINES $TARGET
+m4 -P "${DEFINES[@]}" "$TARGET"
index 96f58922810a1b6c4f2f54368a3520f22892369d..653a73b0bd460f2e79ffab6abde8a517d4ba7a1c 100755 (executable)
@@ -2,6 +2,9 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
 
+SOURCE="${1:?}"
+TARGET="${2:?}"
+
 if [ "${MESON_INSTALL_QUIET:-0}" = 1 ] ; then
     VERBOSE=""
 else
@@ -11,9 +14,9 @@ fi
 # this is needed mostly because $DESTDIR is provided as a variable,
 # and we need to create the target directory...
 
-mkdir -${VERBOSE}p "$(dirname "${DESTDIR:-}$2")"
-if [ "$(dirname $1)" = . -o "$(dirname $1)" = .. ]; then
-    ln -${VERBOSE}fs -T -- "$1" "${DESTDIR:-}$2"
+mkdir -${VERBOSE}p "$(dirname "${DESTDIR:-}$TARGET")"
+if [ "$(dirname "$SOURCE")" = . ] || [ "$(dirname "$SOURCE")" = .. ]; then
+    ln -${VERBOSE}fs -T -- "$SOURCE" "${DESTDIR:-}$TARGET"
 else
-    ln -${VERBOSE}fs -T --relative -- "${DESTDIR:-}$1" "${DESTDIR:-}$2"
+    ln -${VERBOSE}fs -T --relative -- "${DESTDIR:-}$SOURCE" "${DESTDIR:-}$TARGET"
 fi
index 1ec04c76b791d022e94c3afb7b53477203662d41..8ce692498adabba42c4b799d769123ceceafe096 100755 (executable)
@@ -4,8 +4,8 @@
 set -eu
 set -o pipefail
 
-dir="$1"
-fallback="$2"
+dir="${1:?}"
+fallback="${2:?}"
 
 # Apparently git describe has a bug where it always considers the work-tree
 # dirty when invoked with --git-dir (even though 'git status' is happy). Work
index 7d5a9a8cf5a54bf7861c2d14758977bdafcc953d..c69773087dfcbbd27871142d085ef10c66545f35 100755 (executable)
@@ -2,7 +2,7 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
 
-cd "$1"
+cd "${1:?}"
 
 (curl --fail -L 'https://chromium.googlesource.com/chromiumos/platform2/+/master/power_manager/udev/gen_autosuspend_rules.py?format=TEXT'; echo) \
     | base64 -d > tools/chromiumos/gen_autosuspend_rules.py
index 773a959dcf6b9b1e972a63f0d35c41ff189d99ea..abbbb82f4bc4d1a988c21023ab6e7574d7afb04f 100755 (executable)
@@ -2,7 +2,7 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
 
-cd "$1"
+cd "${1:?}"
 
 unset permissive
 if [ "${2:-}" = "-p" ]; then
@@ -28,6 +28,6 @@ if [ "${2:-}" != "-n" ]; then (
 set -x
 ./acpi-update.py >20-acpi-vendor.hwdb.base
 patch -p0 -o- 20-acpi-vendor.hwdb.base <20-acpi-vendor.hwdb.patch >20-acpi-vendor.hwdb
-! diff -u 20-acpi-vendor.hwdb.base 20-acpi-vendor.hwdb >20-acpi-vendor.hwdb.patch
+diff -u 20-acpi-vendor.hwdb.base 20-acpi-vendor.hwdb >20-acpi-vendor.hwdb.patch && exit 1
 
 ./ids_parser.py
index 4f56aeceddcf4236eb9e4052d388efd24c03813d..5aa85368825a8731e5e892e86a7323d238aaabed 100755 (executable)
@@ -2,10 +2,10 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -eu
 
-cd "$1" && shift
+cd "${1:?}" && shift
 
 curl --fail -L -o syscall-list.txt 'https://raw.githubusercontent.com/hrw/syscalls-table/master/syscall-names.text'
 
 for arch in "$@"; do
-    curl --fail -L -o syscalls-$arch.txt "https://raw.githubusercontent.com/hrw/syscalls-table/master/tables/syscalls-$arch"
+    curl --fail -L -o "syscalls-$arch.txt" "https://raw.githubusercontent.com/hrw/syscalls-table/master/tables/syscalls-$arch"
 done
index 8c6bdf35f56177941230ceb71abe37ea271cb68d..674b7ae74d6a0877a4802c796950c665ad0e3a32 100644 (file)
@@ -10,9 +10,9 @@
 [Unit]
 Description=Initrd File Systems
 Documentation=man:systemd.special(7)
+AssertPathExists=/etc/initrd-release
 OnFailure=emergency.target
 OnFailureJobMode=replace-irreversibly
-AssertPathExists=/etc/initrd-release
 After=initrd-parse-etc.service
 DefaultDependencies=no
 Conflicts=shutdown.target
diff --git a/units/initrd-usr-fs.target b/units/initrd-usr-fs.target
new file mode 100644 (file)
index 0000000..7219655
--- /dev/null
@@ -0,0 +1,17 @@
+#  SPDX-License-Identifier: LGPL-2.1-or-later
+#
+#  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=Initrd /usr File System
+Documentation=man:systemd.special(7)
+AssertPathExists=/etc/initrd-release
+OnFailure=emergency.target
+OnFailureJobMode=replace-irreversibly
+DefaultDependencies=no
+Conflicts=shutdown.target
index 655158a58bca3daa98d5d95f878f1cd75030effb..fc8fbff4bded60a3534cc0b5e20a3b3972f98832 100644 (file)
@@ -14,6 +14,6 @@ OnFailure=emergency.target
 OnFailureJobMode=replace-irreversibly
 AssertPathExists=/etc/initrd-release
 Requires=basic.target
-Wants=initrd-root-fs.target initrd-root-device.target initrd-fs.target initrd-parse-etc.service
-After=initrd-root-fs.target initrd-root-device.target initrd-fs.target basic.target rescue.service rescue.target
+Wants=initrd-root-fs.target initrd-root-device.target initrd-fs.target initrd-usr-fs.target initrd-parse-etc.service
+After=initrd-root-fs.target initrd-root-device.target initrd-fs.target initrd-usr-fs.target basic.target rescue.service rescue.target
 AllowIsolate=yes
index 0d0eeea7530524b0349b11935d83a6752498aa45..fe8e95ff91dc824f7fa8d3da18f9da43089e4c52 100644 (file)
@@ -38,6 +38,7 @@ units = [
         ['initrd-switch-root.service',          'ENABLE_INITRD'],
         ['initrd-switch-root.target',           'ENABLE_INITRD'],
         ['initrd-udevadm-cleanup-db.service',   'ENABLE_INITRD'],
+        ['initrd-usr-fs.target',                'ENABLE_INITRD'],
         ['initrd.target',                       'ENABLE_INITRD'],
         ['kexec.target',                        ''],
         ['ldconfig.service',                    'ENABLE_LDCONFIG',
@@ -209,7 +210,8 @@ in_units = [
         ['systemd-networkd.service',             'ENABLE_NETWORKD'],
         ['systemd-networkd-wait-online.service', 'ENABLE_NETWORKD'],
         ['systemd-nspawn@.service',              ''],
-        ['systemd-oomd.service',                 'ENABLE_OOMD'],
+        ['systemd-oomd.service',                 'ENABLE_OOMD',
+         'dbus-org.freedesktop.oom1.service'],
         ['systemd-portabled.service',            'ENABLE_PORTABLED',
          'dbus-org.freedesktop.portable1.service'],
         ['systemd-userdbd.service',              'ENABLE_USERDB'],
index 9369b73ae27fefc63f6e9a172baad8cfb0f4e9f6..98206a9d0643d4b17bee90ee29ce69006fa5313c 100644 (file)
@@ -9,5 +9,5 @@
 
 [Unit]
 Description=Cryptsetup Units Slice
-Documentation=man:systemd.special(7)
+Documentation=man:systemd-cryptsetup@.service(8)
 DefaultDependencies=no
index 922358fe5d62fde0b8cdcb9c50b9a70296711ef1..565374698d76d8b8d67330e08ec6c010866a2fd4 100644 (file)
@@ -11,6 +11,8 @@
 Description=Process Core Dump Socket
 Documentation=man:systemd-coredump(8)
 DefaultDependencies=no
+Before=shutdown.target
+Conflicts=shutdown.target
 
 [Socket]
 ListenSequentialPacket=/run/systemd/coredump
index 2fea88384f62ccafb3b3dc9049332055288e7384..2e57b064c183d9a2219fa97829109d458578bd17 100644 (file)
@@ -13,7 +13,7 @@ Documentation=man:systemd-firstboot(1)
 DefaultDependencies=no
 Conflicts=shutdown.target
 After=systemd-remount-fs.service
-Before=systemd-sysusers.service sysinit.target first-boot-complete.target shutdown.target
+Before=systemd-sysusers.service systemd-vconsole-setup.service sysinit.target first-boot-complete.target shutdown.target
 Wants=first-boot-complete.target
 ConditionPathIsReadWrite=/etc
 ConditionFirstBoot=yes
@@ -25,3 +25,14 @@ ExecStart=systemd-firstboot --prompt-locale --prompt-timezone --prompt-root-pass
 StandardOutput=tty
 StandardInput=tty
 StandardError=tty
+
+# Optionally, pick up basic fields from credentials passed to the service
+# manager. This is useful for importing this data from nspawn's
+# --set-credential= switch.
+LoadCredential=passwd.hashed-password.root
+LoadCredential=passwd.plaintext-password.root
+LoadCredential=passwd.shell.root
+LoadCredential=firstboot.locale
+LoadCredential=firstboot.locale-messages
+LoadCredential=firstboot.keymap
+LoadCredential=firstboot.timezone
index aa9ad7e02c3e85a881e83208422d72d734351ca1..2d8d1c3b9107a1e38ffc18acf3d26100e09c9e9d 100644 (file)
@@ -12,7 +12,8 @@ Description=Network Service Netlink Socket
 Documentation=man:systemd-networkd.service(8) man:rtnetlink(7)
 ConditionCapability=CAP_NET_ADMIN
 DefaultDependencies=no
-Before=sockets.target
+Before=sockets.target shutdown.target
+Conflicts=shutdown.target
 
 [Socket]
 ReceiveBuffer=128M
index a5565834ebbe3129e6feb71ad579ebab0abbb1a7..4634d983c18e08b3f544dad62c3067b52a866676 100644 (file)
@@ -12,13 +12,18 @@ Description=Repartition Root Disk
 Documentation=man:systemd-repart.service(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
-After=sysroot.mount
+After=initrd-usr-fs.target
 Before=initrd-root-fs.target shutdown.target
 ConditionVirtualization=!container
 ConditionDirectoryNotEmpty=|/usr/lib/repart.d
 ConditionDirectoryNotEmpty=|/usr/local/lib/repart.d
 ConditionDirectoryNotEmpty=|/etc/repart.d
 ConditionDirectoryNotEmpty=|/run/repart.d
+ConditionDirectoryNotEmpty=|/sysroot/usr/lib/repart.d
+ConditionDirectoryNotEmpty=|/sysroot/usr/local/lib/repart.d
+ConditionDirectoryNotEmpty=|/sysroot/etc/repart.d
+ConditionDirectoryNotEmpty=|/sysusr/usr/lib/repart.d
+ConditionDirectoryNotEmpty=|/sysusr/usr/local/lib/repart.d
 
 [Service]
 Type=oneshot
index ff5b3db82138f70bd5a2c7d45b3e8dba42603fc2..47373307b32a527bf9cb0caf9232afe11c3a4938 100644 (file)
@@ -21,3 +21,10 @@ Type=oneshot
 RemainAfterExit=yes
 ExecStart=systemd-sysusers
 TimeoutSec=90s
+
+# Optionally, pick up a root password and shell for the root user from a
+# credential passed to the service manager. This is useful for importing this
+# data from nspawn's --set-credential= switch.
+LoadCredential=passwd.hashed-password.root
+LoadCredential=passwd.plaintext-password.root
+LoadCredential=passwd.shell.root
index 5ecc702b6d109c3dbe7f04ef7bf40f300dd9b839..468d85f968315365d820d66f15713c1c4328f075 100644 (file)
@@ -12,7 +12,7 @@ Description=Enforce Volatile Root File Systems
 Documentation=man:systemd-volatile-root.service(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
-After=sysroot.mount systemd-repart.service
+After=sysroot.mount sysroot-usr.mount systemd-repart.service
 Before=initrd-root-fs.target shutdown.target
 AssertPathExists=/etc/initrd-release