чување 2c8c1df9b920777197d53f2a9a75c934652c0813
родитељ d89a12dd8c4c719b209036395eef469ce8c8c36d
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Sun, 10 Jul 2022 22:13:19 +0200
Chroot up to Python3; lib/gensums,lib/showpkgs: New scripts
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
измењених датотека: 15, додавања: 2530(+), брисања: 149(-)
diff --git a/01-cross.sh b/01-cross.sh
@@ -52,29 +52,43 @@ cp_or_fail -r ${WD}/${FLD}/* ${G_FIL}/
msg info "Copying patches to %s" ${G_PAT}
cp_or_fail -r ${WD}/${PTD}/* ${G_PAT}/
-msg info "Fetching packages"
-sed 1d ${WD}/lib/pkgs.tsv | \
+msg info "Fetching packages and checking MD5 sums"
+lineno=0
+totallines=$(wc -l ${WD}/lib/pkgs.tsv | cut -d ' ' -f1)
+totallines=$((totallines - 1))
while read -r record
do
-(
+ perc=$((lineno * 100 / totallines))
+ printf "%3d%%\r" "${perc}"
+ [ ${lineno} -eq 0 ] || \
+ (
delay=2 # seconds between downloads; customize rate limiting
- IFS=$(printf '\t')
- cn=0
- for column in ${record}; do
- case ${cn} in
- 0) url=${column};;
- 1) dir=${column};;
- *) ;;
- esac
- cn=$((cn+1))
- done
+ url=$(printf "${record}" | cut -d "$(printf '\t')" -f1)
+ dirtb=$(printf "${record}" | cut -sd "$(printf '\t')" -f2)
+ md5=$(printf "${record}" | cut -sd "$(printf '\t')" -f3)
+
+ tarball=${url##*/}
+ if [ -n "${dirtb}" ]; then
+ tarball=${dirtb}
+ fi
+
case ${url} in
- git:*|git+https:*) git_clone "${dir}" ${url##git+} ${delay};;
- https:*) fetch_pkg ${url} "${dir}" ${delay};;
+ git:*|git+https:*) git_clone "${dirtb}" ${url##git+} ${delay};;
+ https:*) fetch_pkg ${url} "${dirtb}" ${delay};;
*) ;;
esac
-)
-done
+ if [ -n "${md5}" ]; then
+ if ! printf "%s %s" "${md5}" "${G_PKG}/${tarball}" | \
+ md5sum -c - >/dev/null 2>&1; then
+ msg err "MD5 check failed on %s" ${tarball}
+ exit 1
+ fi
+ fi
+ ) || exit 1
+ lineno=$((lineno+1))
+done <${WD}/lib/pkgs.tsv
+echo
+unset lineno
begin_substep linux-5.17.13 "Linux headers"
if [ -e ${CT}/${G_TARGET}/include/linux/stddef.h ]; then
@@ -358,7 +372,7 @@ SPECFILE=$(realpath $(dirname $(${G_TARGET}-gcc -print-libgcc-file-name)))/specs
msg info "Specfile at %s" "${SPECFILE}"
${G_TARGET}-gcc -dumpspecs > specs
/bin/sed -i 's,:\(/lib/ld-musl-'${G_ARCH_EXT_ALT}'.so.1\),:/'${TLD}'\1,g' specs
-cat specs >>${G_LOG}
+cat specs >>${G_LOGFILE}
mv_or_fail specs ${SPECFILE}
unset SPECFILE
@@ -574,7 +588,7 @@ SPECFILE=$(realpath $(dirname $(${G_TARGET}-gcc -print-libgcc-file-name)))/specs
msg info "Specfile at %s" "${SPECFILE}"
${G_TARGET}-gcc -dumpspecs > specs
/bin/sed -i 's,:\(/lib/ld-musl-'${G_ARCH_EXT_ALT}'.so.1\),:/'${TLD}'\1,g' specs
-cat specs >>${G_LOG}
+cat specs >>${G_LOGFILE}
mv_or_fail specs ${SPECFILE}
unset SPECFILE
diff --git a/02-prep-chroot.sh b/02-prep-chroot.sh
@@ -143,11 +143,11 @@ cp_or_fail ${WD}/lib/env.sh ${G_LIB}/env.sh
cp_or_fail ${WD}/lib/fun.sh ${G_LIB}/fun.sh
msg warn "Next run 03-chroot.sh"
-msg query "Run as root [y/N]?"
+msg query "Run as root [Y/n]?"
read -r run_as_root
case "${run_as_root}" in
- y|Y) chroot ${GR} /${TLD}/bin/mksh -l +h;;
- *) chroot --userspec=${GUID}:${GGID} ${GR} /${TLD}/bin/mksh -l +h;;
+ n|N) chroot --userspec=${GUID}:${GGID} ${GR} /${TLD}/bin/mksh -l +h;;
+ *) chroot ${GR} /${TLD}/bin/mksh -l +h;;
esac
umount ${GR}/tmp
diff --git a/03-chroot.sh b/03-chroot.sh
@@ -1675,7 +1675,7 @@ XML/Parser.pm ${pkg}
elif [ -e ${G_SPKG}/${pkg}.tar.xz ]; then
unpack_pkg ${pkg} /
else
- extract_pkg ${G_SRC} ${pkg} ${pkg}.tar.gz
+ extract_pkg ${G_SRC} ${pkg} ${pkg}.tar.gz touch
(
cd_or_fail ${G_SRC}/${pkg}
@@ -1768,11 +1768,11 @@ mkpk_install()
./configure --prefix=/sucks
make ${JN} || exit 1
- make install
+ make install DESTDIR=/build
}
!
mkpk ${pkg}
- #unpack_pkg ${pkg} /
+ unpack_pkg ${pkg} /
) || exit 1
remove_dir ${G_SRC}/${pkg}
fi
@@ -1837,11 +1837,6 @@ mkpk_install()
DESTDIR=/build
export CFLAGS LDFLAGS DESTDIR
- touch configure.ac
- touch Makefile.in
- touch aclocal.m4
- touch configure
-
./configure --prefix=/sucks --docdir=/sucks/share/doc/${pkg}
make ${JN} || exit 1
@@ -1879,7 +1874,6 @@ mkpk_install()
export CFLAGS LDFLAGS DESTDIR
sed -i '/pkgconfig_DATA/i pkgconfigdir=/lib/pkgconfig' Makefile.am
- mkdir m4
./bootstrap.sh
./configure --prefix=/ --sysconfdir=/etc --localstatedir=/var
@@ -1895,6 +1889,438 @@ mkpk_install()
fi
end_substep
+begin_substep musl-obstack-1.1
+if [ -e /lib/libobstack.a ]; then
+ msg info "%s exists, skipping %s" /lib/libobstack.a ${pkg}
+elif [ -e ${G_SPKG}/${pkg}.tar.gz ]; then
+ unpack_pkg ${pkg} /
+else
+ extract_pkg ${G_SRC} ${pkg} ${pkg}.tar.gz
+ (
+ cd_or_fail ${G_SRC}/${pkg}
+
+ cat <<! >MKPK
+mkpk_name()
+{
+ printf "%s" "${pkg}"
+}
+
+mkpk_install()
+{
+ CFLAGS='-O3 -march=native -mtune=native -pipe -fPIC'
+ LDFLAGS=
+ DESTDIR=/build
+ export CFLAGS LDFLAGS DESTDIR
+
+ sed -i '/pkgconfig_DATA/i pkgconfigdir=/lib/pkgconfig' Makefile.am
+ ./bootstrap.sh
+
+ ./configure --prefix=/ --sysconfdir=/etc --localstatedir=/var
+
+ make ${JN} || exit 1
+ make install-strip
+}
+!
+ mkpk ${pkg}
+ unpack_pkg ${pkg} /
+ ) || exit 1
+ remove_dir ${G_SRC}/${pkg}
+fi
+end_substep
+
+begin_substep xz-5.2.5
+if [ -e /bin/xz ]; then
+ msg info "%s exists, skipping %s" /bin/xz ${pkg}
+elif [ -e ${G_SPKG}/${pkg}.tar.xz ]; then
+ unpack_pkg ${pkg} /
+else
+ extract_pkg ${G_SRC} ${pkg} ${pkg}.tar.xz
+ (
+ cd_or_fail ${G_SRC}/${pkg}
+
+ apply_patch final-system -Np1 -i \
+ ${G_PAT}/xz-alpine/xzgrep-ZDI-CAN-16587.patch
+
+ cat <<! >MKPK
+mkpk_name()
+{
+ printf "%s" "${pkg}"
+}
+
+mkpk_install()
+{
+ CFLAGS='-O3 -march=native -mtune=native -pipe -static --static -fcommon'
+ LDFLAGS='-static --static -fcommon'
+ DESTDIR=/build
+ export CFLAGS LDFLAGS DESTDIR
+
+ ./configure --prefix=/ --docdir=/share/doc/${pkg}
+
+ make ${JN} || exit 1
+ make install-strip
+}
+!
+ mkpk ${pkg}
+ unpack_pkg ${pkg} /
+ ) || exit 1
+ remove_dir ${G_SRC}/${pkg}
+fi
+end_substep
+
+begin_substep kmod-29
+if [ -e /bin/kmod ]; then
+ msg info "%s exists, skipping %s" /bin/kmod ${pkg}
+elif [ -e ${G_SPKG}/${pkg}.tar.xz ]; then
+ unpack_pkg ${pkg} /
+else
+ extract_pkg ${G_SRC} ${pkg} ${pkg}.tar.xz
+ (
+ cd_or_fail ${G_SRC}/${pkg}
+
+ cat <<! >MKPK
+mkpk_name()
+{
+ printf "%s" "${pkg}"
+}
+
+mkpk_install()
+{
+ CFLAGS='-O3 -march=native -mtune=native -pipe -static --static -fcommon'
+ LDFLAGS='-static --static -fcommon'
+ DESTDIR=/build
+ export CFLAGS LDFLAGS DESTDIR
+
+ ./configure --prefix=/ \
+ --sysconfdir=/etc \
+ --with-xz \
+ --with-zlib \
+ --with-zstd
+
+ make ${JN} || exit 1
+ make install-strip
+
+ for p in depmod insmod lsmod modinfo modprobe rmmod
+ do
+ ln -sfv kmod /build/bin/\$p
+ done
+}
+!
+ mkpk ${pkg}
+ unpack_pkg ${pkg} /
+ ) || exit 1
+ remove_dir ${G_SRC}/${pkg}
+fi
+end_substep
+
+begin_substep gettext-tiny-0.3.2
+if [ -e /bin/msgfmt ]; then
+ msg info "%s exists, skipping %s" /bin/msgfmt ${pkg}
+elif [ -e ${G_SPKG}/${pkg}.tar.xz ]; then
+ unpack_pkg ${pkg} /
+else
+ extract_pkg ${G_SRC} ${pkg} ${pkg}.tar.xz
+ (
+ cd_or_fail ${G_SRC}/${pkg}
+
+ cat <<! >MKPK
+mkpk_name()
+{
+ printf "%s" "${pkg}"
+}
+
+mkpk_install()
+{
+ cat <<@ >config.mak
+CFLAGS=-O3 -march=native -mtune=native -pipe -static --static -fcommon
+LDFLAGS=-static --static -fcommon
+@
+ sed -i 's,/usr/local,,g' Makefile
+ make LIBINTL=MUSL ${JN} || exit 1
+ make LIBINTL=MUSL DESTDIR=/build prefix=/ install
+}
+!
+ mkpk ${pkg}
+ unpack_pkg ${pkg} /
+ ) || exit 1
+ remove_dir ${G_SRC}/${pkg}
+fi
+end_substep
+
+begin_substep musl-legacy-compat-20220710
+if [ -e /include/sys/cdefs.h ]; then
+ msg info "%s exists, skipping %s" /include/sys/cdefs.h ${pkg}
+elif [ -e ${G_SPKG}/${pkg}.tar.xz ]; then
+ unpack_pkg ${pkg} /
+else
+ check_dir ${G_SRC}/${pkg}
+ cp_or_fail -r "${G_FIL}/musl-legacy-compat-void" ${G_SRC}/${pkg}/
+ (
+ cd_or_fail ${G_SRC}/${pkg}
+
+ cat <<! >MKPK
+mkpk_name()
+{
+ printf "%s" "${pkg}"
+}
+
+mkpk_install()
+{
+ for h in cdefs queue tree
+ do
+ install -Dm 644 musl-legacy-compat-void/\$h.h \
+ /build/include/sys/\$h.h
+ done
+}
+!
+ mkpk ${pkg}
+ unpack_pkg ${pkg} /
+ ) || exit 1
+ remove_dir ${G_SRC}/${pkg}
+fi
+end_substep
+
+begin_substep argp-standalone-1.4.1
+if [ -e /lib/libargp.a ]; then
+ msg info "%s exists, skipping %s" /lib/libargp.a ${pkg}
+elif [ -e ${G_SPKG}/${pkg}.tar.xz ]; then
+ unpack_pkg ${pkg} /
+else
+ extract_pkg "${G_SRC}" "${pkg}" "${pkg}.tar.gz"
+ (
+ cd_or_fail ${G_SRC}/${pkg}
+ apply_patch final-system -Np1 -i \
+ ${G_PAT}/argp-standalone-adelie/gnu89-inline.patch
+ apply_patch final-system -Np1 -i \
+ ${G_PAT}/argp-standalone-mlfs/\
+generate_configure_script.patch
+ cat <<! >MKPK
+mkpk_name()
+{
+ printf "%s" "${pkg}"
+}
+
+mkpk_install()
+{
+ chmod +x configure
+
+ CFLAGS='-O3 -march=native -mtune=native -pipe -fPIC' \\
+ ./configure --prefix=/ \\
+ --sysconfdir=/etc \\
+ --localstatedir=/var
+ make ${JN} || exit 1
+
+ mkdir -p /build/lib
+ mkdir -p /build/include
+
+ cp libargp.a /build/lib
+ cp argp.h /build/include
+}
+!
+ mkpk ${pkg}
+ remove_dir ${G_SRC}/${pkg}
+ unpack_pkg ${pkg} /
+ ) || exit 1
+ remove_dir ${G_SRC}/${pkg}
+fi
+end_substep
+
+begin_substep libelf-0.186
+if [ -e /sucks/lib/libelf-0.186.so ]; then
+ msg info "%s exists, skipping %s" /sucks/lib/libelf-0.186.so ${pkg}
+elif [ -e ${G_SPKG}/${pkg}.tar.xz ]; then
+ unpack_pkg ${pkg} /
+else
+ extract_pkg ${G_SRC} elfutils-0.186 ${pkg}.tar.bz2 ${pkg}
+ (
+ cd_or_fail ${G_SRC}/${pkg}
+ cp_or_fail ${G_FIL}/elfutils-void/error.h lib/
+ cp_or_fail ${G_FIL}/elfutils-void/error.h src/
+
+ cat <<! >MKPK
+mkpk_name()
+{
+ printf "%s" "${pkg}"
+}
+
+mkpk_install()
+{
+ CFLAGS='-O3 -march=native -mtune=native -pipe'
+ CFLAGS+=' -DFNM_EXTMATCH=0 -Wno-error -Wno-error=null-dereference'
+ CFLAGS+=' -Wl,-z,stack-size=2097152'
+ LDFLAGS=''
+ DESTDIR=/build
+ export CFLAGS LDFLAGS DESTDIR
+
+ autoreconf -vif
+
+ ./configure --prefix=/sucks \
+ --disable-debuginfod \
+ --enable-libdebuginfod=dummy
+
+ make ${JN} -C lib || exit 1
+ make ${JN} -C libelf || exit 1
+ make -C libelf DESTDIR=\${DESTDIR} install
+
+ mkdir -p /build/sucks/lib/pkgconfig
+ install -vm644 config/libelf.pc /build/sucks/lib/pkgconfig/
+}
+!
+ mkpk ${pkg}
+ unpack_pkg ${pkg} /
+ ) || exit 1
+ remove_dir ${G_SRC}/${pkg}
+fi
+end_substep
+
+begin_substep libffi-3.4.2
+if [ -e /sucks/lib/libffi.so.8.1.0 ]; then
+ msg info "%s exists, skipping %s" /sucks/lib/libffi.so.8.1.0 ${pkg}
+elif [ -e ${G_SPKG}/${pkg}.tar.xz ]; then
+ unpack_pkg ${pkg} /
+else
+ extract_pkg ${G_SRC} ${pkg} ${pkg}.tar.gz
+ (
+ cd_or_fail ${G_SRC}/${pkg}
+
+ apply_patch final-system -Np1 -i \
+ ${G_PAT}/libffi-alpine/pax-dlmmap.patch
+
+ cat <<! >MKPK
+mkpk_name()
+{
+ printf "%s" "${pkg}"
+}
+
+mkpk_install()
+{
+ CFLAGS='-O3 -march=native -mtune=native -pipe'
+ LDFLAGS=''
+ DESTDIR=/build
+ export CFLAGS LDFLAGS DESTDIR
+
+ ./configure --prefix=/sucks \
+ --disable-static \
+ --includedir=/sucks/include \
+ --disable-multi-os-directory \
+ --with-pic
+
+ make ${JN} || exit 1
+ make install
+}
+!
+ mkpk ${pkg}
+ unpack_pkg ${pkg} /
+ ) || exit 1
+ remove_dir ${G_SRC}/${pkg}
+fi
+end_substep
+
+# LibreSSL doesn't suck, even though technically IMHO it should belong in /sucks
+# since currently I don't see a clear way to produce both static and dynamic
+# libraries while keeping binaries static
+begin_substep libressl-3.4.2
+if [ -e /lib/libssl.a ]; then
+ msg info "%s exists, skipping %s" /lib/libssl.a ${pkg}
+elif [ -e ${G_SPKG}/${pkg}.tar.xz ]; then
+ unpack_pkg ${pkg} /
+else
+ extract_pkg ${G_SRC} ${pkg} ${pkg}.tar.gz
+ (
+ cd_or_fail ${G_SRC}/${pkg}
+
+ cat <<! >MKPK
+mkpk_name()
+{
+ printf "%s" "${pkg}"
+}
+
+mkpk_install()
+{
+ CFLAGS='-O3 -march=native -mtune=native -pipe'
+ LDFLAGS=''
+ DESTDIR=/build
+ export CFLAGS LDFLAGS DESTDIR
+
+ autoreconf -vif
+
+ ./configure --prefix=/ \
+ --sysconfdir=/etc \
+ --mandir=/share/man \
+ --localstatedir=/var
+
+ make ${JN} || exit 1
+ make install-strip
+}
+!
+ mkpk ${pkg}
+ unpack_pkg ${pkg} /
+ ) || exit 1
+ remove_dir ${G_SRC}/${pkg}
+fi
+end_substep
+
+begin_substep Python-3.9.9
+if [ -x /sucks/bin/python3 ]; then
+ msg info "%s exists, skipping %s" /sucks/bin/python3 ${pkg}
+elif [ -e ${G_SPKG}/${pkg}.tar.xz ]; then
+ unpack_pkg ${pkg} /
+else
+ extract_pkg ${G_SRC} ${pkg} ${pkg}.tar.xz
+ (
+ cd_or_fail ${G_SRC}/${pkg}
+
+ apply_patch final-system -Np0 -i \
+ ${G_PAT}/python3-void/musl-find_library.patch
+ apply_patch final-system -Np0 -i \
+ ${G_PAT}/python3-void/tweak-MULTIARCH-for-powerpc-\
+linux-musl.patch
+
+ remove_dir Modules/expat
+ remove_dir Modules/_ctypes/darwin
+ remove_dir Modules/_ctypes/libffi
+
+ cat <<! >MKPK
+mkpk_name()
+{
+ printf "%s" "${pkg}"
+}
+
+mkpk_install()
+{
+ CFLAGS='-O3 -march=native -mtune=native -pipe'
+ LDFLAGS=''
+ DESTDIR=/build
+ export CFLAGS LDFLAGS DESTDIR
+
+ ./configure --prefix=/sucks \
+ --enable-shared \
+ --with-system-expat \
+ --with-system-ffi \
+ --with-ensurepip=yes \
+ --enable-ipv6 \
+ --with-threads \
+ --enable-loadable-sqlite-extensions \
+ --with-computed-gotos
+
+ make ${JN} || exit 1
+ make install
+
+ chmod 755 /build/sucks/lib/libpython3.9.so
+
+ ln -sv python3.9 /build/sucks/bin/python
+ ln -sv python3.9-config /build/sucks/bin/python-config
+ ln -sv idle3.9 /build/sucks/bin/idle
+ ln -sv pydoc3.9 /build/sucks/bin/pydoc
+ ln -sv python3.9.1 /build/sucks/share/man/man1/python.1
+}
+!
+ mkpk ${pkg}
+ unpack_pkg ${pkg} /
+ ) || exit 1
+ remove_dir ${G_SRC}/${pkg}
+fi
+end_substep
+
if false; then
# Needs CMake (BMLFS)
begin_substep musl-locales-20220708
@@ -2000,49 +2426,5 @@ fi
end_substep
# Move after autotools
-begin_substep argp-standalone-1.4.1
-if [ -x /bin/argp ]; then
- msg info "%s exists, skipping %s" /bin/pkg-config ${pkg}
-elif [ -e ${G_SPKG}/${pkg}.tar.xz ]; then
- unpack_pkg ${pkg} /
-else
- extract_pkg "${G_SRC}" "${pkg}" "${pkg}.tar.gz"
- (
- cd_or_fail ${G_SRC}/${pkg}
- apply_patch final-system -Np1 -i \
- ${G_PAT}/argp-standalone-adelie/gnu89-inline.patch
- apply_patch final-system -Np1 -i \
- ${G_PAT}/argp-standalone-mlfs/\
-generate_configure_script.patch
- cat <<! >MKPK
-mkpk_name()
-{
- printf "%s" "${pkg}"
-}
-
-mkpk_install()
-{
- chmod +x configure
-
- CFLAGS='-O3 -march=native -mtune=native -pipe -fPIC' \\
- ./configure --prefix=/ \\
- --sysconfdir=/etc \\
- --localstatedir=/var
- make ${JN} || exit 1
-
- mkdir -p /build/lib
- mkdir -p /build/include
-
- cp libargp.a /build/lib
- cp argp.h /build/include
-}
-!
- mkpk ${pkg}
- remove_dir ${G_SRC}/${pkg}
- unpack_pkg ${pkg} /
- ) || exit 1
- remove_dir ${G_SRC}/${pkg}
-fi
-end_substep
fi
end_step
diff --git a/fil/elfutils-void/error.h b/fil/elfutils-void/error.h
@@ -0,0 +1,27 @@
+#ifndef _ERROR_H_
+#define _ERROR_H_
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+static unsigned int error_message_count = 0;
+
+static inline void error(int status, int errnum, const char* format, ...)
+{
+ va_list ap;
+ fprintf(stderr, "%s: ", program_invocation_name);
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ if (errnum)
+ fprintf(stderr, ": %s", strerror(errnum));
+ fprintf(stderr, "\n");
+ error_message_count++;
+ if (status)
+ exit(status);
+}
+
+#endif /* _ERROR_H_ */
diff --git a/fil/musl-legacy-compat-void/cdefs.h b/fil/musl-legacy-compat-void/cdefs.h
@@ -0,0 +1,29 @@
+#warning usage of non-standard #include <sys/cdefs.h> is deprecated
+
+#undef __P
+#undef __PMT
+
+#define __P(args) args
+#define __PMT(args) args
+
+#define __CONCAT(x,y) x ## y
+#define __STRING(x) #x
+
+#ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+#else
+# define __BEGIN_DECLS
+# define __END_DECLS
+#endif
+
+#if defined(__GNUC__) && !defined(__cplusplus)
+# define __THROW __attribute__ ((__nothrow__))
+# define __NTH(fct) __attribute__ ((__nothrow__)) fct
+#else
+# define __THROW
+# define __NTH(fct) fct
+#endif
+
+#define __CONCAT(x,y) x ## y
+#define __STRING(x) #x
diff --git a/fil/musl-legacy-compat-void/queue.h b/fil/musl-legacy-compat-void/queue.h
@@ -0,0 +1,846 @@
+/* $NetBSD: queue.h,v 1.68 2014/11/19 08:10:01 uebayasi Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The
+ * elements are singly linked for minimum space and pointer manipulation
+ * overhead at the expense of O(n) removal for arbitrary elements. New
+ * elements can be added to the list after an existing element or at the
+ * head of the list. Elements being removed from the head of the list
+ * should use the explicit macro for this purpose for optimum
+ * efficiency. A singly-linked list may only be traversed in the forward
+ * direction. Singly-linked lists are ideal for applications with large
+ * datasets and few or no removals or for implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * Include the definition of NULL only on NetBSD because sys/null.h
+ * is not available elsewhere. This conditional makes the header
+ * portable and it can simply be dropped verbatim into any system.
+ * The caveat is that on other systems some other header
+ * must provide NULL before the macros can be used.
+ */
+#ifdef __NetBSD__
+#include <sys/null.h>
+#endif
+
+#if defined(QUEUEDEBUG)
+# if defined(_KERNEL)
+# define QUEUEDEBUG_ABORT(...) panic(__VA_ARGS__)
+# else
+# include <err.h>
+# define QUEUEDEBUG_ABORT(...) err(1, __VA_ARGS__)
+# endif
+#endif
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List access methods.
+ */
+#define SLIST_FIRST(head) ((head)->slh_first)
+#define SLIST_END(head) NULL
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_FOREACH(var, head, field) \
+ for((var) = (head)->slh_first; \
+ (var) != SLIST_END(head); \
+ (var) = (var)->field.sle_next)
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var) != SLIST_END(head) && \
+ ((tvar) = SLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_INIT(head) do { \
+ (head)->slh_first = SLIST_END(head); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ (elm)->field.sle_next = (slistelm)->field.sle_next; \
+ (slistelm)->field.sle_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE_AFTER(slistelm, field) do { \
+ (slistelm)->field.sle_next = \
+ SLIST_NEXT(SLIST_NEXT((slistelm), field), field); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = (head)->slh_first; \
+ while(curelm->field.sle_next != (elm)) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List access methods.
+ */
+#define LIST_FIRST(head) ((head)->lh_first)
+#define LIST_END(head) NULL
+#define LIST_EMPTY(head) ((head)->lh_first == LIST_END(head))
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = ((head)->lh_first); \
+ (var) != LIST_END(head); \
+ (var) = ((var)->field.le_next))
+
+#define LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = LIST_FIRST((head)); \
+ (var) != LIST_END(head) && \
+ ((tvar) = LIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define LIST_MOVE(head1, head2) do { \
+ LIST_INIT((head2)); \
+ if (!LIST_EMPTY((head1))) { \
+ (head2)->lh_first = (head1)->lh_first; \
+ LIST_INIT((head1)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+/*
+ * List functions.
+ */
+#if defined(QUEUEDEBUG)
+#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \
+ if ((head)->lh_first && \
+ (head)->lh_first->field.le_prev != &(head)->lh_first) \
+ QUEUEDEBUG_ABORT("LIST_INSERT_HEAD %p %s:%d", (head), \
+ __FILE__, __LINE__);
+#define QUEUEDEBUG_LIST_OP(elm, field) \
+ if ((elm)->field.le_next && \
+ (elm)->field.le_next->field.le_prev != \
+ &(elm)->field.le_next) \
+ QUEUEDEBUG_ABORT("LIST_* forw %p %s:%d", (elm), \
+ __FILE__, __LINE__); \
+ if (*(elm)->field.le_prev != (elm)) \
+ QUEUEDEBUG_ABORT("LIST_* back %p %s:%d", (elm), \
+ __FILE__, __LINE__);
+#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \
+ (elm)->field.le_next = (void *)1L; \
+ (elm)->field.le_prev = (void *)1L;
+#else
+#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field)
+#define QUEUEDEBUG_LIST_OP(elm, field)
+#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field)
+#endif
+
+#define LIST_INIT(head) do { \
+ (head)->lh_first = LIST_END(head); \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ QUEUEDEBUG_LIST_OP((listelm), field) \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != \
+ LIST_END(head)) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ QUEUEDEBUG_LIST_OP((listelm), field) \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \
+ if (((elm)->field.le_next = (head)->lh_first) != LIST_END(head))\
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_REMOVE(elm, field) do { \
+ QUEUEDEBUG_LIST_OP((elm), field) \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+ QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \
+} while (/*CONSTCOND*/0)
+
+#define LIST_REPLACE(elm, elm2, field) do { \
+ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
+ (elm2)->field.le_next->field.le_prev = \
+ &(elm2)->field.le_next; \
+ (elm2)->field.le_prev = (elm)->field.le_prev; \
+ *(elm2)->field.le_prev = (elm2); \
+ QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \
+} while (/*CONSTCOND*/0)
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue access methods.
+ */
+#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define SIMPLEQ_END(head) NULL
+#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == SIMPLEQ_END(head))
+#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->sqh_first); \
+ (var) != SIMPLEQ_END(head); \
+ (var) = ((var)->field.sqe_next))
+
+#define SIMPLEQ_FOREACH_SAFE(var, head, field, next) \
+ for ((var) = ((head)->sqh_first); \
+ (var) != SIMPLEQ_END(head) && \
+ ((next = ((var)->field.sqe_next)), 1); \
+ (var) = (next))
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
+ == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->sqh_first == (elm)) { \
+ SIMPLEQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->sqh_first; \
+ while (curelm->field.sqe_next != (elm)) \
+ curelm = curelm->field.sqe_next; \
+ if ((curelm->field.sqe_next = \
+ curelm->field.sqe_next->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(curelm)->field.sqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_CONCAT(head1, head2) do { \
+ if (!SIMPLEQ_EMPTY((head2))) { \
+ *(head1)->sqh_last = (head2)->sqh_first; \
+ (head1)->sqh_last = (head2)->sqh_last; \
+ SIMPLEQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_LAST(head, type, field) \
+ (SIMPLEQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *)(void *) \
+ ((char *)((head)->sqh_last) - offsetof(struct type, field))))
+
+/*
+ * Tail queue definitions.
+ */
+#define _TAILQ_HEAD(name, type, qual) \
+struct name { \
+ qual type *tqh_first; /* first element */ \
+ qual type *qual *tqh_last; /* addr of last next element */ \
+}
+#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { TAILQ_END(head), &(head).tqh_first }
+
+#define _TAILQ_ENTRY(type, qual) \
+struct { \
+ qual type *tqe_next; /* next element */ \
+ qual type *qual *tqe_prev; /* address of previous next element */\
+}
+#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
+
+/*
+ * Tail queue access methods.
+ */
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#define TAILQ_END(head) (NULL)
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+#define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == TAILQ_END(head))
+
+
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->tqh_first); \
+ (var) != TAILQ_END(head); \
+ (var) = ((var)->field.tqe_next))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, next) \
+ for ((var) = ((head)->tqh_first); \
+ (var) != TAILQ_END(head) && \
+ ((next) = TAILQ_NEXT(var, field), 1); (var) = (next))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));\
+ (var) != TAILQ_END(head); \
+ (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var) != TAILQ_END(head) && \
+ ((prev) = TAILQ_PREV((var), headname, field), 1); (var) = (prev))
+
+/*
+ * Tail queue functions.
+ */
+#if defined(QUEUEDEBUG)
+#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \
+ if ((head)->tqh_first && \
+ (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \
+ QUEUEDEBUG_ABORT("TAILQ_INSERT_HEAD %p %s:%d", (head), \
+ __FILE__, __LINE__);
+#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \
+ if (*(head)->tqh_last != NULL) \
+ QUEUEDEBUG_ABORT("TAILQ_INSERT_TAIL %p %s:%d", (head), \
+ __FILE__, __LINE__);
+#define QUEUEDEBUG_TAILQ_OP(elm, field) \
+ if ((elm)->field.tqe_next && \
+ (elm)->field.tqe_next->field.tqe_prev != \
+ &(elm)->field.tqe_next) \
+ QUEUEDEBUG_ABORT("TAILQ_* forw %p %s:%d", (elm), \
+ __FILE__, __LINE__); \
+ if (*(elm)->field.tqe_prev != (elm)) \
+ QUEUEDEBUG_ABORT("TAILQ_* back %p %s:%d", (elm), \
+ __FILE__, __LINE__);
+#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \
+ if ((elm)->field.tqe_next == NULL && \
+ (head)->tqh_last != &(elm)->field.tqe_next) \
+ QUEUEDEBUG_ABORT("TAILQ_PREREMOVE head %p elm %p %s:%d",\
+ (head), (elm), __FILE__, __LINE__);
+#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \
+ (elm)->field.tqe_next = (void *)1L; \
+ (elm)->field.tqe_prev = (void *)1L;
+#else
+#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field)
+#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field)
+#define QUEUEDEBUG_TAILQ_OP(elm, field)
+#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field)
+#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field)
+#endif
+
+#define TAILQ_INIT(head) do { \
+ (head)->tqh_first = TAILQ_END(head); \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != TAILQ_END(head))\
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \
+ (elm)->field.tqe_next = TAILQ_END(head); \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ QUEUEDEBUG_TAILQ_OP((listelm), field) \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != \
+ TAILQ_END(head)) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ QUEUEDEBUG_TAILQ_OP((listelm), field) \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \
+ QUEUEDEBUG_TAILQ_OP((elm), field) \
+ if (((elm)->field.tqe_next) != TAILQ_END(head)) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+ QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_REPLACE(head, elm, elm2, field) do { \
+ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != \
+ TAILQ_END(head)) \
+ (elm2)->field.tqe_next->field.tqe_prev = \
+ &(elm2)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm2)->field.tqe_next; \
+ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
+ *(elm2)->field.tqe_prev = (elm2); \
+ QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first; /* first element */ \
+ struct type **stqh_last; /* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue access methods.
+ */
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+#define STAILQ_END(head) NULL
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+#define STAILQ_EMPTY(head) (STAILQ_FIRST(head) == STAILQ_END(head))
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_INIT(head) do { \
+ (head)->stqh_first = NULL; \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (head)->stqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.stqe_next = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (listelm)->field.stqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->stqh_first == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->stqh_first; \
+ while (curelm->field.stqe_next != (elm)) \
+ curelm = curelm->field.stqe_next; \
+ if ((curelm->field.stqe_next = \
+ curelm->field.stqe_next->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(curelm)->field.stqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->stqh_first); \
+ (var); \
+ (var) = ((var)->field.stqe_next))
+
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = STAILQ_FIRST((head)); \
+ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_LAST(head, type, field) \
+ (STAILQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *)(void *) \
+ ((char *)((head)->stqh_last) - offsetof(struct type, field))))
+
+
+#ifndef _KERNEL
+/*
+ * Circular queue definitions. Do not use. We still keep the macros
+ * for compatibility but because of pointer aliasing issues their use
+ * is discouraged!
+ */
+
+/*
+ * __launder_type(): We use this ugly hack to work around the the compiler
+ * noticing that two types may not alias each other and elide tests in code.
+ * We hit this in the CIRCLEQ macros when comparing 'struct name *' and
+ * 'struct type *' (see CIRCLEQ_HEAD()). Modern compilers (such as GCC
+ * 4.8) declare these comparisons as always false, causing the code to
+ * not run as designed.
+ *
+ * This hack is only to be used for comparisons and thus can be fully const.
+ * Do not use for assignment.
+ *
+ * If we ever choose to change the ABI of the CIRCLEQ macros, we could fix
+ * this by changing the head/tail sentinal values, but see the note above
+ * this one.
+ */
+static __inline const void * __launder_type(const void *);
+static __inline const void *
+__launder_type(const void *__x)
+{
+ __asm __volatile("" : "+r" (__x));
+ return __x;
+}
+
+#if defined(QUEUEDEBUG)
+#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) \
+ if ((head)->cqh_first != CIRCLEQ_ENDC(head) && \
+ (head)->cqh_first->field.cqe_prev != CIRCLEQ_ENDC(head)) \
+ QUEUEDEBUG_ABORT("CIRCLEQ head forw %p %s:%d", (head), \
+ __FILE__, __LINE__); \
+ if ((head)->cqh_last != CIRCLEQ_ENDC(head) && \
+ (head)->cqh_last->field.cqe_next != CIRCLEQ_ENDC(head)) \
+ QUEUEDEBUG_ABORT("CIRCLEQ head back %p %s:%d", (head), \
+ __FILE__, __LINE__);
+#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) \
+ if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) { \
+ if ((head)->cqh_last != (elm)) \
+ QUEUEDEBUG_ABORT("CIRCLEQ elm last %p %s:%d", \
+ (elm), __FILE__, __LINE__); \
+ } else { \
+ if ((elm)->field.cqe_next->field.cqe_prev != (elm)) \
+ QUEUEDEBUG_ABORT("CIRCLEQ elm forw %p %s:%d", \
+ (elm), __FILE__, __LINE__); \
+ } \
+ if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) { \
+ if ((head)->cqh_first != (elm)) \
+ QUEUEDEBUG_ABORT("CIRCLEQ elm first %p %s:%d", \
+ (elm), __FILE__, __LINE__); \
+ } else { \
+ if ((elm)->field.cqe_prev->field.cqe_next != (elm)) \
+ QUEUEDEBUG_ABORT("CIRCLEQ elm prev %p %s:%d", \
+ (elm), __FILE__, __LINE__); \
+ }
+#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) \
+ (elm)->field.cqe_next = (void *)1L; \
+ (elm)->field.cqe_prev = (void *)1L;
+#else
+#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field)
+#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field)
+#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field)
+#endif
+
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head) \
+ { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) do { \
+ (head)->cqh_first = CIRCLEQ_END(head); \
+ (head)->cqh_last = CIRCLEQ_END(head); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = CIRCLEQ_END(head); \
+ if ((head)->cqh_last == CIRCLEQ_ENDC(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ (elm)->field.cqe_next = CIRCLEQ_END(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == CIRCLEQ_ENDC(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ QUEUEDEBUG_CIRCLEQ_ELM((head), (elm), field) \
+ if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+ QUEUEDEBUG_CIRCLEQ_POSTREMOVE((elm), field) \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->cqh_first); \
+ (var) != CIRCLEQ_ENDC(head); \
+ (var) = ((var)->field.cqe_next))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
+ for ((var) = ((head)->cqh_last); \
+ (var) != CIRCLEQ_ENDC(head); \
+ (var) = ((var)->field.cqe_prev))
+
+/*
+ * Circular queue access methods.
+ */
+#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
+#define CIRCLEQ_LAST(head) ((head)->cqh_last)
+/* For comparisons */
+#define CIRCLEQ_ENDC(head) (__launder_type(head))
+/* For assignments */
+#define CIRCLEQ_END(head) ((void *)(head))
+#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
+#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
+#define CIRCLEQ_EMPTY(head) \
+ (CIRCLEQ_FIRST(head) == CIRCLEQ_ENDC(head))
+
+#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
+ (((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
+ ? ((head)->cqh_first) \
+ : (elm->field.cqe_next))
+#define CIRCLEQ_LOOP_PREV(head, elm, field) \
+ (((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
+ ? ((head)->cqh_last) \
+ : (elm->field.cqe_prev))
+#endif /* !_KERNEL */
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/fil/musl-legacy-compat-void/tree.h b/fil/musl-legacy-compat-void/tree.h
@@ -0,0 +1,761 @@
+/* $NetBSD: tree.h,v 1.20 2013/09/14 13:20:45 joerg Exp $ */
+/* $OpenBSD: tree.h,v 1.13 2011/07/09 00:19:45 pirofti Exp $ */
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_TREE_H_
+#define _SYS_TREE_H_
+
+/*
+ * This file defines data structures for different types of trees:
+ * splay trees and red-black trees.
+ *
+ * A splay tree is a self-organizing data structure. Every operation
+ * on the tree causes a splay to happen. The splay moves the requested
+ * node to the root of the tree and partly rebalances it.
+ *
+ * This has the benefit that request locality causes faster lookups as
+ * the requested nodes move to the top of the tree. On the other hand,
+ * every lookup causes memory writes.
+ *
+ * The Balance Theorem bounds the total access time for m operations
+ * and n inserts on an initially empty tree as O((m + n)lg n). The
+ * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
+ *
+ * A red-black tree is a binary search tree with the node color as an
+ * extra attribute. It fulfills a set of conditions:
+ * - every search path from the root to a leaf consists of the
+ * same number of black nodes,
+ * - each red node (except for the root) has a black parent,
+ * - each leaf node is black.
+ *
+ * Every operation on a red-black tree is bounded as O(lg n).
+ * The maximum height of a red-black tree is 2lg (n+1).
+ */
+
+#define SPLAY_HEAD(name, type) \
+struct name { \
+ struct type *sph_root; /* root of the tree */ \
+}
+
+#define SPLAY_INITIALIZER(root) \
+ { NULL }
+
+#define SPLAY_INIT(root) do { \
+ (root)->sph_root = NULL; \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_ENTRY(type) \
+struct { \
+ struct type *spe_left; /* left element */ \
+ struct type *spe_right; /* right element */ \
+}
+
+#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
+#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
+#define SPLAY_ROOT(head) (head)->sph_root
+#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
+
+/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
+#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
+ SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
+ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
+ (head)->sph_root = tmp; \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
+ SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
+ SPLAY_LEFT(tmp, field) = (head)->sph_root; \
+ (head)->sph_root = tmp; \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_LINKLEFT(head, tmp, field) do { \
+ SPLAY_LEFT(tmp, field) = (head)->sph_root; \
+ tmp = (head)->sph_root; \
+ (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_LINKRIGHT(head, tmp, field) do { \
+ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
+ tmp = (head)->sph_root; \
+ (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
+ SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
+ SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
+ SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
+ SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
+} while (/*CONSTCOND*/ 0)
+
+/* Generates prototypes and inline functions */
+
+#define SPLAY_PROTOTYPE(name, type, field, cmp) \
+void name##_SPLAY(struct name *, struct type *); \
+void name##_SPLAY_MINMAX(struct name *, int); \
+struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
+struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
+ \
+/* Finds the node with the same key as elm */ \
+static __inline struct type * \
+name##_SPLAY_FIND(struct name *head, struct type *elm) \
+{ \
+ if (SPLAY_EMPTY(head)) \
+ return(NULL); \
+ name##_SPLAY(head, elm); \
+ if ((cmp)(elm, (head)->sph_root) == 0) \
+ return (head->sph_root); \
+ return (NULL); \
+} \
+ \
+static __inline __unused struct type * \
+name##_SPLAY_NEXT(struct name *head, struct type *elm) \
+{ \
+ name##_SPLAY(head, elm); \
+ if (SPLAY_RIGHT(elm, field) != NULL) { \
+ elm = SPLAY_RIGHT(elm, field); \
+ while (SPLAY_LEFT(elm, field) != NULL) { \
+ elm = SPLAY_LEFT(elm, field); \
+ } \
+ } else \
+ elm = NULL; \
+ return (elm); \
+} \
+ \
+static __unused __inline struct type * \
+name##_SPLAY_MIN_MAX(struct name *head, int val) \
+{ \
+ name##_SPLAY_MINMAX(head, val); \
+ return (SPLAY_ROOT(head)); \
+}
+
+/* Main splay operation.
+ * Moves node close to the key of elm to top
+ */
+#define SPLAY_GENERATE(name, type, field, cmp) \
+struct type * \
+name##_SPLAY_INSERT(struct name *head, struct type *elm) \
+{ \
+ if (SPLAY_EMPTY(head)) { \
+ SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
+ } else { \
+ int __comp; \
+ name##_SPLAY(head, elm); \
+ __comp = (cmp)(elm, (head)->sph_root); \
+ if(__comp < 0) { \
+ SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
+ SPLAY_RIGHT(elm, field) = (head)->sph_root; \
+ SPLAY_LEFT((head)->sph_root, field) = NULL; \
+ } else if (__comp > 0) { \
+ SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
+ SPLAY_LEFT(elm, field) = (head)->sph_root; \
+ SPLAY_RIGHT((head)->sph_root, field) = NULL; \
+ } else \
+ return ((head)->sph_root); \
+ } \
+ (head)->sph_root = (elm); \
+ return (NULL); \
+} \
+ \
+struct type * \
+name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
+{ \
+ struct type *__tmp; \
+ if (SPLAY_EMPTY(head)) \
+ return (NULL); \
+ name##_SPLAY(head, elm); \
+ if ((cmp)(elm, (head)->sph_root) == 0) { \
+ if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
+ (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
+ } else { \
+ __tmp = SPLAY_RIGHT((head)->sph_root, field); \
+ (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
+ name##_SPLAY(head, elm); \
+ SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
+ } \
+ return (elm); \
+ } \
+ return (NULL); \
+} \
+ \
+void \
+name##_SPLAY(struct name *head, struct type *elm) \
+{ \
+ struct type __node, *__left, *__right, *__tmp; \
+ int __comp; \
+\
+ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
+ __left = __right = &__node; \
+\
+ while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
+ if (__comp < 0) { \
+ __tmp = SPLAY_LEFT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if ((cmp)(elm, __tmp) < 0){ \
+ SPLAY_ROTATE_RIGHT(head, __tmp, field); \
+ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKLEFT(head, __right, field); \
+ } else if (__comp > 0) { \
+ __tmp = SPLAY_RIGHT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if ((cmp)(elm, __tmp) > 0){ \
+ SPLAY_ROTATE_LEFT(head, __tmp, field); \
+ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKRIGHT(head, __left, field); \
+ } \
+ } \
+ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
+} \
+ \
+/* Splay with either the minimum or the maximum element \
+ * Used to find minimum or maximum element in tree. \
+ */ \
+void name##_SPLAY_MINMAX(struct name *head, int __comp) \
+{ \
+ struct type __node, *__left, *__right, *__tmp; \
+\
+ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
+ __left = __right = &__node; \
+\
+ while (1) { \
+ if (__comp < 0) { \
+ __tmp = SPLAY_LEFT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if (__comp < 0){ \
+ SPLAY_ROTATE_RIGHT(head, __tmp, field); \
+ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKLEFT(head, __right, field); \
+ } else if (__comp > 0) { \
+ __tmp = SPLAY_RIGHT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if (__comp > 0) { \
+ SPLAY_ROTATE_LEFT(head, __tmp, field); \
+ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKRIGHT(head, __left, field); \
+ } \
+ } \
+ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
+}
+
+#define SPLAY_NEGINF -1
+#define SPLAY_INF 1
+
+#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
+#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
+#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
+#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
+#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
+ : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
+#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
+ : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
+
+#define SPLAY_FOREACH(x, name, head) \
+ for ((x) = SPLAY_MIN(name, head); \
+ (x) != NULL; \
+ (x) = SPLAY_NEXT(name, head, x))
+
+/* Macros that define a red-black tree */
+#define RB_HEAD(name, type) \
+struct name { \
+ struct type *rbh_root; /* root of the tree */ \
+}
+
+#define RB_INITIALIZER(root) \
+ { NULL }
+
+#define RB_INIT(root) do { \
+ (root)->rbh_root = NULL; \
+} while (/*CONSTCOND*/ 0)
+
+#define RB_BLACK 0
+#define RB_RED 1
+#define RB_ENTRY(type) \
+struct { \
+ struct type *rbe_left; /* left element */ \
+ struct type *rbe_right; /* right element */ \
+ struct type *rbe_parent; /* parent element */ \
+ int rbe_color; /* node color */ \
+}
+
+#define RB_LEFT(elm, field) (elm)->field.rbe_left
+#define RB_RIGHT(elm, field) (elm)->field.rbe_right
+#define RB_PARENT(elm, field) (elm)->field.rbe_parent
+#define RB_COLOR(elm, field) (elm)->field.rbe_color
+#define RB_ROOT(head) (head)->rbh_root
+#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
+
+#define RB_SET(elm, parent, field) do { \
+ RB_PARENT(elm, field) = parent; \
+ RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
+ RB_COLOR(elm, field) = RB_RED; \
+} while (/*CONSTCOND*/ 0)
+
+#define RB_SET_BLACKRED(black, red, field) do { \
+ RB_COLOR(black, field) = RB_BLACK; \
+ RB_COLOR(red, field) = RB_RED; \
+} while (/*CONSTCOND*/ 0)
+
+#ifndef RB_AUGMENT
+#define RB_AUGMENT(x) do {} while (/*CONSTCOND*/ 0)
+#endif
+
+#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
+ (tmp) = RB_RIGHT(elm, field); \
+ if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
+ RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
+ } \
+ RB_AUGMENT(elm); \
+ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
+ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
+ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
+ else \
+ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
+ } else \
+ (head)->rbh_root = (tmp); \
+ RB_LEFT(tmp, field) = (elm); \
+ RB_PARENT(elm, field) = (tmp); \
+ RB_AUGMENT(tmp); \
+ if ((RB_PARENT(tmp, field))) \
+ RB_AUGMENT(RB_PARENT(tmp, field)); \
+} while (/*CONSTCOND*/ 0)
+
+#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
+ (tmp) = RB_LEFT(elm, field); \
+ if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
+ RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
+ } \
+ RB_AUGMENT(elm); \
+ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
+ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
+ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
+ else \
+ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
+ } else \
+ (head)->rbh_root = (tmp); \
+ RB_RIGHT(tmp, field) = (elm); \
+ RB_PARENT(elm, field) = (tmp); \
+ RB_AUGMENT(tmp); \
+ if ((RB_PARENT(tmp, field))) \
+ RB_AUGMENT(RB_PARENT(tmp, field)); \
+} while (/*CONSTCOND*/ 0)
+
+/* Generates prototypes and inline functions */
+#define RB_PROTOTYPE(name, type, field, cmp) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
+#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
+#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
+attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
+attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
+attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
+attr struct type *name##_RB_INSERT(struct name *, struct type *); \
+attr struct type *name##_RB_FIND(struct name *, struct type *); \
+attr struct type *name##_RB_NFIND(struct name *, struct type *); \
+attr struct type *name##_RB_NEXT(struct type *); \
+attr struct type *name##_RB_PREV(struct type *); \
+attr struct type *name##_RB_MINMAX(struct name *, int); \
+ \
+
+/* Main rb operation.
+ * Moves node close to the key of elm to top
+ */
+#define RB_GENERATE(name, type, field, cmp) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp,)
+#define RB_GENERATE_STATIC(name, type, field, cmp) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
+#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
+attr void \
+name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
+{ \
+ struct type *parent, *gparent, *tmp; \
+ while ((parent = RB_PARENT(elm, field)) != NULL && \
+ RB_COLOR(parent, field) == RB_RED) { \
+ gparent = RB_PARENT(parent, field); \
+ if (parent == RB_LEFT(gparent, field)) { \
+ tmp = RB_RIGHT(gparent, field); \
+ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
+ RB_COLOR(tmp, field) = RB_BLACK; \
+ RB_SET_BLACKRED(parent, gparent, field);\
+ elm = gparent; \
+ continue; \
+ } \
+ if (RB_RIGHT(parent, field) == elm) { \
+ RB_ROTATE_LEFT(head, parent, tmp, field);\
+ tmp = parent; \
+ parent = elm; \
+ elm = tmp; \
+ } \
+ RB_SET_BLACKRED(parent, gparent, field); \
+ RB_ROTATE_RIGHT(head, gparent, tmp, field); \
+ } else { \
+ tmp = RB_LEFT(gparent, field); \
+ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
+ RB_COLOR(tmp, field) = RB_BLACK; \
+ RB_SET_BLACKRED(parent, gparent, field);\
+ elm = gparent; \
+ continue; \
+ } \
+ if (RB_LEFT(parent, field) == elm) { \
+ RB_ROTATE_RIGHT(head, parent, tmp, field);\
+ tmp = parent; \
+ parent = elm; \
+ elm = tmp; \
+ } \
+ RB_SET_BLACKRED(parent, gparent, field); \
+ RB_ROTATE_LEFT(head, gparent, tmp, field); \
+ } \
+ } \
+ RB_COLOR(head->rbh_root, field) = RB_BLACK; \
+} \
+ \
+attr void \
+name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
+{ \
+ struct type *tmp; \
+ while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
+ elm != RB_ROOT(head)) { \
+ if (RB_LEFT(parent, field) == elm) { \
+ tmp = RB_RIGHT(parent, field); \
+ if (RB_COLOR(tmp, field) == RB_RED) { \
+ RB_SET_BLACKRED(tmp, parent, field); \
+ RB_ROTATE_LEFT(head, parent, tmp, field);\
+ tmp = RB_RIGHT(parent, field); \
+ } \
+ if ((RB_LEFT(tmp, field) == NULL || \
+ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
+ (RB_RIGHT(tmp, field) == NULL || \
+ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
+ RB_COLOR(tmp, field) = RB_RED; \
+ elm = parent; \
+ parent = RB_PARENT(elm, field); \
+ } else { \
+ if (RB_RIGHT(tmp, field) == NULL || \
+ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
+ struct type *oleft; \
+ if ((oleft = RB_LEFT(tmp, field)) \
+ != NULL) \
+ RB_COLOR(oleft, field) = RB_BLACK;\
+ RB_COLOR(tmp, field) = RB_RED; \
+ RB_ROTATE_RIGHT(head, tmp, oleft, field);\
+ tmp = RB_RIGHT(parent, field); \
+ } \
+ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
+ RB_COLOR(parent, field) = RB_BLACK; \
+ if (RB_RIGHT(tmp, field)) \
+ RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
+ RB_ROTATE_LEFT(head, parent, tmp, field);\
+ elm = RB_ROOT(head); \
+ break; \
+ } \
+ } else { \
+ tmp = RB_LEFT(parent, field); \
+ if (RB_COLOR(tmp, field) == RB_RED) { \
+ RB_SET_BLACKRED(tmp, parent, field); \
+ RB_ROTATE_RIGHT(head, parent, tmp, field);\
+ tmp = RB_LEFT(parent, field); \
+ } \
+ if ((RB_LEFT(tmp, field) == NULL || \
+ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
+ (RB_RIGHT(tmp, field) == NULL || \
+ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
+ RB_COLOR(tmp, field) = RB_RED; \
+ elm = parent; \
+ parent = RB_PARENT(elm, field); \
+ } else { \
+ if (RB_LEFT(tmp, field) == NULL || \
+ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
+ struct type *oright; \
+ if ((oright = RB_RIGHT(tmp, field)) \
+ != NULL) \
+ RB_COLOR(oright, field) = RB_BLACK;\
+ RB_COLOR(tmp, field) = RB_RED; \
+ RB_ROTATE_LEFT(head, tmp, oright, field);\
+ tmp = RB_LEFT(parent, field); \
+ } \
+ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
+ RB_COLOR(parent, field) = RB_BLACK; \
+ if (RB_LEFT(tmp, field)) \
+ RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
+ RB_ROTATE_RIGHT(head, parent, tmp, field);\
+ elm = RB_ROOT(head); \
+ break; \
+ } \
+ } \
+ } \
+ if (elm) \
+ RB_COLOR(elm, field) = RB_BLACK; \
+} \
+ \
+attr struct type * \
+name##_RB_REMOVE(struct name *head, struct type *elm) \
+{ \
+ struct type *child, *parent, *old = elm; \
+ int color; \
+ if (RB_LEFT(elm, field) == NULL) \
+ child = RB_RIGHT(elm, field); \
+ else if (RB_RIGHT(elm, field) == NULL) \
+ child = RB_LEFT(elm, field); \
+ else { \
+ struct type *left; \
+ elm = RB_RIGHT(elm, field); \
+ while ((left = RB_LEFT(elm, field)) != NULL) \
+ elm = left; \
+ child = RB_RIGHT(elm, field); \
+ parent = RB_PARENT(elm, field); \
+ color = RB_COLOR(elm, field); \
+ if (child) \
+ RB_PARENT(child, field) = parent; \
+ if (parent) { \
+ if (RB_LEFT(parent, field) == elm) \
+ RB_LEFT(parent, field) = child; \
+ else \
+ RB_RIGHT(parent, field) = child; \
+ RB_AUGMENT(parent); \
+ } else \
+ RB_ROOT(head) = child; \
+ if (RB_PARENT(elm, field) == old) \
+ parent = elm; \
+ (elm)->field = (old)->field; \
+ if (RB_PARENT(old, field)) { \
+ if (RB_LEFT(RB_PARENT(old, field), field) == old)\
+ RB_LEFT(RB_PARENT(old, field), field) = elm;\
+ else \
+ RB_RIGHT(RB_PARENT(old, field), field) = elm;\
+ RB_AUGMENT(RB_PARENT(old, field)); \
+ } else \
+ RB_ROOT(head) = elm; \
+ RB_PARENT(RB_LEFT(old, field), field) = elm; \
+ if (RB_RIGHT(old, field)) \
+ RB_PARENT(RB_RIGHT(old, field), field) = elm; \
+ if (parent) { \
+ left = parent; \
+ do { \
+ RB_AUGMENT(left); \
+ } while ((left = RB_PARENT(left, field)) != NULL); \
+ } \
+ goto color; \
+ } \
+ parent = RB_PARENT(elm, field); \
+ color = RB_COLOR(elm, field); \
+ if (child) \
+ RB_PARENT(child, field) = parent; \
+ if (parent) { \
+ if (RB_LEFT(parent, field) == elm) \
+ RB_LEFT(parent, field) = child; \
+ else \
+ RB_RIGHT(parent, field) = child; \
+ RB_AUGMENT(parent); \
+ } else \
+ RB_ROOT(head) = child; \
+color: \
+ if (color == RB_BLACK) \
+ name##_RB_REMOVE_COLOR(head, parent, child); \
+ return (old); \
+} \
+ \
+/* Inserts a node into the RB tree */ \
+attr struct type * \
+name##_RB_INSERT(struct name *head, struct type *elm) \
+{ \
+ struct type *tmp; \
+ struct type *parent = NULL; \
+ int comp = 0; \
+ tmp = RB_ROOT(head); \
+ while (tmp) { \
+ parent = tmp; \
+ comp = (cmp)(elm, parent); \
+ if (comp < 0) \
+ tmp = RB_LEFT(tmp, field); \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ RB_SET(elm, parent, field); \
+ if (parent != NULL) { \
+ if (comp < 0) \
+ RB_LEFT(parent, field) = elm; \
+ else \
+ RB_RIGHT(parent, field) = elm; \
+ RB_AUGMENT(parent); \
+ } else \
+ RB_ROOT(head) = elm; \
+ name##_RB_INSERT_COLOR(head, elm); \
+ return (NULL); \
+} \
+ \
+/* Finds the node with the same key as elm */ \
+attr struct type * \
+name##_RB_FIND(struct name *head, struct type *elm) \
+{ \
+ struct type *tmp = RB_ROOT(head); \
+ int comp; \
+ while (tmp) { \
+ comp = cmp(elm, tmp); \
+ if (comp < 0) \
+ tmp = RB_LEFT(tmp, field); \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ return (NULL); \
+} \
+ \
+/* Finds the first node greater than or equal to the search key */ \
+attr struct type * \
+name##_RB_NFIND(struct name *head, struct type *elm) \
+{ \
+ struct type *tmp = RB_ROOT(head); \
+ struct type *res = NULL; \
+ int comp; \
+ while (tmp) { \
+ comp = cmp(elm, tmp); \
+ if (comp < 0) { \
+ res = tmp; \
+ tmp = RB_LEFT(tmp, field); \
+ } \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ return (res); \
+} \
+ \
+/* ARGSUSED */ \
+attr struct type * \
+name##_RB_NEXT(struct type *elm) \
+{ \
+ if (RB_RIGHT(elm, field)) { \
+ elm = RB_RIGHT(elm, field); \
+ while (RB_LEFT(elm, field)) \
+ elm = RB_LEFT(elm, field); \
+ } else { \
+ if (RB_PARENT(elm, field) && \
+ (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
+ elm = RB_PARENT(elm, field); \
+ else { \
+ while (RB_PARENT(elm, field) && \
+ (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
+ elm = RB_PARENT(elm, field); \
+ elm = RB_PARENT(elm, field); \
+ } \
+ } \
+ return (elm); \
+} \
+ \
+/* ARGSUSED */ \
+attr struct type * \
+name##_RB_PREV(struct type *elm) \
+{ \
+ if (RB_LEFT(elm, field)) { \
+ elm = RB_LEFT(elm, field); \
+ while (RB_RIGHT(elm, field)) \
+ elm = RB_RIGHT(elm, field); \
+ } else { \
+ if (RB_PARENT(elm, field) && \
+ (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
+ elm = RB_PARENT(elm, field); \
+ else { \
+ while (RB_PARENT(elm, field) && \
+ (elm == RB_LEFT(RB_PARENT(elm, field), field)))\
+ elm = RB_PARENT(elm, field); \
+ elm = RB_PARENT(elm, field); \
+ } \
+ } \
+ return (elm); \
+} \
+ \
+attr struct type * \
+name##_RB_MINMAX(struct name *head, int val) \
+{ \
+ struct type *tmp = RB_ROOT(head); \
+ struct type *parent = NULL; \
+ while (tmp) { \
+ parent = tmp; \
+ if (val < 0) \
+ tmp = RB_LEFT(tmp, field); \
+ else \
+ tmp = RB_RIGHT(tmp, field); \
+ } \
+ return (parent); \
+}
+
+#define RB_NEGINF -1
+#define RB_INF 1
+
+#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
+#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
+#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
+#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
+#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
+#define RB_PREV(name, x, y) name##_RB_PREV(y)
+#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
+#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
+
+#define RB_FOREACH(x, name, head) \
+ for ((x) = RB_MIN(name, head); \
+ (x) != NULL; \
+ (x) = name##_RB_NEXT(x))
+
+#define RB_FOREACH_FROM(x, name, y) \
+ for ((x) = (y); \
+ ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
+ (x) = (y))
+
+#define RB_FOREACH_SAFE(x, name, head, y) \
+ for ((x) = RB_MIN(name, head); \
+ ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
+ (x) = (y))
+
+#define RB_FOREACH_REVERSE(x, name, head) \
+ for ((x) = RB_MAX(name, head); \
+ (x) != NULL; \
+ (x) = name##_RB_PREV(x))
+
+#define RB_FOREACH_REVERSE_FROM(x, name, y) \
+ for ((x) = (y); \
+ ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
+ (x) = (y))
+
+#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
+ for ((x) = RB_MAX(name, head); \
+ ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
+ (x) = (y))
+
+#endif /* _SYS_TREE_H_ */
diff --git a/lib/fun.sh b/lib/fun.sh
@@ -162,15 +162,8 @@ exit_cleanup()
extract_pkg()
{
- local prog parent_dir dir tarball realdir
-
- parent_dir=$1
- shift
- dir=$1
- shift
- tarball=$1
- shift
- realdir=$1
+ local prog parent_dir=$1 dir=$2 tarball=$3 realdir=$4 touch=$5
+ local mopt
cd_or_fail ${parent_dir}
if [ -n "${realdir}" ] && [ -d "${realdir}" ]; then
@@ -188,7 +181,11 @@ extract_pkg()
*) msg err "Unsupported archive format"
exit 1;;
esac
- if ! ${prog} "${G_PKG}/${tarball}" | tar -xmf -; then
+ mopt=''
+ if [ "${touch}" = "touch" ]; then
+ mopt=-m
+ fi
+ if ! ${prog} "${G_PKG}/${tarball}" | tar -x ${mopt} -f -; then
msg err "Extracting %s failed" "${tarball}"
exit 1
fi
diff --git a/lib/gensums b/lib/gensums
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+. ./lib/env.sh
+
+pkgdb=./lib/pkgs.tsv
+
+sed 1q "${pkgdb}" >newfile
+lineno=0
+while read -r record
+do
+ [ ${lineno} -eq 0 ] || \
+ (
+ IFS=$(printf '\t')
+ url=$(printf "${record}" | cut -d "$(printf '\t')" -f1)
+ dirtb=$(printf "${record}" | cut -sd "$(printf '\t')" -f2)
+ md5=$(printf "${record}" | cut -sd "$(printf '\t')" -f3)
+
+ tarball=${url##*/}
+ if [ -n "${dirtb}" ]; then
+ tarball=${dirtb}
+ fi
+
+ case ${url} in
+ https:*) md5=$(md5sum ${G_PKG}/${tarball} | \
+ cut -d ' ' -f1);;
+ *) md5='';;
+ esac
+ if [ -n "${md5}" ]; then
+ printf "%s\t%s\t%s\n" "${url}" "${dirtb}" "${md5}" >>newfile
+ else
+ printf "%s\t%s\n" "${url}" "${dirtb}" >>newfile
+ fi
+ )
+ lineno=$((lineno+1))
+done <${pkgdb}
+
+mv newfile "${pkgdb}"
diff --git a/lib/pkgs.tsv b/lib/pkgs.tsv
@@ -1,70 +1,75 @@
-URL Directory
+URL Directory/Tarball MD5 Sum
git+https://github.com/mirbsd/mksh mksh-20220709
git+https://github.com/onetrueawk/awk awk-20220709
git://git.suckless.org/9base 9base-20220706
git://git.suckless.org/sbase sbase-20220709
git://git.suckless.org/ubase ubase-20220709
git://repo.or.cz/tinycc.git tinycc-20220708
-https://astron.com/pub/file/file-5.41.tar.gz
-https://cpan.metacpan.org/authors/id/T/TO/TODDR/XML-Parser-2.46.tar.gz
-https://dev.alpinelinux.org/archive/posixtz/posixtz-0.5.tar.xz
-https://dev.gentoo.org/~xen0n/distfiles/pax-utils-1.3.4.tar.xz
-https://distfiles.dereferenced.org/pkgconf/pkgconf-1.8.0.tar.xz
-https://download.savannah.gnu.org/releases/acl/acl-2.3.1.tar.xz
-https://download.savannah.gnu.org/releases/attr/attr-2.5.1.tar.gz
-https://ftp.barfooze.de/pub/sabotage/tarballs/gettext-tiny-0.3.2.tar.xz
-https://ftp.barfooze.de/pub/sabotage/tarballs/netbsd-curses-0.3.2.tar.xz
-https://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.xz
-https://ftp.gnu.org/gnu/automake/automake-1.16.4.tar.xz
-https://ftp.gnu.org/gnu/bash/bash-5.1.tar.gz
-https://ftp.gnu.org/gnu/binutils/binutils-2.38.tar.xz
-https://ftp.gnu.org/gnu/coreutils/coreutils-9.1.tar.xz
-https://ftp.gnu.org/gnu/diffutils/diffutils-3.8.tar.xz
-https://ftp.gnu.org/gnu/findutils/findutils-4.9.0.tar.xz
-https://ftp.gnu.org/gnu/gdbm/gdbm-1.20.tar.gz
-https://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.xz libgmp-6.2.1.tar.xz
-https://ftp.gnu.org/gnu/gperf/gperf-3.1.tar.gz
-https://ftp.gnu.org/gnu/grep/grep-3.7.tar.xz
-https://ftp.gnu.org/gnu/gzip/gzip-1.12.tar.xz
-https://ftp.gnu.org/gnu/help2man/help2man-1.49.2.tar.xz
-https://ftp.gnu.org/gnu/inetutils/inetutils-2.1.tar.xz
-https://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.xz
-https://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz
-https://ftp.gnu.org/gnu/make/make-4.3.tar.gz
-https://ftp.gnu.org/gnu/mpc/mpc-1.2.1.tar.gz libmpc-1.2.1.tar.gz
-https://ftp.gnu.org/gnu/mpfr/mpfr-4.1.0.tar.xz libmpfr-4.1.0.tar.xz
-https://ftp.gnu.org/gnu/patch/patch-2.7.6.tar.xz
-https://ftp.gnu.org/gnu/readline/readline-8.1.tar.gz
-https://ftp.gnu.org/gnu/sed/sed-4.8.tar.xz
-https://ftp.gnu.org/gnu/tar/tar-1.34.tar.xz
-https://ftp.gnu.org/gnu/texinfo/texinfo-6.8.tar.xz
-https://gcc.gnu.org/pub/gcc/snapshots/11-20220101/gcc-11-20220101.tar.xz
-https://git.sr.ht/~strahinja/sled/archive/v0.10.8.tar.gz sled-0.10.8.tar.gz
-https://github.com/Mic92/iana-etc/releases/download/20210611/iana-etc-20210611.tar.gz
-https://github.com/arsv/perl-cross/releases/download/1.4/perl-cross-1.4.tar.gz
-https://github.com/ericonr/argp-standalone/archive/refs/tags/1.4.1.tar.gz argp-standalone-1.4.1.tar.gz
-https://github.com/facebook/zstd/releases/download/v1.5.0/zstd-1.5.0.tar.gz
-https://github.com/pullmoll/musl-fts/archive/v1.2.7.tar.gz musl-fts-1.2.7.tar.gz
-https://github.com/pullmoll/musl-obstack/archive/v1.1.tar.gz musl-obstack-1.1.tar.gz
-https://github.com/shadow-maint/shadow/releases/download/v4.11.1/shadow-4.11.1.tar.xz
-https://github.com/zlib-ng/zlib-ng/archive/refs/tags/2.0.6.tar.gz zlib-ng-2.0.6.tar.gz
-https://invisible-island.net/archives/byacc/byacc-20220128.tgz
-https://invisible-island.net/archives/reflex/reflex-20210808.tgz
-https://launchpad.net/intltool/trunk/0.51.0/+download/intltool-0.51.0.tar.gz
-https://libisl.sourceforge.io/isl-0.24.tar.xz libisl-0.24.tar.xz
-https://mandoc.bsd.lv/snapshots/mandoc-1.14.6.tar.gz
-https://mandoc.bsd.lv/snapshots/mdocml-1.14.1.tar.gz
-https://mirrors.edge.kernel.org/pub/linux/docs/man-pages/man-pages-5.13.tar.xz
-https://musl.libc.org/releases/musl-1.2.3.tar.gz
-https://prdownloads.sourceforge.net/expat/expat-2.4.8.tar.xz
-https://sourceforge.net/projects/psmisc/files/psmisc/psmisc-23.4.tar.xz
-https://sourceforge.net/projects/tcl/files/Tcl/8.6.12/tcl8.6.12-src.tar.gz
-https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz
-https://tukaani.org/xz/xz-5.2.5.tar.xz
-https://www.cpan.org/src/5.0/perl-5.32.1.tar.xz
-https://www.greenwoodsoftware.com/less/less-590.tar.gz
-https://www.iana.org/time-zones/repository/releases/tzcode2022a.tar.gz
-https://www.iana.org/time-zones/repository/releases/tzdata2022a.tar.gz
-https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.17.13.tar.xz
-https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.17.13.tar.xz
-https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/libcap-2.62.tar.xz
+https://astron.com/pub/file/file-5.41.tar.gz 18233bb0a0089dfdc7dfbc93b96f231b
+https://cpan.metacpan.org/authors/id/T/TO/TODDR/XML-Parser-2.46.tar.gz 80bb18a8e6240fcf7ec2f7b57601c170
+https://dev.alpinelinux.org/archive/posixtz/posixtz-0.5.tar.xz 80f8ae1df19dd28e1c8b192c6ea7b836
+https://dev.gentoo.org/~xen0n/distfiles/pax-utils-1.3.4.tar.xz b9cdbc70fdd4e377dcf17eeff28c5ade
+https://distfiles.dereferenced.org/pkgconf/pkgconf-1.8.0.tar.xz 823212dc241793df8ff1d097769a3473
+https://download.savannah.gnu.org/releases/acl/acl-2.3.1.tar.xz 95ce715fe09acca7c12d3306d0f076b2
+https://download.savannah.gnu.org/releases/attr/attr-2.5.1.tar.gz ac1c5a7a084f0f83b8cace34211f64d8
+https://ftp.barfooze.de/pub/sabotage/tarballs/gettext-tiny-0.3.2.tar.xz 9ddf4d35636fa3beacd3627cc02723ff
+https://ftp.barfooze.de/pub/sabotage/tarballs/netbsd-curses-0.3.2.tar.xz bff9cfda41ae25ea84bd8da6c674dcb7
+https://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.xz 12cfa1687ffa2606337efe1a64416106
+https://ftp.gnu.org/gnu/automake/automake-1.16.4.tar.xz 86e8e682bd74e6390a016c4d9c11267c
+https://ftp.gnu.org/gnu/bash/bash-5.1.tar.gz bb91a17fd6c9032c26d0b2b78b50aff5
+https://ftp.gnu.org/gnu/binutils/binutils-2.38.tar.xz 6e39cad1bb414add02b5b1169c18fdc5
+https://ftp.gnu.org/gnu/coreutils/coreutils-9.1.tar.xz 8b1ca4e018a7dce9bb937faec6618671
+https://ftp.gnu.org/gnu/diffutils/diffutils-3.8.tar.xz 6a6b0fdc72acfe3f2829aab477876fbc
+https://ftp.gnu.org/gnu/findutils/findutils-4.9.0.tar.xz 4a4a547e888a944b2f3af31d789a1137
+https://ftp.gnu.org/gnu/gdbm/gdbm-1.20.tar.gz 006c19b8b60828fd6916a16f3496bd3c
+https://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.xz libgmp-6.2.1.tar.xz 0b82665c4a92fd2ade7440c13fcaa42b
+https://ftp.gnu.org/gnu/gperf/gperf-3.1.tar.gz 9e251c0a618ad0824b51117d5d9db87e
+https://ftp.gnu.org/gnu/grep/grep-3.7.tar.xz 7c9cca97fa18670a21e72638c3e1dabf
+https://ftp.gnu.org/gnu/gzip/gzip-1.12.tar.xz 9608e4ac5f061b2a6479dc44e917a5db
+https://ftp.gnu.org/gnu/help2man/help2man-1.49.2.tar.xz 0372898fbf054140d62385a79c5855f4
+https://ftp.gnu.org/gnu/inetutils/inetutils-2.1.tar.xz 4e7676d1980e57c7df665e5c5c3c1047
+https://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.xz 1bfb9b923f2c1339b4d2ce1807064aa5
+https://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz 0d90823e1426f1da2fd872df0311298d
+https://ftp.gnu.org/gnu/make/make-4.3.tar.gz fc7a67ea86ace13195b0bce683fd4469
+https://ftp.gnu.org/gnu/mpc/mpc-1.2.1.tar.gz libmpc-1.2.1.tar.gz 9f16c976c25bb0f76b50be749cd7a3a8
+https://ftp.gnu.org/gnu/mpfr/mpfr-4.1.0.tar.xz libmpfr-4.1.0.tar.xz bdd3d5efba9c17da8d83a35ec552baef
+https://ftp.gnu.org/gnu/patch/patch-2.7.6.tar.xz 78ad9937e4caadcba1526ef1853730d5
+https://ftp.gnu.org/gnu/readline/readline-8.1.tar.gz e9557dd5b1409f5d7b37ef717c64518e
+https://ftp.gnu.org/gnu/sed/sed-4.8.tar.xz 6d906edfdb3202304059233f51f9a71d
+https://ftp.gnu.org/gnu/tar/tar-1.34.tar.xz 9a08d29a9ac4727130b5708347c0f5cf
+https://ftp.gnu.org/gnu/texinfo/texinfo-6.8.tar.xz a91b404e30561a5df803e6eb3a53be71
+https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.4.2.tar.gz 18aa728e7947a30af3bb04243e4482aa
+https://gcc.gnu.org/pub/gcc/snapshots/11-20220101/gcc-11-20220101.tar.xz 2d984314c9ad01d941358bcf3ec6b29e
+https://git.sr.ht/~strahinja/sled/archive/v0.10.8.tar.gz sled-0.10.8.tar.gz 2a12c7eb0e6cb4f671299acb76753986
+https://github.com/Mic92/iana-etc/releases/download/20210611/iana-etc-20210611.tar.gz f2854be57fe281e3ffc7364984467d2f
+https://github.com/arsv/perl-cross/releases/download/1.4/perl-cross-1.4.tar.gz 73c246c20766d027c3dc9f606418c22c
+https://github.com/ericonr/argp-standalone/archive/refs/tags/1.4.1.tar.gz argp-standalone-1.4.1.tar.gz 7f391d52161e7fe8e8d3df4f850bc7ee
+https://github.com/facebook/zstd/releases/download/v1.5.0/zstd-1.5.0.tar.gz a6eb7fb1f2c21fa80030a47993853e92
+https://github.com/libffi/libffi/releases/download/v3.4.2/libffi-3.4.2.tar.gz 294b921e6cf9ab0fbaea4b639f8fdbe8
+https://github.com/pullmoll/musl-fts/archive/v1.2.7.tar.gz musl-fts-1.2.7.tar.gz bce0b5de0cf2519a74fbfacead60369d
+https://github.com/pullmoll/musl-obstack/archive/v1.1.tar.gz musl-obstack-1.1.tar.gz 185975cc117dba8e6158cce847ba44d5
+https://github.com/shadow-maint/shadow/releases/download/v4.11.1/shadow-4.11.1.tar.xz 5a95ec069aa91508167d02fecafaa912
+https://github.com/zlib-ng/zlib-ng/archive/refs/tags/2.0.6.tar.gz zlib-ng-2.0.6.tar.gz 4ba0da231291632799948c5568906ce4
+https://invisible-island.net/archives/byacc/byacc-20220128.tgz c861b313fb59857a5ca3475ce9d62c4e
+https://invisible-island.net/archives/reflex/reflex-20210808.tgz 31ed4340e8b636cb2c1de2ad378a14e9
+https://launchpad.net/intltool/trunk/0.51.0/+download/intltool-0.51.0.tar.gz 12e517cac2b57a0121cda351570f1e63
+https://libisl.sourceforge.io/isl-0.24.tar.xz libisl-0.24.tar.xz fae030f604a9537adc2502990a8ab4d1
+https://mandoc.bsd.lv/snapshots/mandoc-1.14.6.tar.gz f0adf24e8fdef5f3e332191f653e422a
+https://mandoc.bsd.lv/snapshots/mdocml-1.14.1.tar.gz 07db67f437ee894e7e4b18b305d53ca1
+https://mirrors.edge.kernel.org/pub/linux/docs/man-pages/man-pages-5.13.tar.xz 3ac24e8c6fae26b801cb87ceb63c0a30
+https://musl.libc.org/releases/musl-1.2.3.tar.gz a507ae4f7f20bcfe566d8eb65c1af73e
+https://prdownloads.sourceforge.net/expat/expat-2.4.8.tar.xz 0584a7318a4c007f7ec94778799d72fe
+https://sourceforge.net/projects/psmisc/files/psmisc/psmisc-23.4.tar.xz 8114cd4489b95308efe2509c3a406bbf
+https://sourceforge.net/projects/tcl/files/Tcl/8.6.12/tcl8.6.12-src.tar.gz 87ea890821d2221f2ab5157bc5eb885f
+https://sourceware.org/ftp/elfutils/0.186/elfutils-0.186.tar.bz2 libelf-0.186.tar.bz2 2c095e31e35d6be7b3718477b6d52702
+https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz 67e051268d0c475ea773822f7500d0e5
+https://tukaani.org/xz/xz-5.2.5.tar.xz aa1621ec7013a19abab52a8aff04fe5b
+https://www.cpan.org/src/5.0/perl-5.32.1.tar.xz 7f104064b906ad8c7329ca5e409a32d7
+https://www.greenwoodsoftware.com/less/less-590.tar.gz f029087448357812fba450091a1172ab
+https://www.iana.org/time-zones/repository/releases/tzcode2022a.tar.gz fdc790effd7b01d29837fb27b3e81672
+https://www.iana.org/time-zones/repository/releases/tzdata2022a.tar.gz 081662184f3b902f8e5d96816568432e
+https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.17.13.tar.xz 1f0478b27e1ec649e33b6c3dc0f6a583
+https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.17.13.tar.xz 1f0478b27e1ec649e33b6c3dc0f6a583
+https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/libcap-2.62.tar.xz 342c7560ed2103899f6914d1de75a89f
+https://www.kernel.org/pub/linux/utils/kernel/kmod/kmod-29.tar.xz e81e63acd80697d001c8d85c1acb38a0
+https://www.python.org/ftp/python/3.9.9/Python-3.9.9.tar.xz 11d12076311563252a995201248d17e5
diff --git a/lib/showpkgs b/lib/showpkgs
@@ -0,0 +1,12 @@
+#!/bin/sh
+cols=''
+if [ -n "$*" ]; then
+ cols="-c $*"
+fi
+total=$(wc -l lib/pkgs.tsv | cut -d ' ' -f1)
+total=$((total-1))
+git=$(grep '^git' lib/pkgs.tsv | wc -l | cut -d ' ' -f1)
+tarballs=$((total-git))
+{ printf "%d total packages (%d git repos, %d tarballs)\n" \
+ "${total}" "${git}" "${tarballs}"
+table -d "$(printf '\t')" ${cols} lib/pkgs.tsv -f 35:10:12; } | less -S
diff --git a/pat-11.2.1/libffi-alpine/pax-dlmmap.patch b/pat-11.2.1/libffi-alpine/pax-dlmmap.patch
@@ -0,0 +1,120 @@
+From 48d2e46528fb6e621d95a7fa194069fd136b712d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Stefan=20B=C3=BChler?= <buehler@cert.uni-stuttgart.de>
+Date: Wed, 7 Sep 2016 15:49:48 +0200
+Subject: [PATCH 1/2] dlmmap_locked always needs locking as it always modifies
+ execsize
+
+---
+ src/closures.c | 13 ++++---------
+ 1 file changed, 4 insertions(+), 9 deletions(-)
+
+diff --git a/src/closures.c b/src/closures.c
+index 2e0ffb45..04d6e27f 100644
+--- a/src/closures.c
++++ b/src/closures.c
+@@ -769,16 +769,11 @@ dlmmap (void *start, size_t length, int prot,
+ MREMAP_DUP and prot at this point. */
+ }
+
+- if (execsize == 0 || execfd == -1)
+- {
+- pthread_mutex_lock (&open_temp_exec_file_mutex);
+- ptr = dlmmap_locked (start, length, prot, flags, offset);
+- pthread_mutex_unlock (&open_temp_exec_file_mutex);
++ pthread_mutex_lock (&open_temp_exec_file_mutex);
++ ptr = dlmmap_locked (start, length, prot, flags, offset);
++ pthread_mutex_unlock (&open_temp_exec_file_mutex);
+
+- return ptr;
+- }
+-
+- return dlmmap_locked (start, length, prot, flags, offset);
++ return ptr;
+ }
+
+ /* Release memory at the given address, as well as the corresponding
+
+From 7aad5f895e2dfdb79d2ef67e1b231d21063e6511 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Stefan=20B=C3=BChler?= <buehler@cert.uni-stuttgart.de>
+Date: Wed, 7 Sep 2016 15:50:54 +0200
+Subject: [PATCH 2/2] ignore PaX EMUTRAMP flag; instead check for MPROTECT
+
+- code using ffi_closure_alloc doesn't necessarily generate gcc compatible trampolines; only those are allowed by PaX
+- if MPROTECT is enabled use the same workaround as is used for SELinux (double mmap())
+---
+ src/closures.c | 29 +++++++++++++----------------
+ 1 file changed, 13 insertions(+), 16 deletions(-)
+
+diff --git a/src/closures.c b/src/closures.c
+index 04d6e27f..babecc1a 100644
+--- a/src/closures.c
++++ b/src/closures.c
+@@ -401,14 +401,15 @@ selinux_enabled_check (void)
+
+ #endif /* !FFI_MMAP_EXEC_SELINUX */
+
+-/* On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. */
++/* On PaX enable kernels that have MPROTECT enabled we can't use PROT_EXEC. */
+ #ifdef FFI_MMAP_EXEC_EMUTRAMP_PAX
+ #include <stdlib.h>
+
+-static int emutramp_enabled = -1;
++/* -1: not read yet; 0: no PaX or MPROTECT disabled; 1: MPROTECT enabled. */
++static int mprotect_enabled = -1;
+
+ static int
+-emutramp_enabled_check (void)
++mprotect_enabled_check (void)
+ {
+ char *buf = NULL;
+ size_t len = 0;
+@@ -422,9 +423,7 @@ emutramp_enabled_check (void)
+ while (getline (&buf, &len, f) != -1)
+ if (!strncmp (buf, "PaX:", 4))
+ {
+- char emutramp;
+- if (sscanf (buf, "%*s %*c%c", &emutramp) == 1)
+- ret = (emutramp == 'E');
++ ret = (NULL != strchr (buf + 4, 'M'));
+ break;
+ }
+ free (buf);
+@@ -432,8 +431,9 @@ emutramp_enabled_check (void)
+ return ret;
+ }
+
+-#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
+- : (emutramp_enabled = emutramp_enabled_check ()))
++#define is_mprotect_enabled() (mprotect_enabled >= 0 ? mprotect_enabled \
++ : (mprotect_enabled = mprotect_enabled_check ()))
++
+ #endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
+
+ #elif defined (__CYGWIN__) || defined(__INTERIX)
+@@ -446,7 +446,7 @@ emutramp_enabled_check (void)
+ #endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
+
+ #ifndef FFI_MMAP_EXEC_EMUTRAMP_PAX
+-#define is_emutramp_enabled() 0
++#define is_mprotect_enabled() 0
+ #endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
+
+ /* Declare all functions defined in dlmalloc.c as static. */
+@@ -750,13 +750,10 @@ dlmmap (void *start, size_t length, int prot,
+ && flags == (MAP_PRIVATE | MAP_ANONYMOUS)
+ && fd == -1 && offset == 0);
+
+- if (execfd == -1 && is_emutramp_enabled ())
+- {
+- ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset);
+- return ptr;
+- }
+-
+- if (execfd == -1 && !is_selinux_enabled ())
++ /* -1 != execfd hints that we already decided to use dlmmap_locked
++ last time. If PaX MPROTECT or SELinux is active fallback to
++ dlmmap_locked. */
++ if (execfd == -1 && !is_mprotect_enabled () && !is_selinux_enabled ())
+ {
+ ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset);
+
diff --git a/pat-11.2.1/python3-void/musl-find_library.patch b/pat-11.2.1/python3-void/musl-find_library.patch
@@ -0,0 +1,44 @@
+--- Lib/ctypes/util.py.orig
++++ Lib/ctypes/util.py
+@@ -204,6 +204,41 @@
+ def find_library(name, is64 = False):
+ return _get_soname(_findLib_crle(name, is64) or _findLib_gcc(name))
+
++ elif True:
++
++ # Patched for Alpine Linux / musl - search manually system paths
++ def _is_elf(filepath):
++ try:
++ with open(filepath, 'rb') as fh:
++ return fh.read(4) == b'\x7fELF'
++ except:
++ return False
++
++ def find_library(name):
++ from glob import glob
++ # absolute name?
++ if os.path.isabs(name):
++ return name
++ # special case for libm, libcrypt and libpthread and musl
++ if name in ['m', 'crypt', 'pthread']:
++ name = 'c'
++ elif name in ['libm.so', 'libcrypt.so', 'libpthread.so']:
++ name = 'libc.so'
++ # search in standard locations (musl order)
++ paths = ['/lib', '/local/lib', '/sucks/lib']
++ if 'LD_LIBRARY_PATH' in os.environ:
++ paths = os.environ['LD_LIBRARY_PATH'].split(':') + paths
++ for d in paths:
++ f = os.path.join(d, name)
++ if _is_elf(f):
++ return os.path.basename(f)
++
++ prefix = os.path.join(d, 'lib'+name)
++ for suffix in ['.so', '.so.*']:
++ for f in glob('{0}{1}'.format(prefix, suffix)):
++ if _is_elf(f):
++ return os.path.basename(f)
++
+ else:
+
+ def _findSoname_ldconfig(name):
diff --git a/pat-11.2.1/python3-void/tweak-MULTIARCH-for-powerpc-linux-musl.patch b/pat-11.2.1/python3-void/tweak-MULTIARCH-for-powerpc-linux-musl.patch
@@ -0,0 +1,13 @@
+--- configure
++++ configure
+@@ -5205,6 +5205,10 @@
+
+ MULTIARCH=$($CC --print-multiarch 2>/dev/null)
+
++if test x$MULTIARCH = xpowerpc-linux-musl
++then
++ MULTIARCH="powerpc-linux-gnu"
++fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the platform triplet based on compiler characteristics" >&5
+ $as_echo_n "checking for the platform triplet based on compiler characteristics... " >&6; }
diff --git a/pat-11.2.1/xz-alpine/xzgrep-ZDI-CAN-16587.patch b/pat-11.2.1/xz-alpine/xzgrep-ZDI-CAN-16587.patch
@@ -0,0 +1,94 @@
+From 69d1b3fc29677af8ade8dc15dba83f0589cb63d6 Mon Sep 17 00:00:00 2001
+From: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue, 29 Mar 2022 19:19:12 +0300
+Subject: [PATCH] xzgrep: Fix escaping of malicious filenames (ZDI-CAN-16587).
+
+Malicious filenames can make xzgrep to write to arbitrary files
+or (with a GNU sed extension) lead to arbitrary code execution.
+
+xzgrep from XZ Utils versions up to and including 5.2.5 are
+affected. 5.3.1alpha and 5.3.2alpha are affected as well.
+This patch works for all of them.
+
+This bug was inherited from gzip's zgrep. gzip 1.12 includes
+a fix for zgrep.
+
+The issue with the old sed script is that with multiple newlines,
+the N-command will read the second line of input, then the
+s-commands will be skipped because it's not the end of the
+file yet, then a new sed cycle starts and the pattern space
+is printed and emptied. So only the last line or two get escaped.
+
+One way to fix this would be to read all lines into the pattern
+space first. However, the included fix is even simpler: All lines
+except the last line get a backslash appended at the end. To ensure
+that shell command substitution doesn't eat a possible trailing
+newline, a colon is appended to the filename before escaping.
+The colon is later used to separate the filename from the grep
+output so it is fine to add it here instead of a few lines later.
+
+The old code also wasn't POSIX compliant as it used \n in the
+replacement section of the s-command. Using \<newline> is the
+POSIX compatible method.
+
+LC_ALL=C was added to the two critical sed commands. POSIX sed
+manual recommends it when using sed to manipulate pathnames
+because in other locales invalid multibyte sequences might
+cause issues with some sed implementations. In case of GNU sed,
+these particular sed scripts wouldn't have such problems but some
+other scripts could have, see:
+
+ info '(sed)Locale Considerations'
+
+This vulnerability was discovered by:
+cleemy desu wayo working with Trend Micro Zero Day Initiative
+
+Thanks to Jim Meyering and Paul Eggert discussing the different
+ways to fix this and for coordinating the patch release schedule
+with gzip.
+---
+ src/scripts/xzgrep.in | 20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+diff --git a/src/scripts/xzgrep.in b/src/scripts/xzgrep.in
+index b180936..e5186ba 100644
+--- a/src/scripts/xzgrep.in
++++ b/src/scripts/xzgrep.in
+@@ -180,22 +180,26 @@ for i; do
+ { test $# -eq 1 || test $no_filename -eq 1; }; then
+ eval "$grep"
+ else
++ # Append a colon so that the last character will never be a newline
++ # which would otherwise get lost in shell command substitution.
++ i="$i:"
++
++ # Escape & \ | and newlines only if such characters are present
++ # (speed optimization).
+ case $i in
+ (*'
+ '* | *'&'* | *'\'* | *'|'*)
+- i=$(printf '%s\n' "$i" |
+- sed '
+- $!N
+- $s/[&\|]/\\&/g
+- $s/\n/\\n/g
+- ');;
++ i=$(printf '%s\n' "$i" | LC_ALL=C sed 's/[&\|]/\\&/g; $!s/$/\\/');;
+ esac
+- sed_script="s|^|$i:|"
++
++ # $i already ends with a colon so don't add it here.
++ sed_script="s|^|$i|"
+
+ # Fail if grep or sed fails.
+ r=$(
+ exec 4>&1
+- (eval "$grep" 4>&-; echo $? >&4) 3>&- | sed "$sed_script" >&3 4>&-
++ (eval "$grep" 4>&-; echo $? >&4) 3>&- |
++ LC_ALL=C sed "$sed_script" >&3 4>&-
+ ) || r=2
+ exit $r
+ fi >&3 5>&-
+--
+2.35.1
+