Elliott Mitchell
2020-Oct-25 00:34 UTC
[Pkg-xen-devel] [PATCH 0/9] Fixing cross-compilation for Debian, some script work
Resending several since they're still waiting for some action. Plus a few extras which appear to distinctly improve things. With these, plus commit 17d192e0238d6c714e9f04593b59597b7090be38 from Xen's main branch cross-builds work. Yes, I'm including some shell script optimization. I doubt these speed the build that much, but a bunch of small steps together can result in large gains. `set -o pipefail` may be a substantial reliability gain when using large, complex pipes with bash; but simplifying those pipes results in larger reliability gains. `xl` and some of the other utilities wrapped by `xen-utils-wrapper` are used repeatedly in many places. At which point removing most of the commands which produce forks from `xen-utils-wrapper` is a very large gain. On a system of mine `/etc/init.d/xendomains start` appeared to use roughly 500 processes per domain restored, with the optimization that drops to 100 per domain restored. Then using an internal xen() wrapper results in further gains. I haven't found anything beside `/etc/init.d/xendomains` using the `xen` wrapper, but just in case I left that in place. For systems where the xen-acpi-processor kernel module is available, enabling that can be substantial savings. Right now that is i386/amd64-only, but I suspect it may get ported to ARM in the future. For reference, on a memory-constrained machine of mine `sensors` was showing the processor idle at 100W of power without xen-acpi-processor, and with xen-acpi-processor it was idling below 30W. Elliott Mitchell (9): Rework "debian/rules: Do not try to move EFI binaries on armhf" debian/rules: Correct shim install step for current Xen d/shuffle-binaries: Fix binary shuffling script for cross-building d/shuffle-boot-files: Rework boot shuffling script debian/rules: Set CC/LD for cross-building debian/rules: Setup use of noOCAML profile debian/xen.init: Load xen_acpi_processor on boot debian/scripts: Optimize runtime scripts d/xendomains.init: Remove use of `xen` compat wrapper for `xl` debian/control | 5 +-- debian/rules | 36 ++++++++++++------- debian/scripts/xen-utils-wrapper | 43 ++++++++++++++++++++--- debian/scripts/xen-version | 6 ++-- debian/shuffle-binaries | 46 ++++++++++++++----------- debian/shuffle-boot-files | 26 +++++++------- debian/xen-utils-common.xen.init | 1 + debian/xen-utils-common.xendomains.init | 5 +++ 8 files changed, 115 insertions(+), 53 deletions(-) -- -- (\___(\___(\______ --=> 8-) EHM <=-- ______/)___/)___/) \BS ( | ehem+sigmsg at m5p.com PGP 87145445 | ) / \_CS\ | _____ -O #include <stddisclaimer.h> O- _____ | / _/ 8A19\___\_|_/58D2 7E3D DDF4 7BA6 <-PGP-> 41D1 B375 37D0 8714\_|_/___/5445
Elliott Mitchell
2020-Oct-25 01:46 UTC
[Pkg-xen-devel] [PATCH 1/9] Rework "debian/rules: Do not try to move EFI binaries on armhf"
What is actually needed is a move command which fails if the move fails, but succeeds if no files are moved. A combination of find/xargs can match this, so use what works. This reverts commit 8ff478af61fa8a87806a89bbd618cd9da2354302. --- debian/rules | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/debian/rules b/debian/rules index 81a0896a76..3f2daaee6f 100755 --- a/debian/rules +++ b/debian/rules @@ -229,10 +229,7 @@ override_dh_auto_install: $(TEMPLATED_FILES) -C tools/firmware install-shim : @# Inexplicably, upstream puts the efi binares in usr/lib64 - case $(flavour) in \ - armhf) ;; \ - *) mv $t/usr/lib64/efi/* $t/boot/. ;; \ - esac + find "$t/usr/lib64/efi" -mindepth 1 -maxdepth 1 -print0 | xargs -r -0 mv -t "$t/boot" : @# This file contains an arch-specific path and we put it @# in xen-utils-common, an arch-all package. But the -- -- (\___(\___(\______ --=> 8-) EHM <=-- ______/)___/)___/) \BS ( | ehem+sigmsg at m5p.com PGP 87145445 | ) / \_CS\ | _____ -O #include <stddisclaimer.h> O- _____ | / _/ 8A19\___\_|_/58D2 7E3D DDF4 7BA6 <-PGP-> 41D1 B375 37D0 8714\_|_/___/5445
Elliott Mitchell
2020-Oct-25 01:46 UTC
[Pkg-xen-devel] [PATCH 2/9] debian/rules: Correct shim install step for current Xen
When originally implemented, the separated shim install step relied on the shim install being a NOP on shimless architectures. Either this is no longer the case, or else cross-building confuses the architecture detection. Take out a typo while at it. Signed-off-by: Elliott Mitchell <ehem+debian at m5p.com> --- debian/rules | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/debian/rules b/debian/rules index 3f2daaee6f..83395f25e9 100755 --- a/debian/rules +++ b/debian/rules @@ -222,11 +222,13 @@ override_dh_auto_install: $(TEMPLATED_FILES) : @# shim install target needs to be run separately because we @# need to pass it the make_args_xen settings, in particular - @# on i386 bwe need to pass x86_64 here to actually build it. - @# Luckily this target, unlike the build, is a noop on - @# shimless arches, so it does not need to be conditional. - $(MAKE) $(make_args_xen) DESTDIR=$t $(make_args_xen) \ - -C tools/firmware install-shim + @# on i386 we need to pass x86_64 here to actually build it. + case $(flavour) in \ + amd64|i386) \ + $(MAKE) $(make_args_xen) DESTDIR=$t $(make_args_xen) \ + -C tools/firmware install-shim \ + ;; \ + esac : @# Inexplicably, upstream puts the efi binares in usr/lib64 find "$t/usr/lib64/efi" -mindepth 1 -maxdepth 1 -print0 | xargs -r -0 mv -t "$t/boot" -- -- (\___(\___(\______ --=> 8-) EHM <=-- ______/)___/)___/) \BS ( | ehem+sigmsg at m5p.com PGP 87145445 | ) / \_CS\ | _____ -O #include <stddisclaimer.h> O- _____ | / _/ 8A19\___\_|_/58D2 7E3D DDF4 7BA6 <-PGP-> 41D1 B375 37D0 8714\_|_/___/5445
Elliott Mitchell
2020-Oct-25 01:46 UTC
[Pkg-xen-devel] [PATCH 3/9] d/shuffle-binaries: Fix binary shuffling script for cross-building
`ldd` doesn't work with cross-builds, so use `file` to detect scripts and `strings | grep` for identifying linked libraries. Even though debhelper depends on file, make the requirement explicit. Heavily simplify script inner loop. While the core of that inner loop was often executed only once, it is best to shrink inner loops. With the reduced inner loop, less is being done inside pipes, so pipefail is lower value (the early commands in pipes are unlikely to fail). This makes the script POSIX compliant so switch to /bin/sh. Remove the useless extra argument passed to the script. Signed-off-by: Elliott Mitchell <ehem+debian at m5p.com> --- debian/control | 1 + debian/rules | 2 +- debian/shuffle-binaries | 46 ++++++++++++++++++++++------------------- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/debian/control b/debian/control index 942bf6711c..90007f6a02 100644 --- a/debian/control +++ b/debian/control @@ -6,6 +6,7 @@ Section: admin Standards-Version: 4.5.0 Build-Depends: debhelper (>= 10), + file, dh-exec, dpkg-dev (>= 1.16.0~), rdfind, diff --git a/debian/rules b/debian/rules index 83395f25e9..9c88bf3b86 100755 --- a/debian/rules +++ b/debian/rules @@ -267,7 +267,7 @@ xenstore_rm = $(addprefix debian/xen-utils-common/, \ )) override_dh_install: - debian/shuffle-binaries $(upstream_version) $(flavour) + debian/shuffle-binaries $(upstream_version) : debian/shuffle-boot-files $(upstream_version) $(flavour) : diff --git a/debian/shuffle-binaries b/debian/shuffle-binaries index cff6de5428..7356531f1a 100755 --- a/debian/shuffle-binaries +++ b/debian/shuffle-binaries @@ -1,6 +1,5 @@ -#!/bin/bash +#!/bin/sh set -e -set -o pipefail version=$1; shift @@ -17,34 +16,39 @@ version=$1; shift list=debian/libxenmiscV.install.vsn-in t=debian/tmp -vd=/usr/lib/xen-$version/bin +vd="/usr/lib/xen-$version/bin" cd=/usr/lib/xen-common/bin -mkdir -p $t/$vd +mkdir -p "$t/$vd" -for binary in `find $t/usr/{bin,sbin} -type f`; do - reason='' - { ldd "$binary" ||: ; } | { fgrep '=>' ||: ; } \ - | ( - while read lib dummy; do +find "$t"/usr/*bin -type f | while read binary; do + + # filter out scripts + file "$binary" | grep -q -eELF.\\+version.\\+interpreter || continue + + # ldd doesn't work for cross-building + reason=$( + strings "$binary" | grep -e^lib.\\+\\.so\\.\[.0-9\]\\+\$ | \ + while read lib; do lib=${lib%.so.*} - if grep -F "usr/lib/*/$lib.so.*" $list >/dev/null; then - reason+=" $lib" + if grep -q -F "usr/lib/*/$lib.so.*" $list; then + printf " %s" "$lib" fi done + ) - if [ "x$reason" = x ]; then - exit 0 - fi + # if no reason, then skip + [ -n "$reason" ] || continue - echo "shuffling $binary $reason" + echo "shuffling $binary$reason" - leaf=${binary##*} - mv -v $binary $t/$vd/$leaf - ln -vs $cd/xen-utils-wrapper $binary + mv -v "$binary" "$t/$vd" + ln -vs "$cd/xen-utils-wrapper" "$binary" - touch debian/shuffle-binaries.stamp - ) + touch "$0.stamp" done -ls debian/shuffle-binaries.stamp +if [ ! -e "$0.stamp" ]; then + echo "Failed to shuffle binaries!" 1>&2 + exit 1 +fi -- -- (\___(\___(\______ --=> 8-) EHM <=-- ______/)___/)___/) \BS ( | ehem+sigmsg at m5p.com PGP 87145445 | ) / \_CS\ | _____ -O #include <stddisclaimer.h> O- _____ | / _/ 8A19\___\_|_/58D2 7E3D DDF4 7BA6 <-PGP-> 41D1 B375 37D0 8714\_|_/___/5445
Elliott Mitchell
2020-Oct-25 01:46 UTC
[Pkg-xen-devel] [PATCH 4/9] d/shuffle-boot-files: Rework boot shuffling script
Rather than passing two strings which are strictly joined and used to replace filename versions, turn them into a simple version replacement. Rework the script logic to specifically target the version string in filenames and replace *that*. This fixes an issues with some Xen files having names distinct enough names to not match the assumed format. While at it use structures which conform to POSIX, allowing the use of /bin/sh instead of bash. Signed-off-by: Elliott Mitchell <ehem+debian at m5p.com> --- debian/rules | 2 +- debian/shuffle-boot-files | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/debian/rules b/debian/rules index 9c88bf3b86..acf1825edd 100755 --- a/debian/rules +++ b/debian/rules @@ -269,7 +269,7 @@ xenstore_rm = $(addprefix debian/xen-utils-common/, \ override_dh_install: debian/shuffle-binaries $(upstream_version) : - debian/shuffle-boot-files $(upstream_version) $(flavour) + debian/shuffle-boot-files $(upstream_version)-$(flavour) : dh_install $(dh_install_excludes) if test -d debian/xen-utils-common; then rm -v $(xenstore_rm); fi diff --git a/debian/shuffle-boot-files b/debian/shuffle-boot-files index f7492c0c72..7338032fe6 100755 --- a/debian/shuffle-boot-files +++ b/debian/shuffle-boot-files @@ -1,14 +1,13 @@ -#!/bin/bash +#!/bin/sh set -e -version=$1; shift -flavour=$1; shift +newvers=$1; shift t=debian/tmp -hv=xen-hypervisor-$version-$flavour -dest=debian/$hv/boot -mkdir -p $dest +hv="xen-hypervisor-$newvers" +dest="debian/$hv/boot" +mkdir -p "$dest" # The upstream build system puts a pile of needless symlinks in /boot. # @@ -21,11 +20,14 @@ mkdir -p $dest # more useful when the -i386 flavour existed and was coinstallable # with the -amd64 flavour.) -verstring=$(readlink debian/tmp/boot/xen.gz || - readlink debian/tmp/boot/xen) -verstring=${verstring##*/} -verstring=${verstring%.gz} +xenvers="$(readlink debian/tmp/boot/xen.?z* || + readlink debian/tmp/boot/xen)" +xenvers="${xenvers##*xen-}" +xenvers="${xenvers%.?z*}" -for f in `cd $t/boot && find * -type f -print`; do - cp -v $t/boot/$f $dest/${f/$verstring/xen-$version-$flavour} +find "$t/boot" -type f -print | while read f +do + head="${f%$xenvers*}" + tail="${f#*$xenvers}" + cp -vl "$f" "$dest${head#$t/boot}$newvers${tail}" done -- -- (\___(\___(\______ --=> 8-) EHM <=-- ______/)___/)___/) \BS ( | ehem+sigmsg at m5p.com PGP 87145445 | ) / \_CS\ | _____ -O #include <stddisclaimer.h> O- _____ | / _/ 8A19\___\_|_/58D2 7E3D DDF4 7BA6 <-PGP-> 41D1 B375 37D0 8714\_|_/___/5445
Elliott Mitchell
2020-Oct-25 01:46 UTC
[Pkg-xen-devel] [PATCH 5/9] debian/rules: Set CC/LD for cross-building
Set $(CC) and $(LD) when building. People building ARM executables on ARM hosts aren't that common. Signed-off-by: Elliott Mitchell <ehem+debian at m5p.com> --- debian/rules | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index acf1825edd..ed9f4895bc 100755 --- a/debian/rules +++ b/debian/rules @@ -136,7 +136,9 @@ dpkg_LDFLAGS := $(shell $(dbmo) dpkg-buildflags --get LDFLAGS) make_args_common := \ XEN_COMPILE_ARCH=$(xen_arch_$(DEB_BUILD_ARCH)) \ - XEN_TARGET_ARCH=$(xen_arch_$(flavour)) + XEN_TARGET_ARCH=$(xen_arch_$(flavour)) \ + CC=$(DEB_HOST_MULTIARCH)-gcc \ + LD=$(DEB_HOST_MULTIARCH)-ld make_args_xen := $(make_args_common) # (Xen upstream does not offer a separate CPPFLAGS, -- -- (\___(\___(\______ --=> 8-) EHM <=-- ______/)___/)___/) \BS ( | ehem+sigmsg at m5p.com PGP 87145445 | ) / \_CS\ | _____ -O #include <stddisclaimer.h> O- _____ | / _/ 8A19\___\_|_/58D2 7E3D DDF4 7BA6 <-PGP-> 41D1 B375 37D0 8714\_|_/___/5445
Elliott Mitchell
2020-Oct-25 01:47 UTC
[Pkg-xen-devel] [PATCH 6/9] debian/rules: Setup use of noOCAML profile
This adds support for use of the "noocaml" profile (https://wiki.debian.org/BuildProfileSpec). This allows disabling build of OCAML portions of Xen. As presently there is no separate oxenstored package, this makes due by using empty files to replace expected files. Presently the primary expected use is to allow cross-building of the Xen packages. At this time cross-building for OCAML is very broken. Hopefully it may work in future, but at this time it does not. Signed-off-by: Elliott Mitchell <ehem+debian at m5p.com> --- debian/control | 4 ++-- debian/rules | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/debian/control b/debian/control index 90007f6a02..4c25e95971 100644 --- a/debian/control +++ b/debian/control @@ -32,8 +32,8 @@ Build-Depends: zlib1g-dev, pandoc, markdown, - ocaml-native-compilers | ocaml-nox, - ocaml-findlib, + ocaml-native-compilers <!noocaml> | ocaml-nox <!noocaml>, + ocaml-findlib <!noocaml>, Homepage: https://xenproject.org/ Vcs-Browser: https://salsa.debian.org/xen-team/debian-xen Vcs-Git: https://salsa.debian.org/xen-team/debian-xen.git diff --git a/debian/rules b/debian/rules index ed9f4895bc..2ff2574497 100755 --- a/debian/rules +++ b/debian/rules @@ -148,6 +148,11 @@ make_args_tools := $(make_args_common) \ EXTRA_CFLAGS_XEN_TOOLS='$(dpkg_CFLAGS) $(dpkg_CPPFLAGS)' \ PREPEND_LDFLAGS_XEN_TOOLS='$(dpkg_LDFLAGS)' +# Disable Xen's OCAML build if specified +ifneq ($(filter noocaml,$(DEB_BUILD_PROFILES)),) +make_args_tools += OCAML_TOOLS=n +endif + export PYBUILD_NAME=xen export PYBUILD_DISABLE=test export PYBUILD_SYSTEM=distutils @@ -222,6 +227,12 @@ override_dh_auto_install: $(TEMPLATED_FILES) $(MAKE) $(make_args_tools) DESTDIR=$t \ install-{tools,docs} CONFIG_PV_SHIM=n : + @# xen-utils-common needs these against another installation w/OCAML + if [ -n "$(filter noocaml,$(DEB_BUILD_PROFILES))" ]; then \ + ln tools/ocaml/xenstored/oxenstored.conf $t/etc/xen/oxenstored.conf ; \ + ln -s /usr/lib/xen-common/bin/xen-utils-wrapper $t/usr/sbin/oxenstored ; \ + fi + : @# shim install target needs to be run separately because we @# need to pass it the make_args_xen settings, in particular @# on i386 we need to pass x86_64 here to actually build it. -- -- (\___(\___(\______ --=> 8-) EHM <=-- ______/)___/)___/) \BS ( | ehem+sigmsg at m5p.com PGP 87145445 | ) / \_CS\ | _____ -O #include <stddisclaimer.h> O- _____ | / _/ 8A19\___\_|_/58D2 7E3D DDF4 7BA6 <-PGP-> 41D1 B375 37D0 8714\_|_/___/5445
Elliott Mitchell
2020-Oct-25 01:47 UTC
[Pkg-xen-devel] [PATCH 7/9] debian/xen.init: Load xen_acpi_processor on boot
This allows more control of processor state, potentially resulting in reduced power usage. Alternatively simply more information on processor use. Signed-off-by: Elliott Mitchell <ehem+debian at m5p.com> --- debian/xen-utils-common.xen.init | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/xen-utils-common.xen.init b/debian/xen-utils-common.xen.init index 1a64d6767e..8dac05f9de 100644 --- a/debian/xen-utils-common.xen.init +++ b/debian/xen-utils-common.xen.init @@ -67,6 +67,7 @@ modules_setup() modprobe xenfs 2>/dev/null modprobe xen-evtchn 2>/dev/null modprobe xen-gntdev 2>/dev/null + modprobe xen-acpi-processor 2>/dev/null } xenfs_setup() -- -- (\___(\___(\______ --=> 8-) EHM <=-- ______/)___/)___/) \BS ( | ehem+sigmsg at m5p.com PGP 87145445 | ) / \_CS\ | _____ -O #include <stddisclaimer.h> O- _____ | / _/ 8A19\___\_|_/58D2 7E3D DDF4 7BA6 <-PGP-> 41D1 B375 37D0 8714\_|_/___/5445
Elliott Mitchell
2020-Oct-25 01:47 UTC
[Pkg-xen-devel] [PATCH 8/9] debian/scripts: Optimize runtime scripts
Fewer fork()s and execve()s quickly add up to significant savings. I'm concerned Debian is slowly headed towards recreating SunOS^WSolaris 5.7^W2.7^W7 and the layers and layers of scripts which killed performance. As these runtime scripts are heavily used, avoid all uses of external programs by them. Signed-off-by: Elliott Mitchell <ehem+debian at m5p.com> --- debian/scripts/xen-utils-wrapper | 43 +++++++++++++++++++++++++++++--- debian/scripts/xen-version | 6 +++-- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/debian/scripts/xen-utils-wrapper b/debian/scripts/xen-utils-wrapper index 4d27a62d33..6247fd0b29 100755 --- a/debian/scripts/xen-utils-wrapper +++ b/debian/scripts/xen-utils-wrapper @@ -1,6 +1,41 @@ -#!/bin/sh -e +#!/bin/sh -COMMAND="$(basename $0)" -DIR=$(/usr/lib/xen-common/bin/xen-dir) +# This portion is fast-path, avoid external programs, NOTE: NOT -e HERE! + +COMMAND="${0##*/}" + +DIR=/sys/hypervisor/version +# these return non-zero if hypervisor is absent, this is detected below +read major 2> /dev/null < $DIR/major +read minor 2> /dev/null < $DIR/minor +VERSION="$major.$minor" + +DIR="/usr/lib/xen-$VERSION/bin" + +[ -x "$DIR/$COMMAND" ] && exec "$DIR/$COMMAND" "$@" + + +# Certainly didn't work, now report failures, slower-path +set -e + +error() { + err="$1" + shift + echo "ERROR: " "$@" >&2 + exit $err +} + +[ -e "/sys/hypervisor/type" ] || error 1 "Can't find hypervisor information in sysfs!" + +read type < /sys/hypervisor/type +if [ "$type" != xen ]; then + [ -n "$type" ] || error 1 "Can't read hypervisor type from sysfs!" + error 1 "Hypervisor is not xen but '$type'!" +fi + +if [ ! -d "/usr/lib/xen-$VERSION" ]; then + error 127 "Can't find version $VERSION of xen utils (maybe xen-utils-$VERSION was already removed before rebooting out of Xen $VERSION), bailing out!" +fi + +error 127 "Unable to execute $DIR/$COMMAND" -exec "$DIR/bin/$COMMAND" "$@" diff --git a/debian/scripts/xen-version b/debian/scripts/xen-version index 492070a43b..5c42ad7351 100755 --- a/debian/scripts/xen-version +++ b/debian/scripts/xen-version @@ -6,10 +6,12 @@ error() { } if [ -e "/sys/hypervisor/type" ]; then - type="$(cat /sys/hypervisor/type)" + read type < /sys/hypervisor/type if [ "$type" = xen ]; then DIR=/sys/hypervisor/version - VERSION="$(cat $DIR/major).$(cat $DIR/minor)" + read major < $DIR/major + read minor < $DIR/minor + VERSION="$major.$minor" elif [ -z "$type" ]; then error "Can't read hypervisor type from sysfs!" else -- -- (\___(\___(\______ --=> 8-) EHM <=-- ______/)___/)___/) \BS ( | ehem+sigmsg at m5p.com PGP 87145445 | ) / \_CS\ | _____ -O #include <stddisclaimer.h> O- _____ | / _/ 8A19\___\_|_/58D2 7E3D DDF4 7BA6 <-PGP-> 41D1 B375 37D0 8714\_|_/___/5445
Elliott Mitchell
2020-Oct-25 01:47 UTC
[Pkg-xen-devel] [PATCH 9/9] d/xendomains.init: Remove use of `xen` compat wrapper for `xl`
During the transition from `xm` to `xl` there may have been some benefit to using a `xen` wrapper to call the appropriate one. Now `xl` is the only one in use and has been the only one for some time. As such adjust the `xendomains` script to use an internal wrapper instead. I am highly tempted to purge the `xen` wrapper, but could understand some users desiring to keep the compatibility around. Perhaps for a future where something replaces `xl`. Signed-off-by: Elliott Mitchell <ehem+debian at m5p.com> --- debian/xen-utils-common.xendomains.init | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/debian/xen-utils-common.xendomains.init b/debian/xen-utils-common.xendomains.init index ca03ae4cfe..cd6902d26e 100644 --- a/debian/xen-utils-common.xendomains.init +++ b/debian/xen-utils-common.xendomains.init @@ -31,6 +31,11 @@ fi shopt -s nullglob +xen() +{ + xl "$@" +} + check_config_name() { /usr/lib/xen-common/bin/xen-init-name "$1" 2>/dev/null -- -- (\___(\___(\______ --=> 8-) EHM <=-- ______/)___/)___/) \BS ( | ehem+sigmsg at m5p.com PGP 87145445 | ) / \_CS\ | _____ -O #include <stddisclaimer.h> O- _____ | / _/ 8A19\___\_|_/58D2 7E3D DDF4 7BA6 <-PGP-> 41D1 B375 37D0 8714\_|_/___/5445