ASR_BASE
Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/external/subpack/utils/acl/Makefile b/external/subpack/utils/acl/Makefile
new file mode 100644
index 0000000..f746910
--- /dev/null
+++ b/external/subpack/utils/acl/Makefile
@@ -0,0 +1,85 @@
+#
+# Copyright (C) 2014-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=acl
+PKG_VERSION:=2.2.53
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://git.savannah.nongnu.org/cgit/acl.git/snapshot
+PKG_HASH:=9e905397ac10d06768c63edd0579c34b8431555f2ea8e8f2cee337b31f856805
+PKG_MAINTAINER:=Maxim Storchak <m.storchak@gmail.com>
+
+PKG_LICENSE:=LGPL-2.1 GPL-2.0
+PKG_LICENSE_FILES:=doc/COPYING doc/COPYING.LGPL
+
+PKG_INSTALL:=1
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/acl/Default
+ TITLE:=Access control list (ACL) manipulation
+ URL:=https://savannah.nongnu.org/projects/acl
+ SUBMENU:=Filesystem
+endef
+
+define Package/acl/Default/description
+ Access control list support
+endef
+
+define Package/acl
+$(call Package/acl/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE+=utils
+ DEPENDS:=+libacl
+endef
+
+define Package/libacl
+$(call Package/acl/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+=library
+ DEPENDS:=+libattr
+endef
+
+define Package/libacl/description
+$(call Package/acl/Default/description)
+ This package provides libacl
+endef
+
+define Package/acl/description
+$(call Package/acl/Default/description)
+ This package provides ACL manipulation utilities
+ - chacl
+ - getfacl
+ - setfacl
+endef
+
+CONFIGURE_ARGS += --enable-static --enable-shared
+
+define Package/acl/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+endef
+
+define Package/libacl/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
+endef
+
+define Build/InstallDev
+ mkdir -p $(1)/usr/include
+ mkdir -p $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/{include,lib} $(1)/usr/
+endef
+
+$(eval $(call BuildPackage,acl))
+$(eval $(call BuildPackage,libacl))
diff --git a/external/subpack/utils/acl/patches/100-no-gettext_configure.patch b/external/subpack/utils/acl/patches/100-no-gettext_configure.patch
new file mode 100644
index 0000000..c846176
--- /dev/null
+++ b/external/subpack/utils/acl/patches/100-no-gettext_configure.patch
@@ -0,0 +1,19 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -33,9 +33,6 @@ AC_SYS_LARGEFILE
+ AM_PROG_AR
+ LT_INIT
+
+-AM_GNU_GETTEXT_VERSION([0.18.2])
+-AM_GNU_GETTEXT([external])
+-
+ AC_ARG_ENABLE([debug],
+ [AS_HELP_STRING([--enable-debug], [Enable extra debugging])])
+ AS_IF([test "x$enable_debug" = "xyes"],
+@@ -62,6 +59,5 @@ AC_CONFIG_COMMANDS([include/sys],
+ AC_CONFIG_FILES([
+ libacl.pc
+ Makefile
+- po/Makefile.in
+ ])
+ AC_OUTPUT
diff --git a/external/subpack/utils/acl/patches/101-no-gettext_autogen.patch b/external/subpack/utils/acl/patches/101-no-gettext_autogen.patch
new file mode 100644
index 0000000..e9a8c8c
--- /dev/null
+++ b/external/subpack/utils/acl/patches/101-no-gettext_autogen.patch
@@ -0,0 +1,7 @@
+--- a/autogen.sh
++++ b/autogen.sh
+@@ -1,4 +1,2 @@
+ #!/bin/sh -ex
+-po/update-potfiles
+-autopoint --force
+ exec autoreconf -f -i
diff --git a/external/subpack/utils/acl/patches/102-no-gettext_Makefile.patch b/external/subpack/utils/acl/patches/102-no-gettext_Makefile.patch
new file mode 100644
index 0000000..4d562b9
--- /dev/null
+++ b/external/subpack/utils/acl/patches/102-no-gettext_Makefile.patch
@@ -0,0 +1,11 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -3,8 +3,6 @@ ACLOCAL_AMFLAGS = -I m4
+ EXTRA_DIST = \
+ exports
+
+-SUBDIRS = po
+-
+ AM_CPPFLAGS = \
+ -I$(top_builddir)/include \
+ -I$(top_srcdir)/include \
diff --git a/external/subpack/utils/acpid/Makefile b/external/subpack/utils/acpid/Makefile
new file mode 100644
index 0000000..9328cbd
--- /dev/null
+++ b/external/subpack/utils/acpid/Makefile
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2012-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=acpid
+PKG_VERSION:=2.0.32
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@SF/acpid2
+PKG_HASH:=f2d2d30b3edc3234bd82f6f7186699a6aa3c85c8d20bc4e30e9b3c68a1ed157e
+
+PKG_MAINTAINER:=Thomas Heil <heil@terminal-consulting.de>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:tedfelix:acpid
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/acpid
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=The ACPI Daemon (acpid) With Netlink Support
+ URL:=https://sourceforge.net/projects/acpid2/
+ DEPENDS:=+kmod-input-evdev
+endef
+
+define Package/acpid/description
+ The ACPI Daemon (acpid) With Netlink Support
+endef
+
+TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto
+TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed
+
+define Package/acpid/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/acpid $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/kacpimon $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/acpi_listen $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc/acpi/events
+ $(INSTALL_CONF) ./files/default $(1)/etc/acpi/events/default
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_CONF) ./files/acpid.init $(1)/etc/init.d/acpid
+ chmod 0750 $(1)/etc/init.d/acpid
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/input/
+ $(INSTALL_CONF) ./files/acpid.hotplug $(1)/etc/hotplug.d/input/
+endef
+
+define Package/acpid/postinst
+#!/bin/sh
+[ -n "$${IPKG_INSTROOT}" ] || {
+ echo "waiting for input devices to come up"
+ /etc/init.d/acpid enable
+ sleep 5
+ /etc/init.d/acpid start
+ echo "please try the power button"
+ exit 0
+}
+endef
+
+$(eval $(call BuildPackage,acpid))
diff --git a/external/subpack/utils/acpid/files/acpid.hotplug b/external/subpack/utils/acpid/files/acpid.hotplug
new file mode 100644
index 0000000..6e08d01
--- /dev/null
+++ b/external/subpack/utils/acpid/files/acpid.hotplug
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+. /lib/functions.sh
+
+if [ "$ACTION" = add ] && [ "$DEVICENAME" = event0 ]; then
+ ( /etc/init.d/acpid/stop; sleep 3; /usr/sbin/acpid )&
+fi
diff --git a/external/subpack/utils/acpid/files/acpid.init b/external/subpack/utils/acpid/files/acpid.init
new file mode 100644
index 0000000..411eea2
--- /dev/null
+++ b/external/subpack/utils/acpid/files/acpid.init
@@ -0,0 +1,19 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2009-2010 OpenWrt.org
+
+START=99
+STOP=80
+
+USE_PROCD=1
+
+start_service() {
+ procd_open_instance
+ procd_set_param command "/usr/sbin/acpid"
+ procd_append_param command -f
+ procd_append_param command -S
+ procd_set_param pidfile "/var/run/acpid.pid"
+}
+
+reload_service() {
+ procd_send_signal "acpid"
+}
diff --git a/external/subpack/utils/acpid/files/default b/external/subpack/utils/acpid/files/default
new file mode 100644
index 0000000..cf8d9a3
--- /dev/null
+++ b/external/subpack/utils/acpid/files/default
@@ -0,0 +1,5 @@
+# This is a sample ACPID configuration
+
+event=button/power.*
+action=/sbin/poweroff
+
diff --git a/external/subpack/utils/acsccid/Makefile b/external/subpack/utils/acsccid/Makefile
new file mode 100644
index 0000000..2365bc1
--- /dev/null
+++ b/external/subpack/utils/acsccid/Makefile
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2009-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=acsccid
+PKG_VERSION:=1.1.8
+PKG_RELEASE:=1
+
+PKG_SOURCE:=v$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/acshk/acsccid/archive/
+PKG_HASH:=68d15eb20e7f52153509f1dc300cf0c68b388c59d7d124ba494fd96c61a6e7c6
+PKG_MAINTAINER:=Vincent JARDIN <vjardin@free.fr>
+PKG_LICENSE:=LGPL-2.1-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_FIXUP:=libtool
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/acsccid
+ SECTION:=libs
+ CATEGORY:=Libraries
+ DEPENDS:=$(ICONV_DEPENDS) +libusb-1.0 +libpcsclite
+ TITLE:=PCSC driver for ACS USB CCID smart card readers
+ URL:=https://github.com/acshk/acsccid
+endef
+
+define Package/acsccid/description
+ PCSC driver for ACS USB CCID (Chip/Smart Card Interface Devices)
+ smart card readers and ICCD (Integrated Circuit(s)
+ Card Devices).
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+TARGET_LDFLAGS += "-lpthread"
+
+CONFIGURE_ARGS += \
+ --enable-embedded \
+ --enable-usbdropdir=/usr/lib/pcsc/drivers
+
+define Package/acsccid/install
+ $(INSTALL_DIR) $(1)/usr/lib/pcsc
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pcsc/drivers $(1)/usr/lib/pcsc/
+endef
+
+$(eval $(call BuildPackage,acsccid))
diff --git a/external/subpack/utils/afuse/Makefile b/external/subpack/utils/afuse/Makefile
new file mode 100644
index 0000000..bae53b6
--- /dev/null
+++ b/external/subpack/utils/afuse/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2021 Michal Hrusecky <michal@hrusecky.net>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=afuse
+PKG_VERSION:=0.4.1
+PKG_RELEASE:=1
+
+PKG_MAINTAINER:=Michal Hrusecky <michal@hrusecky.net>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/pcarrier/$(PKG_NAME)/archive/refs/tags/v$(PKG_VERSION).tar.gz?
+PKG_HASH:=8c7950cdeb24cdff828cdd3807537ee12cab87b18ecef4496b7bdedb2b8bd0e9
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/afuse
+ SECTION:=net
+ CATEGORY:=Utilities
+ SUBMENU:=Filesystem
+ TITLE:=Automounting file system implemented in user-space using FUSE
+ DEPENDS:=+libfuse +fuse-utils
+ URL:=https://github.com/pcarrier/afuse
+endef
+
+define Package/afuse/description
+ Automounting file system implemented in user-space using FUSE. It
+ implements the most basic functionality that can be expected by an
+ automounter; that is it manages a directory of virtual directories. If
+ one of these virtual directories is accessed and is not already
+ automounted, afuse will attempt to mount a filesystem onto that
+ directory. If the mount succeeds the requested access proceeds as
+ normal, otherwise it will fail with an error.
+endef
+
+TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include/fuse/
+
+define Package/afuse/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/afuse $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,afuse))
diff --git a/external/subpack/utils/airos-dfs-reset/Makefile b/external/subpack/utils/airos-dfs-reset/Makefile
new file mode 100644
index 0000000..353795f
--- /dev/null
+++ b/external/subpack/utils/airos-dfs-reset/Makefile
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2021 Simon Polack <spolack+git@@mailbox.org>
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=airos-dfs-reset
+PKG_VERSION:=1
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_MAINTAINER:=Simon Polack <spolack+git@mailbox.org>
+PKG_LICENSE:=GPL-2.0-only
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/airos-dfs-reset
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Companion app for Ubiquity AirOS to help with DFS
+ PKGARCH:=all
+ EXTRA_DEPENDS:=dropbear
+endef
+
+define Package/airos-dfs-reset/description
+Companion app for Ubiquity AirOS Gear to enforce fallback to original frequency after DFS event is over.
+It works by soft-rebooting if running-frequency doesnt match the configured frequency.
+endef
+
+define Package/airos-dfs-reset/conffiles
+/etc/config/airos-dfs-reset
+endef
+
+define Build/Compile
+endef
+
+define Package/airos-dfs-reset/install
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/airos-dfs-reset.init $(1)/etc/init.d/airos-dfs-reset
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) ./files/airos-dfs-reset $(1)/usr/bin/airos-dfs-reset
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/airos-dfs-reset.config $(1)/etc/config/airos-dfs-reset
+endef
+
+$(eval $(call BuildPackage,airos-dfs-reset))
diff --git a/external/subpack/utils/airos-dfs-reset/files/airos-dfs-reset b/external/subpack/utils/airos-dfs-reset/files/airos-dfs-reset
new file mode 100644
index 0000000..1d15c91
--- /dev/null
+++ b/external/subpack/utils/airos-dfs-reset/files/airos-dfs-reset
@@ -0,0 +1,114 @@
+#!/bin/sh
+
+. /lib/functions.sh
+
+log() {
+ local msg="$1"
+ logger -t airos-dfs-reset -s "$msg"
+}
+
+rexec() {
+ local target="$1"
+ local username="$2"
+ local password="$3"
+ local cmd="$4"
+ raw=$(DROPBEAR_PASSWORD="$password" ssh -y $username@$target "$cmd")
+ ssh_result=$?
+}
+
+reset_dfs() {
+ local cmd="/usr/etc/rc.d/rc.softrestart force"
+ rexec $* "$cmd"
+}
+
+get_running_freq() {
+ local cmd="iwconfig ath0 | grep Frequency | awk -F ':' '{print \$3}' | awk '{print \$1}' | sed 's/\.//'"
+
+ rexec $* "$cmd"
+
+ # Append zeroes which are then cut to 4, we have to convert GHz into MHz
+ raw="$raw"000
+
+ running_freq=${raw:0:4}
+}
+
+get_target_freq() {
+ local cmd="grep 'radio.1.freq' /tmp/system.cfg | awk -F '=' '{ print \$2}'"
+ rexec $* "$cmd"
+ target_freq="$raw"
+}
+
+check_dfs() {
+ local target="$1"
+ local username="$2"
+ local password="$3"
+
+ get_running_freq $target $username $password
+ if [ "$ssh_result" != 0 ]; then
+ return
+ fi
+ get_target_freq $target $username $password
+ if [ "$ssh_result" != 0 ]; then
+ return
+ fi
+ log "Running freq: $running_freq - Target freq: $target_freq"
+
+ [ "$running_freq" == "$target_freq" ]
+}
+
+
+reset_allowed() {
+ local daytime_limit="$1"
+ local start="$(echo $daytime_limit | awk -F '-' '{print $1'})"
+ local end="$(echo $daytime_limit | awk -F '-' '{print $2'})"
+ local cur="$(date +%H)"
+ [ "$cur" -ge "$start" ] && [ "$cur" -le "$end" ]
+}
+
+handle_device() {
+ local device="$1"
+ config_get target "$device" target
+ config_get username "$device" username
+ config_get password "$device" password
+ config_get daytime_limit "$device" daytime_limit "0-23"
+
+ ssh_result=0
+
+ log "Checking Device $device"
+
+ check_dfs $target $username $password
+ freqmatch=$?
+
+ if [ "$ssh_result" != 0 ]; then
+ log "ssh exited non-zero - connect timeout?"
+ return
+ elif [ "$freqmatch" == 0 ]; then
+ log "Frequency is matching. No radar event fired"
+ else
+ log "Frequency doesnt match. Looks like DFS activity :("
+ if reset_allowed $daytime_limit; then
+ log "Initiating reset"
+ reset_dfs $target $username $password
+ log "Waiting $cfg_reset_sleep seconds after reset"
+ sleep $cfg_reset_sleep
+ else
+ log "Resetting is forbidden at this daytime"
+ fi
+ fi
+}
+
+main() {
+ log "started!"
+
+ config_load airos-dfs-reset
+ config_get cfg_interval general interval 600
+ config_get cfg_reset_sleep general reset_sleep 120
+
+ while :;
+ do
+ config_foreach handle_device device
+ sleep $cfg_interval
+ done
+}
+
+main
diff --git a/external/subpack/utils/airos-dfs-reset/files/airos-dfs-reset.config b/external/subpack/utils/airos-dfs-reset/files/airos-dfs-reset.config
new file mode 100644
index 0000000..c718a52
--- /dev/null
+++ b/external/subpack/utils/airos-dfs-reset/files/airos-dfs-reset.config
@@ -0,0 +1,15 @@
+config airos-dfs-reset general
+ option interval '600' # Check every x seconds
+ option reset_sleep '120' # Sleep after reset to let routing protocols reconverge
+
+config device 'sample_ap' # make sure to not use dashes in name
+ option target '192.168.1.20'
+ option username 'ubnt'
+ option password 'ubnt'
+ option daytime_limit '2-7' # .. from 2:xx to 7:xx reset is allowed
+
+#config device 'sample_ap1'
+# option target '10.31.81.21'
+# option username 'ubnt'
+# option password '...'
+# option daytime_limit '0-23'
diff --git a/external/subpack/utils/airos-dfs-reset/files/airos-dfs-reset.init b/external/subpack/utils/airos-dfs-reset/files/airos-dfs-reset.init
new file mode 100644
index 0000000..d75c5b9
--- /dev/null
+++ b/external/subpack/utils/airos-dfs-reset/files/airos-dfs-reset.init
@@ -0,0 +1,18 @@
+#!/bin/sh /etc/rc.common
+
+USE_PROCD=1
+START=95
+STOP=01
+
+start_service() {
+ procd_open_instance
+ procd_set_param command /usr/bin/airos-dfs-reset
+ procd_set_param stdout 0
+ procd_set_param stderr 0
+ procd_set_param user nobody
+ procd_close_instance
+}
+
+service_stopped() {
+ echo "airos-dfs-reset stopped!"
+}
diff --git a/external/subpack/utils/ap51-flash/Makefile b/external/subpack/utils/ap51-flash/Makefile
new file mode 100644
index 0000000..5654447
--- /dev/null
+++ b/external/subpack/utils/ap51-flash/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2010-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ap51-flash
+PKG_VERSION:=2019.0.1
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/ap51-flash/ap51-flash/releases/download/v$(PKG_VERSION)
+PKG_HASH:=7146a22576a23bfe36673980bc3795a97417692eaddb2f90b527074a7d7e42d5
+
+PKG_MAINTAINER:=Russell Senior <russell@personaltelco.net>
+PKG_LICENSE:=GPL-3.0-or-later CC0-1.0
+PKG_LICENSE_FILES:=LICENSES/GPL-3.0-or-later.txt LICENSES/CC0-1.0.txt
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ap51-flash
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=A tool for flashing (nearly) all ap51/ap61 based routers
+ URL:=https://ap51-flash.readthedocs.io/en/latest/
+endef
+
+# pass optimization flags
+MAKE_FLAGS += \
+ REVISION="$(PKG_VERSION)" \
+ ap51-flash
+
+TARGET_CFLAGS += -flto
+TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed
+
+define Package/ap51-flash/install
+ $(INSTALL_DIR) $(1)/etc/config $(1)/etc/init.d $(1)/usr/sbin \
+ $(1)/usr/lib/ap51-flash
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ap51-flash $(1)/usr/sbin/
+ $(INSTALL_BIN) ./files/ap51-flash.init $(1)/etc/init.d/ap51-flash
+ $(INSTALL_BIN) ./files/ap51-flash.sh $(1)/usr/lib/ap51-flash/ap51-flash.sh
+ $(INSTALL_DATA) ./files/ap51-flash.config $(1)/etc/config/ap51-flash
+endef
+
+define Package/ap51-flash/conffiles
+/etc/config/ap51-flash
+endef
+
+$(eval $(call BuildPackage,ap51-flash))
diff --git a/external/subpack/utils/ap51-flash/files/ap51-flash.config b/external/subpack/utils/ap51-flash/files/ap51-flash.config
new file mode 100644
index 0000000..f66973f
--- /dev/null
+++ b/external/subpack/utils/ap51-flash/files/ap51-flash.config
@@ -0,0 +1,6 @@
+#config flash
+# option ifname eth0.1
+# option rootfs /tmp/images/openwrt-atheros-root.squashfs
+# option kernel /tmp/images/openwrt-atheros-vmlinux.lzma
+# option ubnt /tmp/images/openwrt-atheros-ubnt5-squashfs.bin
+## option loop '1'
diff --git a/external/subpack/utils/ap51-flash/files/ap51-flash.init b/external/subpack/utils/ap51-flash/files/ap51-flash.init
new file mode 100644
index 0000000..7969385
--- /dev/null
+++ b/external/subpack/utils/ap51-flash/files/ap51-flash.init
@@ -0,0 +1,44 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2010 OpenWrt.org
+
+START=20
+
+NAME=ap51-flash
+
+start_daemon() {
+ local cfg="$1"
+
+ config_get_bool loop "$cfg" loop
+ config_get ifname "$cfg" ifname
+ config_get rootfs "$cfg" rootfs
+ config_get kernel "$cfg" kernel
+ config_get ubnt "$cfg" ubnt
+ [ "$loop" != "1" ] && loop=0
+ if [ -n "$ifname" -a -n "$rootfs" -a -n "$kernel" ] || \
+ [ -n "$ifname" -a -n "$ubnt" ]; then
+ PID="$(cat /var/run/$NAME.sh-$ifname.pid 2> /dev/null)"
+ if ! pgrep "^.[ ]*$PID "; then
+ rm "/var/run/$NAME.sh-$ifname.pid"
+ fi
+ if find /var/run/ -name "$NAME.sh-$ifname.pid"; then
+ echo "Can't start more than one ap51-flash for interface $ifname!"
+ return 0
+ fi
+ start-stop-daemon -S -b -m -p "/var/run/$NAME.sh-$ifname.pid" -n $NAME.sh \
+ -x /usr/lib/ap51-flash/$NAME.sh -- "$loop" "$ifname" "$rootfs" "$kernel" "$ubnt"
+ fi
+}
+
+start() {
+ config_load ap51-flash
+ config_foreach start_daemon flash
+}
+
+stop() {
+ # Terminating all ap51-flash processes
+ echo "WARNING: Going to teminate all ap51-flash processes! (hope you made sure that they're not flashing right now)"
+ echo "OR you can stop this with Ctrl+c within 10 seconds"
+ sleep 10
+ find /var/run/ -name "$NAME.sh-*.pid" -exec start-stop-daemon -K -s TERM -p '{}' -n "$NAME.sh" \; -exec rm -f '{}' \;
+ find /var/run/ -name "$NAME.sh-*.pid" -exec start-stop-daemon -K -s TERM -p '{}' -n "$NAME" \; -exec rm -f '{}' \;
+}
diff --git a/external/subpack/utils/ap51-flash/files/ap51-flash.sh b/external/subpack/utils/ap51-flash/files/ap51-flash.sh
new file mode 100755
index 0000000..4eb5ea5
--- /dev/null
+++ b/external/subpack/utils/ap51-flash/files/ap51-flash.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+NAME=ap51-flash
+rootfs=""
+kernel=""
+ubnt=""
+
+[ "$1" -eq "1" ] && loop="1"
+ifname="$2"
+[ -n "$3" ] && rootfs="--rootfs $3"
+[ -n "$4" ] && kernel="--kernel $4"
+[ -n "$5" ] && ubnt="--ubnt $5"
+
+while true; do
+ start-stop-daemon -S -m -p "/var/run/$NAME-$ifname.pid" -n $NAME \
+ -x /usr/sbin/$NAME -- --flash-from-file "$rootfs" "$kernel" "$ubnt" "$ifname"
+
+ rm "/var/run/$NAME-$ifname.pid"
+ [ "$loop" != "1" ] && break
+ sleep 15
+done
diff --git a/external/subpack/utils/at/Makefile b/external/subpack/utils/at/Makefile
new file mode 100644
index 0000000..5e4d4d2
--- /dev/null
+++ b/external/subpack/utils/at/Makefile
@@ -0,0 +1,63 @@
+#
+# Copyright (C) 2008-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=at
+PKG_VERSION:=3.2.1
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://salsa.debian.org/debian/at.git
+PKG_SOURCE_VERSION:=release/3.2.1
+PKG_MIRROR_HASH=c37feb425e7d310f29b4c8dffd846b8a3b410ff6e88a6563f0ecaa636fb22cc2
+
+PKG_MAINTAINER:=Phil Eichinger <phil@zankapfel.net>
+PKG_LICENSE:=GPL-2.0-or-later GPL-3.0-or-later ISC
+PKG_LICENSE_FILES:=COPYING Copyright
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/at
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libelf
+ TITLE:=Delayed job execution and batch processing
+ URL:=http://packages.debian.org/stable/at
+endef
+
+define Package/at/description
+ At and batch read shell commands from standard input storing them as a job to
+ be scheduled for execution in the future.
+endef
+
+export SENDMAIL=/bin/true
+EXTRA_CFLAGS:=-DNEED_YYWRAP -I$(PKG_BUILD_DIR) \
+ $(TARGET_LDFLAGS)
+
+CONFIGURE_ARGS+= \
+ --prefix=/usr \
+ --without-selinux \
+ --with-daemon_username=nobody \
+ --with-daemon_groupname=nogroup \
+ --with-jobdir=/var/spool/cron/atjobs \
+ --with-atspool=/var/spool/cron/atspool
+
+CONFIGURE_VARS += \
+ ac_cv_header_security_pam_appl_h=no
+
+define Package/at/install
+ $(INSTALL_DIR) $(1)/usr/bin $(1)/usr/sbin $(1)/etc/init.d/
+ $(INSTALL_BIN) ./files/atd.init $(1)/etc/init.d/atd
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/at $(1)/usr/bin
+ ln -sf at $(1)/usr/bin/atq
+ ln -sf at $(1)/usr/bin/atrm
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/atd $(1)/usr/sbin
+endef
+
+$(eval $(call BuildPackage,at))
diff --git a/external/subpack/utils/at/files/atd.init b/external/subpack/utils/at/files/atd.init
new file mode 100755
index 0000000..f293b1c
--- /dev/null
+++ b/external/subpack/utils/at/files/atd.init
@@ -0,0 +1,26 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2015 OpenWrt.org
+
+START=50
+
+USE_PROCD=1
+
+start_service() {
+ [ -d /var/spool/cron/atjobs ] || {
+ mkdir -m 0755 -p /var/spool/cron/atjobs
+ touch /var/spool/cron/atjobs/.SEQ
+ chown -R nobody:nogroup /var/spool/cron/atjobs
+ }
+ [ -d /var/spool/cron/atspool ] || {
+ mkdir -m 0755 -p /var/spool/cron/atspool
+ chown -R nobody:nogroup /var/spool/cron/atspool
+ }
+ procd_open_instance
+
+ procd_set_param command /usr/sbin/atd -f
+ procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
+ procd_set_param stdout 1 # forward stdout of the command to logd
+ procd_set_param stderr 1 # same for stderr
+
+ procd_close_instance
+}
diff --git a/external/subpack/utils/at/patches/100-remove-glibc-assumption.patch b/external/subpack/utils/at/patches/100-remove-glibc-assumption.patch
new file mode 100644
index 0000000..f8a5e59
--- /dev/null
+++ b/external/subpack/utils/at/patches/100-remove-glibc-assumption.patch
@@ -0,0 +1,54 @@
+From 7f811d9c4ebc9444e613e251c31d6bf537a24dc1 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Mon, 13 Apr 2015 16:35:30 -0700
+Subject: [PATCH] remove glibc assumption
+
+glibc time.h header has an undocumented __isleap macro
+that we are using anf musl is missing it.
+Since it is undocumented & does not appear
+on any other libc, stop using it and just define the macro in
+locally instead.
+
+Upstream-Status: Pending
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+[patch from: http://patchwork.openembedded.org/patch/91893/ ]
+Signed-off-by: Phil Eichinger <phil@zankapfel.net>
+---
+ parsetime.y | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/parsetime.y
++++ b/parsetime.y
+@@ -14,6 +14,9 @@
+ ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
+ #endif
+
++#define is_leap_year(y) \
++ ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
++
+ struct tm exectm;
+ static int isgmt;
+ static char *tz = NULL;
+@@ -230,8 +233,8 @@ date : month_name day_number
+ mnum == 12) && dnum > 31)
+ || ((mnum == 4 || mnum == 6 || mnum == 9 ||
+ mnum == 11) && dnum > 30)
+- || (mnum == 2 && dnum > 29 && __isleap(ynum+1900))
+- || (mnum == 2 && dnum > 28 && !__isleap(ynum+1900))
++ || (mnum == 2 && dnum > 29 && is_leap_year(ynum+1900))
++ || (mnum == 2 && dnum > 28 && !is_leap_year(ynum+1900))
+ )
+ {
+ yyerror("Error in day of month");
+@@ -274,8 +277,8 @@ date : month_name day_number
+ mnum == 12) && dnum > 31)
+ || ((mnum == 4 || mnum == 6 || mnum == 9 ||
+ mnum == 11) && dnum > 30)
+- || (mnum == 2 && dnum > 29 && __isleap(ynum+1900))
+- || (mnum == 2 && dnum > 28 && !__isleap(ynum+1900))
++ || (mnum == 2 && dnum > 29 && is_leap_year(ynum+1900))
++ || (mnum == 2 && dnum > 28 && !is_leap_year(ynum+1900))
+ )
+ {
+ yyerror("Error in day of month");
diff --git a/external/subpack/utils/at/patches/110-getloadavg.patch b/external/subpack/utils/at/patches/110-getloadavg.patch
new file mode 100644
index 0000000..0faef97
--- /dev/null
+++ b/external/subpack/utils/at/patches/110-getloadavg.patch
@@ -0,0 +1,14 @@
+--- a/getloadavg.c
++++ b/getloadavg.c
+@@ -69,8 +69,9 @@ Boston, MA 02110-1301 USA */
+ #include <config.h>
+ #endif
+
+-#include "lisp.h"
+-#include "sysfile.h" /* for encapsulated open, close, read, write */
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
+
+ #ifndef HAVE_GETLOADAVG
+
diff --git a/external/subpack/utils/atheepmgr/Makefile b/external/subpack/utils/atheepmgr/Makefile
new file mode 100644
index 0000000..bb69566
--- /dev/null
+++ b/external/subpack/utils/atheepmgr/Makefile
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2021 Sergey Ryazanov <ryazanov.s.a@gmail.com>
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=atheepmgr
+PKG_VERSION:=2.1.1
+PKG_RELEASE:=2
+
+PKG_SOURCE_VERSION:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/rsa9000/$(PKG_NAME).git
+PKG_MIRROR_HASH:=dc77354538bd16343afb3e93c50cdd46792ced0f1632c7be0ddf56d2fcd75ba4
+
+PKG_MAINTAINER:=Sergey Ryazanov <ryazanov.s.a@gmail.com>
+PKG_LICENSE:=ISC
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_CONFIG_DEPENDS:=\
+ CONFIG_ATHEEPMGR_DANGEROUS_FUNCTIONS \
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/atheepmgr
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=EEPROM/boarddata management utility for Atheros WLAN chips
+ MENU:=1
+endef
+
+define Package/atheepmgr/description
+ This utility is intended to investigate the content of Atheros WLAN
+ chips EEPROM (OTP, boarddata, ART, etc.). It supports data extraction,
+ unpacking, parsing, dumping in a text form, saving binary data for
+ further analysis, as well as quick editing of some basic fields (e.g.
+ MAC address, etc.).
+
+ The utility supports both data access methods: direct EEPROM (OTP)
+ access (via the chip) and offline binary dumps handling.
+
+endef
+
+define Package/atheepmgr/config
+ if PACKAGE_atheepmgr
+ config ATHEEPMGR_DANGEROUS_FUNCTIONS
+ bool "Enable dangerous functions"
+ default n
+ help
+ This option enables some functions, the use of which could cause
+ permanent hardware damages and (or) make the operation of the
+ equipment illegal due to RF spectre usage violation.
+
+ These functions are intended for use by developers and radio
+ engineers.
+
+ You have been warned. If unsure, say no.
+ endif
+endef
+
+MAKE_VARS += \
+ OS=Linux \
+ CONFIG_CON_PCI=n \
+ CONFIG_I_KNOW_WHAT_I_AM_DOING=$(CONFIG_ATHEEPMGR_DANGEROUS_FUNCTIONS) \
+
+define Package/atheepmgr/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/atheepmgr $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,atheepmgr))
diff --git a/external/subpack/utils/attendedsysupgrade-common/Makefile b/external/subpack/utils/attendedsysupgrade-common/Makefile
new file mode 100644
index 0000000..fca6532
--- /dev/null
+++ b/external/subpack/utils/attendedsysupgrade-common/Makefile
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: GPL-2.0
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=attendedsysupgrade-common
+PKG_VERSION:=0.3
+PKG_RELEASE:=1
+PKG_LICENSE:=GPL-2.0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/attendedsysupgrade-common
+ SECTION:=utils
+ CATEGORY:=Base system
+ TITLE:=Common files neede by attendedsysupgrade packages
+ MAINTAINER:=Paul Spooren <mail@aparcar.org>
+ DEPENDS:=+rpcd +rpcd-mod-rpcsys
+ PKGARCH:=all
+endef
+
+define Package/attendedsysupgrade-common/description
+ Common needed files for attendedsysupgrade tool
+
+ Manages dependencies and brings settings used by clients.
+
+ UCI options:
+
+ * attendedsysupgrade.server.url
+ URL of compatible upgrade server [1]
+
+ * attendedsysupgrade.client.upgrade_packages
+ Client should request image also if no new release but new packages
+ upgrade are available.
+
+ * attendedsysupgrade.client.advanced_mode
+ Offer advanced options like editing packages before request and show
+ additional information.
+
+ * attendedsysupgrade.client.auto_search
+ Tells the client to automattically search for upgrades
+
+ [1]: https://github.com/aparcar/asu
+endef
+
+define Build/Compile
+endef
+
+define Build/Configure
+endef
+
+define Package/attendedsysupgrade-common/install
+ $(INSTALL_DIR) $(1)/etc/uci-defaults/
+ $(INSTALL_BIN) ./files/attendedsysupgrade.defaults $(1)/etc/uci-defaults/attendedsysupgrade
+
+ $(INSTALL_DIR) $(1)/etc/opkg/keys/
+ $(INSTALL_BIN) ./files/86241a707a30cb7f $(1)/etc/opkg/keys/86241a707a30cb7f
+endef
+
+$(eval $(call BuildPackage,attendedsysupgrade-common))
diff --git a/external/subpack/utils/attendedsysupgrade-common/files/86241a707a30cb7f b/external/subpack/utils/attendedsysupgrade-common/files/86241a707a30cb7f
new file mode 100644
index 0000000..8007327
--- /dev/null
+++ b/external/subpack/utils/attendedsysupgrade-common/files/86241a707a30cb7f
@@ -0,0 +1,2 @@
+untrusted comment: ASU CA pubkey
+RWSGJBpwejDLf4OApA5SOavh0GBlBFY9FhqxnivUQHpi0/t0QRI98LPW
diff --git a/external/subpack/utils/attendedsysupgrade-common/files/attendedsysupgrade.defaults b/external/subpack/utils/attendedsysupgrade-common/files/attendedsysupgrade.defaults
new file mode 100644
index 0000000..4f49288
--- /dev/null
+++ b/external/subpack/utils/attendedsysupgrade-common/files/attendedsysupgrade.defaults
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+[ -e /etc/config/attendedsysupgrade ] && return 0
+
+touch /etc/config/attendedsysupgrade
+
+uci -q batch <<EOF
+set attendedsysupgrade.server=server
+set attendedsysupgrade.server.url='https://sysupgrade.openwrt.org'
+
+set attendedsysupgrade.client=client
+set attendedsysupgrade.client.upgrade_packages='1'
+set attendedsysupgrade.client.auto_search='0'
+set attendedsysupgrade.client.advanced_mode='0'
+
+commit attendedsysupgrade
+EOF
diff --git a/external/subpack/utils/attr/Makefile b/external/subpack/utils/attr/Makefile
new file mode 100644
index 0000000..eb107ce
--- /dev/null
+++ b/external/subpack/utils/attr/Makefile
@@ -0,0 +1,93 @@
+#
+# Copyright (C) 2014-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=attr
+PKG_VERSION:=2.4.48
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://git.savannah.nongnu.org/cgit/attr.git/snapshot
+PKG_HASH:=095699f71230ace37e5bc680c6f9d15cf8e53eb38d00b2c46db5cc7e0712e5f3
+
+PKG_MAINTAINER:=Maxim Storchak <m.storchak@gmail.com>
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/attr/Default
+ TITLE:=Extended attributes (xattr) manipulation
+ URL:=http://savannah.nongnu.org/projects/attr
+ SUBMENU:=Filesystem
+endef
+
+define Package/attr/Default/description
+ Extended attributes support
+endef
+
+define Package/attr
+$(call Package/attr/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE+=utils
+ LICENSE:=GPL-2.0-or-later
+ LICENSE_FILES:=doc/COPYING
+ DEPENDS:=+libattr
+endef
+
+define Package/libattr
+$(call Package/attr/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+=library
+ LICENSE:=LGPL-2.1-or-later
+ LICENSE_FILES:=doc/COPYING.LGPL
+endef
+
+define Package/libattr/description
+$(call Package/attr/Default/description)
+ This package provides libattr
+endef
+
+define Package/attr/description
+$(call Package/attr/Default/description)
+ This package provides xattr manipulation utilities
+ - attr
+ - getfattr
+ - setfattr
+endef
+
+CONFIGURE_ARGS += --enable-static --enable-shared
+
+define Package/attr/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+endef
+
+define Package/libattr/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_DIR) $(1)/etc
+ $(CP) $(PKG_INSTALL_DIR)/etc $(1)/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
+endef
+
+define Package/attr/conffiles
+/etc/xattr.conf
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/{include,lib} $(1)/usr/
+endef
+
+$(eval $(call BuildPackage,attr))
+$(eval $(call BuildPackage,libattr))
diff --git a/external/subpack/utils/attr/patches/100-no-gettext_configure.patch b/external/subpack/utils/attr/patches/100-no-gettext_configure.patch
new file mode 100644
index 0000000..dea6f2e
--- /dev/null
+++ b/external/subpack/utils/attr/patches/100-no-gettext_configure.patch
@@ -0,0 +1,19 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -34,9 +34,6 @@ AC_FUNC_GCC_VISIBILITY
+ AM_PROG_AR
+ LT_INIT
+
+-AM_GNU_GETTEXT_VERSION([0.18.2])
+-AM_GNU_GETTEXT([external])
+-
+ AC_ARG_ENABLE([debug],
+ [AS_HELP_STRING([--enable-debug], [Enable extra debugging])])
+ AS_IF([test "x$enable_debug" = "xyes"],
+@@ -55,6 +52,5 @@ AC_CONFIG_COMMANDS([include/attr],
+ AC_CONFIG_FILES([
+ libattr.pc
+ Makefile
+- po/Makefile.in
+ ])
+ AC_OUTPUT
diff --git a/external/subpack/utils/attr/patches/101-no-gettext_autogen.patch b/external/subpack/utils/attr/patches/101-no-gettext_autogen.patch
new file mode 100644
index 0000000..e9a8c8c
--- /dev/null
+++ b/external/subpack/utils/attr/patches/101-no-gettext_autogen.patch
@@ -0,0 +1,7 @@
+--- a/autogen.sh
++++ b/autogen.sh
+@@ -1,4 +1,2 @@
+ #!/bin/sh -ex
+-po/update-potfiles
+-autopoint --force
+ exec autoreconf -f -i
diff --git a/external/subpack/utils/attr/patches/102-no-gettext_Makefile.patch b/external/subpack/utils/attr/patches/102-no-gettext_Makefile.patch
new file mode 100644
index 0000000..4d562b9
--- /dev/null
+++ b/external/subpack/utils/attr/patches/102-no-gettext_Makefile.patch
@@ -0,0 +1,11 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -3,8 +3,6 @@ ACLOCAL_AMFLAGS = -I m4
+ EXTRA_DIST = \
+ exports
+
+-SUBDIRS = po
+-
+ AM_CPPFLAGS = \
+ -I$(top_builddir)/include \
+ -I$(top_srcdir)/include \
diff --git a/external/subpack/utils/attr/patches/110-Replace-bzero-with-memset.patch b/external/subpack/utils/attr/patches/110-Replace-bzero-with-memset.patch
new file mode 100644
index 0000000..cfae36a
--- /dev/null
+++ b/external/subpack/utils/attr/patches/110-Replace-bzero-with-memset.patch
@@ -0,0 +1,60 @@
+From 0ce120a140dadaa56875af2efc66ff805d37925b Mon Sep 17 00:00:00 2001
+From: Rosen Penev <rosenp@gmail.com>
+Date: Sun, 11 Aug 2019 16:17:11 -0700
+Subject: [PATCH] attr: Replace bzero with memset
+
+bzero is a deprecated function that is optionally unavailable with
+uClibc-ng.
+
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+---
+ include/attributes.h | 4 ++--
+ libattr/libattr.c | 4 ++--
+ tools/attr.c | 2 +-
+ 3 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/include/attributes.h
++++ b/include/attributes.h
+@@ -91,9 +91,9 @@ typedef struct attrlist_ent { /* data fr
+ * Implement a "cursor" for use in successive attr_list() calls.
+ * It provides a way to find the last attribute that was returned in the
+ * last attr_list() call so that we can get the next one without missing
+- * any. This should be bzero()ed before use and whenever it is desired to
++ * any. This should be zeroed before use and whenever it is desired to
+ * start over from the beginning of the attribute list. The only valid
+- * operation on a cursor is to bzero() it.
++ * operation on a cursor is to zero it.
+ */
+ typedef struct attrlist_cursor {
+ uint32_t opaque[4]; /* an opaque cookie */
+--- a/libattr/libattr.c
++++ b/libattr/libattr.c
+@@ -298,7 +298,7 @@ attr_list(const char *path, char *buffer
+ errno = EINVAL;
+ return -1;
+ }
+- bzero(buffer, sizeof(attrlist_t));
++ memset(buffer, 0, sizeof(attrlist_t));
+
+ if (flags & ATTR_DONTFOLLOW)
+ length = llistxattr(path, lbuf, sizeof(lbuf));
+@@ -348,7 +348,7 @@ attr_listf(int fd, char *buffer, const i
+ errno = EINVAL;
+ return -1;
+ }
+- bzero(buffer, sizeof(attrlist_t));
++ memset(buffer, 0, sizeof(attrlist_t));
+
+ length = flistxattr(fd, lbuf, sizeof(lbuf));
+ if (length < 0)
+--- a/tools/attr.c
++++ b/tools/attr.c
+@@ -228,7 +228,7 @@ main(int argc, char **argv)
+ perror("malloc");
+ exit(1);
+ }
+- bzero((char *)&cursor, sizeof(cursor));
++ memset(&cursor, 0, sizeof(cursor));
+ do {
+ error = attr_list(filename, buffer, BUFSIZE,
+ attrflags, &cursor);
diff --git a/external/subpack/utils/auc/Makefile b/external/subpack/utils/auc/Makefile
new file mode 100644
index 0000000..7bd296e
--- /dev/null
+++ b/external/subpack/utils/auc/Makefile
@@ -0,0 +1,36 @@
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=auc
+PKG_VERSION:=0.3.1
+PKG_RELEASE:=$(AUTORELEASE)
+PKG_LICENSE:=GPL-3.0
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/auc
+ SECTION:=base
+ CATEGORY:=Base system
+ TITLE:=Attended sysUpgrade CLI (EXPERIMENTAL)
+ DEPENDS:=+attendedsysupgrade-common +libblobmsg-json +libubox +libubus \
+ +libuci +libuclient +rpcd-mod-rpcsys
+endef
+
+define Package/auc/description
+ CLI client for attended-sysupgrade
+endef
+
+EXTRA_CFLAGS += \
+ -D'AUC_VERSION=\"$(PKG_VERSION)-$(PKG_RELEASE)\"' \
+ $(if $(CONFIG_DEBUG),-DAUC_DEBUG=ON)
+
+define Package/auc/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/auc $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,auc))
diff --git a/external/subpack/utils/auc/src/CMakeLists.txt b/external/subpack/utils/auc/src/CMakeLists.txt
new file mode 100644
index 0000000..14cc199
--- /dev/null
+++ b/external/subpack/utils/auc/src/CMakeLists.txt
@@ -0,0 +1,12 @@
+cmake_minimum_required(VERSION 2.6...3.12)
+
+PROJECT(auc C)
+ADD_DEFINITIONS(-Os -ggdb -Wall --std=gnu99 -Wmissing-declarations)
+
+SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+
+find_library(json NAMES json-c json)
+
+ADD_EXECUTABLE(auc auc.c)
+TARGET_LINK_LIBRARIES(auc uci ubox ubus uclient blobmsg_json ${json} ${CMAKE_DL_LIBS})
+INSTALL(TARGETS auc RUNTIME DESTINATION sbin)
diff --git a/external/subpack/utils/auc/src/auc.c b/external/subpack/utils/auc/src/auc.c
new file mode 100644
index 0000000..711ca81
--- /dev/null
+++ b/external/subpack/utils/auc/src/auc.c
@@ -0,0 +1,2186 @@
+/*
+ * auc - attendedsysUpgrade CLI
+ * Copyright (C) 2017-2021 Daniel Golle <daniel@makrotopia.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define _GNU_SOURCE
+#ifndef AUC_VERSION
+#define AUC_VERSION "unknown"
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <glob.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include <uci.h>
+#include <uci_blob.h>
+#include <json-c/json.h>
+#include <libubox/ulog.h>
+#include <libubox/list.h>
+#include <libubox/vlist.h>
+#include <libubox/blobmsg_json.h>
+#include <libubox/avl-cmp.h>
+#include <libubox/uclient.h>
+#include <libubox/uclient-utils.h>
+#include <libubus.h>
+
+#define REQ_TIMEOUT 15
+
+#define API_BRANCHES "branches"
+#define API_INDEX "index"
+#define API_JSON "json"
+#define API_JSON_VERSION "v1"
+#define API_JSON_EXT "." API_JSON
+#define API_PACKAGES "packages"
+#define API_REQUEST "api/v1/build"
+#define API_STATUS_QUEUED "queued"
+#define API_STATUS_STARTED "started"
+#define API_STORE "store"
+#define API_TARGETS "targets"
+
+#define PUBKEY_PATH "/etc/opkg/keys"
+#define SHA256SUM "/bin/busybox sha256sum"
+
+#ifdef AUC_DEBUG
+#define DPRINTF(...) if (debug) fprintf(stderr, __VA_ARGS__)
+#else
+#define DPRINTF(...)
+#endif
+
+static const char server_issues[]="https://github.com/openwrt/asu/issues";
+
+static struct ubus_context *ctx;
+static struct uclient *ucl = NULL;
+static char user_agent[80];
+static char *serverurl;
+static int upgrade_packages;
+static struct ustream_ssl_ctx *ssl_ctx;
+static const struct ustream_ssl_ops *ssl_ops;
+static off_t out_bytes;
+static off_t out_len;
+static off_t out_offset;
+static bool cur_resume;
+static int output_fd = -1;
+static bool retry = false;
+static char *board_name = NULL;
+static char *target = NULL;
+static char *distribution = NULL, *version = NULL, *revision = NULL;
+static char *rootfs_type = NULL;
+static int uptodate;
+static char *filename = NULL;
+static void *dlh = NULL;
+static int rc;
+static bool dont_ask = false;
+
+struct branch {
+ struct avl_node avl;
+ char *name;
+ char *git_branch;
+ char *path_packages;
+ char *arch_packages;
+ char **repos;
+ struct avl_tree versions;
+ struct list_head package_changes;
+ bool snapshot;
+ unsigned int branch_off_rev;
+};
+static struct avl_tree branches = AVL_TREE_INIT(branches, avl_strcmp, false, NULL);
+
+struct branch_version {
+ struct avl_node avl;
+ struct branch *branch;
+ char *path;
+ char *version;
+ char *version_code;
+ char *version_number;
+ bool snapshot;
+};
+
+struct package_changes {
+ struct list_head list;
+ unsigned int revision;
+ char *source;
+ char *target;
+ bool mandatory;
+};
+static LIST_HEAD(selected_package_changes);
+
+struct avl_pkg {
+ struct avl_node avl;
+ char *name;
+ char *version;
+};
+static struct avl_tree pkg_tree = AVL_TREE_INIT(pkg_tree, avl_strcmp, false, NULL);
+
+#ifdef AUC_DEBUG
+static int debug = 0;
+#endif
+
+/*
+ * policy for ubus call system board
+ * see procd/system.c
+ */
+enum {
+ BOARD_BOARD_NAME,
+ BOARD_RELEASE,
+ BOARD_ROOTFS_TYPE,
+ __BOARD_MAX,
+};
+
+static const struct blobmsg_policy board_policy[__BOARD_MAX] = {
+ [BOARD_BOARD_NAME] = { .name = "board_name", .type = BLOBMSG_TYPE_STRING },
+ [BOARD_RELEASE] = { .name = "release", .type = BLOBMSG_TYPE_TABLE },
+ [BOARD_ROOTFS_TYPE] = { .name = "rootfs_type", .type = BLOBMSG_TYPE_STRING },
+};
+
+/*
+ * policy for release information in system board reply
+ * see procd/system.c
+ */
+enum {
+ RELEASE_DISTRIBUTION,
+ RELEASE_REVISION,
+ RELEASE_TARGET,
+ RELEASE_VERSION,
+ __RELEASE_MAX,
+};
+
+static const struct blobmsg_policy release_policy[__RELEASE_MAX] = {
+ [RELEASE_DISTRIBUTION] = { .name = "distribution", .type = BLOBMSG_TYPE_STRING },
+ [RELEASE_REVISION] = { .name = "revision", .type = BLOBMSG_TYPE_STRING },
+ [RELEASE_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
+ [RELEASE_VERSION] = { .name = "version", .type = BLOBMSG_TYPE_STRING },
+};
+
+/*
+ * policy for package list returned from rpc-sys or from server
+ * see rpcd/sys.c and ASU sources
+ */
+enum {
+ PACKAGES_ARCHITECTURE,
+ PACKAGES_PACKAGES,
+ __PACKAGES_MAX,
+};
+
+static const struct blobmsg_policy packages_policy[__PACKAGES_MAX] = {
+ [PACKAGES_ARCHITECTURE] = { .name = "architecture", .type = BLOBMSG_TYPE_STRING },
+ [PACKAGES_PACKAGES] = { .name = "packages", .type = BLOBMSG_TYPE_TABLE },
+};
+
+/*
+ * policy for upgrade_test
+ * see rpcd/sys.c
+ */
+enum {
+ UPGTEST_CODE,
+ UPGTEST_STDERR,
+ __UPGTEST_MAX,
+};
+
+static const struct blobmsg_policy upgtest_policy[__UPGTEST_MAX] = {
+ [UPGTEST_CODE] = { .name = "code", .type = BLOBMSG_TYPE_INT32 },
+ [UPGTEST_STDERR] = { .name = "stderr", .type = BLOBMSG_TYPE_STRING },
+};
+
+/*
+ * policy for branches.json
+ */
+enum {
+ BRANCH_ENABLED,
+ BRANCH_GIT_BRANCH,
+ BRANCH_BRANCH_OFF_REV,
+ BRANCH_NAME,
+ BRANCH_PATH,
+ BRANCH_PATH_PACKAGES,
+ BRANCH_SNAPSHOT,
+ BRANCH_REPOS,
+ BRANCH_TARGETS,
+ BRANCH_UPDATES,
+ BRANCH_VERSIONS,
+ BRANCH_PACKAGE_CHANGES,
+ __BRANCH_MAX,
+};
+
+static const struct blobmsg_policy branches_policy[__BRANCH_MAX] = {
+ [BRANCH_ENABLED] = { .name = "enabled", .type = BLOBMSG_TYPE_BOOL },
+ [BRANCH_GIT_BRANCH] = { .name = "git_branch", .type = BLOBMSG_TYPE_STRING },
+ [BRANCH_BRANCH_OFF_REV] = { .name = "branch_off_rev", .type = BLOBMSG_TYPE_INT32 },
+ [BRANCH_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
+ [BRANCH_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
+ [BRANCH_PATH_PACKAGES] = { .name = "path_packages", .type = BLOBMSG_TYPE_STRING },
+ [BRANCH_SNAPSHOT] = { .name = "snapshot", .type = BLOBMSG_TYPE_BOOL },
+ [BRANCH_REPOS] = { .name = "repos", .type = BLOBMSG_TYPE_ARRAY },
+ [BRANCH_TARGETS] = { .name = "targets", .type = BLOBMSG_TYPE_TABLE },
+ [BRANCH_UPDATES] = { .name = "updates", .type = BLOBMSG_TYPE_STRING },
+ [BRANCH_VERSIONS] = { .name = "versions", .type = BLOBMSG_TYPE_ARRAY },
+ [BRANCH_PACKAGE_CHANGES] = { .name = "package_changes", .type = BLOBMSG_TYPE_ARRAY },
+};
+
+enum {
+ PACKAGE_CHANGES_SOURCE,
+ PACKAGE_CHANGES_TARGET,
+ PACKAGE_CHANGES_REVISION,
+ PACKAGE_CHANGES_MANDATORY,
+ __PACKAGE_CHANGES_MAX,
+};
+
+static const struct blobmsg_policy package_changes_policy[__PACKAGE_CHANGES_MAX] = {
+ [PACKAGE_CHANGES_SOURCE] = { .name = "source", .type = BLOBMSG_TYPE_STRING },
+ [PACKAGE_CHANGES_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
+ [PACKAGE_CHANGES_REVISION] = { .name = "revision", .type = BLOBMSG_TYPE_INT32 },
+ [PACKAGE_CHANGES_MANDATORY] = { .name = "mandatory", .type = BLOBMSG_TYPE_BOOL },
+};
+
+/*
+ * shared policy for target.json and server image request reply
+ */
+enum {
+ TARGET_ARCH_PACKAGES,
+ TARGET_BINDIR,
+ TARGET_DEVICE_PACKAGES,
+ TARGET_ENQUEUED_AT,
+ TARGET_IMAGES,
+ TARGET_DETAIL,
+ TARGET_MANIFEST,
+ TARGET_METADATA_VERSION,
+ TARGET_REQUEST_HASH,
+ TARGET_QUEUE_POSITION,
+ TARGET_STATUS,
+ TARGET_STDERR,
+ TARGET_STDOUT,
+ TARGET_TARGET,
+ TARGET_TITLES,
+ TARGET_VERSION_CODE,
+ TARGET_VERSION_NUMBER,
+ __TARGET_MAX,
+};
+
+static const struct blobmsg_policy target_policy[__TARGET_MAX] = {
+ [TARGET_ARCH_PACKAGES] = { .name = "arch_packages", .type = BLOBMSG_TYPE_STRING },
+ [TARGET_BINDIR] = { .name = "bin_dir", .type = BLOBMSG_TYPE_STRING },
+ [TARGET_DEVICE_PACKAGES] = { .name = "device_packages", .type = BLOBMSG_TYPE_ARRAY },
+ [TARGET_ENQUEUED_AT] = { .name = "enqueued_at", .type = BLOBMSG_TYPE_STRING },
+ [TARGET_IMAGES] = { .name = "images", .type = BLOBMSG_TYPE_ARRAY },
+ [TARGET_MANIFEST] = { .name = "manifest", .type = BLOBMSG_TYPE_TABLE },
+ [TARGET_DETAIL] = { .name = "detail", .type = BLOBMSG_TYPE_STRING },
+ [TARGET_METADATA_VERSION] = { .name = "metadata_version", .type = BLOBMSG_TYPE_INT32 },
+ [TARGET_REQUEST_HASH] = { .name = "request_hash", .type = BLOBMSG_TYPE_STRING },
+ [TARGET_QUEUE_POSITION] = { .name = "queue_position", .type = BLOBMSG_TYPE_INT32 },
+ [TARGET_STATUS] = { .name = "status", .type = BLOBMSG_TYPE_STRING },
+ [TARGET_STDERR] = { .name = "stderr", .type = BLOBMSG_TYPE_STRING },
+ [TARGET_STDOUT] = { .name = "stdout", .type = BLOBMSG_TYPE_STRING },
+ [TARGET_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
+ [TARGET_TITLES] = { .name = "titles", .type = BLOBMSG_TYPE_ARRAY },
+ [TARGET_VERSION_CODE] = { .name = "version_code", .type = BLOBMSG_TYPE_STRING },
+ [TARGET_VERSION_NUMBER] = { .name = "version_number", .type = BLOBMSG_TYPE_STRING },
+};
+
+/*
+ * policy for images object in target
+ */
+enum {
+ IMAGES_FILESYSTEM,
+ IMAGES_NAME,
+ IMAGES_SHA256,
+ IMAGES_TYPE,
+ __IMAGES_MAX,
+};
+
+static const struct blobmsg_policy images_policy[__IMAGES_MAX] = {
+ [IMAGES_FILESYSTEM] = { .name = "filesystem", .type = BLOBMSG_TYPE_STRING },
+ [IMAGES_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
+ [IMAGES_SHA256] = { .name = "sha256", .type = BLOBMSG_TYPE_STRING },
+ [IMAGES_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING },
+};
+
+/*
+ * generic policy for HTTP JSON reply
+ */
+enum {
+ REPLY_ARRAY,
+ REPLY_OBJECT,
+ __REPLY_MAX,
+};
+
+static const struct blobmsg_policy reply_policy[__REPLY_MAX] = {
+ [REPLY_ARRAY] = { .name = "reply", .type = BLOBMSG_TYPE_ARRAY },
+ [REPLY_OBJECT] = { .name = "reply", .type = BLOBMSG_TYPE_TABLE },
+};
+
+/*
+ * policy for HTTP headers received from server
+ */
+enum {
+ H_LEN,
+ H_RANGE,
+ H_UNKNOWN_PACKAGE,
+ H_QUEUE_POSITION,
+ __H_MAX
+};
+
+static const struct blobmsg_policy header_policy[__H_MAX] = {
+ [H_LEN] = { .name = "content-length", .type = BLOBMSG_TYPE_STRING },
+ [H_RANGE] = { .name = "content-range", .type = BLOBMSG_TYPE_STRING },
+ [H_UNKNOWN_PACKAGE] = { .name = "x-unknown-package", .type = BLOBMSG_TYPE_STRING },
+ [H_QUEUE_POSITION] = { .name = "x-queue-position", .type = BLOBMSG_TYPE_INT32 },
+};
+
+/*
+ * load serverurl from UCI
+ */
+static int load_config() {
+ struct uci_context *uci_ctx;
+ struct uci_package *uci_attendedsysupgrade;
+ struct uci_section *uci_s;
+ char *url;
+
+ uci_ctx = uci_alloc_context();
+ if (!uci_ctx)
+ return -1;
+
+ uci_ctx->flags &= ~UCI_FLAG_STRICT;
+
+ if (uci_load(uci_ctx, "attendedsysupgrade", &uci_attendedsysupgrade) ||
+ !uci_attendedsysupgrade) {
+ fprintf(stderr, "Failed to load attendedsysupgrade config\n");
+ return -1;
+ }
+ uci_s = uci_lookup_section(uci_ctx, uci_attendedsysupgrade, "server");
+ if (!uci_s) {
+ fprintf(stderr, "Failed to read server config section\n");
+ return -1;
+ }
+ url = uci_lookup_option_string(uci_ctx, uci_s, "url");
+ if (!url) {
+ fprintf(stderr, "Failed to read server url from config\n");
+ return -1;
+ }
+ if (strncmp(url, "https://", strlen("https://")) &&
+ strncmp(url, "http://", strlen("http://"))) {
+ fprintf(stderr, "Server url invalid (needs to be http://... or https://...)\n");
+ return -1;
+ }
+
+ serverurl = strdup(url);
+
+ uci_s = uci_lookup_section(uci_ctx, uci_attendedsysupgrade, "client");
+ if (!uci_s) {
+ fprintf(stderr, "Failed to read client config\n");
+ return -1;
+ }
+ upgrade_packages = atoi(uci_lookup_option_string(uci_ctx, uci_s, "upgrade_packages"));
+
+ uci_free_context(uci_ctx);
+
+ return 0;
+}
+
+/*
+ * libdpkg - Debian packaging suite library routines
+ * vercmp.c - comparison of version numbers
+ *
+ * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
+ */
+
+/* assume ascii; warning: evaluates x multiple times! */
+#define order(x) ((x) == '~' ? -1 \
+ : isdigit((x)) ? 0 \
+ : !(x) ? 0 \
+ : isalpha((x)) ? (x) \
+ : (x) + 256)
+
+static int verrevcmp(const char *val, const char *ref)
+{
+ if (!val)
+ val = "";
+ if (!ref)
+ ref = "";
+
+ while (*val || *ref) {
+ int first_diff = 0;
+
+ while ((*val && !isdigit(*val)) || (*ref && !isdigit(*ref))) {
+ int vc = order(*val), rc = order(*ref);
+ if (vc != rc)
+ return vc - rc;
+ val++;
+ ref++;
+ }
+
+ while (*val == '0')
+ val++;
+ while (*ref == '0')
+ ref++;
+ while (isdigit(*val) && isdigit(*ref)) {
+ if (!first_diff)
+ first_diff = *val - *ref;
+ val++;
+ ref++;
+ }
+ if (isdigit(*val))
+ return 1;
+ if (isdigit(*ref))
+ return -1;
+ if (first_diff)
+ return first_diff;
+ }
+ return 0;
+}
+
+static int avl_verrevcmp(const void *k1, const void *k2, void *ptr)
+{
+ const char *d1 = (const char *)k1, *d2 = (const char*)k2;
+
+ return verrevcmp(d1, d2);
+}
+
+/*
+ * replace '-rc' by '~' in string
+ */
+static inline void release_replace_rc(char *ver)
+{
+ char *tmp;
+
+ tmp = strstr(ver, "-rc");
+ if (tmp && strlen(tmp) > 3) {
+ *tmp = '~';
+ memmove(tmp + 1, tmp + 3, strlen(tmp + 3) + 1);
+ }
+}
+
+/*
+ * OpenWrt release version string comperator
+ * replaces '-rc' by '~' to fix ordering of release(s) (candidates)
+ * using the void release_replace_rc(char *ver) function above.
+ */
+static int openwrt_release_verrevcmp(const char *ver1, const char *ver2)
+{
+ char mver1[16], mver2[16];
+
+ strncpy(mver1, ver1, sizeof(mver1) - 1);
+ mver1[sizeof(mver1) - 1] = '\0';
+ strncpy(mver2, ver2, sizeof(mver2) - 1);
+ mver2[sizeof(mver2) - 1] = '\0';
+
+ release_replace_rc(mver1);
+ release_replace_rc(mver2);
+
+ return verrevcmp(mver1, mver2);
+}
+
+/*
+ * Select package_changes from branch to global list
+ */
+static void grab_changes(struct branch *br, unsigned int rev)
+{
+ struct package_changes *c, *n;
+
+#ifdef AUC_DEBUG
+ if (debug)
+ fprintf(stderr, "grabbing changes for branch %s from revision %u\n", br->name, rev);
+#endif
+
+ list_for_each_entry(c, &br->package_changes, list) {
+ if (c->revision == 0 || c->revision > rev) {
+ n = malloc(sizeof(struct package_changes));
+ memcpy(n, c, sizeof(struct package_changes));
+ INIT_LIST_HEAD(&n->list);
+ list_add_tail(&n->list, &selected_package_changes);
+ }
+ }
+}
+
+/**
+ * UBUS response callbacks
+ */
+/*
+ * rpc-sys packagelist
+ * append array of package names to blobbuf given in req->priv
+ */
+#define ANSI_ESC "\x1b"
+#define ANSI_COLOR_RESET ANSI_ESC "[0m"
+#define ANSI_COLOR_RED ANSI_ESC "[1;31m"
+#define ANSI_COLOR_GREEN ANSI_ESC "[1;32m"
+#define ANSI_COLOR_BLUE ANSI_ESC "[1;34m"
+#define ANSI_CURSOR_SAFE "[s"
+#define ANSI_CURSOR_RESTORE "[u"
+#define ANSI_ERASE_LINE "[K"
+
+#define PKG_UPGRADE 0x1
+#define PKG_DOWNGRADE 0x2
+#define PKG_NOT_FOUND 0x4
+#define PKG_ERROR 0x8
+
+static bool ask_user(const char *message)
+{
+ char user_input;
+ fflush(stdin);
+ fprintf(stderr, "%s [N/y] ", message);
+ user_input = getchar();
+ fflush(stdin);
+ if ((user_input == 'y') || (user_input == 'Y'))
+ return true;
+
+ return false;
+}
+
+static inline bool is_builtin_pkg(const char *pkgname)
+{
+ return !strcmp(pkgname, "libc") ||
+ !strcmp(pkgname, "librt") ||
+ !strcmp(pkgname, "libpthread") ||
+ !strcmp(pkgname, "kernel");
+}
+
+static const char *apply_package_changes(const char *pkgname, bool interactive)
+{
+ struct package_changes *pkc;
+ const char *mpkgname = pkgname;
+
+ list_for_each_entry(pkc, &selected_package_changes, list) {
+ /* package_change additions are dealt with later */
+ if (!pkc->source)
+ continue;
+
+ if (strcmp(pkc->source, mpkgname))
+ continue;
+
+ if (!pkc->mandatory && interactive) {
+ if (pkc->target)
+ fprintf(stderr, "Package %s should be replaced by %s.\n", pkc->source, pkc->target);
+ else
+ fprintf(stderr, "Package %s should be removed.\n", pkc->source);
+
+ if (dont_ask)
+ pkc->mandatory = true;
+ else
+ pkc->mandatory = ask_user("Apply change");
+ }
+
+ if (!pkc->mandatory)
+ continue;
+
+ mpkgname = pkc->target;
+
+ if (!mpkgname)
+ break;
+ }
+ return mpkgname;
+}
+
+static void pkglist_check_cb(struct ubus_request *req, int type, struct blob_attr *msg)
+{
+ int *status = (int *)req->priv;
+ struct blob_attr *tb[__PACKAGES_MAX], *cur;
+ struct avl_pkg *pkg;
+ int rem;
+ int cmpres;
+ const char *pkgname;
+ struct package_changes *pkc;
+
+ blobmsg_parse(packages_policy, __PACKAGES_MAX, tb, blobmsg_data(msg), blobmsg_len(msg));
+
+ if (!tb[PACKAGES_PACKAGES])
+ return;
+
+ blobmsg_for_each_attr(cur, tb[PACKAGES_PACKAGES], rem) {
+ pkgname = blobmsg_name(cur);
+ if (is_builtin_pkg(pkgname))
+ continue;
+
+ pkgname = apply_package_changes(pkgname, true);
+ if (!pkgname) {
+ fprintf(stderr, " %s: %s%s -> (not installed)%s\n",
+ blobmsg_name(cur), ANSI_COLOR_BLUE,
+ blobmsg_get_string(cur), ANSI_COLOR_RESET);
+ continue;
+ }
+
+ pkg = avl_find_element(&pkg_tree, pkgname, pkg, avl);
+ if (!pkg) {
+ fprintf(stderr, "installed package %s%s%s cannot be found in remote list!\n",
+ ANSI_COLOR_RED, pkgname, ANSI_COLOR_RESET);
+ *status |= PKG_NOT_FOUND;
+ continue;
+ }
+
+ if (pkgname != blobmsg_name(cur)) {
+ fprintf(stderr, " %s%s: %s -> %s: %s%s\n", ANSI_COLOR_BLUE,
+ blobmsg_name(cur),
+ blobmsg_get_string(cur), pkgname, pkg->version,
+ ANSI_COLOR_RESET);
+ *status |= PKG_UPGRADE;
+ continue;
+ }
+
+ cmpres = verrevcmp(blobmsg_get_string(cur), pkg->version);
+ if (cmpres < 0)
+ *status |= PKG_UPGRADE;
+
+ if (cmpres > 0)
+ *status |= PKG_DOWNGRADE;
+
+ if (cmpres
+#ifdef AUC_DEBUG
+ || debug
+#endif
+ )
+ fprintf(stderr, " %s: %s%s -> %s%s\n", blobmsg_name(cur),
+ (!cmpres)?"":(cmpres > 0)?ANSI_COLOR_RED:ANSI_COLOR_GREEN,
+ blobmsg_get_string(cur), pkg->version,
+ (cmpres)?ANSI_COLOR_RESET:"");
+ }
+
+ list_for_each_entry(pkc, &selected_package_changes, list) {
+ /* deal only with package_change additions now */
+ if (pkc->source)
+ continue;
+
+ pkg = avl_find_element(&pkg_tree, pkc->target, pkg, avl);
+ if (!pkg) {
+ fprintf(stderr, "new package %s%s%s cannot be found in remote list!\n",
+ ANSI_COLOR_RED, pkc->target, ANSI_COLOR_RESET);
+ *status |= PKG_NOT_FOUND;
+ continue;
+ }
+ fprintf(stderr, " %s: %s(not installed) -> %s%s\n", pkc->target, ANSI_COLOR_BLUE,
+ pkg->version, ANSI_COLOR_RESET);
+ }
+}
+
+/*
+ * rpc-sys packagelist
+ * append array of package names to blobbuf given in req->priv
+ */
+static void pkglist_req_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
+ struct blob_buf *buf = (struct blob_buf *)req->priv;
+ struct blob_attr *tb[__PACKAGES_MAX];
+ struct blob_attr *cur;
+ int rem;
+ struct avl_pkg *pkg;
+ void *table;
+ const char *pkgname;
+ struct package_changes *pkc;
+
+ blobmsg_parse(packages_policy, __PACKAGES_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[PACKAGES_PACKAGES]) {
+ fprintf(stderr, "No packagelist received\n");
+ return;
+ }
+
+ table = blobmsg_open_table(buf, "packages_versions");
+
+ blobmsg_for_each_attr(cur, tb[PACKAGES_PACKAGES], rem) {
+ pkgname = blobmsg_name(cur);
+ if (is_builtin_pkg(pkgname))
+ continue;
+
+ pkgname = apply_package_changes(pkgname, false);
+ pkg = avl_find_element(&pkg_tree, pkgname, pkg, avl);
+ if (!pkg)
+ continue;
+
+ blobmsg_add_string(buf, pkgname, pkg->version);
+ }
+
+ list_for_each_entry(pkc, &selected_package_changes, list) {
+ /* add new packages to request */
+ if (pkc->source)
+ continue;
+
+ pkg = avl_find_element(&pkg_tree, pkc->target, pkg, avl);
+ if (!pkg)
+ continue;
+
+ blobmsg_add_string(buf, pkc->target, pkg->version);
+ }
+ blobmsg_close_table(buf, table);
+};
+
+/*
+ * system board
+ * append append board information to blobbuf given in req->priv
+ * populate board and release global strings
+ */
+static void board_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
+ struct blob_buf *buf = (struct blob_buf *)req->priv;
+ struct blob_attr *tb[__BOARD_MAX];
+ struct blob_attr *rel[__RELEASE_MAX];
+
+ blobmsg_parse(board_policy, __BOARD_MAX, tb, blob_data(msg), blob_len(msg));
+
+
+ if (!tb[BOARD_RELEASE]) {
+ fprintf(stderr, "No release received\n");
+ rc=-ENODATA;
+ return;
+ }
+
+ blobmsg_parse(release_policy, __RELEASE_MAX, rel,
+ blobmsg_data(tb[BOARD_RELEASE]), blobmsg_data_len(tb[BOARD_RELEASE]));
+
+ if (!rel[RELEASE_TARGET] ||
+ !rel[RELEASE_DISTRIBUTION] ||
+ !rel[RELEASE_VERSION] ||
+ !rel[RELEASE_REVISION]) {
+ fprintf(stderr, "No release information received\n");
+ rc=-ENODATA;
+ return;
+ }
+
+ target = strdup(blobmsg_get_string(rel[RELEASE_TARGET]));
+ distribution = strdup(blobmsg_get_string(rel[RELEASE_DISTRIBUTION]));
+ version = strdup(blobmsg_get_string(rel[RELEASE_VERSION]));
+ revision = strdup(blobmsg_get_string(rel[RELEASE_REVISION]));
+
+ if (!strcmp(target, "x86/64") || !strcmp(target, "x86/generic")) {
+ /*
+ * ugly work-around ahead:
+ * ignore board name on generic x86 targets, as image name is always 'generic'
+ */
+ board_name = strdup("generic");
+ } else {
+ if (!tb[BOARD_BOARD_NAME]) {
+ fprintf(stderr, "No board name received\n");
+ rc=-ENODATA;
+ return;
+ }
+ board_name = strdup(blobmsg_get_string(tb[BOARD_BOARD_NAME]));
+ }
+
+ if (tb[BOARD_ROOTFS_TYPE])
+ rootfs_type = strdup(blobmsg_get_string(tb[BOARD_ROOTFS_TYPE]));
+
+ blobmsg_add_string(buf, "target", target);
+ blobmsg_add_string(buf, "version", version);
+ blobmsg_add_string(buf, "revision", revision);
+}
+
+/*
+ * rpc-sys upgrade_test
+ * check if downloaded file is accepted by sysupgrade
+ */
+static void upgtest_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
+ int *valid = (int *)req->priv;
+ struct blob_attr *tb[__UPGTEST_MAX];
+
+ blobmsg_parse(upgtest_policy, __UPGTEST_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[UPGTEST_CODE]) {
+ fprintf(stderr, "No sysupgrade test return code received\n");
+ return;
+ }
+
+ *valid = (blobmsg_get_u32(tb[UPGTEST_CODE]) == 0)?1:0;
+
+ if (tb[UPGTEST_STDERR])
+ fprintf(stderr, "%s", blobmsg_get_string(tb[UPGTEST_STDERR]));
+ else if (*valid == 0)
+ fprintf(stderr, "image verification failed\n");
+ else
+ fprintf(stderr, "image verification succeeded\n");
+};
+
+/**
+ * uclient stuff
+ */
+static int open_output_file(const char *path, uint64_t resume_offset)
+{
+ char *filename = NULL;
+ int flags;
+ int ret;
+
+ if (cur_resume)
+ flags = O_RDWR;
+ else
+ flags = O_WRONLY | O_EXCL;
+
+ flags |= O_CREAT;
+
+ filename = uclient_get_url_filename(path, "firmware.bin");
+
+ fprintf(stderr, "Writing to '%s'\n", filename);
+ ret = open(filename, flags, 0644);
+ if (ret < 0)
+ goto free;
+
+ if (resume_offset &&
+ lseek(ret, resume_offset, SEEK_SET) < 0) {
+ fprintf(stderr, "Failed to seek %"PRIu64" bytes in output file\n", resume_offset);
+ close(ret);
+ ret = -1;
+ goto free;
+ }
+
+ out_offset = resume_offset;
+ out_bytes += resume_offset;
+
+free:
+ free(filename);
+ return ret;
+}
+
+struct jsonblobber {
+ json_tokener *tok;
+ struct blob_buf *outbuf;
+};
+
+static void request_done(struct uclient *cl)
+{
+ struct jsonblobber *jsb = (struct jsonblobber *)cl->priv;
+ if (jsb) {
+ json_tokener_free(jsb->tok);
+ free(jsb);
+ };
+
+ uclient_disconnect(cl);
+ uloop_end();
+}
+
+static void header_done_cb(struct uclient *cl)
+{
+ struct blob_attr *tb[__H_MAX];
+ struct jsonblobber *jsb = (struct jsonblobber *)cl->priv;
+ struct blob_buf *outbuf = NULL;
+
+ if (jsb)
+ outbuf = jsb->outbuf;
+
+ uint64_t resume_offset = 0, resume_end, resume_size;
+
+ if (uclient_http_redirect(cl)) {
+ fprintf(stderr, "Redirected to %s on %s\n", cl->url->location, cl->url->host);
+
+ return;
+ }
+
+ if (cl->status_code == 204 && cur_resume) {
+ /* Resume attempt failed, try normal download */
+ cur_resume = false;
+ //init_request(cl);
+ return;
+ }
+
+ DPRINTF("status code: %d\n", cl->status_code);
+ DPRINTF("headers:\n%s\n", blobmsg_format_json_indent(cl->meta, true, 0));
+ blobmsg_parse(header_policy, __H_MAX, tb, blob_data(cl->meta), blob_len(cl->meta));
+
+ switch (cl->status_code) {
+ case 400:
+ request_done(cl);
+ rc=-ESRCH;
+ break;
+ case 422:
+ fprintf(stderr, "unknown package '%s' requested.\n",
+ blobmsg_get_string(tb[H_UNKNOWN_PACKAGE]));
+ rc=-ENOPKG;
+ request_done(cl);
+ break;
+ case 201:
+ case 202:
+ retry = true;
+ if (!outbuf)
+ break;
+
+ blobmsg_add_u32(outbuf, "status", cl->status_code);
+
+ if (tb[H_QUEUE_POSITION])
+ blobmsg_add_u32(outbuf, "queue_position", blobmsg_get_u32(tb[H_QUEUE_POSITION]));
+
+ break;
+ case 200:
+ retry = false;
+ if (cl->priv)
+ break;
+
+ if (tb[H_LEN])
+ out_len = strtoul(blobmsg_get_string(tb[H_LEN]), NULL, 10);
+
+ output_fd = open_output_file(cl->url->location, resume_offset);
+ if (output_fd < 0) {
+ perror("Cannot open output file");
+ request_done(cl);
+ }
+ break;
+ case 500:
+ /* server may reply JSON object */
+ break;
+
+ default:
+ DPRINTF("HTTP error %d\n", cl->status_code);
+ request_done(cl);
+ break;
+ }
+}
+
+static void read_data_cb(struct uclient *cl)
+{
+ char buf[256];
+ int len;
+ json_object *jsobj;
+ struct blob_buf *outbuf = NULL;
+ json_tokener *tok = NULL;
+ struct jsonblobber *jsb = (struct jsonblobber *)cl->priv;
+
+ if (!jsb) {
+ while (1) {
+ len = uclient_read(cl, buf, sizeof(buf));
+ if (!len)
+ return;
+
+ out_bytes += len;
+ write(output_fd, buf, len);
+ }
+ return;
+ }
+
+ outbuf = jsb->outbuf;
+ tok = jsb->tok;
+
+ while (1) {
+ len = uclient_read(cl, buf, sizeof(buf));
+ if (!len)
+ break;
+
+ out_bytes += len;
+
+ jsobj = json_tokener_parse_ex(tok, buf, len);
+
+ if (json_tokener_get_error(tok) == json_tokener_continue)
+ continue;
+
+ if (json_tokener_get_error(tok) != json_tokener_success)
+ break;
+
+ if (jsobj)
+ {
+ blobmsg_add_json_element(outbuf, "reply", jsobj);
+
+ json_object_put(jsobj);
+ break;
+ }
+ }
+}
+
+static void eof_cb(struct uclient *cl)
+{
+ if (!cl->data_eof && !uptodate) {
+ fprintf(stderr, "Connection reset prematurely\n");
+ }
+ request_done(cl);
+}
+
+static void handle_uclient_error(struct uclient *cl, int code)
+{
+ const char *type = "Unknown error";
+
+ switch(code) {
+ case UCLIENT_ERROR_CONNECT:
+ type = "Connection failed";
+ break;
+ case UCLIENT_ERROR_TIMEDOUT:
+ type = "Connection timed out";
+ break;
+ case UCLIENT_ERROR_SSL_INVALID_CERT:
+ type = "Invalid SSL certificate";
+ break;
+ case UCLIENT_ERROR_SSL_CN_MISMATCH:
+ type = "Server hostname does not match SSL certificate";
+ break;
+ default:
+ break;
+ }
+
+ fprintf(stderr, "Connection error: %s\n", type);
+
+ request_done(cl);
+}
+
+static const struct uclient_cb check_cb = {
+ .header_done = header_done_cb,
+ .data_read = read_data_cb,
+ .data_eof = eof_cb,
+ .error = handle_uclient_error,
+};
+
+static int server_request(const char *url, struct blob_buf *inbuf, struct blob_buf *outbuf) {
+ struct jsonblobber *jsb = NULL;
+ int rc = -ENOENT;
+ char *post_data;
+ out_offset = 0;
+ out_bytes = 0;
+ out_len = 0;
+
+#ifdef AUC_DEBUG
+ if (debug)
+ fprintf(stderr, "Requesting URL: %s\n", url);
+#endif
+
+ if (outbuf) {
+ jsb = malloc(sizeof(struct jsonblobber));
+ jsb->outbuf = outbuf;
+ jsb->tok = json_tokener_new();
+ };
+
+ if (!ucl) {
+ ucl = uclient_new(url, NULL, &check_cb);
+ uclient_http_set_ssl_ctx(ucl, ssl_ops, ssl_ctx, 1);
+ ucl->timeout_msecs = REQ_TIMEOUT * 1000;
+ } else {
+ uclient_set_url(ucl, url, NULL);
+ }
+
+ ucl->priv = jsb;
+
+ rc = uclient_connect(ucl);
+ if (rc)
+ return rc;
+
+ rc = uclient_http_set_request_type(ucl, inbuf?"POST":"GET");
+ if (rc)
+ return rc;
+
+ uclient_http_reset_headers(ucl);
+ uclient_http_set_header(ucl, "User-Agent", user_agent);
+ if (inbuf) {
+ uclient_http_set_header(ucl, "Content-Type", "application/json");
+ post_data = blobmsg_format_json(inbuf->head, true);
+ uclient_write(ucl, post_data, strlen(post_data));
+ }
+ rc = uclient_request(ucl);
+ if (rc)
+ return rc;
+
+ uloop_run();
+
+ return 0;
+}
+
+/**
+ * ustream-ssl
+ */
+static int init_ustream_ssl(void) {
+ glob_t gl;
+ int i;
+
+ dlh = dlopen("libustream-ssl.so", RTLD_LAZY | RTLD_LOCAL);
+ if (!dlh)
+ return -ENOENT;
+
+ ssl_ops = dlsym(dlh, "ustream_ssl_ops");
+ if (!ssl_ops)
+ return -ENOENT;
+
+ ssl_ctx = ssl_ops->context_new(false);
+
+ glob("/etc/ssl/certs/*.crt", 0, NULL, &gl);
+ if (!gl.gl_pathc)
+ return -ENOKEY;
+
+ for (i = 0; i < gl.gl_pathc; i++)
+ ssl_ops->context_add_ca_crt_file(ssl_ctx, gl.gl_pathv[i]);
+
+ return 0;
+}
+
+static char* alloc_replace_var(char *in, const char *var, const char *replace)
+{
+ char *tmp = in;
+ char *res = NULL;
+ char *eptr;
+
+ while ((tmp = strchr(tmp, '{'))) {
+ ++tmp;
+ eptr = strchr(tmp, '}');
+ if (!eptr)
+ return NULL;
+
+ if (!strncmp(tmp, var, (unsigned int)(eptr - tmp))) {
+ asprintf(&res, "%.*s%s%s",
+ (unsigned int)(tmp - in) - 1, in, replace, eptr + 1);
+ break;
+ }
+ }
+
+ if (!res)
+ res = strdup(in);
+
+ return res;
+}
+
+static int request_target(struct branch_version *bver, char *url)
+{
+ static struct blob_buf boardbuf;
+ struct blob_attr *tbr[__REPLY_MAX], *tb[__TARGET_MAX];
+
+ blobmsg_buf_init(&boardbuf);
+
+ if ((rc = server_request(url, NULL, &boardbuf))) {
+ blob_buf_free(&boardbuf);
+ return rc;
+ }
+
+ blobmsg_parse(reply_policy, __REPLY_MAX, tbr, blob_data(boardbuf.head), blob_len(boardbuf.head));
+
+ if (!tbr[REPLY_OBJECT])
+ return -ENODATA;
+
+ blobmsg_parse(target_policy, __TARGET_MAX, tb, blobmsg_data(tbr[REPLY_OBJECT]), blobmsg_len(tbr[REPLY_OBJECT]));
+
+ if (!tb[TARGET_METADATA_VERSION] ||
+ !tb[TARGET_ARCH_PACKAGES] ||
+ !tb[TARGET_IMAGES] ||
+ !tb[TARGET_TARGET]) {
+ blob_buf_free(&boardbuf);
+ return -ENODATA;
+ }
+
+ if (blobmsg_get_u32(tb[TARGET_METADATA_VERSION]) != 1) {
+ blob_buf_free(&boardbuf);
+ return -EPFNOSUPPORT;
+ }
+
+ if (strcmp(blobmsg_get_string(tb[TARGET_TARGET]), target))
+ return -EINVAL;
+
+ if (strcmp(blobmsg_get_string(tb[TARGET_ARCH_PACKAGES]), bver->branch->arch_packages))
+ return -EINVAL;
+
+ if (tb[TARGET_VERSION_CODE])
+ bver->version_code = strdup(blobmsg_get_string(tb[TARGET_VERSION_CODE]));
+
+ if (tb[TARGET_VERSION_NUMBER])
+ bver->version_number = strdup(blobmsg_get_string(tb[TARGET_VERSION_NUMBER]));
+
+ blob_buf_free(&boardbuf);
+ return 0;
+};
+
+static char* validate_target(struct blob_attr *branch)
+{
+ struct blob_attr *cur;
+ int rem;
+
+ blobmsg_for_each_attr(cur, branch, rem)
+ if (!strcmp(blobmsg_name(cur), target))
+ return strdup(blobmsg_get_string(cur));
+
+ return NULL;
+}
+
+static void process_branch(struct blob_attr *branch, bool only_active)
+{
+ struct blob_attr *tb[__BRANCH_MAX], *pkc[__PACKAGE_CHANGES_MAX];
+ struct blob_attr *curver, *curpkc;
+ int remver, rempkc;
+ struct branch *br;
+ struct package_changes *pkce;
+ char *tmp, *board_json_file;
+ const char *brname;
+
+ blobmsg_parse(branches_policy, __BRANCH_MAX, tb, blobmsg_data(branch), blobmsg_len(branch));
+
+ /* mandatory fields */
+ if (!(tb[BRANCH_ENABLED] && blobmsg_get_bool(tb[BRANCH_ENABLED]) &&
+ tb[BRANCH_NAME] && tb[BRANCH_PATH] && tb[BRANCH_PATH_PACKAGES] &&
+ tb[BRANCH_VERSIONS] && tb[BRANCH_TARGETS]))
+ return;
+
+ brname = blobmsg_get_string(tb[BRANCH_NAME]);
+ if (only_active && strncmp(brname, version, strlen(brname)))
+ return;
+
+ br = calloc(1, sizeof(struct branch));
+ avl_init(&br->versions, avl_verrevcmp, false, NULL);
+ INIT_LIST_HEAD(&br->package_changes);
+
+ /* check if target is offered in branch and get arch_packages */
+ br->arch_packages = validate_target(tb[BRANCH_TARGETS]);
+ if (!br->arch_packages) {
+ free(br);
+ return;
+ }
+
+ if (tb[BRANCH_GIT_BRANCH])
+ br->git_branch = strdup(blobmsg_get_string(tb[BRANCH_GIT_BRANCH]));
+
+ if (tb[BRANCH_BRANCH_OFF_REV])
+ br->branch_off_rev = blobmsg_get_u32(tb[BRANCH_BRANCH_OFF_REV]);
+ else
+ br->branch_off_rev = 0;
+
+ if (tb[BRANCH_SNAPSHOT])
+ br->snapshot = blobmsg_get_bool(tb[BRANCH_SNAPSHOT]);
+ else
+ br->snapshot = false;
+
+ br->name = strdup(blobmsg_get_string(tb[BRANCH_NAME]));
+ br->path_packages = alloc_replace_var(blobmsg_get_string(tb[BRANCH_PATH_PACKAGES]), "branch", br->name);
+ if (!br->path_packages) {
+ free(br->name);
+ free(br->arch_packages);
+ free(br);
+ return;
+ }
+
+ /* parse package changes */
+ blobmsg_for_each_attr(curpkc, tb[BRANCH_PACKAGE_CHANGES], rempkc) {
+ if (blobmsg_type(curpkc) != BLOBMSG_TYPE_TABLE)
+ continue;
+
+ blobmsg_parse(package_changes_policy, __PACKAGE_CHANGES_MAX, pkc, blobmsg_data(curpkc), blobmsg_len(curpkc));
+ if (!pkc[PACKAGE_CHANGES_REVISION] || (!pkc[PACKAGE_CHANGES_SOURCE] && !pkc[PACKAGE_CHANGES_TARGET]))
+ continue;
+
+ pkce = calloc(1, sizeof(struct package_changes));
+ if (!pkce)
+ break;
+
+ if (pkc[PACKAGE_CHANGES_SOURCE])
+ pkce->source = strdup(blobmsg_get_string(pkc[PACKAGE_CHANGES_SOURCE]));
+
+ if (pkc[PACKAGE_CHANGES_TARGET])
+ pkce->target = strdup(blobmsg_get_string(pkc[PACKAGE_CHANGES_TARGET]));
+
+ pkce->revision = blobmsg_get_u32(pkc[PACKAGE_CHANGES_REVISION]);
+
+ if (pkc[PACKAGE_CHANGES_MANDATORY])
+ pkce->mandatory = blobmsg_get_bool(pkc[PACKAGE_CHANGES_MANDATORY]);
+
+ list_add_tail(&pkce->list, &br->package_changes);
+ }
+
+ /* add each version of the branch */
+ blobmsg_for_each_attr(curver, tb[BRANCH_VERSIONS], remver) {
+ if (blobmsg_type(curver) != BLOBMSG_TYPE_STRING)
+ continue;
+
+ struct branch_version *bver = calloc(1, sizeof(struct branch_version));
+ bver->snapshot = !!strcasestr(blobmsg_get_string(curver), "snapshot");
+ bver->path = alloc_replace_var(blobmsg_get_string(tb[BRANCH_PATH]), "version", blobmsg_get_string(curver));
+ if (!bver->path) {
+ free(bver);
+ continue;
+ }
+ bver->version = strdup(blobmsg_get_string(curver));
+ if (!bver->version) {
+ free(bver->path);
+ free(bver);
+ continue;
+ }
+ bver->branch = br;
+ if (asprintf(&board_json_file, "%s/%s/%s/%s/%s/%s/%s%s", serverurl, API_JSON,
+ API_JSON_VERSION, bver->path, API_TARGETS, target, board_name,
+ API_JSON_EXT) < 0) {
+ free(bver->version);
+ free(bver->path);
+ free(bver);
+ continue;
+ }
+ tmp = board_json_file;
+ while ((tmp = strchr(tmp, ',')))
+ *tmp = '_';
+
+ if (request_target(bver, board_json_file)) {
+ free(board_json_file);
+ free(bver->version);
+ free(bver->path);
+ free(bver);
+ continue;
+ }
+ free(board_json_file);
+ bver->avl.key = bver->version;
+ avl_insert(&br->versions, &bver->avl);
+ }
+
+ br->avl.key = br->name;
+ avl_insert(&branches, &br->avl);
+}
+
+static int request_branches(bool only_active)
+{
+ static struct blob_buf brbuf;
+ struct blob_attr *cur;
+ struct blob_attr *tb[__REPLY_MAX];
+ int rem;
+ char url[256];
+ struct blob_attr *data;
+
+ blobmsg_buf_init(&brbuf);
+ snprintf(url, sizeof(url), "%s/%s/%s/%s%s", serverurl, API_JSON,
+ API_JSON_VERSION, API_BRANCHES, API_JSON_EXT);
+
+ if ((rc = server_request(url, NULL, &brbuf))) {
+ blob_buf_free(&brbuf);
+ return rc;
+ };
+
+ blobmsg_parse(reply_policy, __REPLY_MAX, tb, blob_data(brbuf.head), blob_len(brbuf.head));
+
+ /* newer server API replies OBJECT, older API replies ARRAY... */
+ if ((!tb[REPLY_ARRAY] && !tb[REPLY_OBJECT]))
+ return -ENODATA;
+
+ if (tb[REPLY_OBJECT])
+ data = tb[REPLY_OBJECT];
+ else
+ data = tb[REPLY_ARRAY];
+
+ blobmsg_for_each_attr(cur, data, rem)
+ process_branch(cur, only_active);
+
+ blob_buf_free(&brbuf);
+
+ return 0;
+}
+
+static void free_branches()
+{
+ struct branch *br, *tmp;
+ struct branch_version *bver, *tmp2;
+ struct package_changes *pkce, *tmp3;
+
+ avl_for_each_element_safe(&branches, br, avl, tmp) {
+ free(br->name);
+ free(br->path_packages);
+ free(br->arch_packages);
+
+ avl_for_each_element_safe(&br->versions, bver, avl, tmp2) {
+ avl_delete(&br->versions, &bver->avl);
+ free(bver->version);
+ free(bver->version_code);
+ free(bver->version_number);
+ free(bver->path);
+ free(bver);
+ }
+
+ list_for_each_entry_safe(pkce, tmp3, &br->package_changes, list) {
+ list_del(&pkce->list);
+ free(pkce->source);
+ free(pkce->target);
+ free(pkce);
+ }
+
+ avl_delete(&branches, &br->avl);
+ }
+}
+
+static struct branch *get_current_branch()
+{
+ struct branch *br, *abr = NULL;
+
+ avl_for_each_element(&branches, br, avl) {
+ /* if branch name doesn't match version *prefix*, skip */
+ if (!strncasecmp(br->name, version, strlen(br->name))) {
+ abr = br;
+ break;
+ }
+ }
+
+ return abr;
+}
+
+static int revision_from_version_code(const char *version_code)
+{
+ int res;
+
+ if (sscanf(version_code, "r%d-", &res) == 1)
+ return res;
+
+ return -1;
+}
+
+static struct branch_version *select_branch(char *name, char *select_version)
+{
+ struct branch *br;
+ struct branch_version *bver, *abver = NULL;
+
+ if (!name)
+ name = version;
+
+ avl_for_each_element(&branches, br, avl) {
+ /* if branch name doesn't match version *prefix*, skip */
+ if (strncasecmp(br->name, name, strlen(br->name)))
+ continue;
+
+ avl_for_each_element(&br->versions, bver, avl) {
+ if (select_version) {
+ if (!strcasecmp(bver->version, select_version)) {
+ abver = bver;
+ break;
+ }
+ } else {
+ if (!strcasecmp(name, "snapshot")) {
+ /* we are on the main snapshot branch */
+ if (br->snapshot && bver->snapshot) {
+ abver = bver;
+ break;
+ }
+ } else {
+ /* skip main snapshot branch */
+ if (br->snapshot)
+ continue;
+
+ if (strcasestr(version, "snapshot")) {
+ /* we are on a stable snapshot branch or coming from main snapshot branch */
+ if (bver->snapshot) {
+ abver = bver;
+ break;
+ }
+ } else {
+ if (bver->snapshot)
+ continue;
+
+ if (!abver || (openwrt_release_verrevcmp(abver->version, bver->version) < 0))
+ abver = bver;
+ }
+ }
+ }
+ }
+ if (abver)
+ break;
+ }
+
+ return abver;
+}
+
+static int add_upg_packages(struct blob_attr *reply, char *arch)
+{
+ struct blob_attr *tbr[__REPLY_MAX];
+ struct blob_attr *tba[__PACKAGES_MAX];
+ struct blob_attr *packages;
+ struct blob_attr *cur;
+ int rem;
+ struct avl_pkg *avpk;
+
+ blobmsg_parse(reply_policy, __REPLY_MAX, tbr, blob_data(reply), blob_len(reply));
+
+ if (!tbr[REPLY_OBJECT])
+ return -ENODATA;
+
+ if (arch) {
+ blobmsg_parse(packages_policy, __PACKAGES_MAX, tba, blobmsg_data(tbr[REPLY_OBJECT]), blobmsg_len(tbr[REPLY_OBJECT]));
+ if (!tba[PACKAGES_ARCHITECTURE] ||
+ !tba[PACKAGES_PACKAGES])
+ return -ENODATA;
+
+ if (strcmp(blobmsg_get_string(tba[PACKAGES_ARCHITECTURE]), arch))
+ return -EBADMSG;
+
+ packages = tba[PACKAGES_PACKAGES];
+ } else {
+ packages = tbr[REPLY_OBJECT];
+ }
+
+ blobmsg_for_each_attr(cur, packages, rem) {
+ avpk = calloc(1, sizeof(struct avl_pkg));
+ if (!avpk)
+ return -ENOMEM;
+
+ avpk->name = strdup(blobmsg_name(cur));
+ if (!avpk->name) {
+ free(avpk);
+ return -ENOMEM;
+ }
+
+ avpk->version = strdup(blobmsg_get_string(cur));
+ if (!avpk->version) {
+ free(avpk->name);
+ free(avpk);
+ return -ENOMEM;
+ }
+
+ avpk->avl.key = avpk->name;
+ if (avl_insert(&pkg_tree, &avpk->avl)) {
+
+#ifdef AUC_DEBUG
+ if (debug)
+ fprintf(stderr, "failed to insert package %s (%s)!\n", blobmsg_name(cur), blobmsg_get_string(cur));
+#endif
+
+ if (avpk->name)
+ free(avpk->name);
+
+ if (avpk->version)
+ free(avpk->version);
+
+ free(avpk);
+ }
+ }
+
+ return 0;
+}
+
+static int request_packages(struct branch_version *bver)
+{
+ static struct blob_buf pkgbuf, archpkgbuf;
+ char url[256];
+ int ret;
+
+ fprintf(stderr, "Requesting package lists...\n");
+
+ blobmsg_buf_init(&archpkgbuf);
+ snprintf(url, sizeof(url), "%s/%s/%s/%s/%s/%s/%s%s", serverurl, API_JSON,
+ API_JSON_VERSION, bver->path, API_TARGETS, target, API_INDEX, API_JSON_EXT);
+ if ((rc = server_request(url, NULL, &archpkgbuf))) {
+ blob_buf_free(&archpkgbuf);
+ return rc;
+ };
+
+ ret = add_upg_packages(archpkgbuf.head, bver->branch->arch_packages);
+ blob_buf_free(&archpkgbuf);
+
+ if (ret)
+ return ret;
+
+ blobmsg_buf_init(&pkgbuf);
+ snprintf(url, sizeof(url), "%s/%s/%s/%s/%s/%s-%s%s", serverurl, API_JSON,
+ API_JSON_VERSION, bver->path, API_PACKAGES, bver->branch->arch_packages,
+ API_INDEX, API_JSON_EXT);
+ if ((rc = server_request(url, NULL, &pkgbuf))) {
+ blob_buf_free(&archpkgbuf);
+ blob_buf_free(&pkgbuf);
+ return rc;
+ };
+
+ ret = add_upg_packages(pkgbuf.head, NULL);
+ blob_buf_free(&pkgbuf);
+
+ return ret;
+}
+
+
+static int check_installed_packages(void)
+{
+ static struct blob_buf allpkg;
+ uint32_t id;
+ int status = 0;
+
+ blob_buf_init(&allpkg, 0);
+ blobmsg_add_u8(&allpkg, "all", 1);
+ blobmsg_add_string(&allpkg, "dummy", "foo");
+ if (ubus_lookup_id(ctx, "rpc-sys", &id) ||
+ ubus_invoke(ctx, id, "packagelist", allpkg.head, pkglist_check_cb, &status, 3000)) {
+ fprintf(stderr, "cannot request packagelist from rpcd\n");
+ status |= PKG_ERROR;
+ }
+
+ return status;
+}
+
+static int req_add_selected_packages(struct blob_buf *req)
+{
+ static struct blob_buf allpkg;
+ uint32_t id;
+
+ blob_buf_init(&allpkg, 0);
+ blobmsg_add_u8(&allpkg, "all", 0);
+ blobmsg_add_string(&allpkg, "dummy", "foo");
+ if (ubus_lookup_id(ctx, "rpc-sys", &id) ||
+ ubus_invoke(ctx, id, "packagelist", allpkg.head, pkglist_req_cb, req, 3000)) {
+ fprintf(stderr, "cannot request packagelist from rpcd\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+#if defined(__amd64__) || defined(__i386__)
+static int system_is_efi(void)
+{
+ const char efidname[] = "/sys/firmware/efi/efivars";
+ int fd = open(efidname, O_DIRECTORY | O_PATH);
+
+ if (fd != -1) {
+ close(fd);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+#else
+static inline int system_is_efi(void) { return 0; }
+#endif
+
+static int get_image_by_type(struct blob_attr *images, const char *typestr, const char *fstype, char **image_name, char **image_sha256)
+{
+ struct blob_attr *tb[__IMAGES_MAX];
+ struct blob_attr *cur;
+ int rem, ret = -ENOENT;
+
+ blobmsg_for_each_attr(cur, images, rem) {
+ blobmsg_parse(images_policy, __IMAGES_MAX, tb, blobmsg_data(cur), blobmsg_len(cur));
+ if (!tb[IMAGES_FILESYSTEM] ||
+ !tb[IMAGES_NAME] ||
+ !tb[IMAGES_TYPE] ||
+ !tb[IMAGES_SHA256])
+ continue;
+
+ if (fstype && strcmp(blobmsg_get_string(tb[IMAGES_FILESYSTEM]), fstype))
+ continue;
+
+ if (!strcmp(blobmsg_get_string(tb[IMAGES_TYPE]), typestr)) {
+ *image_name = strdup(blobmsg_get_string(tb[IMAGES_NAME]));
+ *image_sha256 = strdup(blobmsg_get_string(tb[IMAGES_SHA256]));
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int select_image(struct blob_attr *images, const char *target_fstype, char **image_name, char **image_sha256)
+{
+ const char *combined_type;
+ const char *fstype = rootfs_type;
+ int ret = -ENOENT;
+
+ if (target_fstype)
+ fstype = target_fstype;
+
+ if (system_is_efi())
+ combined_type = "combined-efi";
+ else
+ combined_type = "combined";
+
+ DPRINTF("images: %s\n", blobmsg_format_json_indent(images, true, 0));
+
+ if (fstype) {
+ ret = get_image_by_type(images, "sysupgrade", fstype, image_name, image_sha256);
+ if (!ret)
+ return 0;
+
+ ret = get_image_by_type(images, combined_type, fstype, image_name, image_sha256);
+ if (!ret)
+ return 0;
+
+ ret = get_image_by_type(images, "sdcard", fstype, image_name, image_sha256);
+ if (!ret)
+ return 0;
+ }
+
+ /* fallback to squashfs unless fstype requested explicitly */
+ if (!target_fstype) {
+ ret = get_image_by_type(images, "sysupgrade", "squashfs", image_name, image_sha256);
+ if (!ret)
+ return 0;
+
+ ret = get_image_by_type(images, combined_type, "squashfs", image_name, image_sha256);
+ if (!ret)
+ return 0;
+
+ ret = get_image_by_type(images, "sdcard", fstype, image_name, image_sha256);
+ }
+
+ return ret;
+}
+
+static bool validate_sha256(char *filename, char *sha256str)
+{
+ char *cmd = calloc(strlen(SHA256SUM) + 1 + strlen(filename) + 1, sizeof(char));
+ size_t reslen = (64 + 2 + strlen(filename) + 1) * sizeof(char);
+ char *resstr = malloc(reslen);
+ FILE *f;
+ bool ret = false;
+
+ strcpy(cmd, SHA256SUM);
+ strcat(cmd, " ");
+ strcat(cmd, filename);
+
+ f = popen(cmd, "r");
+ if (!f)
+ goto sha256free;
+
+ if (fread(resstr, reslen, 1, f) < 1)
+ goto sha256close;
+
+ if (!strncmp(sha256str, resstr, 64))
+ ret = true;
+
+sha256close:
+ fflush(f);
+ pclose(f);
+sha256free:
+ free(cmd);
+ free(resstr);
+
+ return ret;
+}
+
+static inline bool status_delay(const char *status)
+{
+ return !strcmp(API_STATUS_QUEUED, status) ||
+ !strcmp(API_STATUS_STARTED, status);
+}
+
+static void usage(const char *arg0)
+{
+ fprintf(stdout, "%s: Attended sysUpgrade CLI client\n", arg0);
+ fprintf(stdout, "Usage: auc [-b <branch>] [-B <ver>] [-c] %s[-f] [-h] [-r] [-y]\n",
+#ifdef AUC_DEBUG
+"[-d] "
+#else
+""
+#endif
+ );
+ fprintf(stdout, " -b <branch>\tuse specific release branch\n");
+ fprintf(stdout, " -B <ver>\tuse specific release version\n");
+ fprintf(stdout, " -c\t\tonly check if system is up-to-date\n");
+#ifdef AUC_DEBUG
+ fprintf(stdout, " -d\t\tenable debugging output\n");
+#endif
+ fprintf(stdout, " -f\t\tuse force\n");
+ fprintf(stdout, " -h\t\toutput help\n");
+ fprintf(stdout, " -n\t\tdry-run (don't download or upgrade)\n");
+ fprintf(stdout, " -r\t\tcheck only for release upgrades\n");
+ fprintf(stdout, " -F <fstype>\toverride filesystem type\n");
+ fprintf(stdout, " -y\t\tdon't wait for user confirmation\n");
+ fprintf(stdout, "\n");
+ fprintf(stdout, "Please report issues to improve the server:\n");
+ fprintf(stdout, "%s\n", server_issues);
+}
+
+
+/* this main function is too big... todo: split */
+int main(int args, char *argv[]) {
+ static struct blob_buf checkbuf, infobuf, reqbuf, imgbuf, upgbuf;
+ struct branch *current_branch, *running_branch;
+ struct branch_version *target_version;
+ int running_revision, covered_revision = 0;
+ uint32_t id;
+ int valid;
+ char url[256];
+ char *sanetized_board_name, *image_name, *image_sha256, *tmp;
+ char *cmd_target_branch = NULL, *cmd_target_version = NULL, *cmd_target_fstype = NULL;
+ struct blob_attr *tbr[__REPLY_MAX];
+ struct blob_attr *tb[__TARGET_MAX] = {}; /* make sure tb is NULL initialized even if blobmsg_parse isn't called */
+ struct stat imgstat;
+ bool check_only = false;
+ bool retry_delay = false;
+ bool upg_check = false;
+ bool dry_run = false;
+ int revcmp;
+ int addargs;
+ unsigned char argc = 1;
+ bool force = false, use_get = false, in_queue = false, release_only = false;
+
+ snprintf(user_agent, sizeof(user_agent), "%s/%s", argv[0], AUC_VERSION);
+ fprintf(stdout, "%s\n", user_agent);
+
+ while (argc<args) {
+ if (!strncmp(argv[argc], "-h", 3) ||
+ !strncmp(argv[argc], "--help", 7)) {
+ usage(argv[0]);
+ return 0;
+ }
+
+ addargs = 0;
+#ifdef AUC_DEBUG
+ if (!strncmp(argv[argc], "-d", 3))
+ debug = 1;
+#endif
+ if (!strncmp(argv[argc], "-b", 3)) {
+ cmd_target_branch = argv[argc + 1];
+ addargs = 1;
+ }
+
+ if (!strncmp(argv[argc], "-B", 3)) {
+ cmd_target_version = argv[argc + 1];
+ addargs = 1;
+ }
+
+ if (!strncmp(argv[argc], "-c", 3))
+ check_only = true;
+
+ if (!strncmp(argv[argc], "-f", 3))
+ force = true;
+
+ if (!strncmp(argv[argc], "-F", 3)) {
+ cmd_target_fstype = argv[argc + 1];
+ addargs = 1;
+ }
+
+ if (!strncmp(argv[argc], "-n", 3))
+ dry_run = true;
+
+ if (!strncmp(argv[argc], "-r", 3))
+ release_only = true;
+
+ if (!strncmp(argv[argc], "-y", 3))
+ dont_ask = true;
+
+ argc += 1 + addargs;
+ };
+
+ if (load_config()) {
+ rc=-EFAULT;
+ goto freeubus;
+ }
+
+ if (chdir("/tmp")) {
+ rc=-EFAULT;
+ goto freeconfig;
+ }
+
+ if (!strncmp(serverurl, "https", 5)) {
+ rc = init_ustream_ssl();
+ if (rc == -2) {
+ fprintf(stderr, "No CA certificates loaded, please install ca-certificates\n");
+ rc=-1;
+ goto freessl;
+ }
+
+ if (rc || !ssl_ctx) {
+ fprintf(stderr, "SSL support not available, please install ustream-ssl\n");
+ rc=-EPROTONOSUPPORT;
+ goto freessl;
+ }
+ }
+
+ uloop_init();
+ ctx = ubus_connect(NULL);
+ if (!ctx) {
+ fprintf(stderr, "failed to connect to ubus.\n");
+ return -1;
+ }
+
+ blobmsg_buf_init(&checkbuf);
+ blobmsg_buf_init(&infobuf);
+ blobmsg_buf_init(&reqbuf);
+ blobmsg_buf_init(&imgbuf);
+ /* ubus requires BLOBMSG_TYPE_UNSPEC */
+ blob_buf_init(&upgbuf, 0);
+
+ if (ubus_lookup_id(ctx, "system", &id) ||
+ ubus_invoke(ctx, id, "board", NULL, board_cb, &checkbuf, 3000)) {
+ fprintf(stderr, "cannot request board info from procd\n");
+ rc=-EFAULT;
+ goto freebufs;
+ }
+
+ fprintf(stdout, "Server: %s\n", serverurl);
+ fprintf(stdout, "Running: %s %s on %s (%s)\n", version, revision, target, board_name);
+ if (cmd_target_fstype && rootfs_type && strcmp(rootfs_type, cmd_target_fstype))
+ fprintf(stderr, "WARNING: will change rootfs type from '%s' to '%s'\n",
+ rootfs_type, cmd_target_fstype);
+
+ if (request_branches(!(cmd_target_branch || cmd_target_version))) {
+ rc=-ENODATA;
+ goto freeboard;
+ }
+
+ running_branch = get_current_branch();
+ if (!running_branch)
+ fprintf(stderr, "WARNING: cannot determing currently running branch.\n");
+
+ target_version = select_branch(cmd_target_branch, cmd_target_version);
+ if (!target_version) {
+ rc=-EINVAL;
+ goto freebranches;
+ }
+
+ fprintf(stdout, "Available: %s %s\n", target_version->version_number, target_version->version_code);
+
+ revcmp = verrevcmp(revision, target_version->version_code);
+ if (revcmp < 0)
+ upg_check |= PKG_UPGRADE;
+ else if (revcmp > 0)
+ upg_check |= PKG_DOWNGRADE;
+
+ if (release_only && !(upg_check & PKG_UPGRADE)) {
+ fprintf(stderr, "Nothing to be updated. Use '-f' to force.\n");
+ rc = 0;
+ goto freebranches;
+ }
+
+ running_revision = revision_from_version_code(revision);
+ if (target_version->branch == running_branch)
+ grab_changes(running_branch, running_revision);
+ else avl_for_element_range(running_branch, target_version->branch, current_branch, avl) {
+ if (current_branch == running_branch)
+ grab_changes(running_branch, running_revision);
+ else
+ grab_changes(current_branch, covered_revision);
+
+ if (current_branch->branch_off_rev > 0)
+ covered_revision = current_branch->branch_off_rev;
+ }
+
+ if ((rc = request_packages(target_version)))
+ goto freebranches;
+
+ upg_check |= check_installed_packages();
+ if (upg_check & PKG_ERROR) {
+ rc = -ENOPKG;
+ goto freebranches;
+ }
+
+ if (!upg_check && !force) {
+ fprintf(stderr, "Nothing to be updated. Use '-f' to force.\n");
+ rc=0;
+ goto freebranches;
+ };
+
+ if (!force && (upg_check & PKG_DOWNGRADE)) {
+ fprintf(stderr, "Refusing to downgrade. Use '-f' to force.\n");
+ rc = -ENOTRECOVERABLE;
+ goto freebranches;
+ };
+
+ if (!force && (upg_check & PKG_NOT_FOUND)) {
+ fprintf(stderr, "Not all installed packages found in remote lists. Use '-f' to force.\n");
+ rc = -ENOTRECOVERABLE;
+ goto freebranches;
+ };
+
+ if (check_only)
+ goto freebranches;
+
+ if (!dont_ask) {
+ if (!ask_user("Are you sure you want to continue the upgrade process?")) {
+ rc = 0;
+ goto freebranches;
+ }
+ }
+
+ blobmsg_add_string(&reqbuf, "version", target_version->version);
+ blobmsg_add_string(&reqbuf, "version_code", target_version->version_code);
+ blobmsg_add_string(&reqbuf, "target", target);
+
+ if (cmd_target_fstype || rootfs_type)
+ blobmsg_add_string(&reqbuf, "filesystem", cmd_target_fstype?cmd_target_fstype:rootfs_type);
+
+ sanetized_board_name = strdup(board_name);
+ tmp = sanetized_board_name;
+ while ((tmp = strchr(tmp, ',')))
+ *tmp = '_';
+
+ blobmsg_add_string(&reqbuf, "profile", sanetized_board_name);
+ blobmsg_add_u8(&reqbuf, "diff_packages", 1);
+
+ req_add_selected_packages(&reqbuf);
+
+ snprintf(url, sizeof(url), "%s/%s", serverurl, API_REQUEST);
+
+ use_get = false;
+ do {
+ retry = false;
+
+ DPRINTF("requesting from %s\n%s%s", url, use_get?"":blobmsg_format_json_indent(reqbuf.head, true, 0), use_get?"":"\n");
+
+ rc = server_request(url, use_get?NULL:&reqbuf, &imgbuf);
+ if (rc)
+ break;
+
+ blobmsg_parse(reply_policy, __REPLY_MAX, tbr, blob_data(imgbuf.head), blob_len(imgbuf.head));
+ if (!tbr[REPLY_OBJECT])
+ break;
+
+ blobmsg_parse(target_policy, __TARGET_MAX, tb, blobmsg_data(tbr[REPLY_OBJECT]), blobmsg_len(tbr[REPLY_OBJECT]));
+
+ /* for compatibility with old server version, also support status in 200 reply */
+ if (tb[TARGET_STATUS]) {
+ tmp = blobmsg_get_string(tb[TARGET_STATUS]);
+ if (status_delay(tmp))
+ retry = 1;
+ }
+
+ if (tb[TARGET_REQUEST_HASH]) {
+ if (retry) {
+ if (!retry_delay)
+ fputs("Requesting build", stderr);
+
+ retry_delay = 2;
+ if (tb[TARGET_QUEUE_POSITION]) {
+ fprintf(stderr, "%s%s (position in queue: %d)",
+ ANSI_ESC, in_queue?ANSI_CURSOR_RESTORE:ANSI_CURSOR_SAFE,
+ blobmsg_get_u32(tb[TARGET_QUEUE_POSITION]));
+ in_queue = true;
+ } else {
+ if (in_queue)
+ fprintf(stderr, "%s%s%s%s",
+ ANSI_ESC, ANSI_CURSOR_RESTORE,
+ ANSI_ESC, ANSI_ERASE_LINE);
+ fputc('.', stderr);
+ in_queue = false;
+ }
+ } else {
+ retry_delay = 0;
+ }
+ if (!use_get) {
+ snprintf(url, sizeof(url), "%s/%s/%s", serverurl,
+ API_REQUEST,
+ blobmsg_get_string(tb[TARGET_REQUEST_HASH]));
+ DPRINTF("polling via GET %s\n", url);
+ }
+ use_get = true;
+ } else if (retry_delay) {
+ retry_delay = 0;
+ }
+
+#ifdef AUC_DEBUG
+ if (debug && tb[TARGET_STDOUT])
+ fputs(blobmsg_get_string(tb[TARGET_STDOUT]), stdout);
+
+ if (debug && tb[TARGET_STDERR])
+ fputs(blobmsg_get_string(tb[TARGET_STDERR]), stderr);
+#endif
+
+ if (retry) {
+ blob_buf_free(&imgbuf);
+ blobmsg_buf_init(&imgbuf);
+ sleep(retry_delay);
+ }
+ } while(retry);
+
+ free(sanetized_board_name);
+
+ if (!tb[TARGET_IMAGES] || !tb[TARGET_BINDIR]) {
+ if (!rc)
+ rc=-EBADMSG;
+ goto freebranches;
+ }
+
+ if ((rc = select_image(tb[TARGET_IMAGES], cmd_target_fstype, &image_name, &image_sha256)))
+ goto freebranches;
+
+ snprintf(url, sizeof(url), "%s/%s/%s/%s", serverurl, API_STORE,
+ blobmsg_get_string(tb[TARGET_BINDIR]),
+ image_name);
+
+ if (dry_run) {
+ fprintf(stderr, "\nImage available at %s\n", url);
+ rc = 0;
+ goto freebranches;
+ }
+
+ fprintf(stderr, "\nDownloading image from %s\n", url);
+ rc = server_request(url, NULL, NULL);
+ if (rc)
+ goto freebranches;
+
+ filename = uclient_get_url_filename(url, "firmware.bin");
+
+ if (stat(filename, &imgstat)) {
+ fprintf(stderr, "image download failed\n");
+ rc=-EPIPE;
+ goto freebranches;
+ }
+
+ if ((intmax_t)imgstat.st_size != out_len) {
+ fprintf(stderr, "file size mismatch\n");
+ unlink(filename);
+ rc=-EMSGSIZE;
+ goto freebranches;
+ }
+
+ if (!validate_sha256(filename, image_sha256)) {
+ fprintf(stderr, "sha256 mismatch\n");
+ unlink(filename);
+ rc=-EBADMSG;
+ goto freebranches;
+ }
+
+ if (strcmp(filename, "firmware.bin")) {
+ if (rename(filename, "firmware.bin")) {
+ fprintf(stderr, "can't rename to firmware.bin\n");
+ unlink(filename);
+ rc=-errno;
+ goto freebranches;
+ }
+ }
+
+ valid = 0;
+ if (ubus_lookup_id(ctx, "rpc-sys", &id) ||
+ ubus_invoke(ctx, id, "upgrade_test", NULL, upgtest_cb, &valid, 15000)) {
+ rc=-EFAULT;
+ goto freebranches;
+ }
+
+ if (!valid) {
+ rc=-EINVAL;
+ goto freebranches;
+ }
+
+ fprintf(stdout, "invoking sysupgrade\n");
+ blobmsg_add_u8(&upgbuf, "keep", 1);
+ ubus_invoke(ctx, id, "upgrade_start", upgbuf.head, NULL, NULL, 120000);
+ sleep(10);
+
+freebranches:
+ free_branches();
+ if (rc && tb[TARGET_STDOUT]
+#ifdef AUC_DEBUG
+ && !debug
+#endif
+ )
+ fputs(blobmsg_get_string(tb[TARGET_STDOUT]), stdout);
+ if (rc && tb[TARGET_STDERR]
+#ifdef AUC_DEBUG
+ && !debug
+#endif
+ )
+ fputs(blobmsg_get_string(tb[TARGET_STDERR]), stderr);
+
+ if (tb[TARGET_DETAIL]) {
+ fputs(blobmsg_get_string(tb[TARGET_DETAIL]), stderr);
+ fputc('\n', stderr);
+ }
+
+freeboard:
+ if (rootfs_type)
+ free(rootfs_type);
+
+ free(board_name);
+ free(target);
+ free(distribution);
+ free(version);
+
+freebufs:
+ blob_buf_free(&checkbuf);
+ blob_buf_free(&infobuf);
+ blob_buf_free(&reqbuf);
+ blob_buf_free(&imgbuf);
+ blob_buf_free(&upgbuf);
+
+freessl:
+ if (ssl_ctx)
+ ssl_ops->context_free(ssl_ctx);
+
+freeconfig:
+ free(serverurl);
+
+freeubus:
+ uloop_done();
+ ubus_free(ctx);
+
+ if (ucl)
+ uclient_free(ucl);
+
+ if (dlh)
+ dlclose(dlh);
+
+ if (rc)
+ fprintf(stderr, "%s (%d)\n", strerror(-1 * rc), -1 * rc);
+
+ return rc;
+}
diff --git a/external/subpack/utils/augeas/Makefile b/external/subpack/utils/augeas/Makefile
new file mode 100644
index 0000000..2afe0c4
--- /dev/null
+++ b/external/subpack/utils/augeas/Makefile
@@ -0,0 +1,97 @@
+#
+# Copyright (C) 2019 CZ.NIC, z. s. p. o. (https://www.nic.cz/)
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=augeas
+PKG_VERSION:=1.12.0
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://download.augeas.net/
+PKG_HASH:=321942c9cc32185e2e9cb72d0a70eea106635b50269075aca6714e3ec282cb87
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+PKG_LICENSE:=LGPL-2.1-or-later
+PKG_MAINTAINER:=Jan Pavlinec <jan.pavlinec@nic.cz>
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/augeas
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=A configuration editing tool
+ URL:=http://augeas.net
+ DEPENDS:=+libxml2 +libreadline +libncurses
+endef
+
+define Package/augeas/description
+ Augeas is a configuration editing tool.
+ It parses configuration files in their
+ native formats and transforms them into a tree.
+ Configuration changes are made by manipulating this
+ tree and saving it back into native config files.
+endef
+
+define Package/augeas-lenses
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Augeas lenses
+ URL:=http://augeas.net
+ DEPENDS:=+augeas
+endef
+
+define Package/augeas-lense/description
+ Set of Augeas lenses.
+endef
+
+CONFIGURE_ARGS+= \
+ --without-selinux
+
+define Package/augeas-lenses-tests
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Augeas lenses tests
+ URL:=http://augeas.net
+ DEPENDS:=+augeas
+endef
+
+define Package/augeas-lenses-tests/description
+ Set of tests for official Augeas lenses.
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/* $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/augeas/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/* $(1)/usr/lib/
+endef
+
+define Package/augeas-lenses/install
+ $(INSTALL_DIR) $(1)/usr/share/augeas/lenses/dist
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/augeas/lenses/dist/* $(1)/usr/share/augeas/lenses/dist/
+endef
+
+define Package/augeas-lenses-tests/install
+ $(INSTALL_DIR) $(1)/usr/share/augeas/lenses/dist/tests
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/augeas/lenses/dist/tests/* $(1)/usr/share/augeas/lenses/dist/tests
+endef
+
+$(eval $(call BuildPackage,augeas))
+$(eval $(call BuildPackage,augeas-lenses))
+$(eval $(call BuildPackage,augeas-lenses-tests))
diff --git a/external/subpack/utils/avrdude/Makefile b/external/subpack/utils/avrdude/Makefile
new file mode 100644
index 0000000..04f9b15
--- /dev/null
+++ b/external/subpack/utils/avrdude/Makefile
@@ -0,0 +1,60 @@
+#
+# Copyright (C) 2008-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=avrdude
+PKG_VERSION:=6.3
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SAVANNAH/$(PKG_NAME)
+PKG_HASH:=0f9f731b6394ca7795b88359689a7fa1fba818c6e1d962513eb28da670e0a196
+
+PKG_MAINTAINER:=Ted Hess <thess@kitschensync.net>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/avrdude
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Microcontroller programming
+ TITLE:=AVR Downloader/UploaDEr
+ URL:=https://www.nongnu.org/avrdude/
+ DEPENDS:=+libncurses +libreadline +libusb-compat +libftdi1 +libelf
+endef
+
+define Package/avrdude/description
+ AVRDUDE is a full featured program for programming Atmel's AVR CPU's.
+endef
+
+CONFIGURE_ARGS+= \
+ --disable-doc \
+ --disable-parport \
+ --enable-linuxgpio \
+
+TARGET_CFLAGS+= \
+ -D_GNU_SOURCE \
+
+define Package/avrdude/conffiles
+/etc/avrdude.conf
+endef
+
+define Package/avrdude/install
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/avrdude.conf $(1)/etc/
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/avrdude $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,avrdude))
diff --git a/external/subpack/utils/avrdude/patches/010-configure-fixups.patch b/external/subpack/utils/avrdude/patches/010-configure-fixups.patch
new file mode 100644
index 0000000..11ddad7
--- /dev/null
+++ b/external/subpack/utils/avrdude/patches/010-configure-fixups.patch
@@ -0,0 +1,18 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -38,6 +38,7 @@ LT_INIT()
+
+ # Checks for programs.
+ AC_PROG_CC
++AC_PROG_CPP
+ AC_PROG_INSTALL
+ AC_PROG_SED
+ AC_PROG_YACC
+@@ -182,6 +183,7 @@ fi
+ AC_SUBST(LIBPTHREAD, $LIBPTHREAD)
+ # Checks for header files.
+ AC_CHECK_HEADERS([limits.h stdlib.h string.h])
++AC_CHECK_HEADERS([inttypes.h stdint.h])
+ AC_CHECK_HEADERS([fcntl.h sys/ioctl.h sys/time.h termios.h unistd.h])
+ AC_CHECK_HEADERS([ddk/hidsdi.h],,,[#include <windows.h>
+ #include <setupapi.h>])
diff --git a/external/subpack/utils/avrdude/patches/020-no-cpp-timestamps.patch b/external/subpack/utils/avrdude/patches/020-no-cpp-timestamps.patch
new file mode 100644
index 0000000..dab8a43
--- /dev/null
+++ b/external/subpack/utils/avrdude/patches/020-no-cpp-timestamps.patch
@@ -0,0 +1,21 @@
+Description: no CPP macro timestamps
+ Reporducible builds project support, see:
+ http://wiki.debian.org/ReproducibleBuilds/TimestampsFromCPPMacros
+Author: Milan Kupcevic <milan@debian.org>
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/main.c
++++ b/main.c
+@@ -679,10 +679,10 @@ int main(int argc, char * argv [])
+ * Print out an identifying string so folks can tell what version
+ * they are running
+ */
+- avrdude_message(MSG_NOTICE, "\n%s: Version %s, compiled on %s at %s\n"
++ avrdude_message(MSG_NOTICE, "\n%s: Version %s\n"
+ "%sCopyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/\n"
+ "%sCopyright (c) 2007-2014 Joerg Wunsch\n\n",
+- progname, version, __DATE__, __TIME__, progbuf, progbuf);
++ progname, version, progbuf, progbuf);
+ avrdude_message(MSG_NOTICE, "%sSystem wide configuration file is \"%s\"\n",
+ progbuf, sys_config);
+
diff --git a/external/subpack/utils/avrdude/patches/100-musl-compat.patch b/external/subpack/utils/avrdude/patches/100-musl-compat.patch
new file mode 100644
index 0000000..cef5fe4
--- /dev/null
+++ b/external/subpack/utils/avrdude/patches/100-musl-compat.patch
@@ -0,0 +1,60 @@
+--- a/dfu.h
++++ b/dfu.h
+@@ -25,6 +25,7 @@
+
+ #ifdef HAVE_LIBUSB
+ #if defined(HAVE_USB_H)
++# include <sys/types.h>
+ # include <usb.h>
+ #elif defined(HAVE_LUSB0_USB_H)
+ # include <lusb0_usb.h>
+--- a/pickit2.c
++++ b/pickit2.c
+@@ -50,6 +50,7 @@
+ #include <string.h>
+ #include <inttypes.h>
+ #include <unistd.h>
++#include <sys/types.h>
+
+ #include "avrdude.h"
+ #include "libavrdude.h"
+--- a/ser_avrdoper.c
++++ b/ser_avrdoper.c
+@@ -248,6 +248,7 @@ static int usbGetReport(union filedescri
+ /* ------------------------------------------------------------------------ */
+
+ #if defined(HAVE_USB_H)
++# include <sys/types.h>
+ # include <usb.h>
+ #elif defined(HAVE_LUSB0_USB_H)
+ # include <lusb0_usb.h>
+--- a/usbtiny.c
++++ b/usbtiny.c
+@@ -40,6 +40,7 @@
+
+ #if defined(HAVE_LIBUSB) // we use LIBUSB to talk to the board
+ #if defined(HAVE_USB_H)
++# include <sys/types.h>
+ # include <usb.h>
+ #elif defined(HAVE_LUSB0_USB_H)
+ # include <lusb0_usb.h>
+--- a/usbasp.c
++++ b/usbasp.c
+@@ -54,6 +54,7 @@
+ # endif
+ #else
+ # if defined(HAVE_USB_H)
++# include <sys/types.h>
+ # include <usb.h>
+ # elif defined(HAVE_LUSB0_USB_H)
+ # include <lusb0_usb.h>
+--- a/usb_libusb.c
++++ b/usb_libusb.c
+@@ -36,6 +36,7 @@
+ #include <sys/time.h>
+
+ #if defined(HAVE_USB_H)
++# include <sys/types.h>
+ # include <usb.h>
+ #elif defined(HAVE_LUSB0_USB_H)
+ # include <lusb0_usb.h>
diff --git a/external/subpack/utils/avrdude/patches/110-ud-to-u.patch b/external/subpack/utils/avrdude/patches/110-ud-to-u.patch
new file mode 100644
index 0000000..470f4da
--- /dev/null
+++ b/external/subpack/utils/avrdude/patches/110-ud-to-u.patch
@@ -0,0 +1,38 @@
+--- a/linuxgpio.c
++++ b/linuxgpio.c
+@@ -66,7 +66,7 @@ static int linuxgpio_export(unsigned int
+ return fd;
+ }
+
+- len = snprintf(buf, sizeof(buf), "%ud", gpio);
++ len = snprintf(buf, sizeof(buf), "%u", gpio);
+ r = write(fd, buf, len);
+ close(fd);
+
+@@ -84,7 +84,7 @@ static int linuxgpio_unexport(unsigned i
+ return fd;
+ }
+
+- len = snprintf(buf, sizeof(buf), "%ud", gpio);
++ len = snprintf(buf, sizeof(buf), "%u", gpio);
+ r = write(fd, buf, len);
+ close(fd);
+
+@@ -95,7 +95,7 @@ static int linuxgpio_openfd(unsigned int
+ {
+ char filepath[60];
+
+- snprintf(filepath, sizeof(filepath), "/sys/class/gpio/gpio%ud/value", gpio);
++ snprintf(filepath, sizeof(filepath), "/sys/class/gpio/gpio%u/value", gpio);
+ return (open(filepath, O_RDWR));
+ }
+
+@@ -104,7 +104,7 @@ static int linuxgpio_dir(unsigned int gp
+ int fd, r;
+ char buf[60];
+
+- snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%ud/direction", gpio);
++ snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%u/direction", gpio);
+
+ fd = open(buf, O_WRONLY);
+ if (fd < 0) {
diff --git a/external/subpack/utils/bandwidthd/Makefile b/external/subpack/utils/bandwidthd/Makefile
new file mode 100644
index 0000000..53e2a6f
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/Makefile
@@ -0,0 +1,225 @@
+#
+# Copyright (C) 2006-2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bandwidthd
+PKG_VERSION:=2.0.1-35
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/NethServer/bandwidthd/tar.gz/$(PKG_VERSION)?
+PKG_HASH:=75f526d9e81c5a543accbb9e197b6b582c293aa20d6cdfc8be5cef43046981c5
+
+PKG_MAINTAINER:=Jean-Michel Lacroix <lacroix@lepine-lacroix.info>
+PKG_LICENSE:=GPL-2.0-or-later
+
+PKG_FIXUP:=autoreconf
+PKG_BUILD_PARALLEL:=0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/bandwidthd/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Bandwidthd
+ URL:=http://bandwidthd.sourceforge.net/
+endef
+
+define Package/bandwidthd
+$(call Package/bandwidthd/Default)
+ TITLE += (without database)
+ VARIANT:=no-db
+ DEPENDS:=+libgd +libpcap
+endef
+
+define Package/bandwidthd-pgsql
+$(call Package/bandwidthd/Default)
+ TITLE += (with postgresql enabled)
+ VARIANT:=pgsql
+ DEPENDS:=+libgd +libpcap +libpq
+endef
+
+define Package/bandwidthd-sqlite
+$(call Package/bandwidthd/Default)
+ TITLE += (with sqlite enabled)
+ VARIANT:=sqlite
+ DEPENDS:=+libgd +libpcap +libsqlite3 +php7 +php7-cgi +php7-mod-gd +php7-mod-pdo +php7-mod-pdo-sqlite
+endef
+
+define Package/bandwidthd-php
+$(call Package/bandwidthd/Default)
+ TITLE = PHP files to graph bandwidthd data from postgresql
+ VARIANT:=php
+ DEPENDS:=+libpcre +libxml2 +php7 +php7-cgi +php7-mod-pgsql +php7-mod-gd
+endef
+
+define Package/bandwidthd/description
+ A bandwidthd tracking utility.
+endef
+
+define Package/bandwidthd-pgsql/description
+$(call Package/bandwidthd/description)
+With the ability to store in a postgresql database.
+endef
+
+define Package/bandwidthd-sqlite/description
+$(call Package/bandwidthd/description)
+With the ability to store in a sqlite database.
+endef
+
+define Package/bandwidthd-php/description
+ PHP files to graph bandwidthd data from pgsql.
+endef
+
+define Package/bandwidthd/daemon
+ This package contains bandwidthd, a bandwidth tracking utility.
+endef
+
+define Package/bandwidthd-pgsql/daemon
+ This package contains bandwidthd, a bandwidth tracking utility.
+endef
+
+define Package/bandwidthd-sqlite/daemon
+ This package contains bandwidthd, a bandwidth tracking utility.
+endef
+
+define Package/bandwidthd-php/daemon
+ This package contains the PHP files to graph the data from a pgsql database.
+endef
+
+ifeq ($(BUILD_VARIANT),no-db)
+CONFIGURE_ARGS += \
+ ac_cv_file__sw_lib=no \
+ ac_cv_file__sw_include=no \
+ ac_cv_file__usr_pkg_lib=no \
+ ac_cv_file__usr_pkg_include=no \
+ ac_cv_file__usr_local_pgsql_lib=no \
+ ac_cv_file__usr_local_pgsql_include=no \
+ ac_cv_lib_pq_PQconnectdb=no \
+ ac_cv_lib_sqlite3_sqlite3_open=no
+endif
+
+ifeq ($(BUILD_VARIANT),pgsql)
+CONFIGURE_ARGS += \
+ ac_cv_file__sw_lib=no \
+ ac_cv_file__sw_include=no \
+ ac_cv_file__usr_pkg_lib=no \
+ ac_cv_file__usr_pkg_include=no \
+ ac_cv_file__usr_local_pgsql_lib=no \
+ ac_cv_file__usr_local_pgsql_include=no \
+ ac_cv_lib_sqlite3_sqlite3_open=no
+endif
+
+ifeq ($(BUILD_VARIANT),sqlite)
+CONFIGURE_ARGS += \
+ ac_cv_file__sw_lib=no \
+ ac_cv_file__sw_include=no \
+ ac_cv_file__usr_pkg_lib=no \
+ ac_cv_file__usr_pkg_include=no \
+ ac_cv_file__usr_local_pgsql_lib=no \
+ ac_cv_file__usr_local_pgsql_include=no \
+ ac_cv_lib_pq_PQconnectdb=no
+endif
+
+ifeq ($(BUILD_VARIANT),php)
+CONFIGURE_ARGS += \
+ ac_cv_file__sw_lib=no \
+ ac_cv_file__sw_include=no \
+ ac_cv_file__usr_pkg_lib=no \
+ ac_cv_file__usr_pkg_include=no \
+ ac_cv_file__usr_local_pgsql_lib=no \
+ ac_cv_file__usr_local_pgsql_include=no \
+ ac_cv_lib_pq_PQconnectdb=no \
+ ac_cv_lib_sqlite3_sqlite3_open=no
+endif
+
+EXTRA_CFLAGS+= $(TARGET_CPPFLAGS) -fgnu89-inline
+EXTRA_LDFLAGS+= $(TARGET_LDFLAGS) -Wl,-rpath-link,$(STAGING_DIR)/usr/lib
+
+define Package/bandwidthd/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/bandwidthd $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/bandwidthd.config $(1)/etc/config/bandwidthd
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/bandwidthd.init $(1)/etc/init.d/bandwidthd
+ $(INSTALL_DIR) $(1)/www
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/phphtdocs/legend.gif $(1)/www/
+ $(INSTALL_DATA) ./files/logo-openwrt.gif $(1)/www/logo.gif
+endef
+
+define Package/bandwidthd-pgsql/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/bandwidthd $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/bandwidthd-pgsql.config $(1)/etc/config/bandwidthd
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/bandwidthd.init $(1)/etc/init.d/bandwidthd
+ $(INSTALL_DIR) $(1)/www
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/phphtdocs/legend.gif $(1)/www/
+ $(INSTALL_DATA) ./files/logo-openwrt.gif $(1)/www/logo.gif
+ $(INSTALL_DIR) $(1)/usr/share/postgresql
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/phphtdocs/bd_pgsql_purge.sh $(1)/usr/share/postgresql
+endef
+
+define Package/bandwidthd-sqlite/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/bandwidthd $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/bandwidthd-sqlite.config $(1)/etc/config/bandwidthd
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/bandwidthd-sqlite.init $(1)/etc/init.d/bandwidthd
+ $(INSTALL_DIR) $(1)/www/phphtdocs
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/phphtdocs/legend.gif $(1)/www/phphtdocs/
+ $(INSTALL_DATA) ./files/phphtdocs-sqlite/details.php $(1)/www/phphtdocs/
+ $(INSTALL_DATA) ./files/phphtdocs-sqlite/footer.php $(1)/www/phphtdocs/
+ $(INSTALL_DATA) ./files/phphtdocs-sqlite/graph.php $(1)/www/phphtdocs/
+ $(INSTALL_DATA) ./files/phphtdocs-sqlite/include.php $(1)/www/phphtdocs/
+ $(INSTALL_DATA) ./files/phphtdocs-sqlite/index.php $(1)/www/phphtdocs/
+ $(INSTALL_DATA) ./files/logo-openwrt.gif $(1)/www/phphtdocs/logo.gif
+ ln -s /var/etc/bandwidthd-php.conf $(1)/www/phphtdocs/config.conf.php
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/phphtdocs/legend.gif $(1)/www/
+ $(INSTALL_DATA) ./files/logo-openwrt.gif $(1)/www/logo.gif
+endef
+
+define Package/bandwidthd-php/install
+ $(INSTALL_DIR) $(1)/www/phphtdocs
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/phphtdocs/legend.gif $(1)/www/phphtdocs/
+ $(INSTALL_DATA) ./files/phphtdocs/details.php $(1)/www/phphtdocs/
+ $(INSTALL_DATA) ./files/phphtdocs/footer.php $(1)/www/phphtdocs/
+ $(INSTALL_DATA) ./files/phphtdocs/graph.php $(1)/www/phphtdocs/
+ $(INSTALL_DATA) ./files/phphtdocs/include.php $(1)/www/phphtdocs/
+ $(INSTALL_DATA) ./files/phphtdocs/index.php $(1)/www/phphtdocs/
+ $(INSTALL_DATA) ./files/logo-openwrt.gif $(1)/www/phphtdocs/logo.gif
+ ln -s /var/etc/bandwidthd-php.conf $(1)/www/phphtdocs/config.conf
+ $(INSTALL_DIR) $(1)//etc/config
+ $(INSTALL_CONF) ./files/bandwidthd-php.config $(1)/etc/config/bandwidthd-php
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/bandwidthd-php.init $(1)/etc/init.d/bandwidthd-php
+endef
+
+define Package/bandwidthd/conffiles
+/etc/config/bandwidthd
+endef
+
+define Package/bandwidthd-pgsql/conffiles
+/etc/config/bandwidthd
+endef
+
+define Package/bandwidthd-sqlite/conffiles
+/etc/config/bandwidthd
+endef
+
+define Package/bandwidthd-php/conffiles
+/etc/config/bandwidthd-php
+endef
+
+$(eval $(call BuildPackage,bandwidthd))
+$(eval $(call BuildPackage,bandwidthd-pgsql))
+$(eval $(call BuildPackage,bandwidthd-sqlite))
+$(eval $(call BuildPackage,bandwidthd-php))
diff --git a/external/subpack/utils/bandwidthd/files/bandwidthd-pgsql.config b/external/subpack/utils/bandwidthd/files/bandwidthd-pgsql.config
new file mode 100644
index 0000000..f94c737
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/bandwidthd-pgsql.config
@@ -0,0 +1,13 @@
+config bandwidthd
+ option dev br-lan
+ option subnets "192.168.1.0/24"
+ option skip_intervals 0
+ option graph_cutoff 1024
+ option promiscuous true
+ option output_cdf false
+ option recover_cdf false
+ option filter ip
+ option graph true
+ option meta_refresh 150
+ option pgsql_connect_string "user = postgres dbname = bandwidthd host = 192.168.1.1"
+ option sensor_id "openwrt"
diff --git a/external/subpack/utils/bandwidthd/files/bandwidthd-php.config b/external/subpack/utils/bandwidthd/files/bandwidthd-php.config
new file mode 100644
index 0000000..3bad494
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/bandwidthd-php.config
@@ -0,0 +1,7 @@
+config bandwidthd-php
+ option dflt_width '900'
+ option dflt_height '256'
+ option dflt_interval 'INT_DAILY'
+ option host '127.0.0.1'
+ option user 'postgres'
+ option dbname 'bandwidthd'
diff --git a/external/subpack/utils/bandwidthd/files/bandwidthd-php.init b/external/subpack/utils/bandwidthd/files/bandwidthd-php.init
new file mode 100755
index 0000000..b7b6434
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/bandwidthd-php.init
@@ -0,0 +1,75 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006-2017 OpenWrt.org
+
+START=99
+
+USE_PROCD=1
+
+CONFIGNAME="bandwidthd-php"
+CONFIGFILE="/var/etc/bandwidthd-php.conf"
+
+config_cb() {
+ local cfg_type="$1"
+ local cfg_name="$2"
+ case "$cfg_type" in
+ $CONFIGNAME)
+ append cfgs "$cfg_name"
+ ;;
+ esac
+}
+
+export_number() {
+ local option="$1"
+ local section="$2"
+ local _loctmp
+ paramstr=""
+ config_get _loctmp "$section" "$option"
+ if [ -n "$_loctmp" ]; then
+ paramstr="${_loctmp}"
+ fi
+}
+
+export_string() {
+ local option="$1"
+ local section="$2"
+ local _loctmp
+ paramstr=""
+ config_get _loctmp "$section" "$option"
+ if [ -n "$_loctmp" ]; then
+ paramstr="${_loctmp}"
+ fi
+}
+
+service_triggers()
+{
+ procd_add_reload_trigger $CONFIGNAME
+}
+
+
+start_service() {
+ local conffile="<?php\n// auto-generated config file from /etc/config/${CONFIGNAME}\n"
+ rm -f $CONFIGFILE
+ touch $CONFIGFILE
+
+ config_load $CONFIGNAME
+ for cfg in $cfgs; do
+ export_number dflt_width $cfg
+ conffile="${conffile}define(\"DFLT_WIDTH\", ${paramstr:-"900"});\n"
+
+ export_number dflt_height $cfg
+ conffile="${conffile}define(\"DFLT_HEIGHT\", ${paramstr:-"256"});\n"
+
+ export_string dflt_interval $cfg
+ conffile="${conffile}define(\"DFLT_INTERVAL\", ${paramstr:-"INT_DAILY"});\n\n"'$db_connect_string = "host='
+
+ export_string host $cfg
+ conffile="${conffile}${paramstr:-"127.0.0.1"} user="
+
+ export_string user $cfg
+ conffile="${conffile}${paramstr:-"postgres"} dbname="
+
+ export_string dbname $cfg
+ conffile="${conffile}${paramstr:-"bandwidthd"}"'"'"\n?>"
+ [ -n "$conffile" ] && echo -e "$conffile" >>$CONFIGFILE
+ done
+}
diff --git a/external/subpack/utils/bandwidthd/files/bandwidthd-sqlite.config b/external/subpack/utils/bandwidthd/files/bandwidthd-sqlite.config
new file mode 100644
index 0000000..bc4154a
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/bandwidthd-sqlite.config
@@ -0,0 +1,13 @@
+config bandwidthd
+ option dev br-lan
+ option subnets "192.168.1.0/24"
+ option skip_intervals 0
+ option graph_cutoff 1024
+ option promiscuous true
+ option output_cdf false
+ option recover_cdf false
+ option filter ip
+ option graph true
+ option meta_refresh 150
+ option sqlite_filename "/www/bandwidthd/stats.db"
+ option sensor_id "default"
diff --git a/external/subpack/utils/bandwidthd/files/bandwidthd-sqlite.init b/external/subpack/utils/bandwidthd/files/bandwidthd-sqlite.init
new file mode 100755
index 0000000..c456974
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/bandwidthd-sqlite.init
@@ -0,0 +1,133 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2008-2017 OpenWrt.org
+
+START=99
+
+USE_PROCD=1
+
+CONFIGNAME="bandwidthd"
+CONFIGPHPNAME="bandwidthd-php"
+CONFIGFILE="/tmp/etc/bandwidthd.conf"
+CONFIGPHPFILE="/tmp/etc/bandwidthd-php.conf"
+
+config_cb() {
+ local cfg_type="$1"
+ local cfg_name="$2"
+
+ case "$cfg_type" in
+ bandwidthd)
+ append cfgs "$cfg_name"
+ ;;
+ esac
+}
+
+export_bool() {
+ local option="$1"
+ local section="$2"
+ local _loctmp
+ config_get_bool _loctmp "$section" "$option"
+ if [ -n "$_loctmp" ]; then
+ conffile="${conffile}$option "
+ if [ 1 -eq "$_loctmp" ]; then
+ conffile="${conffile}true"
+ else
+ conffile="${conffile}false"
+ fi
+ conffile="${conffile}\n"
+ fi
+}
+
+export_number() {
+ local option="$1"
+ local section="$2"
+ local _loctmp
+ config_get _loctmp "$section" "$option"
+ if [ -n "$_loctmp" ]; then
+ conffile="${conffile}$option ${_loctmp}\n"
+ fi
+}
+
+export_string() {
+ local option="$1"
+ local section="$2"
+ local _loctmp
+ config_get _loctmp "$section" "$option"
+ if [ -n "$_loctmp" ]; then
+ conffile="${conffile}$option \"${_loctmp}\"\n"
+ fi
+}
+
+set_conf_file() {
+ local subnet conffile="# auto-generated config file from /etc/config/${CONFIGNAME}\n"
+
+ [ -d /tmp/bandwidthd ] || mkdir -p /tmp/bandwidthd && cp /www/legend.gif /www/logo.gif /tmp/bandwidthd/
+ [ -e /htdocs ] || ln -s /tmp/bandwidthd /htdocs
+ [ -e /www/bandwidthd ] || ln -s /tmp/bandwidthd /www/bandwidthd
+ rm -f $CONFIGFILE
+ touch $CONFIGFILE
+ [ -e /etc/bandwidthd.conf ] || ln -s $CONFIGFILE /etc/bandwidthd.conf
+
+ config_load $CONFIGNAME
+ for cfg in $cfgs; do
+ config_get subnets $cfg subnets
+ for subnet in $subnets; do
+ conffile="${conffile}subnet ${subnet}\n"
+ done
+ export_string dev $cfg
+ export_number skip_intervals $cfg
+ export_number graph_cutoff $cfg
+ export_bool promiscuous $cfg
+ export_bool output_cdf $cfg
+ export_bool recover_cdf $cfg
+ export_string filter $cfg
+ export_bool graph $cfg
+ export_number meta_refresh $cfg
+ export_string pgsql_connect_string $cfg
+ export_string sqlite_filename $cfg
+ export_string sensor_id $cfg
+ [ -n "$conffile" ] && echo -e "$conffile" >>$CONFIGFILE
+ unset conffile
+ done
+ cd /
+}
+
+set_php_conf_file() {
+ local subnet conffile="<?php\n// auto-generated config file from /etc/config/${CONFIGPHPNAME}\n"
+
+ rm -f $CONFIGPHPFILE
+ touch $CONFIGPHPFILE
+
+ config_load $CONFIGPHPNAME
+ for cfg in $cfgs; do
+ export_number dflt_width $cfg
+ conffile="${conffile}define(\"DFLT_WIDTH\", ${paramstr:-"900"});\n"
+
+ export_number dflt_height $cfg
+ conffile="${conffile}define(\"DFLT_HEIGHT\", ${paramstr:-"256"});\n"
+
+ export_string dflt_interval $cfg
+ conffile="${conffile}define(\"DFLT_INTERVAL\", ${paramstr:-"INT_DAILY"});\n\n"'$db_connect_string = "sqlite:'
+
+ export_string sqlite_dbname $cfg
+ conffile="${conffile}${paramstr:-"/www/bandwidthd/stats.db"}"'"'"\n?>"
+ [ -n "$conffile" ] && echo -e "$conffile" >>$CONFIGPHPFILE
+ done
+ cd /
+}
+
+service_triggers() {
+ procd_add_reload_trigger $CONFIGNAME
+ procd_add_reload_trigger $CONFIGPHPNAME
+}
+
+start_service() {
+ set_conf_file
+ set_php_conf_file
+ procd_open_instance
+ procd_set_param command /usr/sbin/bandwidthd
+ procd_close_instance
+}
+
+stop_service() {
+ service_stop /usr/sbin/bandwidthd
+}
diff --git a/external/subpack/utils/bandwidthd/files/bandwidthd.config b/external/subpack/utils/bandwidthd/files/bandwidthd.config
new file mode 100644
index 0000000..ac1669e
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/bandwidthd.config
@@ -0,0 +1,11 @@
+config bandwidthd
+ option dev br-lan
+ option subnets "192.168.1.0/24"
+ option skip_intervals 0
+ option graph_cutoff 1024
+ option promiscuous true
+ option output_cdf false
+ option recover_cdf false
+ option filter ip
+ option graph true
+ option meta_refresh 150
diff --git a/external/subpack/utils/bandwidthd/files/bandwidthd.init b/external/subpack/utils/bandwidthd/files/bandwidthd.init
new file mode 100755
index 0000000..ac9d01d
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/bandwidthd.init
@@ -0,0 +1,106 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2008-2017 OpenWrt.org
+
+START=99
+
+USE_PROCD=1
+
+CONFIGNAME="bandwidthd"
+CONFIGFILE="/tmp/etc/bandwidthd.conf"
+
+config_cb() {
+ local cfg_type="$1"
+ local cfg_name="$2"
+
+ case "$cfg_type" in
+ bandwidthd)
+ append cfgs "$cfg_name"
+ ;;
+ esac
+}
+
+export_bool() {
+ local option="$1"
+ local section="$2"
+ local _loctmp
+ config_get_bool _loctmp "$section" "$option"
+ if [ -n "$_loctmp" ]; then
+ conffile="${conffile}$option "
+ if [ 1 -eq "$_loctmp" ]; then
+ conffile="${conffile}true"
+ else
+ conffile="${conffile}false"
+ fi
+ conffile="${conffile}\n"
+ fi
+}
+
+export_number() {
+ local option="$1"
+ local section="$2"
+ local _loctmp
+ config_get _loctmp "$section" "$option"
+ if [ -n "$_loctmp" ]; then
+ conffile="${conffile}$option ${_loctmp}\n"
+ fi
+}
+
+export_string() {
+ local option="$1"
+ local section="$2"
+ local _loctmp
+ config_get _loctmp "$section" "$option"
+ if [ -n "$_loctmp" ]; then
+ conffile="${conffile}$option \"${_loctmp}\"\n"
+ fi
+}
+
+set_conf_file() {
+ local subnet conffile
+
+ [ -d /tmp/bandwidthd ] || mkdir -p /tmp/bandwidthd && cp /www/legend.gif /www/logo.gif /tmp/bandwidthd/
+ [ -e /htdocs ] || ln -s /tmp/bandwidthd /htdocs
+ [ -e /www/bandwidthd ] || ln -s /tmp/bandwidthd /www/bandwidthd
+ rm -f $CONFIGFILE
+ touch $CONFIGFILE
+ [ -e /etc/bandwidthd.conf ] || ln -s $CONFIGFILE /etc/bandwidthd.conf
+
+ config_load $CONFIGNAME
+ for cfg in $cfgs; do
+ config_get subnets $cfg subnets
+ for subnet in $subnets; do
+ conffile="${conffile}subnet ${subnet}\n"
+ done
+ export_string dev $cfg
+ export_number skip_intervals $cfg
+ export_number graph_cutoff $cfg
+ export_bool promiscuous $cfg
+ export_bool output_cdf $cfg
+ export_bool recover_cdf $cfg
+ export_string filter $cfg
+ export_bool graph $cfg
+ export_number meta_refresh $cfg
+ export_string pgsql_connect_string $cfg
+ export_string sqlite_filename $cfg
+ export_string sensor_id $cfg
+ [ -n "$conffile" ] && echo -e "$conffile" >>$CONFIGFILE
+ unset conffile
+ done
+ cd /
+}
+
+service_triggers()
+{
+ procd_add_reload_trigger $CONFIGNAME
+}
+
+start_service() {
+ set_conf_file
+ procd_open_instance
+ procd_set_param command /usr/sbin/bandwidthd
+ procd_close_instance
+}
+
+stop_service() {
+ service_stop /usr/sbin/bandwidthd
+}
diff --git a/external/subpack/utils/bandwidthd/files/logo-openwrt.gif b/external/subpack/utils/bandwidthd/files/logo-openwrt.gif
new file mode 100644
index 0000000..2ffec56
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/logo-openwrt.gif
Binary files differ
diff --git a/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/details.php b/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/details.php
new file mode 100644
index 0000000..448ea46
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/details.php
@@ -0,0 +1,104 @@
+<?php
+include("include.php");
+?>
+<html>
+<center>
+<img src=logo.gif>
+<?php
+if (isset($_GET['sensor_name']))
+ $sensor_name = $_GET['sensor_name'];
+else
+ {
+ echo "<br>Please provide a sensor_name";
+ exit(1);
+ }
+
+if (isset($_GET['ip']))
+ $ip = $_GET['ip'];
+else
+ {
+ echo "<br>Please provide an ip address";
+ exit(1);
+ }
+
+echo "<h3>";
+if (strpos($ip, "/") === FALSE)
+ echo "$ip - ".gethostbyaddr($ip)."</h3>";
+else
+ echo "Total - $ip</h3>";
+
+$db = ConnectDb();
+
+if ($ip == "0.0.0.0/0")
+ {
+ $rxtable = "bd_rx_total_log";
+ $txtable = "bd_tx_total_log";
+ }
+else
+ {
+ $rxtable = "bd_rx_log";
+ $txtable = "bd_tx_log";
+ }
+
+$sql = "select rx.scale as rxscale, tx.scale as txscale, tx.total+rx.total as total, tx.total as sent,
+rx.total as received, tx.tcp+rx.tcp as tcp, tx.udp+rx.udp as udp,
+tx.icmp+rx.icmp as icmp, tx.http+rx.http as http,
+tx.p2p+rx.p2p as p2p, tx.ftp+rx.ftp as ftp
+from
+
+(SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp,
+sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp
+from sensors, $txtable
+where sensor_name = '$sensor_name'
+and sensors.sensor_id = ".$txtable.".sensor_id
+$sql_subnet
+group by ip) as tx,
+
+(SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp,
+sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp
+from sensors, $rxtable
+where sensor_name = '$sensor_name'
+and sensors.sensor_id = ".$rxtable.".sensor_id
+$sql_subnet
+group by ip) as rx
+
+where tx.ip = rx.ip;";
+//error_log($sql); printf('</center><tt>%s</tt><center>', $sql);
+$db = ConnectDb();
+$result = $db->query($sql);
+echo "<table width=100% border=1 cellspacing=0><tr><td>Ip<td>Name<td>Total<td>Sent<td>Received<td>tcp<td>udp<td>icmp<td>http<td>smtp<td>ftp";
+$r = $result->fetch();
+$db = NULL;
+echo "<tr><td>";
+if (strpos($ip, "/") === FALSE)
+ echo "$ip<td>".gethostbyaddr($ip);
+else
+ echo "Total<td>$ip";
+echo fmtb($r['total']).fmtb($r['sent']).fmtb($r['received']).
+ fmtb($r['tcp']).fmtb($r['udp']).fmtb($r['icmp']).fmtb($r['http']).
+ fmtb($r['p2p']).fmtb($r['ftp']);
+echo "</table></center>";
+
+echo "<center><h4>Daily</h4></center>";
+echo "Send:<br><img src=graph.php?ip=$ip&sensor_name=".$sensor_name."&table=$txtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+echo "Receive:<br><img src=graph.php?ip=$ip&sensor_name=".$sensor_name."&table=$rxtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+
+echo "<center><h4>Weekly</h4></center>";
+echo "Send:<br><img src=graph.php?interval=".INT_WEEKLY."&ip=$ip&sensor_name=$sensor_name&table=$txtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+echo "Receive:<br><img src=graph.php?interval=".INT_WEEKLY."&ip=$ip&sensor_name=$sensor_name&table=$rxtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+
+echo "<center><h4>Monthly</h4></center>";
+echo "Send:<br><img src=graph.php?interval=".INT_MONTHLY."&ip=$ip&sensor_name=$sensor_name&table=$txtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+echo "Receive:<br><img src=graph.php?interval=".INT_MONTHLY."&ip=$ip&sensor_name=$sensor_name&table=$rxtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+
+echo "<center><h4>Yearly</h4></center>";
+echo "Send:<br><img src=graph.php?interval=".INT_YEARLY."&ip=$ip&sensor_name=$sensor_name&table=$txtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+echo "Receive:<br><img src=graph.php?interval=".INT_YEARLY."&ip=$ip&sensor_name=$sensor_name&table=$rxtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
diff --git a/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/footer.php b/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/footer.php
new file mode 100644
index 0000000..b342825
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/footer.php
@@ -0,0 +1,3 @@
+<?php
+echo("Page load completed in ". (time() - $starttime) ." seconds");
+?>
diff --git a/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/graph.php b/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/graph.php
new file mode 100644
index 0000000..82df317
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/graph.php
@@ -0,0 +1,455 @@
+<?php
+require("include.php");
+
+// Returns x location of any given timestamp
+function ts2x($ts)
+ {
+ global $timestamp, $width, $interval;
+ return(($ts-$timestamp)*(($width-XOFFSET) / $interval) + XOFFSET);
+ }
+
+// If we have multiple IP's in a result set we need to total the average of each IP's samples
+function AverageAndAccumulate()
+ {
+ global $Count, $total, $icmp, $udp, $tcp, $ftp, $http, $p2p, $YMax;
+ global $a_total, $a_icmp, $a_udp, $a_tcp, $a_ftp, $a_http, $a_p2p;
+
+ foreach ($Count as $key => $number)
+ {
+ $total[$key] /= $number;
+ $icmp[$key] /= $number;
+ $udp[$key] /= $number;
+ $tcp[$key] /= $number;
+ $ftp[$key] /= $number;
+ $http[$key] /= $number;
+ $p2p[$key] /= $number;
+ }
+
+ foreach ($Count as $key => $number)
+ {
+ $a_total[$key] += $total[$key];
+ $a_icmp[$key] += $icmp[$key];
+ $a_udp[$key] += $udp[$key];
+ $a_tcp[$key] += $tcp[$key];
+ $a_ftp[$key] += $ftp[$key];
+ $a_http[$key] += $http[$key];
+ $a_p2p[$key] += $p2p[$key];
+
+ if ($a_total[$key] > $YMax)
+ $YMax = $a_total[$key];
+ }
+
+ unset($GLOBALS['total'], $GLOBALS['icmp'], $GLOBALS['udp'], $GLOBALS['tcp'], $GLOBALS['ftp'], $GLOBALS['http'], $GLOBALS['p2p'], $GLOBALS['Count']);
+
+ $total = array();
+ $icmp = array();
+ $udp = array();
+ $tcp = array();
+ $ftp = array();
+ $http = array();
+ $p2p = array();
+ $Count = array();
+ }
+
+$db = ConnectDb();
+
+// Get parameters
+
+if (isset($_GET['width']))
+ $width = $_GET['width'];
+else
+ $width = DFLT_WIDTH;
+
+if (isset($_GET['height']))
+ $height = $_GET['height'];
+else
+ $height = DFLT_HEIGHT;
+
+if (isset($_GET['interval']))
+ $interval = $_GET['interval'];
+else
+ $interval = DFLT_INTERVAL;
+
+if (isset($_GET['ip']))
+ $ip = $_GET['ip'];
+else
+ exit(1);
+
+if (isset($_GET['sensor_name']))
+ $sensor_name = $_GET['sensor_name'];
+else
+ exit(1);
+
+if (isset($_GET['timestamp']))
+ $timestamp = $_GET['timestamp'];
+else
+ $timestamp = time() - $interval + (0.05*$interval);
+
+if (isset($_GET['table']))
+ $table = $_GET['table'];
+else
+ $table = "bd_rx_log";
+
+if (isset($_GET['yscale']))
+ $yscale = $_GET['yscale'];
+
+$total = array();
+$icmp = array();
+$udp = array();
+$tcp = array();
+$ftp = array();
+$http = array();
+$p2p = array();
+$Count = array();
+
+// Accumulator
+$a_total = array();
+$a_icmp = array();
+$a_udp = array();
+$a_tcp = array();
+$a_ftp = array();
+$a_http = array();
+$a_p2p = array();
+
+$sql_subnet = prepare_sql_subnet($ip);
+$sql = "select *, timestamp as ts from sensors, $table where sensors.sensor_id = ".$table.".sensor_id $sql_subnet and sensor_name = '$sensor_name' and timestamp > $timestamp and timestamp < ".($timestamp+$interval)." order by ip;";
+//error_log($sql);
+$result = $db->query($sql);
+
+// The SQL statement pulls the data out of the database ordered by IP address, that way we can average each
+// datapoint for each IP address to provide smoothing and then toss the smoothed value into the accumulator
+// to provide accurate total traffic rate.
+
+while ($row = $result->fetch())
+ {
+ if ($row['ip'] != $last_ip)
+ {
+ AverageAndAccumulate();
+ $last_ip = $row['ip'];
+ }
+
+ $x = ($row['ts']-$timestamp)*(($width-XOFFSET)/$interval)+XOFFSET;
+ $xint = (int) $x;
+
+ //echo "xint: ".$xint."<br>";
+ $Count[$xint]++;
+
+ if ($row['total']/$row['sample_duration'] > $SentPeak)
+ $SentPeak = $row['total']/$row['sample_duration'];
+ $TotalSent += $row['total'];
+ $total[$xint] += $row['total']/$row['sample_duration'];
+ $icmp[$xint] += $row['icmp']/$row['sample_duration'];
+ $udp[$xint] += $row['udp']/$row['sample_duration'];
+ $tcp[$xint] += $row['tcp']/$row['sample_duration'];
+ $ftp[$xint] += $row['ftp']/$row['sample_duration'];
+ $http[$xint] += $row['http']/$row['sample_duration'];
+ $p2p[$xint] += $row['p2p']/$row['sample_duration'];
+ }
+
+// One more time for the last IP
+AverageAndAccumulate();
+
+// Pull the data out of Accumulator
+$total = $a_total;
+$icmp = $a_icmp;
+$udp = $a_udp;
+$tcp = $a_tcp;
+$ftp = $a_ftp;
+$http = $a_http;
+$p2p = $a_p2p;
+
+$YMax += $YMax*0.05; // Add an extra 5%
+
+// if a y scale was specified override YMax
+if (isset($yscale)&& $yscale > 0)
+ $YMax = $yscale/8;
+
+// Plot the data
+
+header("Content-type: image/png");
+
+$im = imagecreate($width, $height);
+$white = imagecolorallocate($im, 255, 255, 255);
+$purple = ImageColorAllocate($im, 255, 0, 255);
+$green = ImageColorAllocate($im, 0, 255, 0);
+$blue = ImageColorAllocate($im, 0, 0, 255);
+$lblue = ImageColorAllocate($im, 128, 128, 255);
+$brown = ImageColorAllocate($im, 128, 0, 0);
+$red = ImageColorAllocate($im, 255, 0, 0);
+$black = ImageColorAllocate($im, 0, 0, 0);
+
+for($Counter=XOFFSET+1; $Counter < $width; $Counter++)
+ {
+ if (isset($total[$Counter]))
+ {
+ // Convert the bytes/sec to y coords
+ $total[$Counter] = ($total[$Counter]*($height-YOFFSET))/$YMax;
+ $tcp[$Counter] = ($tcp[$Counter]*($height-YOFFSET))/$YMax;
+ $ftp[$Counter] = ($ftp[$Counter]*($height-YOFFSET))/$YMax;
+ $http[$Counter] = ($http[$Counter]*($height-YOFFSET))/$YMax;
+ $p2p[$Counter] = ($p2p[$Counter]*($height-YOFFSET))/$YMax;
+ $udp[$Counter] = ($udp[$Counter]*($height-YOFFSET))/$YMax;
+ $icmp[$Counter] = ($icmp[$Counter]*($height-YOFFSET))/$YMax;
+
+ // Stack 'em up!
+ // Total is stacked from the bottom
+ // Icmp is on the bottom too
+ // Udp is stacked on top of icmp
+ $udp[$Counter] += $icmp[$Counter];
+ // TCP and p2p are stacked on top of Udp
+ $tcp[$Counter] += $udp[$Counter];
+ $p2p[$Counter] += $udp[$Counter];
+ // Http is stacked on top of p2p
+ $http[$Counter] += $p2p[$Counter];
+ // Ftp is stacked on top of http
+ $ftp[$Counter] += $http[$Counter];
+
+ // Plot them!
+ //echo "$Counter:".$Counter." (h-y)-t:".($height-YOFFSET) - $total[$Counter]." h-YO-1:".$height-YOFFSET-1;
+ ImageLine($im, $Counter, ($height-YOFFSET) - $icmp[$Counter], $Counter, $height-YOFFSET-1, $red);
+ ImageLine($im, $Counter, ($height-YOFFSET) - $udp[$Counter], $Counter, ($height-YOFFSET) - $icmp[$Counter] - 1, $brown);
+ ImageLine($im, $Counter, ($height-YOFFSET) - $tcp[$Counter], $Counter, ($height-YOFFSET) - $udp[$Counter] - 1, $green);
+ ImageLine($im, $Counter, ($height-YOFFSET) - $p2p[$Counter], $Counter, ($height-YOFFSET) - $udp[$Counter] - 1, $purple);
+ ImageLine($im, $Counter, ($height-YOFFSET) - $http[$Counter], $Counter, ($height-YOFFSET) - $p2p[$Counter] - 1, $blue);
+ ImageLine($im, $Counter, ($height-YOFFSET) - $ftp[$Counter], $Counter, ($height-YOFFSET) - $http[$Counter] - 1, $lblue);
+ }
+// else
+// echo $Counter." not set<br>";
+ }
+
+// Margin Text
+if ($SentPeak < 1024/8)
+ $txtPeakSendRate = sprintf("Peak Send Rate: %.1f KBits/sec", $SentPeak*8);
+else if ($SentPeak < (1024*1024)/8)
+ $txtPeakSendRate = sprintf("Peak Send Rate: %.1f MBits/sec", ($SentPeak*8.0)/1024.0);
+else
+ $txtPeakSendRate = sprintf("Peak Send Rate: %.1f GBits/sec", ($SentPeak*8.0)/(1024.0*1024.0));
+
+if ($TotalSent < 1024)
+ $txtTotalSent = sprintf("Sent %.1f KBytes", $TotalSent);
+else if ($TotalSent < 1024*1024)
+ $txtTotalSent = sprintf("Sent %.1f MBytes", $TotalSent/1024.0);
+else
+ $txtTotalSent = sprintf("Sent %.1f GBytes", $TotalSent/(1024.0*1024.0));
+
+ImageString($im, 2, XOFFSET+5, $height-20, $txtTotalSent, $black);
+ImageString($im, 2, $width/2+XOFFSET/2, $height-20, $txtPeakSendRate, $black);
+
+// Draw X Axis
+
+ImageLine($im, 0, $height-YOFFSET, $width, $height-YOFFSET, $black);
+
+// Day/Month Seperator bars
+
+if ((24*60*60*($width-XOFFSET))/$interval > ($width-XOFFSET)/10)
+ {
+ $ts = getdate($timestamp);
+ $MarkTime = mktime(0, 0, 0, $ts['mon'], $ts['mday'], $ts['year']);
+
+ $x = ts2x($MarkTime);
+ while ($x < XOFFSET)
+ {
+ $MarkTime += (24*60*60);
+ $x = ts2x($MarkTime);
+ }
+
+ while ($x < ($width-10))
+ {
+ // Day Lines
+ ImageLine($im, $x, 0, $x, $height-YOFFSET, $black);
+ ImageLine($im, $x+1, 0, $x+1, $height-YOFFSET, $black);
+
+ $txtDate = strftime("%a, %b %d", $MarkTime);
+ ImageString($im, 2, $x-30, $height-YOFFSET+10, $txtDate, $black);
+
+ // Calculate Next x
+ $MarkTime += (24*60*60);
+ $x = ts2x($MarkTime);
+ }
+ }
+else if ((24*60*60*30*($width-XOFFSET))/$interval > ($width-XOFFSET)/10)
+ {
+ // Monthly Bars
+ $ts = getdate($timestamp);
+ $month = $ts['mon'];
+ $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']);
+
+ $x = ts2x($MarkTime);
+ while ($x < XOFFSET)
+ {
+ $month++;
+ $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']);
+ $x = ts2x($MarkTime);
+ }
+
+ while ($x < ($width-10))
+ {
+ // Day Lines
+ ImageLine($im, $x, 0, $x, $height-YOFFSET, $black);
+ ImageLine($im, $x+1, 0, $x+1, $height-YOFFSET, $black);
+
+ $txtDate = strftime("%b, %Y", $MarkTime);
+ ImageString($im, 2, $x-25, $height-YOFFSET+10, $txtDate, $black);
+
+ // Calculate Next x
+ $month++;
+ $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']);
+ $x = ts2x($MarkTime);
+ }
+ }
+else
+ {
+ // Year Bars
+ $ts = getdate($timestamp);
+ $year = $ts['year'];
+ $MarkTime = mktime(0, 0, 0, 1, 1, $year);
+
+ $x = ts2x($MarkTime);
+ while ($x < XOFFSET)
+ {
+ $year++;
+ $MarkTime = mktime(0, 0, 0, 1, 1, $year);
+ $x = ts2x($MarkTime);
+ }
+
+ while ($x < ($width-10))
+ {
+ // Day Lines
+ ImageLine($im, $x, 0, $x, $height-YOFFSET, $black);
+ ImageLine($im, $x+1, 0, $x+1, $height-YOFFSET, $black);
+
+ $txtDate = strftime("%b, %Y", $MarkTime);
+ ImageString($im, 2, $x-25, $height-YOFFSET+10, $txtDate, $black);
+
+ // Calculate Next x
+ $year++;
+ $MarkTime = mktime(0, 0, 0, 1, 1, $year);
+ $x = ts2x($MarkTime);
+ }
+ }
+
+// Draw Major Tick Marks
+if ((6*60*60*($width-XOFFSET))/$interval > 10) // pixels per 6 hours is more than 2
+ $MarkTimeStep = 6*60*60; // Major ticks are 6 hours
+else if ((24*60*60*($width-XOFFSET))/$interval > 10)
+ $MarkTimeStep = 24*60*60; // Major ticks are 24 hours;
+else if ((24*60*60*30*($width-XOFFSET))/$interval > 10)
+ {
+ // Major tick marks are months
+ $MarkTimeStep = 0; // Skip the standard way of drawing major tick marks below
+
+ $ts = getdate($timestamp);
+ $month = $ts['mon'];
+ $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']);
+
+ $x = ts2x($MarkTime);
+ while ($x < XOFFSET)
+ {
+ $month++;
+ $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']);
+ $x = ts2x($MarkTime);
+ }
+
+ while ($x < ($width-10))
+ {
+ // Day Lines
+ $date = getdate($MarkTime);
+ if ($date['mon'] != 1)
+ {
+ ImageLine($im, $x, $height-YOFFSET-5, $x, $height-YOFFSET+5, $black);
+ $txtDate = strftime("%b", $MarkTime);
+ ImageString($im, 2, $x-5, $height-YOFFSET+10, $txtDate, $black);
+ }
+
+ // Calculate Next x
+ $month++;
+ $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']);
+ $x = ts2x($MarkTime);
+ }
+ }
+else
+ $MarkTimeStep = 0; // Skip Major Tick Marks
+
+if ($MarkTimeStep)
+ {
+ $ts = getdate($timestamp);
+ $MarkTime = mktime(0, 0, 0, $ts['mon'], $ts['mday'], $ts['year']);
+ $x = ts2x($MarkTime);
+
+ while ($x < ($width-10))
+ {
+ if ($x > XOFFSET)
+ {
+ ImageLine($im, $x, $height-YOFFSET-5, $x, $height-YOFFSET+5, $black);
+ }
+ $MarkTime += $MarkTimeStep;
+ $x = ts2x($MarkTime);
+ }
+ }
+
+// Draw Minor Tick marks
+if ((60*60*($width-XOFFSET))/$interval > 4) // pixels per hour is more than 2
+ $MarkTimeStep = 60*60; // Minor ticks are 1 hour
+else if ((6*60*60*($width-XOFFSET))/$interval > 4)
+ $MarkTimeStep = 6*60*60; // Minor ticks are 6 hours
+else if ((24*60*60*($width-XOFFSET))/$interval > 4)
+ $MarkTimeStep = 24*60*60;
+else
+ $MarkTimeStep = 0; // Skip minor tick marks
+
+if ($MarkTimeStep)
+ {
+ $ts = getdate($timestamp);
+ $MarkTime = mktime(0, 0, 0, $ts['mon'], $ts['mday'], $ts['year']);
+ $x = ts2x($MarkTime);
+
+ while ($x < ($width-10))
+ {
+ if ($x > XOFFSET)
+ {
+ ImageLine($im, $x, $height-YOFFSET, $x, $height-YOFFSET+5, $black);
+ }
+ $MarkTime += $MarkTimeStep;
+ $x = ts2x($MarkTime);
+ }
+ }
+
+// Draw Y Axis
+ImageLine($im, XOFFSET, 0, XOFFSET, $height, $black);
+
+$YLegend = 'k';
+$Divisor = 1;
+if ($YMax*8 > 1024*2)
+ {
+ $Divisor = 1024; // Display in m
+ $YLegend = 'm';
+ }
+
+if ($YMax*8 > 1024*1024*2)
+ {
+ $Divisor = 1024*1024; // Display in g
+ $YLegend = 'g';
+ }
+
+if ($YMax*8 > 1024*1024*1024*2)
+ {
+ $Divisor = 1024*1024*1024; // Display in t
+ $YLegend = 't';
+ }
+
+$YStep = $YMax/10;
+if ($YStep < 1)
+ $YStep=1;
+$YTic=$YStep;
+
+while ($YTic <= ($YMax - $YMax/10))
+ {
+ $y = ($height-YOFFSET)-(($YTic*($height-YOFFSET))/$YMax);
+ ImageLine($im, XOFFSET, $y, $width, $y, $black);
+ $txtYLegend = sprintf("%4.1f %sbits/s", (8.0*$YTic)/$Divisor, $YLegend);
+ ImageString($im, 2, 3, $y-7, $txtYLegend, $black);
+ $YTic += $YStep;
+ }
+
+imagepng($im);
+imagedestroy($im);
diff --git a/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/include.php b/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/include.php
new file mode 100644
index 0000000..5195098
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/include.php
@@ -0,0 +1,69 @@
+<?php
+error_reporting(E_ALL & ~(E_NOTICE|E_STRICT));
+define("INT_DAILY", 60*60*24*2);
+define("INT_WEEKLY", 60*60*24*8);
+define("INT_MONTHLY", 60*60*24*35);
+define("INT_YEARLY", 60*60*24*400);
+
+define("XOFFSET", 90);
+define("YOFFSET", 45);
+
+require("config.conf.php");
+
+function ConnectDb() {
+ global $db_connect_string;
+ try {
+ $db = new PDO($db_connect_string);
+ } catch (PDOException $ex) {
+ die("DB Error, could not connect to database: " . $ex->getMessage());
+ }
+ return $db;
+}
+
+function fmtb($kbytes)
+ {
+ $Max = 1024;
+ $Output = $kbytes;
+ $Suffix = 'K';
+
+ if ($Output > $Max)
+ {
+ $Output /= 1024;
+ $Suffix = 'M';
+ }
+
+ if ($Output > $Max)
+ {
+ $Output /= 1024;
+ $Suffix = 'G';
+ }
+
+ if ($Output > $Max)
+ {
+ $Output /= 1024;
+ $Suffix = 'T';
+ }
+
+ return(sprintf("<td align=right><tt>%.1f%s</td>", $Output, $Suffix));
+ }
+
+function ip2s32($ip) {
+ $i = ip2long($ip);
+ return ($i & 0x80000000 ? '-' . ((~$i & 0x7fffffff)+1) : ''. ($i & 0x7fffffff));
+}
+
+function prepare_sql_subnet($subnet) {
+ list($snet, $smask) = explode('/', $subnet);
+ $inet = ip2s32($snet);
+ if($smask > 0 && $smask < 32) {
+ $mask = -1 << (32 - (int)$smask);
+ return "and (ip & $mask = $inet)";
+ } elseif ($inet) {
+ return "and ip = " . $inet;
+ }
+ return "";
+}
+
+$starttime = time();
+set_time_limit(300);
+?>
diff --git a/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/index.php b/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/index.php
new file mode 100644
index 0000000..c8b8598
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/phphtdocs-sqlite/index.php
@@ -0,0 +1,190 @@
+<?php
+include("include.php");
+?>
+<html>
+<center>
+<img src=logo.gif>
+<?php
+
+$sensor_name = 'default';
+
+// Get variables from url
+
+if (isset($_GET['interval']) && $_GET['interval'] != "none")
+ $interval = $_GET['interval'];
+
+if (isset($_GET['timestamp']) && $_GET['timestamp'] != "none")
+ $timestamp = $_GET['timestamp'];
+
+if (isset($_GET['subnet']) && $_GET['subnet'] != "none")
+ $subnet = $_GET['subnet'];
+
+if (isset($_GET['limit']) && $_GET['limit'] != "none")
+ $limit = $_GET['limit'];
+
+
+$db = ConnectDb();
+?>
+<FORM name="navigation" method="get">
+<table width=100% cellspacing=0 cellpadding=5 border=1>
+<tr>
+<td><SELECT name="interval">
+<OPTION value="none">--Select An Interval--
+<OPTION value=<?php echo INT_DAILY?> <?php echo $interval==INT_DAILY?"SELECTED":""?>>Daily
+<OPTION value=<?php echo INT_WEEKLY?> <?php echo $interval==INT_WEEKLY?"SELECTED":""?>>Weekly
+<OPTION value=<?php echo INT_MONTHLY?> <?php echo $interval==INT_MONTHLY?"SELECTED":""?>>Monthly
+<OPTION value=<?php echo INT_YEARLY?> <?php echo $interval==INT_YEARLY?"SELECTED":""?>>Yearly
+<OPTION value=<?php echo 24*60*60?> <?php echo $interval==24*60*60?"SELECTED":""?>>24hrs
+<OPTION value=<?php echo 30*24*60*60?> <?php echo $interval==30*24*60*60?"SELECTED":""?>>30days
+</select>
+
+<td><SELECT name="limit">
+<OPTION value="none">--How Many Results--
+<OPTION value=20 <?php echo $limit==20?"SELECTED":""?>>20
+<OPTION value=50 <?php echo $limit==50?"SELECTED":""?>>50
+<OPTION value=100 <?php echo $limit==100?"SELECTED":""?>>100
+<OPTION value=all <?php echo $limit=="all"?"SELECTED":""?>>All
+</select>
+
+<td>Subnet Filter:<input name=subnet value="<?php echo isset($subnet)?$subnet:"0.0.0.0/0"?>">
+<input type=submit value="Go">
+</table>
+</FORM>
+<?php
+// Set defaults
+if (!isset($interval))
+ $interval = DFLT_INTERVAL;
+
+if (!isset($timestamp))
+ $timestamp = time() - $interval + (0.05*$interval);
+
+if (!isset($limit))
+ $limit = 20;
+
+// Validation
+if (!isset($sensor_name))
+ exit(0);
+
+// Print Title
+
+if (isset($limit))
+ echo "<h2>Top $limit - $sensor_name</h2>";
+else
+ echo "<h2>All Records - $sensor_name</h2>";
+
+// Sqlize the incomming variables
+if (isset($subnet)) {
+ $sql_subnet = prepare_sql_subnet($subnet);
+}
+
+// Sql Statement
+$sql = "select tx.ip, rx.scale as rxscale, tx.scale as txscale, tx.total+rx.total as total, tx.total as sent,
+rx.total as received, tx.tcp+rx.tcp as tcp, tx.udp+rx.udp as udp,
+tx.icmp+rx.icmp as icmp, tx.http+rx.http as http,
+tx.p2p+rx.p2p as p2p, tx.ftp+rx.ftp as ftp
+from
+
+(SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp,
+sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp
+from sensors, bd_tx_log
+where sensor_name = '$sensor_name'
+and sensors.sensor_id = bd_tx_log.sensor_id
+$sql_subnet
+and timestamp > $timestamp and timestamp < ".($timestamp+$interval)."
+group by ip) as tx,
+
+(SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp,
+sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp
+from sensors, bd_rx_log
+where sensor_name = '$sensor_name'
+and sensors.sensor_id = bd_rx_log.sensor_id
+$sql_subnet
+and timestamp > $timestamp and timestamp < ".($timestamp+$interval)."
+group by ip) as rx
+
+where tx.ip = rx.ip
+order by total desc;";
+
+//echo "</center><pre>$sql</pre><center>"; error_log($sql);
+$pdoResult = $db->query($sql);
+$result = $pdoResult->fetchAll();
+$db = NULL;
+$num_rows = count($result);
+if ($limit == "all")
+ $limit = $num_rows;
+
+echo "<table width=100% border=1 cellspacing=0><tr><td>Ip<td>Name<td>Total<td>Sent<td>Received<td>tcp<td>udp<td>icmp<td>http<td>smtp<td>ftp";
+
+if (!isset($subnet)) // Set this now for total graphs
+ $subnet = "0.0.0.0/0";
+
+// Output Total Line
+echo "<TR><TD><a href=Total>Total</a><TD>$subnet";
+foreach (array("total", "sent", "received", "tcp", "udp", "icmp", "http", "p2p", "ftp") as $key)
+ {
+ for($Counter=0, $Total = 0; $Counter < $num_rows; $Counter++)
+ {
+ $r = $result[$Counter];
+ $Total += $r[$key];
+ }
+ echo fmtb($Total);
+ }
+echo "\n";
+
+// Output Other Lines
+for($Counter=0; $Counter < $num_rows && $Counter < $limit; $Counter++)
+ {
+ $r = $result[$Counter];
+ $r['ip'] = long2ip($r['ip']);
+ echo "<tr><td><a href=#".$r['ip'].">";
+ echo $r['ip']."<td>".gethostbyaddr($r['ip']);
+ echo "</a>";
+ echo fmtb($r['total']).fmtb($r['sent']).fmtb($r['received']).
+ fmtb($r['tcp']).fmtb($r['udp']).fmtb($r['icmp']).fmtb($r['http']).
+ fmtb($r['p2p']).fmtb($r['ftp'])."\n";
+ }
+echo "</table></center>";
+
+// Output Total Graph
+for($Counter=0, $Total = 0; $Counter < $num_rows; $Counter++)
+ {
+ $r = $result[$Counter];
+ $scale = max($r['txscale'], $scale);
+ $scale = max($r['rxscale'], $scale);
+ }
+
+if ($subnet == "0.0.0.0/0")
+ $total_table = "bd_tx_total_log";
+else
+ $total_table = "bd_tx_log";
+echo "<a name=Total><h3><a href=details.php?sensor_name=$sensor_name&ip=$subnet>";
+echo "Total - Total of $subnet</h3>";
+echo "</a>";
+echo "Send:<br><img src=graph.php?ip=$subnet&interval=$interval&sensor_name=".$sensor_name."&table=$total_table><br>";
+echo "<img src=legend.gif><br>\n";
+if ($subnet == "0.0.0.0/0")
+ $total_table = "bd_rx_total_log";
+else
+ $total_table = "bd_rx_log";
+echo "Receive:<br><img src=graph.php?ip=$subnet&interval=$interval&sensor_name=".$sensor_name."&table=$total_table><br>";
+echo "<img src=legend.gif><br>\n";
+
+
+// Output Other Graphs
+for($Counter=0; $Counter < $num_rows && $Counter < $limit; $Counter++)
+ {
+ $r = $result[$Counter];
+ $r['ip'] = long2ip($r['ip']);
+ echo "<a name=".$r['ip']."><h3><a href=details.php?sensor_name=$sensor_name&ip=".$r['ip'].">";
+ if ($r['ip'] == "0.0.0.0")
+ echo "Total - Total of all subnets</h3>";
+ else
+ echo $r['ip']." - ".gethostbyaddr($r['ip'])."</h3>";
+ echo "</a>";
+ echo "Send:<br><img src=graph.php?ip=".$r['ip']."&interval=$interval&sensor_name=".$sensor_name."&table=bd_tx_log&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+ echo "<img src=legend.gif><br>\n";
+ echo "Receive:<br><img src=graph.php?ip=".$r['ip']."&interval=$interval&sensor_name=".$sensor_name."&table=bd_rx_log&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+ echo "<img src=legend.gif><br>\n";
+ }
+
+include('footer.php');
diff --git a/external/subpack/utils/bandwidthd/files/phphtdocs/details.php b/external/subpack/utils/bandwidthd/files/phphtdocs/details.php
new file mode 100644
index 0000000..cb52f43
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/phphtdocs/details.php
@@ -0,0 +1,102 @@
+<?php
+include("include.php");
+?>
+<html>
+<center>
+<img src=logo.gif>
+<?php
+if (isset($_GET['sensor_name']))
+ $sensor_name = $_GET['sensor_name'];
+else
+ {
+ echo "<br>Please provide a sensor_name";
+ exit(1);
+ }
+
+if (isset($_GET['ip']))
+ $ip = $_GET['ip'];
+else
+ {
+ echo "<br>Please provide an ip address";
+ exit(1);
+ }
+
+echo "<h3>";
+if (strpos($ip, "/") === FALSE)
+ echo "$ip - ".gethostbyaddr($ip)."</h3>";
+else
+ echo "Total - $ip</h3>";
+
+$db = ConnectDb();
+
+if ($ip == "0.0.0.0/0")
+ {
+ $rxtable = "bd_rx_total_log";
+ $txtable = "bd_tx_total_log";
+ }
+else
+ {
+ $rxtable = "bd_rx_log";
+ $txtable = "bd_tx_log";
+ }
+
+$sql = "select rx.scale as rxscale, tx.scale as txscale, tx.total+rx.total as total, tx.total as sent,
+rx.total as received, tx.tcp+rx.tcp as tcp, tx.udp+rx.udp as udp,
+tx.icmp+rx.icmp as icmp, tx.http+rx.http as http,
+tx.p2p+rx.p2p as p2p, tx.ftp+rx.ftp as ftp
+from
+
+(SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp,
+sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp
+from sensors, $txtable
+where sensor_name = '$sensor_name'
+and sensors.sensor_id = ".$txtable.".sensor_id
+and ip <<= '$ip'
+group by ip) as tx,
+
+(SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp,
+sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp
+from sensors, $rxtable
+where sensor_name = '$sensor_name'
+and sensors.sensor_id = ".$rxtable.".sensor_id
+and ip <<= '$ip'
+group by ip) as rx
+
+where tx.ip = rx.ip;";
+//echo "</center><pre>$sql</pre><center>";exit(0);
+$result = pg_query($sql);
+echo "<table width=100% border=1 cellspacing=0><tr><td>Ip<td>Name<td>Total<td>Sent<td>Received<td>tcp<td>udp<td>icmp<td>http<td>smtp<td>ftp";
+$r = pg_fetch_array($result);
+echo "<tr><td>";
+if (strpos($ip, "/") === FALSE)
+ echo "$ip<td>".gethostbyaddr($ip);
+else
+ echo "Total<td>$ip";
+echo fmtb($r['total']).fmtb($r['sent']).fmtb($r['received']).
+ fmtb($r['tcp']).fmtb($r['udp']).fmtb($r['icmp']).fmtb($r['http']).
+ fmtb($r['p2p']).fmtb($r['ftp']);
+echo "</table></center>";
+
+echo "<center><h4>Daily</h4></center>";
+echo "Send:<br><img src=graph.php?ip=$ip&sensor_name=".$sensor_name."&table=$txtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+echo "Receive:<br><img src=graph.php?ip=$ip&sensor_name=".$sensor_name."&table=$rxtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+
+echo "<center><h4>Weekly</h4></center>";
+echo "Send:<br><img src=graph.php?interval=".INT_WEEKLY."&ip=$ip&sensor_name=$sensor_name&table=$txtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+echo "Receive:<br><img src=graph.php?interval=".INT_WEEKLY."&ip=$ip&sensor_name=$sensor_name&table=$rxtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+
+echo "<center><h4>Monthly</h4></center>";
+echo "Send:<br><img src=graph.php?interval=".INT_MONTHLY."&ip=$ip&sensor_name=$sensor_name&table=$txtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+echo "Receive:<br><img src=graph.php?interval=".INT_MONTHLY."&ip=$ip&sensor_name=$sensor_name&table=$rxtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+
+echo "<center><h4>Yearly</h4></center>";
+echo "Send:<br><img src=graph.php?interval=".INT_YEARLY."&ip=$ip&sensor_name=$sensor_name&table=$txtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
+echo "Receive:<br><img src=graph.php?interval=".INT_YEARLY."&ip=$ip&sensor_name=$sensor_name&table=$rxtable&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+echo "<img src=legend.gif><br>";
diff --git a/external/subpack/utils/bandwidthd/files/phphtdocs/footer.php b/external/subpack/utils/bandwidthd/files/phphtdocs/footer.php
new file mode 100644
index 0000000..b342825
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/phphtdocs/footer.php
@@ -0,0 +1,3 @@
+<?php
+echo("Page load completed in ". (time() - $starttime) ." seconds");
+?>
diff --git a/external/subpack/utils/bandwidthd/files/phphtdocs/graph.php b/external/subpack/utils/bandwidthd/files/phphtdocs/graph.php
new file mode 100644
index 0000000..323d659
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/phphtdocs/graph.php
@@ -0,0 +1,454 @@
+<?php
+require("include.php");
+
+// Returns x location of any given timestamp
+function ts2x($ts)
+ {
+ global $timestamp, $width, $interval;
+ return(($ts-$timestamp)*(($width-XOFFSET) / $interval) + XOFFSET);
+ }
+
+// If we have multiple IP's in a result set we need to total the average of each IP's samples
+function AverageAndAccumulate()
+ {
+ global $Count, $total, $icmp, $udp, $tcp, $ftp, $http, $p2p, $YMax;
+ global $a_total, $a_icmp, $a_udp, $a_tcp, $a_ftp, $a_http, $a_p2p;
+
+ foreach ($Count as $key => $number)
+ {
+ $total[$key] /= $number;
+ $icmp[$key] /= $number;
+ $udp[$key] /= $number;
+ $tcp[$key] /= $number;
+ $ftp[$key] /= $number;
+ $http[$key] /= $number;
+ $p2p[$key] /= $number;
+ }
+
+ foreach ($Count as $key => $number)
+ {
+ $a_total[$key] += $total[$key];
+ $a_icmp[$key] += $icmp[$key];
+ $a_udp[$key] += $udp[$key];
+ $a_tcp[$key] += $tcp[$key];
+ $a_ftp[$key] += $ftp[$key];
+ $a_http[$key] += $http[$key];
+ $a_p2p[$key] += $p2p[$key];
+
+ if ($a_total[$key] > $YMax)
+ $YMax = $a_total[$key];
+ }
+
+ unset($GLOBALS['total'], $GLOBALS['icmp'], $GLOBALS['udp'], $GLOBALS['tcp'], $GLOBALS['ftp'], $GLOBALS['http'], $GLOBALS['p2p'], $GLOBALS['Count']);
+
+ $total = array();
+ $icmp = array();
+ $udp = array();
+ $tcp = array();
+ $ftp = array();
+ $http = array();
+ $p2p = array();
+ $Count = array();
+ }
+
+$db = ConnectDb();
+
+// Get parameters
+
+if (isset($_GET['width']))
+ $width = $_GET['width'];
+else
+ $width = DFLT_WIDTH;
+
+if (isset($_GET['height']))
+ $height = $_GET['height'];
+else
+ $height = DFLT_HEIGHT;
+
+if (isset($_GET['interval']))
+ $interval = $_GET['interval'];
+else
+ $interval = DFLT_INTERVAL;
+
+if (isset($_GET['ip']))
+ $ip = $_GET['ip'];
+else
+ exit(1);
+
+if (isset($_GET['sensor_name']))
+ $sensor_name = $_GET['sensor_name'];
+else
+ exit(1);
+
+if (isset($_GET['timestamp']))
+ $timestamp = $_GET['timestamp'];
+else
+ $timestamp = time() - $interval + (0.05*$interval);
+
+if (isset($_GET['table']))
+ $table = $_GET['table'];
+else
+ $table = "bd_rx_log";
+
+if (isset($_GET['yscale']))
+ $yscale = $_GET['yscale'];
+
+$total = array();
+$icmp = array();
+$udp = array();
+$tcp = array();
+$ftp = array();
+$http = array();
+$p2p = array();
+$Count = array();
+
+// Accumulator
+$a_total = array();
+$a_icmp = array();
+$a_udp = array();
+$a_tcp = array();
+$a_ftp = array();
+$a_http = array();
+$a_p2p = array();
+
+$sql = "select *, extract(epoch from timestamp) as ts from sensors, $table where sensors.sensor_id = ".$table.".sensor_id and ip <<= '$ip' and sensor_name = '$sensor_name' and timestamp > $timestamp::abstime and timestamp < ".($timestamp+$interval)."::abstime order by ip;";
+//echo $sql."<br>"; exit(1);
+$result = pg_query($sql);
+
+// The SQL statement pulls the data out of the database ordered by IP address, that way we can average each
+// datapoint for each IP address to provide smoothing and then toss the smoothed value into the accumulator
+// to provide accurate total traffic rate.
+
+while ($row = pg_fetch_array($result))
+ {
+ if ($row['ip'] != $last_ip)
+ {
+ AverageAndAccumulate();
+ $last_ip = $row['ip'];
+ }
+
+ $x = ($row['ts']-$timestamp)*(($width-XOFFSET)/$interval)+XOFFSET;
+ $xint = (int) $x;
+
+ //echo "xint: ".$xint."<br>";
+ $Count[$xint]++;
+
+ if ($row['total']/$row['sample_duration'] > $SentPeak)
+ $SentPeak = $row['total']/$row['sample_duration'];
+ $TotalSent += $row['total'];
+ $total[$xint] += $row['total']/$row['sample_duration'];
+ $icmp[$xint] += $row['icmp']/$row['sample_duration'];
+ $udp[$xint] += $row['udp']/$row['sample_duration'];
+ $tcp[$xint] += $row['tcp']/$row['sample_duration'];
+ $ftp[$xint] += $row['ftp']/$row['sample_duration'];
+ $http[$xint] += $row['http']/$row['sample_duration'];
+ $p2p[$xint] += $row['p2p']/$row['sample_duration'];
+ }
+
+// One more time for the last IP
+AverageAndAccumulate();
+
+// Pull the data out of Accumulator
+$total = $a_total;
+$icmp = $a_icmp;
+$udp = $a_udp;
+$tcp = $a_tcp;
+$ftp = $a_ftp;
+$http = $a_http;
+$p2p = $a_p2p;
+
+$YMax += $YMax*0.05; // Add an extra 5%
+
+// if a y scale was specified override YMax
+if (isset($yscale))
+ $YMax = $yscale/8;
+
+// Plot the data
+
+header("Content-type: image/png");
+
+$im = imagecreate($width, $height);
+$white = imagecolorallocate($im, 255, 255, 255);
+$purple = ImageColorAllocate($im, 255, 0, 255);
+$green = ImageColorAllocate($im, 0, 255, 0);
+$blue = ImageColorAllocate($im, 0, 0, 255);
+$lblue = ImageColorAllocate($im, 128, 128, 255);
+$brown = ImageColorAllocate($im, 128, 0, 0);
+$red = ImageColorAllocate($im, 255, 0, 0);
+$black = ImageColorAllocate($im, 0, 0, 0);
+
+for($Counter=XOFFSET+1; $Counter < $width; $Counter++)
+ {
+ if (isset($total[$Counter]))
+ {
+ // Convert the bytes/sec to y coords
+ $total[$Counter] = ($total[$Counter]*($height-YOFFSET))/$YMax;
+ $tcp[$Counter] = ($tcp[$Counter]*($height-YOFFSET))/$YMax;
+ $ftp[$Counter] = ($ftp[$Counter]*($height-YOFFSET))/$YMax;
+ $http[$Counter] = ($http[$Counter]*($height-YOFFSET))/$YMax;
+ $p2p[$Counter] = ($p2p[$Counter]*($height-YOFFSET))/$YMax;
+ $udp[$Counter] = ($udp[$Counter]*($height-YOFFSET))/$YMax;
+ $icmp[$Counter] = ($icmp[$Counter]*($height-YOFFSET))/$YMax;
+
+ // Stack 'em up!
+ // Total is stacked from the bottom
+ // Icmp is on the bottom too
+ // Udp is stacked on top of icmp
+ $udp[$Counter] += $icmp[$Counter];
+ // TCP and p2p are stacked on top of Udp
+ $tcp[$Counter] += $udp[$Counter];
+ $p2p[$Counter] += $udp[$Counter];
+ // Http is stacked on top of p2p
+ $http[$Counter] += $p2p[$Counter];
+ // Ftp is stacked on top of http
+ $ftp[$Counter] += $http[$Counter];
+
+ // Plot them!
+ //echo "$Counter:".$Counter." (h-y)-t:".($height-YOFFSET) - $total[$Counter]." h-YO-1:".$height-YOFFSET-1;
+ ImageLine($im, $Counter, ($height-YOFFSET) - $icmp[$Counter], $Counter, $height-YOFFSET-1, $red);
+ ImageLine($im, $Counter, ($height-YOFFSET) - $udp[$Counter], $Counter, ($height-YOFFSET) - $icmp[$Counter] - 1, $brown);
+ ImageLine($im, $Counter, ($height-YOFFSET) - $tcp[$Counter], $Counter, ($height-YOFFSET) - $udp[$Counter] - 1, $green);
+ ImageLine($im, $Counter, ($height-YOFFSET) - $p2p[$Counter], $Counter, ($height-YOFFSET) - $udp[$Counter] - 1, $purple);
+ ImageLine($im, $Counter, ($height-YOFFSET) - $http[$Counter], $Counter, ($height-YOFFSET) - $p2p[$Counter] - 1, $blue);
+ ImageLine($im, $Counter, ($height-YOFFSET) - $ftp[$Counter], $Counter, ($height-YOFFSET) - $http[$Counter] - 1, $lblue);
+ }
+// else
+// echo $Counter." not set<br>";
+ }
+
+// Margin Text
+if ($SentPeak < 1024/8)
+ $txtPeakSendRate = sprintf("Peak Send Rate: %.1f KBits/sec", $SentPeak*8);
+else if ($SentPeak < (1024*1024)/8)
+ $txtPeakSendRate = sprintf("Peak Send Rate: %.1f MBits/sec", ($SentPeak*8.0)/1024.0);
+else
+ $txtPeakSendRate = sprintf("Peak Send Rate: %.1f GBits/sec", ($SentPeak*8.0)/(1024.0*1024.0));
+
+if ($TotalSent < 1024)
+ $txtTotalSent = sprintf("Sent %.1f KBytes", $TotalSent);
+else if ($TotalSent < 1024*1024)
+ $txtTotalSent = sprintf("Sent %.1f MBytes", $TotalSent/1024.0);
+else
+ $txtTotalSent = sprintf("Sent %.1f GBytes", $TotalSent/(1024.0*1024.0));
+
+ImageString($im, 2, XOFFSET+5, $height-20, $txtTotalSent, $black);
+ImageString($im, 2, $width/2+XOFFSET/2, $height-20, $txtPeakSendRate, $black);
+
+// Draw X Axis
+
+ImageLine($im, 0, $height-YOFFSET, $width, $height-YOFFSET, $black);
+
+// Day/Month Seperator bars
+
+if ((24*60*60*($width-XOFFSET))/$interval > ($width-XOFFSET)/10)
+ {
+ $ts = getdate($timestamp);
+ $MarkTime = mktime(0, 0, 0, $ts['mon'], $ts['mday'], $ts['year']);
+
+ $x = ts2x($MarkTime);
+ while ($x < XOFFSET)
+ {
+ $MarkTime += (24*60*60);
+ $x = ts2x($MarkTime);
+ }
+
+ while ($x < ($width-10))
+ {
+ // Day Lines
+ ImageLine($im, $x, 0, $x, $height-YOFFSET, $black);
+ ImageLine($im, $x+1, 0, $x+1, $height-YOFFSET, $black);
+
+ $txtDate = strftime("%a, %b %d", $MarkTime);
+ ImageString($im, 2, $x-30, $height-YOFFSET+10, $txtDate, $black);
+
+ // Calculate Next x
+ $MarkTime += (24*60*60);
+ $x = ts2x($MarkTime);
+ }
+ }
+else if ((24*60*60*30*($width-XOFFSET))/$interval > ($width-XOFFSET)/10)
+ {
+ // Monthly Bars
+ $ts = getdate($timestamp);
+ $month = $ts['mon'];
+ $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']);
+
+ $x = ts2x($MarkTime);
+ while ($x < XOFFSET)
+ {
+ $month++;
+ $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']);
+ $x = ts2x($MarkTime);
+ }
+
+ while ($x < ($width-10))
+ {
+ // Day Lines
+ ImageLine($im, $x, 0, $x, $height-YOFFSET, $black);
+ ImageLine($im, $x+1, 0, $x+1, $height-YOFFSET, $black);
+
+ $txtDate = strftime("%b, %Y", $MarkTime);
+ ImageString($im, 2, $x-25, $height-YOFFSET+10, $txtDate, $black);
+
+ // Calculate Next x
+ $month++;
+ $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']);
+ $x = ts2x($MarkTime);
+ }
+ }
+else
+ {
+ // Year Bars
+ $ts = getdate($timestamp);
+ $year = $ts['year'];
+ $MarkTime = mktime(0, 0, 0, 1, 1, $year);
+
+ $x = ts2x($MarkTime);
+ while ($x < XOFFSET)
+ {
+ $year++;
+ $MarkTime = mktime(0, 0, 0, 1, 1, $year);
+ $x = ts2x($MarkTime);
+ }
+
+ while ($x < ($width-10))
+ {
+ // Day Lines
+ ImageLine($im, $x, 0, $x, $height-YOFFSET, $black);
+ ImageLine($im, $x+1, 0, $x+1, $height-YOFFSET, $black);
+
+ $txtDate = strftime("%b, %Y", $MarkTime);
+ ImageString($im, 2, $x-25, $height-YOFFSET+10, $txtDate, $black);
+
+ // Calculate Next x
+ $year++;
+ $MarkTime = mktime(0, 0, 0, 1, 1, $year);
+ $x = ts2x($MarkTime);
+ }
+ }
+
+// Draw Major Tick Marks
+if ((6*60*60*($width-XOFFSET))/$interval > 10) // pixels per 6 hours is more than 2
+ $MarkTimeStep = 6*60*60; // Major ticks are 6 hours
+else if ((24*60*60*($width-XOFFSET))/$interval > 10)
+ $MarkTimeStep = 24*60*60; // Major ticks are 24 hours;
+else if ((24*60*60*30*($width-XOFFSET))/$interval > 10)
+ {
+ // Major tick marks are months
+ $MarkTimeStep = 0; // Skip the standard way of drawing major tick marks below
+
+ $ts = getdate($timestamp);
+ $month = $ts['mon'];
+ $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']);
+
+ $x = ts2x($MarkTime);
+ while ($x < XOFFSET)
+ {
+ $month++;
+ $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']);
+ $x = ts2x($MarkTime);
+ }
+
+ while ($x < ($width-10))
+ {
+ // Day Lines
+ $date = getdate($MarkTime);
+ if ($date['mon'] != 1)
+ {
+ ImageLine($im, $x, $height-YOFFSET-5, $x, $height-YOFFSET+5, $black);
+ $txtDate = strftime("%b", $MarkTime);
+ ImageString($im, 2, $x-5, $height-YOFFSET+10, $txtDate, $black);
+ }
+
+ // Calculate Next x
+ $month++;
+ $MarkTime = mktime(0, 0, 0, $month, 1, $ts['year']);
+ $x = ts2x($MarkTime);
+ }
+ }
+else
+ $MarkTimeStep = 0; // Skip Major Tick Marks
+
+if ($MarkTimeStep)
+ {
+ $ts = getdate($timestamp);
+ $MarkTime = mktime(0, 0, 0, $ts['mon'], $ts['mday'], $ts['year']);
+ $x = ts2x($MarkTime);
+
+ while ($x < ($width-10))
+ {
+ if ($x > XOFFSET)
+ {
+ ImageLine($im, $x, $height-YOFFSET-5, $x, $height-YOFFSET+5, $black);
+ }
+ $MarkTime += $MarkTimeStep;
+ $x = ts2x($MarkTime);
+ }
+ }
+
+// Draw Minor Tick marks
+if ((60*60*($width-XOFFSET))/$interval > 4) // pixels per hour is more than 2
+ $MarkTimeStep = 60*60; // Minor ticks are 1 hour
+else if ((6*60*60*($width-XOFFSET))/$interval > 4)
+ $MarkTimeStep = 6*60*60; // Minor ticks are 6 hours
+else if ((24*60*60*($width-XOFFSET))/$interval > 4)
+ $MarkTimeStep = 24*60*60;
+else
+ $MarkTimeStep = 0; // Skip minor tick marks
+
+if ($MarkTimeStep)
+ {
+ $ts = getdate($timestamp);
+ $MarkTime = mktime(0, 0, 0, $ts['mon'], $ts['mday'], $ts['year']);
+ $x = ts2x($MarkTime);
+
+ while ($x < ($width-10))
+ {
+ if ($x > XOFFSET)
+ {
+ ImageLine($im, $x, $height-YOFFSET, $x, $height-YOFFSET+5, $black);
+ }
+ $MarkTime += $MarkTimeStep;
+ $x = ts2x($MarkTime);
+ }
+ }
+
+// Draw Y Axis
+ImageLine($im, XOFFSET, 0, XOFFSET, $height, $black);
+
+$YLegend = 'k';
+$Divisor = 1;
+if ($YMax*8 > 1024*2)
+ {
+ $Divisor = 1024; // Display in m
+ $YLegend = 'm';
+ }
+
+if ($YMax*8 > 1024*1024*2)
+ {
+ $Divisor = 1024*1024; // Display in g
+ $YLegend = 'g';
+ }
+
+if ($YMax*8 > 1024*1024*1024*2)
+ {
+ $Divisor = 1024*1024*1024; // Display in t
+ $YLegend = 't';
+ }
+
+$YStep = $YMax/10;
+if ($YStep < 1)
+ $YStep=1;
+$YTic=$YStep;
+
+while ($YTic <= ($YMax - $YMax/10))
+ {
+ $y = ($height-YOFFSET)-(($YTic*($height-YOFFSET))/$YMax);
+ ImageLine($im, XOFFSET, $y, $width, $y, $black);
+ $txtYLegend = sprintf("%4.1f %sbits/s", (8.0*$YTic)/$Divisor, $YLegend);
+ ImageString($im, 2, 3, $y-7, $txtYLegend, $black);
+ $YTic += $YStep;
+ }
+
+imagepng($im);
+imagedestroy($im);
diff --git a/external/subpack/utils/bandwidthd/files/phphtdocs/include.php b/external/subpack/utils/bandwidthd/files/phphtdocs/include.php
new file mode 100644
index 0000000..6b435d1
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/phphtdocs/include.php
@@ -0,0 +1,54 @@
+<?php
+define("INT_DAILY", 60*60*24*2);
+define("INT_WEEKLY", 60*60*24*8);
+define("INT_MONTHLY", 60*60*24*35);
+define("INT_YEARLY", 60*60*24*400);
+
+define("XOFFSET", 90);
+define("YOFFSET", 45);
+
+require("config.conf");
+
+function ConnectDb()
+ {
+ global $db_connect_string;
+
+ $db = pg_pconnect($db_connect_string);
+ if (!$db)
+ {
+ printf("DB Error, could not connect to database");
+ exit(1);
+ }
+ return($db);
+ }
+
+function fmtb($kbytes)
+ {
+ $Max = 1024;
+ $Output = $kbytes;
+ $Suffix = 'K';
+
+ if ($Output > $Max)
+ {
+ $Output /= 1024;
+ $Suffix = 'M';
+ }
+
+ if ($Output > $Max)
+ {
+ $Output /= 1024;
+ $Suffix = 'G';
+ }
+
+ if ($Output > $Max)
+ {
+ $Output /= 1024;
+ $Suffix = 'T';
+ }
+
+ return(sprintf("<td align=right><tt>%.1f%s</td>", $Output, $Suffix));
+ }
+
+$starttime = time();
+set_time_limit(300);
+?>
diff --git a/external/subpack/utils/bandwidthd/files/phphtdocs/index.php b/external/subpack/utils/bandwidthd/files/phphtdocs/index.php
new file mode 100644
index 0000000..b3602af
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/files/phphtdocs/index.php
@@ -0,0 +1,197 @@
+<?php
+include("include.php");
+?>
+<html>
+<center>
+<img src=logo.gif>
+<?php
+// Get variables from url
+
+if (isset($_GET['sensor_name']) && $_GET['sensor_name'] != "none")
+ $sensor_name = $_GET['sensor_name'];
+
+if (isset($_GET['interval']) && $_GET['interval'] != "none")
+ $interval = $_GET['interval'];
+
+if (isset($_GET['timestamp']) && $_GET['timestamp'] != "none")
+ $timestamp = $_GET['timestamp'];
+
+if (isset($_GET['subnet']) && $_GET['subnet'] != "none")
+ $subnet = $_GET['subnet'];
+
+if (isset($_GET['limit']) && $_GET['limit'] != "none")
+ $limit = $_GET['limit'];
+
+
+$db = ConnectDb();
+?>
+<FORM name="navigation" method=get action=<?php echo $PHP_SELF?>>
+<table width=100% cellspacing=0 cellpadding=5 border=1>
+<tr>
+<td><SELECT name="sensor_name">
+
+<OPTION value="none">--Select A Sensor--
+<?php
+$sql = "SELECT sensor_name from sensors order by sensor_name;";
+$result = pg_query($sql);
+while ($r = pg_fetch_array($result))
+ echo "<option value=\"".$r['sensor_name']."\" ".($sensor_name==$r['sensor_name']?"SELECTED":"").">".$r['sensor_name']."\n";
+?>
+</SELECT>
+<td><SELECT name="interval">
+<OPTION value="none">--Select An Interval--
+<OPTION value=<?php echo INT_DAILY?> <?php echo $interval==INT_DAILY?"SELECTED":""?>>Daily
+<OPTION value=<?php echo INT_WEEKLY?> <?php echo $interval==INT_WEEKLY?"SELECTED":""?>>Weekly
+<OPTION value=<?php echo INT_MONTHLY?> <?php echo $interval==INT_MONTHLY?"SELECTED":""?>>Monthly
+<OPTION value=<?php echo INT_YEARLY?> <?php echo $interval==INT_YEARLY?"SELECTED":""?>>Yearly
+<OPTION value=<?php echo 24*60*60?> <?php echo $interval==24*60*60?"SELECTED":""?>>24hrs
+<OPTION value=<?php echo 30*24*60*60?> <?php echo $interval==30*24*60*60?"SELECTED":""?>>30days
+</select>
+
+<td><SELECT name="limit">
+<OPTION value="none">--How Many Results--
+<OPTION value=20 <?php echo $limit==20?"SELECTED":""?>>20
+<OPTION value=50 <?php echo $limit==50?"SELECTED":""?>>50
+<OPTION value=100 <?php echo $limit==100?"SELECTED":""?>>100
+<OPTION value=all <?php echo $limit=="all"?"SELECTED":""?>>All
+</select>
+
+<td>Subnet Filter:<input name=subnet value="<?php echo isset($subnet)?$subnet:"0.0.0.0/0"?>">
+<input type=submit value="Go">
+</table>
+</FORM>
+<?php
+// Set defaults
+if (!isset($interval))
+ $interval = DFLT_INTERVAL;
+
+if (!isset($timestamp))
+ $timestamp = time() - $interval + (0.05*$interval);
+
+if (!isset($limit))
+ $limit = 20;
+
+// Validation
+if (!isset($sensor_name))
+ exit(0);
+
+// Print Title
+
+if (isset($limit))
+ echo "<h2>Top $limit - $sensor_name</h2>";
+else
+ echo "<h2>All Records - $sensor_name</h2>";
+
+// Sqlize the incomming variables
+if (isset($subnet))
+ $sql_subnet = "and ip <<= '$subnet'";
+
+// Sql Statement
+$sql = "select tx.ip, rx.scale as rxscale, tx.scale as txscale, tx.total+rx.total as total, tx.total as sent,
+rx.total as received, tx.tcp+rx.tcp as tcp, tx.udp+rx.udp as udp,
+tx.icmp+rx.icmp as icmp, tx.http+rx.http as http,
+tx.p2p+rx.p2p as p2p, tx.ftp+rx.ftp as ftp
+from
+
+(SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp,
+sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp
+from sensors, bd_tx_log
+where sensor_name = '$sensor_name'
+and sensors.sensor_id = bd_tx_log.sensor_id
+$sql_subnet
+and timestamp > $timestamp::abstime and timestamp < ".($timestamp+$interval)."::abstime
+group by ip) as tx,
+
+(SELECT ip, max(total/sample_duration)*8 as scale, sum(total) as total, sum(tcp) as tcp, sum(udp) as udp, sum(icmp) as icmp,
+sum(http) as http, sum(p2p) as p2p, sum(ftp) as ftp
+from sensors, bd_rx_log
+where sensor_name = '$sensor_name'
+and sensors.sensor_id = bd_rx_log.sensor_id
+$sql_subnet
+and timestamp > $timestamp::abstime and timestamp < ".($timestamp+$interval)."::abstime
+group by ip) as rx
+
+where tx.ip = rx.ip
+order by total desc;";
+
+//echo "</center><pre>$sql</pre><center>"; exit(0);
+pg_query("SET sort_mem TO 30000;");
+$result = pg_query($sql);
+pg_query("set sort_mem to default;");
+
+if ($limit == "all")
+ $limit = pg_num_rows($result);
+
+echo "<table width=100% border=1 cellspacing=0><tr><td>Ip<td>Name<td>Total<td>Sent<td>Received<td>tcp<td>udp<td>icmp<td>http<td>smtp<td>ftp";
+
+if (!isset($subnet)) // Set this now for total graphs
+ $subnet = "0.0.0.0/0";
+
+// Output Total Line
+echo "<TR><TD><a href=Total>Total</a><TD>$subnet";
+foreach (array("total", "sent", "received", "tcp", "udp", "icmp", "http", "p2p", "ftp") as $key)
+ {
+ for($Counter=0, $Total = 0; $Counter < pg_num_rows($result); $Counter++)
+ {
+ $r = pg_fetch_array($result, $Counter);
+ $Total += $r[$key];
+ }
+ echo fmtb($Total);
+ }
+echo "\n";
+
+// Output Other Lines
+for($Counter=0; $Counter < pg_num_rows($result) && $Counter < $limit; $Counter++)
+ {
+ $r = pg_fetch_array($result, $Counter);
+ echo "<tr><td><a href=#".$r['ip'].">";
+ echo $r['ip']."<td>".gethostbyaddr($r['ip']);
+ echo "</a>";
+ echo fmtb($r['total']).fmtb($r['sent']).fmtb($r['received']).
+ fmtb($r['tcp']).fmtb($r['udp']).fmtb($r['icmp']).fmtb($r['http']).
+ fmtb($r['p2p']).fmtb($r['ftp'])."\n";
+ }
+echo "</table></center>";
+
+// Output Total Graph
+for($Counter=0, $Total = 0; $Counter < pg_num_rows($result); $Counter++)
+ {
+ $r = pg_fetch_array($result, $Counter);
+ $scale = max($r['txscale'], $scale);
+ $scale = max($r['rxscale'], $scale);
+ }
+
+if ($subnet == "0.0.0.0/0")
+ $total_table = "bd_tx_total_log";
+else
+ $total_table = "bd_tx_log";
+echo "<a name=Total><h3><a href=details.php?sensor_name=$sensor_name&ip=$subnet>";
+echo "Total - Total of $subnet</h3>";
+echo "</a>";
+echo "Send:<br><img src=graph.php?ip=$subnet&interval=$interval&sensor_name=".$sensor_name."&table=$total_table><br>";
+echo "<img src=legend.gif><br>\n";
+if ($subnet == "0.0.0.0/0")
+ $total_table = "bd_rx_total_log";
+else
+ $total_table = "bd_rx_log";
+echo "Receive:<br><img src=graph.php?ip=$subnet&interval=$interval&sensor_name=".$sensor_name."&table=$total_table><br>";
+echo "<img src=legend.gif><br>\n";
+
+
+// Output Other Graphs
+for($Counter=0; $Counter < pg_num_rows($result) && $Counter < $limit; $Counter++)
+ {
+ $r = pg_fetch_array($result, $Counter);
+ echo "<a name=".$r['ip']."><h3><a href=details.php?sensor_name=$sensor_name&ip=".$r['ip'].">";
+ if ($r['ip'] == "0.0.0.0")
+ echo "Total - Total of all subnets</h3>";
+ else
+ echo $r['ip']." - ".gethostbyaddr($r['ip'])."</h3>";
+ echo "</a>";
+ echo "Send:<br><img src=graph.php?ip=".$r['ip']."&interval=$interval&sensor_name=".$sensor_name."&table=bd_tx_log&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+ echo "<img src=legend.gif><br>\n";
+ echo "Receive:<br><img src=graph.php?ip=".$r['ip']."&interval=$interval&sensor_name=".$sensor_name."&table=bd_rx_log&yscale=".(max($r['txscale'], $r['rxscale']))."><br>";
+ echo "<img src=legend.gif><br>\n";
+ }
+
+include('footer.php');
diff --git a/external/subpack/utils/bandwidthd/patches/010-dont-add-host-paths-in-config.in.patch b/external/subpack/utils/bandwidthd/patches/010-dont-add-host-paths-in-config.in.patch
new file mode 100644
index 0000000..cfaba70
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/patches/010-dont-add-host-paths-in-config.in.patch
@@ -0,0 +1,24 @@
+--- a/configure.in
++++ b/configure.in
+@@ -24,11 +24,6 @@ if test -n "$x_libraries" && test "x$x_l
+ LDFLAGS="$LDFLAGS -L$x_libraries"
+ fi
+
+-# May be equired for BSD
+-LDFLAGS="$LDFLAGS -L/usr/local/lib"
+-
+-CPPFLAGS="$CPPFLAGS -I/usr/local/include"
+-
+ #Check for Darwin sw directory
+ AC_CHECK_FILE(/sw/lib, LDFLAGS="$LDFLAGS -L/sw/lib")
+ AC_CHECK_FILE(/sw/include, CPPFLAGS="$CPPFLAGS -I/sw/include")
+@@ -55,8 +50,7 @@ AC_CHECK_LIB(pcap, pcap_open_live, ,
+ [AC_CHECK_LIB(wpcap, pcap_open_live, ,[AC_MSG_ERROR([Bandwidthd requires but cannot find libpcap])])])
+
+ # Optional Library
+-AC_CHECK_FILE(/usr/lib, LDFLAGS="$LDFLAGS -L/usr/lib")
+-AC_CHECK_FILE(/usr/include/pgsql, CPPFLAGS="$CPPFLAGS -I/usr/include/pgsql")
++AC_CHECK_FILE(/usr/local/pgsql/include, CPPFLAGS="$CPPFLAGS -I/usr/local/pgsql/include")
+ AC_CHECK_LIB(pq, PQconnectdb,
+ [AC_CHECK_LIB(pq,PQexecParams, ,AC_MSG_WARN([libpq exists but is too old... bandwidthd requires support for PQexecParams]))])
+ AC_CHECK_LIB(sqlite3, sqlite3_open, ,AC_MSG_WARN([sqlite3 is recommended for storage of data but cannot be found]))
diff --git a/external/subpack/utils/bandwidthd/patches/020-change-p2p-to-smtp.patch b/external/subpack/utils/bandwidthd/patches/020-change-p2p-to-smtp.patch
new file mode 100644
index 0000000..d0e6144
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/patches/020-change-p2p-to-smtp.patch
@@ -0,0 +1,20 @@
+--- a/graph.c
++++ b/graph.c
+@@ -274,7 +274,7 @@ void MakeIndexPages(int NumIps, struct S
+
+ // PASS 1: Write out the table
+
+- fprintf(file, "<TR bgcolor=lightblue><TD>Ip and Name<TD align=center>Total<TD align=center>Total Sent<TD align=center>Total Received<TD align=center>FTP<TD align=center>HTTP<TD align=center>P2P<TD align=center>TCP<TD align=center>UDP<TD align=center>ICMP\n");
++ fprintf(file, "<TR bgcolor=lightblue><TD>Ip and Name<TD align=center>Total<TD align=center>Total Sent<TD align=center>Total Received<TD align=center>FTP<TD align=center>HTTP<TD align=center>SMTP<TD align=center>TCP<TD align=center>UDP<TD align=center>ICMP\n");
+ for (Counter=0; Counter < 21 && Counter < NumIps; Counter++)
+ PrintTableLine(file, SummaryData[Counter], Counter);
+
+@@ -341,7 +341,7 @@ void MakeIndexPages(int NumIps, struct S
+
+ // PASS 1: Write out the table
+
+- fprintf(file, "<TR bgcolor=lightblue><TD>Ip and Name<TD align=center>Total<TD align=center>Total Sent<TD align=center>Total Received<TD align=center>FTP<TD align=center>HTTP<TD align=center>P2P<TD align=center>TCP<TD align=center>UDP<TD align=center>ICMP\n");
++ fprintf(file, "<TR bgcolor=lightblue><TD>Ip and Name<TD align=center>Total<TD align=center>Total Sent<TD align=center>Total Received<TD align=center>FTP<TD align=center>HTTP<TD align=center>SMTP<TD align=center>TCP<TD align=center>UDP<TD align=center>ICMP\n");
+ for (tCounter=0, Counter=0; Counter < NumIps; Counter++)
+ {
+ if (SubnetTable[SubnetCounter].ip == (SummaryData[Counter]->IP & SubnetTable[SubnetCounter].mask))
diff --git a/external/subpack/utils/bandwidthd/patches/030-gcc10.patch b/external/subpack/utils/bandwidthd/patches/030-gcc10.patch
new file mode 100644
index 0000000..04d3ce0
--- /dev/null
+++ b/external/subpack/utils/bandwidthd/patches/030-gcc10.patch
@@ -0,0 +1,20 @@
+--- a/bandwidthd.h
++++ b/bandwidthd.h
+@@ -120,7 +120,7 @@ struct config
+ char *sensor_id;
+ };
+
+-struct SubnetData
++extern struct SubnetData
+ {
+ uint32_t ip;
+ uint32_t mask;
+@@ -139,7 +139,7 @@ struct Statistics
+ unsigned long long p2p;
+ };
+
+-struct IPData
++extern struct IPData
+ {
+ time_t timestamp;
+ uint32_t ip; // Host byte order
diff --git a/external/subpack/utils/banhosts/Makefile b/external/subpack/utils/banhosts/Makefile
new file mode 100644
index 0000000..0087a6f
--- /dev/null
+++ b/external/subpack/utils/banhosts/Makefile
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=banhostlist
+PKG_VERSION:=1
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_MAINTAINER:=Matteo Croce <matteo@openwrt.org>
+PKG_LICENCE:=GPL-2.0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/banhostlist
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=List of advertising domains
+ URL:=http://winhelp2002.mvps.org/
+endef
+
+define Package/banhostlist/description
+List of domains serving advertising and malicious content to easily block them
+endef
+
+
+define Build/Compile/Default
+endef
+
+define Package/banhostlist/install
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/iface
+ $(INSTALL_BIN) ./files/updatebanhost $(1)/etc/hotplug.d/iface/80-banhosts
+endef
+
+$(eval $(call BuildPackage,banhostlist))
diff --git a/external/subpack/utils/banhosts/files/updatebanhost b/external/subpack/utils/banhosts/files/updatebanhost
new file mode 100644
index 0000000..a00d9cb
--- /dev/null
+++ b/external/subpack/utils/banhosts/files/updatebanhost
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+file=/tmp/banhost
+
+gethosts() {
+ logger -t "banhost[$$]" "Update $file"
+ wget -qO- http://winhelp2002.mvps.org/hosts.txt |awk 'BEGIN{printf "0.0.0.0"}/^0\.0\.0\.0/{printf " "$2}END{exit(!FNR)}' >$file || exit 1
+ echo -n $time >$file.time
+ exec killall -HUP dnsmasq
+}
+
+if [ "$ACTION" = ifup -a "$INTERFACE" = wan ]; then
+ read time </proc/uptime
+ time=${time%%.*}
+
+ [ -f $file -a -f $file.time ] || gethosts
+ read oldtime <$file.time
+ [ $((time - oldtime)) -lt 604800 ] || gethosts
+fi
diff --git a/external/subpack/utils/bash/Makefile b/external/subpack/utils/bash/Makefile
new file mode 100644
index 0000000..ca03b62
--- /dev/null
+++ b/external/subpack/utils/bash/Makefile
@@ -0,0 +1,100 @@
+#
+# Copyright (C) 2007-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bash
+PKG_VERSION:=5.1
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@GNU/bash
+PKG_HASH:=cc012bc860406dcf42f64431bcd3d2fa7560c02915a601aba9cd597a39329baa
+
+PKG_MAINTAINER:=Marcel Denia <naoir@gmx.net>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:gnu:bash
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/bash
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Shells
+ TITLE:=The GNU Bourne Again SHell
+ DEPENDS:=+libncurses +libreadline
+ URL:=http://www.gnu.org/software/bash/
+endef
+
+define Package/bash/description
+ Bash is an sh-compatible command language interpreter that executes
+ commands read from the standard input or from a file. Bash also
+ incorporates useful features from the Korn and C shells (ksh and csh).
+endef
+
+define Package/bash/conffiles
+/etc/bash.bashrc
+/etc/bash.bash_logout
+endef
+
+# Bash detects and enables certain features by runtest simple piece of code
+# which is not viable when doing cross compilation and default to no in many
+# cases. Grep for 'cross.compil' in aclocal.m4 and config-bot.h for details
+#
+# bash_cv_job_control_missing: Job control is needed for bash to be used as the
+# default shell
+#
+# bash_cv_getcwd_malloc: The replacement by bash does not work well with
+# overlayfs. See "bash getcwd errors when running under OverlayFS"
+# http://permalink.gmane.org/gmane.linux.embedded.yocto.general/25204
+#
+# bash_cv_dev_fd: The test is done on build system but OpenWrt currently does
+# not have /dev/fd, it provides /proc/self/fd/ instead
+#
+# bash_cv_sys_named_pipes: Required for process substituion
+CONFIGURE_VARS += \
+ ac_cv_rl_prefix="$(STAGING_DIR)/usr" \
+ ac_cv_rl_version="8.0" \
+ bash_cv_getcwd_malloc=yes \
+ bash_cv_job_control_missing=present \
+ bash_cv_dev_fd=whacky \
+ bash_cv_sys_named_pipes=present \
+
+# The following are some other tests that cannot run when cross-compiling
+CONFIGURE_VARS += \
+ bash_cv_func_sigsetjmp=present \
+ bash_cv_printf_a_format=yes \
+
+CONFIGURE_ARGS+= \
+ --with-curses \
+ --without-bash-malloc \
+ --bindir=/bin \
+ --disable-rpath \
+ --enable-direxpand-default \
+ --enable-job-control \
+ --enable-readline
+
+define Package/bash/postinst
+#!/bin/sh
+grep -q bash "$${IPKG_INSTROOT}/etc/shells" || {
+ echo /bin/bash >> "$${IPKG_INSTROOT}/etc/shells"
+ echo /bin/rbash >> "$${IPKG_INSTROOT}/etc/shells"
+}
+endef
+
+define Package/bash/install
+ $(INSTALL_DIR) $(1)/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/bin/bash $(1)/bin/
+ $(LN) bash $(1)/bin/rbash
+ $(CP) ./files/* $(1)/
+endef
+
+$(eval $(call BuildPackage,bash))
diff --git a/external/subpack/utils/bash/files/etc/bash.bashrc b/external/subpack/utils/bash/files/etc/bash.bashrc
new file mode 100644
index 0000000..158deaa
--- /dev/null
+++ b/external/subpack/utils/bash/files/etc/bash.bashrc
@@ -0,0 +1,6 @@
+# System-wide .bashrc file
+
+# Continue if running interactively
+[[ $- == *i* ]] || return 0
+
+[ \! -s /etc/shinit ] || . /etc/shinit
diff --git a/external/subpack/utils/bash/files/etc/profile.d/sys_bashrc.sh b/external/subpack/utils/bash/files/etc/profile.d/sys_bashrc.sh
new file mode 100644
index 0000000..5c06bb5
--- /dev/null
+++ b/external/subpack/utils/bash/files/etc/profile.d/sys_bashrc.sh
@@ -0,0 +1 @@
+[ -z "$BASH" ] || [ "$BASH" = /bin/sh ] || [ \! -s /etc/bash.bashrc ] || . /etc/bash.bashrc
diff --git a/external/subpack/utils/bash/patches/101-bash51-001.patch b/external/subpack/utils/bash/patches/101-bash51-001.patch
new file mode 100644
index 0000000..02898aa
--- /dev/null
+++ b/external/subpack/utils/bash/patches/101-bash51-001.patch
@@ -0,0 +1,64 @@
+ BASH PATCH REPORT
+ =================
+
+Bash-Release: 5.1
+Patch-ID: bash51-001
+
+Bug-Reported-by: Fazal Majid <fazal@majid.org>
+Bug-Reference-ID: <DEAB7D2C-C626-450C-B2E5-281AFF2D26D4@majid.org>
+Bug-Reference-URL: https://lists.gnu.org/archive/html/bug-bash/2020-12/msg00000.html
+
+Bug-Description:
+
+There is a missing dependency on a constructed file, which can cause highly
+parellel builds to fail.
+
+Patch (apply with `patch -p0'):
+
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -1315,6 +1315,7 @@ bashline.o: trap.h flags.h assoc.h $(BAS
+ bashline.o: $(DEFSRC)/common.h $(GLOB_LIBSRC)/glob.h alias.h
+ bashline.o: pcomplete.h ${BASHINCDIR}/chartypes.h input.h
+ bashline.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
++bashline.o: ${DEFDIR}/builtext.h
+ bracecomp.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+ bracecomp.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h
+ bracecomp.o: command.h ${BASHINCDIR}/stdc.h error.h
+@@ -1435,6 +1436,7 @@ builtins/evalstring.o: quit.h unwind_pro
+ builtins/evalstring.o: dispose_cmd.h make_cmd.h subst.h externs.h
+ builtins/evalstring.o: jobs.h builtins.h flags.h input.h execute_cmd.h
+ builtins/evalstring.o: bashhist.h $(DEFSRC)/common.h pathnames.h
++builtins/evalstring.o: ${DEFDIR}/builtext.h
+ builtins/getopt.o: config.h ${BASHINCDIR}/memalloc.h
+ builtins/getopt.o: shell.h syntax.h bashjmp.h command.h general.h xmalloc.h error.h
+ builtins/getopt.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+--- a/builtins/Makefile.in
++++ b/builtins/Makefile.in
+@@ -361,7 +361,7 @@ evalstring.o: $(topdir)/dispose_cmd.h $(
+ evalstring.o: $(topdir)/externs.h $(topdir)/jobs.h $(topdir)/builtins.h
+ evalstring.o: $(topdir)/flags.h $(topdir)/input.h $(topdir)/execute_cmd.h
+ evalstring.o: $(topdir)/bashhist.h $(srcdir)/common.h
+-evalstring.o: $(topdir)/trap.h $(topdir)/redir.h ../pathnames.h
++evalstring.o: $(topdir)/trap.h $(topdir)/redir.h ../pathnames.h ./builtext.h
+ #evalstring.o: $(topdir)/y.tab.h
+ getopt.o: ../config.h $(BASHINCDIR)/memalloc.h
+ getopt.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/bashjmp.h $(topdir)/command.h
+--- a/patchlevel.h
++++ b/patchlevel.h
+@@ -1,6 +1,6 @@
+ /* patchlevel.h -- current bash patch level */
+
+-/* Copyright (C) 2001-2016 Free Software Foundation, Inc.
++/* Copyright (C) 2001-2020 Free Software Foundation, Inc.
+
+ This file is part of GNU Bash, the Bourne Again SHell.
+
+@@ -25,6 +25,6 @@
+ regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
+ looks for to find the patch level (for the sccs version string). */
+
+-#define PATCHLEVEL 0
++#define PATCHLEVEL 1
+
+ #endif /* _PATCHLEVEL_H_ */
diff --git a/external/subpack/utils/bash/patches/102-bash51-002.patch b/external/subpack/utils/bash/patches/102-bash51-002.patch
new file mode 100644
index 0000000..2faa881
--- /dev/null
+++ b/external/subpack/utils/bash/patches/102-bash51-002.patch
@@ -0,0 +1,45 @@
+ BASH PATCH REPORT
+ =================
+
+Bash-Release: 5.1
+Patch-ID: bash51-002
+
+Bug-Reported-by: oguzismailuysal@gmail.com
+Bug-Reference-ID: <CAH7i3LoHFUa4aSF5-AD2r80HG-p-YzD_9ZxomarZkhP8NMq63g@mail.gmail.com>
+Bug-Reference-URL: https://lists.gnu.org/archive/html/bug-bash/2020-12/msg00037.html
+
+Bug-Description:
+
+If there are no jobs, and the `-n' and `-p' options are both supplied to
+`wait', bash can assign a value to the variable name specified with `-p'
+instead of leaving it unset.
+
+Patch (apply with `patch -p0'):
+
+--- a/builtins/wait.def
++++ b/builtins/wait.def
+@@ -213,11 +213,11 @@ wait_builtin (list)
+ }
+
+ status = wait_for_any_job (wflags, &pstat);
+- if (status < 0)
+- status = 127;
+-
+ if (vname && status >= 0)
+ bind_var_to_int (vname, pstat.pid);
++
++ if (status < 0)
++ status = 127;
+ if (list)
+ unset_waitlist ();
+ WAIT_RETURN (status);
+--- a/patchlevel.h
++++ b/patchlevel.h
+@@ -25,6 +25,6 @@
+ regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
+ looks for to find the patch level (for the sccs version string). */
+
+-#define PATCHLEVEL 1
++#define PATCHLEVEL 2
+
+ #endif /* _PATCHLEVEL_H_ */
diff --git a/external/subpack/utils/bash/patches/103-bash51-003.patch b/external/subpack/utils/bash/patches/103-bash51-003.patch
new file mode 100644
index 0000000..72c251b
--- /dev/null
+++ b/external/subpack/utils/bash/patches/103-bash51-003.patch
@@ -0,0 +1,43 @@
+ BASH PATCH REPORT
+ =================
+
+Bash-Release: 5.1
+Patch-ID: bash51-003
+
+Bug-Reported-by: oguzismailuysal@gmail.com
+Bug-Reference-ID: <CAH7i3LpG91BnNcDtaTUm2Ph7a+PnJkuh6nAc87cVL7_38tOaMQ@mail.gmail.com>
+Bug-Reference-URL: https://lists.gnu.org/archive/html/bug-bash/2020-12/msg00050.html
+
+Bug-Description:
+
+Bash does not put a command substitution process that is started to perform an
+expansion in a child process into the right process group where it can receive
+keyboard-generated signals.
+
+Patch (apply with `patch -p0'):
+
+--- a/subst.c
++++ b/subst.c
+@@ -6356,8 +6356,10 @@ command_substitute (string, quoted, flag
+
+ #if defined (JOB_CONTROL)
+ old_pipeline_pgrp = pipeline_pgrp;
+- /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
+- if ((subshell_environment & SUBSHELL_PIPE) == 0)
++ /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline or
++ we've already forked to run a disk command (and are expanding redirections,
++ for example). */
++ if ((subshell_environment & (SUBSHELL_FORK|SUBSHELL_PIPE)) == 0)
+ pipeline_pgrp = shell_pgrp;
+ cleanup_the_pipeline ();
+ #endif /* JOB_CONTROL */
+--- a/patchlevel.h
++++ b/patchlevel.h
+@@ -25,6 +25,6 @@
+ regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
+ looks for to find the patch level (for the sccs version string). */
+
+-#define PATCHLEVEL 2
++#define PATCHLEVEL 3
+
+ #endif /* _PATCHLEVEL_H_ */
diff --git a/external/subpack/utils/bash/patches/104-bash51-004.patch b/external/subpack/utils/bash/patches/104-bash51-004.patch
new file mode 100644
index 0000000..218b843
--- /dev/null
+++ b/external/subpack/utils/bash/patches/104-bash51-004.patch
@@ -0,0 +1,114 @@
+ BASH PATCH REPORT
+ =================
+
+Bash-Release: 5.1
+Patch-ID: bash51-004
+
+Bug-Reported-by: oguzismailuysal@gmail.com
+Bug-Reference-ID: <CAH7i3LoHGmwaghDpCWRUfcY04gQmeDTH3RiG=bf2b=KbU=gyhw@mail.gmail.com>
+Bug-Reference-URL: https://lists.gnu.org/archive/html/bug-bash/2020-12/msg00039.html
+
+Bug-Description:
+
+If a key-value compound array assignment to an associative array is supplied
+as an assignment statement argument to the `declare' command that declares the
+array, the assignment doesn't perform the correct word expansions.
+
+This patch makes key-value assignment and subscript assignment perform the
+same expansions when they're supplied as an argument to `declare'.
+
+Patch (apply with `patch -p0'):
+
+--- a/arrayfunc.c
++++ b/arrayfunc.c
+@@ -597,6 +597,27 @@ assign_assoc_from_kvlist (var, nlist, h,
+ free (aval);
+ }
+ }
++
++/* Return non-zero if L appears to be a key-value pair associative array
++ compound assignment. */
++int
++kvpair_assignment_p (l)
++ WORD_LIST *l;
++{
++ return (l && (l->word->flags & W_ASSIGNMENT) == 0 && l->word->word[0] != '['); /*]*/
++}
++
++char *
++expand_and_quote_kvpair_word (w)
++ char *w;
++{
++ char *t, *r;
++
++ t = w ? expand_assignment_string_to_string (w, 0) : 0;
++ r = sh_single_quote (t ? t : "");
++ free (t);
++ return r;
++}
+ #endif
+
+ /* Callers ensure that VAR is not NULL. Associative array assignments have not
+@@ -640,7 +661,7 @@ assign_compound_array_list (var, nlist,
+ last_ind = (a && (flags & ASS_APPEND)) ? array_max_index (a) + 1 : 0;
+
+ #if ASSOC_KVPAIR_ASSIGNMENT
+- if (assoc_p (var) && nlist && (nlist->word->flags & W_ASSIGNMENT) == 0 && nlist->word->word[0] != '[') /*]*/
++ if (assoc_p (var) && kvpair_assignment_p (nlist))
+ {
+ iflags = flags & ~ASS_APPEND;
+ assign_assoc_from_kvlist (var, nlist, nhash, iflags);
+--- a/arrayfunc.h
++++ b/arrayfunc.h
+@@ -67,6 +67,9 @@ extern SHELL_VAR *assign_array_var_from_
+ extern char *expand_and_quote_assoc_word PARAMS((char *, int));
+ extern void quote_compound_array_list PARAMS((WORD_LIST *, int));
+
++extern int kvpair_assignment_p PARAMS((WORD_LIST *));
++extern char *expand_and_quote_kvpair_word PARAMS((char *));
++
+ extern int unbind_array_element PARAMS((SHELL_VAR *, char *, int));
+ extern int skipsubscript PARAMS((const char *, int, int));
+
+--- a/subst.c
++++ b/subst.c
+@@ -11604,6 +11604,7 @@ expand_oneword (value, flags)
+ {
+ WORD_LIST *l, *nl;
+ char *t;
++ int kvpair;
+
+ if (flags == 0)
+ {
+@@ -11618,11 +11619,21 @@ expand_oneword (value, flags)
+ {
+ /* Associative array */
+ l = parse_string_to_word_list (value, 1, "array assign");
++#if ASSOC_KVPAIR_ASSIGNMENT
++ kvpair = kvpair_assignment_p (l);
++#endif
++
+ /* For associative arrays, with their arbitrary subscripts, we have to
+ expand and quote in one step so we don't have to search for the
+ closing right bracket more than once. */
+ for (nl = l; nl; nl = nl->next)
+ {
++#if ASSOC_KVPAIR_ASSIGNMENT
++ if (kvpair)
++ /* keys and values undergo the same set of expansions */
++ t = expand_and_quote_kvpair_word (nl->word->word);
++ else
++#endif
+ if ((nl->word->flags & W_ASSIGNMENT) == 0)
+ t = sh_single_quote (nl->word->word ? nl->word->word : "");
+ else
+--- a/patchlevel.h
++++ b/patchlevel.h
+@@ -25,6 +25,6 @@
+ regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
+ looks for to find the patch level (for the sccs version string). */
+
+-#define PATCHLEVEL 3
++#define PATCHLEVEL 4
+
+ #endif /* _PATCHLEVEL_H_ */
diff --git a/external/subpack/utils/bash/patches/900-no_doc.patch b/external/subpack/utils/bash/patches/900-no_doc.patch
new file mode 100644
index 0000000..eda7f2d
--- /dev/null
+++ b/external/subpack/utils/bash/patches/900-no_doc.patch
@@ -0,0 +1,13 @@
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -798,10 +798,8 @@ loadables:
+ # $(MAKE) -f $(srcdir)/Makefile $(MFLAGS) srcdir=$(srcdir)
+
+ doc documentation: force
+- @(cd $(DOCDIR) ; $(MAKE) $(MFLAGS) )
+
+ info dvi ps: force
+- @(cd $(DOCDIR) ; $(MAKE) $(MFLAGS) CFLAGS='$(CCFLAGS)' $@ )
+
+ force:
+
diff --git a/external/subpack/utils/bash/patches/901-startup-files.patch b/external/subpack/utils/bash/patches/901-startup-files.patch
new file mode 100644
index 0000000..c97054d
--- /dev/null
+++ b/external/subpack/utils/bash/patches/901-startup-files.patch
@@ -0,0 +1,27 @@
+--- a/config-top.h
++++ b/config-top.h
+@@ -91,20 +91,20 @@
+ #define DEFAULT_BASHRC "~/.bashrc"
+
+ /* System-wide .bashrc file for interactive shells. */
+-/* #define SYS_BASHRC "/etc/bash.bashrc" */
++#define SYS_BASHRC "/etc/bash.bashrc"
+
+ /* System-wide .bash_logout for login shells. */
+-/* #define SYS_BASH_LOGOUT "/etc/bash.bash_logout" */
++#define SYS_BASH_LOGOUT "/etc/bash.bash_logout"
+
+ /* Define this to make non-interactive shells begun with argv[0][0] == '-'
+ run the startup files when not in posix mode. */
+-/* #define NON_INTERACTIVE_LOGIN_SHELLS */
++#define NON_INTERACTIVE_LOGIN_SHELLS
+
+ /* Define this if you want bash to try to check whether it's being run by
+ sshd and source the .bashrc if so (like the rshd behavior). This checks
+ for the presence of SSH_CLIENT or SSH2_CLIENT in the initial environment,
+ which can be fooled under certain not-uncommon circumstances. */
+-/* #define SSH_SOURCE_BASHRC */
++#define SSH_SOURCE_BASHRC
+
+ /* Define if you want the case-toggling operators (~[~]) and the
+ `capcase' variable attribute (declare -c). */
diff --git a/external/subpack/utils/bc/Makefile b/external/subpack/utils/bc/Makefile
new file mode 100644
index 0000000..f02285e
--- /dev/null
+++ b/external/subpack/utils/bc/Makefile
@@ -0,0 +1,65 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bc
+PKG_VERSION:=1.06.95
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.gz
+PKG_SOURCE_URL:=ftp://ftp.debian.org/debian/pool/main/b/bc
+PKG_HASH:=5e1471869dd27ba4120dd3942d2f4ec6646cf917fb056be9ae0d3a8259668d47
+
+PKG_MAINTAINER:=Bruno Randolf <br1@einfach.org>
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/bc/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ URL:=http://packages.debian.org/bc
+endef
+
+define Package/bc
+ $(call Package/bc/Default)
+ TITLE:=Arbitrary precision calculator language
+ DEPENDS:=+libreadline +libncurses
+endef
+
+define Package/bc/description
+ bc is a language that supports arbitrary precision numbers with
+ interactive execution of statements.
+endef
+
+define Package/dc
+ $(call Package/bc/Default)
+ TITLE:=Arbitrary precision reverse-polish calculator
+ DEPENDS:=bc
+endef
+
+define Package/dc/description
+ dc is a reverse-polish desk calculator which supports unlimited
+ precision arithmetic.
+endef
+
+CONFIGURE_ARGS += --with-readline
+
+define Package/bc/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/bc/bc $(1)/usr/bin/
+endef
+
+define Package/dc/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/dc/dc $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,bc))
+$(eval $(call BuildPackage,dc))
diff --git a/external/subpack/utils/bc/patches/001-disable-doc.patch b/external/subpack/utils/bc/patches/001-disable-doc.patch
new file mode 100644
index 0000000..4b80086
--- /dev/null
+++ b/external/subpack/utils/bc/patches/001-disable-doc.patch
@@ -0,0 +1,21 @@
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -149,7 +149,7 @@ sbindir = @sbindir@
+ sharedstatedir = @sharedstatedir@
+ sysconfdir = @sysconfdir@
+ target_alias = @target_alias@
+-SUBDIRS = lib bc dc doc
++SUBDIRS = lib bc dc
+ MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in \
+ stamp-h $(distdir).tar.gz h/number.h depcomp missing
+
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,6 +1,6 @@
+ ## Process this file with automake to produce Makefile.in
+
+-SUBDIRS = lib bc dc doc
++SUBDIRS = lib bc dc
+
+ MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in \
+ stamp-h $(distdir).tar.gz h/number.h depcomp missing
diff --git a/external/subpack/utils/bcm27xx-eeprom/Makefile b/external/subpack/utils/bcm27xx-eeprom/Makefile
new file mode 100644
index 0000000..d67893a
--- /dev/null
+++ b/external/subpack/utils/bcm27xx-eeprom/Makefile
@@ -0,0 +1,58 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bcm27xx-eeprom
+PKG_VERSION:=3129546271da09dde04da5c9715db909b8e1e417
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/raspberrypi/rpi-eeprom/tar.gz/$(PKG_VERSION)?
+PKG_HASH:=8ae34dd286d777484e670284883c91831ca8bdd15cc90a069009fdf1016de40b
+
+PKG_LICENSE:=BSD-3-Clause Custom
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_MAINTAINER:=Álvaro Fernández Rojas <noltari@gmail.com>
+
+include $(INCLUDE_DIR)/package.mk
+
+TAR_OPTIONS:=--strip-components 1 $(TAR_OPTIONS)
+TAR_CMD=$(HOST_TAR) -C $(1) $(TAR_OPTIONS)
+
+define Package/bcm27xx-eeprom
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=bcm27xx-userland +blkid +coreutils +coreutils-od +pciutils +python3-light
+ TITLE:=BCM27xx EEPROM tools
+endef
+
+define Package/bcm27xx-eeprom/description
+ BCM27xx EEPROM tools.
+endef
+
+define Build/Compile
+ true
+endef
+
+define Package/bcm27xx-eeprom/conffiles
+/etc/bcm27xx-eeprom.conf
+endef
+
+define Package/bcm27xx-eeprom/install
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/rpi-eeprom-update-default $(1)/etc/bcm27xx-eeprom.conf
+
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/rpi-eeprom-config $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/rpi-eeprom-update $(1)/usr/bin
+
+ $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader
+ $(CP) $(PKG_BUILD_DIR)/firmware/release-notes.md $(1)/lib/firmware/raspberrypi/bootloader
+
+ $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader/critical
+ $(CP) $(PKG_BUILD_DIR)/firmware/critical/ $(1)/lib/firmware/raspberrypi/bootloader/
+
+ $(INSTALL_DIR) $(1)/lib/firmware/raspberrypi/bootloader/stable
+ $(CP) $(PKG_BUILD_DIR)/firmware/stable/ $(1)/lib/firmware/raspberrypi/bootloader/
+endef
+
+$(eval $(call BuildPackage,bcm27xx-eeprom))
diff --git a/external/subpack/utils/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch b/external/subpack/utils/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch
new file mode 100644
index 0000000..f7b398f
--- /dev/null
+++ b/external/subpack/utils/bcm27xx-eeprom/patches/0001-rpi-eeprom-update-OpenWrt-defaults.patch
@@ -0,0 +1,47 @@
+From da37f7b051fe6833e25e78184cc9217dd4379187 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Mon, 23 Mar 2020 10:10:55 +0100
+Subject: [PATCH] rpi-eeprom-update: OpenWrt defaults
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+---
+ rpi-eeprom-update | 6 +++---
+ rpi-eeprom-update-default | 5 +++--
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+--- a/rpi-eeprom-update
++++ b/rpi-eeprom-update
+@@ -24,13 +24,13 @@ else
+ fi
+
+ # Selects the release sub-directory
+-FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-default}
++FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-stable}
+ FIRMWARE_IMAGE_DIR=${FIRMWARE_IMAGE_DIR:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}}
+-FIRMWARE_BACKUP_DIR=${FIRMWARE_BACKUP_DIR:-/var/lib/raspberrypi/bootloader/backup}
++FIRMWARE_BACKUP_DIR=${FIRMWARE_BACKUP_DIR:-${FIRMWARE_ROOT}/backup}
+ ENABLE_VL805_UPDATES=${ENABLE_VL805_UPDATES:-1}
+ RECOVERY_BIN=${RECOVERY_BIN:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}/recovery.bin}
+ BOOTFS=${BOOTFS:-/boot}
+-VCMAILBOX=${VCMAILBOX:-/opt/vc/bin/vcmailbox}
++VCMAILBOX=${VCMAILBOX:-/usr/bin/vcmailbox}
+ CM4_ENABLE_RPI_EEPROM_UPDATE=${CM4_ENABLE_RPI_EEPROM_UPDATE:-0}
+ RPI_EEPROM_UPDATE_CONFIG_TOOL="${RPI_EEPROM_UPDATE_CONFIG_TOOL:-raspi-config}"
+
+--- a/rpi-eeprom-update-default
++++ b/rpi-eeprom-update-default
+@@ -1,8 +1,9 @@
+
+ FIRMWARE_ROOT=/lib/firmware/raspberrypi/bootloader
+-FIRMWARE_RELEASE_STATUS="critical"
++FIRMWARE_RELEASE_STATUS="stable"
+ FIRMWARE_IMAGE_DIR="${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}"
+-FIRMWARE_BACKUP_DIR="/var/lib/raspberrypi/bootloader/backup"
++FIRMWARE_BACKUP_DIR="${FIRMWARE_ROOT}/backup"
+ BOOTFS=/boot
+ USE_FLASHROM=0
+ EEPROM_CONFIG_HOOK=
++VCMAILBOX=/usr/bin/vcmailbo
diff --git a/external/subpack/utils/bcm27xx-eeprom/patches/0002-rpi-eeprom-config-switch-to-Python-3.patch b/external/subpack/utils/bcm27xx-eeprom/patches/0002-rpi-eeprom-config-switch-to-Python-3.patch
new file mode 100644
index 0000000..11d3b2f
--- /dev/null
+++ b/external/subpack/utils/bcm27xx-eeprom/patches/0002-rpi-eeprom-config-switch-to-Python-3.patch
@@ -0,0 +1,21 @@
+From 869a29ec65a0985670a259f4820df4fafc22c971 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Wed, 25 Mar 2020 10:14:34 +0100
+Subject: [PATCH] rpi-eeprom-config: switch to Python 3
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+---
+ rpi-eeprom-config | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/rpi-eeprom-config
++++ b/rpi-eeprom-config
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/env python3
+
+ """
+ rpi-eeprom-config
diff --git a/external/subpack/utils/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch b/external/subpack/utils/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch
new file mode 100644
index 0000000..27d5f1e
--- /dev/null
+++ b/external/subpack/utils/bcm27xx-eeprom/patches/0003-rpi-eeprom-update-change-default-include-path.patch
@@ -0,0 +1,44 @@
+From 6674d49dea0104031b3f54df4c7a356dc4307bb2 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Wed, 25 Mar 2020 20:58:35 +0100
+Subject: [PATCH] rpi-eeprom-update: change default include path
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+---
+ rpi-eeprom-update | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/rpi-eeprom-update
++++ b/rpi-eeprom-update
+@@ -6,8 +6,8 @@ set -e
+
+ script_dir=$(cd "$(dirname "$0")" && pwd)
+
+-if [ -f /etc/default/rpi-eeprom-update ]; then
+- . /etc/default/rpi-eeprom-update
++if [ -f /etc/bcm27xx-eeprom.conf ]; then
++ . /etc/bcm27xx-eeprom.conf
+ fi
+
+ LOCAL_MODE=0
+@@ -386,7 +386,7 @@ The system should then boot normally.
+
+ If /boot does not correspond to the boot partition and this
+ is not a NOOBS system, then the mount point for BOOTFS should be defined
+-in /etc/default/rpi-eeprom-update by defining the BOOTFS variable.
++in /etc/bcm27xx-eeprom.conf by defining the BOOTFS variable.
+
+ A backup of the current EEPROM config file is written to ${FIRMWARE_BACKUP_DIR}
+ before applying the update.
+@@ -415,7 +415,7 @@ Options:
+ -u Install the specified VL805 (USB EEPROM) image file.
+
+ Environment:
+-Environment variables should be defined in /etc/default/rpi-eeprom-update
++Environment variables should be defined in /etc/bcm27xx-eeprom.conf
+
+ EEPROM_CONFIG_HOOK
+
diff --git a/external/subpack/utils/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch b/external/subpack/utils/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch
new file mode 100644
index 0000000..bb9fe14
--- /dev/null
+++ b/external/subpack/utils/bcm27xx-eeprom/patches/0004-rpi-eeprom-update-chmod-silent-f-is-not-supported.patch
@@ -0,0 +1,33 @@
+From 8376ac74390af0ad736c88615e128b82a75eebc0 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Fri, 19 Feb 2021 10:54:23 +0100
+Subject: [PATCH] rpi-eeprom-update: chmod silent (-f) is not supported
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+---
+ rpi-eeprom-update | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/rpi-eeprom-update
++++ b/rpi-eeprom-update
+@@ -212,7 +212,7 @@ applyRecoveryUpdate()
+ || die "Failed to copy ${TMP_EEPROM_IMAGE} to ${BOOTFS}"
+
+ # For NFS mounts ensure that the files are readable to the TFTP user
+- chmod -f go+r "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig" \
++ chmod go+r "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig" \
+ || die "Failed to set permissions on eeprom update files"
+ fi
+
+@@ -224,7 +224,7 @@ applyRecoveryUpdate()
+ || die "Failed to copy ${VL805_UPDATE_IMAGE} to ${BOOTFS}/vl805.bin"
+
+ # For NFS mounts ensure that the files are readable to the TFTP user
+- chmod -f go+r "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig" \
++ chmod go+r "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig" \
+ || die "Failed to set permissions on eeprom update files"
+ fi
+
diff --git a/external/subpack/utils/beep/Makefile b/external/subpack/utils/beep/Makefile
new file mode 100644
index 0000000..eb96e31
--- /dev/null
+++ b/external/subpack/utils/beep/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2017 Chris Blake (chrisrblake93@gmail.com)
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=beep
+PKG_VERSION:=1.4.12
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/spkr-beep/beep/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=6188d0f0c180db7a30467b5b6065a3cb5d2665b937d2e8c40366efb52bf689fe
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/beep
+ SECTION:=sound
+ CATEGORY:=Sound
+ DEPENDS:=+TARGET_x86:kmod-pcspkr @!TARGET_x86:kmod-gpio-beeper
+ TITLE:=Play beep sounds through a PC speaker
+ URL:=https://github.com/spkr-beep/beep
+endef
+
+define Package/beep/description
+ This program plays beeps through the PC speaker
+endef
+
+MAKE_FLAGS += \
+ CFLAGS="$(TARGET_CFLAGS)"
+
+define Package/beep/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/beep $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,beep))
diff --git a/external/subpack/utils/beep/patches/0001-GNUmakefile-comment-out-D_FORTIFY_SOURCE.patch b/external/subpack/utils/beep/patches/0001-GNUmakefile-comment-out-D_FORTIFY_SOURCE.patch
new file mode 100644
index 0000000..5f9a4e3
--- /dev/null
+++ b/external/subpack/utils/beep/patches/0001-GNUmakefile-comment-out-D_FORTIFY_SOURCE.patch
@@ -0,0 +1,24 @@
+From 937b2e633754c1234cc0037e47c77f7735704a12 Mon Sep 17 00:00:00 2001
+From: Josef Schlehofer <pepe.schlehofer@gmail.com>
+Date: Tue, 7 Jun 2022 17:55:59 +0200
+Subject: [PATCH] GNUmakefile: comment out D_FORTIFY_SOURCE
+
+Fixes:
+<command-line>: error: "_FORTIFY_SOURCE" redefined [-Werror]
+<command-line>: note: this is the location of the previous definition
+cc1: all warnings being treated as errors
+---
+ GNUmakefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/GNUmakefile
++++ b/GNUmakefile
+@@ -160,7 +160,7 @@ $(eval $(call CHECK_CFLAGS,common_CFLAGS
+ $(eval $(call CHECK_CFLAGS,common_CFLAGS,-Werror=format-security))
+ $(eval $(call CHECK_CFLAGS,common_CFLAGS,-Wno-disabled-macro-expansion))
+ $(eval $(call CHECK_CFLAGS,common_CFLAGS,-Wno-format-nonliteral))
+-$(eval $(call CHECK_CFLAGS,CPPFLAGS,-D_FORTIFY_SOURCE=2))
++# $(eval $(call CHECK_CFLAGS,CPPFLAGS,-D_FORTIFY_SOURCE=2))
+ $(eval $(call CHECK_CFLAGS,CPPFLAGS,-D_GLIBCXX_ASSERTIONS))
+ # $(eval $(call CHECK_CFLAGS,CFLAGS,-Wp$$(comma)-D_FORTIFY_SOURCE=2))
+ # $(eval $(call CHECK_CFLAGS,CFLAGS,-Wp$$(comma)-D_GLIBCXX_ASSERTIONS))
diff --git a/external/subpack/utils/bigclown/bigclown-control-tool/Makefile b/external/subpack/utils/bigclown/bigclown-control-tool/Makefile
new file mode 100644
index 0000000..4aaa6fe
--- /dev/null
+++ b/external/subpack/utils/bigclown/bigclown-control-tool/Makefile
@@ -0,0 +1,37 @@
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bigclown-control-tool
+PKG_VERSION:=0.2.0
+PKG_RELEASE:=3
+
+PYPI_NAME:=bch
+PKG_HASH:=4cd73b92757fce7275a4744baed411c867af2e671c521b90d6690b2320851d58
+
+PKG_MAINTAINER:=Josef Schlehofer <pepe.schlehofer@gmail.com>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+include ../../../lang/python/pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../../../lang/python/python3-package.mk
+
+define Package/bigclown-control-tool
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=BigClown
+ TITLE:=BigCLown control tool
+ URL:=https://github.com/bigclownlabs/bch-control-tool
+ DEPENDS:=\
+ +python3-click \
+ +python3-click-log \
+ +python3-paho-mqtt \
+ +python3-pyserial \
+ +python3-yaml
+endef
+
+$(eval $(call Py3Package,bigclown-control-tool))
+$(eval $(call BuildPackage,bigclown-control-tool))
diff --git a/external/subpack/utils/bigclown/bigclown-control-tool/patches/0001-bch-use-Python-s-built-in-json-library.patch b/external/subpack/utils/bigclown/bigclown-control-tool/patches/0001-bch-use-Python-s-built-in-json-library.patch
new file mode 100644
index 0000000..6f484ca
--- /dev/null
+++ b/external/subpack/utils/bigclown/bigclown-control-tool/patches/0001-bch-use-Python-s-built-in-json-library.patch
@@ -0,0 +1,40 @@
+--- a/bch.egg-info/requires.txt
++++ b/bch.egg-info/requires.txt
+@@ -3,4 +3,3 @@ click-log>=0.2.1
+ paho-mqtt>=1.0
+ pyserial>=3.0
+ PyYAML>=3.11
+-simplejson>=3.6.0
+--- a/bch/cli.py
++++ b/bch/cli.py
+@@ -6,7 +6,7 @@ import sys
+ import logging
+ import click
+ import click_log
+-import simplejson as json
++import json
+ from datetime import datetime
+ import paho.mqtt.client
+ from paho.mqtt.client import topic_matches_sub
+--- a/bch/mqtt_client.py
++++ b/bch/mqtt_client.py
+@@ -1,7 +1,7 @@
+ import paho.mqtt.client
+ from paho.mqtt.client import topic_matches_sub
+ import logging
+-import simplejson as json
++import json
+ import time
+
+
+--- a/setup.py
++++ b/setup.py
+@@ -3,7 +3,7 @@
+
+ from setuptools import setup, find_packages
+
+-requirements = ['Click>=6.0', 'click-log>=0.2.1', 'paho-mqtt>=1.0', 'pyserial>=3.0', 'PyYAML>=3.11', 'simplejson>=3.6.0']
++requirements = ['Click>=6.0', 'click-log>=0.2.1', 'paho-mqtt>=1.0', 'pyserial>=3.0', 'PyYAML>=3.11']
+
+ setup(
+ name='bch',
diff --git a/external/subpack/utils/bigclown/bigclown-firmware-tool/Makefile b/external/subpack/utils/bigclown/bigclown-firmware-tool/Makefile
new file mode 100644
index 0000000..7c15901
--- /dev/null
+++ b/external/subpack/utils/bigclown/bigclown-firmware-tool/Makefile
@@ -0,0 +1,40 @@
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bigclown-firmware-tool
+PKG_VERSION:=1.5.2
+PKG_RELEASE:=1
+
+PYPI_NAME:=bcf
+PKG_HASH:=8ad897586d02433d01a58b4978516621bea388cd230640eb0b8f8f9e40f10e6c
+
+PKG_MAINTAINER:=Josef Schlehofer <pepe.schlehofer@gmail.com>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+include ../../../lang/python/pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../../../lang/python/python3-package.mk
+
+define Package/bigclown-firmware-tool
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=BigClown
+ TITLE:=BigCLown firmware tool
+ URL:=https://github.com/bigclownlabs/bch-firmware-tool
+ DEPENDS:= \
+ +python3-appdirs \
+ +python3-pyserial \
+ +python3-colorama \
+ +python3-yaml \
+ +python3-schema \
+ +python3-requests \
+ +python3-click \
+ +python3-intelhex
+endef
+
+$(eval $(call Py3Package,bigclown-firmware-tool))
+$(eval $(call BuildPackage,bigclown-firmware-tool))
diff --git a/external/subpack/utils/bigclown/bigclown-gateway/Makefile b/external/subpack/utils/bigclown/bigclown-gateway/Makefile
new file mode 100644
index 0000000..6adc7c4
--- /dev/null
+++ b/external/subpack/utils/bigclown/bigclown-gateway/Makefile
@@ -0,0 +1,55 @@
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bigclown-gateway
+PKG_VERSION:=1.16.2
+PKG_RELEASE:=3
+
+PYPI_NAME:=bcg
+PKG_HASH:=ce7f27f372551c0beb3f8929af2d779417d9dcd0feaa2fa2dc49e87b1416c536
+
+PKG_MAINTAINER:=Josef Schlehofer <pepe.schlehofer@gmail.com>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+include ../../../lang/python/pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../../../lang/python/python3-package.mk
+
+define Package/bigclown-gateway
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=BigClown
+ TITLE:=BigCLown gateway
+ URL:=https://github.com/bigclownlabs/bch-gateway
+ DEPENDS:= \
+ +kmod-usb-serial-ftdi \
+ +kmod-usb-acm \
+ +python3-click \
+ +python3-click-log \
+ +python3-paho-mqtt \
+ +python3-pyserial \
+ +python3-yaml \
+ +python3-schema \
+ +python3-appdirs
+endef
+
+define Py3Package/bigclown-gateway/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) ./files/config $(1)/etc/config/bigclown-gateway
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/init $(1)/etc/init.d/bigclown-gateway
+endef
+
+define Package/bigclown-gateway/conffiles
+/etc/config/bigclown-gateway
+endef
+
+$(eval $(call Py3Package,bigclown-gateway))
+$(eval $(call BuildPackage,bigclown-gateway))
diff --git a/external/subpack/utils/bigclown/bigclown-gateway/files/config b/external/subpack/utils/bigclown/bigclown-gateway/files/config
new file mode 100644
index 0000000..6a60ae4
--- /dev/null
+++ b/external/subpack/utils/bigclown/bigclown-gateway/files/config
@@ -0,0 +1,10 @@
+
+config gateway 'gateway'
+ option enabled '0'
+ option name 'usb-dongle'
+ option device '/dev/ttyUSB0'
+ option automatic_rename_kit_nodes '1'
+
+config mqtt 'mqtt'
+ option host 'localhost'
+ option port '1883'
diff --git a/external/subpack/utils/bigclown/bigclown-gateway/files/init b/external/subpack/utils/bigclown/bigclown-gateway/files/init
new file mode 100755
index 0000000..37ddd0d
--- /dev/null
+++ b/external/subpack/utils/bigclown/bigclown-gateway/files/init
@@ -0,0 +1,58 @@
+#!/bin/sh /etc/rc.common
+
+START=98
+STOP=1
+
+USE_PROCD=1
+
+PROG=/usr/bin/bcg
+CONF=/tmp/etc/bigclown-gateway.conf
+
+append() {
+ local cfg="$1"
+ local uci_name="$2"
+ local out_name="$3"
+ local default="$4"
+ config_get val $cfg $uci_name $default
+ if [ -n "$val" ]; then
+ echo "$out_name $val" >> $CONF
+ fi
+}
+
+start_service() {
+ config_load bigclown-gateway
+
+ local enabled
+ config_get_bool enabled gateway enabled "0"
+ [ "$enabled" = "1" ] || {
+ echo "Bigclown gateway service disabled"
+ exit 1
+ }
+
+ rm -rf $CONF
+ echo "Generating bigclown-gateway config file in $CONF"
+
+ append gateway name 'name:' usb-dongle
+ # TODO add hotplug script and use different default here
+ append gateway device 'device:' /dev/ttyUSB0
+ append gateway automatic_rename_kit_nodes 'automatic_rename_kit_nodes:' 1
+ append gateway base_topic_prefix 'base_topic_prefix:'
+
+ echo "mqtt:" >> $CONF
+ append mqtt host ' host:' localhost
+ append mqtt port ' port:' 1883
+ append mqtt cafile ' cafile:'
+ append mqtt certfile ' certfile:'
+ append mqtt keyfile ' keyfile:'
+
+ procd_open_instance
+ procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
+ procd_set_param command "$PROG" -c "$CONF"
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_close_instance
+}
+
+service_triggers() {
+ procd_add_reload_trigger 'bigclown-gateway'
+}
diff --git a/external/subpack/utils/bigclown/bigclown-gateway/patches/0001-bcg-gateway-use-Python-s-built-in-json-library.patch b/external/subpack/utils/bigclown/bigclown-gateway/patches/0001-bcg-gateway-use-Python-s-built-in-json-library.patch
new file mode 100644
index 0000000..d7b909d
--- /dev/null
+++ b/external/subpack/utils/bigclown/bigclown-gateway/patches/0001-bcg-gateway-use-Python-s-built-in-json-library.patch
@@ -0,0 +1,34 @@
+From 0d9251aa4b7f925c908c048ae2eab123acab32d6 Mon Sep 17 00:00:00 2001
+From: Alexandru Ardelean <ardeleanalex@gmail.com>
+Date: Wed, 16 Mar 2022 09:46:03 +0200
+Subject: [PATCH] bcg: gateway: use Python's built-in json library
+
+This reduces the dependency list by one, since Python has a built-in JSON
+library with the same API.
+
+Signed-off-by: Alexandru Ardelean <ardeleanalex@gmail.com>
+---
+ bcg/gateway.py | 2 +-
+ requirements.txt | 1 -
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+--- a/bcg/gateway.py
++++ b/bcg/gateway.py
+@@ -3,7 +3,7 @@
+ import os
+ import time
+ import logging
+-import simplejson as json
++import json
+ import platform
+ import socket
+ import decimal
+--- a/requirements.txt
++++ b/requirements.txt
+@@ -3,6 +3,5 @@ click-log>=0.2.1
+ paho-mqtt>=1.0 # deb:python3-paho-mqtt>=1.0
+ pyserial>=3.0 # deb:python3-serial>=3.0
+ PyYAML>=3.11 # deb:python3-yaml>=3.11
+-simplejson>=3.6.0 # deb:python3-simplejson>=3.6.0
+ schema>=0.6
+ appdirs>=1.0
diff --git a/external/subpack/utils/bigclown/bigclown-mqtt2influxdb/Makefile b/external/subpack/utils/bigclown/bigclown-mqtt2influxdb/Makefile
new file mode 100644
index 0000000..89b5dca
--- /dev/null
+++ b/external/subpack/utils/bigclown/bigclown-mqtt2influxdb/Makefile
@@ -0,0 +1,50 @@
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bigclown-mqtt2influxdb
+PKG_VERSION:=1.4.0
+PKG_RELEASE:=1
+
+PYPI_NAME:=mqtt2influxdb
+PKG_HASH:=9fd98d2239c0b9a2482db8e55e3e5a310c5b644aa7d42c57d35ed775adb0101a
+
+PKG_MAINTAINER:=Josef Schlehofer <pepe.schlehofer@gmail.com>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+include ../../../lang/python/pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../../../lang/python/python3-package.mk
+
+define Package/bigclown-mqtt2influxdb
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=BigClown
+ TITLE:=BigCLown MQTT to Influxdb bridge
+ URL:=https://github.com/bigclownlabs/bch-mqtt2influxdb
+ DEPENDS:= \
+ +python3-paho-mqtt \
+ +python3-yaml \
+ +python3-influxdb \
+ +python3-jsonpath-ng \
+ +python3-schema
+endef
+
+define Py3Package/bigclown-mqtt2influxdb/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/init $(1)/etc/init.d/bigclown-mqtt2influxdb
+ $(INSTALL_DATA) ./files/config.yml $(1)/etc/bigclown-mqtt2influxdb.yml
+endef
+
+define Package/bigclown-mqtt2influxdb/conffiles
+/etc/bigclown-mqtt2influxdb.yml
+endef
+
+$(eval $(call Py3Package,bigclown-mqtt2influxdb))
+$(eval $(call BuildPackage,bigclown-mqtt2influxdb))
diff --git a/external/subpack/utils/bigclown/bigclown-mqtt2influxdb/files/config.yml b/external/subpack/utils/bigclown/bigclown-mqtt2influxdb/files/config.yml
new file mode 100644
index 0000000..350c85a
--- /dev/null
+++ b/external/subpack/utils/bigclown/bigclown-mqtt2influxdb/files/config.yml
@@ -0,0 +1,67 @@
+## Example bigclown-mqtt2influxdb configuration
+
+# MQTT configuration
+mqtt:
+ #host: 127.0.0.1
+ #port: 1883
+
+# InfluxDB configuration
+influxdb:
+ #host: 127.0.0.1
+ #port: 8086
+ #database: node
+
+# This is default configuration used to mirror all values produced by default
+# BigClown modules firmware. You might want to add your topics or drop those for
+# modules you don't own.
+points:
+ - measurement: temperature
+ topic: node/+/thermometer/+/temperature
+ fields:
+ value: $.payload
+ tags:
+ id: $.topic[1]
+ channel: $.topic[3]
+
+ - measurement: relative-humidity
+ topic: node/+/hygrometer/0:4/relative-humidity
+ fields:
+ value: $.payload
+ tags:
+ id: $.topic[1]
+
+ - measurement: illuminance
+ topic: node/+/lux-meter/0:0/illuminance
+ fields:
+ value: $.payload
+ tags:
+ id: $.topic[1]
+
+ - measurement: pressure
+ topic: node/+/barometer/0:0/pressure
+ fields:
+ value: $.payload
+ tags:
+ id: $.topic[1]
+
+ - measurement: co2
+ topic: node/+/co2-meter/-/concentration
+ fields:
+ value: $.payload
+ tags:
+ id: $.topic[1]
+
+ - measurement: voltage
+ topic: node/+/battery/+/voltage
+ fields:
+ value: $.payload
+ tags:
+ id: $.topic[1]
+
+ - measurement: button
+ topic: node/+/push-button/+/event-count
+ fields:
+ value: $.payload
+ tags:
+ id: $.topic[1]
+ channel: $.topic[3]
diff --git a/external/subpack/utils/bigclown/bigclown-mqtt2influxdb/files/init b/external/subpack/utils/bigclown/bigclown-mqtt2influxdb/files/init
new file mode 100644
index 0000000..5c95600
--- /dev/null
+++ b/external/subpack/utils/bigclown/bigclown-mqtt2influxdb/files/init
@@ -0,0 +1,21 @@
+#!/bin/sh /etc/rc.common
+
+START=99
+STOP=1
+
+USE_PROCD=1
+
+PROG=/usr/bin/mqtt2influxdb
+CONF=/etc/bigclown-mqtt2influxdb.yml
+
+start_service() {
+ procd_open_instance
+ procd_set_param command "$PROG" -d -c "$CONF"
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_close_instance
+}
+
+stop_service() {
+ service_stop "$PROG"
+}
diff --git a/external/subpack/utils/bluelog/Makefile b/external/subpack/utils/bluelog/Makefile
new file mode 100644
index 0000000..3c60d61
--- /dev/null
+++ b/external/subpack/utils/bluelog/Makefile
@@ -0,0 +1,110 @@
+#
+# Copyright (C) 2012-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bluelog
+PKG_VERSION:=1.1.2
+PKG_RELEASE:=4
+
+PKG_SOURCE:=Bluelog-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/MS3FGX/Bluelog/tar.gz/$(PKG_VERSION)?
+PKG_HASH:=ebbc1357e14bc46cbddd8390cdbd29c0131b09b8ab680a1c382164ef076cb53e
+PKG_BUILD_DIR:=$(BUILD_DIR)/Bluelog-$(PKG_VERSION)
+
+OUI_SOURCE:=oui-2016-05-30.txt.gz
+OUI_URL:=https://sources.openwrt.org/
+OUI_HASH:=19d0b02eeb0d42507ee17b637a295782c14956fe1ac4803589ed93ef92c4fad5
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=Nicolas Thill <nico@openwrt.org>
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/bluelog/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Bluetooth scanner and logger
+ URL:=https://github.com/MS3FGX/Bluelog
+ DEPENDS:=+bluez-libs +kmod-bluetooth
+endef
+
+define Package/bluelog/Default/description
+ Bluelog is a simple Bluetooth scanner designed to tell you how many
+ discoverable devices there are in an area as quickly as possible. It is
+ intended to be used as a site survey tool, identifying the number of possible
+ Bluetooth targets there are in the surrounding environment.
+endef
+
+define Package/bluelog
+ $(call Package/bluelog/Default)
+endef
+
+define Package/bluelog/description
+ $(call Package/bluelog/Default/description)
+endef
+
+define Package/bluelog-live
+ $(call Package/bluelog/Default)
+ TITLE+= (live output)
+ DEPENDS+= bluelog
+endef
+
+define Package/bluelog-live/description
+ $(call Package/bluelog/Default/description)
+ This package contains the files for "Bluelog Live", an optional mode of
+ Bluelog which creates a real-time webpage of discovered Bluetooth devices.
+endef
+
+define Download/oui.txt
+ FILE:=$(OUI_SOURCE)
+ URL:=$(OUI_URL)
+ HASH:=$(OUI_HASH)
+endef
+
+TARGET_CFLAGS += -DOPENWRT
+
+MAKE_FLAGS += \
+ LIBS="$(TARGET_LDFLAGS) -lbluetooth -lm"
+
+define Build/Prepare
+ $(eval $(call Download,oui.txt))
+ $(Build/Prepare/Default)
+ zcat $(DL_DIR)/$(OUI_SOURCE) > $(PKG_BUILD_DIR)/oui.tmp
+endef
+
+define Package/bluelog/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/bluelog $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/bluelog.init $(1)/etc/init.d/bluelog
+endef
+
+define Package/bluelog-live/install
+ $(INSTALL_DIR) $(1)/www/bluelog
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/bluelog/*.html $(1)/www/bluelog/
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/share/bluelog/openwrt.css \
+ $(1)/www/bluelog/style.css
+ $(INSTALL_DIR) $(1)/www/bluelog/images
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/share/bluelog/images/digifail_logo.png \
+ $(PKG_INSTALL_DIR)/usr/share/bluelog/images/email.png \
+ $(PKG_INSTALL_DIR)/usr/share/bluelog/images/favicon.png \
+ $(PKG_INSTALL_DIR)/usr/share/bluelog/images/openwrt_logo.png \
+ $(PKG_INSTALL_DIR)/usr/share/bluelog/images/qrcontact.png \
+ $(1)/www/bluelog/images/
+ $(INSTALL_DIR) $(1)/www/cgi-bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/bluelog/cgi-bin/* $(1)/www/cgi-bin/
+endef
+
+$(eval $(call BuildPackage,bluelog))
+$(eval $(call BuildPackage,bluelog-live))
diff --git a/external/subpack/utils/bluelog/files/bluelog.init b/external/subpack/utils/bluelog/files/bluelog.init
new file mode 100644
index 0000000..efae288
--- /dev/null
+++ b/external/subpack/utils/bluelog/files/bluelog.init
@@ -0,0 +1,13 @@
+#!/bin/sh /etc/rc.common
+
+START=65
+
+SERVICE_DAEMONIZE=1
+
+start() {
+ service_start /usr/bin/bluelog
+}
+
+stop() {
+ service_stop /usr/bin/bluelog
+}
diff --git a/external/subpack/utils/bluelog/patches/100-gen-oui-fix-tempfile-use-mirror.patch b/external/subpack/utils/bluelog/patches/100-gen-oui-fix-tempfile-use-mirror.patch
new file mode 100644
index 0000000..414ecb8
--- /dev/null
+++ b/external/subpack/utils/bluelog/patches/100-gen-oui-fix-tempfile-use-mirror.patch
@@ -0,0 +1,31 @@
+--- a/gen_oui.sh
++++ b/gen_oui.sh
+@@ -3,7 +3,7 @@
+ VER="1.2"
+
+ # Location of tmp file
+-TMPFILE="/tmp/oui.tmp"
++TMPFILE="./oui.tmp"
+
+ # File to write
+ OUIFILE="oui.txt"
+@@ -22,10 +22,7 @@ exit 1
+
+ get_oui ()
+ {
+-echo -n "Downloading OUI file from IEEE..."
+-wget --quiet -O $TMPFILE http://standards.ieee.org/develop/regauth/oui/oui.txt || \
+- ErrorMsg ERR "Unable to contact IEEE server!"
+-
++[ -f "$TMPFILE" ] || ErrorMsg ERR "Unable to find $TMPFILE"
+ echo "OK"
+ }
+
+@@ -44,7 +41,6 @@ echo "OK"
+ clean_all ()
+ {
+ echo -n "Removing files..."
+-rm -f $TMPFILE
+ rm -f $OUIFILE
+ echo "OK"
+ }
diff --git a/external/subpack/utils/bluez/Makefile b/external/subpack/utils/bluez/Makefile
new file mode 100644
index 0000000..588a2f1
--- /dev/null
+++ b/external/subpack/utils/bluez/Makefile
@@ -0,0 +1,157 @@
+#
+# Copyright (C) 2006-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bluez
+PKG_VERSION:=5.64
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/linux/bluetooth/
+PKG_HASH:=ae437e65b6b3070c198bc5b0109fe9cdeb9eaa387380e2072f9de65fe8a1de34
+
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=
+PKG_CPE_ID:=cpe:/a:bluez:bluez
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/bluez/Default
+ TITLE:=Bluetooth
+ URL:=http://www.bluez.org/
+endef
+
+define Package/bluez-libs
+$(call Package/bluez/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+= library
+ DEPENDS:=+libpthread +USB_SUPPORT:kmod-bluetooth
+endef
+
+define Package/bluez-utils
+$(call Package/bluez/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE+= utilities
+ DEPENDS:=+bluez-libs
+endef
+
+define Package/bluez-utils-extra
+$(call Package/bluez/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE+= additional utilities
+ DEPENDS:=+bluez-libs +libpthread +librt +glib2 +libncurses +libreadline $(INTL_DEPENDS) $(ICONV_DEPENDS) +dbus
+endef
+
+define Package/bluez-daemon
+$(call Package/bluez/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE+= daemon
+ DEPENDS:=+bluez-libs +bluez-utils +bluez-utils-extra +glib2 +libncurses +libreadline +dbus +libical $(INTL_DEPENDS) $(ICONV_DEPENDS)
+endef
+
+define Package/bluez-daemon/conffiles
+/etc/bluetooth/main.conf
+/etc/bluetooth/network.conf
+/etc/bluetooth/input.conf
+/etc/bluetooth/keys
+/etc/config/bluetooth
+endef
+
+TARGET_CFLAGS += -D_GNU_SOURCE -ffunction-sections -fdata-sections
+TARGET_LDFLAGS += -Wl,--gc-sections
+
+CONFIGURE_ARGS += \
+ --enable-static \
+ --enable-shared \
+ --enable-client \
+ --enable-datafiles \
+ --enable-experimental \
+ --enable-library \
+ --enable-monitor \
+ --enable-obex \
+ --enable-threads \
+ --enable-tools \
+ --disable-android \
+ --disable-cups \
+ --disable-manpages \
+ --disable-sixaxis \
+ --disable-systemd \
+ --disable-test \
+ --disable-udev \
+ --enable-deprecated
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/bluetooth $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbluetooth.{a,so*} $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/bluez.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/bluez-libs/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbluetooth.so.* $(1)/usr/lib/
+endef
+
+define Package/bluez-utils/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/tools/bdaddr $(1)/usr/bin/
+# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/bccmd $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/bluemoon $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/btattach $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/btmon $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ciptool $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hciattach $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hciconfig $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hcidump $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hcitool $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hex2hcd $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/l2ping $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/l2test $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/rctest $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/rfcomm $(1)/usr/bin/
+endef
+
+define Package/bluez-utils-extra/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/tools/btmgmt $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mpris-proxy $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/sdptool $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/attrib/gatttool $(1)/usr/bin/
+endef
+
+define Package/bluez-daemon/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/bluetooth/bluetoothd $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/bluetoothctl $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/bluetooth/obexd $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/dbus-1/system.d/
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/src/bluetooth.conf $(1)/etc/dbus-1/system.d/bluetooth.conf
+ $(INSTALL_DIR) $(1)/etc/bluetooth
+ $(INSTALL_DIR) $(1)/etc/bluetooth/keys
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/src/main.conf $(1)/etc/bluetooth/main.conf
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/profiles/network/network.conf $(1)/etc/bluetooth/network.conf
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/profiles/input/input.conf $(1)/etc/bluetooth/input.conf
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/bluetoothd.init $(1)/etc/init.d/bluetoothd
+endef
+
+$(eval $(call BuildPackage,bluez-libs))
+$(eval $(call BuildPackage,bluez-utils))
+$(eval $(call BuildPackage,bluez-utils-extra))
+$(eval $(call BuildPackage,bluez-daemon))
diff --git a/external/subpack/utils/bluez/files/bluetoothd.init b/external/subpack/utils/bluez/files/bluetoothd.init
new file mode 100644
index 0000000..8c548bc
--- /dev/null
+++ b/external/subpack/utils/bluez/files/bluetoothd.init
@@ -0,0 +1,14 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2007 OpenWrt.org
+
+#start after dbus (60)
+START=62
+USE_PROCD=1
+PROG=/usr/bin/bluetoothd
+
+start_service() {
+ ln -snf /etc/bluetooth/keys/ /var/lib/bluetooth
+ procd_open_instance
+ procd_set_param command "$PROG" -n
+ procd_close_instance
+}
diff --git a/external/subpack/utils/bluez/files/givepin b/external/subpack/utils/bluez/files/givepin
new file mode 100644
index 0000000..e52a338
--- /dev/null
+++ b/external/subpack/utils/bluez/files/givepin
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# Write bluetooth PIN number here:
+pin=
+
+if [ -z "$pin" ]; then
+ msg="Set bluetooth PIN in file $0"
+ logger -p user.err "$msg"
+ for i in /dev/pts/* ; do
+ [ -w $i ] && echo "$msg" > $i
+ done
+else
+ echo "PIN:$pin"
+fi
diff --git a/external/subpack/utils/bluez/patches/001-bcm43xx-Add-bcm43xx-3wire-variant.patch b/external/subpack/utils/bluez/patches/001-bcm43xx-Add-bcm43xx-3wire-variant.patch
new file mode 100644
index 0000000..9465ddc
--- /dev/null
+++ b/external/subpack/utils/bluez/patches/001-bcm43xx-Add-bcm43xx-3wire-variant.patch
@@ -0,0 +1,21 @@
+From b4f2b77472aeb967d3a7595e8a965785c7a37c87 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 16 Feb 2016 16:40:46 +0000
+Subject: [PATCH 1/4] bcm43xx: Add bcm43xx-3wire variant
+
+---
+ tools/hciattach.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/tools/hciattach.c
++++ b/tools/hciattach.c
+@@ -1078,6 +1078,9 @@ struct uart_t uart[] = {
+ { "bcm43xx", 0x0000, 0x0000, HCI_UART_H4, 115200, 3000000,
+ FLOW_CTL, DISABLE_PM, NULL, bcm43xx, NULL },
+
++ { "bcm43xx-3wire", 0x0000, 0x0000, HCI_UART_3WIRE, 115200, 3000000,
++ 0, DISABLE_PM, NULL, bcm43xx, NULL },
++
+ { "ath3k", 0x0000, 0x0000, HCI_UART_ATH3K, 115200, 115200,
+ FLOW_CTL, DISABLE_PM, NULL, ath3k_ps, ath3k_pm },
+
diff --git a/external/subpack/utils/bluez/patches/002-bcm43xx-The-UART-speed-must-be-reset-after-the-firmw.patch b/external/subpack/utils/bluez/patches/002-bcm43xx-The-UART-speed-must-be-reset-after-the-firmw.patch
new file mode 100644
index 0000000..3df6341
--- /dev/null
+++ b/external/subpack/utils/bluez/patches/002-bcm43xx-The-UART-speed-must-be-reset-after-the-firmw.patch
@@ -0,0 +1,33 @@
+From e145c9621f976063e5c573db1f2053d906f63427 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 16 Feb 2016 16:39:09 +0000
+Subject: [PATCH 2/4] bcm43xx: The UART speed must be reset after the firmware
+ download
+
+---
+ tools/hciattach_bcm43xx.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/tools/hciattach_bcm43xx.c
++++ b/tools/hciattach_bcm43xx.c
+@@ -354,11 +354,8 @@ int bcm43xx_init(int fd, int def_speed,
+ return -1;
+
+ if (bcm43xx_locate_patch(FIRMWARE_DIR, chip_name, fw_path)) {
+- fprintf(stderr, "Patch not found, continue anyway\n");
++ fprintf(stderr, "Patch not found for %s, continue anyway\n", chip_name);
+ } else {
+- if (bcm43xx_set_speed(fd, ti, speed))
+- return -1;
+-
+ if (bcm43xx_load_firmware(fd, fw_path))
+ return -1;
+
+@@ -368,6 +365,7 @@ int bcm43xx_init(int fd, int def_speed,
+ return -1;
+ }
+
++ sleep(1);
+ if (bcm43xx_reset(fd))
+ return -1;
+ }
diff --git a/external/subpack/utils/bluez/patches/003-Increase-firmware-load-timeout-to-30s.patch b/external/subpack/utils/bluez/patches/003-Increase-firmware-load-timeout-to-30s.patch
new file mode 100644
index 0000000..ec13dd7
--- /dev/null
+++ b/external/subpack/utils/bluez/patches/003-Increase-firmware-load-timeout-to-30s.patch
@@ -0,0 +1,20 @@
+From d41dc2046dd08d8c95197f677e224506f5b39bdd Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 20 Jan 2016 16:00:37 +0000
+Subject: [PATCH 3/4] Increase firmware load timeout to 30s
+
+---
+ tools/hciattach.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/tools/hciattach.c
++++ b/tools/hciattach.c
+@@ -1227,7 +1227,7 @@ int main(int argc, char *argv[])
+ {
+ struct uart_t *u = NULL;
+ int detach, printpid, raw, opt, i, n, ld, err;
+- int to = 10;
++ int to = 30;
+ int init_speed = 0;
+ int send_break = 0;
+ pid_t pid;
diff --git a/external/subpack/utils/bluez/patches/004-Move-the-43xx-firmware-into-lib-firmware.patch b/external/subpack/utils/bluez/patches/004-Move-the-43xx-firmware-into-lib-firmware.patch
new file mode 100644
index 0000000..670d430
--- /dev/null
+++ b/external/subpack/utils/bluez/patches/004-Move-the-43xx-firmware-into-lib-firmware.patch
@@ -0,0 +1,20 @@
+From 76681284b0ea49852041fdb97a35175089a08781 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Tue, 23 Feb 2016 17:52:29 +0000
+Subject: [PATCH 4/4] Move the 43xx firmware into /lib/firmware
+
+---
+ tools/hciattach_bcm43xx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/tools/hciattach_bcm43xx.c
++++ b/tools/hciattach_bcm43xx.c
+@@ -31,7 +31,7 @@
+ #include "hciattach.h"
+
+ #ifndef FIRMWARE_DIR
+-#define FIRMWARE_DIR "/etc/firmware"
++#define FIRMWARE_DIR "/lib/firmware/brcm"
+ #endif
+
+ #define FW_EXT ".hcd"
diff --git a/external/subpack/utils/bluez/patches/201-readline.patch b/external/subpack/utils/bluez/patches/201-readline.patch
new file mode 100644
index 0000000..f60001c
--- /dev/null
+++ b/external/subpack/utils/bluez/patches/201-readline.patch
@@ -0,0 +1,75 @@
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -3479,7 +3479,7 @@ unit_tests = $(am__append_55) unit/test-
+ @CLIENT_TRUE@ client/admin.c
+
+ @CLIENT_TRUE@client_bluetoothctl_LDADD = gdbus/libgdbus-internal.la src/libshared-glib.la \
+-@CLIENT_TRUE@ $(GLIB_LIBS) $(DBUS_LIBS) -lreadline
++@CLIENT_TRUE@ $(GLIB_LIBS) $(DBUS_LIBS) -lreadline -lncurses
+
+ @ZSH_COMPLETIONS_TRUE@zshcompletiondir = $(ZSH_COMPLETIONDIR)
+ @ZSH_COMPLETIONS_TRUE@dist_zshcompletion_DATA = completion/zsh/_bluetoothctl
+@@ -3722,7 +3722,7 @@ unit_tests = $(am__append_55) unit/test-
+
+ @MESH_TRUE@@TOOLS_TRUE@tools_meshctl_LDADD = gdbus/libgdbus-internal.la src/libshared-glib.la \
+ @MESH_TRUE@@TOOLS_TRUE@ lib/libbluetooth-internal.la \
+-@MESH_TRUE@@TOOLS_TRUE@ $(GLIB_LIBS) $(DBUS_LIBS) -ljson-c -lreadline
++@MESH_TRUE@@TOOLS_TRUE@ $(GLIB_LIBS) $(DBUS_LIBS) -ljson-c -lreadline -lncurses
+
+ @MESH_TRUE@@TOOLS_TRUE@tools_mesh_cfgclient_SOURCES = tools/mesh-cfgclient.c \
+ @MESH_TRUE@@TOOLS_TRUE@ tools/mesh/model.h tools/mesh/config-model.h \
+@@ -3736,7 +3736,7 @@ unit_tests = $(am__append_55) unit/test-
+ @MESH_TRUE@@TOOLS_TRUE@ mesh/crypto.h mesh/crypto.c
+
+ @MESH_TRUE@@TOOLS_TRUE@tools_mesh_cfgclient_LDADD = lib/libbluetooth-internal.la src/libshared-ell.la \
+-@MESH_TRUE@@TOOLS_TRUE@ $(ell_ldadd) -ljson-c -lreadline
++@MESH_TRUE@@TOOLS_TRUE@ $(ell_ldadd) -ljson-c -lreadline -lncurses
+
+ @MESH_TRUE@@TOOLS_TRUE@tools_mesh_cfgtest_SOURCES = tools/mesh-cfgtest.c
+ @MESH_TRUE@@TOOLS_TRUE@tools_mesh_cfgtest_LDADD = lib/libbluetooth-internal.la src/libshared-ell.la \
+@@ -3793,7 +3793,7 @@ unit_tests = $(am__append_55) unit/test-
+ @READLINE_TRUE@ tools/obex-client-tool.c
+
+ @READLINE_TRUE@tools_obex_client_tool_LDADD = lib/libbluetooth-internal.la \
+-@READLINE_TRUE@ src/libshared-glib.la $(GLIB_LIBS) -lreadline
++@READLINE_TRUE@ src/libshared-glib.la $(GLIB_LIBS) -lreadline -lncurses
+
+ @READLINE_TRUE@tools_obex_server_tool_SOURCES = $(gobex_sources) $(btio_sources) \
+ @READLINE_TRUE@ tools/obex-server-tool.c
+@@ -3804,15 +3804,15 @@ unit_tests = $(am__append_55) unit/test-
+ @READLINE_TRUE@tools_bluetooth_player_SOURCES = tools/bluetooth-player.c
+ @READLINE_TRUE@tools_bluetooth_player_LDADD = gdbus/libgdbus-internal.la \
+ @READLINE_TRUE@ src/libshared-glib.la \
+-@READLINE_TRUE@ $(GLIB_LIBS) $(DBUS_LIBS) -lreadline
++@READLINE_TRUE@ $(GLIB_LIBS) $(DBUS_LIBS) -lreadline -lncurses
+
+ @READLINE_TRUE@tools_obexctl_SOURCES = tools/obexctl.c
+ @READLINE_TRUE@tools_obexctl_LDADD = gdbus/libgdbus-internal.la src/libshared-glib.la \
+-@READLINE_TRUE@ $(GLIB_LIBS) $(DBUS_LIBS) -lreadline
++@READLINE_TRUE@ $(GLIB_LIBS) $(DBUS_LIBS) -lreadline -lncurses
+
+ @READLINE_TRUE@tools_btmgmt_SOURCES = tools/btmgmt.c src/uuid-helper.c client/display.c
+ @READLINE_TRUE@tools_btmgmt_LDADD = lib/libbluetooth-internal.la src/libshared-mainloop.la \
+-@READLINE_TRUE@ -lreadline
++@READLINE_TRUE@ -lreadline -lncurses
+
+ @DEPRECATED_TRUE@@READLINE_TRUE@attrib_gatttool_SOURCES = attrib/gatttool.c attrib/att.c attrib/gatt.c \
+ @DEPRECATED_TRUE@@READLINE_TRUE@ attrib/gattrib.c btio/btio.c \
+@@ -3821,7 +3821,7 @@ unit_tests = $(am__append_55) unit/test-
+ @DEPRECATED_TRUE@@READLINE_TRUE@ client/display.h
+
+ @DEPRECATED_TRUE@@READLINE_TRUE@attrib_gatttool_LDADD = lib/libbluetooth-internal.la \
+-@DEPRECATED_TRUE@@READLINE_TRUE@ src/libshared-glib.la $(GLIB_LIBS) -lreadline
++@DEPRECATED_TRUE@@READLINE_TRUE@ src/libshared-glib.la $(GLIB_LIBS) -lreadline -lncurses
+
+ @CUPS_TRUE@cupsdir = $(libdir)/cups/backend
+ @CUPS_TRUE@profiles_cups_bluetooth_SOURCES = profiles/cups/main.c \
+@@ -3841,7 +3841,7 @@ unit_tests = $(am__append_55) unit/test-
+ @BTPCLIENT_TRUE@tools_btpclient_DEPENDENCIES = lib/libbluetooth-internal.la $(ell_dependencies)
+ @BTPCLIENT_TRUE@tools_btpclientctl_SOURCES = tools/btpclientctl.c client/display.c
+ @BTPCLIENT_TRUE@tools_btpclientctl_LDADD = src/libshared-mainloop.la src/libshared-glib.la \
+-@BTPCLIENT_TRUE@ lib/libbluetooth-internal.la -lreadline
++@BTPCLIENT_TRUE@ lib/libbluetooth-internal.la -lreadline -lncurses
+
+
+ # SPDX-License-Identifier: GPL-2.0
diff --git a/external/subpack/utils/bluez/patches/202-fix-endianness.patch b/external/subpack/utils/bluez/patches/202-fix-endianness.patch
new file mode 100644
index 0000000..c0086cc
--- /dev/null
+++ b/external/subpack/utils/bluez/patches/202-fix-endianness.patch
@@ -0,0 +1,10 @@
+--- a/src/shared/util.h
++++ b/src/shared/util.h
+@@ -15,6 +15,7 @@
+ #include <byteswap.h>
+ #include <string.h>
+ #include <sys/types.h>
++#include <endian.h>
+
+ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+ #define BIT(n) (1 << (n))
diff --git a/external/subpack/utils/bluez/patches/203-obexd_without_systemd.patch b/external/subpack/utils/bluez/patches/203-obexd_without_systemd.patch
new file mode 100644
index 0000000..c2f23c1
--- /dev/null
+++ b/external/subpack/utils/bluez/patches/203-obexd_without_systemd.patch
@@ -0,0 +1,49 @@
+Submitted By: Armin K. <krejzi at email dot com>
+Date: 2013-04-29
+Initial Package Version: 5.17
+Upstream Status: unknown
+Origin: Arch Linux (Giovanni Campagna)
+Description: Allow using obexd without systemd in the user session
+
+Not all sessions run systemd --user (actually, the majority
+doesn't), so the dbus daemon must be able to spawn obexd
+directly, and to do so it needs the full path of the daemon.
+---
+ Makefile.obexd | 4 ++--
+ obexd/src/org.bluez.obex.service | 4 ----
+ obexd/src/org.bluez.obex.service.in | 4 ++++
+ 3 files changed, 6 insertions(+), 6 deletions(-)
+ delete mode 100644 obexd/src/org.bluez.obex.service
+ create mode 100644 obexd/src/org.bluez.obex.service.in
+
+--- a/Makefile.obexd
++++ b/Makefile.obexd
+@@ -2,12 +2,12 @@
+ if SYSTEMD
+ systemduserunitdir = $(SYSTEMD_USERUNITDIR)
+ systemduserunit_DATA = obexd/src/obex.service
++endif
+
+ dbussessionbusdir = $(DBUS_SESSIONBUSDIR)
+ dbussessionbus_DATA = obexd/src/org.bluez.obex.service
+-endif
+
+-EXTRA_DIST += obexd/src/obex.service.in obexd/src/org.bluez.obex.service
++EXTRA_DIST += obexd/src/obex.service.in obexd/src/org.bluez.obex.service.in
+
+ if OBEX
+
+--- a/obexd/src/org.bluez.obex.service
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[D-BUS Service]
+-Name=org.bluez.obex
+-Exec=/bin/false
+-SystemdService=dbus-org.bluez.obex.service
+--- /dev/null
++++ b/obexd/src/org.bluez.obex.service.in
+@@ -0,0 +1,4 @@
++[D-BUS Service]
++Name=org.bluez.obex
++Exec=@libexecdir@/obexd
++SystemdService=dbus-org.bluez.obex.service
diff --git a/external/subpack/utils/bluez/patches/205-refresh_adv_manager_for_non-LE_devices.patch b/external/subpack/utils/bluez/patches/205-refresh_adv_manager_for_non-LE_devices.patch
new file mode 100644
index 0000000..3252ecf
--- /dev/null
+++ b/external/subpack/utils/bluez/patches/205-refresh_adv_manager_for_non-LE_devices.patch
@@ -0,0 +1,47 @@
+From 2c3bba7b38be03834162e34069156f1fd49f0528 Mon Sep 17 00:00:00 2001
+From: "antoine.belvire@laposte.net" <antoine.belvire@laposte.net>
+Date: Tue, 27 Mar 2018 20:30:26 +0200
+Subject: adapter: Don't refresh adv_manager for non-LE devices
+
+btd_adv_manager_refresh is called upon MGMT_SETTING_DISCOVERABLE setting change
+but as only LE adapters have an adv_manager, this leads to segmentation fault
+for non-LE devices:
+
+0 btd_adv_manager_refresh (manager=0x0) at src/advertising.c:1176
+1 0x0000556fe45fcb02 in settings_changed (settings=<optimized out>,
+ adapter=0x556fe53f7c70) at src/adapter.c:543
+2 new_settings_callback (index=<optimized out>, length=<optimized out>,
+ param=<optimized out>, user_data=0x556fe53f7c70) at src/adapter.c:573
+3 0x0000556fe462c278 in request_complete (mgmt=mgmt@entry=0x556fe53f20c0,
+ status=<optimized out>, opcode=opcode@entry=7, index=index@entry=0,
+ length=length@entry=4, param=0x556fe53eb5f9) at src/shared/mgmt.c:261
+4 0x0000556fe462cd9d in can_read_data (io=<optimized out>,
+ user_data=0x556fe53f20c0) at src/shared/mgmt.c:353
+5 0x0000556fe46396e3 in watch_callback (channel=<optimized out>,
+ cond=<optimized out>, user_data=<optimized out>)
+ at src/shared/io-glib.c:170
+6 0x00007fe351c980e5 in g_main_context_dispatch ()
+ from /usr/lib64/libglib-2.0.so.0
+7 0x00007fe351c984b0 in ?? () from /usr/lib64/libglib-2.0.so.0
+8 0x00007fe351c987c2 in g_main_loop_run () from /usr/lib64/libglib-2.0.so.0
+9 0x0000556fe45abc75 in main (argc=<optimized out>, argv=<optimized out>)
+ at src/main.c:770
+
+This commit prevents the call to btd_adv_manager_refresh for non-LE devices.
+---
+ src/adapter.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/src/adapter.c
++++ b/src/adapter.c
+@@ -601,7 +601,9 @@ static void settings_changed(struct btd_
+ */
+ if (!adapter->discovery_discoverable)
+ store_adapter_info(adapter);
+- btd_adv_manager_refresh(adapter->adv_manager);
++
++ if (adapter->supported_settings & MGMT_SETTING_LE)
++ btd_adv_manager_refresh(adapter->adv_manager);
+ }
+
+ if (changed_mask & MGMT_SETTING_BONDABLE) {
diff --git a/external/subpack/utils/bluez/patches/206-sync.patch b/external/subpack/utils/bluez/patches/206-sync.patch
new file mode 100644
index 0000000..265400e
--- /dev/null
+++ b/external/subpack/utils/bluez/patches/206-sync.patch
@@ -0,0 +1,27 @@
+--- a/obexd/client/sync.c
++++ b/obexd/client/sync.c
+@@ -209,7 +209,7 @@ static void sync_remove(struct obc_sessi
+ g_dbus_unregister_interface(conn, path, SYNC_INTERFACE);
+ }
+
+-static struct obc_driver sync = {
++static struct obc_driver sync2 = {
+ .service = "SYNC",
+ .uuid = SYNC_UUID,
+ .target = OBEX_SYNC_UUID,
+@@ -228,7 +228,7 @@ int sync_init(void)
+ if (!conn)
+ return -EIO;
+
+- err = obc_driver_register(&sync);
++ err = obc_driver_register(&sync2);
+ if (err < 0) {
+ dbus_connection_unref(conn);
+ conn = NULL;
+@@ -245,5 +245,5 @@ void sync_exit(void)
+ dbus_connection_unref(conn);
+ conn = NULL;
+
+- obc_driver_unregister(&sync);
++ obc_driver_unregister(&sync2);
+ }
diff --git a/external/subpack/utils/bmx7-dnsupdate/Makefile b/external/subpack/utils/bmx7-dnsupdate/Makefile
new file mode 100644
index 0000000..aa168c1
--- /dev/null
+++ b/external/subpack/utils/bmx7-dnsupdate/Makefile
@@ -0,0 +1,28 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bmx7-dnsupdate
+PKG_VERSION:=0.1
+PKG_RELEASE:=2
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/bmx7-dnsupdate
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=bmx7-dnsupdate
+ MAINTAINER:=Paul Spooren <spooren@informatik.uni-leipzig.de>
+ DEPENDS:=+bmx7 +bmx7-json inotifywait jshn
+ PKGARCH:=all
+endef
+
+define Build/Compile
+endef
+
+define Build/Configure
+endef
+
+define Package/bmx7-dnsupdate/install
+ $(CP) files/* $(1)/
+endef
+
+$(eval $(call BuildPackage,bmx7-dnsupdate))
diff --git a/external/subpack/utils/bmx7-dnsupdate/files/etc/init.d/bmx7-dnsupdate b/external/subpack/utils/bmx7-dnsupdate/files/etc/init.d/bmx7-dnsupdate
new file mode 100755
index 0000000..551395f
--- /dev/null
+++ b/external/subpack/utils/bmx7-dnsupdate/files/etc/init.d/bmx7-dnsupdate
@@ -0,0 +1,14 @@
+#!/bin/sh /etc/rc.common
+START=92
+USE_PROCD=1
+
+BIN=/usr/bin/bmx7-dnsupdate
+
+start_service() {
+ procd_open_instance "bmx7-dnsupdate"
+ procd_set_param command "$BIN"
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_set_param respawn
+ procd_close_instance
+}
diff --git a/external/subpack/utils/bmx7-dnsupdate/files/usr/bin/bmx7-dnsupdate b/external/subpack/utils/bmx7-dnsupdate/files/usr/bin/bmx7-dnsupdate
new file mode 100755
index 0000000..2f87437
--- /dev/null
+++ b/external/subpack/utils/bmx7-dnsupdate/files/usr/bin/bmx7-dnsupdate
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+. /usr/share/libubox/jshn.sh
+
+while true; do
+ json_load "$(bmx7 -c jshow=originators)"
+ json_select "originators"
+ idx="1"
+
+ # clean all bmx7 dns entries
+ > /tmp/hosts/bmx7
+
+ while json_get_type Type "$idx" && [ "$Type" == object ]; do
+ json_select "$idx"
+ json_get_var shortId shortId
+ json_get_var name name
+ json_get_var primaryIp primaryIp
+ printf "$primaryIp $name\n$primaryIp $shortId\n" >> /tmp/hosts/bmx7
+ json_select ..
+ $((idx++)) 2> /dev/null
+ done
+
+ # reload dnsmasq to apply changes
+ logger -t bmx7-dnsupdate "dnsmasq updated due to new hosts"
+ killall -HUP dnsmasq
+
+ # block until originators changes
+ inotifywait -e create -e delete -q /var/run/bmx7/json/originators/ || sleep 10
+done
diff --git a/external/subpack/utils/bonnie++/Makefile b/external/subpack/utils/bonnie++/Makefile
new file mode 100644
index 0000000..6e6d6df
--- /dev/null
+++ b/external/subpack/utils/bonnie++/Makefile
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2009-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bonnie++
+PKG_VERSION:=1.98
+PKG_RELEASE:=4
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tgz
+PKG_SOURCE_URL:=https://www.coker.com.au/bonnie++/
+PKG_HASH:=6e0bcbc08b78856fd998dd7bcb352d4615a99c26c2dc83d5b8345b102bad0b04
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=copyright.txt
+
+PKG_FIXUP:=autoreconf
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/uclibc++.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/bonniexx
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=$(CXX_DEPENDS) +libpthread
+ TITLE:=Bonnie++ - hard drive bottleneck testing program.
+ URL:=https://www.coker.com.au/bonnie++/
+endef
+
+define Package/bonniexx/description
+ Bonnie++ is a benchmark suite that is aimed at performing a number of simple
+ tests of hard drive and file system performance.
+endef
+
+TARGET_CXXFLAGS += -ffunction-sections -fdata-sections -fno-rtti -flto
+
+define Package/bonniexx/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_BUILD_DIR)/bonnie++ $(1)/usr/bin/
+ $(CP) $(PKG_BUILD_DIR)/bon_csv2html $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,bonniexx))
diff --git a/external/subpack/utils/bonnie++/patches/002-add-verbose-error-messages.patch b/external/subpack/utils/bonnie++/patches/002-add-verbose-error-messages.patch
new file mode 100644
index 0000000..521ca9c
--- /dev/null
+++ b/external/subpack/utils/bonnie++/patches/002-add-verbose-error-messages.patch
@@ -0,0 +1,47 @@
+--- a/bon_file.cpp
++++ b/bon_file.cpp
+@@ -469,25 +469,37 @@ int COpenTest::delete_sequential(BonTime
+ }
+ if(m_number_directories != 1)
+ {
+- if(chdir("..") || rmdir(buf))
++ if(chdir(".."))
+ {
++ io_error("chdir");
++ return -1;
++ }
++ if(rmdir(buf))
++ {
++ fprintf(stderr, "Unable to delete directory '%s'\n", buf);
+ io_error("rmdir");
+ return -1;
+ }
+ }
+ }
+- if(chdir("..") || rmdir(m_dirname))
++ if(count != m_number)
+ {
+- io_error("rmdir");
++ fprintf(stderr, "Expected %d files but only got %d\n", m_number, count);
+ return -1;
+ }
+- delete m_dirname;
+- m_dirname = NULL;
+- if(count != m_number)
++ if(chdir(".."))
+ {
+- fprintf(stderr, "Expected %d files but only got %d\n", m_number, count);
++ io_error("chdir");
++ return -1;
++ }
++ if(rmdir(m_dirname))
++ {
++ fprintf(stderr, "Unable to delete directory '%s'\n", m_dirname);
++ io_error("rmdir");
+ return -1;
+ }
++ delete m_dirname;
++ m_dirname = NULL;
+ sync();
+ timer.stop_and_record(DelSeq);
+ timer.add_latency(DelSeq, dur.getMax());
diff --git a/external/subpack/utils/bonnie++/patches/010-openwrt-fixes.patch b/external/subpack/utils/bonnie++/patches/010-openwrt-fixes.patch
new file mode 100644
index 0000000..123a481
--- /dev/null
+++ b/external/subpack/utils/bonnie++/patches/010-openwrt-fixes.patch
@@ -0,0 +1,81 @@
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -7,12 +7,6 @@ SCRIPTS=bon_csv2txt
+
+ prefix=@prefix@
+ eprefix=@exec_prefix@
+-#MORE_WARNINGS=-Weffc++
+-WFLAGS=-Wall -W -Wshadow -Wpointer-arith -Wwrite-strings -pedantic -ffor-scope -Wcast-align -Wsign-compare -Wpointer-arith -Wwrite-strings -Wformat-security -Wswitch-enum -Winit-self $(MORE_WARNINGS)
+-CFLAGS=-O2 @debug@ -DNDEBUG $(WFLAGS) $(MORECFLAGS)
+-CXX=@CXX@ $(CFLAGS)
+-LINK=@CXX@
+-THREAD_LFLAGS=@thread_ldflags@
+
+ INSTALL=@INSTALL@
+ INSTALL_PROGRAM=@INSTALL_PROGRAM@
+@@ -34,22 +28,22 @@ GETCHSRC=getc_putc_helper.cpp duration.c
+ GETCHOBJS=$(GETCHSRC:.cpp=.o)
+
+ bonnie++: $(BONOBJS)
+- $(LINK) -o bonnie++ $(BONOBJS) $(THREAD_LFLAGS)
++ $(CXX) $(CXXFLAGS) -o bonnie++ $(BONOBJS) @thread_ldflags@
+
+ zcav: $(ZCAVOBJS)
+- $(LINK) -o zcav $(ZCAVOBJS) $(THREAD_LFLAGS)
++ $(CXX) $(CXXFLAGS) -o zcav $(ZCAVOBJS) @thread_ldflags@
+
+ getc_putc: $(GETCOBJS) getc_putc_helper
+- $(LINK) -o getc_putc $(GETCOBJS) $(THREAD_LFLAGS)
++ $(CXX) $(CXXFLAGS) -o getc_putc $(GETCOBJS)
+
+ getc_putc_helper: $(GETCHOBJS)
+- $(CXX) -o getc_putc_helper $(GETCHOBJS)
++ $(CXX) $(CXXFLAGS) -o getc_putc_helper $(GETCHOBJS)
+
+ bon_csv2html: bon_csv2html.o
+- $(LINK) bon_csv2html.o -o bon_csv2html
++ $(CXX) $(CXXFLAGS) bon_csv2html.o -o bon_csv2html
+
+ generate_randfile: generate_randfile.o
+- $(LINK) generate_randfile.o -o generate_randfile
++ $(CXX) $(CXXFLAGS) generate_randfile.o -o generate_randfile
+
+ install-bin: $(EXE) $(EXES)
+ mkdir -p $(eprefix)/bin $(eprefix)/sbin
+@@ -63,7 +57,7 @@ install: install-bin
+ @INSTALL_DATA@ $(MAN8) @mandir@/man8
+
+ %.o: %.cpp
+- $(CXX) -c $<
++ $(CXX) $(CXXFLAGS) -c $<
+
+ clean:
+ rm -f $(EXE) $(EXES) *.o build-stamp install-stamp
+--- a/configure.in
++++ b/configure.in
+@@ -31,7 +31,6 @@ fi
+
+ dnl Checks for programs.
+ AC_LANG_CPLUSPLUS
+-AC_PROG_CC
+ AC_PROG_CXX
+ AC_PROG_CXXCPP
+ AC_PROG_INSTALL
+@@ -66,7 +65,7 @@ AC_SUBST(linux_pthread)
+ AC_TRY_COMPILE([#define _GNU_SOURCE
+ #include <pthread.h>
+ ] , [pthread_mutexattr_t attr;
+- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);]
++ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);]
+ , linux_pthread="yes")
+ if [[ -n "$linux_pthread" ]]; then
+ linux_pthread="#define LINUX_PTHREAD"
+@@ -83,7 +82,7 @@ void * thread_func(void * param) { retur
+ , thread_ldflags="-pthread")
+
+ AC_SUBST(large_file)
+-AC_TRY_RUN([#ifndef _LARGEFILE64_SOURCE
++AC_TRY_COMPILE([#ifndef _LARGEFILE64_SOURCE
+ #define _LARGEFILE64_SOURCE
+ #endif
+ #include <stdio.h>
diff --git a/external/subpack/utils/bottlerocket/Makefile b/external/subpack/utils/bottlerocket/Makefile
new file mode 100644
index 0000000..d865b6d
--- /dev/null
+++ b/external/subpack/utils/bottlerocket/Makefile
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2020 Brian Norris <computersforpeace@gmail.com>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bottlerocket
+PKG_VERSION:=0.04c
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://linuxha.com/bottlerocket
+PKG_HASH:=deb8fbf8856f87af15fa9883e07b1fddb2aa78f6b4c7d119ae4bd664dc1d19ae
+
+PKG_MAINTAINER:=Brian Norris <computersforpeace@gmail.com>
+PKG_LICENSE:=LGPL-2.1-only
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/bottlerocket
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Bottlerocket
+ URL:=https://linuxha.com/bottlerocket/
+endef
+
+define Package/bottlerocket/description
+ BottleRocket is an interface to the X10 FireCracker home automation kit.
+endef
+
+define Package/bottlerocket/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/br $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,bottlerocket))
diff --git a/external/subpack/utils/btrfs-progs/Config.in b/external/subpack/utils/btrfs-progs/Config.in
new file mode 100644
index 0000000..88cd869
--- /dev/null
+++ b/external/subpack/utils/btrfs-progs/Config.in
@@ -0,0 +1,9 @@
+if PACKAGE_btrfs-progs
+
+config BTRFS_PROGS_ZSTD
+ bool "Build with zstd support"
+ default n
+ help
+ This allows you to manage BTRFS with zstd compression
+
+endif
diff --git a/external/subpack/utils/btrfs-progs/Makefile b/external/subpack/utils/btrfs-progs/Makefile
new file mode 100644
index 0000000..8ce482f
--- /dev/null
+++ b/external/subpack/utils/btrfs-progs/Makefile
@@ -0,0 +1,95 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=btrfs-progs
+PKG_VERSION:=5.11
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/linux/kernel/people/kdave/btrfs-progs
+PKG_HASH:=d41961b0a92160c80f894ad9a1882822889c2e1d084cbf3e08b8c214a5cf0137
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-v$(PKG_VERSION)
+
+PKG_MAINTAINER:=Karel Kočí <karel.koci@nic.cz>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+PKG_BUILD_DEPENDS:=acl
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/btrfs-progs
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Filesystem
+ TITLE:=Btrfs filesystems utilities
+ URL:=https://btrfs.wiki.kernel.org/
+ DEPENDS:= \
+ +libattr \
+ +libuuid \
+ +libmount \
+ +zlib \
+ +libblkid \
+ +liblzo \
+ +libpthread \
+ +kmod-fs-btrfs \
+ +BTRFS_PROGS_ZSTD:libzstd
+endef
+
+define Package/btrfs-progs/description
+ Btrfs is a new copy on write filesystem for Linux aimed at implementing
+ advanced features while focusing on fault tolerance, repair and easy
+ administration. Initially developed by Oracle, Btrfs is licensed under the
+ GPL and open for contribution from anyone.
+endef
+
+define Package/btrfs-progs/config
+ source "$(SOURCE)/Config.in"
+endef
+
+boxprogs = btrfsck mkfs.btrfs btrfs-image btrfstune btrfs-find-root
+progs = btrfs-map-logical btrfs-select-super
+
+TARGET_CFLAGS += -ffunction-sections -fdata-sections
+TARGET_LDFLAGS += -Wl,--gc-sections -Wl,--as-needed
+
+EXTRA_CFLAGS=$(TARGET_CPPFLAGS)
+
+CONFIGURE_ARGS += \
+ --disable-backtrace \
+ --disable-convert \
+ --disable-documentation \
+ --disable-python
+ifneq ($(CONFIG_BTRFS_PROGS_ZSTD),y)
+CONFIGURE_ARGS += --disable-zstd
+endif
+
+MAKE_INSTALL_FLAGS += BUILD_PROGRAMS=0
+
+Build/Compile=$(call Build/Compile/Default,btrfs.box $(progs))
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbtrfs* $(1)/usr/lib/
+endef
+
+define Package/btrfs-progs/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbtrfs.so* $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbtrfsutil.so* $(1)/usr/lib
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/btrfs.box $(1)/usr/bin/btrfs
+ $(foreach prog,$(boxprogs),$(LN) btrfs $(1)/usr/bin/$(prog);)
+ $(foreach prog,$(progs),$(INSTALL_BIN) $(PKG_BUILD_DIR)/$(prog) $(1)/usr/bin/;)
+ $(INSTALL_DIR) $(1)/lib/preinit
+ $(INSTALL_BIN) ./files/btrfs-scan.init $(1)/lib/preinit/85_btrfs_scan
+endef
+
+$(eval $(call BuildPackage,btrfs-progs))
diff --git a/external/subpack/utils/btrfs-progs/files/btrfs-scan.init b/external/subpack/utils/btrfs-progs/files/btrfs-scan.init
new file mode 100644
index 0000000..6b9ab62
--- /dev/null
+++ b/external/subpack/utils/btrfs-progs/files/btrfs-scan.init
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+preinit_btrfs_scan() {
+ if grep -q btrfs /proc/filesystems; then
+ btrfs device scan
+ fi
+}
+
+boot_hook_add preinit_main preinit_btrfs_scan
diff --git a/external/subpack/utils/byobu/Makefile b/external/subpack/utils/byobu/Makefile
new file mode 100644
index 0000000..be3a1e9
--- /dev/null
+++ b/external/subpack/utils/byobu/Makefile
@@ -0,0 +1,102 @@
+#
+# Copyright (C) 2009 Sharim At Work, Ltd.
+# Copyright (C) 2019 Jeffery To
+# Author: Xiangfu Liu <xiangfu@sharism.cc>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=byobu
+PKG_VERSION:=5.133
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.gz
+PKG_SOURCE_URL:=https://launchpad.net/byobu/trunk/$(PKG_VERSION)/+download
+PKG_HASH:=4d8ea48f8c059e56f7174df89b04a08c32286bae5a21562c5c6f61be6dab7563
+
+PKG_LICENSE:=GPL-3.0
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=Jeffery To <jeffery.to@gmail.com>
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/byobu/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ URL:=http://byobu.org/
+ PKGARCH:=all
+endef
+
+define Package/byobu
+$(call Package/byobu/Default)
+ TITLE:=Text-based window manager and terminal multiplexer
+ DEPENDS:=+python3-light +python3-newt
+endef
+
+define Package/byobu-utils
+$(call Package/byobu/Default)
+ TITLE:=Utilities included with byobu
+endef
+
+define Package/byobu/description
+ Byobu is a GPLv3 open source text-based window manager and terminal
+ multiplexer. It was originally designed to provide elegant enhancements
+ to the otherwise functional, plain, practical GNU Screen, for the Ubuntu
+ server distribution. Byobu now includes an enhanced profiles, convenient
+ keybindings, configuration utilities, and toggle-able system status
+ notifications for both the GNU Screen window manager and the more modern
+ Tmux terminal multiplexer, and works on most Linux, BSD, and Mac
+ distributions.
+endef
+
+define Package/byobu-utils/description
+$(call Package/byobu/description)
+
+ These are the "bikeshed" utilities bundled with byobu:
+ * col1..col9, NF
+ * ctail
+ * manifest
+ * purge-old-kernels
+ * vigpg
+ * wifi-status
+endef
+
+define Package/byobu/install
+ $(INSTALL_DIR) $(1)/etc
+ $(CP) $(PKG_INSTALL_DIR)/etc/* $(1)/etc/
+
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/byobu* $(1)/usr/bin/
+ $(LN) byobu $(1)/usr/bin/byobu-screen
+ $(LN) byobu $(1)/usr/bin/byobu-tmux
+
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/byobu $(1)/usr/lib/
+
+ $(INSTALL_DIR) $(1)/usr/share/byobu
+ for i in keybindings profiles status windows; do \
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/byobu/$$$$i $(1)/usr/share/byobu/ ; \
+ done
+
+ $(INSTALL_DIR) $(1)/usr/share/doc
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/doc/byobu $(1)/usr/share/doc/
+endef
+
+define Package/byobu-utils/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ for i in col1 ctail manifest purge-old-kernels vigpg wifi-status; do \
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/$$$$i $(1)/usr/bin/ ; \
+ done
+ for i in col2 col3 col4 col5 col6 col7 col8 col9 NF; do \
+ $(LN) col1 $(1)/usr/bin/$$$$i ; \
+ done
+endef
+
+$(eval $(call BuildPackage,byobu))
+$(eval $(call BuildPackage,byobu-utils))
diff --git a/external/subpack/utils/byobu/patches/001-hardcode-utf-8-charmap.patch b/external/subpack/utils/byobu/patches/001-hardcode-utf-8-charmap.patch
new file mode 100644
index 0000000..e824ff0
--- /dev/null
+++ b/external/subpack/utils/byobu/patches/001-hardcode-utf-8-charmap.patch
@@ -0,0 +1,11 @@
+--- a/usr/bin/byobu.in
++++ b/usr/bin/byobu.in
+@@ -46,7 +46,7 @@ if [ -z "${BYOBU_PREFIX}" ]; then
+ . "$HOME/.byoburc"
+ fi
+ fi
+-export BYOBU_CHARMAP=$(locale charmap)
++export BYOBU_CHARMAP=UTF-8
+ [ -r "$HOME/.byoburc" ] && . "$HOME/.byoburc"
+ [ -z "${BYOBU_PREFIX}" ] && export BYOBU_PREFIX="@prefix@" || export BYOBU_PREFIX
+ . "${BYOBU_PREFIX}/lib/${PKG}/include/common"
diff --git a/external/subpack/utils/byobu/patches/002-fix-missing-tty.patch b/external/subpack/utils/byobu/patches/002-fix-missing-tty.patch
new file mode 100644
index 0000000..fe80ecf
--- /dev/null
+++ b/external/subpack/utils/byobu/patches/002-fix-missing-tty.patch
@@ -0,0 +1,11 @@
+--- a/usr/bin/byobu-launch.in
++++ b/usr/bin/byobu-launch.in
+@@ -30,7 +30,7 @@
+ # or edit your sshd_config, ssh_config, and set:
+ # $HOME/.bashrc: export BYOBU_DISABLE=1
+
+-_tty=$(tty)
++_tty=$(readlink /proc/$$/fd/0)
+ if [ "${_tty#/dev/ttyS}" != "$_tty" ] && [ "${_tty#/dev/ttyAMA}" != "$_tty" ]; then
+ # Don't autolaunch byobu on serial consoles
+ # You can certainly run 'byobu' manually, though
diff --git a/external/subpack/utils/byobu/patches/004-skip-python-test.patch b/external/subpack/utils/byobu/patches/004-skip-python-test.patch
new file mode 100644
index 0000000..c183676
--- /dev/null
+++ b/external/subpack/utils/byobu/patches/004-skip-python-test.patch
@@ -0,0 +1,10 @@
+--- a/usr/lib/byobu/include/constants
++++ b/usr/lib/byobu/include/constants
+@@ -58,6 +58,7 @@ $BYOBU_SED --follow-symlinks "s///" /dev
+ eval $BYOBU_TEST ulimit >/dev/null 2>&1 && export BYOBU_ULIMIT="ulimit" || export BYOBU_ULIMIT="false"
+
+ # Find a suitable python interpreter, if undefined
++export BYOBU_PYTHON="python3"
+ if [ -z "$BYOBU_PYTHON" ]; then
+ if python3 -c "import snack" >/dev/null 2>&1; then
+ export BYOBU_PYTHON="python3"
diff --git a/external/subpack/utils/byobu/patches/005-monitor-overlay.patch b/external/subpack/utils/byobu/patches/005-monitor-overlay.patch
new file mode 100644
index 0000000..0fbfb3b
--- /dev/null
+++ b/external/subpack/utils/byobu/patches/005-monitor-overlay.patch
@@ -0,0 +1,41 @@
+--- a/usr/lib/byobu/disk
++++ b/usr/lib/byobu/disk
+@@ -26,7 +26,10 @@ __disk_detail() {
+ __disk() {
+ local out="" MP="" size="" pct="" unit=""
+ # Default to /, but let users override
+- [ -z "$MONITORED_DISK" ] && MP="/" || MP="$MONITORED_DISK"
++ MP="$MONITORED_DISK"
++ [ -n "$MP" ] || {
++ grep -q ' /overlay ' /proc/mounts && MP=/overlay || MP=/
++ }
+ case $MP in
+ /dev/*) MP=$(awk '$1 == m { print $2; exit(0); }' "m=$MP" /proc/mounts);;
+ esac
+--- a/usr/lib/byobu/disk_io
++++ b/usr/lib/byobu/disk_io
+@@ -42,7 +42,10 @@ getdisk() {
+ __disk_io() {
+ local part= i=
+ # Default to disk providing /, but let users override with MONITORED_DISK
+- [ -z "$MONITORED_DISK" ] && mount_point="/" || mount_point="$MONITORED_DISK"
++ local mount_point="$MONITORED_DISK"
++ [ -n "$mount_point" ] || {
++ grep -q ' /overlay ' /proc/mounts && mount_point=/overlay || mount_point=/
++ }
+ # By default, we won't bug the user with the display of network traffic
+ # below DISK_IO_THRESHOLD in kB/s; override in $BYOBU_CONFIG_DIR/status
+ [ -n "$DISK_IO_THRESHOLD" ] || DISK_IO_THRESHOLD=50
+--- a/usr/share/byobu/status/statusrc
++++ b/usr/share/byobu/status/statusrc
+@@ -36,8 +36,8 @@
+ # and your lsb_release is "precise", only "p" will be displayed
+ #RELEASE_ABBREVIATED=1
+
+-# Default: /
+-#MONITORED_DISK=/
++# Default: /overlay
++#MONITORED_DISK=/overlay
+
+ # Minimum disk throughput that triggers the notification (in kB/s)
+ # Default: 50
diff --git a/external/subpack/utils/byobu/patches/006-only-pgrep-services.patch b/external/subpack/utils/byobu/patches/006-only-pgrep-services.patch
new file mode 100644
index 0000000..be1b9a2
--- /dev/null
+++ b/external/subpack/utils/byobu/patches/006-only-pgrep-services.patch
@@ -0,0 +1,11 @@
+--- a/usr/lib/byobu/services
++++ b/usr/lib/byobu/services
+@@ -24,6 +24,8 @@ __services_detail() {
+ }
+
+ service_running() {
++ pgrep "$1" >/dev/null
++ return $?
+ if [ -f "/etc/init/$1.conf" ]; then
+ # Use upstart
+ case "$(status $1 2>/dev/null)" in
diff --git a/external/subpack/utils/byobu/patches/007-count-dropbear-users.patch b/external/subpack/utils/byobu/patches/007-count-dropbear-users.patch
new file mode 100644
index 0000000..357270e
--- /dev/null
+++ b/external/subpack/utils/byobu/patches/007-count-dropbear-users.patch
@@ -0,0 +1,24 @@
+--- a/usr/lib/byobu/users
++++ b/usr/lib/byobu/users
+@@ -26,7 +26,12 @@ __users_detail() {
+ }
+
+ __users() {
+- local count=0
++ local count=0 f pid
++ for f in /var/run/dropbear.*.pid; do
++ read pid < "$f"
++ count=$(($count + $(pgrep -P "$pid" | wc -l)))
++ done
++ if [ $count -eq 0 ]; then
+ if [ "$USERS_DISTINCT" = "1" ]; then
+ count=$(pgrep -fl 'sshd:.*@' | cut -f3 -d\ | cut -f1 -d@ | sort -u | wc -l)
+ else
+@@ -34,6 +39,7 @@ __users() {
+ # busybox and some distro's pgrep (and it doesn't exit non-zero).
+ count=$(pgrep -f "^sshd:.*@|^/usr/sbin/sshd -i" | wc -l) || return
+ fi
++ fi
+ if [ $count -gt 0 ]; then
+ color b w r; printf "%d" "$count"; color -; color w r; printf "##"; color --
+ else
diff --git a/external/subpack/utils/cache-domains/Makefile b/external/subpack/utils/cache-domains/Makefile
new file mode 100644
index 0000000..a7f0633
--- /dev/null
+++ b/external/subpack/utils/cache-domains/Makefile
@@ -0,0 +1,66 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=cache-domains
+PKG_VERSION:=2.3.1
+PKG_RELEASE:=1
+
+PKG_MAINTAINER:=Gerard Ryan <G.M0N3Y.2503@gmail.com>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/cache-domains/default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Game content cache DNS
+ URL:=https://github.com/uklans/cache-domains
+ DEPENDS:=+jq +bash +dnsmasq +ca-bundle
+ DEPENDS+=liblog
+endef
+
+define Package/cache-domains/description/default
+hotplug script to dynamically configure the local DNS (dnsmasq) to redirect game content servers to a LAN cache.
+Definitive list dynamically obtained from https://github.com/uklans/cache-domains.
+endef
+
+define Package/cache-domains/install/default
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) ./files/cache-domains $(1)/usr/bin/
+
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/iface/
+ $(INSTALL_BIN) ./files/30-cache-domains $(1)/etc/hotplug.d/iface/
+endef
+
+Build/Compile=# Nothing to compile, just install the scripts
+
+
+define Package/cache-domains-openssl
+ $(Package/cache-domains/default)
+ TITLE += (openssl)
+ DEPENDS += +libustream-openssl
+ VARIANT:=openssl
+endef
+Package/cache-domains-openssl/description = $(Package/cache-domains/description/default)
+Package/cache-domains-openssl/install = $(Package/cache-domains/install/default)
+
+define Package/cache-domains-mbedtls
+ $(Package/cache-domains/default)
+ TITLE += (mbedtls)
+ DEPENDS += +libustream-mbedtls
+ VARIANT:=mbedtls
+endef
+Package/cache-domains-mbedtls/description = $(Package/cache-domains/description/default)
+Package/cache-domains-mbedtls/install = $(Package/cache-domains/install/default)
+
+define Package/cache-domains-wolfssl
+ $(Package/cache-domains/default)
+ TITLE += (wolfssl)
+ DEPENDS += +libustream-wolfssl
+ VARIANT:=wolfssl
+ DEFAULT_VARIANT:=1
+endef
+Package/cache-domains-wolfssl/description = $(Package/cache-domains/description/default)
+Package/cache-domains-wolfssl/install = $(Package/cache-domains/install/default)
+
+$(eval $(call BuildPackage,cache-domains-openssl))
+$(eval $(call BuildPackage,cache-domains-mbedtls))
+$(eval $(call BuildPackage,cache-domains-wolfssl))
diff --git a/external/subpack/utils/cache-domains/README.md b/external/subpack/utils/cache-domains/README.md
new file mode 100644
index 0000000..ae525fc
--- /dev/null
+++ b/external/subpack/utils/cache-domains/README.md
@@ -0,0 +1,30 @@
+# cache-domains
+
+hotplug script to dynamically configure the local DNS (dnsmasq) to redirect game content servers to a LAN cache. Definitive list dynamically obtained from https://github.com/uklans/cache-domains.
+
+## Configuration
+The configuration file (`/etc/cache-domains.json`) follows the same [syntax as the upsteam file](https://github.com/uklans/cache-domains/blob/master/scripts/config.example.json). The key for each `cache_domains` member matches the name of one of the `.txt` files in the [upstream root directory](https://github.com/uklans/cache-domains/blob/master/), except for the `default` key which matches the all the unreferenced `.txt` files. The value of each `cache_domains` member maps to one of the keys of the `ips` members, Thus mapping a cached domain to a list of IP addresses/LAN cache server.
+
+```json
+{
+ "ips": {
+ "server1": ["10.10.3.10", "10.10.3.11"],
+ "server2": "10.10.3.12",
+ "server3": "10.10.3.13"
+ },
+ "cache_domains": {
+ "default": "server1",
+ "blizzard": "server1",
+ "origin": "server1",
+ "steam": "server2",
+ "wsus": "server3",
+ "xboxlive": "server3"
+ }
+}
+```
+
+## Configure/Cleanup
+`/usr/bin/cache-domains configure` will configure the local DNS (dnsmasq) to redirect the configured cache domains. `/usr/bin/cache-domains cleanup` will cleanup redirection. The hotplug script calls `/usr/bin/cache-domains configure` when the WAN interface is brought up.
+
+## Testing
+After configuring with the above example configuration, running `nslookup lancache.steamcontent.com` would return `10.10.3.12`
diff --git a/external/subpack/utils/cache-domains/files/30-cache-domains b/external/subpack/utils/cache-domains/files/30-cache-domains
new file mode 100644
index 0000000..60b7a56
--- /dev/null
+++ b/external/subpack/utils/cache-domains/files/30-cache-domains
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+. /lib/functions/network.sh
+network_find_wan WAN_IFACE
+
+if [ "${ACTION}" = "ifup" ] && [ "${INTERFACE}" = "${WAN_IFACE}" ] && [ ! -e /var/cache-domains/lancache.conf ]; then
+ for ATTEMPT in $(seq 1 3); do
+ if /usr/bin/cache-domains configure; then
+ break
+ else
+ sleep 30
+ fi
+ done
+fi
diff --git a/external/subpack/utils/cache-domains/files/cache-domains b/external/subpack/utils/cache-domains/files/cache-domains
new file mode 100644
index 0000000..585aef7
--- /dev/null
+++ b/external/subpack/utils/cache-domains/files/cache-domains
@@ -0,0 +1,83 @@
+#!/bin/sh
+
+. /lib/config/uci.sh
+
+set -e
+
+CACHE_DOMAINS_SRC="https://api.github.com/repos/uklans/cache-domains/tarball/master"
+CACHE_DOMAINS_DIR="/var/cache-domains"
+CACHE_DOMAINS_CONF_FILE="${CACHE_DOMAINS_DIR}/lancache.conf"
+CONFIG_FILE="/etc/cache-domains.json"
+
+dnsmasq_conf() {
+ local I=0
+ local DNSMASQ_CONF_DIR
+ local DNSMASQ_CONF_FILE
+
+ while uci_get "dhcp" "@dnsmasq[${I}]" > /dev/null; do
+ DNSMASQ_CONF_DIR="$(uci_get "dhcp" "@dnsmasq[${I}]" "confdir" "/tmp/dnsmasq.d" || :)"
+ DNSMASQ_CONF_FILE="${DNSMASQ_CONF_DIR}/$(basename "${CACHE_DOMAINS_CONF_FILE}")"
+
+ case ${1} in
+ add)
+ ln -sf "${CACHE_DOMAINS_CONF_FILE}" "${DNSMASQ_CONF_FILE}"
+ ;;
+ remove)
+ rm -f "${DNSMASQ_CONF_FILE}"
+ ;;
+ *)
+ echo "ERROR: Invalid action '${1}' for dnsmasq_conf()"
+ return 1
+ ;;
+ esac
+
+ I=$((${I} + 1))
+ done
+
+ /etc/init.d/dnsmasq "restart"
+}
+
+configure() {
+ local INITIAL_DIR
+ local SOURCE_DIR
+ mkdir -p "${CACHE_DOMAINS_DIR}"
+ rm -fr "${CACHE_DOMAINS_DIR:?}/"*
+
+ if ! wget -qO - "${CACHE_DOMAINS_SRC}" | tar -xzC "${CACHE_DOMAINS_DIR}"; then
+ rm -fr "${CACHE_DOMAINS_DIR}"
+ echo "ERROR: Could not retrieve ${CACHE_DOMAINS_SRC}"
+ exit 1
+ fi
+ SOURCE_DIR="${CACHE_DOMAINS_DIR}/$(ls "${CACHE_DOMAINS_DIR}")"
+
+ if [ ! -f "${CONFIG_FILE}" ]; then
+ cp "${SOURCE_DIR}/scripts/config.example.json" "${CONFIG_FILE}"
+ echo "Using example config file ${CONFIG_FILE}"
+ fi
+
+ INITIAL_DIR="$(pwd)"
+ cd "${SOURCE_DIR}/scripts/"
+ cp "${CONFIG_FILE}" "config.json"
+ ./create-dnsmasq.sh > /dev/null
+ cat "./output/dnsmasq/"*".conf" > "${CACHE_DOMAINS_CONF_FILE}"
+ cd "${INITIAL_DIR}"
+ rm -fr "${SOURCE_DIR}"
+
+ dnsmasq_conf add
+}
+
+cleanup() {
+ dnsmasq_conf remove
+}
+
+case ${1} in
+ config*)
+ configure
+ ;;
+ clean*)
+ cleanup
+ ;;
+ *)
+ echo "${0} <configure|cleanup>"
+ ;;
+esac
diff --git a/external/subpack/utils/canutils/Makefile b/external/subpack/utils/canutils/Makefile
new file mode 100644
index 0000000..9bb331d
--- /dev/null
+++ b/external/subpack/utils/canutils/Makefile
@@ -0,0 +1,77 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=canutils
+PKG_VERSION:=2020.11.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/linux-can/can-utils/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=b8e53081c076fca248c39ae9ae5791359a81f1eb3e5fe23ff6fb0d0e1f1033fa
+PKG_BUILD_DIR:=$(BUILD_DIR)/can-utils-$(PKG_VERSION)
+
+PKG_MAINTAINER:=Anton Glukhov <anton.a.glukhov@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/canutils/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ URL:=https://github.com/linux-can/can-utils
+ TITLE:=CAN userspace utilities and tools
+endef
+
+define Package/canutils
+ $(call Package/canutils/Default)
+ MENU:=1
+endef
+
+define GenPlugin
+ define Package/$(addprefix canutils-,$(1))
+ $(call Package/canutils/Default)
+ TITLE:=Utility $(1) from the CAN utilities
+ DEPENDS:=canutils
+ endef
+
+ define Package/$(addprefix canutils-,$(1))/description
+ Utility $(1) from the CAN utilities package.
+ endef
+endef
+
+FILES:= \
+ asc2log bcmserver canbusload can-calc-bit-timing \
+ candump canfdtest cangen cangw canlogserver canplayer \
+ cansend cansniffer isotpdump isotpperf isotprecv isotpsend \
+ isotpserver isotpsniffer isotptun j1939acd j1939cat j1939spy j1939sr \
+ log2asc log2long slcan_attach slcand slcanpty testj1939
+
+$(foreach a,$(FILES),$(eval $(call GenPlugin,$(a))))
+
+define PartInstall
+define Package/canutils-$(1)/install
+ $(INSTALL_DIR) $$(1)/usr/bin
+ $(INSTALL_BIN) \
+ $(PKG_INSTALL_DIR)/usr/bin/$(1) \
+ $$(1)/usr/bin/
+endef
+endef
+
+$(foreach file,$(FILES),$(eval $(call PartInstall,$(file))))
+
+define Package/canutils/install
+ true
+endef
+
+$(eval $(call BuildPackage,canutils))
+$(foreach file,$(FILES),$(eval $(call BuildPackage,canutils-$(file))))
diff --git a/external/subpack/utils/canutils/patches/010-time.patch b/external/subpack/utils/canutils/patches/010-time.patch
new file mode 100644
index 0000000..503f93e
--- /dev/null
+++ b/external/subpack/utils/canutils/patches/010-time.patch
@@ -0,0 +1,10 @@
+--- a/j1939cat.c
++++ b/j1939cat.c
+@@ -13,6 +13,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <time.h>
+ #include <unistd.h>
+
+ #include <linux/errqueue.h>
diff --git a/external/subpack/utils/ccid/Makefile b/external/subpack/utils/ccid/Makefile
new file mode 100644
index 0000000..7f47261
--- /dev/null
+++ b/external/subpack/utils/ccid/Makefile
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2009-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ccid
+PKG_VERSION:=1.5.0
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://ccid.apdu.fr/files/
+PKG_HASH:=81549b3422469d503996d03a3aed2ef1375b359167f10d66be9e3844e729322e
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+PKG_LICENSE:=LGPL-2.1-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_FIXUP:=libtool
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ccid
+ SECTION:=libs
+ CATEGORY:=Libraries
+ DEPENDS:=+libusb-1.0 +libpcsclite
+ TITLE:=Generic USB CCID smart card reader driver
+ URL:=https://ccid.apdu.fr/
+endef
+
+define Package/ccid/description
+ Generic USB CCID (Chip/Smart Card Interface Devices) driver and ICCD
+ (Integrated Circuit(s) Card Devices).
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+TARGET_LDFLAGS += "-lpthread"
+
+CONFIGURE_ARGS += \
+ --enable-embedded \
+ --enable-usbdropdir=/usr/lib/pcsc/drivers
+
+define Package/ccid/install
+ $(INSTALL_DIR) $(1)/usr/lib/pcsc
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pcsc/drivers $(1)/usr/lib/pcsc/
+endef
+
+$(eval $(call BuildPackage,ccid))
diff --git a/external/subpack/utils/ccid/patches/010-macos.patch b/external/subpack/utils/ccid/patches/010-macos.patch
new file mode 100644
index 0000000..0155cde
--- /dev/null
+++ b/external/subpack/utils/ccid/patches/010-macos.patch
@@ -0,0 +1,11 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -79,7 +79,7 @@ AC_CHECK_FUNCS(select strerror strncpy m
+ # Select OS specific versions of source files.
+ AC_SUBST(BUNDLE_HOST)
+ AC_SUBST(DYN_LIB_EXT)
+-BUNDLE_HOST=`uname | sed -e s,/,_,`
++BUNDLE_HOST=Linux
+ DYN_LIB_EXT="so"
+ case "$BUNDLE_HOST" in
+ Darwin)
diff --git a/external/subpack/utils/ccrypt/Makefile b/external/subpack/utils/ccrypt/Makefile
new file mode 100644
index 0000000..f720562
--- /dev/null
+++ b/external/subpack/utils/ccrypt/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2009-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ccrypt
+PKG_VERSION:=1.11
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/ccrypt
+PKG_HASH:=b19c47500a96ee5fbd820f704c912f6efcc42b638c0a6aa7a4e3dc0a6b51a44f
+PKG_MAINTAINER:=Hannu Nyman <hannu.nyman@iki.fi>
+PKG_LICENSE:=GPL-2.0-or-later
+
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ccrypt
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Encryption
+ TITLE:=utility for encrypting/decrypting files and streams
+ URL:=http://ccrypt.sourceforge.net/
+endef
+
+CONFIGURE_ARGS += --disable-emacs
+
+define Package/ccrypt/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ccrypt $(1)/usr/bin/
+ ln -s ccrypt $(1)/usr/bin/ccencrypt
+ ln -s ccrypt $(1)/usr/bin/ccdecrypt
+ ln -s ccrypt $(1)/usr/bin/ccat
+endef
+
+$(eval $(call BuildPackage,ccrypt))
diff --git a/external/subpack/utils/ccrypt/patches/001-no-intl.patch b/external/subpack/utils/ccrypt/patches/001-no-intl.patch
new file mode 100644
index 0000000..cac7ffb
--- /dev/null
+++ b/external/subpack/utils/ccrypt/patches/001-no-intl.patch
@@ -0,0 +1,89 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -4,7 +4,7 @@
+
+ ## Process this file with automake to produce Makefile.in
+
+-SUBDIRS = m4 po intl src emacs doc check
++SUBDIRS = m4 src emacs doc check
+
+ EXTRA_DIST = m4/ChangeLog config.rpath README-WIN
+
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -117,7 +117,7 @@ am__CONFIG_DISTCLEAN_FILES = config.stat
+ configure.lineno config.status.lineno
+ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+ CONFIG_HEADER = config.h
+-CONFIG_CLEAN_FILES = intl/Makefile
++CONFIG_CLEAN_FILES =
+ CONFIG_CLEAN_VPATH_FILES =
+ AM_V_P = $(am__v_P_@AM_V@)
+ am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+@@ -177,7 +177,7 @@ CTAGS = ctags
+ CSCOPE = cscope
+ DIST_SUBDIRS = $(SUBDIRS)
+ am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
+- $(top_srcdir)/intl/Makefile.in ABOUT-NLS AUTHORS COPYING \
++ ABOUT-NLS AUTHORS COPYING \
+ ChangeLog INSTALL NEWS README compile config.guess \
+ config.rpath config.sub install-sh ltmain.sh missing \
+ mkinstalldirs
+@@ -403,7 +403,7 @@ target_alias = @target_alias@
+ top_build_prefix = @top_build_prefix@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+-SUBDIRS = m4 po intl src emacs doc check
++SUBDIRS = m4 src emacs doc check
+ EXTRA_DIST = m4/ChangeLog config.rpath README-WIN
+ ACLOCAL_AMFLAGS = -I m4
+ all: config.h
+--- a/configure.ac
++++ b/configure.ac
+@@ -149,17 +149,6 @@ AC_MSG_RESULT($UINT32_TYPE)
+ AC_DEFINE_UNQUOTED(UINT32_TYPE,$UINT32_TYPE,unsigned 32 bit integer type)
+
+ dnl ----------------------------------------------------------------------
+-dnl Internationalization
+-
+-GETTEXT_PACKAGE=ccrypt
+-AC_SUBST(GETTEXT_PACKAGE)
+-AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Package name for gettext])
+-
+-AM_GNU_GETTEXT
+-AM_GNU_GETTEXT_VERSION([0.19.8])
+-dnl IT_PO_SUBDIR(po)
+-
+-dnl ----------------------------------------------------------------------
+ dnl Libtool (needed by intl/)
+
+ LT_INIT
+@@ -180,9 +169,7 @@ AC_SUBST(TAR)
+ dnl ----------------------------------------------------------------------
+ AC_CONFIG_FILES([doc/ccrypt.1
+ doc/ccguess.1
+- po/Makefile.in
+ m4/Makefile
+- intl/Makefile
+ Makefile
+ src/Makefile
+ emacs/Makefile
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -56,4 +56,4 @@ uninstall-local:
+ # internationalization stuff
+ localedir = $(datadir)/locale
+ AM_CPPFLAGS = @EXTRA_INCLUDES@ -I../intl -I$(top_srcdir)/intl -DLOCALEDIR=\"$(localedir)\"
+-LIBS = @LIBINTL@ @LIBS@
++LIBS = @LIBS@
+--- a/src/Makefile.in
++++ b/src/Makefile.in
+@@ -278,7 +278,7 @@ LIBMULTITHREAD = @LIBMULTITHREAD@
+ LIBOBJS = @LIBOBJS@
+ LIBPTH = @LIBPTH@
+ LIBPTH_PREFIX = @LIBPTH_PREFIX@
+-LIBS = @LIBINTL@ @LIBS@
++LIBS = @LIBS@
+ LIBTHREAD = @LIBTHREAD@
+ LIBTOOL = @LIBTOOL@
+ LIPO = @LIPO@
diff --git a/external/subpack/utils/cgroupfs-mount/Makefile b/external/subpack/utils/cgroupfs-mount/Makefile
new file mode 100644
index 0000000..40facab
--- /dev/null
+++ b/external/subpack/utils/cgroupfs-mount/Makefile
@@ -0,0 +1,47 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=cgroupfs-mount
+PKG_RELEASE:=2
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/tianon/$(PKG_NAME)
+PKG_SOURCE_VERSION:=0549428171605eae3097a3e21bf7664845eac9e8
+PKG_SOURCE_DATE:=2020-06-26
+PKG_MIRROR_HASH:=ca217ffff5aa938149d2d8adfe15d800903d2fec180acb2400c36d62905988ea
+
+PKG_MAINTAINER:=Gerard Ryan <G.M0N3Y.2503@gmail.com>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/cgroupfs-mount/config
+ config CGROUPFS_MOUNT_KERNEL_CGROUPS
+ bool "Enable kernel cgroups support"
+ depends on PACKAGE_cgroupfs-mount
+ default y if ( DOCKER_KERNEL_OPTIONS || LXC_KERNEL_OPTIONS )
+ select KERNEL_CGROUPS
+endef
+
+define Package/cgroupfs-mount
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=cgroup mount scripts
+ DEPENDS:=+mount-utils
+ MENU:=1
+endef
+
+define Package/cgroupfs-mount/description
+Simple scripts to properly mount the cgroupfs hierarchy, especially structured for Debian packaging
+endef
+
+Build/Compile=# Nothing to compile, just install the scripts
+
+define Package/cgroupfs-mount/install
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/cgroupfs-mount $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/cgroupfs-umount $(1)/usr/bin/
+
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/cgroupfs-mount.init $(1)/etc/init.d/cgroupfs-mount
+endef
+
+$(eval $(call BuildPackage,cgroupfs-mount))
diff --git a/external/subpack/utils/cgroupfs-mount/files/cgroupfs-mount.init b/external/subpack/utils/cgroupfs-mount/files/cgroupfs-mount.init
new file mode 100755
index 0000000..0d6b68d
--- /dev/null
+++ b/external/subpack/utils/cgroupfs-mount/files/cgroupfs-mount.init
@@ -0,0 +1,12 @@
+#!/bin/sh /etc/rc.common
+
+START=01
+
+boot() {
+ # Procd mounts non-hierarchical cgroupfs so unmount first before cgroupfs-mount
+ if mountpoint -q /sys/fs/cgroup; then
+ umount /sys/fs/cgroup/
+ fi
+
+ cgroupfs-mount
+}
diff --git a/external/subpack/utils/checksec/Makefile b/external/subpack/utils/checksec/Makefile
new file mode 100644
index 0000000..b6dc2ed
--- /dev/null
+++ b/external/subpack/utils/checksec/Makefile
@@ -0,0 +1,65 @@
+#
+# Copyright (C) 2020 CZ.NIC z.s.p.o. (https://www.nic.cz/)
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=checksec.sh
+PKG_VERSION:=2.7.1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/slimm609/checksec.sh/archive/$(PKG_VERSION)
+PKG_HASH:=94b7cd8f9b1fb63341abf166d66d1264aa5136f6fc0f72d28ff9f8af1fcf3c0b
+
+PKG_MAINTAINER:=Jan Pavlinec <jan.pavlinec@nic.cz>
+PKG_LICENSE_FILES:=LICENSE.txt
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/checksec/default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ URL:=https://github.com/slimm609/checksec.sh
+endef
+
+define Package/checksec
+ $(call Package/checksec/default)
+ TITLE:=Utility to check PIE, RELRO, ASLR etc.
+ DEPENDS:=+bash +file +binutils +procps-ng +procps-ng-sysctl +openssl-util +coreutils +coreutils-stat
+endef
+
+define Package/checksec_automator
+ $(call Package/checksec/default)
+ TITLE:=Utility to use checksec for dirs
+ DEPENDS:=+checksec +coreutils-tee +findutils-find +grep
+endef
+
+define Package/checksec/description
+ Checksec is a bash script to check the properties
+ of executables (like PIE, RELRO, PaX, Canaries, ASLR, Fortify Source).
+endef
+
+define Package/checksec_automator/description
+ Script for checksec directory scan.
+endef
+
+Build/Compile:=:
+Build/Install:=:
+
+define Package/checksec/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/checksec $(1)/usr/bin/
+endef
+
+define Package/checksec_automator/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/checksec_automator.sh $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,checksec))
+$(eval $(call BuildPackage,checksec_automator))
diff --git a/external/subpack/utils/cmdpad/Makefile b/external/subpack/utils/cmdpad/Makefile
new file mode 100644
index 0000000..aa34f31
--- /dev/null
+++ b/external/subpack/utils/cmdpad/Makefile
@@ -0,0 +1,61 @@
+#
+# Copyright (C) 2007-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=cmdpad
+PKG_VERSION:=0.0.3
+PKG_RELEASE:=5
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tgz
+PKG_SOURCE_URL:=@SF/cmdpad
+PKG_HASH:=19963f20f1af50fab0013fb373af294ea412da7241d1ea91fad90455291948b9
+
+PKG_MAINTAINER:=Ted Hess <thess@kitschensync.net>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=doc/COPYING
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/cmdpad
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=execute commands when key is pressed/released/held down
+ URL:=http://cmdpad.sourceforge.net/index.php
+endef
+
+CONFIGURE_ARGS += \
+ --enable-static \
+ --enable-shared
+
+define Package/cmdpad/description
+ cmdpad - execute commands when a key is pressed, released or hold down.
+ Should be started from /etc/rc or /etc/rc.local. To run it as daemon you
+ need to start it with '&'. All logs are printed to standard out and standard
+ error (to write the log to disk use cmdpad > /var/log/cmdpad). Cmdpad
+ searches for /etc/cmdpad.conf and load the key bindings. Then wait for
+ key event and check each command to see if it should be run.
+endef
+
+MAKE_FLAGS += \
+ $(TARGET_CONFIGURE_OPTS) \
+ $(1)
+
+define Package/cmdpad/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/cmdpad $(1)/usr/sbin/
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/src/cmdpad.conf $(1)/etc/
+ $(INSTALL_BIN) ./files/cmdpad.init $(1)/etc/init.d/cmdpad
+endef
+
+define Package/cmdpad/conffiles
+/etc/cmdpad.conf
+endef
+
+$(eval $(call BuildPackage,cmdpad))
diff --git a/external/subpack/utils/cmdpad/files/cmdpad.init b/external/subpack/utils/cmdpad/files/cmdpad.init
new file mode 100644
index 0000000..f612033
--- /dev/null
+++ b/external/subpack/utils/cmdpad/files/cmdpad.init
@@ -0,0 +1,14 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2007-2011 OpenWrt.org
+
+START=93
+
+SSD_DAEMONIZE=1
+
+start() {
+ service_start /usr/sbin/cmdpad --quiet
+}
+
+stop() {
+ service_stop /usr/sbin/cmdpad
+}
diff --git a/external/subpack/utils/cmdpad/patches/100-Makefile.patch b/external/subpack/utils/cmdpad/patches/100-Makefile.patch
new file mode 100644
index 0000000..6ebe1b8
--- /dev/null
+++ b/external/subpack/utils/cmdpad/patches/100-Makefile.patch
@@ -0,0 +1,35 @@
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -5,25 +5,25 @@
+ TOP=..
+ include $(TOP)/Makefile.common
+
+-INCLUDE= -I/usr/include
+-LIBS= -L/usr/lib -lc
+-CFLAGS= -g3
+-LDFLAGS= -Xlinker -Map -Xlinker $(PROG).map #,--stack,16Mb
++#INCLUDE= -I/usr/include
++#LIBS= -L/usr/lib -lc
++#CFLAGS= -g3
++#LDFLAGS= -Xlinker -Map -Xlinker $(PROG).map #,--stack,16Mb
+ OBJ= main.o command.o parse.o
+ SCRIPTS= *.sh
+
+ build: $(PROG)
+
+ $(PROG): $(OBJ)
+- gcc -o $(PROG) $(OBJ) $(LIBS) $(LDFLAGS)
++ $(GCC) -o $(PROG) $(OBJ) $(LIBS) $(LDFLAGS)
+ @echo "==============================================="
+ @echo "edit $(PROG).conf file to set default preferences"
+
+ %.o : %.c
+- gcc $(CFLAGS) -D__COPYLEFT__='$(COPYLEFT)' -c $<
++ $(GCC) $(CFLAGS) -D__COPYLEFT__='$(COPYLEFT)' -c $<
+
+ %.o : %.c %.h
+- gcc $(CFLAGS) -D__COPYLEFT__='$(COPYLEFT)' -c $<
++ $(GCC) $(CFLAGS) -D__COPYLEFT__='$(COPYLEFT)' -c $<
+
+ distclean clean:
+ rm $(PROG) *~ *.o -vf
diff --git a/external/subpack/utils/cmdpad/patches/120-kernel26-compat.patch b/external/subpack/utils/cmdpad/patches/120-kernel26-compat.patch
new file mode 100644
index 0000000..6a9813e
--- /dev/null
+++ b/external/subpack/utils/cmdpad/patches/120-kernel26-compat.patch
@@ -0,0 +1,15 @@
+--- a/src/parse.c
++++ b/src/parse.c
+@@ -289,6 +289,12 @@ int ParseCommand( char * pchCommandLine)
+ pchEventDevice = strdup( pchValue) ;
+ return 1 ;
+ }
++ if( (pchValue != NULL) &&
++ (strncmp( pchValue, "/dev/event", 6) == 0) )
++ {
++ pchEventDevice = strdup( pchValue) ;
++ return 1 ;
++ }
+ printf( "Option 'device' expects a /dev/input/eventX argument\n");
+ return -1 ;
+ }
diff --git a/external/subpack/utils/cmdpad/patches/130-no_zombie.patch b/external/subpack/utils/cmdpad/patches/130-no_zombie.patch
new file mode 100644
index 0000000..e359a1b
--- /dev/null
+++ b/external/subpack/utils/cmdpad/patches/130-no_zombie.patch
@@ -0,0 +1,18 @@
+--- a/src/command.c
++++ b/src/command.c
+@@ -68,6 +68,7 @@ struct CMD * cmd = NULL ;
+
+ void exec( char * command)
+ {
++ int status;
+ if( fork() == 0) {
+ char ** tmp ;
+ int i ;
+@@ -88,6 +89,7 @@ void exec( char * command)
+ perror( "ERROR: execv") ;
+ exit( 1) ;
+ } // end if( fork())
++ wait(&status);
+ }
+
+ int getNumberofEntry()
diff --git a/external/subpack/utils/cmdpad/patches/140-compile_fix.patch b/external/subpack/utils/cmdpad/patches/140-compile_fix.patch
new file mode 100644
index 0000000..c7a9bb3
--- /dev/null
+++ b/external/subpack/utils/cmdpad/patches/140-compile_fix.patch
@@ -0,0 +1,11 @@
+--- a/src/parse.c
++++ b/src/parse.c
+@@ -125,7 +125,7 @@ int readCommandLine( int argc, char *arg
+
+ d2printf( "command line command %s found\n", pchCommandTranslations[ iCmd+1]) ;
+
+- vsnprintf( achCommand, sizeof( achCommand),
++ snprintf( achCommand, sizeof( achCommand),
+ pchCommandTranslations[ iCmd+1],
+ &argv[ i+1]) ;
+
diff --git a/external/subpack/utils/cmdpad/patches/150-header.patch b/external/subpack/utils/cmdpad/patches/150-header.patch
new file mode 100644
index 0000000..2b4c3aa
--- /dev/null
+++ b/external/subpack/utils/cmdpad/patches/150-header.patch
@@ -0,0 +1,49 @@
+--- a/src/command.c
++++ b/src/command.c
+@@ -43,6 +43,7 @@
+
+ #include <linux/input.h>
+ #include <linux/ioctl.h>
++#include <sys/wait.h>
+ #include <stdlib.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+--- a/src/main.c
++++ b/src/main.c
+@@ -54,6 +54,7 @@
+
+ #include "debug.h"
+ #include "command.h"
++#include "parse.h"
+
+ #define DEBUGNAME "MAIN: "
+
+--- a/src/parse.c
++++ b/src/parse.c
+@@ -58,7 +58,7 @@
+ extern char * pchProgramName ;
+ extern char * pchEventDevice ;
+
+-inline void ltrim( char * pchText)
++static void ltrim( char * pchText)
+ {
+ if( pchText) {
+ char * pchTxt = pchText ;
+@@ -67,7 +67,7 @@ inline void ltrim( char * pchText)
+ }
+ }
+
+-inline void rtrim( char * pchText)
++static void rtrim( char * pchText)
+ {
+ if( pchText)
+ {
+@@ -77,7 +77,7 @@ inline void rtrim( char * pchText)
+ }
+ }
+
+-inline void trim( char * pchText)
++static void trim( char * pchText)
+ {
+ ltrim( pchText) ;
+ rtrim( pchText) ;
diff --git a/external/subpack/utils/cni-plugins/Makefile b/external/subpack/utils/cni-plugins/Makefile
new file mode 100644
index 0000000..3c6336f
--- /dev/null
+++ b/external/subpack/utils/cni-plugins/Makefile
@@ -0,0 +1,49 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=cni-plugins
+PKG_VERSION:=1.0.1
+PKG_RELEASE:=$(AUTORELEASE)
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/containernetworking/plugins/archive/v$(PKG_VERSION)
+PKG_HASH:=2ba3cd9f341a7190885b60d363f6f23c6d20d975a7a0ab579dd516f8c6117619
+
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>, Paul Spooren <mail@aparcar.org>
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/containernetworking/plugins/
+GO_PKG_BUILD_PKG:=github.com/containernetworking/plugins/plugins/main/... \
+ github.com/containernetworking/plugins/plugins/meta/... \
+ github.com/containernetworking/plugins/plugins/ipam/...
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+PKG_UNPACK:=$(HOST_TAR) -C "$(PKG_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(PKG_SOURCE)"
+
+define Package/cni-plugins
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=cni-plugins
+ URL:=https://github.com/containernetworking/cni-plugins
+ DEPENDS:=$(GO_ARCH_DEPENDS) +ip-full +kmod-veth
+endef
+
+define Package/cni-plugins/description
+ Some CNI network plugins, maintained by the containernetworking team. For
+ more information, see the individual READMEs.
+endef
+
+define Package/cni-plugins/install
+ $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
+ $(INSTALL_DIR) $(1)/usr/lib/cni
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/lib/cni
+endef
+
+$(eval $(call GoBinPackage,cni-plugins))
+$(eval $(call BuildPackage,cni-plugins))
diff --git a/external/subpack/utils/cni/Makefile b/external/subpack/utils/cni/Makefile
new file mode 100644
index 0000000..129ec5e
--- /dev/null
+++ b/external/subpack/utils/cni/Makefile
@@ -0,0 +1,51 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=cni
+PKG_VERSION:=1.0.1
+PKG_RELEASE:=$(AUTORELEASE)
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/containernetworking/$(PKG_NAME)/archive/v$(PKG_VERSION)
+PKG_HASH:=0e5376f70fb36c26935ddfb90b0da69736592ba8b577fbfb904750034c053d3b
+
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>, Paul Spooren <mail@aparcar.org>, Oskari Rauta <oskari.rauta@gmail.com>
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/containernetworking/cni/
+GO_PKG_BUILD_PKG:=github.com/containernetworking/cni/cnitool
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+PKG_USE_MIPS16:=0
+GO_PKG_BUILD_VARS += GO111MODULE=auto
+
+define Package/cni
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=cni
+ URL:=https://github.com/containernetworking/cni
+ DEPENDS:=$(GO_ARCH_DEPENDS)
+endef
+
+define Package/cni/description
+ CNI (Container Network Interface), a Cloud Native Computing Foundation
+ project, consists of a specification and libraries for writing plugins to
+ configure network interfaces in Linux containers, along with a number of
+ supported plugins. CNI concerns itself only with network connectivity of
+ containers and removing allocated resources when the container is deleted.
+ Because of this focus, CNI has a wide range of support and the specification
+ is simple to implement.
+endef
+
+define Package/cni/install
+ $(call GoPackage/Package/Install/Bin,$(1))
+endef
+
+$(eval $(call GoBinPackage,cni))
+$(eval $(call BuildPackage,cni))
diff --git a/external/subpack/utils/collectd/Makefile b/external/subpack/utils/collectd/Makefile
new file mode 100644
index 0000000..dfe3edf
--- /dev/null
+++ b/external/subpack/utils/collectd/Makefile
@@ -0,0 +1,505 @@
+#
+# Copyright (C) 2006-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=collectd
+PKG_VERSION:=5.12.0
+PKG_RELEASE:=10
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://collectd.org/files/ \
+ https://github.com/collectd/collectd/releases/download/collectd-$(PKG_VERSION)
+PKG_HASH:=5bae043042c19c31f77eb8464e56a01a5454e0b39fa07cf7ad0f1bfc9c3a09d6
+
+PKG_FIXUP:=autoreconf
+PKG_REMOVE_FILES:=aclocal.m4 libltdl/aclocal.m4
+PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>, Hannu Nyman <hannu.nyman@iki.fi>
+PKG_CPE_ID:=cpe:/a:collectd:collectd
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+PKG_CONFIG_DEPENDS:= \
+ PACKAGE_COLLECTD_ENCRYPTED_NETWORK \
+ PACKAGE_COLLECTD_DEBUG_OUTPUT_ENABLE
+
+COLLECTD_PLUGINS_DISABLED:= \
+ amqp \
+ ampq1 \
+ apple_sensors \
+ aquaero \
+ barometer \
+ battery \
+ buddyinfo \
+ capabilities \
+ ceph \
+ cgroups \
+ cpusleep \
+ curl_jolokia \
+ curl_json \
+ curl_xml \
+ dbi \
+ dcpmm \
+ dpdkevents \
+ dpdkstat \
+ dpdk_telemetry \
+ drbd \
+ fhcount \
+ genericjmx \
+ gmond \
+ gps \
+ gpu_nvidia \
+ grpc \
+ hddtemp \
+ hugepages \
+ infiniband \
+ intel_pmu \
+ intel_rdt \
+ ipc \
+ ipmi \
+ ipstats \
+ ipvs \
+ java \
+ logparser \
+ log_logstash \
+ lvm \
+ lpar \
+ madwifi \
+ mbmon \
+ mcelog \
+ md \
+ mdevents \
+ memcachec \
+ memcached \
+ mic \
+ monitorus \
+ multimeter \
+ netapp \
+ netstat_udp \
+ nfs \
+ notify_desktop \
+ notify_email \
+ notify_nagios \
+ numa \
+ onewire \
+ openldap \
+ openvz \
+ oracle \
+ ovs_events \
+ ovs_stats \
+ pcie_errors \
+ perl \
+ pf \
+ pinba \
+ procevent \
+ python \
+ redfish \
+ redis \
+ rrdcached \
+ serial \
+ sigrok \
+ slurm \
+ snmp_agent \
+ statsd \
+ synproxy \
+ sysevent \
+ tape \
+ tokyotyrant \
+ turbostat \
+ uuid \
+ varnish \
+ virt \
+ vserver \
+ write_influxdb_udp \
+ write_kafka \
+ write_log \
+ write_mongodb \
+ write_prometheus \
+ write_redis \
+ write_riemann \
+ write_sensu \
+ write_stackdriver \
+ write_syslog \
+ write_tsdb \
+ xencpu \
+ xmms \
+ zfs_arc \
+ zone \
+ zookeeper
+
+COLLECTD_PLUGINS_SELECTED:= \
+ apache \
+ apcups \
+ ascent \
+ bind \
+ chrony \
+ conntrack \
+ contextswitch \
+ cpu \
+ cpufreq \
+ csv \
+ curl \
+ df \
+ dhcpleases \
+ disk \
+ dns \
+ email \
+ entropy \
+ ethstat \
+ exec \
+ filecount \
+ fscache \
+ interface \
+ ipstatistics \
+ iptables \
+ irq \
+ iwinfo \
+ load \
+ logfile \
+ lua \
+ match_empty_counter \
+ match_hashed \
+ match_regex \
+ match_timediff \
+ match_value \
+ memory \
+ modbus \
+ mqtt \
+ mysql \
+ netlink \
+ network \
+ nginx \
+ ntpd \
+ nut \
+ olsrd \
+ openvpn \
+ ping \
+ postgresql \
+ powerdns \
+ processes \
+ protocols \
+ routeros \
+ rrdtool \
+ sensors \
+ smart \
+ snmp \
+ snmp6 \
+ swap \
+ syslog \
+ table \
+ tail \
+ tail_csv \
+ tcpconns \
+ teamspeak2 \
+ ted \
+ thermal \
+ threshold \
+ ubi \
+ unixsock \
+ uptime \
+ users \
+ vmem \
+ wireless \
+ write_graphite \
+ write_http
+
+PKG_CONFIG_DEPENDS:= \
+ $(patsubst %,CONFIG_PACKAGE_collectd-mod-%,$(subst _,-,$(COLLECTD_PLUGINS_SELECTED))) \
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/kernel.mk
+# collectd-mod-mysql needs iconv
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/collectd/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Lightweight system statistics collection daemon
+ URL:=https://collectd.org/
+endef
+
+define Package/collectd
+$(call Package/collectd/Default)
+ DEPENDS:= +libpthread \
+ +zlib \
+ +libltdl \
+ +libip4tc \
+ +jshn \
+ +PACKAGE_collectd-mod-lua:liblua
+ MENU:=1
+endef
+
+define Package/collectd/description
+ collectd is a small daemon which collects system information periodically
+ and provides mechanismns to store the values in a variety of ways.
+endef
+
+define Package/collectd/config
+ config PACKAGE_COLLECTD_ENCRYPTED_NETWORK
+ bool "Enable ability to use encrypted networking"
+ default n
+ depends on PACKAGE_collectd
+ select PACKAGE_collectd-mod-network
+
+ config PACKAGE_COLLECTD_DEBUG_OUTPUT_ENABLE
+ bool "Enable debug output"
+ default n
+ depends on PACKAGE_collectd
+ help
+ Enables the compiler option that collectd is compiled with
+ debugging support. This is used at development stages to get
+ more messages from the collectd during development.
+endef
+
+# common configure args
+CONFIGURE_ARGS+= \
+ --disable-werror \
+ --enable-daemon \
+ --with-nan-emulation \
+ --with-libyajl=no \
+ --without-perl-bindings
+
+CONFIGURE_VARS+= \
+ CFLAGS="$$$$CFLAGS $(FPIC)" \
+ LDFLAGS="$$$$LDFLAGS -lm -lz" \
+ KERNEL_DIR="$(LINUX_DIR)"
+
+ifneq ($(CONFIG_PACKAGE_collectd-mod-lua),)
+CONFIGURE_VARS+= \
+ LDFLAGS="$$$$LDFLAGS -llua"
+endif
+
+ifneq ($(CONFIG_PACKAGE_COLLECTD_ENCRYPTED_NETWORK),)
+CONFIGURE_ARGS+= \
+ --with-libgcrypt=$(STAGING_DIR)/usr
+CONFIGURE_VARS+= \
+ GCRYPT_LIBS="-lgcrypt"
+else
+CONFIGURE_ARGS+= \
+ --without-libgcrypt
+endif
+
+ifeq ($(CONFIG_PACKAGE_COLLECTD_DEBUG_OUTPUT_ENABLE),y)
+CONFIGURE_ARGS+= \
+ --enable-debug
+else
+CONFIGURE_ARGS+= \
+ --disable-debug
+endif
+
+CONFIGURE_PLUGIN= \
+ $(foreach m, $(1), \
+ $(if $(CONFIG_PACKAGE_collectd-mod-$(subst _,-,$(m))),--enable-$(m),--disable-$(m)) \
+ )
+
+CONFIGURE_ARGS+= \
+ $(call CONFIGURE_PLUGIN,$(COLLECTD_PLUGINS_SELECTED)) \
+ $(call CONFIGURE_PLUGIN,$(COLLECTD_PLUGINS_DISABLED)) \
+
+# exception: mod-ascent needs libxml2
+ifneq ($(CONFIG_PACKAGE_collectd-mod-ascent),)
+ CONFIGURE_VARS+= \
+ CPPFLAGS="$$$$CPPFLAGS -I$(STAGING_DIR)/usr/include/libxml2"
+endif
+
+ifneq ($(CONFIG_BIG_ENDIAN),)
+ CONFIGURE_ARGS+= --with-fp-layout=endianflip
+else
+ CONFIGURE_ARGS+= --with-fp-layout=nothing
+endif
+
+ifneq ($(CONFIG_PACKAGE_collectd-mod-postgresql),)
+ CONFIGURE_ARGS+= --with-libpq="$(STAGING_DIR)/usr/"
+endif
+
+ifneq ($(CONFIG_PACKAGE_collectd-mod-mysql),)
+ CONFIGURE_ARGS+= --with-libmysql="$(STAGING_DIR)/usr/"
+endif
+
+# exception: mod-netlink needs libnetlink from iproute
+ifneq ($(CONFIG_PACKAGE_collectd-mod-netlink),)
+ CONFIGURE_ARGS+= --with-libnetlink="$(STAGING_DIR)/usr"
+endif
+
+# exception: mod-modbus needs libmodbus
+ifneq ($(CONFIG_PACKAGE_collectd-mod-modbus),)
+ CONFIGURE_ARGS+= --with-libmodbus="$(STAGING_DIR)/usr"
+endif
+
+# exception: mod-rrdtool needs rrdtool-1.0.x
+ifneq ($(CONFIG_PACKAGE_collectd-mod-rrdtool),)
+ CONFIGURE_ARGS+= --with-librrd="$(STAGING_DIR)/usr/lib/rrdtool-1.0"
+endif
+
+# exception: mod-smart needs libatasmart
+ifneq ($(CONFIG_PACKAGE_collectd-mod-smart),)
+ CONFIGURE_ARGS+= \
+ --with-libatasmart="$(STAGING_DIR)/usr" \
+ --with-libudev="$(STAGING_DIR)/usr"
+else
+ CONFIGURE_ARGS+= --without-libudev
+endif
+
+define Package/collectd/conffiles
+/etc/collectd.conf
+/etc/config/collectd
+endef
+
+define Package/collectd/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/collectd $(1)/usr/sbin/
+
+ $(INSTALL_DIR) $(1)/usr/share/collectd
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/collectd/types.db $(1)/usr/share/collectd/
+
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/collectd.init $(1)/etc/init.d/collectd
+
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) files/collectd.uci $(1)/etc/config/collectd
+endef
+
+# 1: plugin name
+# 2: plugin title/description
+# 3: files
+# 4: extra dependency
+define BuildPlugin
+
+ PKG_CONFIG_DEPENDS+= CONFIG_PACKAGE_collectd-mod-$(1)
+
+ define Package/collectd-mod-$(1)
+ $$(call Package/collectd/Default)
+ TITLE:=$(2) plugin
+ DEPENDS:= collectd $(4)
+ endef
+
+ define Package/collectd-mod-$(1)/install
+ $(INSTALL_DIR) $$(1)/usr/lib/collectd
+ for m in $(3); do \
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/lib/collectd/$$$$$$$${m}.so \
+ $$(1)/usr/lib/collectd/ ; \
+ done
+ if [ -f ./files/usr/share/collectd/plugin/$(1).json ]; then \
+ $(INSTALL_DIR) $$(1)/usr/share/collectd/plugin ; \
+ $(INSTALL_DATA) ./files/usr/share/collectd/plugin/$(1).json \
+ $$(1)/usr/share/collectd/plugin/$(1).json ; \
+ fi
+ endef
+
+ $$(eval $$(call BuildPackage,collectd-mod-$(1)))
+
+endef
+
+define BuildScriptPlugin
+ PKG_CONFIG_DEPENDS+= CONFIG_PACKAGE_collectd-mod-$(1)
+
+ define Package/collectd-mod-$(1)
+ $$(call Package/collectd/Default)
+ TITLE:=$(2) plugin
+ DEPENDS:= $(4)
+ endef
+
+ define Package/collectd-mod-$(1)/install
+ $(INSTALL_DIR) $$(1)/usr/libexec/collectd
+ for m in $(3); do \
+ ${INSTALL_BIN} \
+ ./files/exec-scripts/$$$$$$$${m}.sh $$(1)/usr/libexec/collectd/ ; \
+ done
+ if [ -f ./files/usr/share/collectd/plugin/$(1).json ]; then \
+ $(INSTALL_DIR) $$(1)/usr/share/collectd/plugin ; \
+ $(INSTALL_DATA) ./files/usr/share/collectd/plugin/$(1).json \
+ $$(1)/usr/share/collectd/plugin/$(1).json ; \
+ fi
+ endef
+
+ $$(eval $$(call BuildPackage,collectd-mod-$(1)))
+
+endef
+
+$(eval $(call BuildPackage,collectd))
+
+#$(eval $(call BuildPlugin,NAME,DESCRIPTION,FILES,DEPENDENCIES))
+$(eval $(call BuildPlugin,apache,apache status input,apache,+PACKAGE_collectd-mod-apache:libcurl))
+$(eval $(call BuildPlugin,apcups,apcups status input,apcups,))
+$(eval $(call BuildPlugin,ascent,ascent status input,ascent,+PACKAGE_collectd-mod-ascent:libcurl +PACKAGE_collectd-mod-ascent:libxml2))
+$(eval $(call BuildPlugin,bind,BIND server/zone input,bind,+PACKAGE_collectd-mod-bind:libcurl +PACKAGE_collectd-mod-bind:libxml2))
+$(eval $(call BuildPlugin,chrony,chrony status input,chrony,))
+$(eval $(call BuildPlugin,conntrack,connection tracking table size input,conntrack,))
+$(eval $(call BuildPlugin,contextswitch,context switch input,contextswitch,))
+$(eval $(call BuildPlugin,cpu,CPU input,cpu,))
+$(eval $(call BuildPlugin,cpufreq,CPU Freq input,cpufreq,@(TARGET_x86||TARGET_x86_64||TARGET_mvebu||TARGET_ipq806x||TARGET_armvirt||TARGET_ipq40xx||TARGET_bcm27xx_bcm2709||TARGET_rockchip))) # Only enable on targets with CPUs supporting frequency scaling
+$(eval $(call BuildPlugin,csv,CSV output,csv,))
+$(eval $(call BuildPlugin,curl,cURL input,curl,+PACKAGE_collectd-mod-curl:libcurl))
+#$(eval $(call BuildPlugin,dbi,relational database input,dbi,+PACKAGE_collectd-mod-dbi:libdbi))
+$(eval $(call BuildPlugin,df,disk space input,df,))
+$(eval $(call BuildPlugin,dhcpleases,show dhcpleases,dhcpleases,))
+$(eval $(call BuildPlugin,disk,disk usage/timing input,disk,+PACKAGE_collectd-mod-smart:libudev))
+$(eval $(call BuildPlugin,dns,DNS traffic input,dns,+PACKAGE_collectd-mod-dns:libpcap))
+$(eval $(call BuildPlugin,email,email output,email,))
+$(eval $(call BuildPlugin,entropy,Entropy amount input,entropy,))
+$(eval $(call BuildPlugin,ethstat,Ethernet adapter statistics input,ethstat,))
+$(eval $(call BuildPlugin,exec,process exec input,exec,))
+$(eval $(call BuildPlugin,filecount,file count input,filecount,))
+$(eval $(call BuildPlugin,fscache,file-system based caching framework input,fscache,))
+$(eval $(call BuildPlugin,interface,network interfaces input,interface,))
+$(eval $(call BuildPlugin,ipstatistics,ipstatistics input,ipstatistics,))
+$(eval $(call BuildPlugin,iptables,iptables status input,iptables,+PACKAGE_collectd-mod-iptables:iptables +libip4tc +libip6tc))
+$(eval $(call BuildPlugin,irq,interrupt usage input,irq,))
+$(eval $(call BuildPlugin,iwinfo,libiwinfo wireless statistics,iwinfo,+PACKAGE_collectd-mod-iwinfo:libiwinfo))
+$(eval $(call BuildPlugin,load,system load input,load,))
+$(eval $(call BuildPlugin,logfile,log files output,logfile,))
+$(eval $(call BuildPlugin,lua,lua input/output,lua,+PACKAGE_collectd-mod-lua:liblua))
+$(eval $(call BuildPlugin,match-empty-counter,empty-counter match,match_empty_counter,))
+$(eval $(call BuildPlugin,match-hashed,hashed match,match_hashed,))
+$(eval $(call BuildPlugin,match-regex,regex match,match_regex,))
+$(eval $(call BuildPlugin,match-timediff,timediff match,match_timediff,))
+$(eval $(call BuildPlugin,match-value,value match,match_value,))
+$(eval $(call BuildPlugin,mysql,MySQL status input,mysql,+PACKAGE_collectd-mod-mysql:libmysqlclient-r))
+$(eval $(call BuildPlugin,memory,physical memory usage input,memory,))
+$(eval $(call BuildPlugin,modbus,read variables through libmodbus,modbus,+PACKAGE_collectd-mod-modbus:libmodbus))
+$(eval $(call BuildPlugin,mqtt,transmit data with MQTT,mqtt,+PACKAGE_collectd-mod-mqtt:libmosquitto))
+$(eval $(call BuildPlugin,netlink,netlink input,netlink,+PACKAGE_collectd-mod-netlink:libmnl))
+$(eval $(call BuildPlugin,network,network input/output,network,+PACKAGE_COLLECTD_ENCRYPTED_NETWORK:libgcrypt))
+$(eval $(call BuildPlugin,nginx,nginx status input,nginx,+PACKAGE_collectd-mod-nginx:libcurl))
+$(eval $(call BuildPlugin,ntpd,NTP daemon status input,ntpd,))
+$(eval $(call BuildPlugin,nut,UPS monitoring input,nut,+PACKAGE_collectd-mod-nut:nut-common))
+$(eval $(call BuildPlugin,olsrd,OLSRd status input,olsrd,))
+$(eval $(call BuildPlugin,openvpn,OpenVPN traffic/compression input,openvpn,))
+$(eval $(call BuildPlugin,ping,ping status input,ping,+PACKAGE_collectd-mod-ping:liboping))
+$(eval $(call BuildPlugin,postgresql,PostgreSQL status input,postgresql,+PACKAGE_collectd-mod-postgresql:libpq))
+$(eval $(call BuildPlugin,powerdns,PowerDNS server status input,powerdns,))
+$(eval $(call BuildPlugin,processes,process status input,processes,+PACKAGE_collectd-mod-processes:libmnl))
+$(eval $(call BuildPlugin,protocols,network protocols input,protocols,))
+$(eval $(call BuildPlugin,routeros,MikroTik RouterOS input,routeros,+PACKAGE_collectd-mod-routeros:librouteros))
+$(eval $(call BuildPlugin,rrdtool,RRDtool output,rrdtool,+PACKAGE_collectd-mod-rrdtool:librrd1))
+$(eval $(call BuildPlugin,sensors,lm_sensors input,sensors,+PACKAGE_collectd-mod-sensors:lm-sensors))
+$(eval $(call BuildPlugin,smart,smart input,smart,+PACKAGE_collectd-mod-smart:libatasmart))
+$(eval $(call BuildPlugin,snmp,SNMP input,snmp,+PACKAGE_collectd-mod-snmp:libnetsnmp))
+$(eval $(call BuildPlugin,snmp6,snmp6 input,snmp6,))
+$(eval $(call BuildPlugin,swap,swap input,swap,))
+$(eval $(call BuildPlugin,syslog,syslog output,syslog,))
+$(eval $(call BuildPlugin,tail,tail input,tail,))
+$(eval $(call BuildPlugin,tail-csv,tail CSV input,tail_csv,))
+$(eval $(call BuildPlugin,table,table-like structured file input,table,))
+$(eval $(call BuildPlugin,teamspeak2,TeamSpeak2 input,teamspeak2,))
+$(eval $(call BuildPlugin,ted,The Energy Detective input,ted,))
+$(eval $(call BuildPlugin,tcpconns,TCP connection tracking input,tcpconns,))
+$(eval $(call BuildPlugin,thermal,system temperatures input,thermal,))
+$(eval $(call BuildPlugin,threshold,Notifications and thresholds,threshold,))
+$(eval $(call BuildPlugin,ubi,Unsorted block images,ubi,@NAND_SUPPORT))
+$(eval $(call BuildPlugin,unixsock,unix socket output,unixsock,))
+$(eval $(call BuildPlugin,uptime,uptime status input,uptime,))
+$(eval $(call BuildPlugin,users,user logged in status input,users,))
+$(eval $(call BuildPlugin,vmem,virtual memory usage input,vmem,))
+$(eval $(call BuildPlugin,wireless,wireless status input,wireless,))
+$(eval $(call BuildPlugin,write-graphite,Carbon/Graphite output,write_graphite,+PACKAGE_collectd-mod-write-graphite:libpthread))
+$(eval $(call BuildPlugin,write-http,HTTP POST output,write_http,+PACKAGE_collectd-mod-write-http:libcurl))
+
+$(eval $(call BuildScriptPlugin,sqm,SQM/qdisc collection,sqm_collectd,+PACKAGE_collectd-mod-sqm:collectd-mod-exec))
diff --git a/external/subpack/utils/collectd/files/collectd.init b/external/subpack/utils/collectd/files/collectd.init
new file mode 100644
index 0000000..b8c0f36
--- /dev/null
+++ b/external/subpack/utils/collectd/files/collectd.init
@@ -0,0 +1,378 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006-2016 OpenWrt.org
+
+START=80
+STOP=10
+
+USE_PROCD=1
+COLLECTD_CONF="/tmp/collectd.conf"
+LOG="logger -t collectd[$$] -p"
+NICEPRIO=5
+
+CONFIG_STRING=""
+
+[ -d /usr/libexec/collectd ] && {
+ find /usr/libexec/collectd ! -perm 0500 -exec chmod 0500 '{}' '+'
+ find /usr/libexec/collectd ! \( -user nobody -a -group nogroup \) -exec chown nobody:nogroup '{}' '+'
+}
+
+process_exec() {
+ printf "<Plugin exec>\n" >> "$COLLECTD_CONF"
+ config_foreach process_exec_sections exec_input "Exec"
+ config_foreach process_exec_sections exec_notify "NotificationExec"
+ printf "</Plugin>\n\n" >> "$COLLECTD_CONF"
+}
+
+process_exec_sections() {
+ local cfg="$1"
+ local section="$2"
+
+ local cmdline cmduser cmdgroup
+
+ config_get cmdline "$cfg" cmdline
+ [ -z "$cmdline" ] && {
+ $LOG notice "No cmdline option in config $cfg defined"
+ return 0
+ }
+
+ config_get cmduser "$cfg" cmduser
+ [ -z "$cmduser" ] && {
+ $LOG notice "No cmduser option in config $cfg defined"
+ return 0
+ }
+
+ config_get cmdgroup "$cfg" cmdgroup
+ if [ -z "$cmdgroup" ]; then
+ printf "\\t%s \"%s\" \"%s\"\n" "${section}" "${cmduser}" "${cmdline}" >> "$COLLECTD_CONF"
+ else
+ printf "\\t%s \"%s:%s\" \"%s\"\n" "${section}" "${cmduser}" "${cmdgroup}" "${cmdline}" >> "$COLLECTD_CONF"
+ fi
+}
+
+process_curl() {
+ printf "<Plugin curl>\n" >> "$COLLECTD_CONF"
+ config_foreach process_curl_page curl_page
+ printf "</Plugin>\n\n" >> "$COLLECTD_CONF"
+}
+
+process_curl_page() {
+ local cfg="$1"
+
+ local name url
+
+ config_get name "$cfg" name
+ [ -z "$name" ] && {
+ $LOG notice "No name option in config $cfg defined"
+ return 0
+ }
+
+ config_get url "$cfg" url
+ [ -z "$url" ] && {
+ $LOG notice "No URL option in config $cfg defined"
+ return 0
+ }
+
+ printf "\\t<Page \"%s\">\n" "${name}" >> "$COLLECTD_CONF"
+ printf "\\t\\tURL \"%s\"\n" "${url}" >> "$COLLECTD_CONF"
+ printf "\\t\\tMeasureResponseTime true\n" >> "$COLLECTD_CONF"
+ printf "\\t</Page>\n" >> "$COLLECTD_CONF"
+}
+
+process_network() {
+ local cfg="$1"
+
+ local TimeToLive Forward CacheFlush
+
+ printf "<Plugin network>\n" >> "$COLLECTD_CONF"
+ config_foreach process_network_sections network_listen "listen"
+ config_foreach process_network_sections network_server "server"
+
+ config_get TimeToLive "$cfg" TimeToLive
+ [ -z "$TimeToLive" ] || {
+ printf "\\tTimeToLive %s\n" "${TimeToLive}" >> "$COLLECTD_CONF"
+ }
+
+ config_get CacheFlush "$cfg" CacheFlush
+ [ -z "$CacheFlush" ] || {
+ printf "\\tCacheFlush %s\n" "${CacheFlush}" >> "$COLLECTD_CONF"
+ }
+
+ config_get_bool Forward "$cfg" Forward
+ if [ "$Forward" = "0" ]; then
+ printf "\\tForward false\n" >> "$COLLECTD_CONF"
+ else
+ printf "\\tForward true\n" >> "$COLLECTD_CONF"
+ fi
+
+ printf "</Plugin>\n\n" >> "$COLLECTD_CONF"
+}
+
+process_network_sections() {
+ local cfg="$1"
+ local section="$2"
+
+ local host port output
+
+ config_get host "$cfg" host
+ [ -z "$host" ] && {
+ $LOG notice "No host option in config $cfg defined"
+ return 0
+ }
+
+ if [ "$section" = "server" ]; then
+ output="Server \"$host\""
+ else
+ output="Listen \"$host\""
+ fi
+
+ config_get port "$cfg" port
+ if [ -z "$port" ]; then
+ printf "\\t%s\n" "${output}" >> "$COLLECTD_CONF"
+ else
+ printf "\\t%s \"%s\"\n" "${output}" "${port}" >> "$COLLECTD_CONF"
+ fi
+}
+
+process_iptables() {
+ local cfg="$1"
+
+ printf "<Plugin iptables>\n" >> "$COLLECTD_CONF"
+ config_foreach process_iptables_sections iptables_match
+ printf "</Plugin>\n\n" >> "$COLLECTD_CONF"
+}
+
+process_iptables_sections() {
+ local cfg="$1"
+
+ local table chain
+
+ config_get table "$cfg" table
+ [ -z "$table" ] && {
+ $LOG notice "No table option in config $cfg defined"
+ return 0
+ }
+
+ config_get chain "$cfg" chain
+ [ -z "$chain" ] && {
+ $LOG notice "No chain option in config $cfg defined"
+ return 0
+ }
+
+ config_get index "$cfg" index
+ [ -z "$index" ] && {
+ $LOG notice "No index option in config $cfg defined"
+ return 0
+ }
+
+ config_get name "$cfg" name
+ if [ -z "$name" ]; then
+ printf "\\tChain %s %s %s\n" "${table}" "${chain}" "${index}" >> "$COLLECTD_CONF"
+ else
+ printf "\\tChain %s %s %s \"%s\"\n" "${table}" "${chain}" "${index}" "${name}">> "$COLLECTD_CONF"
+ fi
+}
+
+CONFIG_LIST=""
+add_list_option() {
+ local value="$1"
+ local option="$2"
+ local indent="$3"
+
+ CONFIG_LIST="${CONFIG_LIST}${indent}${option} \"$value\"\n"
+}
+
+process_generic() {
+ local cfg="$1"
+ local indent="$2"
+ local json="$3"
+
+ local config=""
+
+ . /usr/share/libubox/jshn.sh
+ json_init
+ json_load_file "$json"
+
+ json_select string 1>/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ json_get_keys keys
+ for key in ${keys}; do
+ json_get_var option "$key"
+ config_get value "$cfg" "$option" ""
+ [ -z "$value" ] || {
+ config="${config}${indent}${option} \"${value}\"\n"
+ }
+ done
+ json_select ..
+ fi
+
+ json_select bool 1>/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ json_get_keys keys
+ for key in ${keys}; do
+ json_get_var option "$key"
+ config_get_bool value "$cfg" "$option"
+ if [ "$value" = "0" ]; then
+ config="${config}${indent}${option} false\n"
+ fi
+
+ if [ "$value" = "1" ]; then
+ config="${config}${indent}${option} true\n"
+ fi
+ done
+ json_select ..
+ fi
+
+ json_select list 1>/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ json_get_keys keys
+ for key in ${keys}; do
+ json_get_var option "$key"
+ CONFIG_LIST=""
+ config_list_foreach "$cfg" "$option" add_list_option "$option" "$indent"
+ config="${config}${CONFIG_LIST}"
+ done
+ json_select ..
+ fi
+
+ [ -z "$config" ] || {
+ printf "%s<Plugin %s>\n" "${CONFIG_STRING}" "$cfg" >> "$COLLECTD_CONF"
+ echo -n -e "${config}" >> "$COLLECTD_CONF"
+ printf "%s</Plugin>\n" "${CONFIG_STRING}" >> "$COLLECTD_CONF"
+ }
+}
+
+process_plugins() {
+ local cfg="$1"
+
+ local enable keys key option value
+
+ config_get enable "$cfg" enable 0
+ [ "$enable" = "1" ] || return 0
+
+ [ -f "/usr/lib/collectd/$cfg.so" ] || {
+ $LOG notice "Plugin collectd-mod-$cfg not installed"
+ return 0
+ }
+
+ [ -f "/usr/share/collectd/plugin/$cfg.json" ] || {
+ $LOG notice "Configuration definition file for $cfg not found"
+ return 0
+ }
+
+ printf "LoadPlugin %s\n" "$cfg" >> "$COLLECTD_CONF"
+ case "$cfg" in
+ exec)
+ CONFIG_STRING=""
+ process_exec
+ ;;
+ curl)
+ CONFIG_STRING=""
+ process_curl
+ ;;
+ network)
+ CONFIG_STRING=""
+ process_network "$cfg"
+ ;;
+ iptables)
+ CONFIG_STRING=""
+ process_iptables
+ ;;
+ *)
+ CONFIG_STRING=""
+ process_generic "$cfg" "\\t" "/usr/share/collectd/plugin/$cfg.json"
+ ;;
+ esac
+}
+
+process_config() {
+ local alt_config_file BaseDir Include PIDFile PluginDir TypesDB
+ local Interval ReadThreads WriteThreads Hostname
+ local WriteQueueLimitHigh WriteQueueLimitLow CollectInternalStats
+
+ rm -f "$COLLECTD_CONF"
+
+ [ -f /etc/config/collectd ] || {
+ $LOG notice "UCI config not found"
+ return 0
+ }
+ config_load collectd
+ config_get alt_config_file globals alt_config_file
+
+ # If "alt_config_file" specified, use that instead
+ [ -n "$alt_config_file" ] && [ -f "$alt_config_file" ] && {
+ rm -f "$COLLECTD_CONF"
+ ln -s "$alt_config_file" "$COLLECTD_CONF"
+ return 0
+ }
+
+ # GOBAL CONFIG
+ config_get BaseDir globals BaseDir "/var/run/collectd"
+ printf "BaseDir \"%s\"\n" "$BaseDir" >> "$COLLECTD_CONF"
+
+ config_get PIDFile globals PIDFile "/var/run/collectd.pid"
+ printf "PIDFile \"%s\"\n" "$PIDFile" >> "$COLLECTD_CONF"
+
+ config_get PluginDir globals PluginDir "/usr/lib/collectd"
+ printf "PluginDir \"%s\"\n" "$PluginDir" >> "$COLLECTD_CONF"
+
+ config_get TypesDB globals TypesDB "/usr/share/collectd/types.db"
+ printf "TypesDB \"%s\"\n" "$TypesDB" >> "$COLLECTD_CONF"
+
+ config_get Interval globals Interval 30
+ printf "Interval %s\n" "$Interval" >> "$COLLECTD_CONF"
+
+ config_get ReadThreads globals ReadThreads 2
+ printf "ReadThreads %s\n" "$ReadThreads" >> "$COLLECTD_CONF"
+
+ config_get WriteThreads globals WriteThreads 2
+ printf "WriteThreads %s\n" "$WriteThreads" >> "$COLLECTD_CONF"
+
+ config_get WriteQueueLimitLow globals WriteQueueLimitLow 0
+ [ "$WriteQueueLimitLow" -ne 0 ] \
+ && printf "WriteQueueLimitLow %s\n" "$WriteQueueLimitLow" >> "$COLLECTD_CONF"
+
+ config_get WriteQueueLimitHigh globals WriteQueueLimitHigh 0
+ [ "$WriteQueueLimitHigh" -ne 0 ] \
+ && printf "WriteQueueLimitHigh %s\n" "$WriteQueueLimitHigh" >> "$COLLECTD_CONF"
+
+ config_get_bool CollectInternalStats globals CollectInternalStats 0
+ if [ "$CollectInternalStats" = "0" ]; then
+ printf "CollectInternalStats false\n" >> "$COLLECTD_CONF"
+ else
+ printf "CollectInternalStats true\n" >> "$COLLECTD_CONF"
+ fi
+
+ config_get Hostname globals Hostname "$(uname -n)"
+ printf "Hostname \"%s\"\n" "$Hostname" >> "$COLLECTD_CONF"
+
+ config_get Include globals Include "/tmp/collectd.d"
+ printf "Include \"%s\"\n" "$Include" >> "$COLLECTD_CONF"
+ mkdir -p "$Include"
+
+ printf "\n" >> "$COLLECTD_CONF"
+
+ # PLUGIN CONFIG
+ config_foreach process_plugins plugin
+}
+
+service_triggers()
+{
+ procd_add_reload_trigger "collectd"
+}
+
+start_service() {
+ process_config
+
+ procd_open_instance
+ procd_set_param command /usr/sbin/collectd
+ procd_append_param command -C "$COLLECTD_CONF"
+ procd_append_param command -f # don't daemonize
+ procd_set_param nice "$NICEPRIO"
+ procd_set_param stderr 1
+ procd_set_param respawn
+ procd_close_instance
+}
+
+reload_service() {
+ restart "$@"
+}
diff --git a/external/subpack/utils/collectd/files/collectd.uci b/external/subpack/utils/collectd/files/collectd.uci
new file mode 100644
index 0000000..a716e93
--- /dev/null
+++ b/external/subpack/utils/collectd/files/collectd.uci
@@ -0,0 +1,215 @@
+config globals 'globals'
+ option alt_config_file "/etc/collectd.conf"
+# option BaseDir '/var/run/collectd'
+# option Include '/tmp/collectd.d'
+# option PIDFile '/var/run/collectd.pid'
+# option PluginDir '/usr/lib/collectd'
+# option TypesDB '/usr/share/collectd/types.db'
+# option Interval '30'
+# option ReadThreads '2'
+# option WriteThreads '2'
+# option WriteQueueLimitLow '0'
+# option WriteQueueLimitHigh '0'
+# option CollectInternalStats '0'
+
+#config plugin 'apcups'
+# option enable '0'
+# option Host 'localhost'
+# option Port '3551'
+
+#config plugin 'conntrack'
+# option enable '0'
+
+#config plugin 'contextswitch'
+# option enable '0'
+
+#config plugin 'cpu'
+# option enable '0'
+
+#config plugin 'cpufreq'
+# option enable '0'
+
+#config plugin 'csv'
+# option enable '0'
+# option StoreRates '0'
+# option DataDir '/tmp'
+
+#config plugin 'curl'
+# option enable '0'
+
+#config curl_page
+# option name 'test'
+# option url 'http://finance.google.com/finance?q=NYSE%3AAMD%22'
+
+#config plugin 'df'
+# option enable '0'
+# list Device '/dev/mtdblock/4'
+# list MountPoint '/jffs'
+# list FSType 'tmpfs'
+# option IgnoreSelected '0'
+
+#config plugin 'disk'
+# option enable '0'
+# list Disk 'hda1'
+# list Disk 'hdb'
+# option IgnoreSelected '0'
+
+#config plugin 'dns'
+# option enable '0'
+# list Interface 'br-lan'
+# list IgnoreSource '127.0.0.1'
+
+#config plugin 'email'
+# option enable '0'
+# option SocketFile '/var/run/collectd/email.sock'
+# option SocketGroup 'nogroup'
+
+#config plugin 'entropy'
+# option enable '0'
+
+#config plugin 'exec'
+# option enable '0'
+
+#config exec_input
+# option cmdline '/usr/bin/stat-dhcpusers'
+# option cmduser 'nobody'
+# option cmdgroup 'nogroup'
+
+#config exec_notify
+# option cmdline '/usr/bin/stat-dhcpusers'
+# option cmduser 'nobody'
+# option cmdgroup 'nogroup'
+
+#config plugin 'interface'
+# option enable '1'
+# list Interface 'br-lan'
+# option IgnoreSelected '0'
+
+#config plugin 'iptables'
+# option enable '1'
+
+#config iptables_match
+# option table 'nat'
+# option chain 'zone_wan_postrouting'
+# option index '1'
+# option name 'WLAN-Clients traffic'
+
+#config plugin 'irq'
+# option enable '0'
+# list Irq '2'
+# list Irq '3'
+# list Irq '4'
+# list Irq '7'
+
+#config plugin 'iwinfo'
+# option enable '0'
+
+#config plugin 'load'
+# option enable '0'
+
+#config plugin 'lua'
+# option BasePath '/usr/share/collectd-mod-lua'
+# list Script 'script1.lua'
+# list Script 'script2.lua
+
+#config plugin 'memory'
+# option enable '0'
+
+#config plugin 'netlink'
+# option enable '0'
+# option IgnoreSelected '0'
+# list VerboseInterface 'br-lan'
+# list QDisc 'br-lan'
+
+#config plugin 'network'
+# option enable '1'
+# option TimeToLive '128'
+# option Forward '1'
+# option CacheFlush '86400'
+
+#config network_listen
+# option host '0.0.0.0'
+# option port '25826'
+
+#config network_server
+# option host '1.1.1.1'
+# option port '25826'
+
+#config plugin 'nut'
+# option enable '0'
+# option UPS 'myupsname'
+
+#config plugin 'olsrd'
+# option enable '0'
+# option Port '2006'
+# option Host '127.0.0.1'
+
+#config plugin 'openvpn'
+# option enable '0'
+# option StatusFile '/var/run/openvpn/openvpn.status'
+# option CollectIndividualUsers '1'
+# optoin CollectUserCount '1'
+# optoin CollectCompression '1'
+# option ImprovedNamingSchema '0'
+
+#config plugin 'ping'
+# option enable '0'
+# option TTL '127'
+# option Interval '30'
+# list Host '127.0.0.1'
+
+#config plugin 'processes'
+# option enable '0'
+# list Process 'uhttpd'
+# list Process 'dnsmasq'
+# list Process 'dropbear'
+
+#config plugin 'rrdtool'
+# option enable '0'
+# option DataDir '/tmp/rrd'
+# option RRARows '100'
+# option RRASingle '1'
+# list RRATimespan '3600'
+# list RRATimespan '86400'
+# list RRATimespan '604800'
+# list RRATimespan '2678400'
+# list RRATimespan '31622400'
+
+#config plugin 'sensors'
+# option enable '0'
+
+#config plugin 'swap'
+# option enable '0'
+# option ReportByDevice '1'
+# option ValuesAbsolute '1'
+# option ValuesPercentage '0'
+# option ReportIO '1'
+# option ReportBytes '1'
+
+#config plugin 'tcpconns'
+# option enable '0'
+# list ListeningPort '0'
+# list LocalPort '22'
+# list LocalPort '80'
+
+#config plugin 'thermal'
+# option enable '0'
+# option IgnoreSelected '0'
+# list Device ''
+
+#config plugin 'ubi'
+# option enable '0'
+# list Device 'ubi0'
+# option IgnoreSelected '0'
+
+#config plugin 'unixsock'
+# option enable '0'
+# option SocketFile '/var/run/collectd/query.sock'
+# option SocketGroup 'nogroup'
+
+#config plugin 'uptime'
+# option enable '0'
+
+#config plugin 'vmem'
+# option enable '0'
+# option Verbose '0'
diff --git a/external/subpack/utils/collectd/files/exec-scripts/sqm_collectd.sh b/external/subpack/utils/collectd/files/exec-scripts/sqm_collectd.sh
new file mode 100755
index 0000000..ad84fc7
--- /dev/null
+++ b/external/subpack/utils/collectd/files/exec-scripts/sqm_collectd.sh
@@ -0,0 +1,107 @@
+#!/bin/sh
+
+. /usr/share/libubox/jshn.sh
+
+HOSTNAME="${COLLECTD_HOSTNAME:-localhost}"
+INTERVAL="${COLLECTD_INTERVAL:-60}"
+
+handle_cake() {
+ local ifc ifr tin i
+
+ ifc="$1"
+ ifr="${ifc//[!0-9A-Za-z]/_}"
+
+ # Overall
+ json_get_vars bytes packets drops backlog qlen
+
+ # Options
+ json_select options
+ json_get_vars bandwidth diffserv
+ json_select ".."
+
+ echo "PUTVAL \"$HOSTNAME/sqm-$ifc/qdisc_bytes\" interval=$INTERVAL N:$bytes"
+ echo "PUTVAL \"$HOSTNAME/sqm-$ifc/qdisc_drops\" interval=$INTERVAL N:$drops"
+ echo "PUTVAL \"$HOSTNAME/sqm-$ifc/qdisc_backlog\" interval=$INTERVAL N:$backlog"
+
+ # ash doesn't have arrays so prepare to get a little creative
+ case "$diffserv" in
+ diffserv3 | diffserv4) tns="BKBEVIVO"
+ ;;
+ *) tns="T0T1T2T3T4T5T6T7"
+ ;;
+ esac
+
+ # Tins
+ # Flows & delays indicate the state as of the last packet that flowed through, so they appear to get stuck.
+ # Discard the results from a stuck tin.
+ json_get_keys tins tins
+ json_select tins
+ i=0
+ for tin in $tins; do
+ json_select "$tin"
+ json_get_vars threshold_rate sent_bytes sent_packets backlog_bytes target_us peak_delay_us avg_delay_us base_delay_us drops ecn_mark ack_drops sparse_flows bulk_flows unresponsive_flows
+
+ eval osp="\$osp${ifr}t${i}"
+ if [ "$osp" ] && [ "$osp" -eq "$sent_packets" ] ; then
+ peak_delay_us=0; avg_delay_us=0; base_delay_us=0
+ sparse_flows=0; bulk_flows=0; unresponsive_flows=0
+ else
+ eval "osp${ifr}t${i}=$sent_packets"
+ fi
+
+ tn=${tns:$((i<<1)):2}
+
+ echo "PUTVAL \"$HOSTNAME/sqmcake-$ifc/qdisct_bytes-$tn\" interval=$INTERVAL N:$sent_bytes"
+ echo "PUTVAL \"$HOSTNAME/sqmcake-$ifc/qdisct_thres-$tn\" interval=$INTERVAL N:$threshold_rate"
+ echo "PUTVAL \"$HOSTNAME/sqmcake-$ifc/qdisct_drops-$tn\" interval=$INTERVAL N:$drops:$ecn_mark:$ack_drops"
+ echo "PUTVAL \"$HOSTNAME/sqmcake-$ifc/qdisct_backlog-$tn\" interval=$INTERVAL N:$backlog_bytes"
+ echo "PUTVAL \"$HOSTNAME/sqmcake-$ifc/qdisct_flows-$tn\" interval=$INTERVAL N:$sparse_flows:$bulk_flows:$unresponsive_flows"
+ echo "PUTVAL \"$HOSTNAME/sqmcake-$ifc/qdisct_latencyus-$tn\" interval=$INTERVAL N:$target_us:$peak_delay_us:$avg_delay_us:$base_delay_us"
+
+ json_select ..
+ i=$((i+1))
+ done
+ json_select ..
+}
+
+handle_mq() {
+ ifc="$1"
+
+ # Overall
+ json_get_vars bytes drops backlog
+
+ echo "PUTVAL \"$HOSTNAME/sqm-$ifc/qdisc_bytes\" interval=$INTERVAL N:$bytes"
+ echo "PUTVAL \"$HOSTNAME/sqm-$ifc/qdisc_drops\" interval=$INTERVAL N:$drops"
+ echo "PUTVAL \"$HOSTNAME/sqm-$ifc/qdisc_backlog\" interval=$INTERVAL N:$backlog"
+}
+
+process_qdisc() {
+ local ifc jsn
+
+ ifc="$1"
+ jsn=$(tc -s -j qdisc show dev "$ifc") || return
+
+ # strip leading & trailing []
+ jsn="${jsn#[}" ; jsn="${jsn%]}"
+
+ json_load "${jsn}"
+ json_get_var qdisc kind
+
+ case "$qdisc" in
+ cake) handle_cake "$ifc"
+ ;;
+ mq) handle_mq "$ifc"
+ ;;
+
+ *) echo "Unknown qdisc type '$qdisc' on interface '$ifc'" 1>&2
+ ;;
+ esac
+ json_cleanup
+}
+
+while true ; do
+ for ifc in "$@" ; do
+ process_qdisc "$ifc"
+ done
+ sleep "${INTERVAL%%.*}"
+done
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/apcups.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/apcups.json
new file mode 100644
index 0000000..15a31df
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/apcups.json
@@ -0,0 +1,6 @@
+{
+ "string": [
+ "Host",
+ "Port"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/conntrack.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/conntrack.json
new file mode 100644
index 0000000..2c63c08
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/conntrack.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/contextswitch.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/contextswitch.json
new file mode 100644
index 0000000..2c63c08
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/contextswitch.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/cpu.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/cpu.json
new file mode 100644
index 0000000..ef28a43
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/cpu.json
@@ -0,0 +1,7 @@
+{
+ "bool": [
+ "ValuesPercentage",
+ "ReportByCpu",
+ "ReportByState"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/cpufreq.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/cpufreq.json
new file mode 100644
index 0000000..2c63c08
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/cpufreq.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/csv.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/csv.json
new file mode 100644
index 0000000..3e89972
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/csv.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ "DataDir"
+ ],
+ "bool": [
+ "StoreRates"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/curl.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/curl.json
new file mode 100644
index 0000000..2c63c08
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/curl.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/df.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/df.json
new file mode 100644
index 0000000..dde65fd
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/df.json
@@ -0,0 +1,10 @@
+{
+ "bool": [
+ "IgnoreSelected"
+ ],
+ "list": [
+ "Device",
+ "MountPoint",
+ "FSType"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/disk.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/disk.json
new file mode 100644
index 0000000..e7b9214
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/disk.json
@@ -0,0 +1,8 @@
+{
+ "bool": [
+ "IgnoreSelected"
+ ],
+ "list": [
+ "Disk"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/dns.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/dns.json
new file mode 100644
index 0000000..c9dacf1
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/dns.json
@@ -0,0 +1,6 @@
+{
+ "list": [
+ "Interface",
+ "IgnoreSource"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/email.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/email.json
new file mode 100644
index 0000000..eb6b3ef
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/email.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ "SocketFile",
+ "SocketGroup",
+ "SocketPerms",
+ "MaxConns"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/entropy.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/entropy.json
new file mode 100644
index 0000000..2c63c08
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/entropy.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/exec.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/exec.json
new file mode 100644
index 0000000..2c63c08
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/exec.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/interface.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/interface.json
new file mode 100644
index 0000000..aef2522
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/interface.json
@@ -0,0 +1,8 @@
+{
+ "bool": [
+ "IgnoreSelected"
+ ],
+ "list": [
+ "Interface"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/iptables.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/iptables.json
new file mode 100644
index 0000000..2c63c08
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/iptables.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/irq.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/irq.json
new file mode 100644
index 0000000..0f7e59c
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/irq.json
@@ -0,0 +1,8 @@
+{
+ "bool": [
+ "IgnoreSelected"
+ ],
+ "list": [
+ "Irq"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/iwinfo.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/iwinfo.json
new file mode 100644
index 0000000..aef2522
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/iwinfo.json
@@ -0,0 +1,8 @@
+{
+ "bool": [
+ "IgnoreSelected"
+ ],
+ "list": [
+ "Interface"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/load.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/load.json
new file mode 100644
index 0000000..2c63c08
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/load.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/logfile.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/logfile.json
new file mode 100644
index 0000000..fd16084
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/logfile.json
@@ -0,0 +1,9 @@
+{
+ "string": [
+ "LogLevel",
+ "File"
+ ],
+ "bool": [
+ "Timestamp"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/lua.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/lua.json
new file mode 100644
index 0000000..2bc7b68
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/lua.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ "BasePath"
+ ],
+ "list": [
+ "Script"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/memory.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/memory.json
new file mode 100644
index 0000000..fc43e2f
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/memory.json
@@ -0,0 +1,6 @@
+{
+ "bool": [
+ "ValuesPercentage",
+ "ValuesAbsolute"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/netlink.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/netlink.json
new file mode 100644
index 0000000..7ef7b77
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/netlink.json
@@ -0,0 +1,12 @@
+{
+ "bool": [
+ "IgnoreSelected"
+ ],
+ "list": [
+ "Interface",
+ "VerboseInterface",
+ "QDisc",
+ "Classe",
+ "Filter"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/network.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/network.json
new file mode 100644
index 0000000..2c63c08
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/network.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/nut.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/nut.json
new file mode 100644
index 0000000..4cac99f
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/nut.json
@@ -0,0 +1,5 @@
+{
+ "string": [
+ "UPS"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/olsrd.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/olsrd.json
new file mode 100644
index 0000000..04c0438
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/olsrd.json
@@ -0,0 +1,9 @@
+{
+ "string": [
+ "Host",
+ "Port",
+ "CollectLinks",
+ "CollectRoutes",
+ "CollectTopology"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/openvpn.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/openvpn.json
new file mode 100644
index 0000000..87a3f16
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/openvpn.json
@@ -0,0 +1,11 @@
+{
+ "string": [
+ "StatusFile"
+ ],
+ "bool": [
+ "CollectIndividualUsers",
+ "CollectUserCount",
+ "CollectCompression",
+ "ImprovedNamingSchema"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/ping.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/ping.json
new file mode 100644
index 0000000..53bc88c
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/ping.json
@@ -0,0 +1,9 @@
+{
+ "string": [
+ "TTL",
+ "Interval"
+ ],
+ "list": [
+ "Host"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/processes.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/processes.json
new file mode 100644
index 0000000..6e38fa9
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/processes.json
@@ -0,0 +1,5 @@
+{
+ "list": [
+ "Process"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/rrdtool.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/rrdtool.json
new file mode 100644
index 0000000..339f6ac
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/rrdtool.json
@@ -0,0 +1,17 @@
+{
+ "string": [
+ "DataDir",
+ "StepSize",
+ "HeartBeat",
+ "RRARows",
+ "XFF",
+ "CacheFlush",
+ "CacheTimeout"
+ ],
+ "bool": [
+ "RRASingle"
+ ],
+ "list": [
+ "RRATimespan"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/sensors.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/sensors.json
new file mode 100644
index 0000000..35915ba
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/sensors.json
@@ -0,0 +1,8 @@
+{
+ "bool": [
+ "IgnoreSelected"
+ ],
+ "list": [
+ "Sensor"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/smart.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/smart.json
new file mode 100644
index 0000000..52d6246
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/smart.json
@@ -0,0 +1,10 @@
+{
+ "bool": [
+ "IgnoreSelected",
+ "IgnoreSleepMode",
+ "UseSerial"
+ ],
+ "list": [
+ "Disk"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/swap.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/swap.json
new file mode 100644
index 0000000..88734af
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/swap.json
@@ -0,0 +1,9 @@
+{
+ "bool": [
+ "ReportBytes",
+ "ReportByDevice",
+ "ValuesAbsolute",
+ "ValuesPercentage",
+ "ReportIO"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/syslog.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/syslog.json
new file mode 100644
index 0000000..d476509
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/syslog.json
@@ -0,0 +1,6 @@
+{
+ "string": [
+ "LogLevel",
+ "NotifyLevel"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/tcpconns.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/tcpconns.json
new file mode 100644
index 0000000..56a4c81
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/tcpconns.json
@@ -0,0 +1,9 @@
+{
+ "bool": [
+ "ListeningPorts"
+ ],
+ "list": [
+ "LocalPort",
+ "RemotePort"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/thermal.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/thermal.json
new file mode 100644
index 0000000..cf93fc2
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/thermal.json
@@ -0,0 +1,8 @@
+{
+ "bool": [
+ "IgnoreSelected"
+ ],
+ "list": [
+ "Device"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/ubi.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/ubi.json
new file mode 100644
index 0000000..cf93fc2
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/ubi.json
@@ -0,0 +1,8 @@
+{
+ "bool": [
+ "IgnoreSelected"
+ ],
+ "list": [
+ "Device"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/unixsock.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/unixsock.json
new file mode 100644
index 0000000..6362a9d
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/unixsock.json
@@ -0,0 +1,7 @@
+{
+ "string": [
+ "SocketFile",
+ "SocketGroup",
+ "SocketPerms"
+ ]
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/uptime.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/uptime.json
new file mode 100644
index 0000000..2c63c08
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/uptime.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/external/subpack/utils/collectd/files/usr/share/collectd/plugin/vmem.json b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/vmem.json
new file mode 100644
index 0000000..5fb8a85
--- /dev/null
+++ b/external/subpack/utils/collectd/files/usr/share/collectd/plugin/vmem.json
@@ -0,0 +1,5 @@
+{
+ "bool": [
+ "Verbose"
+ ]
+}
diff --git a/external/subpack/utils/collectd/patches/001-undefined-AM_PATH_LIBGCRYPT.patch b/external/subpack/utils/collectd/patches/001-undefined-AM_PATH_LIBGCRYPT.patch
new file mode 100644
index 0000000..0e01744
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/001-undefined-AM_PATH_LIBGCRYPT.patch
@@ -0,0 +1,4 @@
+--- /dev/null
++++ b/fake-am_path_libgcrypt.m4
+@@ -0,0 +1 @@
++AC_DEFUN([AM_PATH_LIBGCRYPT],[:])
diff --git a/external/subpack/utils/collectd/patches/100-rrdtool-add-rrasingle-option.patch b/external/subpack/utils/collectd/patches/100-rrdtool-add-rrasingle-option.patch
new file mode 100644
index 0000000..9fb749b
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/100-rrdtool-add-rrasingle-option.patch
@@ -0,0 +1,55 @@
+--- a/src/rrdtool.c
++++ b/src/rrdtool.c
+@@ -60,6 +60,7 @@ typedef struct rrd_queue_s rrd_queue_t;
+ static const char *config_keys[] = {
+ "CacheTimeout", "CacheFlush", "CreateFilesAsync", "DataDir",
+ "StepSize", "HeartBeat", "RRARows", "RRATimespan",
++ "RRASingle",
+ "XFF", "WritesPerSecond", "RandomTimeout"};
+ static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
+
+@@ -77,6 +78,8 @@ static rrdcreate_config_t rrdcreate_conf
+ /* timespans = */ NULL,
+ /* timespans_num = */ 0,
+
++ /* rrasingle = */ 0,
++
+ /* consolidation_functions = */ NULL,
+ /* consolidation_functions_num = */ 0,
+
+@@ -944,6 +947,12 @@ static int rrd_config(const char *key, c
+ /* compar = */ rrd_compare_numeric);
+
+ free(value_copy);
++ } else if (strcasecmp ("RRASingle", key) == 0) {
++ if (IS_TRUE (value))
++ {
++ rrdcreate_config.rrasingle = 1;
++ NOTICE ("rrdtool plugin: RRASingle = true: creating only AVERAGE RRAs");
++ }
+ } else if (strcasecmp("XFF", key) == 0) {
+ double tmp = atof(value);
+ if ((tmp < 0.0) || (tmp >= 1.0)) {
+--- a/src/utils/rrdcreate/rrdcreate.c
++++ b/src/utils/rrdcreate/rrdcreate.c
+@@ -180,6 +180,9 @@ static int rra_get(char ***ret, const va
+ rts_num = rra_timespans_num;
+ }
+
++ if (cfg->rrasingle)
++ rra_types_num = 1;
++
+ rra_max = rts_num * rra_types_num;
+ assert(rra_max > 0);
+
+--- a/src/utils/rrdcreate/rrdcreate.h
++++ b/src/utils/rrdcreate/rrdcreate.h
+@@ -40,6 +40,8 @@ struct rrdcreate_config_s {
+ int *timespans;
+ size_t timespans_num;
+
++ int rrasingle;
++
+ char **consolidation_functions;
+ size_t consolidation_functions_num;
+
diff --git a/external/subpack/utils/collectd/patches/140-fix-fqdnlookup.patch b/external/subpack/utils/collectd/patches/140-fix-fqdnlookup.patch
new file mode 100644
index 0000000..30c6f7f
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/140-fix-fqdnlookup.patch
@@ -0,0 +1,11 @@
+--- a/src/daemon/configfile.c
++++ b/src/daemon/configfile.c
+@@ -104,7 +104,7 @@ static cf_global_option_t cf_global_opti
+ {"BaseDir", NULL, 0, PKGLOCALSTATEDIR},
+ {"PIDFile", NULL, 0, PIDFILE},
+ {"Hostname", NULL, 0, NULL},
+- {"FQDNLookup", NULL, 0, "true"},
++ {"FQDNLookup", NULL, 0, "false"},
+ {"Interval", NULL, 0, NULL},
+ {"ReadThreads", NULL, 0, "5"},
+ {"WriteThreads", NULL, 0, "5"},
diff --git a/external/subpack/utils/collectd/patches/300-delay-first-read-cycle.patch b/external/subpack/utils/collectd/patches/300-delay-first-read-cycle.patch
new file mode 100644
index 0000000..d4eb826
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/300-delay-first-read-cycle.patch
@@ -0,0 +1,11 @@
+--- a/src/daemon/plugin.c
++++ b/src/daemon/plugin.c
+@@ -1092,7 +1092,7 @@ static int plugin_insert_read(read_func_
+ int status;
+ llentry_t *le;
+
+- rf->rf_next_read = cdtime();
++ rf->rf_next_read = cdtime() + (cdtime_t) 1073741824; //delay first read 1s
+ rf->rf_effective_interval = rf->rf_interval;
+
+ pthread_mutex_lock(&read_lock);
diff --git a/external/subpack/utils/collectd/patches/320-reaction-to-ntp-time-change-at-boot.patch b/external/subpack/utils/collectd/patches/320-reaction-to-ntp-time-change-at-boot.patch
new file mode 100644
index 0000000..9b0d033
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/320-reaction-to-ntp-time-change-at-boot.patch
@@ -0,0 +1,61 @@
+Adjust the reaction to a polling interval timestamp that references
+to a past time.
+
+Past timestamps can happen when ntpd adjusts router's time after network
+connectivity is obtained after boot. Collectd shows warnings for each plugin
+as it tries to enter new values with the same timestamp as the previous one.
+
+This patch adjusts the next polling time to be now+2 seconds for the main
+loop and for the plugin-specific read loops. That avoids the warnings, but
+does not overreact in case there are shorter polling intervals or the time
+gets adjusted for other reasons.
+
+Additionally some debug statements are added, but they are visible only
+when --enable-debug configure option is used in Makefile.
+
+
+--- a/src/daemon/collectd.c
++++ b/src/daemon/collectd.c
+@@ -274,20 +274,23 @@ static int do_loop(void) {
+ update_kstat();
+ #endif
+
++ DEBUG("do_loop before plugin_read_all: now = %.3f", CDTIME_T_TO_DOUBLE(cdtime()));
+ /* Issue all plugins */
+ plugin_read_all();
+
+ cdtime_t now = cdtime();
++ DEBUG("do_loop after plugin_read_all: now = %.3f, wait_until= %.3f", CDTIME_T_TO_DOUBLE(now), CDTIME_T_TO_DOUBLE(wait_until));
+ if (now >= wait_until) {
+- WARNING("Not sleeping because the next interval is "
++ WARNING("Sleeping only 2s because the next interval is "
+ "%.3f seconds in the past!",
+ CDTIME_T_TO_DOUBLE(now - wait_until));
+- wait_until = now + interval;
+- continue;
++ wait_until = now + DOUBLE_TO_CDTIME_T(2);
++ DEBUG("do_loop: wait_until adjusted to now+2 = %.3f", CDTIME_T_TO_DOUBLE(wait_until));
+ }
+
+ struct timespec ts_wait = CDTIME_T_TO_TIMESPEC(wait_until - now);
+ wait_until = wait_until + interval;
++ DEBUG("do_loop ends: wait_until set to %.3f", CDTIME_T_TO_DOUBLE(wait_until));
+
+ while ((loop == 0) && (nanosleep(&ts_wait, &ts_wait) != 0)) {
+ if (errno != EINTR) {
+--- a/src/daemon/plugin.c
++++ b/src/daemon/plugin.c
+@@ -585,10 +585,11 @@ static void *plugin_read_thread(void __a
+
+ /* Check, if `rf_next_read' is in the past. */
+ if (rf->rf_next_read < now) {
+- /* `rf_next_read' is in the past. Insert `now'
++ /* `rf_next_read' is in the past. Insert `now'+2s
+ * so this value doesn't trail off into the
+ * past too much. */
+- rf->rf_next_read = now;
++ rf->rf_next_read = now + DOUBLE_TO_CDTIME_T(2);
++ DEBUG("plugin_read_thread: Next read is in the past. Adjusted to now+2s");
+ }
+
+ DEBUG("plugin_read_thread: Next read of the `%s' plugin at %.3f.",
diff --git a/external/subpack/utils/collectd/patches/400-fix-olsrd-get-all.patch b/external/subpack/utils/collectd/patches/400-fix-olsrd-get-all.patch
new file mode 100644
index 0000000..d46a57a
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/400-fix-olsrd-get-all.patch
@@ -0,0 +1,11 @@
+--- a/src/olsrd.c
++++ b/src/olsrd.c
+@@ -582,7 +582,7 @@ static int olsrd_read(void) /* {{{ */
+ if (fh == NULL)
+ return -1;
+
+- fputs("\r\n", fh);
++ fputs("/all \r\n", fh);
+ fflush(fh);
+
+ while (fgets(buffer, sizeof(buffer), fh) != NULL) {
diff --git a/external/subpack/utils/collectd/patches/600-fix-libmodbus-detection.patch b/external/subpack/utils/collectd/patches/600-fix-libmodbus-detection.patch
new file mode 100644
index 0000000..ff03547
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/600-fix-libmodbus-detection.patch
@@ -0,0 +1,43 @@
+Patch reverts upstream commit:
+https://github.com/collectd/collectd/commit/6124da7a48f28f54fc09ebeb942d1037516fe6ab
+
+The commit changed the detection path due to FreeBSD issues,
+but apparently affects also Openwrt buildroot negatively.
+
+Original explanation:
+ From 6124da7a48f28f54fc09ebeb942d1037516fe6ab Mon Sep 17 00:00:00 2001
+ Subject: [PATCH] Fix libmodbus detection on FreeBSD
+
+ We look for modbus/modbus.h in /usr/local/include/modbus
+ but we should look for modbus.h
+
+ This is only an issue on FreeBSD since /usr/local/include is not
+ in the default search path.
+
+Reversed patch to be applied:
+
+--- a/configure.ac
++++ b/configure.ac
+@@ -3385,9 +3385,9 @@ if test "x$with_libmodbus" = "xyes"; the
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libmodbus_cflags"
+
+- AC_CHECK_HEADERS([modbus.h],
++ AC_CHECK_HEADERS([modbus/modbus.h],
+ [with_libmodbus="yes"],
+- [with_libmodbus="no (modbus.h not found)"]
++ [with_libmodbus="no (modbus/modbus.h not found)"]
+ )
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+--- a/src/modbus.c
++++ b/src/modbus.c
+@@ -26,7 +26,7 @@
+ #include "plugin.h"
+ #include "utils/common/common.h"
+
+-#include <modbus.h>
++#include <modbus/modbus.h>
+ #include <netdb.h>
+ #include <sys/socket.h>
+
diff --git a/external/subpack/utils/collectd/patches/700-disable-sys-capability-check.patch b/external/subpack/utils/collectd/patches/700-disable-sys-capability-check.patch
new file mode 100644
index 0000000..349c524
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/700-disable-sys-capability-check.patch
@@ -0,0 +1,15 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -533,11 +533,7 @@ if test "x$ac_system" = "xLinux"; then
+ [have_cpuid_h="no (cpuid.h not found)"]
+ )
+
+- AC_CHECK_HEADERS([sys/capability.h],
+- [have_capability="yes"],
+- [have_capability="no (<sys/capability.h> not found)"]
+- )
+-
++ have_capability="no"
+ if test "x$have_capability" = "xyes"; then
+ AC_CHECK_LIB([cap], [cap_get_proc],
+ [have_capability="yes"],
diff --git a/external/subpack/utils/collectd/patches/900-add-iwinfo-plugin.patch b/external/subpack/utils/collectd/patches/900-add-iwinfo-plugin.patch
new file mode 100644
index 0000000..0fec73a
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/900-add-iwinfo-plugin.patch
@@ -0,0 +1,279 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -713,6 +713,11 @@ AC_CACHE_CHECK([whether clock_boottime a
+ ]
+ )
+
++# For the iwinfo plugin
++AC_CHECK_LIB([iwinfo], [iwinfo_backend],
++ [with_iwinfo="yes"],
++ [with_iwinfo="no (libiwinfo not found)"]
++)
+
+ #
+ # Checks for typedefs, structures, and compiler characteristics.
+@@ -6619,6 +6624,7 @@ plugin_ipmi="no"
+ plugin_ipstats="no"
+ plugin_ipvs="no"
+ plugin_irq="no"
++plugin_iwinfo="no"
+ plugin_load="no"
+ plugin_log_logstash="no"
+ plugin_mcelog="no"
+@@ -7086,6 +7092,7 @@ AC_PLUGIN([iptables], [$with_
+ AC_PLUGIN([ipstats], [$plugin_ipstats], [IP packet statistics])
+ AC_PLUGIN([ipvs], [$plugin_ipvs], [IPVS connection statistics])
+ AC_PLUGIN([irq], [$plugin_irq], [IRQ statistics])
++AC_PLUGIN([iwinfo], [$with_iwinfo], [Common iwinfo wireless statistics])
+ AC_PLUGIN([java], [$with_java], [Embed the Java Virtual Machine])
+ AC_PLUGIN([load], [$plugin_load], [System load])
+ AC_PLUGIN([log_logstash], [$plugin_log_logstash], [Logstash json_event compatible logging])
+@@ -7465,6 +7472,7 @@ AC_MSG_RESULT([ libyajl . . . . . . .
+ AC_MSG_RESULT([ oracle . . . . . . . $with_oracle])
+ AC_MSG_RESULT([ protobuf-c . . . . . $have_protoc_c])
+ AC_MSG_RESULT([ protoc 3 . . . . . . $have_protoc3])
++AC_MSG_RESULT([ iwinfo . . . . . . . $with_iwinfo])
+ AC_MSG_RESULT()
+ AC_MSG_RESULT([ Features:])
+ AC_MSG_RESULT([ daemon mode . . . . . $enable_daemon])
+@@ -7533,6 +7541,7 @@ AC_MSG_RESULT([ iptables . . . . . .
+ AC_MSG_RESULT([ ipstats . . . . . . . $enable_ipstats])
+ AC_MSG_RESULT([ ipvs . . . . . . . . $enable_ipvs])
+ AC_MSG_RESULT([ irq . . . . . . . . . $enable_irq])
++AC_MSG_RESULT([ iwinfo . . . . . . . $enable_iwinfo])
+ AC_MSG_RESULT([ java . . . . . . . . $enable_java])
+ AC_MSG_RESULT([ load . . . . . . . . $enable_load])
+ AC_MSG_RESULT([ logfile . . . . . . . $enable_logfile])
+--- a/src/collectd.conf.in
++++ b/src/collectd.conf.in
+@@ -147,6 +147,7 @@
+ #@BUILD_PLUGIN_IPTABLES_TRUE@LoadPlugin iptables
+ #@BUILD_PLUGIN_IPVS_TRUE@LoadPlugin ipvs
+ #@BUILD_PLUGIN_IRQ_TRUE@LoadPlugin irq
++#@BUILD_PLUGIN_IWINFO_TRUE@LoadPlugin iwinfo
+ #@BUILD_PLUGIN_JAVA_TRUE@LoadPlugin java
+ @BUILD_PLUGIN_LOAD_TRUE@@BUILD_PLUGIN_LOAD_TRUE@LoadPlugin load
+ #@BUILD_PLUGIN_LPAR_TRUE@LoadPlugin lpar
+@@ -897,6 +898,12 @@
+ # IgnoreSelected true
+ #</Plugin>
+
++#<Plugin iwinfo>
++# Interface "ath0"
++# Interface "ra0"
++# Interface "wlan0"
++#</Plugin>
++
+ #<Plugin java>
+ # JVMArg "-verbose:jni"
+ # JVMArg "-Djava.class.path=@prefix@/share/collectd/java/collectd-api.jar"
+--- a/src/collectd.conf.pod
++++ b/src/collectd.conf.pod
+@@ -4343,6 +4343,27 @@ and all other interrupts are collected.
+
+ =back
+
++=head2 Plugin C<iwinfo>
++
++=over 4
++
++=item B<Interface> I<Interface>
++
++Select this interface. By default all detected wireless interfaces will be
++collected. For a more detailed description see B<IgnoreSelected> below.
++
++=item B<IgnoreSelected> I<true>|I<false>
++
++If no configuration if given, the B<iwinfo>-plugin will collect data from all
++detected wireless interfaces. You can use the B<Interface>-option to pick the
++interfaces you're interested in. Sometimes, however, it's easier/preferred to
++collect all interfaces I<except> a few ones. This option enables you to do
++that: By setting B<IgnoreSelected> to I<true> the effect of B<Interface> is
++inverted: All selected interfaces are ignored and all other interfaces are
++collected.
++
++=back
++
+ =head2 Plugin C<java>
+
+ The I<Java> plugin makes it possible to write extensions for collectd in Java.
+--- /dev/null
++++ b/src/iwinfo.c
+@@ -0,0 +1,150 @@
++/**
++ * collectd - src/iwinfo.c
++ * Copyright (C) 2011 Jo-Philipp Wich
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; only version 2 of the License is applicable.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ **/
++
++#include "collectd.h"
++#include "plugin.h"
++#include "utils/common/common.h"
++#include "utils/ignorelist/ignorelist.h"
++
++#include <stdint.h>
++#include <iwinfo.h>
++
++#define PROCNETDEV "/proc/net/dev"
++
++static const char *config_keys[] = {
++ "Interface",
++ "IgnoreSelected"
++};
++static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
++
++static ignorelist_t *ignorelist = NULL;
++
++static int iwinfo_config(const char *key, const char *value)
++{
++ if (ignorelist == NULL)
++ ignorelist = ignorelist_create(1);
++
++ if (ignorelist == NULL)
++ return 1;
++
++ if (strcasecmp(key, "Interface") == 0)
++ ignorelist_add(ignorelist, value);
++ else if (strcasecmp(key, "IgnoreSelected") == 0)
++ ignorelist_set_invert(ignorelist, IS_TRUE(value) ? 0 : 1);
++ else
++ return -1;
++
++ return 0;
++}
++
++static void iwinfo_submit(const char *ifname, const char *type, int value)
++{
++ value_t values[1];
++ value_list_t vl = VALUE_LIST_INIT;
++
++ values[0].gauge = value;
++
++ vl.values = values;
++ vl.values_len = 1;
++
++ sstrncpy(vl.host, hostname_g, sizeof(vl.host));
++ sstrncpy(vl.plugin, "iwinfo", sizeof(vl.plugin));
++ sstrncpy(vl.plugin_instance, ifname, sizeof(vl.plugin_instance));
++ sstrncpy(vl.type, type, sizeof(vl.type));
++ /*sstrncpy(vl.type_instance, "", sizeof(vl.type_instance));*/
++
++ plugin_dispatch_values(&vl);
++}
++
++static void iwinfo_process(const char *ifname)
++{
++ int val;
++ char buf[IWINFO_BUFSIZE];
++ const struct iwinfo_ops *iw = iwinfo_backend(ifname);
++
++ /* does appear to be a wifi iface */
++ if (iw)
++ {
++ if (iw->bitrate(ifname, &val))
++ val = 0;
++ iwinfo_submit(ifname, "bitrate", val * 1000);
++
++ if (iw->signal(ifname, &val))
++ val = 0;
++ iwinfo_submit(ifname, "signal_power", val);
++
++ if (iw->noise(ifname, &val))
++ val = 0;
++ iwinfo_submit(ifname, "signal_noise", val);
++
++ if (iw->quality(ifname, &val))
++ val = 0;
++ iwinfo_submit(ifname, "signal_quality", val);
++
++ if (iw->assoclist(ifname, buf, &val))
++ val = 0;
++ iwinfo_submit(ifname, "stations",
++ val / sizeof(struct iwinfo_assoclist_entry));
++ }
++
++ iwinfo_finish();
++}
++
++static int iwinfo_read(void)
++{
++ char line[1024];
++ char ifname[128];
++ FILE *f;
++
++ f = fopen(PROCNETDEV, "r");
++ if (f == NULL)
++ {
++ char err[1024];
++ WARNING("iwinfo: Unable to open " PROCNETDEV ": %s",
++ sstrerror(errno, err, sizeof(err)));
++ return -1;
++ }
++
++ while (fgets(line, sizeof(line), f))
++ {
++ if (!strchr(line, ':'))
++ continue;
++
++ if (!sscanf(line, " %127[^:]", ifname))
++ continue;
++
++ if (ignorelist_match(ignorelist, ifname))
++ continue;
++
++ if (strstr(ifname, "mon.") || strstr(ifname, ".sta") ||
++ strstr(ifname, "tmp.") || strstr(ifname, "wifi"))
++ continue;
++
++ iwinfo_process(ifname);
++ }
++
++ fclose(f);
++
++ return 0;
++}
++
++void module_register(void)
++{
++ plugin_register_config("iwinfo", iwinfo_config, config_keys, config_keys_num);
++ plugin_register_read("iwinfo", iwinfo_read);
++}
+--- a/src/types.db
++++ b/src/types.db
+@@ -308,6 +308,7 @@ snr value:GAUGE:0:U
+ spam_check value:GAUGE:0:U
+ spam_score value:GAUGE:U:U
+ spl value:GAUGE:U:U
++stations value:GAUGE:0:256
+ swap value:GAUGE:0:1099511627776
+ swap_io value:DERIVE:0:U
+ sysevent value:GAUGE:0:1
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1246,6 +1246,14 @@ irq_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+ irq_la_LIBADD = libignorelist.la
+ endif
+
++if BUILD_PLUGIN_IWINFO
++pkglib_LTLIBRARIES += iwinfo.la
++iwinfo_la_SOURCES = src/iwinfo.c
++#iwinfo_la_LDFLAGS = -module -avoid-version
++iwinfo_la_LDFLAGS = $(PLUGIN_LDFLAGS)
++iwinfo_la_LIBADD = -liwinfo libignorelist.la
++endif
++
+ if BUILD_PLUGIN_JAVA
+ pkglib_LTLIBRARIES += java.la
+ java_la_SOURCES = src/java.c
diff --git a/external/subpack/utils/collectd/patches/910-add-cake-qdisc-types.patch b/external/subpack/utils/collectd/patches/910-add-cake-qdisc-types.patch
new file mode 100644
index 0000000..a1d0cc9
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/910-add-cake-qdisc-types.patch
@@ -0,0 +1,20 @@
+--- a/src/types.db
++++ b/src/types.db
+@@ -359,6 +359,17 @@ vs_memory value:GAUGE:0:92
+ vs_processes value:GAUGE:0:65535
+ vs_threads value:GAUGE:0:65535
+
++qdisc_bytes value:DERIVE:0:U
++qdisc_drops value:DERIVE:0:U
++qdisc_backlog value:GAUGE:0:U
++
++qdisct_bytes value:DERIVE:0:U
++qdisct_thres value:GAUGE:0:U
++qdisct_drops drops:DERIVE:0:U, ecn:DERIVE:0:U, ack:DERIVE:0:U
++qdisct_backlog value:GAUGE:0:U
++qdisct_latencyus tg:GAUGE:0:U, pk:GAUGE:0:U, av:GAUGE:0:U, sp:GAUGE:0:U
++qdisct_flows sp:GAUGE:0:U, bu:GAUGE:0:U, un:GAUGE:0:U
++
+ #
+ # Legacy types
+ # (required for the v5 upgrade target)
diff --git a/external/subpack/utils/collectd/patches/920-backport-netlink-reg-noerror.patch b/external/subpack/utils/collectd/patches/920-backport-netlink-reg-noerror.patch
new file mode 100644
index 0000000..650fb47
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/920-backport-netlink-reg-noerror.patch
@@ -0,0 +1,37 @@
+From 5e600ae2ad370ddbb759e84ce55a7dfaa9a0bdd7 Mon Sep 17 00:00:00 2001
+From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
+Date: Sun, 6 Sep 2020 14:17:23 +0200
+Subject: [PATCH] src/netlink.c: remove REG_NOERROR
+
+REG_NOERROR is used since version 5.12.0 and
+https://github.com/collectd/collectd/commit/f7fd32e5209e188db7985a42054252fc4cbfe7c1
+
+However, REG_NOERROR is not defined by musl, even GNU regex do not
+mention REG_NOERROR, so just remove it to avoid the following build
+failure:
+
+src/netlink.c: In function 'check_ignorelist':
+src/netlink.c:243:51: error: 'REG_NOERROR' undeclared (first use in this function); did you mean 'REG_NOTBOL'?
+ if (regexec(i->rdevice, dev, 0, NULL, 0) != REG_NOERROR)
+ ^~~~~~~~~~~
+ REG_NOTBOL
+
+Fixes:
+ - http://autobuild.buildroot.org/results/cd4d75888b5259b028132dd224be34f69bcbb702
+
+Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
+---
+ src/netlink.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/src/netlink.c
++++ b/src/netlink.c
+@@ -240,7 +240,7 @@ static int check_ignorelist(const char *
+ for (ir_ignorelist_t *i = ir_ignorelist_head; i != NULL; i = i->next) {
+ #if HAVE_REGEX_H
+ if (i->rdevice != NULL) {
+- if (regexec(i->rdevice, dev, 0, NULL, 0) != REG_NOERROR)
++ if (regexec(i->rdevice, dev, 0, NULL, 0))
+ continue;
+ } else
+ #endif
diff --git a/external/subpack/utils/collectd/patches/930-dhcpleases-add-dhcpleases-plugin.patch b/external/subpack/utils/collectd/patches/930-dhcpleases-add-dhcpleases-plugin.patch
new file mode 100644
index 0000000..03b3902
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/930-dhcpleases-add-dhcpleases-plugin.patch
@@ -0,0 +1,172 @@
+From: Nick Hainke <vincent@systemli.org>
+Date: Mon, 7 Dec 2020 23:07:30 +0100
+Subject: [PATCH] dhcpleases: add dhcpleases plugin
+
+Changelog: dhcpleases: add plugin for counting current dhcp leases
+
+The plugin is useful for the Freifunk Community. Currently, we use
+the exec-plugin. With that dhcpleases plugin we have native collectd
+support to measure this important statistic.
+
+Signed-off-by: Nick Hainke <vincent@systemli.org>
+---
+ Makefile.am | 6 ++++
+ README | 3 ++
+ configure.ac | 2 ++
+ src/collectd.conf.in | 5 +++
+ src/dhcpleases.c | 83 ++++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 99 insertions(+)
+ create mode 100644 src/dhcpleases.c
+
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -963,6 +963,12 @@ df_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+ df_la_LIBADD = libignorelist.la libmount.la
+ endif
+
++if BUILD_PLUGIN_DHCPLEASES
++pkglib_LTLIBRARIES += dhcpleases.la
++dhcpleases_la_SOURCES = src/dhcpleases.c
++dhcpleases_la_LDFLAGS = $(PLUGIN_LDFLAGS)
++endif
++
+ if BUILD_PLUGIN_DISK
+ pkglib_LTLIBRARIES += disk.la
+ disk_la_SOURCES = src/disk.c
+--- a/README
++++ b/README
+@@ -106,6 +106,9 @@ Features
+ Disk utilization: Sectors read/written, number of read/write actions,
+ average time an IO-operation took to complete.
+
++ - dhcpleases
++ Collect number of current dhcp leases.
++
+ - dns
+ DNS traffic: Query types, response codes, opcodes and traffic/octets
+ transferred.
+--- a/configure.ac
++++ b/configure.ac
+@@ -7063,6 +7063,7 @@ AC_PLUGIN([curl_xml], [$plugi
+ AC_PLUGIN([dbi], [$with_libdbi], [General database statistics])
+ AC_PLUGIN([dcpmm], [$with_libpmwapi], [Intel(R) Optane(TM) DC Persistent Memory performance and health statistics])
+ AC_PLUGIN([df], [$plugin_df], [Filesystem usage statistics])
++AC_PLUGIN([dhcpleases], [yes], [DHCP Leases])
+ AC_PLUGIN([disk], [$plugin_disk], [Disk usage statistics])
+ AC_PLUGIN([dns], [$with_libpcap], [DNS traffic analysis])
+ AC_PLUGIN([dpdkevents], [$plugin_dpdkevents], [Events from DPDK])
+@@ -7512,6 +7513,7 @@ AC_MSG_RESULT([ curl_xml . . . . . .
+ AC_MSG_RESULT([ dbi . . . . . . . . . $enable_dbi])
+ AC_MSG_RESULT([ dcpmm . . . . . . . $enable_dcpmm])
+ AC_MSG_RESULT([ df . . . . . . . . . $enable_df])
++AC_MSG_RESULT([ dhcpleases. . . . . . $enable_dhcpleases])
+ AC_MSG_RESULT([ disk . . . . . . . . $enable_disk])
+ AC_MSG_RESULT([ dns . . . . . . . . . $enable_dns])
+ AC_MSG_RESULT([ dpdkevents. . . . . . $enable_dpdkevents])
+--- a/src/collectd.conf.in
++++ b/src/collectd.conf.in
+@@ -119,6 +119,7 @@
+ #@BUILD_PLUGIN_DBI_TRUE@LoadPlugin dbi
+ #@BUILD_PLUGIN_DCPMM_TRUE@LoadPlugin dcpmm
+ #@BUILD_PLUGIN_DF_TRUE@LoadPlugin df
++#@BUILD_PLUGIN_DHCPLEASES_TRUE@LoadPlugin dhcpleases
+ #@BUILD_PLUGIN_DISK_TRUE@LoadPlugin disk
+ #@BUILD_PLUGIN_DNS_TRUE@LoadPlugin dns
+ #@BUILD_PLUGIN_DPDKEVENTS_TRUE@LoadPlugin dpdkevents
+@@ -690,6 +691,10 @@
+ # SelectNumericQueryTypes true
+ #</Plugin>
+
++#<Plugin dhcpleases>
++# Path "/tmp/dhcp.leases"
++#</Plugin>
++
+ #<Plugin "dpdkevents">
+ # <EAL>
+ # Coremask "0x1"
+--- /dev/null
++++ b/src/dhcpleases.c
+@@ -0,0 +1,83 @@
++#include <errno.h>
++#include <stdio.h>
++
++#include "utils/common/common.h"
++
++#include "configfile.h"
++#include "plugin.h"
++
++static char *dhcp_lease_file;
++
++static const char *config_keys[] = {
++ "Path",
++};
++static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
++
++/* copied from ping.c plugin */
++static int config_set_string(const char *name, /* {{{ */
++ char **var, const char *value) {
++ char *tmp;
++
++ tmp = strdup(value);
++ if (tmp == NULL) {
++ ERROR("dhcpleases plugin: Setting `%s' to `%s' failed: strdup failed: %s", name,
++ value, STRERRNO);
++ return 1;
++ }
++
++ if (*var != NULL)
++ free(*var);
++ *var = tmp;
++ return 0;
++} /* }}} int config_set_string */
++
++static int dhcpleases_config(const char *key, const char *value) {
++ if (strcasecmp(key, "Path") == 0) {
++ int status = config_set_string(key, &dhcp_lease_file, value);
++ if (status != 0)
++ return status;
++ }
++ return 0;
++}
++
++static void dhcpleases_submit(gauge_t counter) {
++ value_list_t vl = VALUE_LIST_INIT;
++ value_t values[] = {
++ {.gauge = counter},
++ };
++
++ vl.values = values;
++ vl.values_len = STATIC_ARRAY_SIZE(values);
++
++ sstrncpy(vl.plugin, "dhcpleases", sizeof(vl.plugin));
++ sstrncpy(vl.type, "count", sizeof(vl.type));
++
++ plugin_dispatch_values(&vl);
++}
++
++static int dhcp_leases_read(void) {
++
++ FILE *fh;
++ char buffer[1024];
++ gauge_t count = 0;
++
++ if ((fh = fopen(dhcp_lease_file, "r")) == NULL) {
++ WARNING("interface plugin: fopen: %s", STRERRNO);
++ return -1;
++ }
++
++ while (fgets(buffer, 1024, fh) != NULL) {
++ count++;
++ }
++ fclose(fh);
++
++ dhcpleases_submit(count);
++
++ return 0;
++}
++
++void module_register(void) {
++ plugin_register_config("dhcpleases", dhcpleases_config, config_keys,
++ config_keys_num);
++ plugin_register_read("dhcpleases", dhcp_leases_read);
++}
diff --git a/external/subpack/utils/collectd/patches/931-snmp6-add-ipv6-statistics.patch b/external/subpack/utils/collectd/patches/931-snmp6-add-ipv6-statistics.patch
new file mode 100644
index 0000000..94bfbac
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/931-snmp6-add-ipv6-statistics.patch
@@ -0,0 +1,239 @@
+From: Nick Hainke <vincent@systemli.org>
+Date: Mon, 7 Dec 2020 19:29:54 +0100
+Subject: [PATCH] snmp6: add ipv6 statistics
+
+ChangeLog: snmp6 plugin: Add plugin for parsing IPv6 statistics
+
+We would like to have pure ipv6 interface statistics. To get them,
+we parse the snmp6 interface.
+
+Signed-off-by: Nick Hainke <vincent@systemli.org>
+---
+ Makefile.am | 8 +++
+ README | 4 ++
+ configure.ac | 2 +
+ src/collectd.conf.in | 6 ++
+ src/snmp6.c | 135 +++++++++++++++++++++++++++++++++++++++++++
+ src/types.db | 2 +
+ 6 files changed, 157 insertions(+)
+ create mode 100644 src/snmp6.c
+
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1964,6 +1964,14 @@ TESTS += test_plugin_snmp_agent
+
+ endif
+
++if BUILD_PLUGIN_SNMP6
++pkglib_LTLIBRARIES += snmp6.la
++snmp6_la_SOURCES = src/snmp6.c
++snmp6_la_CFLAGS = $(AM_CFLAGS)
++snmp6_la_LDFLAGS = $(PLUGIN_LDFLAGS)
++snmp6_la_LIBADD = libignorelist.la
++endif # BUILD_PLUGIN_SNMP6
++
+ if BUILD_PLUGIN_STATSD
+ pkglib_LTLIBRARIES += statsd.la
+ statsd_la_SOURCES = src/statsd.c
+--- a/README
++++ b/README
+@@ -422,6 +422,10 @@ Features
+ network devices such as switches, routers, thermometers, rack monitoring
+ servers, etc. See collectd-snmp(5).
+
++ - snmp6
++ Read values from SNMP6 (Simple Network Management Protocol). Supports pure
++ IPv6 interface statistics.
++
+ - statsd
+ Acts as a StatsD server, reading values sent over the network from StatsD
+ clients and calculating rates and other aggregates out of these values.
+--- a/configure.ac
++++ b/configure.ac
+@@ -7162,6 +7162,7 @@ AC_PLUGIN([slurm], [$with_
+ AC_PLUGIN([smart], [$plugin_smart], [SMART statistics])
+ AC_PLUGIN([snmp], [$with_libnetsnmp], [SNMP querying plugin])
+ AC_PLUGIN([snmp_agent], [$with_libnetsnmpagent], [SNMP agent plugin])
++AC_PLUGIN([snmp6], [yes], [IPv6 Interface traffic statistics via snmp6])
+ AC_PLUGIN([statsd], [yes], [StatsD plugin])
+ AC_PLUGIN([swap], [$plugin_swap], [Swap usage statistics])
+ AC_PLUGIN([synproxy], [$plugin_synproxy], [Synproxy stats plugin])
+@@ -7611,6 +7612,7 @@ AC_MSG_RESULT([ slurm . . . . . . . .
+ AC_MSG_RESULT([ smart . . . . . . . . $enable_smart])
+ AC_MSG_RESULT([ snmp . . . . . . . . $enable_snmp])
+ AC_MSG_RESULT([ snmp_agent . . . . . $enable_snmp_agent])
++AC_MSG_RESULT([ snmp6 . . . . . . . . $enable_snmp6])
+ AC_MSG_RESULT([ statsd . . . . . . . $enable_statsd])
+ AC_MSG_RESULT([ swap . . . . . . . . $enable_swap])
+ AC_MSG_RESULT([ synproxy . . . . . . $enable_synproxy])
+--- a/src/collectd.conf.in
++++ b/src/collectd.conf.in
+@@ -207,6 +207,7 @@
+ #@BUILD_PLUGIN_SMART_TRUE@LoadPlugin smart
+ #@BUILD_PLUGIN_SNMP_TRUE@LoadPlugin snmp
+ #@BUILD_PLUGIN_SNMP_AGENT_TRUE@LoadPlugin snmp_agent
++#@BUILD_PLUGIN_SNMP6_TRUE@LoadPlugin snmp6
+ #@BUILD_PLUGIN_STATSD_TRUE@LoadPlugin statsd
+ #@BUILD_PLUGIN_SWAP_TRUE@LoadPlugin swap
+ #@BUILD_PLUGIN_SYSEVENT_TRUE@LoadPlugin sysevent
+@@ -1718,6 +1719,11 @@
+ # </Table>
+ #</Plugin>
+
++#<Plugin snmp6>
++# Interface "eth0"
++# IgnoreSelected false
++#</Plugin>
++
+ #<Plugin statsd>
+ # Host "::"
+ # Port "8125"
+--- /dev/null
++++ b/src/snmp6.c
+@@ -0,0 +1,135 @@
++/*
++ This Plugin is based opn the interface.c Plugin.
++*/
++#include <stdint.h>
++#include <stdlib.h>
++#include <string.h>
++#include <errno.h>
++#include <stdbool.h>
++#include <stdio.h>
++
++#include <net/if.h>
++#include <sys/types.h>
++#include <ifaddrs.h>
++
++#include "plugin.h"
++#include "utils/cmds/putval.h"
++#include "utils/common/common.h"
++#include "utils/ignorelist/ignorelist.h"
++
++static const char *config_keys[] = {
++ "Interface",
++ "IgnoreSelected",
++};
++static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
++
++static ignorelist_t *ignorelist;
++
++static int snmp6_config(const char *key, const char *value) {
++ if (ignorelist == NULL)
++ ignorelist = ignorelist_create(/* invert = */ 1);
++
++ if (strcasecmp(key, "Interface") == 0) {
++ ignorelist_add(ignorelist, value);
++ } else if (strcasecmp(key, "IgnoreSelected") == 0) {
++ int invert = 1;
++ if (IS_TRUE(value))
++ invert = 0;
++ ignorelist_set_invert(ignorelist, invert);
++ }
++
++ return 0;
++}
++
++/* Copied from interface.c */
++static void snmp6_submit(const char *dev, const char *type, derive_t rx,
++ derive_t tx) {
++ value_list_t vl = VALUE_LIST_INIT;
++ value_t values[] = {
++ {.derive = rx},
++ {.derive = tx},
++ };
++
++ vl.values = values;
++ vl.values_len = STATIC_ARRAY_SIZE(values);
++ sstrncpy(vl.plugin, "snmp6", sizeof(vl.plugin));
++ sstrncpy(vl.plugin_instance, dev, sizeof(vl.plugin_instance));
++ sstrncpy(vl.type, type, sizeof(vl.type));
++
++ plugin_dispatch_values(&vl);
++} /* void if_submit */
++
++int snmp_read(char *ifname) {
++ FILE *fh;
++ char buffer[1024];
++ char *fields[2];
++ int numfields;
++ int currline = 0;
++ derive_t data[76];
++ char procpath[1024];
++ int offset = 0;
++
++ if (ignorelist_match(ignorelist, ifname) != 0)
++ return 0;
++
++ if (strncmp("all", ifname, strlen("all")) == 0) {
++ snprintf(procpath, 1024, "/proc/net/snmp6");
++ offset = 1;
++ } else {
++ snprintf(procpath, 1024, "/proc/net/dev_snmp6/%s", ifname);
++ }
++
++ if ((fh = fopen(procpath, "r")) == NULL) {
++ WARNING("snmp6 plugin: try opening %s : fopen: %s", procpath, STRERRNO);
++ return -1;
++ }
++
++ while (fgets(buffer, 1024, fh) != NULL) {
++ numfields = strsplit(buffer, fields, 2);
++
++ if (numfields < 2)
++ return -1;
++
++ data[currline++] = atoll(fields[1]);
++ }
++
++ fclose(fh);
++
++ if (currline < 28) {
++ return -1;
++ }
++
++ snmp6_submit(ifname, "if_octets", data[23 - offset], data[24 - offset]);
++ snmp6_submit(ifname, "if_octets_mcast", data[25 - offset], data[26 - offset]);
++ snmp6_submit(ifname, "if_octets_bcast", data[27 - offset], data[28 - offset]);
++ return 0;
++}
++
++int read_all_interfaces(void) {
++#ifndef HAVE_IFADDRS_H
++ return -1;
++#else
++
++ // getifaddrs is not working all the time (e.g. wireguard interfaces)
++ // instead we use if_nameindex() syscall as suggested in:
++ // https://stackoverflow.com/a/45796495/8474618
++ struct if_nameindex *if_nidxs, *intf;
++
++ if_nidxs = if_nameindex();
++
++ if (if_nidxs != NULL) {
++ for (intf = if_nidxs; intf->if_index != 0 || intf->if_name != NULL; intf++) {
++ snmp_read(intf->if_name);
++ }
++ if_freenameindex(if_nidxs);
++ }
++
++ snmp_read("all");
++ return 0;
++#endif
++}
++
++void module_register(void) {
++ plugin_register_config("snmp6", snmp6_config, config_keys, config_keys_num);
++ plugin_register_read("snmp6", read_all_interfaces);
++} /* void module_register */
+--- a/src/types.db
++++ b/src/types.db
+@@ -132,6 +132,8 @@ if_dropped rx:DERIVE:0:U, t
+ if_errors rx:DERIVE:0:U, tx:DERIVE:0:U
+ if_multicast value:DERIVE:0:U
+ if_octets rx:DERIVE:0:U, tx:DERIVE:0:U
++if_octets_mcast rx:DERIVE:0:U, tx:DERIVE:0:U
++if_octets_bcast rx:DERIVE:0:U, tx:DERIVE:0:U
+ if_packets rx:DERIVE:0:U, tx:DERIVE:0:U
+ if_rx_dropped value:DERIVE:0:U
+ if_rx_errors value:DERIVE:0:U
diff --git a/external/subpack/utils/collectd/patches/932-add-ipstatistics.patch b/external/subpack/utils/collectd/patches/932-add-ipstatistics.patch
new file mode 100644
index 0000000..e8dd6c5
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/932-add-ipstatistics.patch
@@ -0,0 +1,160 @@
+--- /dev/null
++++ b/src/ipstatistics.c
+@@ -0,0 +1,104 @@
++/*
++ This Plugin is based opn the interface.c Plugin.
++*/
++#include <errno.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <ifaddrs.h>
++#include <net/if.h>
++#include <sys/types.h>
++
++#include "plugin.h"
++#include "utils/cmds/putval.h"
++#include "utils/common/common.h"
++
++/* Copied from interface.c */
++static void ipstatistics_submit(const char *type, derive_t ip4rx,
++ derive_t ip4tx, derive_t ip6rx, derive_t ip6tx) {
++ value_list_t vl = VALUE_LIST_INIT;
++ value_t values[] = {
++ {.derive = ip4rx},
++ {.derive = ip4tx},
++ {.derive = ip6rx},
++ {.derive = ip6tx}
++ };
++
++ vl.values = values;
++ vl.values_len = STATIC_ARRAY_SIZE(values);
++ sstrncpy(vl.plugin, "ipstatistics", sizeof(vl.plugin));
++ sstrncpy(vl.plugin_instance, "all", sizeof(vl.plugin_instance));
++ sstrncpy(vl.type, type, sizeof(vl.type));
++
++ plugin_dispatch_values(&vl);
++} /* void if_submit */
++
++int ipstatistics_read() {
++ FILE *fh;
++ char buffer[1024];
++ char *fields[19];
++ int numfields;
++
++ derive_t ip4_in = 0;
++ derive_t ip4_out = 0;
++ derive_t ip6_in = 0;
++ derive_t ip6_out = 0;
++
++ if ((fh = fopen("/proc/net/snmp6", "r")) == NULL) {
++ WARNING("ipstatistics plugin: try opening %s : fopen: %s", "/proc/net/snmp6",
++ STRERRNO);
++ return -1;
++ }
++
++ while (fgets(buffer, 1024, fh) != NULL) {
++ numfields = strsplit(buffer, fields, 2);
++
++ if (numfields < 2)
++ return -1;
++
++ if (strcasecmp(fields[0], "Ip6OutOctets") == 0) {
++ ip6_out = atoll(fields[1]);
++ }
++
++ if (strcasecmp(fields[0], "Ip6InOctets") == 0) {
++ ip6_in = atoll(fields[1]);
++ }
++ }
++
++ fclose(fh);
++
++ if ((fh = fopen("/proc/net/netstat", "r")) == NULL) {
++ WARNING("ipstatistics plugin: try opening %s : fopen: %s", "/proc/net/netstat",
++ STRERRNO);
++ return -1;
++ }
++
++ int count_ipext = 0;
++ while (fgets(buffer, 1024, fh) != NULL) {
++ numfields = strsplit(buffer, fields, 19);
++
++ if (numfields < 8)
++ return -1;
++
++ if (strcasecmp(fields[0], "IpExt:") == 0) {
++ count_ipext++;
++ if (count_ipext == 2) {
++ ip4_in = atoll(fields[7]);
++ ip4_out = atoll(fields[8]);
++ }
++ }
++ }
++
++ fclose(fh);
++
++ ipstatistics_submit("ip_stats_octets", ip4_in, ip4_out, ip6_in, ip6_out);
++ return 0;
++}
++
++void module_register(void) {
++ plugin_register_read("ipstatistics", ipstatistics_read);
++} /* void module_register */
++
+--- a/src/types.db
++++ b/src/types.db
+@@ -148,6 +148,7 @@ invocations value:DERIVE:0:U
+ io_octets rx:DERIVE:0:U, tx:DERIVE:0:U
+ io_ops read:DERIVE:0:U, write:DERIVE:0:U
+ io_packets rx:DERIVE:0:U, tx:DERIVE:0:U
++ip_stats_octets ip4rx:DERIVE:0:U, ip4tx:DERIVE:0:U, ip6rx:DERIVE:0:U, ip6tx:DERIVE:0:U
+ ipc value:GAUGE:0:U
+ ipt_bytes value:DERIVE:0:U
+ ipt_packets value:DERIVE:0:U
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1239,6 +1239,12 @@ ipstats_la_SOURCES = src/ipstats.c
+ ipstats_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+ endif
+
++if BUILD_PLUGIN_IPSTATISTICS
++pkglib_LTLIBRARIES += ipstatistics.la
++ipstatistics_la_SOURCES = src/ipstatistics.c
++ipstatistics_la_LDFLAGS = $(PLUGIN_LDFLAGS)
++endif
++
+ if BUILD_PLUGIN_IPVS
+ pkglib_LTLIBRARIES += ipvs.la
+ ipvs_la_SOURCES = src/ipvs.c
+--- a/configure.ac
++++ b/configure.ac
+@@ -7091,6 +7091,7 @@ AC_PLUGIN([ipc], [$plugi
+ AC_PLUGIN([ipmi], [$plugin_ipmi], [IPMI sensor statistics])
+ AC_PLUGIN([iptables], [$with_libiptc], [IPTables rule counters])
+ AC_PLUGIN([ipstats], [$plugin_ipstats], [IP packet statistics])
++AC_PLUGIN([ipstatistics], [yes], [IP4 and IP6 statistics])
+ AC_PLUGIN([ipvs], [$plugin_ipvs], [IPVS connection statistics])
+ AC_PLUGIN([irq], [$plugin_irq], [IRQ statistics])
+ AC_PLUGIN([iwinfo], [$with_iwinfo], [Common iwinfo wireless statistics])
+@@ -7542,6 +7543,7 @@ AC_MSG_RESULT([ ipc . . . . . . . . .
+ AC_MSG_RESULT([ ipmi . . . . . . . . $enable_ipmi])
+ AC_MSG_RESULT([ iptables . . . . . . $enable_iptables])
+ AC_MSG_RESULT([ ipstats . . . . . . . $enable_ipstats])
++AC_MSG_RESULT([ ipstatistics . . . . $enable_ipstatistics])
+ AC_MSG_RESULT([ ipvs . . . . . . . . $enable_ipvs])
+ AC_MSG_RESULT([ irq . . . . . . . . . $enable_irq])
+ AC_MSG_RESULT([ iwinfo . . . . . . . $enable_iwinfo])
+--- a/src/collectd.conf.in
++++ b/src/collectd.conf.in
+@@ -145,6 +145,7 @@
+ #@BUILD_PLUGIN_IPC_TRUE@LoadPlugin ipc
+ #@BUILD_PLUGIN_IPMI_TRUE@LoadPlugin ipmi
+ #@BUILD_PLUGIN_IPSTATS_TRUE@LoadPlugin ipstats
++#@BUILD_PLUGIN_IPSTATISTICS_TRUE@LoadPlugin ipstatistics
+ #@BUILD_PLUGIN_IPTABLES_TRUE@LoadPlugin iptables
+ #@BUILD_PLUGIN_IPVS_TRUE@LoadPlugin ipvs
+ #@BUILD_PLUGIN_IRQ_TRUE@LoadPlugin irq
diff --git a/external/subpack/utils/collectd/patches/934-ubi-prepare-read-for-percent.patch b/external/subpack/utils/collectd/patches/934-ubi-prepare-read-for-percent.patch
new file mode 100644
index 0000000..0277863
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/934-ubi-prepare-read-for-percent.patch
@@ -0,0 +1,66 @@
+--- a/src/ubi.c
++++ b/src/ubi.c
+@@ -84,9 +84,8 @@ static void ubi_submit(const char *dev_n
+ plugin_dispatch_values(&vl);
+ } /* void ubi_submit */
+
+-static int ubi_read_dev_attr(const char *dev_name, const char *attr) {
++static int ubi_read_dev_attr(const char *dev_name, const char *attr, int *value) {
+ FILE *f;
+- int val;
+ char
+ str[sizeof(SYS_PATH) + strlen(dev_name) + sizeof("/") + strlen(attr) + 1];
+ int n;
+@@ -98,7 +97,7 @@ static int ubi_read_dev_attr(const char
+ return -1;
+ }
+
+- n = fscanf(f, "%d", &val);
++ n = fscanf(f, "%d", value);
+ fclose(f);
+
+ if (n != 1) {
+@@ -106,17 +105,39 @@ static int ubi_read_dev_attr(const char
+ return -1;
+ }
+
+- ubi_submit(dev_name, attr, (gauge_t)val);
+-
+ return 0;
+ } /* int ubi_read_dev_attr */
+
+ static inline int ubi_read_dev_bad_count(const char *dev_name) {
+- return ubi_read_dev_attr(dev_name, DEV_BAD_COUNT);
++ int ret;
++ int value;
++
++ ret = ubi_read_dev_attr(dev_name, DEV_BAD_COUNT, &value);
++
++ if (ret != 0) {
++ ERROR(PLUGIN_NAME " : Unable to read bat_peb_count");
++ return -1;
++ }
++
++ ubi_submit(dev_name, DEV_BAD_COUNT, (gauge_t)value);
++
++ return 0;
+ } /* int ubi_read_dev_bad_count */
+
+ static inline int ubi_read_max_ec(const char *dev_name) {
+- return ubi_read_dev_attr(dev_name, MAXIMUM_ERASE);
++ int ret;
++ int value;
++
++ ret = ubi_read_dev_attr(dev_name, MAXIMUM_ERASE, &value);
++
++ if (ret != 0) {
++ ERROR(PLUGIN_NAME " : Unable to read max_ec");
++ return -1;
++ }
++
++ ubi_submit(dev_name, MAXIMUM_ERASE, (gauge_t)value);
++
++ return 0;
+ } /* int ubi_read_max_ec */
+
+ static int ubi_read(void) {
diff --git a/external/subpack/utils/collectd/patches/935-ubi-add-percent.patch b/external/subpack/utils/collectd/patches/935-ubi-add-percent.patch
new file mode 100644
index 0000000..4736b85
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/935-ubi-add-percent.patch
@@ -0,0 +1,56 @@
+--- a/src/ubi.c
++++ b/src/ubi.c
+@@ -35,6 +35,9 @@
+ #define DEV_BAD_COUNT \
+ "bad_peb_count" // Count of bad physical eraseblocks on the underlying MTD
+ // device.
++// Value reserved for bad block
++#define DEV_RESERVED_BAD_BLOCK "reserved_for_bad"
++
+ #define MAXIMUM_ERASE "max_ec" // Current maximum erase counter value
+
+ /*
+@@ -140,6 +143,35 @@ static inline int ubi_read_max_ec(const
+ return 0;
+ } /* int ubi_read_max_ec */
+
++static inline int ubi_read_percent(const char *dev_name) {
++ int ret;
++ int bcount;
++ int bblock;
++
++ ret = ubi_read_dev_attr(dev_name, DEV_BAD_COUNT, &bcount);
++
++ if (ret != 0) {
++ ERROR(PLUGIN_NAME " : Unable to read bad_peb_count");
++ return -1;
++ }
++
++ ret = ubi_read_dev_attr(dev_name, DEV_RESERVED_BAD_BLOCK, &bblock);
++
++ if (ret != 0) {
++ ERROR(PLUGIN_NAME " : Unable to read reserved_for_bad");
++ return -1;
++ }
++
++ if (bblock == 0) {
++ ERROR(PLUGIN_NAME " : Percentage value cannot be determined (reserved_for_bad = 0)");
++ return -2;
++ }
++
++ ubi_submit(dev_name, "percent", (gauge_t)((float_t)bcount / (float_t)bblock * 100.0));
++
++ return 0;
++} /* int ubi_read_percent */
++
+ static int ubi_read(void) {
+ DIR *dir;
+ struct dirent *dirent;
+@@ -155,6 +187,7 @@ static int ubi_read(void) {
+
+ ubi_read_dev_bad_count(dirent->d_name);
+ ubi_read_max_ec(dirent->d_name);
++ ubi_read_percent(dirent->d_name);
+ }
+
+ closedir(dir);
diff --git a/external/subpack/utils/collectd/patches/941-Check-udev_enumerate_scan_devices-return-value.patch b/external/subpack/utils/collectd/patches/941-Check-udev_enumerate_scan_devices-return-value.patch
new file mode 100644
index 0000000..176c8f4
--- /dev/null
+++ b/external/subpack/utils/collectd/patches/941-Check-udev_enumerate_scan_devices-return-value.patch
@@ -0,0 +1,61 @@
+From 289f58c9c96d5478cf200f7a3e62b82e86b12d32 Mon Sep 17 00:00:00 2001
+From: Florian Eckert <fe@dev.tdt.de>
+Date: Tue, 15 Mar 2022 14:56:19 +0100
+Subject: [PATCH] Check udev_enumerate_scan_devices return value
+
+This change checks the return value of the function and cancels the call
+if the returned integer is not greater than or equal to 0.
+
+Signed-off-by: Florian Eckert <fe@dev.tdt.de>
+---
+ src/smart.c | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+--- a/src/smart.c
++++ b/src/smart.c
+@@ -104,6 +104,7 @@ static int create_ignorelist_by_serial(i
+ struct udev_enumerate *enumerate;
+ struct udev_list_entry *devices, *dev_list_entry;
+ struct udev_device *dev;
++ int r;
+
+ if (ignorelist_by_serial == NULL)
+ ignorelist_by_serial = ignorelist_create(invert_ignorelist);
+@@ -127,7 +128,13 @@ static int create_ignorelist_by_serial(i
+ }
+ udev_enumerate_add_match_subsystem(enumerate, "block");
+ udev_enumerate_add_match_property(enumerate, "DEVTYPE", "disk");
+- udev_enumerate_scan_devices(enumerate);
++
++ r = udev_enumerate_scan_devices(enumerate);
++ if (r < 0) {
++ WARNING("smart plugin: udev scan devices failed");
++ return -1;
++ }
++
+ devices = udev_enumerate_get_list_entry(enumerate);
+ if (devices == NULL) {
+ ERROR("udev returned an empty list deviecs");
+@@ -597,6 +604,7 @@ static int smart_read(void) {
+ struct udev_enumerate *enumerate;
+ struct udev_list_entry *devices, *dev_list_entry;
+ struct udev_device *dev;
++ int r;
+
+ /* Use udev to get a list of disks */
+ handle_udev = udev_new();
+@@ -611,7 +619,13 @@ static int smart_read(void) {
+ }
+ udev_enumerate_add_match_subsystem(enumerate, "block");
+ udev_enumerate_add_match_property(enumerate, "DEVTYPE", "disk");
+- udev_enumerate_scan_devices(enumerate);
++
++ r = udev_enumerate_scan_devices(enumerate);
++ if (r < 0) {
++ WARNING("smart plugin: udev scan devices failed");
++ return -1;
++ }
++
+ devices = udev_enumerate_get_list_entry(enumerate);
+ if (devices == NULL) {
+ ERROR("udev returned an empty list deviecs");
diff --git a/external/subpack/utils/conmon/Makefile b/external/subpack/utils/conmon/Makefile
new file mode 100644
index 0000000..11afc5e
--- /dev/null
+++ b/external/subpack/utils/conmon/Makefile
@@ -0,0 +1,42 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=conmon
+PKG_VERSION:=2.1.10
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/containers/$(PKG_NAME)/archive/v$(PKG_VERSION)
+PKG_HASH:=455fabcbd4a5a5dc5e05374a71b62dc0b08ee865c2ba398e9dc9acac1ea1836a
+
+PKG_MAINTAINER:=Oskari Rauta <oskari.rauta@gmail.com>
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_DEPENDS:=libseccomp
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+include $(INCLUDE_DIR)/meson.mk
+
+define Package/conmon
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Podman conmon
+ URL:=https://podman.io
+ DEPENDS:=@!arc +glib2 $(INTL_DEPENDS) $(ICONV_DEPENDS)
+endef
+
+define Package/conmon/description
+ An OCI container runtime monitor.
+
+ Conmon is a monitoring program and communication tool between
+ a container manager (like Podman or CRI-O) and an OCI runtime
+ (like runc or crun) for a single container.
+endef
+
+define Package/conmon/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/libexec/podman/conmon $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,conmon))
diff --git a/external/subpack/utils/conmon/patches/010-remove-libdl-dep.patch b/external/subpack/utils/conmon/patches/010-remove-libdl-dep.patch
new file mode 100644
index 0000000..bcfb4d0
--- /dev/null
+++ b/external/subpack/utils/conmon/patches/010-remove-libdl-dep.patch
@@ -0,0 +1,11 @@
+--- a/meson.build
++++ b/meson.build
+@@ -90,7 +90,7 @@ executable('conmon',
+ 'src/utils.h',
+ 'src/seccomp_notify.c',
+ 'src/seccomp_notify.h'],
+- dependencies : [glib, libdl, sd_journal, seccomp],
++ dependencies : [glib, sd_journal, seccomp],
+ install : true,
+ install_dir : join_paths(get_option('libexecdir'), 'podman'),
+ )
diff --git a/external/subpack/utils/containerd/Makefile b/external/subpack/utils/containerd/Makefile
new file mode 100644
index 0000000..138f881
--- /dev/null
+++ b/external/subpack/utils/containerd/Makefile
@@ -0,0 +1,61 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=containerd
+PKG_VERSION:=1.6.6
+PKG_RELEASE:=1
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/containerd/containerd/tar.gz/v${PKG_VERSION}?
+PKG_HASH:=27afb673c20d53aa5c31aec07b38eb7e4dc911e7e1f0c76fac9513bbf070bd24
+
+PKG_MAINTAINER:=Gerard Ryan <G.M0N3Y.2503@gmail.com>
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/containerd/containerd
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/containerd
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=containerd container runtime
+ URL:=https://containerd.io/
+ DEPENDS:=$(GO_ARCH_DEPENDS) +btrfs-progs +runc
+ MENU:=1
+endef
+
+define Package/containerd/description
+An industry-standard container runtime with an emphasis on simplicity, robustness and portability
+endef
+
+GO_PKG_BUILD_VARS += GO111MODULE=auto
+GO_PKG_INSTALL_ALL:=1
+MAKE_PATH:=$(GO_PKG_WORK_DIR_NAME)/build/src/$(GO_PKG)
+MAKE_VARS += $(GO_PKG_VARS)
+MAKE_FLAGS += \
+ VERSION=$(PKG_VERSION) \
+ REVISION=$(PKG_SOURCE_VERSION) \
+ PREFIX=""
+
+ifeq ($(CONFIG_SELINUX),y)
+MAKE_FLAGS += BUILDTAGS='selinux'
+else
+MAKE_FLAGS += BUILDTAGS=''
+endif
+
+# Reset golang-package.mk overrides so we can use the Makefile
+Build/Compile=$(call Build/Compile/Default)
+
+define Package/containerd/install
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/bin/{ctr,containerd,containerd-stress,containerd-shim,containerd-shim-runc-v1,containerd-shim-runc-v2} $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,containerd))
diff --git a/external/subpack/utils/coremark/Makefile b/external/subpack/utils/coremark/Makefile
new file mode 100644
index 0000000..06a05c8
--- /dev/null
+++ b/external/subpack/utils/coremark/Makefile
@@ -0,0 +1,84 @@
+#
+# Copyright (C) 2018 Lim Guo Wei
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=coremark
+PKG_SOURCE_DATE:=2023-01-25
+PKG_SOURCE_VERSION:=d5fad6bd094899101a4e5fd53af7298160ced6ab
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_DATE).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/eembc/coremark/tar.gz/$(PKG_SOURCE_VERSION)?
+PKG_HASH:=76f3b98fc940d277521023dc6e106551ef4a2180fa4c3da8cd5bf933aa494ef2
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_SOURCE_VERSION)
+
+PKG_MAINTAINER:=Lim Guo Wei <limguowei@gmail.com> \
+ Aleksander Jan Bajkowski <olek2@wp.pl>
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE.md
+
+PKG_BUILD_FLAGS:=no-mips16 lto
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/coremark
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=CoreMark Embedded Microprocessor Benchmark
+ URL:=https://github.com/eembc/coremark
+endef
+
+define Package/coremark/description
+ Embedded Microprocessor Benchmark
+endef
+
+define Package/coremark/config
+ config COREMARK_OPTIMIZE_O3
+ bool "Use all optimizations (-O3)"
+ depends on PACKAGE_coremark
+ default y
+ help
+ This enables additional optmizations using the -O3 compilation flag.
+
+ config COREMARK_ENABLE_MULTITHREADING
+ bool "Enable multithreading support"
+ depends on PACKAGE_coremark
+ default n
+ help
+ This enables multithreading support
+
+ config COREMARK_NUMBER_OF_THREADS
+ int "Number of threads"
+ depends on COREMARK_ENABLE_MULTITHREADING
+ default 2
+ help
+ Number of threads to run in parallel
+endef
+
+ifeq ($(CONFIG_COREMARK_OPTIMIZE_O3),y)
+ TARGET_CFLAGS := $(filter-out -O%,$(TARGET_CFLAGS)) -O3
+endif
+
+ifeq ($(CONFIG_COREMARK_ENABLE_MULTITHREADING),y)
+ EXTRA_CFLAGS := -DMULTITHREAD=$(CONFIG_COREMARK_NUMBER_OF_THREADS) -DUSE_PTHREAD
+endif
+
+define Build/Compile
+ $(SED) 's|EXE = .exe|EXE =|' $(PKG_BUILD_DIR)/posix/core_portme.mak
+ mkdir $(PKG_BUILD_DIR)/$(ARCH)
+ $(CP) -r $(PKG_BUILD_DIR)/linux/* $(PKG_BUILD_DIR)/$(ARCH)
+ $(MAKE) -C $(PKG_BUILD_DIR) PORT_DIR=$(ARCH) $(MAKE_FLAGS) \
+ PORT_CFLAGS="$(TARGET_CFLAGS)" XCFLAGS="$(EXTRA_CFLAGS)" compile
+endef
+
+define Package/coremark/install
+ $(INSTALL_DIR) $(1)/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/coremark $(1)/bin/
+endef
+
+$(eval $(call BuildPackage,coremark))
diff --git a/external/subpack/utils/coreutils/Makefile b/external/subpack/utils/coreutils/Makefile
new file mode 100644
index 0000000..620707b
--- /dev/null
+++ b/external/subpack/utils/coreutils/Makefile
@@ -0,0 +1,153 @@
+#
+# Copyright (C) 2008-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=coreutils
+PKG_VERSION:=9.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/coreutils
+PKG_HASH:=adbcfcfe899235b71e8768dcf07cd532520b7f54f9a8064843f8d199a904bbaa
+
+PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:gnu:coreutils
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+COREUTILS_APPLETS := \
+ base32 base64 basename basenc b2sum cat chcon chgrp chmod chown chroot \
+ cksum comm cp csplit cut date dd df dir dircolors dirname du echo env \
+ expand expr factor false fmt fold groups head hostid id install join \
+ kill link ln logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl \
+ nohup nproc numfmt od paste pathchk pinky pr printenv printf ptx pwd \
+ readlink realpath rm rmdir runcon seq sha1sum sha224sum sha256sum \
+ sha384sum sha512sum shred shuf sleep sort split stat stdbuf stty sum \
+ sync tac tail tee test timeout touch tr true truncate tsort tty uname \
+ unexpand uniq unlink uptime users vdir wc who whoami yes
+
+DIR_BIN := \
+ base64 cat chgrp chmod chown cp date dd df echo false kill link ln ls \
+ mkdir mknod mktemp mv nice printenv pwd rm rmdir sleep stat stty sync \
+ touch true uname
+
+DIR_USR_BIN := \
+ basename chcon cksum comm cut dirname du env expand expr factor fold \
+ groups head hostid id install logname md5sum mkfifo nl nohup nproc od \
+ paste printf readlink realpath runcon seq sha1sum sha256sum sha512sum \
+ shred shuf sort split sum tac tail tee test timeout tr truncate tty \
+ unexpand uniq unlink uptime users wc who whoami yes
+
+DIR_USR_SBIN := \
+ chroot
+
+# BusyBox does not provide these yet
+DIR_OTHERS := \
+ base32 b2sum basenc csplit dir dircolors fmt join numfmt pathchk pinky \
+ pr ptx sha224sum sha384sum stdbuf tsort vdir
+
+$(eval $(foreach a,$(DIR_BIN),ALTS_$(a):=300:/bin/$(a):/usr/libexec/$(a)-coreutils$(newline)))
+$(eval $(foreach a,$(DIR_USR_BIN),ALTS_$(a):=300:/usr/bin/$(a):/usr/libexec/$(a)-coreutils$(newline)))
+$(eval $(foreach a,$(DIR_USR_SBIN),ALTS_$(a):=300:/usr/sbin/$(a):/usr/libexec/$(a)-coreutils$(newline)))
+
+DEPENDS_sort = +libpthread
+DEPENDS_timeout = +librt
+DEPENDS_expr = +libgmp
+DEPENDS_factor = +libgmp
+DEPENDS_cp = +libacl
+DEPENDS_dir = +libacl +libcap
+DEPENDS_install = +libacl
+DEPENDS_ls = +libacl +libcap
+DEPENDS_mv = +libacl
+DEPENDS_vdir = +libacl +libcap
+
+FILES_stdbuf := usr/lib/coreutils/libstdbuf.so
+
+define Package/coreutils/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=The GNU core utilities
+ URL:=http://www.gnu.org/software/coreutils/
+endef
+
+define Package/coreutils
+ $(call Package/coreutils/Default)
+ TITLE:=The GNU core utilities
+ MENU:=1
+endef
+
+define Package/coreutils/description
+ Full versions of standard GNU utilities. If an equivalent Busybox applet is
+ available, you should consider compiling that instead as Busybox applets are
+ usually smaller, at the expense of reduced functionality.
+endef
+
+define GenPlugin
+ define Package/$(1)
+ $(call Package/coreutils/Default)
+ DEPENDS:=coreutils $(DEPENDS_$(2))
+ TITLE:=Utility $(2) from the GNU core utilities
+ ALTERNATIVES:=$(ALTS_$(2))
+ endef
+
+ define Package/$(1)/description
+ Full version of standard GNU $(2) utility.
+ endef
+endef
+
+$(foreach a,$(COREUTILS_APPLETS),$(eval $(call GenPlugin,coreutils-$(a),$(a))))
+
+CONFIGURE_VARS += \
+ gl_cv_func_mbrtowc_incomplete_state=yes \
+ gl_cv_func_mbrtowc_retval=yes \
+ gl_cv_func_wcrtomb_retval=yes \
+ ac_cv_header_selinux_context_h=no \
+ ac_cv_header_selinux_flash_h=no \
+ ac_cv_header_selinux_selinux_h=no \
+ ac_cv_search_setfilecon=no
+
+CONFIGURE_ARGS += \
+ --disable-xattr \
+ --enable-install-program=su \
+ --enable-threads=posix \
+ --enable-acl \
+ --disable-assert \
+ --disable-rpath \
+ --disable-libsmack \
+ --enable-libcap \
+ --without-linux-crypto \
+ --without-openssl \
+ --$(if $(CONFIG_USE_MUSL),with,without)-included-regex \
+ --without-selinux \
+ --with-gmp
+
+define Package/coreutils/install
+ true
+endef
+
+define BuildPlugin
+ define Package/$(1)/install
+ $(INSTALL_DIR) $$(1)/usr/$(if $(ALTS_$(2)),libexec,bin)
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/$(2) $$(1)/usr/$(if $(ALTS_$(2)),libexec/$(2)-coreutils,bin/$(2))
+ $(foreach f,$(FILES_$(2)),
+ $(INSTALL_DIR) $$(1)/$(dir $(f))
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/$(f) $$(1)/$(f)
+ )
+ endef
+
+ $$(eval $$(call BuildPackage,$(1)))
+endef
+
+$(eval $(call BuildPackage,coreutils))
+
+$(foreach a,$(COREUTILS_APPLETS),$(eval $(call BuildPlugin,coreutils-$(a),$(a))))
diff --git a/external/subpack/utils/coreutils/patches/001-no_docs_man_tests.patch b/external/subpack/utils/coreutils/patches/001-no_docs_man_tests.patch
new file mode 100644
index 0000000..2bcd8fc
--- /dev/null
+++ b/external/subpack/utils/coreutils/patches/001-no_docs_man_tests.patch
@@ -0,0 +1,93 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -17,7 +17,7 @@
+
+ ALL_RECURSIVE_TARGETS =
+
+-SUBDIRS = po . gnulib-tests
++SUBDIRS = po
+
+ EXTRA_DIST = \
+ .mailmap \
+@@ -211,6 +211,3 @@ AM_CPPFLAGS = -Ilib -I$(top_srcdir)/lib
+
+ include $(top_srcdir)/lib/local.mk
+ include $(top_srcdir)/src/local.mk
+-include $(top_srcdir)/doc/local.mk
+-include $(top_srcdir)/man/local.mk
+-include $(top_srcdir)/tests/local.mk
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -4149,11 +4149,7 @@ RECURSIVE_TARGETS = all-recursive check-
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+-am__can_run_installinfo = \
+- case $$AM_UPDATE_INFO_DIR in \
+- n|no|NO) false;; \
+- *) (install-info --version) >/dev/null 2>&1;; \
+- esac
++am__can_run_installinfo = false
+ am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+ am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+@@ -4403,10 +4399,10 @@ am__DIST_COMMON = $(doc_coreutils_TEXINF
+ $(top_srcdir)/build-aux/missing \
+ $(top_srcdir)/build-aux/test-driver \
+ $(top_srcdir)/build-aux/texinfo.tex \
+- $(top_srcdir)/build-aux/ylwrap $(top_srcdir)/doc/local.mk \
+- $(top_srcdir)/lib/alloca.c $(top_srcdir)/lib/config.hin \
+- $(top_srcdir)/lib/local.mk $(top_srcdir)/man/local.mk \
+- $(top_srcdir)/src/local.mk $(top_srcdir)/src/single-binary.mk \
++ $(top_srcdir)/build-aux/ylwrap \
++ $(top_srcdir)/lib/alloca.c \
++ $(top_srcdir)/lib/local.mk \
++ $(top_srcdir)/src/local.mk \
+ $(top_srcdir)/tests/local.mk ABOUT-NLS AUTHORS COPYING \
+ ChangeLog INSTALL NEWS README THANKS TODO build-aux/compile \
+ build-aux/config.guess build-aux/config.rpath \
+@@ -4520,7 +4516,7 @@ ERROR_H = @ERROR_H@
+ ETAGS = @ETAGS@
+ EUIDACCESS_LIBGEN = @EUIDACCESS_LIBGEN@
+ EXEEXT = @EXEEXT@
+-EXTRA_MANS = @EXTRA_MANS@
++EXTRA_MANS =
+ FDATASYNC_LIB = @FDATASYNC_LIB@
+ FILE_HAS_ACL_LIB = @FILE_HAS_ACL_LIB@
+ FLOAT_H = @FLOAT_H@
+@@ -6181,7 +6177,7 @@ localedir_c_make = @localedir_c_make@
+ localstatedir = @localstatedir@
+ localstatedir_c = @localstatedir_c@
+ localstatedir_c_make = @localstatedir_c_make@
+-man1_MANS = @man1_MANS@
++man1_MANS =
+ mandir = @mandir@
+ mandir_c = @mandir_c@
+ mandir_c_make = @mandir_c_make@
+@@ -6230,7 +6226,7 @@ top_build_prefix = @top_build_prefix@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+ ALL_RECURSIVE_TARGETS = distcheck-hook check-root
+-SUBDIRS = po . gnulib-tests
++SUBDIRS = po
+
+ #if GNU_MAKE
+ # [nicer features that work only with GNU Make]
+@@ -8437,7 +8433,7 @@ all: $(BUILT_SOURCES)
+ .SUFFIXES: .1 .c .dvi .log .o .obj .pl .pl$(EXEEXT) .ps .sh .sh$(EXEEXT) .trs .x .xpl .xpl$(EXEEXT) .y
+ am--refresh: Makefile
+ @:
+-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/lib/local.mk $(srcdir)/lib/gnulib.mk $(top_srcdir)/src/local.mk $(srcdir)/src/cu-progs.mk $(top_srcdir)/src/single-binary.mk $(top_srcdir)/doc/local.mk $(top_srcdir)/man/local.mk $(top_srcdir)/tests/local.mk $(am__configure_deps)
++$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/lib/local.mk $(srcdir)/lib/gnulib.mk $(top_srcdir)/src/local.mk $(srcdir)/src/cu-progs.mk $(top_srcdir)/src/single-binary.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+@@ -8459,7 +8455,7 @@ Makefile: $(srcdir)/Makefile.in $(top_bu
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
+ esac;
+-$(top_srcdir)/lib/local.mk $(srcdir)/lib/gnulib.mk $(top_srcdir)/src/local.mk $(srcdir)/src/cu-progs.mk $(top_srcdir)/src/single-binary.mk $(top_srcdir)/doc/local.mk $(top_srcdir)/man/local.mk $(top_srcdir)/tests/local.mk $(am__empty):
++$(top_srcdir)/lib/local.mk $(srcdir)/lib/gnulib.mk $(top_srcdir)/src/local.mk $(srcdir)/src/cu-progs.mk $(top_srcdir)/src/single-binary.mk $(am__empty):
+
+ $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
diff --git a/external/subpack/utils/cpusage/Makefile b/external/subpack/utils/cpusage/Makefile
new file mode 100644
index 0000000..995215e
--- /dev/null
+++ b/external/subpack/utils/cpusage/Makefile
@@ -0,0 +1,39 @@
+# SPDX-Identifier-License: GPL-2.0-only
+#
+# Copyright (C) 2005 Fabian Schneider,
+# 2010 Florian Sesser,
+# 2022 Thomas Hühn
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=cpusage
+PKG_VERSION:=1
+PKG_MAINTAINER:=Thomas Hühn <thomas.huehn@hs-nordhausen.de>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/cpusage
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Outputs CPU usage statistics once per second
+endef
+
+define Package/cpusage/description
+ CPUsage outputs CPU usage statistics once per second.
+ Optionally writes CSV output (see '-o' option).
+ Originally written by Fabian Schneider (TUM, TUB) in 2005.
+ Timestamp and CSV-compliance by Florian Sesser (TUM), 2010.
+ Refreshed by Thomas Hühn in 2022.
+endef
+
+define Build/Compile
+ $(TARGET_CC) $(TARGET_CFLAGS) \
+ -o $(PKG_BUILD_DIR)/cpusage $(PKG_BUILD_DIR)/cpusage.c
+endef
+
+define Package/cpusage/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/cpusage $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,cpusage))
diff --git a/external/subpack/utils/cpusage/src/cpusage.c b/external/subpack/utils/cpusage/src/cpusage.c
new file mode 100644
index 0000000..300fb62
--- /dev/null
+++ b/external/subpack/utils/cpusage/src/cpusage.c
@@ -0,0 +1,343 @@
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+#define CPUSTATES 7
+#define IDLEI 3
+/* long names:
+ * user - nice - system - idle - iowait - irq - soft irq */
+char *cpustatenames[] = {"user", "nice", "system", "idle",
+ "iowait", "irq", "softirq", NULL};
+
+#define LIMIT 95
+
+static const char usage[] =
+ "\n usage: cpusage [ -hos ] [ -a | -l limit | -o ] [ -c CPU ]\n";
+
+char *appname;
+
+static float cpu_perc[CPUSTATES];
+static float cpu_max[CPUSTATES];
+static float cpu_min[CPUSTATES];
+
+int cpunum; /* -1 all, 0-n CPU/Core 0-n */
+
+int output;
+
+int breakloop;
+
+/* returns 1-n yielding the number of CPU's/Cores */
+int getNumCPU() {
+ char buffer[32768];
+ int fd, len, i;
+ char *test;
+
+ fd = open("/proc/stat", O_RDONLY);
+ if (fd <= 0)
+ fprintf(stderr, "%s: cannot open /proc/stat \n", appname);
+
+ len = read(fd, buffer, sizeof(buffer) - 1);
+ close(fd);
+ buffer[len] = '\0';
+
+ i = 0;
+
+ test = strstr(buffer, "cpu");
+ if (test != NULL) {
+ test += sizeof("cpu");
+ test = strstr(test, "cpu");
+ }
+
+ while (test != NULL) {
+ test += sizeof("cpu");
+ /* fprintf(stderr, "%s: DEBUG: %s\n", appname, test); */
+ i++;
+ test = strstr(test, "cpu");
+ }
+ return i;
+}
+
+void getSysinfo(unsigned long *ptr, size_t size) {
+ char buffer[4096];
+ char match[100];
+ char *start;
+ int fd, len, j;
+
+ for (j = 0; j < size; j++)
+ ptr[j] = 0;
+
+ fd = open("/proc/stat", O_RDONLY);
+ if (fd <= 0)
+ fprintf(stderr, "%s: cannot open /proc/stat\n", appname);
+
+ len = read(fd, buffer, sizeof(buffer) - 1);
+ close(fd);
+ buffer[len] = '\0';
+
+ strcpy(match, "cpu ");
+ start = buffer;
+ if (cpunum != -1) {
+ sprintf(match, "cpu%d ", cpunum);
+ start = strstr(buffer, match);
+ }
+
+ strcat(match, "%ld %ld %ld %ld %ld %ld %ld");
+ if (sscanf(start, match, &ptr[0], &ptr[1], &ptr[2], &ptr[3], &ptr[4], &ptr[5],
+ &ptr[6]) != 7) {
+ fprintf(stderr, "%s: wrong /proc/stat format\n", appname);
+ }
+}
+
+long perc(int cpustates, long *cp_time, long *cp_old, long *cp_diff) {
+
+ int i = 0;
+ long total = 0;
+
+ for (i = 0; i < cpustates; i++) {
+ cp_diff[i] = cp_time[i] - cp_old[i];
+ total += cp_diff[i];
+ }
+
+ for (i = 0; i < cpustates; i++) {
+ cpu_perc[i] = ((float)cp_diff[i] * 100.0 / total);
+ /* new max ? */
+ if (cpu_perc[i] > cpu_max[i])
+ cpu_max[i] = cpu_perc[i];
+ /* new min ? */
+ if (cpu_perc[i] < cpu_min[i])
+ cpu_min[i] = cpu_perc[i];
+ }
+
+ return total;
+}
+
+void print_perc(float *perc, const char *head) {
+ int i;
+ time_t Zeitstempel;
+ struct tm *now;
+
+ /* human readable */
+ if ((output == 0) && (head != ""))
+ printf("%s: ", head);
+
+ /* machine readable */
+ if ((output == 1) && (head != ""))
+ printf("%s;", head);
+
+ /* timestamp */
+ time(&Zeitstempel);
+ now = localtime(&Zeitstempel);
+ if (output == 0)
+ printf("timestamp: %04d-%02d-%02d %02d.%02d.%02d, ", now->tm_year + 1900,
+ now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min,
+ now->tm_sec);
+ else
+ printf("%04d-%02d-%02d;%02d:%02d:%02d;", now->tm_year + 1900,
+ now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min,
+ now->tm_sec);
+
+ if (output == 0)
+ printf("%s: %5.1f%%, ", cpustatenames[0], perc[0]);
+ else
+ printf("%.1f", perc[0]);
+
+ /* print out calculated information in percentages */
+ for (i = 1; i < CPUSTATES; i++) {
+ if (output == 0)
+ printf("%s: %5.1f%%, ", cpustatenames[i], perc[i]);
+ else
+ printf(";%.1f", perc[i]);
+ }
+ printf("\n");
+}
+
+/* to catch Strg+C when looping */
+void loop_term_handler(int signum) { breakloop = 1; }
+
+int main(int argc, char **argv) {
+
+ appname = argv[0];
+
+ int i, c, limit;
+ int runonce; /* run just once and exit */
+ int avg; /* is avg measurement allready running */
+ int avg_run; /* did we allready had an avg measurement */
+ static long cp_time1[CPUSTATES];
+ static long cp_time2[CPUSTATES];
+ static long cp_avg_start[CPUSTATES];
+ static long cp_avg_stop[CPUSTATES];
+ static long cp_diff[CPUSTATES];
+
+ struct sigaction sigold, signew;
+
+ long *old = cp_time2;
+ long *new = cp_time1;
+
+ long total;
+ limit = LIMIT;
+ output = 0; /* 0: human readable; 1: machine readable */
+ runonce = 0; /* 0: run continuesly; 1: run once */
+
+ cpunum = -1; /* -1: all CPUs/Cores, 0-n: special CPU/Core */
+
+ /* reading commandline options */
+ while (1) {
+ c = getopt(argc, argv, "saohl:c:");
+
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ /*run once and exit */
+ case 's':
+ runonce = 1;
+ break;
+ /* use avg from begin to end -> same as "-l 100" */
+ case 'a':
+ limit = 100;
+ break;
+ case 'o':
+ output = 1; /* machine readable */
+ // header for CSV output
+ printf("date;time;user;nice;system;idle;iowait;irq;softirq\n");
+ break;
+ /* print usage */
+ case 'h':
+ fprintf(stderr, "%s: %s", appname, usage);
+ exit(0);
+ break;
+ /* set limit */
+ case 'l':
+ if (!(sscanf(optarg, "%d", &limit) == 1)) {
+ fprintf(stderr, "%s: option for -l should be integer (is %s)\n",
+ appname, optarg);
+ exit(1);
+ }
+ break;
+ /* select CPU/Core */
+ case 'c':
+ if (!(sscanf(optarg, "%d", &cpunum) == 1)) {
+ fprintf(stderr, "%s: option for -c should be integer (is %s)\n",
+ appname, optarg);
+ exit(1);
+ }
+ break;
+ }
+ }
+
+ if (cpunum != -1) {
+ int numcpu = getNumCPU();
+ if (cpunum < numcpu) {
+ printf("-- Selected CPU %d\n", cpunum);
+ } else {
+ if (numcpu == 1) {
+ fprintf(stderr, "%s: CPU %d not available (found %d CPU: [0])\n",
+ appname, cpunum, numcpu);
+ } else {
+ fprintf(stderr,
+ "%s: CPU %d not available (found %d CPU's: [0]-[%d])\n ",
+ appname, cpunum, numcpu, numcpu - 1);
+ }
+ exit(1);
+ }
+ }
+
+ breakloop = 0;
+
+ for (i = 0; i < CPUSTATES; i++) {
+ cpu_max[i] = 0;
+ cpu_min[i] = 100;
+ }
+
+ /* get information */
+ getSysinfo((unsigned long *)new, CPUSTATES);
+
+ /* catch Strg+C when capturing to call pcap_breakloop() */
+ memset(&signew, 0, sizeof(signew));
+ signew.sa_handler = loop_term_handler;
+ if (sigaction(SIGINT, &signew, &sigold) < 0) {
+ fprintf(stderr, "Could not set signal handler -> exiting");
+ }
+
+ avg = 0;
+ avg_run = 0;
+
+ if (runonce) {
+ breakloop = 1;
+ }
+
+ while (1) {
+ usleep(1000000);
+
+ if (new == cp_time1) {
+ new = cp_time2;
+ old = cp_time1;
+ } else {
+ new = cp_time1;
+ old = cp_time2;
+ }
+
+ /* get information again */
+ getSysinfo((unsigned long *)new, CPUSTATES);
+
+ /* convert cp_time counts to percentages */
+ total = perc(CPUSTATES, new, old, cp_diff);
+
+ /* check for avg measurement start */
+ if (!avg_run && !avg && (cpu_perc[IDLEI] <= limit)) {
+ avg = 1;
+ for (i = 0; i < CPUSTATES; i++)
+ cp_avg_start[i] = new[i];
+ }
+
+ /* check for avg measurement stop */
+ if (!avg_run && avg && (cpu_perc[IDLEI] > limit)) {
+ avg = 0;
+ for (i = 0; i < CPUSTATES; i++)
+ cp_avg_stop[i] = new[i];
+ avg_run = 1;
+ }
+
+ print_perc(cpu_perc, "");
+
+ if (breakloop) {
+ if (avg) {
+ avg = 0;
+ for (i = 0; i < CPUSTATES; i++)
+ cp_avg_stop[i] = new[i];
+ }
+ break;
+ }
+ }
+
+ /* Set default behaviour when loop is done */
+ if (sigaction(SIGINT, &sigold, &signew) < 0) {
+ fprintf(stderr, "%s: Could not restore signal handler -> exiting", appname);
+ }
+
+ if (!runonce && output == 0) {
+ // print avg only when not making a one-shot msg and
+ // when not writing CSV output
+ printf("---Summary----\n");
+
+ print_perc(cpu_min, "Min");
+
+ print_perc(cpu_max, "Max");
+
+ perc(CPUSTATES, cp_avg_start, cp_avg_stop, cp_diff);
+
+ print_perc(cpu_perc, "Avg");
+ }
+
+ return 0;
+}
diff --git a/external/subpack/utils/crconf/Makefile b/external/subpack/utils/crconf/Makefile
new file mode 100644
index 0000000..5375ae6
--- /dev/null
+++ b/external/subpack/utils/crconf/Makefile
@@ -0,0 +1,48 @@
+#
+# Copyright (C) 2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=crconf
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://git.code.sf.net/p/crconf/code
+PKG_SOURCE_DATE:=2018-03-02
+PKG_SOURCE_VERSION:=8bd996400d087028ba56b724abc1f5b378eaa77f
+PKG_MIRROR_HASH:=1948274e96584c74161f33841b3bbc6e48c3f674f1bfbb4d50731ce295e241c3
+
+PKG_MAINTAINER:=Alexandru Ardelean <ardeleanalex@gmail.com>
+PKG_LICENSE:=GPL-2.0-only
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/crconf
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Linux crypto layer configuraton tool
+ URL:=https://sourceforge.net/projects/crconf
+endef
+
+define Package/crconf/description
+ Linux crypto layer configuraton tool.
+ Use this to manipulate kernel Crypto API/framework stuff,
+ like drivers, templates, etc.
+ Example: https://wiki.strongswan.org/projects/strongswan/wiki/Pcrypt
+ Most interesting stuff you can find on https://wiki.strongswan.org
+endef
+
+MAKE_FLAGS += CFLAGS="$(TARGET_CFLAGS) -I../include"
+
+define Package/crconf/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/crconf $(1)/sbin
+endef
+
+$(eval $(call BuildPackage,crconf))
diff --git a/external/subpack/utils/crelay/Makefile b/external/subpack/utils/crelay/Makefile
new file mode 100644
index 0000000..8163040
--- /dev/null
+++ b/external/subpack/utils/crelay/Makefile
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2015-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=crelay
+PKG_VERSION:=0.14.1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/ondrej1024/crelay/tar.gz/V$(PKG_VERSION)?
+PKG_HASH:=291f51d60c3003ad594ac2c10f75b0c5d0b40e49b298f73caf6a47afe3279fde
+
+PKG_MAINTAINER:=Ted Hess <thess@kitschensync.net>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=LICENSE
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+include $(INCLUDE_DIR)/meson.mk
+
+define Package/crelay
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=USB relay remote control daemon
+ URL:=https://github.com/ondrej1024/crelay
+ DEPENDS:=+libftdi1 +hidapi +libusb-1.0
+endef
+
+define Package/crelay/description
+ crelay is used to control different relay cards in a unified manner. It provides
+ several interfaces for controlling the relays locally or remotely by a web browser
+ or a smartphone. The card which is detected first will be used. A WebUI control is
+ available on port 8000 (default)
+ .
+ Currently supported relay cards:
+ - Conrad USB 4-channel relay card
+ - Sainsmart USB 4/8-channel relay board
+ - Sainsmart USB 16-channel relay control module
+ - Generic GPIO relays
+ - HID API compatible relay card
+endef
+
+define Package/crelay/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/crelay $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/crelay.init $(1)/etc/init.d/crelay
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/conf/crelay.conf $(1)/etc
+endef
+
+$(eval $(call BuildPackage,crelay))
diff --git a/external/subpack/utils/crelay/files/crelay.init b/external/subpack/utils/crelay/files/crelay.init
new file mode 100644
index 0000000..b7c5123
--- /dev/null
+++ b/external/subpack/utils/crelay/files/crelay.init
@@ -0,0 +1,24 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2016 OpenWrt.org
+
+NAME=crelay
+START=93
+
+PROG=/usr/bin/${NAME}
+
+USE_PROCD=1
+
+# Custom relay labels (for Web GUI) are defined in /etc/crelay.conf
+
+start_service() {
+ procd_open_instance
+
+ # restart if it croaks
+ procd_set_param respawn
+
+ procd_set_param command "$PROG"
+ # daemon mode in foreground - starts HTTP server
+ procd_append_param command -d
+
+ procd_close_instance
+}
diff --git a/external/subpack/utils/crelay/patches/010-meson.patch b/external/subpack/utils/crelay/patches/010-meson.patch
new file mode 100644
index 0000000..8e1f230
--- /dev/null
+++ b/external/subpack/utils/crelay/patches/010-meson.patch
@@ -0,0 +1,64 @@
+From 5e122c8adabb3305dd7524a24ec296bb8d1b7cac Mon Sep 17 00:00:00 2001
+From: Rosen Penev <rosenp@gmail.com>
+Date: Tue, 19 Jul 2022 01:07:57 -0700
+Subject: [PATCH] add meson
+
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+---
+ meson.build | 34 ++++++++++++++++++++++++++++++++++
+ meson_options.txt | 11 +++++++++++
+ 2 files changed, 45 insertions(+)
+ create mode 100644 meson.build
+ create mode 100644 meson_options.txt
+
+--- /dev/null
++++ b/meson.build
+@@ -0,0 +1,34 @@
++project('crelay', 'c', version : '0.14.1')
++
++hidapi_dep = dependency('hidapi-libusb', required: get_option('hidapi'))
++ftdi_dep = dependency('libftdi1', required: get_option('sainsmart'))
++libusb_dep = dependency('libusb-1.0', required: get_option('conrad'))
++
++sources = files(
++ 'src/config.c',
++ 'src/crelay.c',
++ 'src/relay_drv.c',
++ 'src/relay_drv_gpio.c',
++)
++
++if hidapi_dep.found()
++ add_project_arguments('-DDRV_HIDAPI', language: 'c')
++ add_project_arguments('-DDRV_SAINSMART16', language: 'c')
++ sources += files('src/relay_drv_hidapi.c', 'src/relay_drv_sainsmart16.c',)
++endif
++
++if ftdi_dep.found()
++ add_project_arguments('-DDRV_SAINSMART', language: 'c')
++ sources += files('src/relay_drv_sainsmart.c')
++endif
++
++if libusb_dep.found()
++ add_project_arguments('-DDRV_CONRAD', language: 'c')
++ sources += files('src/relay_drv_conrad.c')
++endif
++
++executable('crelay',
++ sources,
++ dependencies: [ hidapi_dep, ftdi_dep, libusb_dep ],
++ install: true,
++)
+--- /dev/null
++++ b/meson_options.txt
+@@ -0,0 +1,11 @@
++option('hidapi', type : 'feature',
++ description: 'Enable HIDAPI driver',
++)
++
++option('sainsmart', type : 'feature',
++ description: 'Enable SAINSMART driver',
++)
++
++option('conrad', type : 'feature',
++ description: 'Enable CONRAD driver',
++)
diff --git a/external/subpack/utils/crun/Makefile b/external/subpack/utils/crun/Makefile
new file mode 100644
index 0000000..f9522c4
--- /dev/null
+++ b/external/subpack/utils/crun/Makefile
@@ -0,0 +1,93 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=crun
+PKG_VERSION:=1.15
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/containers/crun/tar.gz/$(PKG_VERSION)?
+PKG_HASH:=357ebf4b391284d29176e1a638cff8f47569595db66c272c558241e4f807c600
+
+PKG_BUILD_DEPENDS:=argp-standalone
+PKG_BUILD_PARALLEL:=1
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+
+PKG_MAINTAINER:=Oskari Rauta <oskari.rauta@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:crun_project:crun
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/crun
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=crun
+ URL:=https://github.com/containers/crun
+ DEPENDS:=@!arc +libseccomp +libcap +libgcrypt
+endef
+
+define Package/crun/description
+ A fast and low-memory footprint OCI Container Runtime fully written in C.
+endef
+
+LIBOCISPEC_COMMIT:=7b27d0a0bb87fdd7ee46365994e450a58405004f
+
+define Download/libocispec
+ PROTO:=git
+ URL:=https://github.com/containers/libocispec.git
+ VERSION:=$(LIBOCISPEC_COMMIT)
+ MIRROR_HASH:=45562d4650b509e97d145a90a7fda07c9855f79ee96190cfd4181ae619fcc037
+ FILE:=libocispec-$(LIBOCISPEC_COMMIT).tar.xz
+ SUBDIR:=libocispec
+endef
+$(eval $(call Download,libocispec))
+
+CONFIGURE_ARGS+= \
+ --disable-systemd \
+ --enable-embedded-yajl \
+ --enable-caps \
+ --enable-dl \
+ --enable-seccomp \
+ --enable-bpf
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(SED) '/#include <git-version.h>/d' $(PKG_BUILD_DIR)/src/{crun.c,libcrun/container.c}
+ xzcat $(DL_DIR)/libocispec-$(LIBOCISPEC_COMMIT).tar.xz | $(HOST_TAR) -C $(PKG_BUILD_DIR) $(TAR_OPTIONS)
+endef
+
+define Build/Configure
+ $(call Build/Configure/Default)
+
+ $(SED) '/#define PACKAGE \"/d' $(PKG_BUILD_DIR)/config.h
+ $(SED) '/#define VERSION \"/d' $(PKG_BUILD_DIR)/config.h
+ $(SED) '/#define GIT_VERSION \"/d' $(PKG_BUILD_DIR)/config.h
+ $(SED) '/#define PACKAGE_BUGREPORT \"/d' $(PKG_BUILD_DIR)/config.h
+ $(SED) '/#define PACKAGE_NAME \"/d' $(PKG_BUILD_DIR)/config.h
+ $(SED) '/#define PACKAGE_STRING \"/d' $(PKG_BUILD_DIR)/config.h
+ $(SED) '/#define PACKAGE_TARNAME \"/d' $(PKG_BUILD_DIR)/config.h
+ $(SED) '/#define PACKAGE_VERSION \"/d' $(PKG_BUILD_DIR)/config.h
+
+ echo "#define PACKAGE \"$(PKG_NAME)\"" >> $(PKG_BUILD_DIR)/config.h
+ echo "#define VERSION \"$(PKG_VERSION)\"" >> $(PKG_BUILD_DIR)/config.h
+ echo "#define PACKAGE_NAME \"$(PKG_NAME)\"" >> $(PKG_BUILD_DIR)/config.h
+ echo "#define PACKAGE_VERSION \"$(PKG_VERSION)\"" >> $(PKG_BUILD_DIR)/config.h
+ echo "#define PACKAGE_STRING \"$(PKG_NAME) $(PKG_VERSION)\"" >> $(PKG_BUILD_DIR)/config.h
+ echo "#define PACKAGE_TARNAME \"$(PKG_NAME)\"" >> $(PKG_BUILD_DIR)/config.h
+ echo "#define PACKAGE_BUGREPORT \"bugs@openwrt.org\"" >> $(PKG_BUILD_DIR)/config.h
+ echo "#define GIT_VERSION \"$(PKG_SOURCE_VERSION)\"" >> $(PKG_BUILD_DIR)/config.h
+endef
+
+define Package/crun/install
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/crun $(1)/usr/bin/
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libcrun.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,crun))
diff --git a/external/subpack/utils/cryptsetup/Makefile b/external/subpack/utils/cryptsetup/Makefile
new file mode 100644
index 0000000..3b2eab6
--- /dev/null
+++ b/external/subpack/utils/cryptsetup/Makefile
@@ -0,0 +1,106 @@
+#
+# Copyright (C) 2006-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=cryptsetup
+PKG_VERSION:=2.7.4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/linux/utils/cryptsetup/v$(subst $(space),.,$(wordlist 1, 2, $(subst .,$(space),$(PKG_VERSION))))
+PKG_HASH:=dce29903a58f7b774fe61191e7e6de955de0f40d9e27b0028ffcf3438c0e9480
+
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+PKG_LICENSE:=GPL-2.0-or-later LGPL-2.1-or-later
+PKG_LICENSE_FILES:=COPYING COPYING.LGPL
+PKG_CPE_ID:=cpe:/a:cryptsetup_project:cryptsetup
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+PKG_BUILD_DEPENDS:=!USE_GLIBC:argp-standalone
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/cryptsetup
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Encryption
+ TITLE:=Cryptsetup
+ DEPENDS:=$(ICONV_DEPENDS) $(INTL_DEPENDS) +libblkid +libuuid +libpopt +lvm2 \
+ +libdevmapper +libjson-c +@KERNEL_DIRECT_IO +kmod-crypto-user
+ URL:=https://gitlab.com/cryptsetup/cryptsetup/
+endef
+
+define Package/cryptsetup/description
+ Cryptsetup is utility used to conveniently setup disk encryption based on DMCrypt kernel module.
+endef
+
+define Package/cryptsetup-ssh
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Encryption
+ TITLE:=Cryptsetup SSH token
+ DEPENDS:=+cryptsetup +PACKAGE_cryptsetup-ssh:libssh
+ URL:=https://gitlab.com/cryptsetup/cryptsetup/
+endef
+
+define Package/cryptsetup-ssh/description
+ Experimental SSH token support for cryptsetup.
+endef
+
+CONFIGURE_ARGS += \
+ --disable-asciidoc \
+ --disable-cryptsetup-reencrypt \
+ --disable-integritysetup \
+ --disable-selinux \
+ --disable-rpath \
+ --disable-veritysetup \
+ --disable-udev \
+ --with-default-luks-format=LUKS2 \
+ --with-luks2-lock-path=/var/run/cryptsetup \
+ --with-crypto_backend=kernel
+
+ifeq ($(CONFIG_PACKAGE_cryptsetup-ssh),)
+CONFIGURE_ARGS += --disable-ssh-token
+endif
+
+CONFIGURE_VARS += \
+ LIBSSH_CFLAGS="-I$(STAGING_DIR)/usr/include" \
+ LIBSSH_LIBS="-L$(STAGING_DIR)/usr/lib -lssh"
+
+TARGET_CFLAGS += -D_LARGEFILE64_SOURCE
+TARGET_LDFLAGS += -Wl,--gc-sections $(if $(INTL_FULL),-lintl)
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/include/libcryptsetup.h $(1)/usr/include
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libcryptsetup.so* $(1)/usr/lib
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libcryptsetup.pc $(1)/usr/lib/pkgconfig
+endef
+
+define Package/cryptsetup/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libcryptsetup.so* $(1)/usr/lib
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/cryptsetup $(1)/usr/sbin
+endef
+
+define Package/cryptsetup-ssh/install
+ $(INSTALL_DIR) $(1)/usr/lib/cryptsetup
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/cryptsetup/* $(1)/usr/lib/cryptsetup
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/cryptsetup-ssh $(1)/usr/sbin
+endef
+
+$(eval $(call BuildPackage,cryptsetup))
+$(eval $(call BuildPackage,cryptsetup-ssh))
diff --git a/external/subpack/utils/ctop/Makefile b/external/subpack/utils/ctop/Makefile
new file mode 100644
index 0000000..09b8722
--- /dev/null
+++ b/external/subpack/utils/ctop/Makefile
@@ -0,0 +1,52 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ctop
+PKG_VERSION:=0.7.7
+PKG_RELEASE:=1
+
+PKG_SOURCE:=v$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/bcicen/ctop/archive
+PKG_HASH:=0db439f2030af73ad5345884b08a33a762c3b41b30604223dd0ebddde72d2741
+
+PKG_MAINTAINER:=Javier Marcet <javier@marcet.info>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_BUILD_FLAGS:=no-mips16
+
+GO_PKG:=github.com/bcicen/ctop
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/ctop
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Top-like interface for container metrics
+ URL:=https://ctop.sh/
+ DEPENDS:=$(GO_ARCH_DEPENDS)
+endef
+
+define Package/ctop/description
+ Top-like interface for container metrics
+endef
+
+MAKE_PATH:=$(GO_PKG_WORK_DIR_NAME)/build/src/$(GO_PKG)
+MAKE_VARS += \
+ GOPATH=$(GO_PKG_BUILD_DIR) \
+ GOCACHE=$(GO_BUILD_CACHE_DIR) \
+ GOROOT_FINAL=$(GO_TARGET_ROOT) \
+ CC="$(TARGET_CC)" \
+ CXX="$(TARGET_CXX)" \
+ $(GO_PKG_VARS)
+MAKE_FLAGS += \
+ COMMIT=$(PKG_SOURCE_VERSION)
+
+define Package/ctop/install
+ $(INSTALL_DIR) $(1)/usr/sbin/
+ $(INSTALL_BIN) $(GO_PKG_BUILD_BIN_DIR)/ctop $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,ctop))
diff --git a/external/subpack/utils/dbus/Makefile b/external/subpack/utils/dbus/Makefile
new file mode 100644
index 0000000..0ebeb7a
--- /dev/null
+++ b/external/subpack/utils/dbus/Makefile
@@ -0,0 +1,146 @@
+#
+# Copyright (C) 2007-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dbus
+PKG_VERSION:=1.13.12
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://dbus.freedesktop.org/releases/dbus
+PKG_HASH:=7588649b56dd257c6a5f85a8c45aa2dfdf9e99f4de3983710f452081ca43eca6
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=AFL-2.1
+PKG_CPE_ID:=cpe:/a:freedesktop:dbus
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/dbus/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Simple interprocess messaging system
+ URL:=http://dbus.freedesktop.org/
+endef
+
+define Package/dbus/Default/description
+ D-Bus is a message bus system, a simple way for applications to talk to one
+ another. In addition to interprocess communication, D-Bus helps coordinate
+ process lifecycle; it makes it simple and reliable to code a "single instance"
+ application or daemon, and to launch applications and daemons on demand when
+ their services are needed.
+endef
+
+define Package/libdbus
+$(call Package/dbus/Default)
+ CATEGORY:=Libraries
+ TITLE+= (library)
+ DEPENDS:= +libpthread
+endef
+
+define Package/libdbus/Description
+$(call Package/dbus/Default/description)
+ This package contains the D-Bus shared library.
+endef
+
+define Package/dbus
+$(call Package/dbus/Default)
+ TITLE+= (daemon)
+ DEPENDS:= +libexpat +libdbus
+endef
+
+define Package/dbus/Description
+$(call Package/dbus/Default/description)
+ This package contains the D-Bus daemon.
+endef
+
+define Package/dbus-utils
+$(call Package/dbus/Default)
+ TITLE+= (utilities)
+ DEPENDS:= +dbus
+endef
+
+define Package/dbus-utils/Description
+$(call Package/dbus/Default/description)
+ This package contains D-Bus utilities.
+endef
+
+CONFIGURE_ARGS += \
+ --disable-maintainer-mode \
+ --disable-developer \
+ --enable-debug=no \
+ --enable-shared \
+ --disable-static \
+ --disable-verbose-mode \
+ --disable-asserts \
+ --disable-xml-docs \
+ --disable-doxygen-docs \
+ --disable-ducktype-docs \
+ --disable-selinux \
+ --disable-apparmor \
+ --disable-libaudit \
+ --enable-inotify \
+ --disable-kqueue \
+ --disable-console-owner-file \
+ --disable-systemd \
+ --disable-tests \
+ --disable-code-coverage \
+ --disable-x11-autolaunch \
+ --with-session-socket-dir=/tmp \
+ --with-system-socket=/var/run/dbus/system_bus_socket \
+ --with-system-pid-file=/var/run/dbus.pid \
+ --with-dbus-user=root \
+ --without-x
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/dbus-1.0 $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib/dbus-1.0/include/dbus/
+ $(INSTALL_DATA) \
+ $(PKG_INSTALL_DIR)/usr/lib/dbus-1.0/include/dbus/*.h \
+ $(1)/usr/lib/dbus-1.0/include/dbus/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libdbus-1.{so*,la} \
+ $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/dbus-1.0 $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/dbus-1.pc \
+ $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/libdbus/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libdbus-1.so.* $(1)/usr/lib/
+endef
+
+define Package/dbus/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dbus-cleanup-sockets $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dbus-daemon $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dbus-launch $(1)/usr/bin/dbus-launch.real
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dbus-uuidgen $(1)/usr/bin/
+ $(INSTALL_BIN) ./files/dbus-launch $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/dbus-daemon-launch-helper $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/dbus.init $(1)/etc/init.d/dbus
+ $(INSTALL_DIR) $(1)/usr/share/dbus-1
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/dbus-1 $(1)/usr/share/
+endef
+
+define Package/dbus-utils/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dbus-{monitor,send,update-activation-environment} $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,libdbus))
+$(eval $(call BuildPackage,dbus))
+$(eval $(call BuildPackage,dbus-utils))
diff --git a/external/subpack/utils/dbus/files/dbus-launch b/external/subpack/utils/dbus/files/dbus-launch
new file mode 100644
index 0000000..9769842
--- /dev/null
+++ b/external/subpack/utils/dbus/files/dbus-launch
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# Simple wrapper script which allows us to build dbus without general x support
+# If an application needs x support in dbus-launch it has to depend on the
+# dbus-launch-x package. The script is used to prefer dbus-launch with x over
+# the dbus-lauch without x.
+
+if [ -f /usr/bin/dbus-launch-x ]; then
+ exec /usr/bin/dbus-launch-x "$@"
+else
+ exec /usr/bin/dbus-launch.real "$@"
+fi
diff --git a/external/subpack/utils/dbus/files/dbus.init b/external/subpack/utils/dbus/files/dbus.init
new file mode 100644
index 0000000..afb7054
--- /dev/null
+++ b/external/subpack/utils/dbus/files/dbus.init
@@ -0,0 +1,17 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2007-2011 OpenWrt.org
+
+START=60
+
+SERVICE_PID_FILE=/var/run/dbus.pid
+
+start() {
+ mkdir -m 0755 -p /var/lib/dbus
+ mkdir -m 0755 -p /var/run/dbus
+ [ -x /usr/bin/dbus-uuidgen ] && /usr/bin/dbus-uuidgen --ensure
+ service_start /usr/bin/dbus-daemon --system
+}
+
+stop() {
+ service_stop /usr/bin/dbus-daemon
+}
diff --git a/external/subpack/utils/device-observatory/Makefile b/external/subpack/utils/device-observatory/Makefile
new file mode 100644
index 0000000..9317df1
--- /dev/null
+++ b/external/subpack/utils/device-observatory/Makefile
@@ -0,0 +1,41 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=device-observatory
+PKG_VERSION:=1.2.0
+PKG_RELEASE:=7
+
+PKG_SOURCE_URL:=https://codeload.github.com/mwarning/device-observatory/tar.gz/v$(PKG_VERSION)?
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_HASH:=83b3f362f154a427abbd3af31b3c2dda9983cdc15f6b833d804727ef0fbdc72e
+
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_BUILD_DEPENDS:=vim/host
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/device-observatory
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=device-observatory
+ MAINTAINER:=Moritz Warning <moritzwarning@web.de>
+ URL:=https://github.com/mwarning/device-observatory/
+ DEPENDS:=+iw +libpcap +libmicrohttpd
+endef
+
+define Package/device-observatory/conffiles
+/etc/config/device-observatory
+endef
+
+define Package/device-observatory/description
+ Show information about connected devices and connections to increase security awareness.
+endef
+
+define Package/device-observatory/install
+ $(CP) files/* $(1)
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/device-observatory $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/share/device-observatory
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/macdb.txt $(1)/usr/share/device-observatory/macdb.txt
+endef
+
+$(eval $(call BuildPackage,device-observatory))
diff --git a/external/subpack/utils/device-observatory/files/etc/config/device-observatory b/external/subpack/utils/device-observatory/files/etc/config/device-observatory
new file mode 100644
index 0000000..b3d80c0
--- /dev/null
+++ b/external/subpack/utils/device-observatory/files/etc/config/device-observatory
@@ -0,0 +1,26 @@
+
+config setup
+ list dev 'wlan0'
+ list mdev 'mon0'
+
+ option mac_db '/usr/share/device-observatory/macdb.txt'
+ option port_db '/etc/services'
+
+ # Optional JSON output into file
+# option json_output '/tmp/device-observatory.json'
+
+ # Time after which a device is removed from the record
+ option device_timeout 3600
+
+ # Create monitoring interface mon0 based on physical interface wifi phy0.
+ # See 'iw dev' output for a list of interfaces.
+ list create_monitor 'mon0'
+
+ # Track router itself as device
+ option track_localhost 0
+
+ # Set to 0 to disable webserver
+ option webserver_port 8080
+
+ # Not needed, all necessary files are included
+# option webserver_path '/www'
diff --git a/external/subpack/utils/device-observatory/files/etc/init.d/device-observatory b/external/subpack/utils/device-observatory/files/etc/init.d/device-observatory
new file mode 100755
index 0000000..1405e36
--- /dev/null
+++ b/external/subpack/utils/device-observatory/files/etc/init.d/device-observatory
@@ -0,0 +1,66 @@
+#!/bin/sh /etc/rc.common
+
+START=90
+USE_PROCD=1
+PROG=/usr/bin/device-observatory
+OPTS=""
+
+
+boot() {
+ local dev="$(uci get -q device-observatory.@setup[0].dev | cut -d ' ' -f 1)"
+
+ # Wait for interface to be up
+ ubus -t 15 wait_for network.interface network.${dev:-localhost} 2>/dev/null
+ rc_procd start_service
+}
+
+xappend() {
+ local name="$2" value="$1"
+ OPTS="$OPTS --${name//_/-} ${value//'/\\'}"
+}
+
+append_opts() {
+ local name value cfg="$1"; shift
+ for name in $*; do
+ config_get value "$cfg" "$name"
+ [ -n "$value" ] && xappend "$value" "$name"
+ done
+}
+
+append_opts_list() {
+ local name cfg="$1"; shift
+ for name in $*; do
+ config_list_foreach "$cfg" "$name" xappend "$name"
+ done
+}
+
+create_monitor_interface() {
+ local ifce="$1" n=$(echo -n "$1" | tail -c 1)
+
+ if [ ! -d "/sys/class/net/$ifce/" ]; then
+ iw phy "phy$n" interface add "$ifce" type monitor
+ ip link set dev "$ifce" up
+ fi
+}
+
+start_instance() {
+ local cfg="$1"
+
+ OPTS=""
+
+ config_list_foreach "$cfg" "create_monitor" create_monitor_interface "create_monitor"
+
+ append_opts_list "$cfg" dev mdev
+ append_opts "$cfg" mac_db port_db json_output device_timeout webserver_port webserver_path track_localhost
+
+ procd_open_instance
+ procd_set_param command $PROG $OPTS
+ procd_set_param stderr 1
+ procd_set_param stdout 0
+ procd_close_instance
+}
+
+start_service() {
+ config_load 'device-observatory'
+ config_foreach start_instance 'setup'
+}
diff --git a/external/subpack/utils/device-observatory/patches/010-uClibc-ng.patch b/external/subpack/utils/device-observatory/patches/010-uClibc-ng.patch
new file mode 100644
index 0000000..077a971
--- /dev/null
+++ b/external/subpack/utils/device-observatory/patches/010-uClibc-ng.patch
@@ -0,0 +1,22 @@
+--- a/src/parse_ether.c
++++ b/src/parse_ether.c
+@@ -21,10 +21,18 @@
+ #include "parse_ether.h"
+
+ /* tcpdump header (ether.h) defines ETHER_HDRLEN) */
+-#ifndef ETHER_HDRLEN
++#ifndef ETHER_HDRLEN
+ #define ETHER_HDRLEN 14
+ #endif
+
++/* uClibc-ng compatibility */
++#ifndef IPPROTO_BEETPH
++#define IPPROTO_BEETPH 94
++#endif
++
++#ifndef IPPROTO_MPLS
++#define IPPROTO_MPLS 137
++#endif
+
+ const char *ip_protcol_str(int p)
+ {
diff --git a/external/subpack/utils/device-observatory/patches/020-libmicrohttpd.patch b/external/subpack/utils/device-observatory/patches/020-libmicrohttpd.patch
new file mode 100644
index 0000000..3d2844b
--- /dev/null
+++ b/external/subpack/utils/device-observatory/patches/020-libmicrohttpd.patch
@@ -0,0 +1,20 @@
+--- a/src/webserver.c
++++ b/src/webserver.c
+@@ -129,7 +129,7 @@ const char *get_mimetype(const char str[
+ return "application/octet-stream";
+ }
+
+-static int send_response(void *cls, struct MHD_Connection *connection,
++static enum MHD_Result send_response(void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method, const char *version,
+ const char *upload_data, size_t *upload_data_size, void **con_cls)
+ {
+@@ -142,7 +142,7 @@ static int send_response(void *cls, stru
+ struct device *device;
+ int is_localhost;
+ FILE *fp;
+- int ret;
++ enum MHD_Result ret;
+
+ connection_info = MHD_get_connection_info(connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS);
+ if (!connection_info) {
diff --git a/external/subpack/utils/dfu-programmer/Makefile b/external/subpack/utils/dfu-programmer/Makefile
new file mode 100644
index 0000000..aadd796
--- /dev/null
+++ b/external/subpack/utils/dfu-programmer/Makefile
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dfu-programmer
+PKG_VERSION:=0.7.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)/$(PKG_VERSION)
+PKG_HASH:=1db4d36b1aedab2adc976e8faa5495df3cf82dc4bf883633dc6ba71f7c4af995
+
+PKG_MAINTAINER:=Stefan Hellermann <stefan@the2masters.de>
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/dfu-programmer
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Microcontroller programming
+ TITLE:=USB programmer for Atmel microcontrollers
+ URL:=http://dfu-programmer.github.io/
+ DEPENDS:=+libusb-1.0
+endef
+
+define Package/dfu-programmer/description
+ dfu-programmer is a Device Firmware Update (DFU) based USB programmer
+ for Atmel chips with a USB bootloader.
+endef
+
+define Package/dfu-programmer/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/$(PKG_NAME) $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,dfu-programmer))
diff --git a/external/subpack/utils/dfu-util/Makefile b/external/subpack/utils/dfu-util/Makefile
new file mode 100644
index 0000000..962839d
--- /dev/null
+++ b/external/subpack/utils/dfu-util/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2017 Bruno Randolf (br1@einfach.org)
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dfu-util
+PKG_VERSION:=0.10
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_MAINTAINER:=Bruno Randolf <br1@einfach.org>
+PKG_HASH:=a03dc58dfc79c056819c0544b2a5970537566460102b3d82cfb038c60e619b42
+
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/dfu-util
+ SUBMENU:=
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libusb-1.0
+ TITLE:=Device Firmware Upgrade Utilities
+ URL:=http://dfu-util.sourceforge.net/
+ MAINTAINER:=Bruno Randolf <br1@einfach.org>
+endef
+
+define Package/dfu-util/description
+ dfu-util is a host side implementation of the DFU 1.0 and DFU 1.1
+ specifications of the USB forum. DFU is intended to download and
+ upload firmware to/from devices connected over USB.
+endef
+
+define Package/dfu-util/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/dfu-util $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,dfu-util))
diff --git a/external/subpack/utils/digitemp/Makefile b/external/subpack/utils/digitemp/Makefile
new file mode 100644
index 0000000..c5e5f17
--- /dev/null
+++ b/external/subpack/utils/digitemp/Makefile
@@ -0,0 +1,87 @@
+#
+# Copyright (C) 2009-2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# Comment: This makefile is based on the oldpackage makefile by acinonyx / nbd
+# https://dev.openwrt.org/browser/packages/utils/digitemp/Makefile
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=digitemp
+PKG_VERSION:=3.7.2
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/bcl/digitemp/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=683df4ab5cc53a45fe4f860c698f148d34bcca91b3e0568a342f32d64d12ba24
+
+PKG_MAINTAINER:=Jasper Scholte <NightNL@outlook.com>
+PKG_LICENSE:=GPL-2.0-or-later
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/digitemp/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=DigiTemp is a simple to use program for reading values from 1-wire devices.
+ URL:=https://www.digitemp.com
+endef
+
+define Package/digitemp/Default/description
+ DigiTemp is a simple to use program for reading values from 1-wire devices.
+ Its main use is for reading temperature sensors, but it also reads counters,
+ and understands the 1-wire hubs with devices on different branches of the network.
+endef
+
+define Package/digitemp
+$(call Package/digitemp/Default)
+ TITLE += (serial version)
+endef
+
+define Package/digitemp/description
+$(call Package/digitemp/Default/description)
+ This package is built without USB support.
+endef
+
+define Package/digitemp-usb
+$(call Package/digitemp/Default)
+ TITLE += (USB version)
+ DEPENDS += +libusb-compat
+endef
+
+define Package/digitemp-usb/description
+$(call Package/digitemp/Default/description)
+ This package is built with USB support.
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS) -DLINUX $(TARGET_CPPFLAGS) \
+ -I./src -I./userial" \
+ LIBS="$(TARGET_LDFLAGS)" \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ ds9097 ds9097u
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS) -DLINUX $(TARGET_CPPFLAGS) \
+ -I./src -I./userial -DOWUSB" \
+ LIBS="$(TARGET_LDFLAGS) -lusb -lm -DOWUSB" \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ clean ds2490
+endef
+
+define Package/digitemp/install
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(CP) $(PKG_BUILD_DIR)/digitemp_{DS9097,DS9097U} $(1)/usr/bin/
+endef
+
+define Package/digitemp-usb/install
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(CP) $(PKG_BUILD_DIR)/digitemp_DS2490 $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,digitemp))
+$(eval $(call BuildPackage,digitemp-usb))
diff --git a/external/subpack/utils/digitemp/patches/0001_add_missing_includes.patch b/external/subpack/utils/digitemp/patches/0001_add_missing_includes.patch
new file mode 100644
index 0000000..a1fbc42
--- /dev/null
+++ b/external/subpack/utils/digitemp/patches/0001_add_missing_includes.patch
@@ -0,0 +1,68 @@
+--- a/src/ds2438.c
++++ b/src/ds2438.c
+@@ -5,6 +5,7 @@
+ Licensed under GPL v2
+ ----------------------------------------------------------------------- */
+ #include <stdio.h>
++#include <sys/types.h>
+ #include "ownet.h"
+ #include "ad26.h"
+
+--- a/userial/ad26.c
++++ b/userial/ad26.c
+@@ -33,7 +33,7 @@
+ #include "ownet.h"
+ #include "ad26.h"
+ #include "owproto.h"
+-
++#include "sys/types.h"
+
+ extern int owBlock(int,int,uchar *,int);
+ extern void setcrc8(int,uchar);
+--- a/userial/cnt1d.c
++++ b/userial/cnt1d.c
+@@ -29,6 +29,7 @@
+ // Version: 2.00
+ //
+ //
++#include "sys/types.h"
+ #include "ownet.h"
+
+ // external One Wire functions from nework layer
+--- a/userial/crcutil.c
++++ b/userial/crcutil.c
+@@ -29,6 +29,7 @@
+
+ // Include files
+ #include "ownet.h"
++#include "sys/types.h"
+
+ // Local subroutines
+ void setcrc16(int,ushort);
+--- a/userial/ds9097u/owtrnu.c
++++ b/userial/ds9097u/owtrnu.c
+@@ -39,6 +39,7 @@
+ // Added file I/O operations
+ //
+
++#include "sys/types.h"
+ #include "ownet.h"
+ #include "ds2480.h"
+
+--- a/userial/ioutil.c
++++ b/userial/ioutil.c
+@@ -36,6 +36,7 @@
+ #include <string.h>
+ #include <ctype.h>
+ #include "ownet.h"
++#include "sys/types.h"
+
+ #ifdef __MC68K__
+ #include <PalmOS.h>
+--- a/userial/owproto.h
++++ b/userial/owproto.h
+@@ -1,3 +1,4 @@
++#include "sys/types.h"
+ /* Prototypes for userial driver functions */
+
+ /* From other low level userial files */
diff --git a/external/subpack/utils/dmidecode/Makefile b/external/subpack/utils/dmidecode/Makefile
new file mode 100644
index 0000000..ca6a043
--- /dev/null
+++ b/external/subpack/utils/dmidecode/Makefile
@@ -0,0 +1,48 @@
+#
+# Copyright (C) 2007-2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dmidecode
+PKG_VERSION:=3.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@SAVANNAH/$(PKG_NAME)
+PKG_HASH:=077006fa2da0d06d6383728112f2edef9684e9c8da56752e97cd45a11f838edd
+PKG_MAINTAINER:=Álvaro Fernández Rojas <noltari@gmail.com>
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/dmidecode
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=@(TARGET_x86||TARGET_x86_64)
+ TITLE:=Displays BIOS informations.
+ URL:=https://www.nongnu.org/dmidecode/
+endef
+
+define Package/dmidecode/description
+ Dmidecode reports information about your system's hardware
+ as described in your system BIOS according to the SMBIOS/DMI
+ standard.
+endef
+
+MAKE_FLAGS += \
+ prefix="/usr"
+
+define Package/dmidecode/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/$(PKG_NAME) $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,dmidecode))
diff --git a/external/subpack/utils/docker-compose/Makefile b/external/subpack/utils/docker-compose/Makefile
new file mode 100644
index 0000000..9e9b44b
--- /dev/null
+++ b/external/subpack/utils/docker-compose/Makefile
@@ -0,0 +1,50 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=docker-compose
+PKG_VERSION:=1.28.2
+PKG_RELEASE:=1
+
+PYPI_NAME:=docker-compose
+PKG_HASH:=2f148b590414915d029dad7551f4cdf0b03a774dc9baa674480217236d260cc1
+
+PKG_MAINTAINER:=Javier Marcet <javier@marcet.info>
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+include ../../lang/python/pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/python/python3-package.mk
+
+PYTHON3_PKG_SETUP_ARGS:=
+
+define Package/docker-compose
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Docker Compose
+ URL:=https://github.com/docker/compose
+ DEPENDS+=+docker \
+ +python3-light \
+ +python3-cached-property \
+ +python3-distro \
+ +python3-distutils \
+ +python3-docopt \
+ +python3-docker \
+ +python3-dockerpty \
+ +python3-dotenv \
+ +python3-jsonschema \
+ +python3-logging \
+ +python3-openssl \
+ +python3-pkg-resources \
+ +python3-requests \
+ +python3-texttable \
+ +python3-websocket-client \
+ +python3-yaml
+endef
+
+define Package/docker-compose/description
+ Multi-container orchestration for Docker
+endef
+
+$(eval $(call Py3Package,docker-compose))
+$(eval $(call BuildPackage,docker-compose))
+$(eval $(call BuildPackage,docker-compose-src))
diff --git a/external/subpack/utils/docker/Makefile b/external/subpack/utils/docker/Makefile
new file mode 100644
index 0000000..3d2349f
--- /dev/null
+++ b/external/subpack/utils/docker/Makefile
@@ -0,0 +1,72 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=docker
+PKG_VERSION:=20.10.17
+PKG_RELEASE:=$(AUTORELEASE)
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_GIT_URL:=github.com/docker/cli
+PKG_GIT_REF:=v$(PKG_VERSION)
+PKG_SOURCE_URL:=https://codeload.$(PKG_GIT_URL)/tar.gz/$(PKG_GIT_REF)?
+PKG_HASH:=ab2b59c2302017fea9ad2f70827e8a6f0204b557ce28e66bcb80fea262c9fbdc
+PKG_GIT_SHORT_COMMIT:=100c701 # SHA1 used within the docker executables
+
+PKG_MAINTAINER:=Gerard Ryan <G.M0N3Y.2503@gmail.com>
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=$(PKG_GIT_URL)
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/docker
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Docker Community Edition CLI
+ URL:=https://www.docker.com/
+ DEPENDS:=$(GO_ARCH_DEPENDS)
+endef
+
+define Package/docker/description
+The CLI used in the Docker CE and Docker EE products.
+endef
+
+GO_PKG_BUILD_VARS += GO111MODULE=auto
+TAR_OPTIONS:=--strip-components 1 $(TAR_OPTIONS)
+TAR_CMD=$(HOST_TAR) -C $(1) $(TAR_OPTIONS)
+TARGET_LDFLAGS += $(if $(CONFIG_USE_GLIBC),-lgcc_eh)
+
+define Build/Prepare
+ $(Build/Prepare/Default)
+
+ # Verify PKG_GIT_SHORT_COMMIT
+ ( \
+ EXPECTED_PKG_GIT_SHORT_COMMIT=$$$$( $(CURDIR)/../dockerd/git-short-commit.sh '$(PKG_GIT_URL)' '$(PKG_GIT_REF)' '$(TMP_DIR)/git-short-commit/$(PKG_NAME)-$(PKG_VERSION)' ); \
+ if [ "$$$${EXPECTED_PKG_GIT_SHORT_COMMIT}" != "$(strip $(PKG_GIT_SHORT_COMMIT))" ]; then \
+ echo "ERROR: Expected 'PKG_GIT_SHORT_COMMIT:=$$$${EXPECTED_PKG_GIT_SHORT_COMMIT}', found 'PKG_GIT_SHORT_COMMIT:=$(strip $(PKG_GIT_SHORT_COMMIT))'"; \
+ exit 1; \
+ fi \
+ )
+endef
+
+define Build/Compile
+ ( \
+ cd $(PKG_BUILD_DIR); \
+ $(GO_PKG_VARS) \
+ GITCOMMIT=$(PKG_GIT_SHORT_COMMIT) \
+ VERSION=$(PKG_VERSION) \
+ ./scripts/build/binary; \
+ )
+endef
+
+define Package/docker/install
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/build/docker $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,docker))
diff --git a/external/subpack/utils/dockerd/Config.in b/external/subpack/utils/dockerd/Config.in
new file mode 100644
index 0000000..21d55aa
--- /dev/null
+++ b/external/subpack/utils/dockerd/Config.in
@@ -0,0 +1,74 @@
+# These options are mostly specified by https://github.com/moby/moby/blob/master/contrib/check-config.sh
+
+config DOCKER_CGROUP_OPTIONS
+ bool "Enable available kernel support for CGroupsV1"
+ default n
+ depends on PACKAGE_dockerd
+ select KERNEL_CGROUP_DEVICE
+ select KERNEL_CGROUP_FREEZER
+ select KERNEL_NET_CLS_CGROUP
+ select KERNEL_CGROUP_NET_PRIO
+ select PACKAGE_cgroupfs-mount
+ help
+ Selects kernel options to enable CGroups V1.
+
+config DOCKER_OPTIONAL_FEATURES
+ bool "Enable optional kernel support for Docker"
+ default n
+ depends on PACKAGE_dockerd
+ select KERNEL_MEMCG_SWAP_ENABLED
+ select KERNEL_CFQ_GROUP_IOSCHED
+ select KERNEL_CGROUP_PERF
+ select KERNEL_CGROUP_HUGETLB
+ help
+ Select 'Optional Features' kernel options for Docker that are unselected.
+ See https://github.com/moby/moby/blob/master/contrib/check-config.sh
+
+menu "Network"
+ depends on PACKAGE_dockerd
+
+ config DOCKER_NET_OVERLAY
+ bool "Includes the Overlay network feature"
+ default n
+ select PACKAGE_kmod-vxlan
+ help
+ Selects kmod-vxlan for the Overlay network feature.
+
+ config DOCKER_NET_ENCRYPT
+ bool "Includes encrypted networking kernel modules"
+ depends on DOCKER_NET_OVERLAY
+ default n
+ select PACKAGE_kmod-crypto-gcm
+ select PACKAGE_kmod-crypto-seqiv
+ select PACKAGE_kmod-crypto-ghash
+ select PACKAGE_kmod-ipsec
+ help
+ Select needed kernel modules for encrypted networking support.
+
+ config DOCKER_NET_MACVLAN
+ bool "Includes macvlan kernel modules"
+ default n
+ select PACKAGE_kmod-macvlan
+ select PACKAGE_kmod-dummy
+
+ config DOCKER_NET_TFTP
+ bool "Includes ftp/tftp client kernel modules"
+ default n
+ select PACKAGE_kmod-nf-nathelper
+ select PACKAGE_kmod-nf-nathelper-extra
+endmenu
+
+menu "Storage"
+ depends on PACKAGE_dockerd
+
+ config DOCKER_STO_EXT4
+ bool "Enables support for ext3 or ext4 as the backing filesystem"
+ default n
+ select KERNEL_EXT4_FS_POSIX_ACL
+ select KERNEL_EXT4_FS_SECURITY
+
+ config DOCKER_STO_BTRFS
+ bool "Enables support for btrfs as the backing filesystem"
+ default n
+ select KERNEL_BTRFS_FS_POSIX_ACL
+endmenu
diff --git a/external/subpack/utils/dockerd/Makefile b/external/subpack/utils/dockerd/Makefile
new file mode 100644
index 0000000..f87fa20
--- /dev/null
+++ b/external/subpack/utils/dockerd/Makefile
@@ -0,0 +1,168 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dockerd
+PKG_VERSION:=20.10.17
+PKG_RELEASE:=$(AUTORELEASE)
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_GIT_URL:=github.com/moby/moby
+PKG_GIT_REF:=v$(PKG_VERSION)
+PKG_SOURCE_URL:=https://codeload.$(PKG_GIT_URL)/tar.gz/$(PKG_GIT_REF)?
+PKG_HASH:=061cf8579aa3c813c353c80fa480744e2f6cca2e6392f546bd0942a6a10c7a14
+PKG_GIT_SHORT_COMMIT:=a89b842 # SHA1 used within the docker executables
+
+PKG_MAINTAINER:=Gerard Ryan <G.M0N3Y.2503@gmail.com>
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/docker/docker
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/dockerd/config
+ source "$(SOURCE)/Config.in"
+endef
+
+define Package/dockerd
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Docker Community Edition Daemon
+ URL:=https://www.docker.com/
+ DEPENDS:=$(GO_ARCH_DEPENDS) +btrfs-progs +ca-certificates +containerd +libdevmapper +libnetwork +tini \
+ +KERNEL_SECCOMP:libseccomp +iptables-mod-extra +kmod-br-netfilter +kmod-ikconfig +kmod-nf-conntrack-netlink +kmod-nf-ipvs \
+ +kmod-nf-nat +kmod-veth
+ USERID:=docker:docker
+ MENU:=1
+endef
+
+define Package/dockerd/conffiles
+/etc/config/dockerd
+endef
+
+define Package/dockerd/description
+The Docker CE Engine.
+endef
+
+GO_PKG_BUILD_VARS += GO111MODULE=auto
+TAR_OPTIONS:=--strip-components 1 $(TAR_OPTIONS)
+TAR_CMD=$(HOST_TAR) -C $(1) $(TAR_OPTIONS)
+TARGET_LDFLAGS += $(if $(CONFIG_USE_GLIBC),-lgcc_eh)
+
+# $(1) = path to dependent package 'Makefile'
+# $(2) = relevant dependency '.installer' file
+define EnsureVendoredVersion
+ ( \
+ DEP_VER=$$$$( grep --only-matching --perl-regexp '(?<=PKG_VERSION:=)(.*)' "$(1)" ); \
+ VEN_VER=$$$$( grep --only-matching --perl-regexp '(?<=_VERSION:=v)(.*)(?=})' "$(PKG_BUILD_DIR)/hack/dockerfile/install/$(2)" ); \
+ if [ "$$$${VEN_VER}" != "$$$${DEP_VER}" ]; then \
+ echo "ERROR: Expected 'PKG_VERSION:=$$$${VEN_VER}' in '$(1)', found 'PKG_VERSION:=$$$${DEP_VER}'"; \
+ exit 1; \
+ fi \
+ )
+endef
+
+# $(1) = path to dependent package 'Makefile'
+# $(2) = relevant dependency '.installer' file
+define EnsureVendoredCommit
+ ( \
+ DEP_VER=$$$$( grep --only-matching --perl-regexp '(?<=PKG_SOURCE_VERSION:=)(.*)' "$(1)" ); \
+ VEN_VER=$$$$( grep --only-matching --perl-regexp '(?<=_COMMIT:=)(.*)(?=})' "$(PKG_BUILD_DIR)/hack/dockerfile/install/$(2)" ); \
+ if [ "$$$${VEN_VER}" != "$$$${DEP_VER}" ]; then \
+ echo "ERROR: Expected 'PKG_SOURCE_VERSION:=$$$${VEN_VER}' in '$(1)', found 'PKG_SOURCE_VERSION:=$$$${DEP_VER}'"; \
+ exit 1; \
+ fi \
+ )
+endef
+
+define Build/Prepare
+ $(Build/Prepare/Default)
+
+ # Verify dependencies are the vendored version
+ $(call EnsureVendoredVersion,../containerd/Makefile,containerd.installer)
+ $(call EnsureVendoredCommit,../libnetwork/Makefile,proxy.installer)
+ $(call EnsureVendoredVersion,../runc/Makefile,runc.installer)
+ $(call EnsureVendoredVersion,../tini/Makefile,tini.installer)
+
+ # Verify CLI is the same version
+ ( \
+ CLI_MAKEFILE="../docker/Makefile"; \
+ CLI_VERSION=$$$$( grep --only-matching --perl-regexp '(?<=PKG_VERSION:=)(.*)' "$$$${CLI_MAKEFILE}" ); \
+ if [ "$$$${CLI_VERSION}" != "$(PKG_VERSION)" ]; then \
+ echo "ERROR: Expected 'PKG_VERSION:=$(PKG_VERSION)' in '$$$${CLI_MAKEFILE}', found 'PKG_VERSION:=$$$${CLI_VERSION}'"; \
+ exit 1; \
+ fi \
+ )
+
+ # Verify PKG_GIT_SHORT_COMMIT
+ ( \
+ EXPECTED_PKG_GIT_SHORT_COMMIT=$$$$( $(CURDIR)/git-short-commit.sh '$(PKG_GIT_URL)' '$(PKG_GIT_REF)' '$(TMP_DIR)/git-short-commit/$(PKG_NAME)-$(PKG_VERSION)' ); \
+ if [ "$$$${EXPECTED_PKG_GIT_SHORT_COMMIT}" != "$(strip $(PKG_GIT_SHORT_COMMIT))" ]; then \
+ echo "ERROR: Expected 'PKG_GIT_SHORT_COMMIT:=$$$${EXPECTED_PKG_GIT_SHORT_COMMIT}', found 'PKG_GIT_SHORT_COMMIT:=$(strip $(PKG_GIT_SHORT_COMMIT))'"; \
+ exit 1; \
+ fi \
+ )
+endef
+
+BUILDTAGS:=
+ifeq ($(KERNEL_SECCOMP),y)
+BUILDTAGS += seccomp
+endif
+ifeq ($(CONFIG_SELINUX),y)
+BUILDTAGS += selinux
+endif
+
+define Build/Compile
+ ( \
+ cd $(PKG_BUILD_DIR); \
+ $(GO_PKG_VARS) \
+ DOCKER_GITCOMMIT=$(PKG_GIT_SHORT_COMMIT) \
+ DOCKER_BUILDTAGS='$(BUILDTAGS)' \
+ VERSION=$(PKG_VERSION) \
+ ./hack/make.sh binary; \
+ )
+endef
+
+define Package/dockerd/install
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/bundles/binary-daemon/dockerd $(1)/usr/bin/
+
+ $(INSTALL_DIR) $(1)/opt/docker/
+ $(INSTALL_DIR) $(1)/usr/share/docker/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/contrib/check-config.sh $(1)/usr/share/docker/
+
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/dockerd.init $(1)/etc/init.d/dockerd
+
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) ./files/etc/config/dockerd $(1)/etc/config/dockerd
+
+ # Must be after systcl 11-br-netfilter.conf from kmod-br-netfilter
+ $(INSTALL_DIR) $(1)/etc/sysctl.d
+ $(INSTALL_DATA) ./files/etc/sysctl.d/sysctl-br-netfilter-ip.conf \
+ $(1)/etc/sysctl.d/12-br-netfilter-ip.conf
+endef
+
+define Package/dockerd/postinst
+#!/bin/sh
+[ -n "$$IPKG_INSTROOT" ] || {
+ /etc/init.d/dockerd enable
+ /etc/init.d/dockerd uciadd
+ /etc/init.d/dockerd start
+}
+endef
+
+define Package/dockerd/prerm
+#!/bin/sh
+[ -n "$$IPKG_INSTROOT" ] || {
+ /etc/init.d/dockerd disable
+ /etc/init.d/dockerd stop
+ /etc/init.d/dockerd ucidel
+}
+endef
+
+$(eval $(call BuildPackage,dockerd))
diff --git a/external/subpack/utils/dockerd/files/dockerd.init b/external/subpack/utils/dockerd/files/dockerd.init
new file mode 100755
index 0000000..68a40de
--- /dev/null
+++ b/external/subpack/utils/dockerd/files/dockerd.init
@@ -0,0 +1,283 @@
+#!/bin/sh /etc/rc.common
+
+USE_PROCD=1
+START=99
+
+extra_command "uciadd" "<interface> <device> <zone> Add docker bridge configuration to network and firewall uci config"
+extra_command "ucidel" "<interface> <device> <zone> Delete docker bridge configuration from network and firewall uci config"
+
+DOCKER_CONF_DIR="/tmp/dockerd"
+DOCKERD_CONF="${DOCKER_CONF_DIR}/daemon.json"
+
+uci_quiet() {
+ uci -q "${@}" >/dev/null
+}
+
+json_add_array_string() {
+ json_add_string "" "${1}"
+}
+
+find_network_device() {
+ local device="${1}"
+ local device_section=""
+
+ check_device() {
+ local cfg="${1}"
+ local device="${2}"
+
+ local type name
+ config_get type "${cfg}" type
+ config_get name "${cfg}" name
+
+ [ "${type}" = "bridge" ] && [ "${name}" = "${device}" ] \
+ && device_section="${cfg}"
+ }
+
+ config_load network
+ config_foreach check_device device "${device}"
+
+ echo "${device_section}"
+}
+
+boot() {
+ uciadd
+ rc_procd start_service
+}
+
+uciadd() {
+ local iface="${1}"
+ local device="${2}"
+ local zone="${3}"
+
+ [ -z "${iface}" ] && {
+ iface="docker"
+ device="docker0"
+ zone="docker"
+ }
+
+ /etc/init.d/dockerd running && {
+ echo "Please stop dockerd service first"
+ exit 0
+ }
+
+ # Add network interface
+ if ! uci_quiet get network.${iface}; then
+ logger -t "dockerd-init" -p notice "Adding interface '${iface}' to network config"
+ uci_quiet add network interface
+ uci_quiet rename network.@interface[-1]="${iface}"
+ uci_quiet set network.@interface[-1].device="${device}"
+ uci_quiet set network.@interface[-1].proto="none"
+ uci_quiet set network.@interface[-1].auto="0"
+ uci_quiet commit network
+ fi
+
+ # Add docker bridge device
+ if [ "$(find_network_device "$device")" = "" ]; then
+ logger -t "dockerd-init" -p notice "Adding bridge device '${device}' to network config"
+ uci_quiet add network device
+ uci_quiet set network.@device[-1].type="bridge"
+ uci_quiet set network.@device[-1].name="${device}"
+ uci_quiet commit network
+ else
+ logger -t "dockerd-init" -p notice "Bridge device '${device}' already defined in network config"
+ fi
+
+ # Add firewall zone
+ if ! uci_quiet get firewall.${zone}; then
+ logger -t "dockerd-init" -p notice "Adding firewall zone '${zone}' to firewall config"
+ uci_quiet add firewall zone
+ uci_quiet rename firewall.@zone[-1]="${zone}"
+ uci_quiet set firewall.@zone[-1].input="ACCEPT"
+ uci_quiet set firewall.@zone[-1].output="ACCEPT"
+ uci_quiet set firewall.@zone[-1].forward="ACCEPT"
+ uci_quiet set firewall.@zone[-1].name="${zone}"
+ uci_quiet commit firewall
+ fi
+
+ # Add interface to firewall zone
+ if uci_quiet get firewall.${zone}; then
+ uci_quiet del_list firewall.${zone}.network="${iface}"
+ uci_quiet add_list firewall.${zone}.network="${iface}"
+ uci_quiet commit firewall
+ fi
+
+ reload_config
+}
+
+ucidel() {
+ local iface="${1}"
+ local device="${2}"
+ local zone="${3}"
+
+ [ -z "${iface}" ] && {
+ iface="docker"
+ device="docker0"
+ zone="docker"
+ }
+
+ /etc/init.d/dockerd running && {
+ echo "Please stop dockerd service first"
+ exit 0
+ }
+
+ # Remove network device
+ if uci_quiet delete network.$(find_network_device "${device}"); then
+ logger -t "dockerd-init" -p notice "Deleting bridge device '${device}' from network config"
+ uci_quiet commit network
+ fi
+
+ # Remove network interface
+ if uci_quiet get network.${iface}; then
+ logger -t "dockerd-init" -p notice "Deleting interface '${iface}' from network config"
+ uci_quiet delete network.${iface}
+ uci_quiet commit network
+ fi
+
+ # Remove interface from firewall zone
+ if uci_quiet get firewall.${zone}; then
+ logger -t "dockerd-init" -p notice "Deleting network interface '${iface}' in zone '${zone}' from firewall config"
+ uci_quiet del_list firewall.${zone}.network="${iface}"
+ uci_quiet commit firewall
+ # Remove Firewall zone if network is empty
+ if ! uci_quiet get firewall.${zone}.network; then
+ logger -t "dockerd-init" -p notice "Deleting firewall zone '${zone}' from firewall config"
+ uci_quiet delete firewall.${zone}
+ fi
+ uci_quiet commit firewall
+ fi
+
+ reload_config
+}
+
+process_config() {
+ local alt_config_file data_root log_level iptables bip
+
+ [ -f /etc/config/dockerd ] || {
+ # Use the daemon default configuration
+ DOCKERD_CONF=""
+ return 0
+ }
+
+ # reset configuration
+ rm -fr "${DOCKER_CONF_DIR}"
+ mkdir -p "${DOCKER_CONF_DIR}"
+
+ config_load 'dockerd'
+ config_get alt_config_file globals alt_config_file
+ [ -n "${alt_config_file}" ] && [ -f "${alt_config_file}" ] && {
+ ln -s "${alt_config_file}" "${DOCKERD_CONF}"
+ return 0
+ }
+
+ config_get data_root globals data_root "/opt/docker/"
+ config_get log_level globals log_level "warn"
+ config_get_bool iptables globals iptables "1"
+
+ # Don't add these options by default
+ # omission == docker defaults
+ config_get bip globals bip ""
+ config_get registry_mirrors globals registry_mirrors ""
+ config_get hosts globals hosts ""
+ config_get dns globals dns ""
+ config_get_bool ipv6 globals ipv6 ""
+ config_get ip globals ip ""
+ config_get fixed_cidr globals fixed_cidr ""
+ config_get fixed_cidr_v6 globals fixed_cidr_v6 ""
+
+ . /usr/share/libubox/jshn.sh
+ json_init
+ json_add_string "data-root" "${data_root}"
+ json_add_string "log-level" "${log_level}"
+ json_add_boolean "iptables" "${iptables}"
+ [ -z "${bip}" ] || json_add_string "bip" "${bip}"
+ [ -z "${registry_mirrors}" ] || json_add_array "registry-mirrors"
+ [ -z "${registry_mirrors}" ] || config_list_foreach globals registry_mirrors json_add_array_string
+ [ -z "${registry_mirrors}" ] || json_close_array
+ [ -z "${hosts}" ] || json_add_array "hosts"
+ [ -z "${hosts}" ] || config_list_foreach globals hosts json_add_array_string
+ [ -z "${hosts}" ] || json_close_array
+ [ -z "${dns}" ] || json_add_array "dns"
+ [ -z "${dns}" ] || config_list_foreach globals dns json_add_array_string
+ [ -z "${dns}" ] || json_close_array
+ [ -z "${ipv6}" ] || json_add_boolean "ipv6" "${ipv6}"
+ [ -z "${ip}" ] || json_add_string "ip" "${ip}"
+ [ -z "${fixed_cidr}" ] || json_add_string "fixed-cidr" "${fixed_cidr}"
+ [ -z "${fixed_cidr_v6}" ] || json_add_string "fixed-cidr-v6" "${fixed_cidr_v6}"
+ json_dump > "${DOCKERD_CONF}"
+
+ [ "${iptables}" -eq "1" ] && config_foreach iptables_add_blocking_rule firewall
+}
+
+start_service() {
+ local nofile=$(cat /proc/sys/fs/nr_open)
+
+ process_config
+
+ procd_open_instance
+ procd_set_param stderr 1
+ if [ -z "${DOCKERD_CONF}" ]; then
+ procd_set_param command /usr/bin/dockerd
+ else
+ procd_set_param command /usr/bin/dockerd --config-file="${DOCKERD_CONF}"
+ fi
+ procd_set_param limits nofile="${nofile} ${nofile}"
+ procd_close_instance
+}
+
+reload_service() {
+ process_config
+ procd_send_signal dockerd
+}
+
+service_triggers() {
+ procd_add_reload_trigger 'dockerd'
+}
+
+iptables_add_blocking_rule() {
+ local cfg="${1}"
+
+ local device=""
+ local extra_iptables_args=""
+
+ handle_iptables_rule() {
+ local interface="${1}"
+ local outbound="${2}"
+ local extra_iptables_args="${3}"
+
+ local inbound=""
+
+ . /lib/functions/network.sh
+ network_get_physdev inbound "${interface}"
+
+ [ -z "${inbound}" ] && {
+ logger -t "dockerd-init" -p notice "Unable to get physical device for interface ${interface}"
+ return
+ }
+
+ # Wait for a maximum of 10 second per command, retrying every millisecond
+ local iptables_wait_args="--wait 10 --wait-interval 1000"
+
+ # Ignore errors as it might already be present
+ iptables ${iptables_wait_args} --table filter --new DOCKER-USER 2>/dev/null
+ if ! iptables ${iptables_wait_args} --table filter --check DOCKER-USER --in-interface "${inbound}" --out-interface "${outbound}" ${extra_iptables_args} --jump REJECT 2>/dev/null; then
+ logger -t "dockerd-init" -p notice "Drop traffic from ${inbound} to ${outbound}"
+ iptables ${iptables_wait_args} --table filter --insert DOCKER-USER --in-interface "${inbound}" --out-interface "${outbound}" ${extra_iptables_args} --jump REJECT
+ fi
+ }
+
+ config_get device "${cfg}" device
+
+ [ -z "${device}" ] && {
+ logger -t "dockerd-init" -p notice "No device configured for ${cfg}"
+ return
+ }
+
+ config_get extra_iptables_args "${cfg}" extra_iptables_args
+ config_list_foreach "${cfg}" blocked_interfaces handle_iptables_rule "${device}" "${extra_iptables_args}"
+}
+
+stop_service() {
+ if /etc/init.d/dockerd running; then
+ service_stop "/usr/bin/dockerd"
+ fi
+}
diff --git a/external/subpack/utils/dockerd/files/etc/config/dockerd b/external/subpack/utils/dockerd/files/etc/config/dockerd
new file mode 100644
index 0000000..872ff13
--- /dev/null
+++ b/external/subpack/utils/dockerd/files/etc/config/dockerd
@@ -0,0 +1,29 @@
+# The following settings require a restart of docker to take full effect, A reload will only have partial or no effect:
+# bip
+# blocked_interfaces
+# extra_iptables_args
+# device
+
+config globals 'globals'
+# option alt_config_file '/etc/docker/daemon.json'
+ option data_root '/opt/docker/'
+ option log_level 'warn'
+ option iptables '1'
+# list hosts 'unix:///var/run/docker.sock'
+# option bip '172.18.0.1/24'
+# option fixed_cidr '172.17.0.0/16'
+# option fixed_cidr_v6 'fc00:1::/80'
+# option ipv6 '1'
+# option ip '::ffff:0.0.0.0'
+# list dns '172.17.0.1'
+# list registry_mirrors 'https://<my-docker-mirror-host>'
+# list registry_mirrors 'https://hub.docker.com'
+
+# Docker ignores fw3 rules and by default all external source IPs are allowed to connect to the Docker host.
+# See https://docs.docker.com/network/iptables/ for more details.
+# firewall config changes are only additive i.e firewall will need to be restarted first to clear old changes,
+# then docker restarted to load in new changes.
+config firewall 'firewall'
+ option device 'docker0'
+ list blocked_interfaces 'wan'
+# option extra_iptables_args '--match conntrack ! --ctstate RELATED,ESTABLISHED' # allow outbound connections
diff --git a/external/subpack/utils/dockerd/files/etc/sysctl.d/sysctl-br-netfilter-ip.conf b/external/subpack/utils/dockerd/files/etc/sysctl.d/sysctl-br-netfilter-ip.conf
new file mode 100644
index 0000000..7b48860
--- /dev/null
+++ b/external/subpack/utils/dockerd/files/etc/sysctl.d/sysctl-br-netfilter-ip.conf
@@ -0,0 +1,7 @@
+# Do not edit, changes to this file will be lost on upgrades
+# /etc/sysctl.conf can be used to customize sysctl settings
+
+# enable bridge firewalling for docker
+net.bridge.bridge-nf-call-ip6tables=1
+net.bridge.bridge-nf-call-iptables=1
+
diff --git a/external/subpack/utils/dockerd/git-short-commit.sh b/external/subpack/utils/dockerd/git-short-commit.sh
new file mode 100755
index 0000000..ea8611b
--- /dev/null
+++ b/external/subpack/utils/dockerd/git-short-commit.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# USAGE: git-short-commit.sh <GIT_URL> <GIT_REF> <GIT_DIR>
+#
+
+set -e
+
+error() {
+ echo "ERROR: ${*}" >&2
+ exit 1
+}
+
+GIT_URL="${1}"
+if [ -z "${GIT_URL}" ]; then
+ error "Git URL not specified"
+fi
+
+GIT_REF="${2}"
+if [ -z "${GIT_REF}" ]; then
+ error "Git reference not specified"
+fi
+
+GIT_DIR="${3}"
+if [ -z "${GIT_DIR}" ]; then
+ error "Git clone directory not specified"
+fi
+
+clean_up() {
+ rm --force --recursive "${GIT_DIR}"
+}
+trap clean_up EXIT
+
+git init --quiet "${GIT_DIR}"
+(
+ cd "${GIT_DIR}"
+ for PREFIX in "" "https://" "http://" "git@"; do
+ echo "Trying remote '${PREFIX}${GIT_URL}'" >&2
+ git remote add origin "${PREFIX}${GIT_URL}"
+
+ if git fetch --depth 1 origin "${GIT_REF}"; then
+ git checkout --detach FETCH_HEAD --
+ git rev-parse --short HEAD
+ break
+ fi
+
+ git remote remove origin
+ done
+)
diff --git a/external/subpack/utils/dockerd/patches/001-libdevmapper_name_fix.patch b/external/subpack/utils/dockerd/patches/001-libdevmapper_name_fix.patch
new file mode 100644
index 0000000..b9b0a6b
--- /dev/null
+++ b/external/subpack/utils/dockerd/patches/001-libdevmapper_name_fix.patch
@@ -0,0 +1,11 @@
+--- a/hack/make.sh
++++ b/hack/make.sh
+@@ -95,7 +95,7 @@ fi
+ # with a newer libdevmapper than the one it was built with.
+ if
+ command -v gcc &> /dev/null \
+- && ! (echo -e '#include <libdevmapper.h>\nint main() { dm_task_deferred_remove(NULL); }' | gcc -xc - -o /dev/null $(pkg-config --libs devmapper) &> /dev/null) \
++ && ! (echo -e '#include <libdevmapper.h>\nint main() { dm_task_deferred_remove(NULL); }' | gcc -xc - -o /dev/null $(pkg-config --libs libdevmapper) &> /dev/null) \
+ ;
+ then
+ add_buildtag libdm dlsym_deferred_remove
diff --git a/external/subpack/utils/domoticz/Makefile b/external/subpack/utils/domoticz/Makefile
new file mode 100644
index 0000000..19b2967
--- /dev/null
+++ b/external/subpack/utils/domoticz/Makefile
@@ -0,0 +1,132 @@
+#
+# Copyright (C) 2016 - 2020 Stijn Tintel <stijn@linux-ipv6.be>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=domoticz
+PKG_VERSION:=2021.1
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/domoticz/domoticz/archive/$(PKG_VERSION)/$(PKG_SOURCE)
+PKG_HASH:=c4dc3455edae8bf00d2e950002f70d5b90ac577b1559ef7ada6870d970069fbb
+
+PKG_MAINTAINER:=David Woodhouse <dwmw2@infradead.org>
+PKG_LICENSE:=GPL-3.0
+PKG_LICENSE_FILES:=License.txt
+
+PKG_BUILD_DEPENDS:=python3 minizip cereal
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+CMAKE_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/domoticz
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Open Source Home Automation System
+ URL:=http://domoticz.com/
+ USERID:=domoticz=6144:domoticz=6144
+ DEPENDS:= \
+ +boost \
+ +boost-date_time \
+ +boost-system \
+ +boost-thread \
+ +jsoncpp \
+ +libcurl \
+ +python3 \
+ +minizip \
+ +lua5.3 \
+ +libfmt \
+ +libmosquitto \
+ +libopenssl \
+ +libopenzwave \
+ +libsqlite3 \
+ +libstdcpp \
+ +telldus-core \
+ +zlib
+endef
+
+define Package/domoticz/description
+ Domoticz is a Home Automation System that lets you monitor and configure various devices like: Lights, Switches, various sensors/meters like Temperature, Rain, Wind, UV, Electra, Gas, Water and much more. Notifications/Alerts can be sent to any mobile device.
+endef
+
+CMAKE_OPTIONS += \
+ -DBUILD_SHARED_LIBS=yes \
+ -DBoost_NO_BOOST_CMAKE=yes \
+ -DGIT_SUBMODULE=no \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DUSE_BUILTIN_MQTT=no \
+ -DUSE_BUILTIN_SQLITE=no \
+ -DUSE_BUILTIN_JSONCPP=no \
+ -DUSE_BUILTIN_MINIZIP=no \
+ -DUSE_BUILTIN_LIBFMT=no \
+ -DUSE_LUA_STATIC=no \
+ -DUSE_STATIC_BOOST=no \
+ -DUSE_STATIC_LIBSTDCXX=no \
+ -DUSE_STATIC_OPENZWAVE=no \
+ -DUSE_OPENSSL_STATIC=no \
+ -DUSE_PYTHON=yes \
+ -DWITH_LIBUSB=no
+
+TARGET_CFLAGS += -flto
+TARGET_CXXFLAGS += -DWITH_GPIO -flto
+TARGET_LDFLAGS += -lpython3.9
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ # Remove unwanted scripts
+ cd $(PKG_BUILD_DIR)/scripts && rm -rf \
+ buienradar_rain_example.pl \
+ _domoticz_main* \
+ download_update.sh \
+ dzVents/{.gitignore,documentation,examples,generated_scripts,data} \
+ dzVents/runtime/{integration-tests,misc/smoothing.xlsx,tests} \
+ logrotate/ \
+ lua_parsers/example* \
+ lua/*demo.lua \
+ python/ \
+ readme.txt \
+ restart_domoticz \
+ templates/All.Python \
+ update_domoticz \
+ domoticz.conf
+ # Remove *.md
+ cd $(PKG_BUILD_DIR) && $(FIND) -name '*.md' -delete
+endef
+
+define Package/domoticz/install
+ $(INSTALL_DIR) $(1)/etc/config $(1)/etc/hotplug.d/tty $(1)/etc/init.d $(1)/etc/domoticz/plugins
+ $(INSTALL_BIN) ./files/domoticz.hotplug $(1)/etc/hotplug.d/tty/domoticz
+ $(INSTALL_BIN) ./files/domoticz.init $(1)/etc/init.d/domoticz
+ $(INSTALL_CONF) ./files/domoticz.config $(1)/etc/config/domoticz
+ $(INSTALL_DIR) $(1)/usr/share/domoticz $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/dzVents $(1)/usr/share/domoticz/dzVents
+ $(CP) $(PKG_INSTALL_DIR)/usr/Config $(1)/usr/share/domoticz/Config
+ $(CP) $(PKG_INSTALL_DIR)/usr/scripts $(1)/etc/domoticz/scripts
+ ln -sf /var/lib/domoticz/dzVents/generated_scripts $(1)/etc/domoticz/scripts/dzVents
+ ln -sf /var/lib/domoticz/dzVents/data $(1)/etc/domoticz/scripts/dzVents
+ $(CP) $(PKG_INSTALL_DIR)/usr/www $(1)/usr/share/domoticz/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/domoticz $(1)/usr/bin/domoticz
+ # compress static web content
+ find $(1)/usr/share/domoticz/www -name "*.css" -exec gzip -9 {} \;
+ find $(1)/usr/share/domoticz/www -name "*.js" -exec gzip -9 {} \;
+ gzip -9 $(1)/usr/share/domoticz/www/*.html
+ gzip -9 $(1)/usr/share/domoticz/www/secpanel/*.html
+ find $(1)/usr/share/domoticz/www/views -name "*.html" -exec sh -c 'grep -q "<\!--#embed" {} || gzip -9 {}' \;
+endef
+
+define Package/domoticz/conffiles
+/etc/config/domoticz
+/var/lib/domoticz/
+/etc/domoticz/
+endef
+
+$(eval $(call BuildPackage,domoticz))
diff --git a/external/subpack/utils/domoticz/files/domoticz.config b/external/subpack/utils/domoticz/files/domoticz.config
new file mode 100644
index 0000000..870701c
--- /dev/null
+++ b/external/subpack/utils/domoticz/files/domoticz.config
@@ -0,0 +1,29 @@
+config domoticz
+ option disabled '1'
+ option loglevel '1'
+ option syslog 'daemon'
+ # option sslcert '/path/to/ssl.crt'
+ # option sslkey '/path/to/ssl.key'
+ # option sslpass 'passphrase'
+ # option ssldhparam '/path/to/dhparam.pem'
+ option sslwww '0'
+ # CAUTION - by default, /var is not persistent accross reboots
+ # Don't forget the trailing / - domoticz requires it
+ option userdata '/var/lib/domoticz/'
+
+#config device
+# option product '658/200/0'
+# option symlink 'ttyACM-aeotec-zstick-g5'
+
+#config device
+# option serial '526359'
+# option symlink 'ttyUSB-serial'
+
+#config device
+# option usbif '2-1:1.0'
+# option symlink 'ttyUSB-port1'
+
+#config device
+# option product '67b/2303/202'
+# option usbif '2-2:1.0'
+# option symlink 'ttyUSB-port2'
diff --git a/external/subpack/utils/domoticz/files/domoticz.hotplug b/external/subpack/utils/domoticz/files/domoticz.hotplug
new file mode 100644
index 0000000..3cd8651
--- /dev/null
+++ b/external/subpack/utils/domoticz/files/domoticz.hotplug
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+. /lib/functions.sh
+
+[ "$SUBSYSTEM" = "tty" ] || exit 0
+
+add() {
+ local cfg="$1"
+ local product serial symlink usbif
+
+ [ -c "/dev/$DEVICENAME" ] || return
+
+ config_get product "$cfg" product
+ config_get serial "$cfg" serial
+ config_get symlink "$cfg" symlink
+ config_get usbif "$cfg" usbif
+
+ [ -z "$product" -a -z "$serial" -a -z "$usbif" ] && return
+
+ . "/sys/$DEVPATH/device/../uevent"
+ SERIAL="$(cat /sys/$DEVPATH/device/../../serial)" 2>/dev/null
+ USBIF="$(echo $DEVPATH | awk -F/ 'BEGIN {i=3}; /ACM/ {i=2}; END {print $(NF-i)}')"
+
+ [ -n "$product" -a "$product" != "$PRODUCT" ] && return
+ [ -n "$serial" -a "$serial" != "$SERIAL" ] && return
+ [ -n "$usbif" -a "$usbif" != "$USBIF" ] && return
+
+ chgrp domoticz "/dev/$DEVICENAME"
+ chmod g+rw "/dev/$DEVICENAME"
+
+ [ -n "$symlink" ] && ln -sf "/dev/$DEVICENAME" "/dev/$symlink"
+}
+
+remove() {
+ local cfg="$1"
+ local symlink
+
+ config_get symlink "$cfg" symlink
+
+ [ "/dev/$DEVICENAME" = "$(readlink /dev/$symlink)" ] && rm "/dev/$symlink"
+}
+
+config_load "domoticz"
+config_foreach "$ACTION" device
diff --git a/external/subpack/utils/domoticz/files/domoticz.init b/external/subpack/utils/domoticz/files/domoticz.init
new file mode 100644
index 0000000..8c0c129
--- /dev/null
+++ b/external/subpack/utils/domoticz/files/domoticz.init
@@ -0,0 +1,71 @@
+#!/bin/sh /etc/rc.common
+
+START=99
+USE_PROCD=1
+PROG=/usr/bin/domoticz
+PIDFILE=/var/run/domoticz.pid
+
+start_domoticz() {
+ local section="$1"
+ local loglevel sslcert sslpass sslwww syslog userdata
+
+ config_get loglevel "$section" "loglevel"
+ config_get sslcert "$section" "sslcert"
+ config_get sslkey "$section" "sslkey"
+ config_get sslpass "$section" "sslpass"
+ config_get ssldhparam "$section" "ssldhparam"
+ config_get sslwww "$section" "sslwww"
+ config_get syslog "$section" "syslog"
+ config_get userdata "$section" "userdata" userdata /var/lib/domoticz
+
+ [ -n "$loglevel" ] && procd_append_param command -loglevel "$loglevel"
+ [ -n "$syslog" ] && procd_append_param command -syslog "$syslog"
+
+ [ -d "${userdata}" ] || {
+ mkdir -p "${userdata}"
+ chmod 0770 "$userdata"
+ chown domoticz:domoticz "$userdata"
+ }
+
+ # By default, ${userdata}/scripts is a symlink to /etc/domoticz/scripts
+ # and the two dzVents directories under there which Domoticz will actually
+ # write to at runtime are symlinked back to /var/lib again.
+ [ -d "${userdata}/plugins" ] || ln -sf /etc/domoticz/plugins "${userdata}/plugins"
+ [ -d "${userdata}/scripts" ] || ln -sf /etc/domoticz/scripts "${userdata}/scripts"
+ for DIR in data generated_scripts; do
+ [ -d /var/lib/domoticz/dzVents/$DIR ] || {
+ mkdir -p /var/lib/domoticz/dzVents/$DIR
+ chown domoticz.domoticz /var/lib/domoticz/dzVents/$DIR
+ }
+ done
+ procd_append_param command -userdata "$userdata"
+
+ [ -n "$sslcert" -a "${sslwww:-0}" -gt 0 ] && {
+ procd_append_param command -sslcert "$sslcert"
+ procd_append_param command -sslwww "$sslwww"
+ [ -n "$sslkey" ] && procd_append_param command -sslkey "$sslkey"
+ [ -n "$sslpass" ] && procd_append_param command -sslpass "$sslpass"
+ [ -n "$ssldhparam" ] && procd_append_param command -ssldhparam "$ssldhparam"
+ } || procd_append_param command -sslwww 0
+}
+
+start_service() {
+ procd_open_instance
+
+ procd_set_param command "$PROG"
+ procd_append_param command -noupdates
+ procd_append_param command -approot /usr/share/domoticz/
+
+ config_load "domoticz"
+ config_get_bool disabled "$section" "disabled" 0
+ [ "$disabled" -gt 0 ] && return 1
+ config_foreach start_domoticz domoticz
+
+ procd_set_param pidfile "$PIDFILE"
+ procd_set_param respawn
+ procd_set_param stdout 0
+ procd_set_param term_timeout 10
+ procd_set_param user "domoticz"
+
+ procd_close_instance
+}
diff --git a/external/subpack/utils/domoticz/patches/012-minizip-overflow.patch b/external/subpack/utils/domoticz/patches/012-minizip-overflow.patch
new file mode 100644
index 0000000..570ebfc
--- /dev/null
+++ b/external/subpack/utils/domoticz/patches/012-minizip-overflow.patch
@@ -0,0 +1,41 @@
+From 3c23a7863c0b01273d4c36423769443ea7e4a7bb Mon Sep 17 00:00:00 2001
+From: David Woodhouse <dwmw2@infradead.org>
+Date: Fri, 5 Jun 2020 15:02:41 +0100
+Subject: [PATCH 1/2] unzip: reduce file name size to 65535 to work with
+ external minizip
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The external minizip project has changed the unzGetCurrentFileInfo()
+function to take a uint16_t as the filename size, instead of a uLong
+as in the original version in zlib.
+
+(Reported as https://github.com/nmoinvaz/minizip/issues/490 but it
+was 3½ years ago and might be too late to fix it now, although changing
+it back to a *larger* type is a lot safer than reducing the size, and
+perhaps they should.)
+
+This means that our 65536-byte buffer gets truncated to zero, as the
+compiler tells us when we build agaisnt the external minizip:
+
+domoticz/main/unzip_stream.h:140:50: warning: conversion from ‘long unsigned int’ to ‘uint16_t’ {aka ‘short unsigned int’} changes value from ‘65536’ to ‘0’ [-Woverflow]
+ 140 | unzGetCurrentFileInfo(handler_, &info, path, sizeof(path), NULL, 0, NULL, 0);
+ | ^~~~~~~~~~~~
+
+Reduce the buffer size to 65535 bytes instead.
+---
+ main/unzip_stream.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/main/unzip_stream.h
++++ b/main/unzip_stream.h
+@@ -143,7 +143,7 @@ namespace clx {
+ basic_unzip_stream& open(handler_type h) {
+ handler_ = h;
+ if (handler_) {
+- char path[65536];
++ char path[65535];
+ unz_file_info info;
+ unzGetCurrentFileInfo(handler_, &info, path, sizeof(path), NULL, 0, NULL, 0);
+ path_ = path;
diff --git a/external/subpack/utils/dosfstools/Makefile b/external/subpack/utils/dosfstools/Makefile
new file mode 100644
index 0000000..38c3041
--- /dev/null
+++ b/external/subpack/utils/dosfstools/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2006-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dosfstools
+PKG_VERSION:=4.1
+PKG_RELEASE:=4
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://github.com/dosfstools/dosfstools/releases/download/v$(PKG_VERSION)/ \
+ http://fossies.org/linux/misc
+PKG_HASH:=e6b2aca70ccc3fe3687365009dd94a2e18e82b688ed4e260e04b7412471cc173
+PKG_MAINTAINER:=Álvaro Fernández Rojas <noltari@gmail.com>
+
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:dosfstools_project:dosfstools
+
+PKG_INSTALL:=1
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+CONFIGURE_ARGS += \
+ --without-udev
+
+define Package/dosfstools
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Filesystem
+ DEPENDS:=$(ICONV_DEPENDS)
+ TITLE:=Utilities for making and checking MS-DOS FAT filesystems
+ URL:=https://github.com/dosfstools
+endef
+
+define Package/dosfstools/description
+ The dosfstools package includes the mkfs.fat and fsck.fat utilities, which respectively make and check MS-DOS FAT filesystems.
+endef
+
+define Package/dosfstools/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/fatlabel $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/fsck.fat $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/mkfs.fat $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,dosfstools))
diff --git a/external/subpack/utils/dosfstools/patches/010-iconv.patch b/external/subpack/utils/dosfstools/patches/010-iconv.patch
new file mode 100644
index 0000000..f594285
--- /dev/null
+++ b/external/subpack/utils/dosfstools/patches/010-iconv.patch
@@ -0,0 +1,24 @@
+From e18bcc65d5772e518c6496b439bad8a986f7e434 Mon Sep 17 00:00:00 2001
+From: Rosen Penev <rosenp@gmail.com>
+Date: Thu, 20 Jun 2019 15:18:19 -0700
+Subject: [PATCH] configure: Fix iconv check for cross compilation
+
+AC_CHECK_LIB is more friendly towards cross-compilation.
+
+Added check for libiconv_open as that can be used when the libc lacks iconv.
+---
+ configure.ac | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/configure.ac
++++ b/configure.ac
+@@ -59,7 +59,8 @@ if test "x$with_udev" != "xno"; then
+ [true])
+ fi
+
+-AC_SEARCH_LIBS(iconv_open, iconv)
++AC_CHECK_LIB(iconv, iconv_open)
++AC_CHECK_LIB(iconv, libiconv_open)
+
+ # xxd (distributed with vim) is used in the testsuite
+ AC_CHECK_PROG([XXD_FOUND], [xxd], [yes])
diff --git a/external/subpack/utils/dumb-init/Makefile b/external/subpack/utils/dumb-init/Makefile
new file mode 100644
index 0000000..33a41c5
--- /dev/null
+++ b/external/subpack/utils/dumb-init/Makefile
@@ -0,0 +1,37 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dumb-init
+PKG_VERSION:=1.2.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/Yelp/dumb-init/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=d4e2e10e39ad49c225e1579a4d770b83637399a0be48e29986f720fae44dafdf
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+PKG_MAINTAINER:=Toni Uhlig <matzeton@googlemail.com>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+include $(INCLUDE_DIR)/package.mk
+
+MAKE_FLAGS+=CFLAGS='$(TARGET_CFLAGS) $(TARGET_LDFLAGS)'
+
+define Package/dumb-init
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=dumb-init
+ URL:=https://github.com/Yelp/dumb-init.git
+endef
+
+define Package/dumb-init/description
+ dumb-init is a simple process supervisor and init system designed to run as
+ PID 1 inside minimal container environments.
+endef
+
+define Package/dumb-init/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/dumb-init $(1)/usr/sbin/dumb-init
+endef
+
+$(eval $(call BuildPackage,dumb-init))
diff --git a/external/subpack/utils/dump1090/Makefile b/external/subpack/utils/dump1090/Makefile
new file mode 100644
index 0000000..26ec46b
--- /dev/null
+++ b/external/subpack/utils/dump1090/Makefile
@@ -0,0 +1,86 @@
+#
+# Copyright (C) 2013-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dump1090
+PKG_VERSION:=4.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/flightaware/dump1090/tar.gz/v${PKG_VERSION}?
+PKG_HASH:=49ace5a06da3d51384de83a4199d043c6093ad475909c58317cedece0e9590d1
+
+PKG_MAINTAINER:=Álvaro Fernández Rojas <noltari@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING LICENSE
+
+PKG_BUILD_DEPENDS:=libusb
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/dump1090/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Mode S decoder for the Realtek RTL2832U
+ URL:=https://github.com/flightaware/dump1090
+endef
+
+define Package/dump1090
+ $(call Package/dump1090/Default)
+ TITLE+= (dump1090)
+ DEPENDS+=+librtlsdr +uhttpd +libncurses
+endef
+
+define Package/view1090
+ $(call Package/dump1090/Default)
+ TITLE+= (view1090)
+ DEPENDS+=+libncurses
+endef
+
+define Package/dump1090/description
+ Dump1090 is a Mode S decoder specifically designed for RTLSDR devices.
+endef
+
+define Package/view1090/description
+ View1090 is a Mode S messages viewer for dump1090 devices.
+endef
+
+MAKE_FLAGS += \
+ BLADERF=no \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ UNAME="Linux"
+
+TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto
+TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed
+
+define Package/dump1090/conffiles
+/etc/config/dump1090
+endef
+
+define Package/dump1090/install
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) files/dump1090.init $(1)/etc/init.d/dump1090
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) files/dump1090.config $(1)/etc/config/dump1090
+ $(INSTALL_DIR) $(1)/etc/uci-defaults
+ $(INSTALL_DATA) files/dump1090.default $(1)/etc/uci-defaults/00_uhttpd_dump1090
+ $(INSTALL_DIR) $(1)/usr/share/dump1090
+ $(CP) $(PKG_BUILD_DIR)/public_html/* $(1)/usr/share/dump1090
+ $(LN) /var/run/dump1090 $(1)/usr/share/dump1090/data
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/dump1090 $(1)/usr/bin
+endef
+
+define Package/view1090/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/view1090 $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,dump1090))
+$(eval $(call BuildPackage,view1090))
diff --git a/external/subpack/utils/dump1090/files/dump1090.config b/external/subpack/utils/dump1090/files/dump1090.config
new file mode 100644
index 0000000..2b9e96a
--- /dev/null
+++ b/external/subpack/utils/dump1090/files/dump1090.config
@@ -0,0 +1,50 @@
+config dump1090 main
+ option disabled '1'
+ option respawn '1'
+ option device_index ''
+ option gain ''
+ option enable_agc '0'
+ option freq ''
+ option ifile ''
+ option iformat ''
+ option throttle '0'
+ option raw '0'
+ option net '1'
+ option modeac '0'
+ option net_only '0'
+ option net_bind_address ''
+ option net_ri_port ''
+ option net_ro_port ''
+ option net_sbs_port ''
+ option net_bi_port ''
+ option net_bo_port ''
+ option net_ro_size ''
+ option net_ro_interval ''
+ option net_heartbeat ''
+ option net_buffer ''
+ option net_verbatim '0'
+ option forward_mlat '0'
+ option lat ''
+ option lon ''
+ option max_range ''
+ option fix '0'
+ option no_fix '0'
+ option no_crc_check '0'
+ option phase_enhance '0'
+ option mlat '0'
+ option stats '0'
+ option stats_range '0'
+ option stats_every ''
+ option onlyaddr '0'
+ option metric '0'
+ option gnss '0'
+ option snip ''
+ option debug ''
+ option ppm ''
+ option html_dir '/usr/share/dump1090'
+ option write_json '/var/run/dump1090'
+ option write_json_every '1'
+ option json_location_accuracy ''
+ option oversample '0'
+ option dcfilter '0'
+ option measure_noise '0'
diff --git a/external/subpack/utils/dump1090/files/dump1090.default b/external/subpack/utils/dump1090/files/dump1090.default
new file mode 100644
index 0000000..51106fa
--- /dev/null
+++ b/external/subpack/utils/dump1090/files/dump1090.default
@@ -0,0 +1,16 @@
+#!/bin/sh
+uci batch <<-EOF
+ set uhttpd.dump1090=uhttpd
+ set uhttpd.dump1090.listen_http='0.0.0.0:8080 [::]:8080'
+ set uhttpd.dump1090.home=/usr/share/dump1090
+ set uhttpd.dump1090.rfc1918_filter=1
+ set uhttpd.dump1090.max_requests=3
+ set uhttpd.dump1090.max_connections=100
+ set uhttpd.dump1090.script_timeout=60
+ set uhttpd.dump1090.network_timeout=30
+ set uhttpd.dump1090.http_keepalive=20
+ set uhttpd.dump1090.tcp_keepalive=1
+ set uhttpd.dump1090.index_page='index.html index.htm gmap.html'
+ commit uhttpd
+EOF
+exit 0
diff --git a/external/subpack/utils/dump1090/files/dump1090.init b/external/subpack/utils/dump1090/files/dump1090.init
new file mode 100644
index 0000000..89c3333
--- /dev/null
+++ b/external/subpack/utils/dump1090/files/dump1090.init
@@ -0,0 +1,107 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2014-2016 OpenWrt.org
+
+START=90
+STOP=10
+USE_PROCD=1
+
+append_arg() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get val "$cfg" "$var"
+ if [ -n "$val" ] || [ -n "$def" ]; then
+ procd_append_param command "$opt" "${val:-$def}"
+ fi
+}
+
+append_bool() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get_bool val "$cfg" "$var" "$def"
+ [ "$val" = 1 ] && procd_append_param command "$opt"
+}
+
+start_instance() {
+ local cfg="$1"
+ local aux
+
+ config_get_bool aux "$cfg" 'disabled' '0'
+ [ "$aux" = 1 ] && return 1
+
+ procd_open_instance
+
+ procd_set_param command /usr/bin/dump1090
+ procd_append_param command "--quiet"
+
+ append_arg "$cfg" device_index "--device-index"
+ append_arg "$cfg" gain "--gain"
+ append_bool "$cfg" enable_agc "--enable-agc"
+ append_arg "$cfg" freq "--freq"
+ append_arg "$cfg" ifile "--ifile"
+ append_arg "$cfg" iformat "--iformat"
+ append_bool "$cfg" throttle "--throttle"
+ append_bool "$cfg" raw "--raw"
+ append_bool "$cfg" net "--net"
+ append_bool "$cfg" modeac "--modeac"
+ append_bool "$cfg" net_only "--net-only"
+ append_arg "$cfg" net_bind_address "--net-bind-address"
+ append_arg "$cfg" net_ri_port "--net-ri-port"
+ append_arg "$cfg" net_ro_port "--net-ro-port"
+ append_arg "$cfg" net_sbs_port "--net-sbs-port"
+ append_arg "$cfg" net_bi_port "--net-bi-port"
+ append_arg "$cfg" net_bo_port "--net-bo-port"
+ append_arg "$cfg" net_ro_size "--net-ro-size"
+ append_arg "$cfg" net_ro_interval "--net-ro-interval"
+ append_arg "$cfg" net_heartbeat "--net-heartbeat"
+ append_arg "$cfg" net_buffer "--net-buffer"
+ append_bool "$cfg" net_verbatim "--net-verbatim"
+ append_bool "$cfg" forward_mlat "--forward-mlat"
+ append_arg "$cfg" lat "--lat"
+ append_arg "$cfg" lon "--lon"
+ append_arg "$cfg" max_range "--max-range"
+ append_bool "$cfg" fix "--fix"
+ append_bool "$cfg" no_fix "--no-fix"
+ append_bool "$cfg" no_crc_check "--no-crc-check"
+ append_bool "$cfg" phase_enhance "--phase-enhance"
+ append_bool "$cfg" mlat "--mlat"
+ append_bool "$cfg" stats "--stats"
+ append_bool "$cfg" stats_range "--stats-range"
+ append_arg "$cfg" stats_every "--stats-every"
+ append_bool "$cfg" onlyaddr "--onlyaddr"
+ append_bool "$cfg" metric "--metric"
+ append_bool "$cfg" gnss "--gnss"
+ append_arg "$cfg" snip "--snip"
+ append_arg "$cfg" debug "--debug"
+ append_arg "$cfg" ppm "--ppm"
+ append_arg "$cfg" html_dir "--html-dir"
+ append_arg "$cfg" write_json "--write-json"
+ config_get aux "$cfg" "write_json"
+ [ -n "$aux" ] && mkdir -p "$aux"
+ append_arg "$cfg" write_json_every "--write-json-every"
+ append_arg "$cfg" json_location_accuracy "--json-location-accuracy"
+ append_bool "$cfg" oversample "--oversample"
+ append_bool "$cfg" dcfilter "--dcfilter"
+ append_bool "$cfg" measure_noise "--measure-noise"
+
+ config_get_bool aux "$cfg" 'respawn' '0'
+ [ "$aux" = 1 ] && procd_set_param respawn
+
+ procd_close_instance
+}
+
+service_triggers() {
+ procd_add_reload_trigger "dump1090"
+}
+
+start_service() {
+ config_load dump1090
+ config_foreach start_instance dump1090
+}
diff --git a/external/subpack/utils/dvtm/Makefile b/external/subpack/utils/dvtm/Makefile
new file mode 100644
index 0000000..ef35abd
--- /dev/null
+++ b/external/subpack/utils/dvtm/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dvtm
+PKG_VERSION:=0.15
+PKG_RELEASE:=1
+
+PKG_SOURCE:=dvtm-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.brain-dump.org/projects/dvtm/
+PKG_HASH:=8f2015c05e2ad82f12ae4cf12b363d34f527a4bbc8c369667f239e4542e1e510
+PKG_MAINTAINER:=Yunfan Jiang <jyf1987@gmail.com>
+
+PKG_LICENSE:=MIT/X
+PKG_LICENSE_FILES:=LICENSE
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/dvtm
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Terminal
+ DEPENDS:=+libncursesw
+ TITLE:=dynamic virtual terminal manager
+ URL:=http://www.brain-dump.org/projects/dvtm/
+endef
+
+define Package/dvtm/description
+ dvtm brings the concept of tiling window management, popularized by X11-window managers like dwm to the console. As a console window manager it tries to make it easy to work with multiple console based programs.
+endef
+
+define Package/dvtm/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/dvtm $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,dvtm))
diff --git a/external/subpack/utils/ecdsautils/Makefile b/external/subpack/utils/ecdsautils/Makefile
new file mode 100644
index 0000000..988e010
--- /dev/null
+++ b/external/subpack/utils/ecdsautils/Makefile
@@ -0,0 +1,71 @@
+#
+# Copyright (C) 2012-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ecdsautils
+PKG_VERSION:=0.4.1
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/freifunk-gluon/ecdsautils
+PKG_SOURCE_VERSION:=39b6d0a77414fd41614953a0e185c4eefa2f88ad
+PKG_MIRROR_HASH:=b6022455af1e126c3893b19b65d5efbda6c1e5105745891481e0b9bf8e1aeb53
+
+PKG_MAINTAINER:=Matthias Schiffer <mschiffer@universe-factory.net>
+PKG_LICENSE_FILES:=COPYRIGHT
+
+PKG_BUILD_PARALLEL:=1
+CMAKE_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/libecdsautil
+ SECTION:=libs
+ CATEGORY:=Libraries
+ DEPENDS:=+libuecc
+ TITLE:=ECDSA library
+ URL:=https://github.com/freifunk-gluon/ecdsautils
+ LICENSE:=MIT
+endef
+
+define Package/ecdsautils
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libecdsautil +libuecc
+ TITLE:=ECDSA Utilities
+ URL:=https://github.com/freifunk-gluon/ecdsautils
+ LICENSE:=BSD-2-Clause
+endef
+
+define Package/libecdsautil/description
+ Library to sign and verify checksums using ECDSA.
+endef
+
+define Package/ecdsautils/description
+ Utilities to sign and verify checksums using ECDSA.
+endef
+
+CMAKE_OPTIONS += \
+ -DCMAKE_BUILD_TYPE:String="MINSIZEREL"
+
+define Package/libecdsautil/install
+ $(INSTALL_DIR) $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libecdsautil.so* $(1)/usr/lib/
+endef
+
+define Package/ecdsautils/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ecdsautil $(1)/usr/bin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/ecdsakeygen $(1)/usr/bin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/ecdsasign $(1)/usr/bin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/ecdsaverify $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,libecdsautil))
+$(eval $(call BuildPackage,ecdsautils))
diff --git a/external/subpack/utils/evtest/Makefile b/external/subpack/utils/evtest/Makefile
new file mode 100644
index 0000000..8f0c51b
--- /dev/null
+++ b/external/subpack/utils/evtest/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=evtest
+PKG_VERSION:=1.34
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://cgit.freedesktop.org/evtest/snapshot
+PKG_HASH:=e49f1f160b30c8f7c2a4caef5ab655f1caf816483d19fdedd6db2d251d7ab80e
+
+PKG_MAINTAINER:=Pushpal Sidhu <psidhu.devel@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_FIXUP:=autoreconf
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/evtest
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Event Test Program
+ URL:=https://gitlab.freedesktop.org/libevdev/evtest
+endef
+
+define Package/evtest/description
+ Utility to test event driven devices such as keyboards and mice
+endef
+
+define Package/evtest/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/evtest $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,evtest))
diff --git a/external/subpack/utils/evtest/patches/010-musl.patch b/external/subpack/utils/evtest/patches/010-musl.patch
new file mode 100644
index 0000000..647c9dc
--- /dev/null
+++ b/external/subpack/utils/evtest/patches/010-musl.patch
@@ -0,0 +1,19 @@
+From 12d5ea5ca2d9a47a1cab06caf2b36967667a3daf Mon Sep 17 00:00:00 2001
+From: Leo <thinkabit.ukim@gmail.com>
+Date: Sun, 24 Nov 2019 20:58:20 +0100
+Subject: [PATCH] Add missing include of limits.h for PATH_MAX
+
+---
+ evtest.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/evtest.c
++++ b/evtest.c
+@@ -59,6 +59,7 @@
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <unistd.h>
++#include <limits.h> /* PATH_MAX */
+
+ #define BITS_PER_LONG (sizeof(long) * 8)
+ #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
diff --git a/external/subpack/utils/evtest/patches/020-Fix-build-on-32bit-arches-with-64bit-time_t.patch b/external/subpack/utils/evtest/patches/020-Fix-build-on-32bit-arches-with-64bit-time_t.patch
new file mode 100644
index 0000000..3fcb252
--- /dev/null
+++ b/external/subpack/utils/evtest/patches/020-Fix-build-on-32bit-arches-with-64bit-time_t.patch
@@ -0,0 +1,38 @@
+From 648f5c1a9e07843e185782d207bc1bcbe6586f6e Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 30 Nov 2019 11:58:58 -0800
+Subject: [PATCH] Fix build on 32bit arches with 64bit time_t
+
+time element is deprecated on new input_event structure in kernel's
+input.h [1]
+
+[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit?id=152194fe9c3f
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ evtest.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/evtest.c
++++ b/evtest.c
+@@ -61,6 +61,11 @@
+ #include <unistd.h>
+ #include <limits.h> /* PATH_MAX */
+
++#ifndef input_event_sec
++#define input_event_sec time.tv_sec
++#define input_event_usec time.tv_usec
++#endif
++
+ #define BITS_PER_LONG (sizeof(long) * 8)
+ #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+ #define OFF(x) ((x)%BITS_PER_LONG)
+@@ -1140,7 +1145,7 @@ static int print_events(int fd)
+ type = ev[i].type;
+ code = ev[i].code;
+
+- printf("Event: time %ld.%06ld, ", ev[i].time.tv_sec, ev[i].time.tv_usec);
++ printf("Event: time %ld.%06ld, ", ev[i].input_event_sec, ev[i].input_event_usec);
+
+ if (type == EV_SYN) {
+ if (code == SYN_MT_REPORT)
diff --git a/external/subpack/utils/exfatprogs/Makefile b/external/subpack/utils/exfatprogs/Makefile
new file mode 100644
index 0000000..37719fd
--- /dev/null
+++ b/external/subpack/utils/exfatprogs/Makefile
@@ -0,0 +1,53 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=exfatprogs
+PKG_VERSION:=1.2.4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://github.com/exfatprogs/exfatprogs/releases/download/$(PKG_VERSION)
+PKG_HASH:=ad38126dfd9f74f8c6ecb35ddfd34d2582601d6c3ff26756610b8418360c8ee2
+
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:namjaejeon:exfatprogs
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/exfatprogs/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Filesystem
+ URL:=https://github.com/exfatprogs/exfatprogs
+endef
+
+define Package/exfat-mkfs
+ $(Package/exfatprogs/Default)
+ TITLE:=Utility for creating an exFAT File System
+endef
+
+define Package/exfat-fsck
+ $(Package/exfatprogs/Default)
+ TITLE:=Utility for checking/repairing an exFAT File System
+endef
+
+CONFIGURE_ARGS += \
+ --enable-shared \
+ --disable-static
+
+define Package/exfat-mkfs/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/mkfs.exfat $(1)/usr/sbin
+endef
+
+define Package/exfat-fsck/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/fsck.exfat $(1)/usr/sbin
+endef
+
+$(eval $(call BuildPackage,exfat-mkfs))
+$(eval $(call BuildPackage,exfat-fsck))
diff --git a/external/subpack/utils/fft-eval/Makefile b/external/subpack/utils/fft-eval/Makefile
new file mode 100644
index 0000000..8e851d7
--- /dev/null
+++ b/external/subpack/utils/fft-eval/Makefile
@@ -0,0 +1,41 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fft-eval
+PKG_VERSION:=2019-11-27
+PKG_RELEASE=$(PKG_SOURCE_VERSION)
+
+PKG_SOURCE_VERSION:=4d3b6faee428e3bd9f44ab6a3d70585ec50484a1
+PKG_SOURCE:=FFT_eval-$(PKG_SOURCE_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/simonwunderlich/FFT_eval/tar.gz/$(PKG_SOURCE_VERSION)?
+PKG_HASH:=fb34ed5691af6c3ec09c41a6689ae64a1a12d770347a4effd48e4b30aef1eb22
+PKG_BUILD_DIR:=$(BUILD_DIR)/FFT_eval-$(PKG_SOURCE_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/$(PKG_NAME)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ MAINTAINER:=Kirill Lukonin <klukonin@gmail.com>
+ URL:=https://github.com/simonwunderlich/FFT_eval
+ TITLE:=Evaluates FFT samples from ath9k, ath10k or ath11k driver
+ DEPENDS:=@PACKAGE_ATH_DEBUG @PACKAGE_ATH_SPECTRAL
+endef
+
+define Package/$(PKG_NAME)/description
+ Evaluates FFT samples from diferent wifi boards drivers
+endef
+
+TARGET_CFLAGS += -Wall -W -std=gnu99 -fno-strict-aliasing -MD -MP
+TARGET_CPPFLAGS += -D_DEFAULT_SOURCE
+
+
+define Build/Compile
+ $(call Build/Compile/Default,CONFIG_fft_eval_sdl=n)
+endef
+
+define Package/$(PKG_NAME)/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/fft_eval_json $(1)/usr/bin/fft_eval
+endef
+
+$(eval $(call BuildPackage,$(PKG_NAME)))
diff --git a/external/subpack/utils/findutils/Makefile b/external/subpack/utils/findutils/Makefile
new file mode 100644
index 0000000..121b0f9
--- /dev/null
+++ b/external/subpack/utils/findutils/Makefile
@@ -0,0 +1,95 @@
+#
+# Copyright (C) 2006-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=findutils
+PKG_VERSION:=4.10.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/$(PKG_NAME)
+PKG_HASH:=1387e0b67ff247d2abde998f90dfbf70c1491391a59ddfecb8ae698789f0a4f5
+
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:gnu:findutils
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/findutils/Default
+ TITLE:=GNU Find Utilities
+ SECTION:=utils
+ CATEGORY:=Utilities
+ URL:=https://www.gnu.org/software/findutils/
+endef
+
+define Package/findutils/description/Default
+Replace busybox versions of findutils with full GNU versions.
+This is normally not needed as busybox is smaller and provides
+sufficient functionality, but some users may want or need
+the full functionality of the GNU tools.
+endef
+
+define Package/findutils
+ $(call Package/findutils/Default)
+ TITLE+= (all)
+ DEPENDS:= \
+ +findutils-find \
+ +findutils-xargs \
+ +findutils-locate
+endef
+
+define Package/findutils-find
+ $(call Package/findutils/Default)
+ TITLE+= - find utility
+ ALTERNATIVES:=300:/usr/bin/find:/usr/libexec/find-findutils
+endef
+
+define Package/findutils-xargs
+ $(call Package/findutils/Default)
+ TITLE+= - xargs utility
+ ALTERNATIVES:=300:/usr/bin/xargs:/usr/libexec/xargs-findutils
+endef
+
+define Package/findutils-locate
+ $(call Package/findutils/Default)
+ TITLE+= - locate and updatedb utility
+endef
+
+CONFIGURE_ARGS += \
+ --localstatedir=/srv/var \
+ --without-selinux
+CONFIGURE_VARS += ac_cv_path_SORT=sort
+
+define Package/findutils/install
+ true
+endef
+
+define Package/findutils-find/install
+ $(INSTALL_DIR) $(1)/usr/libexec
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/find $(1)/usr/libexec/find-findutils
+endef
+
+define Package/findutils-xargs/install
+ $(INSTALL_DIR) $(1)/usr/libexec
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/xargs $(1)/usr/libexec/xargs-findutils
+endef
+
+define Package/findutils-locate/install
+ $(INSTALL_DIR) $(1)/usr/bin $(1)/srv/var
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/locate $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/updatedb $(1)/usr/bin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib $(1)/usr/
+endef
+
+$(eval $(call BuildPackage,findutils))
+$(eval $(call BuildPackage,findutils-find))
+$(eval $(call BuildPackage,findutils-locate))
+$(eval $(call BuildPackage,findutils-xargs))
diff --git a/external/subpack/utils/fio/Makefile b/external/subpack/utils/fio/Makefile
new file mode 100644
index 0000000..f6c2413
--- /dev/null
+++ b/external/subpack/utils/fio/Makefile
@@ -0,0 +1,68 @@
+#
+# Copyright (C) 2018 Daniel Engberg <daniel.engberg.lists@pyret.net>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fio
+PKG_VERSION:=3.37
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://brick.kernel.dk/snaps
+PKG_HASH:=88f0fd6549ca07f7387e784a91706ab11e36d5c12ec26540f1b2d33c6f2d8327
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/fio
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Disc
+ DEPENDS:=+libaio +zlib
+ TITLE:=I/O testing and benchmarking tool
+ URL:=https://github.com/axboe/fio
+endef
+
+define Package/fio/description
+ Fio is an I/O testing tool that will spawn a number of threads or
+ processes doing a particular type of I/O action as specified by
+ the user. Fio can be driven by a 'job file' describing the I/O
+ load one wants to simulate.
+endef
+
+TARGET_CFLAGS := $(filter-out -O%,$(TARGET_CFLAGS))
+TARGET_LDFLAGS += -Wl,--gc-sections
+
+CONFIGURE_ARGS = \
+ --disable-numa \
+ --disable-rdma \
+ --disable-rados \
+ --disable-http \
+ --disable-rbd \
+ --disable-gfapi \
+ --disable-lex \
+ --disable-pmem \
+ --disable-native \
+ --disable-shm \
+ --disable-optimizations \
+ --disable-tcmalloc \
+ --cc="$(TARGET_CC)" \
+ --extra-cflags="$(TARGET_CFLAGS)" \
+ --prefix="$(CONFIGURE_PREFIX)"
+
+define Package/fio/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fio $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,fio))
diff --git a/external/subpack/utils/fish/Makefile b/external/subpack/utils/fish/Makefile
new file mode 100644
index 0000000..e4f2de0
--- /dev/null
+++ b/external/subpack/utils/fish/Makefile
@@ -0,0 +1,70 @@
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fish
+PKG_VERSION:=3.5.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://github.com/fish-shell/fish-shell/releases/download/$(PKG_VERSION)
+PKG_HASH:=291e4ec7c6c3fea54dc1aed057ce3d42b356fa6f70865627b2c7dfcecaefd210
+
+PKG_MAINTAINER:=Curtis Jiang <jqqqqqqqqqq@gmail.com>, Hao Dong <halbertdong@gmail.com>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:fishshell:fish
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/fish
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Shells
+ TITLE:=A smart and user-friendly command line shell
+ DEPENDS:=+libncurses +libstdcpp +libatomic +libpcre2-32
+ URL:=https://fishshell.com
+endef
+
+define Package/fish/description
+ Fish is a smart and user-friendly command line shell for OS X, Linux, and the
+ rest of the family. Fish includes features like syntax highlighting,
+ autosuggest-as-you-type, and fancy tab completions that just work, with no
+ configuration required.
+endef
+
+CMAKE_OPTIONS += \
+ -DBUILD_DOCS=FALSE \
+ -DWITH_GETTEXT=FALSE
+
+define Package/fish/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fish $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fish_indent $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fish_key_reader $(1)/usr/bin
+ $(INSTALL_DIR) $(1)/usr/share/fish
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/fish/* $(1)/usr/share/fish/
+ rm -rf $(1)/usr/share/fish/groff
+ rm -rf $(1)/usr/share/fish/man
+ rm -rf $(1)/usr/share/fish/tools
+endef
+
+define Package/fish/postinst
+#!/bin/sh
+grep fish $${IPKG_INSTROOT}/etc/shells || \
+ echo "/usr/bin/fish" >> $${IPKG_INSTROOT}/etc/shells
+
+# Backwards compatibility
+if [ -e /bin/fish ] && { [ ! -L /bin/fish ] || [ "$(readlink -fn $${IPKG_INSTROOT}/bin/fish)" != "../$(CONFIGURE_PREFIX)/bin/fish" ]; }; then
+ ln -fs "../$(CONFIGURE_PREFIX)/bin/fish" "$${IPKG_INSTROOT}/bin/fish"
+fi
+endef
+
+define Package/fish/postrm
+ rm -rf "$${IPKG_INSTROOT}/$(CONFIGURE_PREFIX)/share/fish/$(PKG_VERSION)"
+endef
+
+$(eval $(call BuildPackage,fish))
diff --git a/external/subpack/utils/flashrom/Makefile b/external/subpack/utils/flashrom/Makefile
new file mode 100644
index 0000000..cced9a8
--- /dev/null
+++ b/external/subpack/utils/flashrom/Makefile
@@ -0,0 +1,126 @@
+#
+# Copyright (C) 2010-2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=flashrom
+PKG_VERSION:=1.3.0
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://download.flashrom.org/releases
+PKG_HASH:=a053234453ccd012e79f3443bdcc61625cf97b7fd7cb4cdd8bfbffbe8b149623
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-v$(PKG_VERSION)
+
+PKG_MAINTAINER:=Álvaro Fernández Rojas <noltari@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/meson.mk
+include flashrom.mk
+
+define Package/flashrom/default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=FlashROM Utility
+ URL:=https://www.flashrom.org/
+endef
+
+define Package/flashrom
+ $(Package/flashrom/default)
+ TITLE+= (full)
+ DEPENDS+= \
+ +(TARGET_x86||TARGET_x86_64):dmidecode \
+ +libftdi1 \
+ +libusb-1.0 \
+ +pciutils
+ VARIANT:=full
+ DEFAULT_VARIANT:=1
+endef
+
+define Package/flashrom-pci
+ $(Package/flashrom/default)
+ TITLE+= (pci)
+ DEPENDS+= \
+ +(TARGET_x86||TARGET_x86_64):dmidecode \
+ +pciutils
+ VARIANT:=pci
+endef
+
+define Package/flashrom-spi
+ $(Package/flashrom/default)
+ TITLE+= (spi)
+ VARIANT:=spi
+endef
+
+define Package/flashrom-usb
+ $(Package/flashrom/default)
+ TITLE+= (usb)
+ DEPENDS+= \
+ +libftdi1 \
+ +libusb-1.0
+ VARIANT:=usb
+endef
+
+define Package/libflashrom
+ $(Package/flashrom/default)
+ TITLE+= (library)
+ DEPENDS+= \
+ +(TARGET_x86||TARGET_x86_64):dmidecode \
+ +libftdi1 \
+ +libusb-1.0 \
+ +pciutils
+ VARIANT:=full
+endef
+
+define Package/flashrom/default/description
+ flashrom is an utility for identifying, reading, writing, verifying
+ and erasing flash chips. It's often used to flash BIOS/EFI/coreboot
+ /firmware images.
+endef
+Package/flashrom/description = $(Package/flashrom/default/description)
+Package/flashrom-pci/description = $(Package/flashrom/default/description)
+Package/flashrom-spi/description = $(Package/flashrom/default/description)
+Package/flashrom-usb/description = $(Package/flashrom/default/description)
+Package/libflashrom/description = $(Package/flashrom/default/description)
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/*.h $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libflashrom.so* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/flashrom.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/flashrom/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/flashrom $(1)/usr/sbin/flashrom
+endef
+define Package/flashrom-pci/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/flashrom $(1)/usr/sbin/flashrom-pci
+endef
+define Package/flashrom-spi/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/flashrom $(1)/usr/sbin/flashrom-spi
+endef
+define Package/flashrom-usb/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/flashrom $(1)/usr/sbin/flashrom-usb
+endef
+define Package/libflashrom/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libflashrom.so* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,flashrom))
+$(eval $(call BuildPackage,flashrom-pci))
+$(eval $(call BuildPackage,flashrom-spi))
+$(eval $(call BuildPackage,flashrom-usb))
+$(eval $(call BuildPackage,libflashrom))
diff --git a/external/subpack/utils/flashrom/flashrom.mk b/external/subpack/utils/flashrom/flashrom.mk
new file mode 100644
index 0000000..454e954
--- /dev/null
+++ b/external/subpack/utils/flashrom/flashrom.mk
@@ -0,0 +1,103 @@
+# Flashrom variants
+
+ifeq ($(BUILD_VARIANT),full)
+ DEFAULT_PROGRAMMER_NAME := linux_spi
+ FLASHROM_BASIC := true
+ FLASHROM_FTDI := true
+ FLASHROM_PCI := true
+ FLASHROM_RAW := $(if $(findstring x86,$(CONFIG_ARCH)),true,false)
+ FLASHROM_SERIAL := true
+ FLASHROM_USB := true
+endif
+ifeq ($(BUILD_VARIANT),pci)
+ DEFAULT_PROGRAMMER_NAME := internal
+ FLASHROM_BASIC := true
+ FLASHROM_FTDI := false
+ FLASHROM_PCI := true
+ FLASHROM_RAW := $(if $(findstring x86,$(CONFIG_ARCH)),true,false)
+ FLASHROM_SERIAL := false
+ FLASHROM_USB := false
+endif
+ifeq ($(BUILD_VARIANT),spi)
+ DEFAULT_PROGRAMMER_NAME := linux_spi
+ FLASHROM_BASIC := true
+ FLASHROM_FTDI := false
+ FLASHROM_PCI := false
+ FLASHROM_RAW := false
+ FLASHROM_SERIAL := false
+ FLASHROM_USB := false
+endif
+ifeq ($(BUILD_VARIANT),usb)
+ DEFAULT_PROGRAMMER_NAME := serprog
+ FLASHROM_BASIC := true
+ FLASHROM_FTDI := true
+ FLASHROM_PCI := false
+ FLASHROM_RAW := false
+ FLASHROM_SERIAL := true
+ FLASHROM_USB := true
+endif
+
+PROGRAMMER_ARGS :=
+
+define Programmer
+ ifeq ($(2),true)
+ PROGRAMMER_ARGS += $(1)
+ endif
+endef
+
+$(eval $(call Programmer,dummy,$(FLASHROM_BASIC)))
+$(eval $(call Programmer,linux_mtd,$(FLASHROM_BASIC)))
+$(eval $(call Programmer,linux_spi,$(FLASHROM_BASIC)))
+$(eval $(call Programmer,mstarddc_spi,$(FLASHROM_BASIC)))
+
+$(eval $(call Programmer,ft2232_spi,$(FLASHROM_FTDI)))
+$(eval $(call Programmer,usbblaster_spi,$(FLASHROM_FTDI)))
+
+$(eval $(call Programmer,atavia,$(FLASHROM_PCI)))
+$(eval $(call Programmer,drkaiser,$(FLASHROM_PCI)))
+$(eval $(call Programmer,gfxnvidia,$(FLASHROM_PCI)))
+$(eval $(call Programmer,internal,$(FLASHROM_PCI)))
+$(eval $(call Programmer,it8212,$(FLASHROM_PCI)))
+$(eval $(call Programmer,nicintel,$(FLASHROM_PCI)))
+$(eval $(call Programmer,nicintel_spi,$(FLASHROM_PCI)))
+$(eval $(call Programmer,nicintel_eeprom,$(FLASHROM_PCI)))
+$(eval $(call Programmer,ogp_spi,$(FLASHROM_PCI)))
+$(eval $(call Programmer,satasii,$(FLASHROM_PCI)))
+
+$(eval $(call Programmer,rayer_spi,$(FLASHROM_RAW)))
+
+$(eval $(call Programmer,buspirate_spi,$(FLASHROM_SERIAL)))
+$(eval $(call Programmer,pony_spi,$(FLASHROM_SERIAL)))
+$(eval $(call Programmer,serprog,$(FLASHROM_SERIAL)))
+
+$(eval $(call Programmer,ch341a_spi,$(FLASHROM_USB)))
+$(eval $(call Programmer,dediprog,$(FLASHROM_USB)))
+$(eval $(call Programmer,developerbox_spi,$(FLASHROM_USB)))
+$(eval $(call Programmer,digilent_spi,$(FLASHROM_USB)))
+$(eval $(call Programmer,pickit2_spi,$(FLASHROM_USB)))
+$(eval $(call Programmer,stlinkv3_spi,$(FLASHROM_USB)))
+
+# PCI
+ifeq ($(findstring i386,$(CONFIG_ARCH))$(findstring x86,$(CONFIG_ARCH)),)
+ MESON_ARGS += -Duse_internal_dmi=true
+ $(eval $(call Programmer,atahpt,false))
+ $(eval $(call Programmer,atapromise,false))
+ $(eval $(call Programmer,nic3com,false))
+ $(eval $(call Programmer,nicnatsemi,false))
+ $(eval $(call Programmer,nicrealtek,false))
+ $(eval $(call Programmer,satamv,false))
+else
+ MESON_ARGS += -Duse_internal_dmi=$(if $(FLASHROM_PCI),false,true)
+ $(eval $(call Programmer,atahpt,$(FLASHROM_PCI)))
+ $(eval $(call Programmer,atapromise,$(FLASHROM_PCI)))
+ $(eval $(call Programmer,nic3com,$(FLASHROM_PCI)))
+ $(eval $(call Programmer,nicnatsemi,$(FLASHROM_PCI)))
+ $(eval $(call Programmer,nicrealtek,$(FLASHROM_PCI)))
+ $(eval $(call Programmer,satamv,$(FLASHROM_PCI)))
+endif
+
+MESON_ARGS += \
+ -Ddefault_programmer_name=$(DEFAULT_PROGRAMMER_NAME) \
+ -Dprogrammer=$(subst $(space),$(comma),$(strip $(PROGRAMMER_ARGS))) \
+ -Dwerror=false \
+ -Dtests=disabled
diff --git a/external/subpack/utils/flent-tools/Makefile b/external/subpack/utils/flent-tools/Makefile
new file mode 100644
index 0000000..f2f5514
--- /dev/null
+++ b/external/subpack/utils/flent-tools/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2007-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=flent-tools
+PKG_VERSION:=1.3.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/tohojo/flent/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=f71793bb924b36d0e4c230182755c3f5dd26cd7f239b1fa6b717d942258cbf9a
+PKG_BUILD_DIR:=$(BUILD_DIR)/flent-$(PKG_VERSION)
+
+PKG_LICENSE:=GPL-3.0-only
+PKG_LICENSE_FILES:=LICENSE
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/flent-tools
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Helper programs for the Flent test tool
+ URL:=https://flent.org
+ MAINTAINER:=Toke Høiland-Jørgensen <toke@toke.dk>
+ DEPENDS+=+librt +coreutils-sleep +coreutils-date
+endef
+
+define Package/flent-tc_iterate/description
+ This builds the C helper programs for gathering data for
+ the Flent network testing tool. These tools are needed for
+ gathering data when a Bash shell is not available (and also
+ perform better than the shell equivalents).
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR)/misc \
+ CC="$(TARGET_CC)" \
+ CFLAGS="$(TARGET_CFLAGS) -std=gnu99"
+endef
+
+define Package/flent-tools/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc/tc_iterate $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc/wifistats_iterate $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,flent-tools))
diff --git a/external/subpack/utils/fontconfig/Makefile b/external/subpack/utils/fontconfig/Makefile
new file mode 100644
index 0000000..ca21c41
--- /dev/null
+++ b/external/subpack/utils/fontconfig/Makefile
@@ -0,0 +1,65 @@
+#
+# Copyright (C) 2008-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fontconfig
+PKG_VERSION:=2.15.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://www.freedesktop.org/software/fontconfig/release/
+PKG_HASH:=63a0658d0e06e0fa886106452b58ef04f21f58202ea02a94c39de0d3335d7c0e
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=
+PKG_LICENSE_FILES:=
+PKG_CPE_ID:=cpe:/a:fontconfig_project:fontconfig
+
+PKG_BUILD_DEPENDS:=gperf/host
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/meson.mk
+
+define Package/fontconfig
+ SECTION:=xorg-util
+ CATEGORY:=Xorg
+ SUBMENU:=Font-Utils
+ TITLE:=fontconfig
+ DEPENDS:=+libpthread +libexpat +libfreetype
+ URL:=https://www.freedesktop.org/wiki/Software/fontconfig/
+endef
+
+MESON_ARGS += \
+ -Ddoc=disabled \
+ -Ddoc-txt=disabled \
+ -Dnls=disabled \
+ -Dtests=disabled \
+ -Dtools=enabled
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/fontconfig $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libfontconfig.* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/fontconfig.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/fontconfig/install
+ $(INSTALL_DIR) $(1)/usr/bin $(1)/usr/lib $(1)/usr/share/fontconfig/conf.avail
+ $(INSTALL_DIR) $(1)/etc/fonts/conf.d
+ $(CP) $(PKG_INSTALL_DIR)/etc/fonts/fonts.conf $(1)/etc/fonts
+ $(CP) $(PKG_INSTALL_DIR)/etc/fonts/conf.d/* $(1)/etc/fonts/conf.d
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/* $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/fontconfig/conf.avail/* $(1)/usr/share/fontconfig/conf.avail
+ $(INSTALL_DIR) $(1)/etc/init.d
+# $(INSTALL_BIN) ./files/fontconfig.init $(1)/etc/init.d/fontconfig
+endef
+
+$(eval $(call BuildPackage,fontconfig))
diff --git a/external/subpack/utils/fuse-overlayfs/Makefile b/external/subpack/utils/fuse-overlayfs/Makefile
new file mode 100644
index 0000000..3d52aa3
--- /dev/null
+++ b/external/subpack/utils/fuse-overlayfs/Makefile
@@ -0,0 +1,38 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fuse-overlayfs
+PKG_VERSION:=1.13
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/containers/fuse-overlayfs/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=96d10344921d5796bcba7a38580ae14a53c4e60399bb90b238ac5a10b3bb65b2
+
+PKG_MAINTAINER:=W. Michael Petullo <mike@flyn.org>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/fuse-overlayfs
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libfuse3
+ TITLE:=fuse-overlayfs
+ URL:=https://github.com/containers/fuse-overlayfs
+endef
+
+define Package/fuse-overlayfs/description
+ FUSE overlay+shiftfs implementation for rootless containers
+endef
+
+define Package/fuse-overlayfs/install
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fuse-overlayfs $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,fuse-overlayfs))
diff --git a/external/subpack/utils/fuse-overlayfs/patches/010-m4.patch b/external/subpack/utils/fuse-overlayfs/patches/010-m4.patch
new file mode 100644
index 0000000..522d6d7
--- /dev/null
+++ b/external/subpack/utils/fuse-overlayfs/patches/010-m4.patch
@@ -0,0 +1,22 @@
+--- a/m4/stdint.m4
++++ b/m4/stdint.m4
+@@ -15,7 +15,7 @@ AC_DEFUN_ONCE([gl_STDINT_H],
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+ AC_REQUIRE([gl_LIMITS_H])
+- AC_REQUIRE([gt_TYPE_WINT_T])
++ AC_REQUIRE([gt_TYPE_WINT_T_FO])
+
+ dnl Check for long long int and unsigned long long int.
+ AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
+--- a/m4/wint_t.m4
++++ b/m4/wint_t.m4
+@@ -9,7 +9,7 @@ dnl Test whether <wchar.h> has the 'wint
+ dnl <wchar.h> or <wctype.h> would, if present, override 'wint_t'.
+ dnl Prerequisite: AC_PROG_CC
+
+-AC_DEFUN([gt_TYPE_WINT_T],
++AC_DEFUN([gt_TYPE_WINT_T_FO],
+ [
+ AC_CACHE_CHECK([for wint_t], [gt_cv_c_wint_t],
+ [AC_COMPILE_IFELSE(
diff --git a/external/subpack/utils/fuse/Makefile b/external/subpack/utils/fuse/Makefile
new file mode 100644
index 0000000..0805996
--- /dev/null
+++ b/external/subpack/utils/fuse/Makefile
@@ -0,0 +1,107 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=fuse
+PKG_VERSION:=2.9.9
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/libfuse/libfuse/releases/download/$(PKG_NAME)-$(PKG_VERSION)
+PKG_HASH:=d0e69d5d608cc22ff4843791ad097f554dd32540ddc9bed7638cc6fea7c1b4b5
+
+PKG_MAINTAINER:=
+PKG_CPE_ID:=cpe:/a:fuse_project:fuse
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/fuse/Default
+ TITLE:=FUSE
+ URL:=https://github.com/libfuse/libfuse
+endef
+
+define Package/fuse/Default/description
+ FUSE (Filesystem in UserSpacE)
+endef
+
+define Package/fuse-utils
+$(call Package/fuse/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libfuse
+ TITLE+= (utilities)
+ SUBMENU:=Filesystem
+ LICENSE:=GPL-2.0-only
+ LICENSE_FILES:=COPYING
+endef
+
+define Package/fuse-utils/description
+$(call Package/fuse/Default/description)
+ This package contains the FUSE utilities.
+ - fusermount
+ - ulockmgr_server
+endef
+
+define Package/libfuse
+$(call Package/fuse/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+= (library)
+ DEPENDS:=+kmod-fuse +libpthread
+ SUBMENU:=Filesystem
+ ABI_VERSION:=1
+ LICENSE:=LGPL-2.1-only
+ LICENSE_FILES:=COPYING.LIB
+endef
+
+define Package/libfuse/description
+$(call Package/fuse/Default/description)
+ This package contains the FUSE shared libraries, needed by other programs.
+ - libfuse
+ - libulockmgr
+endef
+
+# generic args
+CONFIGURE_ARGS += \
+ --enable-shared \
+ --enable-static \
+ --enable-lib \
+ --enable-util \
+ --disable-rpath \
+ --disable-example \
+ --disable-mtab
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/{fuse,fuse.h,ulockmgr.h} $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib{fuse,ulockmgr}.{a,so*} $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/fuse.pc $(1)/usr/lib/pkgconfig/
+ $(SED) 's,-I$$$${includedir}/fuse,,g' $(1)/usr/lib/pkgconfig/fuse.pc
+ $(SED) 's,-L$$$${libdir},,g' $(1)/usr/lib/pkgconfig/fuse.pc
+endef
+
+define Package/fuse-utils/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(CP) $(PKG_INSTALL_DIR)/sbin/mount.fuse $(1)/sbin/
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/{fusermount,ulockmgr_server} $(1)/usr/bin/
+endef
+
+define Package/libfuse/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib{fuse,ulockmgr}.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libfuse))
+$(eval $(call BuildPackage,fuse-utils))
diff --git a/external/subpack/utils/fuse/patches/100-missing_includes.patch b/external/subpack/utils/fuse/patches/100-missing_includes.patch
new file mode 100644
index 0000000..e74a187
--- /dev/null
+++ b/external/subpack/utils/fuse/patches/100-missing_includes.patch
@@ -0,0 +1,10 @@
+--- a/include/fuse.h
++++ b/include/fuse.h
+@@ -32,6 +32,7 @@
+ #include <sys/stat.h>
+ #include <sys/statvfs.h>
+ #include <sys/uio.h>
++#include <sys/file.h>
+
+ #ifdef __cplusplus
+ extern "C" {
diff --git a/external/subpack/utils/fuse/patches/112-no_break_on_mknod.patch b/external/subpack/utils/fuse/patches/112-no_break_on_mknod.patch
new file mode 100644
index 0000000..863af6a
--- /dev/null
+++ b/external/subpack/utils/fuse/patches/112-no_break_on_mknod.patch
@@ -0,0 +1,11 @@
+--- a/util/Makefile.in
++++ b/util/Makefile.in
+@@ -736,7 +736,7 @@ mount_util.c: $(top_srcdir)/lib/mount_ut
+
+ install-exec-hook:
+ -chmod u+s $(DESTDIR)$(bindir)/fusermount
+- @if test ! -e $(DESTDIR)/dev/fuse; then \
++ -@if test ! -e $(DESTDIR)/dev/fuse; then \
+ $(MKDIR_P) $(DESTDIR)/dev; \
+ echo "mknod $(DESTDIR)/dev/fuse -m 0666 c 10 229 || true"; \
+ mknod $(DESTDIR)/dev/fuse -m 0666 c 10 229 || true; \
diff --git a/external/subpack/utils/fuse/patches/200-backport_arm64_fuse_kernel_h_clean_includes.patch b/external/subpack/utils/fuse/patches/200-backport_arm64_fuse_kernel_h_clean_includes.patch
new file mode 100644
index 0000000..d45da84
--- /dev/null
+++ b/external/subpack/utils/fuse/patches/200-backport_arm64_fuse_kernel_h_clean_includes.patch
@@ -0,0 +1,30 @@
+From 914871b20a901e3e1e981c92bc42b1c93b7ab81b Mon Sep 17 00:00:00 2001
+From: Riku Voipio <riku.voipio@linaro.org>
+Date: Thu, 07 Feb 2013 11:04:21 +0000
+Subject: fuse_kernel.h: clean includes
+
+Use <linux/types.h> for linux and define types used for other operating systems
+using <stdint.h> types.
+---
+(limited to 'include/fuse_kernel.h')
+
+--- a/include/fuse_kernel.h
++++ b/include/fuse_kernel.h
+@@ -88,12 +88,16 @@
+ #ifndef _LINUX_FUSE_H
+ #define _LINUX_FUSE_H
+
+-#include <sys/types.h>
++#ifdef __linux__
++#include <linux/types.h>
++#else
++#include <stdint.h>
+ #define __u64 uint64_t
+ #define __s64 int64_t
+ #define __u32 uint32_t
+ #define __s32 int32_t
+ #define __u16 uint16_t
++#endif
+
+ /*
+ * Version negotiation:
diff --git a/external/subpack/utils/fuse/patches/300-closefrom.patch b/external/subpack/utils/fuse/patches/300-closefrom.patch
new file mode 100644
index 0000000..a04f26c
--- /dev/null
+++ b/external/subpack/utils/fuse/patches/300-closefrom.patch
@@ -0,0 +1,20 @@
+--- a/util/ulockmgr_server.c
++++ b/util/ulockmgr_server.c
+@@ -124,7 +124,7 @@ static int receive_message(int sock, voi
+ return res;
+ }
+
+-static int closefrom(int minfd)
++static int closefrom2(int minfd)
+ {
+ DIR *dir = opendir("/proc/self/fd");
+ if (dir) {
+@@ -384,7 +384,7 @@ int main(int argc, char *argv[])
+ dup2(nullfd, 1);
+ }
+ close(3);
+- closefrom(5);
++ closefrom2(5);
+ while (1) {
+ char c;
+ int sock;
diff --git a/external/subpack/utils/fuse3/Makefile b/external/subpack/utils/fuse3/Makefile
new file mode 100644
index 0000000..8154149
--- /dev/null
+++ b/external/subpack/utils/fuse3/Makefile
@@ -0,0 +1,103 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=fuse3
+PKG_VERSION:=3.16.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=fuse-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/libfuse/libfuse/releases/download/fuse-$(PKG_VERSION)
+PKG_HASH:=f797055d9296b275e981f5f62d4e32e089614fc253d1ef2985851025b8a0ce87
+PKG_BUILD_DIR:=$(BUILD_DIR)/fuse-$(PKG_VERSION)
+
+PKG_MAINTAINER:=
+PKG_CPE_ID:=cpe:/a:fuse_project:fuse
+
+PKG_CONFIG_DEPENDS:=CONFIG_PACKAGE_fuse3-utils
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/meson.mk
+
+define Package/fuse3/Default
+ TITLE:=FUSE
+ URL:=https://github.com/libfuse/libfuse
+ SUBMENU:=Filesystem
+endef
+
+define Package/fuse3/Default/description
+ fuse3 (Filesystem in UserSpacE)
+endef
+
+define Package/libfuse3
+$(call Package/fuse3/Default)
+ TITLE+= library
+ URL:=https://github.com/libfuse/libfuse
+ SECTION:=libs
+ CATEGORY:=Libraries
+ DEPENDS:=+kmod-fuse +libpthread
+ ABI_VERSION:=3
+ LICENSE:=LGPL-2.1-only
+ LICENSE_FILES:=LGPL2.txt
+endef
+
+define Package/libfuse3/description
+$(call Package/fuse3/Default/description)
+ This package contains the fuse3 shared libraries, needed by other programs.
+ - libfuse3
+endef
+
+define Package/fuse3-utils
+$(call Package/fuse3/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libfuse3
+ TITLE+= (utilities)
+ SUBMENU:=Filesystem
+ LICENSE:=GPL-2.0-only
+ LICENSE_FILES:=COPYING
+endef
+
+define Package/fuse3-utils/description
+$(call Package/fuse3/Default/description)
+ This package contains the FUSE utilities.
+ - fusermount3
+ - mount.fuse3
+endef
+
+MESON_ARGS += \
+ -Ddisable-mtab=true \
+ -Dudevrulesdir=/dev/null \
+ -Dutils=$(if $(CONFIG_PACKAGE_fuse3-utils),true,false) \
+ -Dexamples=false \
+ -Duseroot=false
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/fuse3
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/include/fuse3/*.h $(1)/usr/include/fuse3
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libfuse3.so* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/fuse3.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/libfuse3/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libfuse3.so.* $(1)/usr/lib/
+endef
+
+define Package/fuse3-utils/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/fusermount3 $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/mount.fuse3 $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,libfuse3))
+$(eval $(call BuildPackage,fuse3-utils))
diff --git a/external/subpack/utils/fwupd/Config.in b/external/subpack/utils/fwupd/Config.in
new file mode 100644
index 0000000..f975b96
--- /dev/null
+++ b/external/subpack/utils/fwupd/Config.in
@@ -0,0 +1,58 @@
+menu "Select fwupd options"
+ depends on PACKAGE_fwupd-libs
+
+config FWUPD_FIRMWARE_PACKAGER
+ bool "firmware packager"
+ default n
+ help
+ Compile fwupd with firmware packager
+
+config FWUPD_HSI
+ bool "Host Security ID"
+ default n
+ help
+ Compile fwupd with HSI support
+
+config FWUPD_LVFS
+ bool "LVFS remote"
+ default y
+ help
+ Compile and install LVFS remote
+
+config FWUPD_CBOR
+ bool "CBOR"
+ default n
+ help
+ Compile fwupd with cbor protocol support
+
+config FWUPD_LZMA
+ bool "LZMA"
+ default n
+ help
+ Compile fwupd with LZMA support
+
+config FWUPD_CURL
+ bool "curl"
+ default n
+ help
+ Compile fwupd with curl support
+
+config FWUPD_LIBARCHIVE
+ bool "libarchive"
+ default y
+ help
+ Compile fwupd with libarchive support
+
+config FWUPD_PLUGIN_MODEMMANAGER
+ bool "ModemManager plugin"
+ default y
+ help
+ Compile fwupd with ModemManager plugin
+
+config FWUPD_PLUGIN_FASTBOOT
+ bool "fastboot plugin"
+ default y
+ help
+ Compile fwupd with fastboot plugin
+
+endmenu
diff --git a/external/subpack/utils/fwupd/Makefile b/external/subpack/utils/fwupd/Makefile
new file mode 100644
index 0000000..0fad4de
--- /dev/null
+++ b/external/subpack/utils/fwupd/Makefile
@@ -0,0 +1,226 @@
+#
+# Copyright (C) 2024 TDT AG <development@tdt.de>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See https://www.gnu.org/licenses/gpl-2.0.txt for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fwupd
+PKG_VERSION:=2.0.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://github.com/fwupd/fwupd/releases/download/$(PKG_VERSION)
+PKG_HASH:=60a62b850e2c3a818f3178cb1de0f632b1e04c6ab07c02483af398940713548a
+
+PKG_MAINTAINER:=Lukas Voegl <lvoegl@tdt.de>
+PKG_LICENSE:=LGPL-2.1-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:fwupd:fwupd
+
+PKG_BUILD_DEPENDS:= \
+ glib2/host \
+ python3/host \
+ python-packaging/host \
+ python-jinja2/host
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+include $(INCLUDE_DIR)/meson.mk
+include ../../lang/python/python3-host.mk
+
+define Package/fwupd/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=fwupd
+ URL:=https://fwupd.org
+ DEPENDS:= \
+ +glib2 \
+ +dbus \
+ +libxmlb \
+ +libjcat \
+ +libprotobuf-c \
+ +libusb-1.0 \
+ +FWUPD_LIBARCHIVE:libarchive \
+ +FWUPD_CBOR:libcbor \
+ +FWUPD_LZMA:liblzma \
+ +FWUPD_CURL:libcurl \
+ +FWUPD_PLUGIN_MODEMMANAGER:modemmanager \
+ +FWUPD_PLUGIN_MODEMMANAGER:libqmi \
+ +FWUPD_PLUGIN_MODEMMANAGER:libmbim
+endef
+
+define Package/fwupd/Default/description
+ A simple system daemon to allow session software to easily update firmware on
+ your local machine.
+endef
+
+define Package/fwupd-libs
+ $(call Package/fwupd/Default)
+ TITLE:=fwupd-libs
+endef
+
+define Package/fwupd-libs/description
+ $(call Package/fwupd/Default/description)
+ This package contains the fwupd libraries.
+endef
+
+define Package/fwupd-libs/config
+ source "$(SOURCE)/Config.in"
+endef
+
+define Package/fwupd-tools
+ $(call Package/fwupd/Default)
+ DEPENDS:=+fwupd-libs
+ TITLE:=fwupd-tools
+endef
+
+define Package/fwupd-tools/description
+ $(call Package/fwupd/Default/description)
+ This package contains the fwupd cli tools.
+endef
+
+define Package/fwupd-daemon
+ $(call Package/fwupd/Default)
+ DEPENDS:=+fwupd-libs
+ TITLE:=fwupd-daemon
+endef
+
+define Package/fwupd-daemon/description
+ $(call Package/fwupd/Default/description)
+ This package contains the fwupd daemon.
+endef
+
+MESON_ARGS += \
+ -Db_lto=true \
+ -Dbuild=all \
+ -Dpython=$(HOST_PYTHON3_BIN) \
+ -Dsupported_build=enabled \
+ -Dstatic_analysis=false \
+ -Dtests=false \
+ -Dmetainfo=false \
+ -Dbash_completion=false \
+ -Dfish_completion=false \
+ -Dman=false \
+ -Dconsolekit=disabled \
+ -Ddocs=disabled \
+ -Dintrospection=disabled \
+ -Dbluez=disabled \
+ -Dvendor_ids_dir=/usr/share/hwdata \
+ -Dpolkit=disabled \
+ -Dgnutls=disabled \
+ -Dpassim=disabled \
+ -Dsqlite=disabled \
+ -Dudev=enabled \
+ -Dplugin_acpi_phat=disabled \
+ -Dplugin_amdgpu=disabled \
+ -Dplugin_android_boot=disabled \
+ -Dplugin_bcm57xx=disabled \
+ -Dplugin_cfu=disabled \
+ -Dplugin_cpu=disabled \
+ -Dplugin_emmc=disabled \
+ -Dplugin_ep963x=disabled \
+ -Dplugin_gpio=disabled \
+ -Dplugin_igsc=disabled \
+ -Dplugin_kinetic_dp=disabled \
+ -Dplugin_logitech_bulkcontroller=disabled \
+ -Dplugin_logitech_scribe=disabled \
+ -Dplugin_logitech_tap=disabled \
+ -Dplugin_parade_lspcon=disabled \
+ -Dplugin_pixart_rf=disabled \
+ -Dplugin_realtek_mst=disabled \
+ -Dplugin_synaptics_mst=disabled \
+ -Dplugin_mediatek_scaler=disabled \
+ -Dplugin_synaptics_rmi=disabled \
+ -Dplugin_scsi=disabled \
+ -Dplugin_tpm=disabled \
+ -Dplugin_redfish=disabled \
+ -Dplugin_uefi_capsule=disabled \
+ -Dplugin_uefi_pk=disabled \
+ -Dplugin_nitrokey=disabled \
+ -Dplugin_nvme=disabled \
+ -Dplugin_msr=disabled \
+ -Dplugin_mtd=disabled \
+ -Dplugin_flashrom=disabled \
+ -Dplugin_intel_me=disabled \
+ -Dplugin_uf2=disabled \
+ -Dplugin_upower=disabled \
+ -Dplugin_powerd=disabled \
+ -Dsystemd=disabled \
+ -Dlaunchd=disabled \
+ -Delogind=disabled \
+ -Dfirmware-packager=$(if $(CONFIG_FWUPD_FIRMWARE_PACKAGER),true,false) \
+ -Dhsi=$(if $(CONFIG_FWUPD_HSI),enabled,disabled) \
+ -Dlvfs=$(if $(CONFIG_FWUPD_LVFS),true,false) \
+ -Dcbor=$(if $(CONFIG_FWUPD_CBOR),enabled,disabled) \
+ -Dlzma=$(if $(CONFIG_FWUPD_LZMA),enabled,disabled) \
+ -Dcurl=$(if $(CONFIG_FWUPD_CURL),enabled,disabled) \
+ -Dlibarchive=$(if $(CONFIG_FWUPD_LIBARCHIVE),enabled,disabled) \
+ -Dplugin_modem_manager=$(if $(CONFIG_FWUPD_PLUGIN_MODEMMANAGER),enabled,disabled) \
+ -Dplugin_fastboot=$(if $(CONFIG_FWUPD_PLUGIN_FASTBOOT),enabled,disabled)
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/fwupd-3
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/fwupd-3/fwupd.h $(1)/usr/include/fwupd-3
+
+ $(INSTALL_DIR) $(1)/usr/include/fwupd-3/libfwupd
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/fwupd-3/libfwupd/*.h $(1)/usr/include/fwupd-3/libfwupd
+
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libfwupd.so* $(1)/usr/lib
+
+ $(INSTALL_DIR) $(1)/usr/lib/fwupd-$(PKG_VERSION)
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/fwupd-$(PKG_VERSION)/*.so* $(1)/usr/lib/fwupd-$(PKG_VERSION)
+
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/fwupd.pc $(1)/usr/lib/pkgconfig
+
+ $(INSTALL_DIR) $(1)/usr/share/dbus-1/interfaces
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/dbus-1/interfaces/*.xml $(1)/usr/share/dbus-1/interfaces
+endef
+
+define Package/fwupd-libs/install
+ $(INSTALL_DIR) $(1)/etc/fwupd
+ $(CP) $(PKG_INSTALL_DIR)/etc/fwupd/fwupd.conf $(1)/etc/fwupd
+
+ $(INSTALL_DIR) $(1)/etc/fwupd/remotes.d
+ $(CP) $(PKG_INSTALL_DIR)/etc/fwupd/remotes.d/*.conf $(1)/etc/fwupd/remotes.d
+
+ $(INSTALL_DIR) $(1)/etc/pki
+ $(CP) $(PKG_INSTALL_DIR)/etc/pki/fwupd $(1)/etc/pki
+ $(CP) $(PKG_INSTALL_DIR)/etc/pki/fwupd-metadata $(1)/etc/pki
+
+ $(INSTALL_DIR) $(1)/usr/share/dbus-1/system.d
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/dbus-1/system.d/org.freedesktop.fwupd.conf $(1)/usr/share/dbus-1/system.d
+
+ $(INSTALL_DIR) $(1)/usr/share/fwupd
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/fwupd/quirks.d $(1)/usr/share/fwupd
+
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libfwupd.so* $(1)/usr/lib
+
+ $(INSTALL_DIR) $(1)/usr/lib/fwupd-$(PKG_VERSION)
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/fwupd-$(PKG_VERSION)/*.so* $(1)/usr/lib/fwupd-$(PKG_VERSION)
+endef
+
+define Package/fwupd-tools/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fwupdtool $(1)/usr/bin
+endef
+
+define Package/fwupd-daemon/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fwupdmgr $(1)/usr/bin
+
+ $(INSTALL_DIR) $(1)/usr/libexec/fwupd
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/libexec/fwupd/fwupd $(1)/usr/libexec/fwupd
+
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/etc/init.d/fwupd $(1)/etc/init.d/fwupd
+endef
+
+$(eval $(call BuildPackage,fwupd-libs))
+$(eval $(call BuildPackage,fwupd-tools))
+$(eval $(call BuildPackage,fwupd-daemon))
diff --git a/external/subpack/utils/fwupd/files/etc/init.d/fwupd b/external/subpack/utils/fwupd/files/etc/init.d/fwupd
new file mode 100644
index 0000000..e48458b
--- /dev/null
+++ b/external/subpack/utils/fwupd/files/etc/init.d/fwupd
@@ -0,0 +1,15 @@
+#!/bin/sh /etc/rc.common
+
+USE_PROCD=1
+START=80
+VERBOSE=0
+
+start_service() {
+ procd_open_instance
+ procd_set_param command /usr/libexec/fwupd/fwupd
+ [ "$VERBOSE" = 1 ] && procd_append_param command --verbose
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}"
+ procd_close_instance
+}
diff --git a/external/subpack/utils/fwupd/test.sh b/external/subpack/utils/fwupd/test.sh
new file mode 100644
index 0000000..e0b788f
--- /dev/null
+++ b/external/subpack/utils/fwupd/test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+case "$1" in
+ fwupdmgr|fwupdtool) "$1" --version 2>&1 | grep "runtime\s*org.freedesktop.fwupd\s*$2" ;;
+esac
diff --git a/external/subpack/utils/gammu/Makefile b/external/subpack/utils/gammu/Makefile
new file mode 100644
index 0000000..300339a
--- /dev/null
+++ b/external/subpack/utils/gammu/Makefile
@@ -0,0 +1,62 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+# 2014-2015 Vitaly Protsko
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gammu
+PKG_VERSION:=1.42.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://dl.cihar.com/gammu/releases
+PKG_HASH:=d8f152314d7e4d3d643610d742845e0a016ce97c234ad4b1151574e1b09651ee
+
+PKG_MAINTAINER:=Vitaly Protsko <villy@sft.ru>
+PKG_LICENCE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+CMAKE_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/gammu
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Cell phone/modem SMS and control tool
+ URL:=https://wammu.eu/gammu/
+ DEPENDS:=+libpthread +libcurl +glib2
+ DEPENDS+=+PACKAGE_bluez-libs:bluez-libs
+ DEPENDS+=+PACKAGE_libmariadb:libmariadb +PACKAGE_unixodbc:unixodbc +PACKAGE_libpq:libpq
+ DEPENDS+=+PACKAGE_libusb-1.0:libusb-1.0
+endef
+
+CMAKE_OPTIONS += \
+ -DDWITH_GettextLibs=OFF \
+ -DWITH_Iconv=OFF \
+ -DWITH_Libintl=OFF \
+ -DWITH_LibDBI:BOOL=OFF
+
+define Package/gammu/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gammu $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gammu-{smsd,smsd-inject,smsd-monitor} $(1)/usr/bin
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib{Gammu*,gsmsd*} $(1)/usr/lib
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) ./files/gammu $(1)/etc/config/gammu
+ $(INSTALL_BIN) ./files/gammu.init $(1)/etc/init.d/gammu
+endef
+
+define Package/gammu/conffiles
+/etc/config/gammu
+endef
+
+$(eval $(call BuildPackage,gammu))
diff --git a/external/subpack/utils/gammu/files/gammu b/external/subpack/utils/gammu/files/gammu
new file mode 100644
index 0000000..d05fb25
--- /dev/null
+++ b/external/subpack/utils/gammu/files/gammu
@@ -0,0 +1,5 @@
+config daemon default
+ option enabled 0
+ option device /dev/ttyUSB0
+ option connection at
+ option logfile syslog
diff --git a/external/subpack/utils/gammu/files/gammu.init b/external/subpack/utils/gammu/files/gammu.init
new file mode 100755
index 0000000..a022697
--- /dev/null
+++ b/external/subpack/utils/gammu/files/gammu.init
@@ -0,0 +1,117 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2015 villy@sft.ru
+
+START=98
+
+USE_PROCD=1
+PROG=/usr/bin/gammu-smsd
+CONFPFX=/var/gammu
+
+start_instance() {
+ local conf="$1"
+ local item
+ local conffile="$CONFPFX-$conf.conf"
+
+ config_get_bool item "$conf" enabled 0
+ [ "$item" = 0 ] && return
+
+ {
+ printf "; don't edit. instead look into /etc/config/gammu\n[gammu]\n\n"
+
+ config_get item "$conf" device
+ [ -z "$item" ] && return
+ echo "device = $item"
+
+ config_get item "$conf" connection
+ [ -z "$item" ] && return
+ echo "connection = $item"
+
+ config_get item "$conf" logfile
+ [ -z "$item" ] && item=syslog
+ echo "logfile = $item"
+
+ printf "\n[smsd]\nphoneid = %s\nservice = files\nlogfile = %s\n" "$conf" "$item"
+ printf "checkbattery = 0\nhangupcalls = 1\n"
+
+ config_get item "$conf" pin
+ [ -n "$item" ] && echo "pin = $item"
+ config_get item "$conf" phonecode
+ [ -n "$item" ] && echo "phonecode = $item"
+
+ config_get item "$conf" send
+ [ -n "$item" ] && echo "send = $item"
+
+ config_get item "$conf" receive
+ [ -n "$item" ] && echo "receive = $item"
+
+ config_get item "$conf" timeout
+ [ -n "$item" ] && echo "commtimeout = $item"
+
+ config_get item "$conf" sleep
+ [ -n "$item" ] && echo "loopsleep = $item"
+
+ config_get item "$conf" report
+ [ -n "$item" ] && echo "deliveryreport = $item"
+
+ config_get item "$conf" onreceive
+ [ -n "$item" ] && echo "runonreceive = $item"
+
+ config_get item "$conf" onerror
+ [ -n "$item" ] && echo "runonfailure = $item"
+
+ config_get item "$conf" spool
+ [ -z "$item" ] && item=/var/sms
+ [ -d "$item" ] || {
+ mkdir "$item"
+ mkdir "$item/inbox"
+ mkdir "$item/outbox"
+ mkdir "$item/sent"
+ mkdir "$item/error"
+ }
+ printf "inboxpath = %s/inbox/\noutboxpath = %s/outbox/\n" "$item" "$item"
+ printf "sentsmspath = %s/sent/\nerrorsmspath = %s/error/\n" "$item" "$item"
+ } > "$conffile"
+
+ config_get item "$conf" allow
+ [ -n "$item" ] && {
+ local data
+ local allowfile=$CONFPFX-$conf.allow
+ for data in $item ; do
+ echo $data >> "$allowfile"
+ done
+
+ echo "includenumbersfile = $allowfile" >> "$conffile"
+ }
+
+ config_get item "$conf" deny
+ [ -n "$item" ] && {
+ local data
+ local denyfile=$CONFPFX-$conf.deny
+ for data in $item ; do
+ echo $data >> "$denyfile"
+ done
+
+ echo "excludenumbersfile = $denyfile" >> "$conffile"
+ }
+
+ procd_open_instance
+
+ config_get_bool item "$conf" respawn 0
+ [ "$item" = 0 ] || procd_set_param respawn
+
+ procd_set_param command $PROG --config="$conffile"
+
+ config_get item "$conf" pidfile
+ [ -n "$item" ] && procd_append_param command --pid=$item
+
+ procd_close_instance
+}
+
+start_service() {
+ config_load gammu
+ config_foreach start_instance daemon
+}
+
+service_triggers() {
+ procd_add_reload_trigger "gammu"
+}
diff --git a/external/subpack/utils/gammu/patches/020-select.patch b/external/subpack/utils/gammu/patches/020-select.patch
new file mode 100644
index 0000000..de4ba46
--- /dev/null
+++ b/external/subpack/utils/gammu/patches/020-select.patch
@@ -0,0 +1,10 @@
+--- a/libgammu/device/devfunc.c
++++ b/libgammu/device/devfunc.c
+@@ -24,6 +24,7 @@
+ # include <signal.h>
+ # include <sys/socket.h>
+ # include <sys/stat.h>
++# include <sys/select.h>
+ #endif
+
+ #include "devfunc.h"
diff --git a/external/subpack/utils/gawk/Makefile b/external/subpack/utils/gawk/Makefile
new file mode 100644
index 0000000..a2cef3d
--- /dev/null
+++ b/external/subpack/utils/gawk/Makefile
@@ -0,0 +1,46 @@
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gawk
+PKG_VERSION:=5.3.0
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/gawk
+PKG_HASH:=ca9c16d3d11d0ff8c69d79dc0b47267e1329a69b39b799895604ed447d3ca90b
+
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/gawk
+ SECTION:=utils
+ CATEGORY:=Utilities
+ URL:=https://www.gnu.org/software/gawk/
+ TITLE:=GNU awk
+ DEPENDS:=+libncursesw +libreadline
+ ALTERNATIVES:=200:/usr/bin/awk:/usr/bin/gawk
+endef
+
+CONFIGURE_ARGS+= --disable-mpfr
+
+define Package/gawk/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/gawk $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/lib/gawk
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/gawk/* $(1)/usr/lib/gawk/
+ $(INSTALL_DIR) $(1)/usr/lib/awk
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/awk/* $(1)/usr/lib/awk/
+ $(INSTALL_DIR) $(1)/usr/share/awk
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/awk/* $(1)/usr/share/awk/
+endef
+
+$(eval $(call BuildPackage,gawk))
diff --git a/external/subpack/utils/gddrescue/Makefile b/external/subpack/utils/gddrescue/Makefile
new file mode 100644
index 0000000..c5de5eb
--- /dev/null
+++ b/external/subpack/utils/gddrescue/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2018 Lucian Cristian
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gddrescue
+PKG_VERSION:=1.23
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.xz
+PKG_SOURCE_URL:=http://http.debian.net/debian/pool/main/g/$(PKG_NAME)
+PKG_HASH:=5831d7e24070bc700d8f22deaeec56af1149392ce30ae67254096eaf8c9169ab
+
+PKG_MAINTAINER:=Lucian Cristian <lucian.cristian@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/uclibc++.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/gddrescue
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Data recovery tool
+ URL:=https://www.gnu.org/software/ddrescue/
+ DEPENDS:=$(CXX_DEPENDS)
+endef
+
+define Package/gddrescue/description
+ GNU ddrescue is a data recovery tool. It copies data from one file
+ or block device (hard disc, cdrom, etc) to another, trying to rescue
+ the good parts first in case of read errors.
+endef
+
+CONFIGURE_ARGS += \
+ CXX="$(TARGET_CXX)" \
+ CPPFLAGS="$(TARGET_CPPFLAGS)" \
+ CXXFLAGS="$(TARGET_CXXFLAGS)" \
+ LDFLAGS="$(TARGET_LDFLAGS)"
+
+define Package/gddrescue/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ddrescue $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ddrescuelog $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,gddrescue))
diff --git a/external/subpack/utils/gddrescue/patches/001-fix_uclibc.patch b/external/subpack/utils/gddrescue/patches/001-fix_uclibc.patch
new file mode 100644
index 0000000..c516d2c
--- /dev/null
+++ b/external/subpack/utils/gddrescue/patches/001-fix_uclibc.patch
@@ -0,0 +1,28 @@
+--- a/block.h
++++ b/block.h
+@@ -34,6 +34,7 @@ class Block
+ { if( size_ < 0 || size_ > LLONG_MAX - pos_ ) size_ = LLONG_MAX - pos_; }
+
+ public:
++ Block() {} // default constructor
+ Block( const long long p, const long long s ) : pos_( p ), size_( s )
+ { if( p < 0 ) { pos_ = 0; if( s > 0 ) size_ -= std::min( s, -p ); }
+ fix_size(); }
+@@ -102,6 +103,7 @@ private:
+ Status status_;
+
+ public:
++ Sblock() {} // default constructor
+ Sblock( const Block & b, const Status st )
+ : Block( b ), status_( st ) {}
+ Sblock( const long long p, const long long s, const Status st )
+--- a/mapbook.cc
++++ b/mapbook.cc
+@@ -19,6 +19,7 @@
+
+ #include <algorithm>
+ #include <cerrno>
++#include <cctype>
+ #include <climits>
+ #include <cstdio>
+ #include <cstdlib>
diff --git a/external/subpack/utils/gkermit/Makefile b/external/subpack/utils/gkermit/Makefile
new file mode 100644
index 0000000..fc59547
--- /dev/null
+++ b/external/subpack/utils/gkermit/Makefile
@@ -0,0 +1,59 @@
+# Copyright (C) 2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v3+.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gkermit
+PKG_VERSION:=1.00
+PKG_RELEASE:=2
+
+PKG_SOURCE:=gku100.tar.gz
+PKG_SOURCE_URL:=https://ftp.nluug.nl/networking/kermit/archives
+PKG_HASH:=3dbe63291277c4795255343b48b860777fb0a160163d7e1d30b1ee68585593eb
+
+PKG_MAINTAINER:=Nathaniel Wesley Filardo <nwfilardo@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/gkermit
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=gkermit
+ URL:=http://www.columbia.edu/kermit/gkermit.html
+endef
+
+define Package/gkermit/description
+ A minimal kermit file transfer program
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ tar -C $(PKG_BUILD_DIR) -xzvf "$(DL_DIR)/$(PKG_SOURCE)"
+ $(Build/Patch)
+endef
+
+# nothing to do
+define Build/Configure
+endef
+
+define Build/Compile
+ mkdir -p $(PKG_INSTALL_DIR)
+ $(TARGET_CC) \
+ $(TARGET_CFLAGS) $(TARGET_CPPFLAGS) \
+ -include string.h -include unistd.h \
+ -DPOSIX -DERRNO_H \
+ -o $(PKG_INSTALL_DIR)/gkermit \
+ $(PKG_BUILD_DIR)/{gproto,gkermit,gunixio,gcmdline}.c
+endef
+
+define Package/gkermit/install
+ $(INSTALL_DIR) $(1)/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/gkermit $(1)/bin
+endef
+
+$(eval $(call BuildPackage,gkermit))
diff --git a/external/subpack/utils/gkermit/patches/010-musl.patch b/external/subpack/utils/gkermit/patches/010-musl.patch
new file mode 100644
index 0000000..e8458a5
--- /dev/null
+++ b/external/subpack/utils/gkermit/patches/010-musl.patch
@@ -0,0 +1,29 @@
+--- a/gcmdline.c
++++ b/gcmdline.c
+@@ -29,6 +29,7 @@
+ */
+
+ #include <stdio.h>
++#include <stdlib.h>
+ #include "gkermit.h"
+
+ /* Externals */
+@@ -53,7 +54,7 @@ _MYPROTOTYPE( VOID fatal, (char *) );
+ _MYPROTOTYPE( VOID usage, (void) );
+
+ #ifndef NOGETENV
+-_MYPROTOTYPE( char * getenv, (char *) );
++_MYPROTOTYPE( char * getenv, (const char *) );
+ #define GARGC 32
+ #define GBUFSIZ 256
+ static char gbuf[GBUFSIZ], *gargs[GARGC], *gptr = NULL;
+--- a/gunixio.c
++++ b/gunixio.c
+@@ -58,6 +58,7 @@
+ */
+
+ #include <stdio.h> /* Standard input/output */
++#include <stdlib.h>
+
+ #ifdef POSIX
+ #include <termios.h> /* Terminal modes */
diff --git a/external/subpack/utils/gl-mifi-mcu/Makefile b/external/subpack/utils/gl-mifi-mcu/Makefile
new file mode 100755
index 0000000..08183d9
--- /dev/null
+++ b/external/subpack/utils/gl-mifi-mcu/Makefile
@@ -0,0 +1,36 @@
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=gl-mifi-mcu
+PKG_VERSION:=1
+PKG_RELEASE:=1
+
+PKG_MAINTAINER:=Nuno Goncalves <nunojpg@gmail.com>
+PKG_LICENSE:=GPL-3.0-or-later
+
+include $(INCLUDE_DIR)/package.mk
+
+define KernelPackage/gl-mifi-mcu
+ SUBMENU:=Hardware Monitoring Support
+ TITLE:=GL.iNet GL-MiFI Power monitoring support
+ AUTOLOAD:=$(call AutoLoad,60,gl-mifi-mcu)
+ FILES:=$(PKG_BUILD_DIR)/gl-mifi-mcu.ko
+endef
+
+define KernelPackage/gl-mifi-mcu/description
+ Interfaces with GL-MiFI Power monitoring MCU with a soft UART
+ and provides Battery SOC, Temperature and charging data at
+ /proc/gl_mifi_mcu.
+ This feature is supported from GL-MiFi PCB revision v2.6.2.
+ The content of /proc/gl_mifi_mcu is JSON as received from the
+ UART and will frequenty contain corrupted data due to soft UART
+ unreliability. User application must validate the data.
+endef
+
+define Build/Compile
+ $(KERNEL_MAKE) \
+ M="$(PKG_BUILD_DIR)" \
+ modules
+endef
+
+$(eval $(call KernelPackage,gl-mifi-mcu))
diff --git a/external/subpack/utils/gl-mifi-mcu/src/Makefile b/external/subpack/utils/gl-mifi-mcu/src/Makefile
new file mode 100755
index 0000000..bce424b
--- /dev/null
+++ b/external/subpack/utils/gl-mifi-mcu/src/Makefile
@@ -0,0 +1,4 @@
+obj-m += gl-mifi-mcu.o
+
+gl-mifi-mcu-objs := module.o
+
diff --git a/external/subpack/utils/gl-mifi-mcu/src/module.c b/external/subpack/utils/gl-mifi-mcu/src/module.c
new file mode 100755
index 0000000..8f5a514
--- /dev/null
+++ b/external/subpack/utils/gl-mifi-mcu/src/module.c
@@ -0,0 +1,210 @@
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/hrtimer.h>
+#include <linux/interrupt.h>
+#include <linux/ktime.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/version.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nuno Goncalves");
+MODULE_DESCRIPTION("GL-MiFi power monitoring MCU interface");
+MODULE_VERSION("0.1");
+
+static int gpio_tx = 19;
+static int gpio_rx = 8;
+static int baudrate = 1200;
+static int query_interval_sec = 4;
+
+static struct hrtimer timer_tx;
+static struct hrtimer timer_rx;
+static ktime_t period;
+static int rx_bit_index = -1;
+
+static unsigned read_buf_ready = 0;
+static unsigned read_buf_size = 0;
+static char read_buf[2][64] = {{0},{0}};
+
+static int proc_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "%s\n", read_buf[read_buf_ready]);
+ return 0;
+}
+
+static int proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_show, NULL);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
+static const struct proc_ops hello_proc_ops = {
+ .proc_open = proc_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release,
+};
+#else
+static const struct file_operations hello_proc_ops = {
+ .owner = THIS_MODULE,
+ .open = proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+#endif
+
+static irq_handler_t handle_rx_start(unsigned int irq, void* device, struct pt_regs* registers)
+{
+ if (rx_bit_index == -1)
+ {
+ hrtimer_start(&timer_rx, ktime_set(0, period / 2), HRTIMER_MODE_REL);
+ }
+ return (irq_handler_t) IRQ_HANDLED;
+}
+
+static enum hrtimer_restart handle_tx(struct hrtimer* timer)
+{
+ ktime_t current_time = ktime_get();
+ const unsigned char character = 'g';
+ static int bit_index = -1;
+
+ // Start bit.
+ if (bit_index == -1)
+ {
+ gpio_set_value(gpio_tx, 0);
+ bit_index++;
+ }
+
+ // Data bits.
+ else if (0 <= bit_index && bit_index < 8)
+ {
+ gpio_set_value(gpio_tx, 1 & (character >> bit_index));
+ bit_index++;
+ }
+
+ // Stop bit.
+ else if (bit_index == 8)
+ {
+ gpio_set_value(gpio_tx, 1);
+ bit_index = -1;
+ }
+
+ hrtimer_forward(&timer_tx, current_time, bit_index == 8
+ ? ktime_set(query_interval_sec, 0) //wait for next query cycle
+ : period); //wait for next bit period
+
+ return HRTIMER_RESTART;
+}
+
+void receive_character(unsigned char character)
+{
+ if(character == '{')
+ read_buf_size = 0;
+
+ if(read_buf_size < (sizeof(read_buf[0])-1) || character == '}')
+ {
+ read_buf[!read_buf_ready][read_buf_size++] = character;
+ if(character == '}')
+ {
+ read_buf[!read_buf_ready][read_buf_size] = '\0';
+ read_buf_ready = !read_buf_ready;
+ read_buf_size = 0;
+ }
+ }
+}
+
+static enum hrtimer_restart handle_rx(struct hrtimer* timer)
+{
+ ktime_t current_time = ktime_get();
+ static unsigned int character = 0;
+ int bit_value = gpio_get_value(gpio_rx);
+ enum hrtimer_restart result = HRTIMER_NORESTART;
+ bool must_restart_timer = false;
+
+ // Start bit.
+ if (rx_bit_index == -1)
+ {
+ rx_bit_index++;
+ character = 0;
+ must_restart_timer = true;
+ }
+
+ // Data bits.
+ else if (0 <= rx_bit_index && rx_bit_index < 8)
+ {
+ if (bit_value == 0)
+ {
+ character &= 0xfeff;
+ }
+ else
+ {
+ character |= 0x0100;
+ }
+
+ rx_bit_index++;
+ character >>= 1;
+ must_restart_timer = true;
+ }
+
+ // Stop bit.
+ else if (rx_bit_index == 8)
+ {
+ receive_character(character);
+ rx_bit_index = -1;
+ }
+
+ // Restarts the RX timer.
+ if (must_restart_timer)
+ {
+ hrtimer_forward(&timer_rx, current_time, period);
+ result = HRTIMER_RESTART;
+ }
+
+ return result;
+}
+
+static int __init init(void)
+{
+ bool success = true;
+
+ proc_create("gl_mifi_mcu", 0, NULL, &hello_proc_ops);
+
+ success &= gpio_request(gpio_tx, "soft_uart_tx") == 0;
+ success &= gpio_direction_output(gpio_tx, 1) == 0;
+ success &= gpio_request(gpio_rx, "soft_uart_rx") == 0;
+ success &= gpio_direction_input(gpio_rx) == 0;
+ success &= gpio_set_debounce(gpio_rx, 1000/baudrate/2);
+
+ success &= request_irq(
+ gpio_to_irq(gpio_rx),
+ (irq_handler_t) handle_rx_start,
+ IRQF_TRIGGER_FALLING,
+ "gl_mifi_mcu_irq_handler",
+ NULL) == 0;
+
+ hrtimer_init(&timer_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ timer_tx.function = &handle_tx;
+ hrtimer_init(&timer_rx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ timer_rx.function = &handle_rx;
+ period = ktime_set(0, 1000000000/baudrate);
+ hrtimer_start(&timer_tx, period, HRTIMER_MODE_REL);
+
+ return success;
+}
+
+static void __exit exit(void)
+{
+ disable_irq(gpio_to_irq(gpio_rx));
+ hrtimer_cancel(&timer_tx);
+ hrtimer_cancel(&timer_rx);
+ free_irq(gpio_to_irq(gpio_rx), NULL);
+ gpio_set_value(gpio_tx, 0);
+ gpio_free(gpio_tx);
+ gpio_free(gpio_rx);
+ remove_proc_entry("gl_mifi_mcu", NULL);
+}
+
+module_init(init);
+module_exit(exit);
+
diff --git a/external/subpack/utils/gnupg/Makefile b/external/subpack/utils/gnupg/Makefile
new file mode 100644
index 0000000..f362643
--- /dev/null
+++ b/external/subpack/utils/gnupg/Makefile
@@ -0,0 +1,112 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gnupg
+PKG_VERSION:=1.4.23
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://gnupg.org/ftp/gcrypt/gnupg
+PKG_HASH:=c9462f17e651b6507848c08c430c791287cd75491f8b5a8b50c6ed46b12678ba
+
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/gnupg/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Encryption
+ DEPENDS:=+zlib +libncurses +libreadline
+ TITLE:=GNU privacy guard - a free PGP replacement
+ URL:=http://www.gnupg.org/
+endef
+
+define Package/gnupg
+ $(call Package/gnupg/Default)
+ MENU:=1
+ ALTERNATIVES:=200:/usr/bin/gpg:/usr/bin/gpg1
+endef
+
+define Package/gpgv
+ $(call Package/gnupg/Default)
+ TITLE:=GnuPG signature verification only
+ ALTERNATIVES:=200:/usr/bin/gpgv:/usr/bin/gpgv1
+endef
+
+define Package/gnupg-utils
+ $(call Package/gnupg/Default)
+ DEPENDS:=gnupg +libcurl
+ TITLE:=Key management utilities for GnuPG
+endef
+
+define Package/gnupg/description
+ GnuPG is GNU's tool for secure communication and data storage.
+ It can be used to encrypt data and to create digital signatures.
+ It includes an advanced key management facility and is compliant
+ with the proposed OpenPGP Internet standard as described in RFC2440.
+ .
+ GnuPG does not use any patented algorithms so it cannot be compatible
+ with PGP2 because it uses IDEA (which is patented worldwide).
+endef
+
+define Package/gpgv/description
+ GPGv is a stripped down version of GnuPG that only checks signatures.
+ .
+ GnuPG does not use any patented algorithms so it cannot be compatible
+ with PGP2 because it uses IDEA (which is patented worldwide).
+endef
+
+define Package/gnupg-utils/description
+ Key management utilies for GnuPG.
+ This package is needed to import keys from a keyserver.
+endef
+
+CONFIGURE_ARGS += \
+ --disable-rpath \
+ --disable-asm \
+ --disable-gnupg-iconv \
+ --disable-card-support \
+ --disable-agent-support \
+ --disable-bzip2 \
+ --disable-ldap \
+ --disable-finger \
+ --disable-dns-srv \
+ --disable-regex
+
+MAKE_FLAGS += \
+ SUBDIRS="m4 intl zlib util mpi cipher tools g10 keyserver ${checks}" \
+
+TARGET_CFLAGS += $(if $(CONFIG_GCC_USE_VERSION_10),-DEXTERN_UNLESS_MAIN_MODULE=static)
+
+define Package/gnupg/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gpg $(1)/usr/bin/gpg1
+endef
+
+define Package/gpgv/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gpgv $(1)/usr/bin/gpgv1
+endef
+
+define Package/gnupg-utils/install
+ $(INSTALL_DIR) $(1)/usr/lib/gnupg
+ for file in gpgkeys_curl gpgkeys_hkp; do \
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/gnupg/$$$$file \
+ $(1)/usr/lib/gnupg/; \
+ done
+endef
+
+$(eval $(call BuildPackage,gnupg))
+$(eval $(call BuildPackage,gpgv))
+$(eval $(call BuildPackage,gnupg-utils))
diff --git a/external/subpack/utils/gnupg2/Makefile b/external/subpack/utils/gnupg2/Makefile
new file mode 100644
index 0000000..7577105
--- /dev/null
+++ b/external/subpack/utils/gnupg2/Makefile
@@ -0,0 +1,142 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gnupg
+PKG_VERSION:=2.2.23
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://gnupg.org/ftp/gcrypt/gnupg
+PKG_HASH:=10b55e49d78b3e49f1edb58d7541ecbdad92ddaeeb885b6f486ed23d1cd1da5c
+
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING COPYING.CC0 COPYING.GPL2 COPYING.LGPL21 COPYING.LGPL3 COPYING.other
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/gnupg2/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Encryption
+ DEPENDS:=+libgpg-error +libnpth +libassuan +libksba +libgcrypt +zlib +libncurses +libreadline $(ICONV_DEPENDS) $(INTL_DEPENDS)
+ TITLE:=GNU privacy guard (version 2) - a free PGP replacement
+ URL:=http://www.gnupg.org/
+endef
+
+define Package/gnupg2
+ $(call Package/gnupg2/Default)
+ MENU:=1
+ ALTERNATIVES:=300:/usr/bin/gpg:/usr/bin/gpg2
+endef
+
+define Package/gpgv2
+ $(call Package/gnupg2/Default)
+ TITLE:=GnuPG signature verification only (version 2)
+ ALTERNATIVES:=300:/usr/bin/gpgv:/usr/bin/gpgv2
+endef
+
+define Package/gnupg2-dirmngr
+ $(call Package/gnupg2/Default)
+ TITLE:=Keyserver, CRL, and OCSP access for GnuPG (version 2)
+endef
+
+define Package/gnupg2-utils
+ $(call Package/gnupg2/Default)
+ DEPENDS:=gnupg2 +libcurl
+ TITLE:=Key management utilities for GnuPG (version 2)
+endef
+
+define Package/gnupg2/description
+GnuPG is a complete and free implementation of the OpenPGP standard as
+defined by RFC4880 (also known as PGP). GnuPG allows you to encrypt and
+sign your data and communications; it features a versatile key
+management system, along with access modules for all kinds of public
+key directories. GnuPG, also known as GPG, is a command line tool with
+features for easy integration with other applications. A wealth of
+frontend applications and libraries are available. GnuPG also provides
+support for S/MIME and Secure Shell (ssh).
+endef
+
+define Package/gpgv2/description
+ GPGv is a stripped down version of GnuPG that only checks signatures.
+endef
+
+define Package/gnupg2-dirmngr/description
+Since version 2.1 of GnuPG, 'dirmngr' takes care of accessing the
+OpenPGP keyservers. As with previous versions it is also used as a
+server for managing and downloading certificate revocation lists (CRLs)
+for X.509 certificates, downloading X.509 certificates, and providing
+access to OCSP providers. Dirmngr is invoked internally by 'gpg',
+'gpgsm', or via the 'gpg-connect-agent' tool.
+endef
+
+define Package/gnupg2-utils/description
+ Key management utilies for GnuPG (version 2).
+ This package is needed to import keys from a keyserver.
+endef
+
+CONFIGURE_ARGS += \
+ --with-gpg-error-prefix="$(STAGING_DIR)/usr/" \
+ --with-libgcrypt-prefix="$(STAGING_DIR)/usr/" \
+ --with-libassuan-prefix="$(STAGING_DIR)/usr/" \
+ --with-ksba-prefix="$(STAGING_DIR)/usr/" \
+ --with-npth-prefix="$(STAGING_DIR)/usr/" \
+ --enable-dirmngr \
+ --disable-bzip2 \
+ --disable-card-support \
+ --disable-ccid-driver \
+ --disable-gnutls \
+ --disable-ldap \
+ --disable-ntbtls \
+ --disable-rpath \
+ --disable-sqlite \
+ --disable-tests \
+ --disable-zip
+
+TARGET_CFLAGS += $(if $(CONFIG_GCC_USE_VERSION_10),-DEXTERN_UNLESS_MAIN_MODULE=static)
+
+define Package/gnupg2/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gpg $(1)/usr/bin/gpg2
+endef
+
+define Package/gpgv2/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gpgv $(1)/usr/bin/gpgv2
+endef
+
+define Package/gnupg2-dirmngr/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dirmngr $(1)/usr/bin/dirmngr
+endef
+
+define Package/gnupg2-utils/install
+ $(INSTALL_DIR) $(1)/usr/bin $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gpgtar $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/kbxutil $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gpg-wks-server $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gpg-agent $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gpg-connect-agent $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gpgsplit $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gpgparsemail $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gpgsm $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/addgnupghome $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/applygnupgdefaults $(1)/usr/sbin
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/gpg-* $(1)/usr/lib
+endef
+
+$(eval $(call BuildPackage,gnupg2))
+$(eval $(call BuildPackage,gpgv2))
+$(eval $(call BuildPackage,gnupg2-dirmngr))
+$(eval $(call BuildPackage,gnupg2-utils))
diff --git a/external/subpack/utils/gnuplot/Makefile b/external/subpack/utils/gnuplot/Makefile
new file mode 100644
index 0000000..5789a53
--- /dev/null
+++ b/external/subpack/utils/gnuplot/Makefile
@@ -0,0 +1,47 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gnuplot
+PKG_VERSION:=5.4.1
+PKG_RELEASE:=1
+PKG_MAINTAINER:=Matteo Cicuttin <datafl4sh@toxicnet.eu>
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/gnuplot-$(PKG_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/gnuplot
+PKG_HASH:=6b690485567eaeb938c26936e5e0681cf70c856d273cc2c45fabf64d8bc6590e
+PKG_CAT:=zcat
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/gnuplot
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+zlib +libgd +libncursesw +libreadline
+ TITLE:=A portable command-line driven graphing utility
+ URL:=http://www.gnuplot.info/
+endef
+
+CONFIGURE_ARGS += \
+ --without-cairo \
+ --with-qt=no \
+ --without-lua \
+ --without-latex \
+ --without-libcerf
+
+# Since Qt is disabled there is no C++ code, so CXX is forced
+# to CC in order to avoid dependency on libstdcpp. This is
+# horrible, but 'DEPENDS:=+libstdcpp' does not work for some
+# reason.
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CXX="$(TARGET_CC_NOCACHE)"
+endef
+
+define Package/gnuplot/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/gnuplot $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,gnuplot))
+
diff --git a/external/subpack/utils/gnuplot/patches/010-remove_doc_from_makefile.patch b/external/subpack/utils/gnuplot/patches/010-remove_doc_from_makefile.patch
new file mode 100644
index 0000000..90c4f5b
--- /dev/null
+++ b/external/subpack/utils/gnuplot/patches/010-remove_doc_from_makefile.patch
@@ -0,0 +1,11 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,7 +1,7 @@
+ ## Process this file with automake to produce Makefile.in -*-Makefile-*-
+ AUTOMAKE_OPTIONS = foreign
+
+-SUBDIRS = config m4 term src docs man demo share
++SUBDIRS = config m4 term src man share
+
+ EXTRA_DIST = BUGS Copyright FAQ.pdf INSTALL INSTALL.gnu \
+ PATCHLEVEL PGPKEYS README RELEASE_NOTES \
diff --git a/external/subpack/utils/gpsd/Makefile b/external/subpack/utils/gpsd/Makefile
new file mode 100644
index 0000000..915200a
--- /dev/null
+++ b/external/subpack/utils/gpsd/Makefile
@@ -0,0 +1,167 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gpsd
+PKG_VERSION:=3.23
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@SAVANNAH/$(PKG_NAME)
+PKG_HASH:=e36429b9f6fc42004894dff3dc4453f5b43f95af8533b96d3d135987418da9df
+
+PKG_MAINTAINER:=Pushpal Sidhu <psidhu.devel@gmail.com>
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:berlios:gps_daemon
+
+PKG_BUILD_DEPENDS:=scons/host
+
+include $(INCLUDE_DIR)/package.mk
+include ../../devel/scons/scons.mk
+
+define Package/gpsd/Default
+ DEPENDS+= +libusb-1.0
+ URL:=https://gpsd.gitlab.io/gpsd/
+endef
+
+define Package/gpsd/Default/description
+ gpsd is a userland daemon acting as a translator between GPS and AIS receivers
+ and their clients. gpsd listens on port 2947 for clients requesting
+ position/time/velocity information. The receivers are expected to generate
+ position information in a well-known format -- as NMEA-0183 sentences, SiRF
+ binary, Rockwell binary, Garmin binary format, or other vendor binary
+ protocols. gpsd takes this information from the GPS and translates it into
+ something uniform and easier to understand for clients.
+endef
+
+define Package/gpsd
+ $(call Package/gpsd/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=An interface daemon for GPS receivers
+endef
+
+define Package/gpsd/conffiles
+/etc/config/gpsd
+endef
+
+define Package/gpsd/description
+ $(call Package/gpsd/Default/description)
+ This package contains the GPS daemon.
+endef
+
+define Package/gpsd-clients
+ $(call Package/gpsd/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS+= +libncurses
+ TITLE:=GPS tools and clients
+endef
+
+define Package/gpsd-clients/description
+ $(call Package/gpsd/Default/description)
+ This package contains auxiliary tools and example clients for monitoring and
+ testing the GPS daemon.
+endef
+
+define Package/gpsd-utils
+ $(call Package/gpsd/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=GPS daemon utils
+endef
+
+define Package/gpsd-utils/description
+ $(call Package/gpsd/Default/description)
+ This package contains utilities for interacting with GPS daemon.
+endef
+
+define Package/libgps
+ $(call Package/gpsd/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=C service library for communicating with the GPS daemon
+ ABI_VERSION:=29
+endef
+
+define Package/libgps/description
+ $(call Package/gpsd/Default/description)
+ This package contains the libgps library.
+endef
+
+SCONS_VARS += \
+ CFLAGS="$(TARGET_CFLAGS) $(EXTRA_CFLAGS) -L$(STAGING_DIR)/usr/lib" \
+ LINKFLAGS="$(TARGET_LDFLAGS)"
+
+SCONS_OPTIONS += \
+ dbus_export=no \
+ tsip=no \
+ fv18=no \
+ tripmate=no \
+ earthmate=no \
+ itrax=no \
+ navcom=no \
+ ubx=no \
+ evermore=no \
+ ntrip=no \
+ libgpsmm=no \
+ libQgpsmm=no \
+ bluez=no \
+ nostrip=yes \
+ python=no \
+ implicit_link=no \
+ chrpath=no \
+ manbuild=no \
+ sysroot="$(TOOLCHAIN_DIR)" \
+ target="$(TARGET_CROSS:-=)"
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/gps.h $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libgps*.so* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libgps.pc $(1)/usr/lib/pkgconfig
+ $(SED) 's,/usr/include,$$$${prefix}/include,g' $(1)/usr/lib/pkgconfig/libgps.pc
+ $(SED) 's,/usr/lib,$$$${exec_prefix}/lib,g' $(1)/usr/lib/pkgconfig/libgps.pc
+endef
+
+define Package/gpsd/install
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) ./files/gpsd.config $(1)/etc/config/gpsd
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/gpsd.init $(1)/etc/init.d/gpsd
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/gpsd $(1)/usr/sbin/
+endef
+
+define Package/gpsd-clients/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) \
+ $(PKG_INSTALL_DIR)/usr/bin/cgps \
+ $(PKG_INSTALL_DIR)/usr/bin/gps{ctl,decode,mon,pipe} \
+ $(PKG_INSTALL_DIR)/usr/bin/gpxlogger \
+ $(PKG_INSTALL_DIR)/usr/bin/lcdgps \
+ $(1)/usr/bin/
+endef
+
+define Package/gpsd-utils/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/gpsdctl $(1)/usr/sbin/
+endef
+
+define Package/libgps/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libgps.so.$(ABI_VERSION)* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,gpsd))
+$(eval $(call BuildPackage,gpsd-clients))
+$(eval $(call BuildPackage,gpsd-utils))
+$(eval $(call BuildPackage,libgps))
diff --git a/external/subpack/utils/gpsd/files/gpsd.config b/external/subpack/utils/gpsd/files/gpsd.config
new file mode 100644
index 0000000..c0c88e0
--- /dev/null
+++ b/external/subpack/utils/gpsd/files/gpsd.config
@@ -0,0 +1,5 @@
+config gpsd 'core'
+ option enabled '0'
+ option device '/dev/ttyUSB0'
+ option port '2947'
+ option listen_globally '0'
diff --git a/external/subpack/utils/gpsd/files/gpsd.init b/external/subpack/utils/gpsd/files/gpsd.init
new file mode 100644
index 0000000..3271d43
--- /dev/null
+++ b/external/subpack/utils/gpsd/files/gpsd.init
@@ -0,0 +1,47 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2009-2011 OpenWrt.org
+START=50
+
+USE_PROCD=1
+PROG=/usr/sbin/gpsd
+NAME=gpsd
+
+validate_section_gpsd()
+{
+ uci_load_validate gpsd gpsd "$1" "$2" \
+ 'enabled:bool:1' \
+ 'device:string' \
+ 'listen_globally:bool:0' \
+ 'port:port:2947'
+}
+
+gpsd_instance()
+{
+ [ "$2" = 0 ] || {
+ echo "validation failed"
+ return 1
+ }
+
+ [ "$enabled" = "0" ] && return 1
+
+ procd_open_instance
+ procd_set_param command "$PROG" -N -n
+
+ [ "$listen_globally" -ne 0 ] && procd_append_param command -G
+ procd_append_param command -S "$port"
+ procd_append_param command "$device"
+ procd_set_param respawn
+
+ procd_close_instance
+}
+
+start_service()
+{
+ config_load "$NAME"
+ config_foreach validate_section_gpsd gpsd gpsd_instance
+}
+
+service_triggers() {
+ procd_add_reload_trigger "$NAME"
+ procd_add_validation validate_section_gpsd
+}
diff --git a/external/subpack/utils/gpsd/patches/0002-ncurses6_detection.patch b/external/subpack/utils/gpsd/patches/0002-ncurses6_detection.patch
new file mode 100644
index 0000000..13ad85c
--- /dev/null
+++ b/external/subpack/utils/gpsd/patches/0002-ncurses6_detection.patch
@@ -0,0 +1,11 @@
+--- a/SConscript
++++ b/SConscript
+@@ -1027,6 +1027,8 @@ if not cleaning and not helping:
+ ncurseslibs += pkg_config('tinfo', rpath_hack=True)
+ # It's not yet known whether rpath_hack is appropriate for
+ # ncurses5-config.
++ elif WhereIs('ncursesw6-config'):
++ ncurseslibs = ['!ncursesw6-config --libs --cflags']
+ elif WhereIs('ncurses5-config'):
+ ncurseslibs = ['!ncurses5-config --libs --cflags']
+ elif WhereIs('ncursesw5-config'):
diff --git a/external/subpack/utils/gpsd/test.sh b/external/subpack/utils/gpsd/test.sh
new file mode 100644
index 0000000..0ebca13
--- /dev/null
+++ b/external/subpack/utils/gpsd/test.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+case "$1" in
+ "gpsd")
+ gpsd -V 2>&1 | grep "$2"
+ ;;
+ "gpsd-clients")
+ cgps -V 2>&1 | grep "$2"
+ ;;
+esac
diff --git a/external/subpack/utils/gptfdisk/Makefile b/external/subpack/utils/gptfdisk/Makefile
new file mode 100644
index 0000000..7f22033
--- /dev/null
+++ b/external/subpack/utils/gptfdisk/Makefile
@@ -0,0 +1,103 @@
+#
+# Copyright (C) 2018 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gptfdisk
+PKG_VERSION:=1.0.10
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_HASH:=2abed61bc6d2b9ec498973c0440b8b804b7a72d7144069b5a9209b2ad693a282
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_BUILD_PARALLEL:=1
+PKG_BUILD_FLAGS:=gc-sections lto
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/gptfdisk/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Disc
+ URL:=https://www.rodsbooks.com/gdisk
+ DEPENDS:=+libstdcpp
+endef
+
+define Package/gdisk
+$(call Package/gptfdisk/Default)
+ TITLE:=GPT aware disk manipulation utility for interactive use
+ DEPENDS+= +libuuid
+endef
+
+define Package/gdisk/description
+ gdisk is GPT aware disk partitioning tool, with interactive UI.
+endef
+
+define Package/cgdisk
+$(call Package/gptfdisk/Default)
+ TITLE:=GPT aware disk manipulation utility for interactive use
+ DEPENDS+= +libuuid +libncursesw
+endef
+
+define Package/cgdisk/description
+ cgdisk is GPT aware disk partitioning tool, with interactive ncurses based UI.
+endef
+
+define Package/sgdisk
+$(call Package/gptfdisk/Default)
+ TITLE:=GPT aware disk manipulation utility for scripting use
+ DEPENDS+= +libuuid +libpopt
+endef
+
+define Package/sgdisk/description
+ sgdisk is GPT-aware disk partitioning tool for scripting use.
+endef
+
+define Package/fixparts
+$(call Package/gptfdisk/Default)
+ TITLE:=A utility to fix corrupted MBR partitions
+ DEPENDS+=
+endef
+
+define Package/fixparts/description
+ a text-mode menu-driven program for repairing certain types of problems with
+ Master Boot Record (MBR) partition tables
+endef
+
+TARGET_CXXFLAGS += -std=c++11 -fno-rtti
+TARGET_LDFLAGS += -Wl,--as-needed
+MAKE_FLAGS += TARGET=linux
+
+define Package/gdisk/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/gdisk $(1)/usr/bin/
+endef
+
+define Package/cgdisk/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/cgdisk $(1)/usr/bin/
+endef
+
+define Package/sgdisk/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/sgdisk $(1)/usr/bin/
+endef
+
+define Package/fixparts/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/fixparts $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,gdisk))
+$(eval $(call BuildPackage,cgdisk))
+$(eval $(call BuildPackage,sgdisk))
+$(eval $(call BuildPackage,fixparts))
diff --git a/external/subpack/utils/grep/Makefile b/external/subpack/utils/grep/Makefile
new file mode 100644
index 0000000..f63d66b
--- /dev/null
+++ b/external/subpack/utils/grep/Makefile
@@ -0,0 +1,55 @@
+#
+# Copyright (C) 2010-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=grep
+PKG_VERSION:=3.11
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/grep
+PKG_HASH:=1db2aedde89d0dea42b16d9528f894c8d15dae4e190b59aecc78f5a951276eab
+
+PKG_MAINTAINER:=Julen Landa Alustiza <julen@zokormazo.info>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:gnu:grep
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+MAKE_FLAGS += SHELL="/bin/sh"
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/grep
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=grep search utility - full version
+ DEPENDS:=+libpcre2
+ URL:=https://www.gnu.org/software/grep/
+ ALTERNATIVES:=\
+ 300:/bin/egrep:/usr/libexec/egrep-gnu \
+ 300:/bin/fgrep:/usr/libexec/fgrep-gnu \
+ 300:/bin/grep:/usr/libexec/grep-gnu
+endef
+
+define Package/grep/description
+The grep command searches one or more input files for lines
+containing a match to a specified pattern. By default, grep
+prints the matching lines.
+endef
+
+define Package/grep/install
+ $(INSTALL_DIR) $(1)/usr/libexec
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/egrep $(1)/usr/libexec/egrep-gnu
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fgrep $(1)/usr/libexec/fgrep-gnu
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/grep $(1)/usr/libexec/grep-gnu
+endef
+
+$(eval $(call BuildPackage,grep))
diff --git a/external/subpack/utils/grep/patches/ppc-musl.patch b/external/subpack/utils/grep/patches/ppc-musl.patch
new file mode 100644
index 0000000..aeb0266
--- /dev/null
+++ b/external/subpack/utils/grep/patches/ppc-musl.patch
@@ -0,0 +1,15 @@
+https://github.com/void-linux/void-packages/commit/0d9556b8593d6e67027fb1c83d176b7f899547e5
+--- a/lib/sigsegv.c
++++ b/lib/sigsegv.c
+@@ -246,8 +246,10 @@ int libsigsegv_version = LIBSIGSEGV_VERS
+ /* Because of the union, both definitions should be equivalent. */
+ # if 0
+ # define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.regs->gpr[1]
+-# else
++# elif defined(__GLIBC__)
+ # define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.uc_regs->gregs[1]
++# else
++# define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs[1]
+ # endif
+ # endif
+ # endif
diff --git a/external/subpack/utils/gzip/Makefile b/external/subpack/utils/gzip/Makefile
new file mode 100644
index 0000000..64189a8
--- /dev/null
+++ b/external/subpack/utils/gzip/Makefile
@@ -0,0 +1,55 @@
+#
+# Copyright (C) 2006-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gzip
+PKG_VERSION:=1.13
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/gzip
+PKG_HASH:=7454eb6935db17c6655576c2e1b0fabefd38b4d0936e0f87f48cd062ce91a057
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_CPE_ID:=cpe:/a:gnu:gzip
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/gzip
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Compression
+ TITLE:=gzip (GNU zip) is a compression utility.
+ URL:=https://www.gnu.org/software/gzip/
+ MAINTAINER:=Christian Beier <dontmind@freeshell.org>
+ ALTERNATIVES:=\
+ 300:/bin/gunzip:/usr/libexec/gunzip-gnu \
+ 300:/bin/gzip:/usr/libexec/gzip-gnu \
+ 300:/bin/zcat:/usr/libexec/zcat-gnu
+endef
+
+define Package/gzip/description
+ gzip (GNU zip) is a compression utility designed to be a \
+ replacement for compress.
+endef
+
+CONFIGURE_VARS += \
+ gl_cv_func_getopt_gnu=yes \
+ ac_cv_search_clock_gettime=no
+
+define Package/gzip/install
+ $(SED) 's,/bin/bash,/bin/sh,g' $(PKG_INSTALL_DIR)/usr/bin/{gunzip,zcat}
+ $(INSTALL_DIR) $(1)/usr/libexec
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gunzip $(1)/usr/libexec/gunzip-gnu
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/gzip $(1)/usr/libexec/gzip-gnu
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/zcat $(1)/usr/libexec/zcat-gnu
+endef
+
+$(eval $(call BuildPackage,gzip))
diff --git a/external/subpack/utils/hamlib/Makefile b/external/subpack/utils/hamlib/Makefile
new file mode 100644
index 0000000..84e0553
--- /dev/null
+++ b/external/subpack/utils/hamlib/Makefile
@@ -0,0 +1,101 @@
+#
+# Copyright (C) 2014-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hamlib
+PKG_VERSION:=3.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/hamlib
+PKG_HASH:=c90b53949c767f049733b442cd6e0a48648b55d99d4df5ef3f852d985f45e880
+
+PKG_MAINTAINER:=Vasilis Tsiligiannis <acinonyx@openwrt.gr>
+PKG_LICENSE:=GPLv2
+PKG_LICENSE_FILES:=COPYING
+
+PKG_FIXUP:=autoreconf
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/hamlib/Default
+ TITLE:=Ham Radio Control
+ URL:=http://hamlib.sourceforge.net
+endef
+
+define Package/hamlib/Default/description
+ Ham Radio Control Libraries is a development effort to provide a consistent
+ interface for programmers wanting to incorporate radio control in their
+ programs.
+endef
+
+define Package/hamlib
+ $(call Package/hamlib/Default)
+ TITLE+= utilities
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libhamlib
+endef
+
+define Package/hamlib/description
+ $(call Package/hamlib/Default/description)
+
+ This package contains the utilities and daemons.
+endef
+
+define Package/libhamlib/Default
+ $(call Package/hamlib/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+= shared library
+endef
+
+define Package/libhamlib
+ $(call Package/libhamlib/Default)
+ DEPENDS:=+libusb-1.0
+ MENU:=1
+endef
+
+define Package/libhamlib/description
+ $(call Package/hamlib/Default/description)
+
+ This package contains the hamlib shared library.
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/hamlib
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/hamlib/*.h $(1)/usr/include/hamlib
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libhamlib.so* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/hamlib.pc $(1)/usr/lib/pkgconfig/
+endef
+
+CONFIGURE_ARGS+= \
+ --disable-html-matrix \
+ --disable-winradio \
+ --without-readline \
+ --without-cxx-binding \
+ --with-pic \
+
+CONFIGURE_VARS+= \
+ LIBUSB_LIBS="-lusb-1.0" \
+
+define Package/hamlib/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/{rig,rot}* $(1)/usr/bin/
+endef
+
+define Package/libhamlib/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libhamlib.so* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,hamlib))
+$(eval $(call BuildPackage,libhamlib))
diff --git a/external/subpack/utils/haserl/Config.in b/external/subpack/utils/haserl/Config.in
new file mode 100644
index 0000000..e5fb90d
--- /dev/null
+++ b/external/subpack/utils/haserl/Config.in
@@ -0,0 +1,35 @@
+if PACKAGE_haserl
+
+ config HASERL_with_lua
+ bool
+ default n
+
+ comment "Lua support"
+
+ config HASERL_shell_luac
+ bool
+ prompt "Support --shell=luac"
+ select HASERL_with_lua
+ default n
+ help
+ haserl(1):
+ The luac "shell" is a precompiled lua chunk, so interactive
+ editing and testing of scripts is not possible. However,
+ haserl can be compiled with luac support only, and this
+ allows lua support even in a small memory environment. All
+ haserl lua features listed above are still available. (If
+ luac is the only shell built into haserl, the
+ haserl.loadfile is disabled, as the haserl parser is not
+ compiled in.)
+
+ config HASERL_shell_lua
+ bool
+ prompt "Support --shell=lua"
+ select HASERL_with_lua
+ default n
+ help
+ haserl(1):
+ If compiled with lua support, --shell=lua will enable lua as the
+ script language instead of bash shell.
+
+endif
diff --git a/external/subpack/utils/haserl/Makefile b/external/subpack/utils/haserl/Makefile
new file mode 100644
index 0000000..6020727
--- /dev/null
+++ b/external/subpack/utils/haserl/Makefile
@@ -0,0 +1,57 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=haserl
+PKG_VERSION:=0.9.35
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/haserl
+PKG_HASH:=a1b633e80f3e2638e7f8f850786e95072cfd9877f88780092996fd6aaf7ae2da
+PKG_MAINTAINER:=Maxim Storchak <m.storchak@gmail.com>
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=COPYING
+
+PKG_CONFIG_DEPENDS:= \
+ CONFIG_HASERL_with_lua \
+ CONFIG_HASERL_shell_luac \
+ CONFIG_HASERL_shell_lua \
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/haserl
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=A CGI wrapper to embed shell scripts in HTML documents
+ URL:=http://haserl.sourceforge.net/
+ MENU:=1
+ DEPENDS:= +HASERL_with_lua:liblua
+endef
+
+define Package/haserl/config
+ source "$(SOURCE)/Config.in"
+endef
+
+ifeq ($(CONFIG_HASERL_with_lua),y)
+ CONFIGURE_ARGS+=--with-lua
+ TARGET_LDFLAGS += -ldl
+endif
+ifneq ($(CONFIG_HASERL_shell_lua),y)
+ CONFIGURE_ARGS+=--disable-luashell
+endif
+ifneq ($(CONFIG_HASERL_shell_luac),y)
+ CONFIGURE_ARGS+=--disable-luacshell
+endif
+
+define Package/haserl/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/haserl $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,haserl))
diff --git a/external/subpack/utils/haserl/patches/100-replace-lua2c-with-sed.patch b/external/subpack/utils/haserl/patches/100-replace-lua2c-with-sed.patch
new file mode 100644
index 0000000..622995e
--- /dev/null
+++ b/external/subpack/utils/haserl/patches/100-replace-lua2c-with-sed.patch
@@ -0,0 +1,80 @@
+--- a/src/Makefile.in
++++ b/src/Makefile.in
+@@ -86,7 +86,6 @@ POST_INSTALL = :
+ NORMAL_UNINSTALL = :
+ PRE_UNINSTALL = :
+ POST_UNINSTALL = :
+-@USE_LUA_TRUE@noinst_PROGRAMS = lua2c$(EXEEXT)
+ @INCLUDE_LUASHELL_TRUE@@USE_LUA_TRUE@am__append_1 = h_lua.c h_lua.h
+ @INCLUDE_LUACSHELL_TRUE@@USE_LUA_TRUE@am__append_2 = h_luac.c h_luac.h
+ bin_PROGRAMS = haserl$(EXEEXT)
+@@ -124,9 +123,6 @@ am__DEPENDENCIES_1 =
+ haserl_DEPENDENCIES = $(am__DEPENDENCIES_1)
+ haserl_LINK = $(CCLD) $(haserl_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+-lua2c_SOURCES = lua2c.c
+-lua2c_OBJECTS = lua2c.$(OBJEXT)
+-lua2c_LDADD = $(LDADD)
+ AM_V_P = $(am__v_P_@AM_V@)
+ am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+ am__v_P_0 = false
+@@ -159,8 +155,8 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+ am__v_CCLD_0 = @echo " CCLD " $@;
+ am__v_CCLD_1 =
+-SOURCES = $(haserl_SOURCES) $(nodist_haserl_SOURCES) lua2c.c
+-DIST_SOURCES = $(am__haserl_SOURCES_DIST) lua2c.c
++SOURCES = $(haserl_SOURCES) $(nodist_haserl_SOURCES)
++DIST_SOURCES = $(am__haserl_SOURCES_DIST)
+ am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+@@ -284,7 +280,7 @@ target_alias = @target_alias@
+ top_build_prefix = @top_build_prefix@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+-EXTRA_DIST = haserl_lualib.lua lua2c.c
++EXTRA_DIST = haserl_lualib.lua
+
+ # Not strictly required, but we explicitly do not distribute the generated inc file
+ nodist_haserl_SOURCES = haserl_lualib.inc
+@@ -396,10 +392,6 @@ haserl$(EXEEXT): $(haserl_OBJECTS) $(has
+ @rm -f haserl$(EXEEXT)
+ $(AM_V_CCLD)$(haserl_LINK) $(haserl_OBJECTS) $(haserl_LDADD) $(LIBS)
+
+-@USE_LUA_FALSE@lua2c$(EXEEXT): $(lua2c_OBJECTS) $(lua2c_DEPENDENCIES) $(EXTRA_lua2c_DEPENDENCIES)
+-@USE_LUA_FALSE@ @rm -f lua2c$(EXEEXT)
+-@USE_LUA_FALSE@ $(AM_V_CCLD)$(LINK) $(lua2c_OBJECTS) $(lua2c_LDADD) $(LIBS)
+-
+ mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+@@ -416,7 +408,6 @@ distclean-compile:
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/haserl-haserl.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/haserl-rfc2388.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/haserl-sliding_buffer.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lua2c.Po@am__quote@
+
+ .c.o:
+ @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@@ -770,17 +761,13 @@ uninstall-am: uninstall-binPROGRAMS
+ .PRECIOUS: Makefile
+
+
+-# lua2c_LIBS ?= -llua -ldl -lm
+-@USE_LUA_TRUE@lua2c_LDFLAGS ?= -Wl,-E
+-@USE_LUA_TRUE@lua2c: lua2c.c
+-@USE_LUA_TRUE@ $(CC_FOR_BUILD) $(CFLAGS) $(LUA_CFLAGS) $(LDFLAGS) $(lua2c_LDFLAGS) \
+-@USE_LUA_TRUE@ -o $@ $^ $(LIBS) $(LUA_LIBS)
+
+-@USE_LUA_TRUE@haserl_lualib.inc : haserl_lualib.lua lua2c
+-@USE_LUA_TRUE@ if ! ./lua2c haserl_lualib haserl_lualib.lua >$@; then \
++@USE_LUA_TRUE@haserl_lualib.inc : haserl_lualib.lua
++@USE_LUA_TRUE@ if ! sed -re '/--\[\[/,/\]\]--/d; s/[[:space:]]*--.*//g; s/^[[:space:]]*//g; /^$$/d; s/ (=+) /\1/g; s/,[[:space:]]*/,/g; s/ ([()])/\1/g; s/key/k/g; s/value/v/g; s/^/"/; s/$$/\\n"/' haserl_lualib.lua >$@.tmp; then \
+ @USE_LUA_TRUE@ rm $@; \
+ @USE_LUA_TRUE@ exit 1 ;\
+ @USE_LUA_TRUE@ fi
++@USE_LUA_TRUE@ { echo "static const char haserl_lualib[] = "; cat $@.tmp; echo ";"; rm $@.tmp; } >$@
+
+ @USE_LUA_TRUE@h_lua_common.c : haserl_lualib.inc
+
diff --git a/external/subpack/utils/haserl/patches/101-adjust-script-size.patch b/external/subpack/utils/haserl/patches/101-adjust-script-size.patch
new file mode 100644
index 0000000..1c4da25
--- /dev/null
+++ b/external/subpack/utils/haserl/patches/101-adjust-script-size.patch
@@ -0,0 +1,11 @@
+--- a/src/h_lua_common.c
++++ b/src/h_lua_common.c
+@@ -79,7 +79,7 @@ lua_common_setup (char *shell, list_t *
+
+ /* and load our haserl library */
+ if (luaL_loadbuffer
+- (lua_vm, (const char *) &haserl_lualib, sizeof (haserl_lualib),
++ (lua_vm, (const char *) haserl_lualib, sizeof(haserl_lualib)-1,
+ "luascript.lua") || lua_pcall (lua_vm, 0, 0, 0))
+ {
+ die_with_message (NULL, NULL,
diff --git a/external/subpack/utils/hashdeep/Makefile b/external/subpack/utils/hashdeep/Makefile
new file mode 100644
index 0000000..f697e08
--- /dev/null
+++ b/external/subpack/utils/hashdeep/Makefile
@@ -0,0 +1,45 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hashdeep
+PKG_VERSION:=4.4
+PKG_RELEASE:=1
+PKG_MAINTAINER=Tobe Deprez <trldp@outlook.com>
+PKG_LICENSE:=NLPL
+PKG_LICENSE_FILES:=COPYING
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/jessek/hashdeep/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=ad78d42142f9a74fe8ec0c61bc78d6588a528cbb9aede9440f50b6ff477f3a7f
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/uclibc++.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/hashdeep
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Recursively compute hashsums or piecewise hashings
+ URL:=http://md5deep.sourceforge.net/
+ DEPENDS:=$(CXX_DEPENDS)
+endef
+
+define Package/hashdeep/description
+ hashdeep is a set of tools to compute MD5, SHA1, SHA256, tiger
+ and whirlpool hashsums of arbitrary number of files recursively.
+endef
+
+define Package/hashdeep/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hashdeep \
+ $(PKG_INSTALL_DIR)/usr/bin/md5deep \
+ $(PKG_INSTALL_DIR)/usr/bin/sha1deep \
+ $(PKG_INSTALL_DIR)/usr/bin/sha256deep \
+ $(PKG_INSTALL_DIR)/usr/bin/tigerdeep \
+ $(PKG_INSTALL_DIR)/usr/bin/whirlpooldeep \
+ $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,hashdeep))
+
diff --git a/external/subpack/utils/haveged/Makefile b/external/subpack/utils/haveged/Makefile
new file mode 100644
index 0000000..05cdc59
--- /dev/null
+++ b/external/subpack/utils/haveged/Makefile
@@ -0,0 +1,66 @@
+#
+# Copyright (C) 2006-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=haveged
+PKG_VERSION:=1.9.18
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/jirka-h/haveged/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=b835fa02b52ee7d06276e028571cadcb14d08f5e5a4b5767adf81451f70561c7
+PKG_BUILD_DIR:=$(BUILD_DIR)/haveged-$(PKG_VERSION)
+PKG_LICENSE:=GPLv3
+
+PKG_MAINTAINER:=Hannu Nyman <hannu.nyman@iki.fi>
+
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/haveged
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libhavege
+ TITLE:=Feeds the kernel entropy pool by timing CPU loops.
+ URL:=http://www.issihosts.com/haveged/
+endef
+
+define Package/libhavege
+ CATEGORY:=Libraries
+ TITLE:=Library for haveged
+ URL:=http://www.issihosts.com/haveged/
+endef
+
+CONFIGURE_ARGS+= \
+ --enable-daemon=yes \
+ --enable-threads=no \
+ --enable-olt=no
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/src/havege.h $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/src/.libs/libhavege.{a,so*} $(1)/usr/lib/
+endef
+
+define Package/haveged/install
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/haveged.init $(1)/etc/init.d/haveged
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/.libs/haveged $(1)/usr/sbin/
+endef
+
+define Package/libhavege/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/src/.libs/libhavege.so* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,haveged))
+$(eval $(call BuildPackage,libhavege))
diff --git a/external/subpack/utils/haveged/files/haveged.init b/external/subpack/utils/haveged/files/haveged.init
new file mode 100644
index 0000000..da3a55d
--- /dev/null
+++ b/external/subpack/utils/haveged/files/haveged.init
@@ -0,0 +1,17 @@
+#!/bin/sh /etc/rc.common
+
+START=01
+USE_PROCD=1
+
+HAVEGED_THRESHOLD=1024
+HAVEGED_DCACHE=32
+HAVEGED_ICACHE=32
+
+start_service() {
+ procd_open_instance
+ procd_set_param command /usr/sbin/haveged
+ procd_append_param command -F -w $HAVEGED_THRESHOLD -d $HAVEGED_DCACHE -i $HAVEGED_ICACHE -v 1
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_close_instance
+}
diff --git a/external/subpack/utils/hd-idle/Makefile b/external/subpack/utils/hd-idle/Makefile
new file mode 100644
index 0000000..405753d
--- /dev/null
+++ b/external/subpack/utils/hd-idle/Makefile
@@ -0,0 +1,55 @@
+#
+# Copyright (C) 2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hd-idle
+PKG_VERSION:=1.05
+PKG_RELEASE:=2
+
+PKG_MAINTAINER:=Lim Guo Wei <limguowei@gmail.com>
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tgz
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_HASH:=4efefe79d145b50e055582730d9d685e485da3df3dad90fef030036d52aa3a0c
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/hd-idle
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Another idle-daemon for attached hard drives
+ SUBMENU:=Disc
+ URL:=http://hd-idle.sourceforge.net/
+endef
+
+define Package/hd-idle/description
+ hd-idle is a utility program for spinning-down external disks after a period of idle time.
+endef
+
+define Build/Compile
+ $(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/$(PKG_NAME) $(PKG_BUILD_DIR)/$(PKG_NAME).c
+endef
+
+define Package/hd-idle/conffiles
+/etc/config/hd-idle
+endef
+
+define Package/hd-idle/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_NAME) $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/$(PKG_NAME).config $(1)/etc/config/$(PKG_NAME)
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/$(PKG_NAME).init $(1)/etc/init.d/$(PKG_NAME)
+endef
+
+$(eval $(call BuildPackage,hd-idle))
diff --git a/external/subpack/utils/hd-idle/files/hd-idle.config b/external/subpack/utils/hd-idle/files/hd-idle.config
new file mode 100644
index 0000000..dbbd358
--- /dev/null
+++ b/external/subpack/utils/hd-idle/files/hd-idle.config
@@ -0,0 +1,5 @@
+config 'hd-idle'
+ option 'disk' 'sda'
+ option 'enabled' '0'
+ option 'idle_time_unit' 'minutes'
+ option 'idle_time_interval' '10'
diff --git a/external/subpack/utils/hd-idle/files/hd-idle.init b/external/subpack/utils/hd-idle/files/hd-idle.init
new file mode 100644
index 0000000..bdf9bb8
--- /dev/null
+++ b/external/subpack/utils/hd-idle/files/hd-idle.init
@@ -0,0 +1,75 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2008-2011 OpenWrt.org
+
+START=50
+STOP=10
+
+USE_PROCD=1
+
+validate_section_hdidle()
+{
+ uci_load_validate hd-idle hd-idle "$1" "$2" \
+ 'disk:string' \
+ 'enabled:bool' \
+ 'idle_time_interval:uinteger:10' \
+ 'idle_time_unit:string:minutes'
+}
+
+compute_seconds() {
+ local interval="$1"
+ local unit="$2"
+
+ # compute interval in seconds
+ case "$unit" in
+ "days" )
+ interval_seconds=$(($interval*60*60*24))
+ ;;
+ "hours" )
+ interval_seconds=$(($interval*60*60))
+ ;;
+ "minutes" )
+ interval_seconds=$(($interval*60))
+ ;;
+ "seconds" )
+ interval_seconds=$interval
+ ;;
+ * )
+ # default is minutes
+ interval_seconds=$(($interval*60))
+ ;;
+ esac
+
+ echo $interval_seconds
+}
+
+hdidle_append() {
+ [ "$2" = 0 ] || return
+
+ [ "$enabled" -gt 0 ] || return
+
+ if [ "$numdisks" = "0" ]; then
+ procd_open_instance
+ procd_set_param command /usr/bin/hd-idle
+ procd_append_param command -d -i 0
+ fi
+ procd_append_param command -a $disk
+ procd_append_param command -i "$(compute_seconds $idle_time_interval $idle_time_unit)"
+ numdisks=$(( numdisks + 1 ))
+}
+
+start_service() {
+ config_load "hd-idle"
+
+ numdisks="0"
+ config_foreach validate_section_hdidle "hd-idle" hdidle_append
+
+ if [ "$numdisks" -gt 0 ]; then
+ procd_set_param respawn
+ procd_close_instance
+ fi
+}
+
+service_triggers() {
+ procd_add_reload_trigger "hd-idle"
+ procd_add_validation validate_section_hdidle
+}
diff --git a/external/subpack/utils/hdparm/Makefile b/external/subpack/utils/hdparm/Makefile
new file mode 100644
index 0000000..f2fa28a
--- /dev/null
+++ b/external/subpack/utils/hdparm/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2006-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hdparm
+PKG_VERSION:=9.60
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_HASH:=8397739c73e44d5ab96c4aef28fa9c0147276d53a1b5657ce04c4565cf6635cc
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=BSD-Style Open Source License
+PKG_LICENSE_FILES:=LICENSE.TXT
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/hdparm
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Disc
+ TITLE:=Hard disk drive configuration utilitity
+ URL:=https://sourceforge.net/projects/hdparm/
+endef
+
+define Package/hdparm/description
+ get/set SATA/IDE device parameters
+endef
+
+define Package/hdparm/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/hdparm $(1)/sbin
+endef
+
+$(eval $(call BuildPackage,hdparm))
diff --git a/external/subpack/utils/hdparm/patches/010-cflags.patch b/external/subpack/utils/hdparm/patches/010-cflags.patch
new file mode 100644
index 0000000..f8b59b8
--- /dev/null
+++ b/external/subpack/utils/hdparm/patches/010-cflags.patch
@@ -0,0 +1,11 @@
+--- a/Makefile
++++ b/Makefile
+@@ -13,7 +13,7 @@ oldmandir = $(manprefix)/man
+ CC ?= gcc
+ STRIP ?= strip
+
+-CFLAGS := -O2 -W -Wall -Wbad-function-cast -Wcast-align -Wpointer-arith -Wcast-qual -Wshadow -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -fkeep-inline-functions -Wwrite-strings -Waggregate-return -Wnested-externs -Wtrigraphs $(CFLAGS)
++CFLAGS ?= -O2 -W -Wall -Wbad-function-cast -Wcast-align -Wpointer-arith -Wcast-qual -Wshadow -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -fkeep-inline-functions -Wwrite-strings -Waggregate-return -Wnested-externs -Wtrigraphs $(CFLAGS)
+
+ INSTALL = install
+ INSTALL_DATA = $(INSTALL) -m 644
diff --git a/external/subpack/utils/hfsprogs/Makefile b/external/subpack/utils/hfsprogs/Makefile
new file mode 100644
index 0000000..d4e25ca
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/Makefile
@@ -0,0 +1,80 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hfsprogs
+PKG_VERSION:=332.25
+PKG_RELEASE:=4
+
+PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.gz
+PKG_SOURCE_URL:=http://archive.ubuntu.com/ubuntu/pool/universe/h/$(PKG_NAME)
+PKG_HASH:=74c9aeca899ed7f4bf155c65fc45bf0f250c0f6d57360ea953b1d536d9aa45e6
+PKG_BUILD_DIR:=$(BUILD_DIR)/diskdev_cmds-$(PKG_VERSION)
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=APSL-2.0
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/hfsprogs/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Filesystem
+ DEPENDS:=+libopenssl +USE_GLIBC:libbsd
+endef
+
+define Package/hfsfsck
+ $(call Package/hfsprogs/Default)
+ TITLE:=fsck (fsck.hfs) utility from hfsprogs
+endef
+
+define Package/mkhfs
+ $(call Package/hfsprogs/Default)
+ TITLE:=mkfs (mkfs.hfs) utility from hfsprogs
+endef
+
+define Package/hfsfsck/description
+ Utilities to create and check HFS/HFS+ filesystems.
+ (fsck.hfs and fsck.hfsplus for checking integrity of HFS/HFS+ volumes)
+endef
+
+define Package/mkhfs/description
+ Utilities to create and check HFS/HFS+ filesystems.
+ (mkfs.hfs and mkfs.hfsplus for creating HFS/HFS+ volumes)
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ -f Makefile.lnx \
+ $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS+="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS) -I$(PKG_BUILD_DIR)/include -DDEBUG_BUILD=0 -D_FILE_OFFSET_BITS=64 -D LINUX=1 -D BSD=1" \
+ LDFLAGS+="$(TARGET_LDFLAGS) $(if $(CONFIG_USE_GLIBC),-lbsd)" \
+ all
+endef
+
+define Package/hfsfsck/install
+ $(INSTALL_DIR) $(1)/lib/functions/fsck
+ $(INSTALL_DATA) ./files/hfsfsck.sh $(1)/lib/functions/fsck/
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/fsck_hfs.tproj/fsck_hfs $(1)/usr/sbin/fsck.hfsplus
+ (cd $(1)/usr/sbin; ln -sf fsck.hfsplus fsck.hfs;)
+endef
+
+define Package/mkhfs/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/newfs_hfs.tproj/newfs_hfs $(1)/usr/sbin/mkfs.hfsplus
+ (cd $(1)/usr/sbin; ln -sf mkfs.hfsplus mkfs.hfs;)
+endef
+
+$(eval $(call BuildPackage,hfsfsck))
+$(eval $(call BuildPackage,mkhfs))
diff --git a/external/subpack/utils/hfsprogs/files/hfsfsck.sh b/external/subpack/utils/hfsprogs/files/hfsfsck.sh
new file mode 100644
index 0000000..8bcd2c1
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/files/hfsfsck.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+# Copyright 2015 OpenWrt.org
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+fsck_hfsfsck() {
+ hfsfsck "$device" 2>&1 | logger -t "fstab: hfsfsck ($device)"
+ local status="$?"
+ case "$status" in
+ 0) ;; #success
+ 4) reboot;;
+ 8) echo "hfsfsck ($device): Warning! Uncorrected errors."| logger -t fstab
+ return 1
+ ;;
+ *) echo "hfsfsck ($device): Error $status. Check not complete."| logger -t fstab;;
+ esac
+ return 0
+}
+
+fsck_hfs() {
+ fsck_hfsfsck "$@"
+}
+
+fsck_hfsplus() {
+ fsck_hfsfsck "$@"
+}
+
+append libmount_known_fsck "hfs"
+append libmount_known_fsck "hfsplus"
diff --git a/external/subpack/utils/hfsprogs/patches/0001-Create-short-Makefiles-for-Debian.patch b/external/subpack/utils/hfsprogs/patches/0001-Create-short-Makefiles-for-Debian.patch
new file mode 100644
index 0000000..a00eec6
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0001-Create-short-Makefiles-for-Debian.patch
@@ -0,0 +1,81 @@
+From: =?UTF-8?q?Rog=C3=A9rio=20Brito?= <rbrito@ime.usp.br>
+Date: Thu, 24 Oct 2013 01:11:21 -0200
+Subject: Create short Makefiles for Debian
+
+Create short Makefiles for compiling just the necessary parts for a
+Debian-based (and possibly other distributions) HFS+ filesystem
+utilities.
+---
+ Makefile.lnx | 8 ++++++++
+ fsck_hfs.tproj/Makefile.lnx | 16 ++++++++++++++++
+ fsck_hfs.tproj/dfalib/Makefile.lnx | 15 +++++++++++++++
+ newfs_hfs.tproj/Makefile.lnx | 12 ++++++++++++
+ 4 files changed, 51 insertions(+)
+ create mode 100644 Makefile.lnx
+ create mode 100644 fsck_hfs.tproj/Makefile.lnx
+ create mode 100644 fsck_hfs.tproj/dfalib/Makefile.lnx
+ create mode 100644 newfs_hfs.tproj/Makefile.lnx
+
+--- /dev/null
++++ b/Makefile.lnx
+@@ -0,0 +1,8 @@
++CC := gcc
++CFLAGS += -I$(PWD)/include -DDEBUG_BUILD=0 -D_FILE_OFFSET_BITS=64 -D LINUX=1 -D BSD=1
++SUBDIRS := newfs_hfs.tproj fsck_hfs.tproj
++
++all clean:
++ for d in $(SUBDIRS); do $(MAKE) -C $$d -f Makefile.lnx $@; done
++
++export CC CFLAGS
+--- /dev/null
++++ b/fsck_hfs.tproj/Makefile.lnx
+@@ -0,0 +1,16 @@
++CFILES = fsck_hfs.c strings.c utilities.c cache.c fsck_debug.c
++OFILES = $(CFILES:.c=.o)
++
++all: fsck_hfs
++
++fsck_hfs: $(OFILES) dfalib/libdfa.a
++ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OFILES) dfalib/libdfa.a
++
++dfalib/libdfa.a: FORCE
++ $(MAKE) -C dfalib -f Makefile.lnx CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" libdfa.a
++
++clean:
++ $(RM) fsck_hfs $(OFILES)
++ $(MAKE) -C dfalib -f Makefile.lnx clean
++
++.PHONY : FORCE clean
+--- /dev/null
++++ b/fsck_hfs.tproj/dfalib/Makefile.lnx
+@@ -0,0 +1,15 @@
++CFILES = hfs_endian.c BlockCache.c\
++ BTree.c BTreeAllocate.c BTreeMiscOps.c \
++ BTreeNodeOps.c BTreeScanner.c BTreeTreeOps.c\
++ CatalogCheck.c HardLinkCheck.c\
++ SBTree.c SControl.c SVerify1.c SVerify2.c\
++ SRepair.c SRebuildCatalogBTree.c\
++ SUtils.c SKeyCompare.c SDevice.c SExtents.c SAllocate.c\
++ SCatalog.c SStubs.c VolumeBitmapCheck.c
++OFILES = $(CFILES:.c=.o)
++
++libdfa.a: $(OFILES)
++ $(AR) rc $@ $?
++
++clean:
++ $(RM) $(OFILES) libdfa.a
+--- /dev/null
++++ b/newfs_hfs.tproj/Makefile.lnx
+@@ -0,0 +1,12 @@
++CFILES = hfs_endian.c makehfs.c newfs_hfs.c
++OFILES = $(CFILES:.c=.o)
++
++all: newfs_hfs
++
++newfs_hfs: $(OFILES)
++ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OFILES) -lcrypto
++
++clean:
++ $(RM) newfs_hfs $(OFILES)
++
++.PHONY : FORCE clean
diff --git a/external/subpack/utils/hfsprogs/patches/0002-Add-exclude-Darwin-specific-code.patch b/external/subpack/utils/hfsprogs/patches/0002-Add-exclude-Darwin-specific-code.patch
new file mode 100644
index 0000000..e65cb76
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0002-Add-exclude-Darwin-specific-code.patch
@@ -0,0 +1,1364 @@
+From: =?UTF-8?q?Rog=C3=A9rio=20Brito?= <rbrito@ime.usp.br>
+Date: Thu, 24 Oct 2013 01:11:21 -0200
+Subject: Add/exclude Darwin-specific code
+
+Modify some of the files so that they can be compiled without the
+Apple owned frameworks in a Debian system (and possibly others).
+---
+ fsck_hfs.tproj/cache.c | 4 ++
+ fsck_hfs.tproj/dfalib/BTree.c | 2 +
+ fsck_hfs.tproj/dfalib/BlockCache.c | 3 +
+ fsck_hfs.tproj/dfalib/SBTree.c | 2 +
+ fsck_hfs.tproj/dfalib/SDevice.c | 92 ++++++++++++++++++++---------
+ fsck_hfs.tproj/dfalib/SKeyCompare.c | 2 +
+ fsck_hfs.tproj/dfalib/SRepair.c | 2 +
+ fsck_hfs.tproj/dfalib/SRuntime.h | 7 ++-
+ fsck_hfs.tproj/dfalib/SUtils.c | 5 +-
+ fsck_hfs.tproj/dfalib/SVerify2.c | 7 +++
+ fsck_hfs.tproj/dfalib/Scavenger.h | 11 +++-
+ fsck_hfs.tproj/dfalib/hfs_endian.c | 4 ++
+ fsck_hfs.tproj/dfalib/hfs_endian.h | 7 ++-
+ fsck_hfs.tproj/fsck_hfs.c | 61 +++++++++++++++----
+ fsck_hfs.tproj/utilities.c | 8 ++-
+ include/missing.h | 115 ++++++++++++++++++++++++++++++++++++
+ newfs_hfs.tproj/hfs_endian.c | 5 ++
+ newfs_hfs.tproj/hfs_endian.h | 5 ++
+ newfs_hfs.tproj/makehfs.c | 72 ++++++++++++++++------
+ newfs_hfs.tproj/newfs_hfs.c | 74 ++++++++++++++++++++---
+ newfs_hfs.tproj/newfs_hfs.h | 26 ++++----
+ 21 files changed, 429 insertions(+), 85 deletions(-)
+ create mode 100644 include/missing.h
+
+--- a/fsck_hfs.tproj/cache.c
++++ b/fsck_hfs.tproj/cache.c
+@@ -26,7 +26,11 @@
+ #include <stdlib.h>
+ #include <sys/mman.h>
+ #include <sys/stat.h>
++#if LINUX
++#include "missing.h"
++#else
+ #include <sys/types.h>
++#endif /* __LINUX__ */
+ #include <sys/uio.h>
+ #include <unistd.h>
+ #include <string.h>
+--- a/fsck_hfs.tproj/dfalib/BTree.c
++++ b/fsck_hfs.tproj/dfalib/BTree.c
+@@ -1705,7 +1705,9 @@ OSStatus BTGetInformation (SFCB *fil
+ UInt16 version,
+ BTreeInfoRec *info )
+ {
++#if !LINUX
+ #pragma unused (version)
++#endif
+
+ BTreeControlBlockPtr btreePtr;
+
+--- a/fsck_hfs.tproj/dfalib/BlockCache.c
++++ b/fsck_hfs.tproj/dfalib/BlockCache.c
+@@ -20,6 +20,9 @@
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
++#if LINUX
++#include "missing.h"
++#endif
+ #include "SRuntime.h"
+ #include "Scavenger.h"
+ #include "../cache.h"
+--- a/fsck_hfs.tproj/dfalib/SBTree.c
++++ b/fsck_hfs.tproj/dfalib/SBTree.c
+@@ -322,7 +322,9 @@ ErrorExit:
+ OSStatus
+ SetEndOfForkProc ( SFCB *filePtr, FSSize minEOF, FSSize maxEOF )
+ {
++#if !LINUX
+ #pragma unused (maxEOF)
++#endif
+
+ OSStatus result;
+ UInt32 actualSectorsAdded;
+--- a/fsck_hfs.tproj/dfalib/SDevice.c
++++ b/fsck_hfs.tproj/dfalib/SDevice.c
+@@ -2,7 +2,7 @@
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+- *
++ *
+ * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
+ * Reserved. This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+@@ -10,7 +10,7 @@
+ * except in compliance with the License. Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+- *
++ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+@@ -18,7 +18,7 @@
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+- *
++ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+ #include "SRuntime.h"
+@@ -28,33 +28,71 @@
+ #include <unistd.h>
+ #include <errno.h>
+ #include <sys/ioctl.h>
+-
++#if LINUX
++#include <fcntl.h>
++#include <sys/stat.h>
++#else
+ #include <IOKit/storage/IOMediaBSDClient.h>
+-
++#endif /* LINUX */
+ #else
+-
+ #include <Files.h>
+ #include <Device.h>
+ #include <Disks.h>
+
+ #endif
+
+-
+ OSErr GetDeviceSize(int driveRefNum, UInt64 *numBlocks, UInt32 *blockSize)
+ {
+ #if BSD
+ UInt64 devBlockCount = 0;
+ int devBlockSize = 0;
++#if LINUX
++ struct stat stbuf;
++
++ devBlockSize = 512;
+
++#ifndef BLKGETSIZE
++#define BLKGETSIZE _IO(0x12,96)
++#endif
++#ifndef BLKGETSIZE64
++#define BLKGETSIZE64 _IOR(0x12,114,size_t)
++#endif
++ if (fstat(driveRefNum, &stbuf) < 0){
++ printf("Error: %s\n", strerror(errno));
++ return(-1);
++ }
++
++ if (S_ISREG(stbuf.st_mode)) {
++ devBlockCount = stbuf.st_size / 512;
++ }
++ else if (S_ISBLK(stbuf.st_mode)) {
++ unsigned long size;
++ u_int64_t size64;
++ if (!ioctl(driveRefNum, BLKGETSIZE64, &size64))
++ devBlockCount = size64 / 512;
++ else if (!ioctl(driveRefNum, BLKGETSIZE, &size))
++ devBlockCount = size;
++ else{
++ printf("Error: %s\n", strerror(errno));
++ return(-1);
++ }
++
++ }
++ else{
++ printf("Device is not a block device");
++ return(-1);
++ }
++#elif BSD
+ if (ioctl(driveRefNum, DKIOCGETBLOCKCOUNT, &devBlockCount) < 0) {
+ printf("ioctl(DKIOCGETBLOCKCOUNT) for fd %d: %s\n", driveRefNum, strerror(errno));
+ return (-1);
+ }
+-
++
+ if (ioctl(driveRefNum, DKIOCGETBLOCKSIZE, &devBlockSize) < 0) {
+ printf("ioctl(DKIOCGETBLOCKSIZE) for fd %d: %s\n", driveRefNum, strerror(errno));
+ return (-1);
+ }
++#endif /* BSD */
+
+ if (devBlockSize != 512) {
+ *numBlocks = (devBlockCount * (UInt64)devBlockSize) / 512;
+@@ -70,24 +108,24 @@ OSErr GetDeviceSize(int driveRefNum, UIn
+ {
+ /* return format list status code */
+ kFmtLstCode = 6,
+-
++
+ /* reference number of .SONY driver */
+ kSonyRefNum = 0xfffb,
+-
++
+ /* values returned by DriveStatus in DrvSts.twoSideFmt */
+ kSingleSided = 0,
+ kDoubleSided = -1,
+ kSingleSidedSize = 800, /* 400K */
+ kDoubleSidedSize = 1600, /* 800K */
+-
++
+ /* values in DrvQEl.qType */
+ kWordDrvSiz = 0,
+ kLongDrvSiz = 1,
+-
++
+ /* more than enough formatListRecords */
+ kMaxFormatListRecs = 16
+ };
+-
++
+ ParamBlockRec pb;
+ FormatListRec formatListRecords[kMaxFormatListRecs];
+ DrvSts status;
+@@ -95,22 +133,22 @@ OSErr GetDeviceSize(int driveRefNum, UIn
+ OSErr result;
+ unsigned long blocks = 0;
+
+-
++
+ /* Attempt to get the drive's format list. */
+ /* (see the Technical Note "What Your Sony Drives For You") */
+-
++
+ pb.cntrlParam.ioVRefNum = driveQElementPtr->dQDrive;
+ pb.cntrlParam.ioCRefNum = driveQElementPtr->dQRefNum;
+ pb.cntrlParam.csCode = kFmtLstCode;
+ pb.cntrlParam.csParam[0] = kMaxFormatListRecs;
+ *(long *)&pb.cntrlParam.csParam[1] = (long)&formatListRecords[0];
+-
++
+ result = PBStatusSync(&pb);
+-
++
+ if ( result == noErr )
+ {
+ /* The drive supports ReturnFormatList status call. */
+-
++
+ /* Get the current disk's size. */
+ for( formatListRecIndex = 0;
+ formatListRecIndex < pb.cntrlParam.csParam[0];
+@@ -131,7 +169,7 @@ OSErr GetDeviceSize(int driveRefNum, UIn
+ else if ( driveQElementPtr->dQRefNum == (short)kSonyRefNum )
+ {
+ /* The drive is a non-SuperDrive floppy which only supports 400K and 800K disks */
+-
++
+ result = DriveStatus(driveQElementPtr->dQDrive, &status);
+ if ( result == noErr )
+ {
+@@ -140,11 +178,11 @@ OSErr GetDeviceSize(int driveRefNum, UIn
+ case kSingleSided:
+ blocks = kSingleSidedSize;
+ break;
+-
++
+ case kDoubleSided:
+ blocks = kDoubleSidedSize;
+ break;
+-
++
+ default: // This should never happen
+ result = paramErr;
+ break;
+@@ -155,20 +193,20 @@ OSErr GetDeviceSize(int driveRefNum, UIn
+ {
+ /* The drive is not a floppy and it doesn't support ReturnFormatList */
+ /* so use the dQDrvSz field(s) */
+-
++
+ result = noErr; /* reset result */
+-
++
+ switch ( driveQElementPtr->qType )
+ {
+ case kWordDrvSiz:
+ blocks = driveQElementPtr->dQDrvSz;
+ break;
+-
++
+ case kLongDrvSiz:
+ blocks = ((unsigned long)driveQElementPtr->dQDrvSz2 << 16) +
+ driveQElementPtr->dQDrvSz;
+ break;
+-
++
+ default: // This should never happen
+ result = paramErr;
+ break;
+@@ -177,7 +215,7 @@ OSErr GetDeviceSize(int driveRefNum, UIn
+
+ *numBlocks = blocks;
+ *blockSize = 512;
+-
++
+ return( result );
+ #endif
+ }
+@@ -188,7 +226,7 @@ OSErr DeviceRead(int device, int drive,
+ #if BSD
+ off_t seek_off;
+ ssize_t nbytes;
+-
++
+ *actBytes = 0;
+
+ seek_off = lseek(device, offset, SEEK_SET);
+--- a/fsck_hfs.tproj/dfalib/SKeyCompare.c
++++ b/fsck_hfs.tproj/dfalib/SKeyCompare.c
+@@ -454,7 +454,9 @@ SInt32 CompareExtentKeysPlus( const HFSP
+ * The name portion of the key is compared using a 16-bit binary comparison.
+ * This is called from the b-tree code.
+ */
++#if !LINUX
+ __private_extern__
++#endif
+ SInt32
+ CompareAttributeKeys(const AttributeKey *searchKey, const AttributeKey *trialKey)
+ {
+--- a/fsck_hfs.tproj/dfalib/SRepair.c
++++ b/fsck_hfs.tproj/dfalib/SRepair.c
+@@ -1617,7 +1617,9 @@ Output:
+
+ static OSErr FixWrapperExtents( SGlobPtr GPtr, RepairOrderPtr p )
+ {
++#if !LINUX
+ #pragma unused (p)
++#endif
+
+ OSErr err;
+ HFSMasterDirectoryBlock *mdb;
+--- a/fsck_hfs.tproj/dfalib/SRuntime.h
++++ b/fsck_hfs.tproj/dfalib/SRuntime.h
+@@ -27,8 +27,11 @@
+ #define __SRUNTIME__
+
+ #if BSD
+-
++#if LINUX
++#include "missing.h"
++#else
+ #include <sys/types.h>
++#endif
+ #include <stdlib.h>
+ #include <string.h>
+ #include <stdio.h>
+@@ -91,10 +94,12 @@ typedef const unsigned char * ConstStr25
+
+ typedef u_int32_t HFSCatalogNodeID;
+
++#if !LINUX
+ enum {
+ false = 0,
+ true = 1
+ };
++#endif
+
+ /* OS error codes */
+ enum {
+--- a/fsck_hfs.tproj/dfalib/SUtils.c
++++ b/fsck_hfs.tproj/dfalib/SUtils.c
+@@ -380,7 +380,8 @@ void InvalidateCalculatedVolumeBitMap( S
+ // GPtr->realVCB Real in-memory vcb
+ //------------------------------------------------------------------------------
+
+-#if !BSD
++#if BSD
++#if !LINUX
+ OSErr GetVolumeFeatures( SGlobPtr GPtr )
+ {
+ OSErr err;
+@@ -418,7 +419,7 @@ OSErr GetVolumeFeatures( SGlobPtr GPtr )
+ return( noErr );
+ }
+ #endif
+-
++#endif
+
+
+ /*-------------------------------------------------------------------------------
+--- a/fsck_hfs.tproj/dfalib/SVerify2.c
++++ b/fsck_hfs.tproj/dfalib/SVerify2.c
+@@ -32,7 +32,9 @@
+ */
+
+ #include <sys/ioctl.h>
++#if !LINUX
+ #include <sys/disk.h>
++#endif
+
+ #include "BTree.h"
+ #include "BTreePrivate.h"
+@@ -1354,8 +1356,13 @@ OSErr CompareVolumeHeader( SGlobPtr GPtr
+ * clump size for read-only media is irrelevant we skip the clump size
+ * check to avoid non useful warnings.
+ */
++#if LINUX
++ // FIXME
++ isWriteable = 1;
++#else
+ isWriteable = 0;
+ ioctl( GPtr->DrvNum, DKIOCISWRITABLE, &isWriteable );
++#endif
+ if ( isWriteable != 0 &&
+ volumeHeader->catalogFile.clumpSize != vcb->vcbCatalogFile->fcbClumpSize ) {
+ PrintError(GPtr, E_InvalidClumpSize, 0);
+--- a/fsck_hfs.tproj/dfalib/Scavenger.h
++++ b/fsck_hfs.tproj/dfalib/Scavenger.h
+@@ -37,11 +37,16 @@
+ #include "../fsck_debug.h"
+
+ #include <assert.h>
++#if LINUX
++#define XATTR_MAXNAMELEN 127
++#include <limits.h>
++#else
+ #include <sys/xattr.h>
+ #include <sys/acl.h>
+ #include <sys/kauth.h>
+-#include <sys/errno.h>
+ #include <sys/syslimits.h>
++#endif
++#include <sys/errno.h>
+
+ #ifdef __cplusplus
+ extern "C" {
+@@ -1465,4 +1470,8 @@ extern int AllocateContigBitmapBits (SV
+ };
+ #endif
+
++/* #if LINUX
++#undef XATTR_MAXNAMELEN
++#endif */
++
+ #endif /* __SCAVENGER__ */
+--- a/fsck_hfs.tproj/dfalib/hfs_endian.c
++++ b/fsck_hfs.tproj/dfalib/hfs_endian.c
+@@ -31,7 +31,11 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+
++#if LINUX
++#include "missing.h"
++#else
+ #include <architecture/byte_order.h>
++#endif
+ #include <hfs/hfs_format.h>
+
+ #include "Scavenger.h"
+--- a/fsck_hfs.tproj/dfalib/hfs_endian.h
++++ b/fsck_hfs.tproj/dfalib/hfs_endian.h
+@@ -27,9 +27,14 @@
+ *
+ * This file prototypes endian swapping routines for the HFS/HFS Plus
+ * volume format.
+- */
++*/
+ #include <hfs/hfs_format.h>
++#if LINUX
++#include <endian.h>
++#include <byteswap.h>
++#else
+ #include <architecture/byte_order.h>
++#endif
+ #include "SRuntime.h"
+
+ /*********************/
+--- a/fsck_hfs.tproj/fsck_hfs.c
++++ b/fsck_hfs.tproj/fsck_hfs.c
+@@ -24,10 +24,14 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <sys/param.h>
++#if !LINUX
+ #include <sys/ucred.h>
++#endif
+ #include <sys/mount.h>
+ #include <sys/ioctl.h>
++#if !LINUX
+ #include <sys/disk.h>
++#endif
+
+ #include <hfs/hfs_mount.h>
+
+@@ -195,8 +199,12 @@ main(argc, argv)
+ if (guiControl)
+ debug = 0; /* debugging is for command line only */
+
++#if LINUX
++// FIXME
++#else
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ (void)signal(SIGINT, catch);
++#endif
+
+ if (argc < 1) {
+ (void) fprintf(stderr, "%s: missing special-device\n", progname);
+@@ -218,7 +226,9 @@ checkfilesys(char * filesys)
+ int chkLev, repLev, logLev;
+ int blockDevice_fd, canWrite;
+ char *unraw, *mntonname;
++#if !LINUX
+ struct statfs *fsinfo;
++#endif
+ int fs_fd=-1; // fd to the root-dir of the fs we're checking (only w/lfag == 1)
+
+ flags = 0;
+@@ -227,7 +237,9 @@ checkfilesys(char * filesys)
+ canWrite = 0;
+ unraw = NULL;
+ mntonname = NULL;
+-
++#if LINUX
++ // FIXME
++#else
+ if (lflag) {
+ result = getmntinfo(&fsinfo, MNT_NOWAIT);
+
+@@ -257,10 +269,10 @@ checkfilesys(char * filesys)
+ }
+ }
+ }
+-
++#endif
+ if (debug && preen)
+ pwarn("starting\n");
+-
++
+ if (setup( filesys, &blockDevice_fd, &canWrite ) == 0) {
+ if (preen)
+ pfatal("CAN'T CHECK FILE SYSTEM.");
+@@ -278,7 +290,7 @@ checkfilesys(char * filesys)
+ repLev = kMajorRepairs;
+ logLev = kVerboseLog;
+
+- if (yflag)
++ if (yflag)
+ repLev = kMajorRepairs;
+
+ if (quick) {
+@@ -298,16 +310,16 @@ checkfilesys(char * filesys)
+
+ if (nflag)
+ repLev = kNeverRepair;
+-
++
+ if ( rebuildCatalogBtree ) {
+ chkLev = kPartialCheck;
+ repLev = kForceRepairs; // this will force rebuild of catalog B-Tree file
+ }
+-
++
+ /*
+ * go check HFS volume...
+ */
+- result = CheckHFS( fsreadfd, fswritefd, chkLev, repLev, logLev,
++ result = CheckHFS( fsreadfd, fswritefd, chkLev, repLev, logLev,
+ guiControl, lostAndFoundMode, canWrite, &fsmodified );
+ if (!hotroot) {
+ ckfini(1);
+@@ -330,6 +342,9 @@ checkfilesys(char * filesys)
+ }
+ }
+ } else {
++#if LINUX
++ // FIXME
++#else
+ struct statfs stfs_buf;
+ /*
+ * Check to see if root is mounted read-write.
+@@ -339,19 +354,25 @@ checkfilesys(char * filesys)
+ else
+ flags = 0;
+ ckfini(flags & MNT_RDONLY);
++#endif
+ }
+
+ /* XXX free any allocated memory here */
+
+ if (hotroot && fsmodified) {
++#if !LINUX
+ struct hfs_mount_args args;
++#endif
+ /*
+ * We modified the root. Do a mount update on
+ * it, unless it is read-write, so we can continue.
+ */
+ if (!preen)
+ printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
+- if (flags & MNT_RDONLY) {
++#if LINUX
++ // FIXME
++#else
++ if (flags & MNT_RDONLY) {
+ bzero(&args, sizeof(args));
+ flags |= MNT_UPDATE | MNT_RELOAD;
+ if (mount("hfs", "/", flags, &args) == 0) {
+@@ -359,6 +380,7 @@ checkfilesys(char * filesys)
+ goto ExitThisRoutine;
+ }
+ }
++#endif
+ if (!preen)
+ printf("\n***** REBOOT NOW *****\n");
+ sync();
+@@ -367,7 +389,7 @@ checkfilesys(char * filesys)
+ }
+
+ result = (result == 0) ? 0 : EEXIT;
+-
++
+ ExitThisRoutine:
+ if (lflag) {
+ fcntl(fs_fd, F_THAW_FS, NULL);
+@@ -401,16 +423,18 @@ setup( char *dev, int *blockDevice_fdPtr
+ fswritefd = -1;
+ *blockDevice_fdPtr = -1;
+ *canWritePtr = 0;
+-
++
+ if (stat(dev, &statb) < 0) {
+ printf("Can't stat %s: %s\n", dev, strerror(errno));
+ return (0);
+ }
++#if !LINUX
+ if ((statb.st_mode & S_IFMT) != S_IFCHR) {
+ pfatal("%s is not a character device", dev);
+ if (reply("CONTINUE") == 0)
+ return (0);
+ }
++#endif
+ if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
+ printf("Can't open %s: %s\n", dev, strerror(errno));
+ return (0);
+@@ -419,7 +443,7 @@ setup( char *dev, int *blockDevice_fdPtr
+ /* attempt to get write access to the block device and if not check if volume is */
+ /* mounted read-only. */
+ getWriteAccess( dev, blockDevice_fdPtr, canWritePtr );
+-
++
+ if (preen == 0 && !guiControl)
+ printf("** %s", dev);
+ if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) {
+@@ -433,10 +457,14 @@ setup( char *dev, int *blockDevice_fdPtr
+ printf("\n");
+
+ /* Get device block size to initialize cache */
++#if LINUX
++ devBlockSize = 512;
++#else
+ if (ioctl(fsreadfd, DKIOCGETBLOCKSIZE, &devBlockSize) < 0) {
+ pfatal ("Can't get device block size\n");
+ return (0);
+ }
++#endif
+
+ /* calculate the cache block size and total blocks */
+ if (CalculateCacheSize(userCacheSize, &cacheBlockSize, &cacheTotalBlocks, debug) != 0) {
+@@ -463,11 +491,15 @@ setup( char *dev, int *blockDevice_fdPtr
+
+ static void getWriteAccess( char *dev, int *blockDevice_fdPtr, int *canWritePtr )
+ {
++#if !LINUX
+ int i;
+ int myMountsCount;
++#endif
+ void * myPtr;
+ char * myCharPtr;
++#if !LINUX
+ struct statfs * myBufPtr;
++#endif
+ void * myNamePtr;
+
+ myPtr = NULL;
+@@ -490,6 +522,9 @@ static void getWriteAccess( char *dev, i
+ }
+
+ // get count of mounts then get the info for each
++#if LINUX
++ // FIXME
++#else
+ myMountsCount = getfsstat( NULL, 0, MNT_NOWAIT );
+ if ( myMountsCount < 0 )
+ goto ExitThisRoutine;
+@@ -513,8 +548,8 @@ static void getWriteAccess( char *dev, i
+ }
+ myBufPtr++;
+ }
+- *canWritePtr = 1; // single user will get us here, f_mntfromname is not /dev/diskXXXX
+-
++#endif
++ *canWritePtr = 1; // single user will get us here, f_mntfromname is not /dev/diskXXXX
+ ExitThisRoutine:
+ if ( myPtr != NULL )
+ free( myPtr );
+--- a/fsck_hfs.tproj/utilities.c
++++ b/fsck_hfs.tproj/utilities.c
+@@ -183,12 +183,14 @@ retry:
+ printf("Can't stat %s\n", raw);
+ return (origname);
+ }
++#if !LINUX
+ if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
+ return (raw);
+ } else {
+ printf("%s is not a character device\n", raw);
+ return (origname);
+ }
++#endif
+ } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
+ newname = unrawname(newname);
+ retried++;
+@@ -214,7 +216,11 @@ rawname(char *name)
+ *dp = 0;
+ (void)strcpy(rawbuf, name);
+ *dp = '/';
+- (void)strcat(rawbuf, "/r");
++#if LINUX
++ (void)strcat(rawbuf, "/");
++#else
++ (void)strcat(rawbuf,"/r");
++#endif
+ (void)strcat(rawbuf, &dp[1]);
+
+ return (rawbuf);
+--- /dev/null
++++ b/include/missing.h
+@@ -0,0 +1,114 @@
++#ifndef _MISSING_H_
++#define _MISSING_H_
++
++#include <endian.h>
++#include <byteswap.h>
++#include <errno.h>
++#include <stdint.h>
++#include <string.h>
++
++#define MAXBSIZE (256 * 4096)
++
++#ifndef true
++#define true 1
++#endif
++#ifndef false
++#define false 0
++#endif
++
++/* Mac types */
++
++/* 8 Bit */
++#ifndef UInt8
++#define UInt8 uint8_t
++#endif
++#ifndef u_int8_t
++#define u_int8_t UInt8
++#endif
++#ifndef SInt8
++#define SInt8 int8_t
++#endif
++
++/* 16 Bit */
++#ifndef UInt16
++#define UInt16 uint16_t
++#endif
++#ifndef u_int16_t
++#define u_int16_t UInt16
++#endif
++#ifndef SInt16
++#define SInt16 int16_t
++#endif
++
++/* 32 Bit */
++#ifndef UInt32
++#define UInt32 uint32_t
++#endif
++#ifndef u_int32_t
++#define u_int32_t UInt32
++#endif
++#ifndef SInt32
++#define SInt32 int32_t
++#endif
++
++/* 64 Bit */
++#ifndef UInt64
++#define UInt64 uint64_t
++#endif
++#ifndef u_int64_t
++#define u_int64_t UInt64
++#endif
++#ifndef SInt64
++#define SInt64 int64_t
++#endif
++
++#define UniChar u_int16_t
++#define Boolean u_int8_t
++
++#define UF_NODUMP 0x00000001
++
++/* syslimits.h */
++#define NAME_MAX 255
++
++/* Byteswap stuff */
++#define NXSwapHostLongToBig(x) cpu_to_be64(x)
++#define NXSwapBigShortToHost(x) be16_to_cpu(x)
++#define OSSwapBigToHostInt16(x) be16_to_cpu(x)
++#define NXSwapBigLongToHost(x) be32_to_cpu(x)
++#define OSSwapBigToHostInt32(x) be32_to_cpu(x)
++#define NXSwapBigLongLongToHost(x) be64_to_cpu(x)
++#define OSSwapBigToHostInt64(x) be64_to_cpu(x)
++
++#if __BYTE_ORDER == __LITTLE_ENDIAN
++/* Big Endian Swaps */
++#ifndef be16_to_cpu
++#define be16_to_cpu(x) bswap_16(x)
++#endif
++#ifndef be32_to_cpu
++#define be32_to_cpu(x) bswap_32(x)
++#endif
++#ifndef be64_to_cpu
++#define be64_to_cpu(x) bswap_64(x)
++#endif
++#ifndef cpu_to_be64
++#define cpu_to_be64(x) bswap_64(x)
++#endif
++#elif __BYTE_ORDER == __BIG_ENDIAN
++/* Big endian doesn't swap */
++#ifndef be16_to_cpu
++#define be16_to_cpu(x) (x)
++#endif
++#ifndef be32_to_cpu
++#define be32_to_cpu(x) (x)
++#endif
++#ifndef be64_to_cpu
++#define be64_to_cpu(x) (x)
++#endif
++#ifndef cpu_to_be64
++#define cpu_to_be64(x) (x)
++#endif
++#endif
++
++#define KAUTH_FILESEC_XATTR "com.apple.system.Security"
++
++#endif
+--- a/newfs_hfs.tproj/hfs_endian.c
++++ b/newfs_hfs.tproj/hfs_endian.c
+@@ -30,7 +30,12 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+
++#if LINUX
++#include "missing.h"
++#else
+ #include <architecture/byte_order.h>
++#endif
++
+ #include <hfs/hfs_format.h>
+
+ #include "hfs_endian.h"
+--- a/newfs_hfs.tproj/hfs_endian.h
++++ b/newfs_hfs.tproj/hfs_endian.h
+@@ -29,7 +29,12 @@
+ * volume format.
+ */
+ #include <hfs/hfs_format.h>
++#if LINUX
++#include <endian.h>
++#include <byteswap.h>
++#else
+ #include <architecture/byte_order.h>
++#endif
+
+ /*********************/
+ /* BIG ENDIAN Macros */
+--- a/newfs_hfs.tproj/makehfs.c
++++ b/newfs_hfs.tproj/makehfs.c
+@@ -31,10 +31,16 @@
+ #include <sys/param.h>
+ #include <sys/types.h>
+ #include <sys/time.h>
++#if LINUX
++#include <time.h>
++#include "missing.h"
++#endif
+ #include <sys/errno.h>
+ #include <sys/stat.h>
+ #include <sys/sysctl.h>
++#if !LINUX
+ #include <sys/vmmeter.h>
++#endif
+
+ #include <err.h>
+ #include <errno.h>
+@@ -47,13 +53,14 @@
+
+ #include <openssl/sha.h>
+
++#if !LINUX
+ #include <architecture/byte_order.h>
+
+ #include <CoreFoundation/CFString.h>
+ #include <CoreFoundation/CFStringEncodingExt.h>
+
+ extern Boolean _CFStringGetFileSystemRepresentation(CFStringRef string, UInt8 *buffer, CFIndex maxBufLen);
+-
++#endif
+
+ #include <hfs/hfs_format.h>
+ #include <hfs/hfs_mount.h>
+@@ -129,7 +136,9 @@ static UInt32 Largest __P((UInt32 a, UIn
+ static void MarkBitInAllocationBuffer __P((HFSPlusVolumeHeader *header,
+ UInt32 allocationBlock, void* sectorBuffer, UInt32 *sector));
+
++#if !LINUX
+ static UInt32 GetDefaultEncoding();
++#endif
+
+ static UInt32 UTCToLocal __P((UInt32 utcTime));
+
+@@ -158,11 +167,14 @@ void SETOFFSET (void *buffer, UInt16 btN
+
+ #define ROUNDUP(x, u) (((x) % (u) == 0) ? (x) : ((x)/(u) + 1) * (u))
+
+-#define ENCODING_TO_BIT(e) \
++#if LINUX
++#define ENCODING_TO_BIT(e) (e)
++#else
++#define ENCODING_TO_BIT(e)
+ ((e) < 48 ? (e) : \
+ ((e) == kCFStringEncodingMacUkrainian ? 48 : \
+ ((e) == kCFStringEncodingMacFarsi ? 49 : 0)))
+-
++#endif
+ /*
+ * make_hfs
+ *
+@@ -528,6 +540,7 @@ InitMDB(hfsparams_t *defaults, UInt32 dr
+ * Map UTF-8 input into a Mac encoding.
+ * On conversion errors "untitled" is used as a fallback.
+ */
++#if !LINUX
+ {
+ UniChar unibuf[kHFSMaxVolumeNameChars];
+ CFStringRef cfstr;
+@@ -553,7 +566,11 @@ InitMDB(hfsparams_t *defaults, UInt32 dr
+ bcopy(&mdbp->drVN[1], defaults->volumeName, mdbp->drVN[0]);
+ defaults->volumeName[mdbp->drVN[0]] = '\0';
+ }
++#endif
+ /* Save the encoding hint in the Finder Info (field 4). */
++ mdbp->drVN[0] = strlen(defaults->volumeName);
++ bcopy(defaults->volumeName,&mdbp->drVN[1],mdbp->drVN[0]);
++
+ mdbp->drFndrInfo[4] = SET_HFS_TEXT_ENCODING(defaults->encodingHint);
+
+ mdbp->drWrCnt = kWriteSeqNum;
+@@ -1100,9 +1117,11 @@ InitCatalogRoot_HFSPlus(const hfsparams_
+ UInt16 nodeSize;
+ SInt16 offset;
+ UInt32 unicodeBytes;
++#if !LINUX
+ UInt8 canonicalName[256];
+ CFStringRef cfstr;
+ Boolean cfOK;
++#endif
+ int index = 0;
+
+ nodeSize = dp->catalogNodeSize;
+@@ -1122,7 +1141,9 @@ InitCatalogRoot_HFSPlus(const hfsparams_
+ * First record is always the root directory...
+ */
+ ckp = (HFSPlusCatalogKey *)((UInt8 *)buffer + offset);
+-
++#if LINUX
++ ConvertUTF8toUnicode(dp->volumeName, sizeof(ckp->nodeName.unicode), ckp->nodeName.unicode, &ckp->nodeName.length);
++#else
+ /* Use CFString functions to get a HFSPlus Canonical name */
+ cfstr = CFStringCreateWithCString(kCFAllocatorDefault, (char *)dp->volumeName, kCFStringEncodingUTF8);
+ cfOK = _CFStringGetFileSystemRepresentation(cfstr, canonicalName, sizeof(canonicalName));
+@@ -1139,6 +1160,7 @@ InitCatalogRoot_HFSPlus(const hfsparams_
+ dp->volumeName, kDefaultVolumeNameStr);
+ }
+ CFRelease(cfstr);
++#endif
+ ckp->nodeName.length = SWAP_BE16 (ckp->nodeName.length);
+
+ unicodeBytes = sizeof(UniChar) * SWAP_BE16 (ckp->nodeName.length);
+@@ -1821,15 +1843,15 @@ WriteBuffer(const DriveInfo *driveInfo,
+ off_t sector;
+
+ if ((byteCount % driveInfo->sectorSize) != 0)
+- errx(1, "WriteBuffer: byte count %ld is not sector size multiple", byteCount);
++ errx(1, "WriteBuffer: byte count %i is not sector size multiple", byteCount);
+
+ sector = driveInfo->sectorOffset + startingSector;
+
+ if (lseek(driveInfo->fd, sector * driveInfo->sectorSize, SEEK_SET) < 0)
+- err(1, "seek (sector %qd)", sector);
++ err(1, "seek (sector %lld)", sector);
+
+ if (write(driveInfo->fd, buffer, byteCount) != byteCount)
+- err(1, "write (sector %qd, %ld bytes)", sector, byteCount);
++ err(1, "write (sector %lld, %i bytes)", sector, byteCount);
+ }
+
+
+@@ -1913,7 +1935,7 @@ DivideAndRoundUp(UInt32 numerator, UInt3
+ return quotient;
+ }
+
+-
++#if !LINUX
+ #define __kCFUserEncodingFileName ("/.CFUserTextEncoding")
+
+ static UInt32
+@@ -1939,7 +1961,7 @@ GetDefaultEncoding()
+ }
+ return 0;
+ }
+-
++#endif
+
+ static int
+ ConvertUTF8toUnicode(const UInt8* source, UInt32 bufsize, UniChar* unibuf,
+@@ -2006,6 +2028,9 @@ ConvertUTF8toUnicode(const UInt8* source
+ static int
+ getencodinghint(unsigned char *name)
+ {
++#if LINUX
++ return(0);
++#else
+ int mib[3];
+ size_t buflen = sizeof(int);
+ struct vfsconf vfc;
+@@ -2023,7 +2048,8 @@ getencodinghint(unsigned char *name)
+ return (hint);
+ error:
+ hint = GetDefaultEncoding();
+- return (hint);
++ return (0);
++#endif
+ }
+
+
+@@ -2034,12 +2060,14 @@ void GenerateVolumeUUID(VolumeUUID *newV
+ unsigned char digest[20];
+ time_t now;
+ clock_t uptime;
+- int mib[2];
+- int sysdata;
+- char sysctlstring[128];
+ size_t datalen;
+ double sysloadavg[3];
++#if !LINUX
++ int sysdata;
++ int mib[2];
++ char sysctlstring[128];
+ struct vmtotal sysvmtotal;
++#endif
+
+ do {
+ /* Initialize the SHA-1 context for processing: */
+@@ -2052,52 +2080,58 @@ void GenerateVolumeUUID(VolumeUUID *newV
+ SHA1_Update(&context, &uptime, sizeof(uptime));
+
+ /* The kernel's boot time: */
++#if !LINUX
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_BOOTTIME;
+ datalen = sizeof(sysdata);
+ sysctl(mib, 2, &sysdata, &datalen, NULL, 0);
+ SHA1_Update(&context, &sysdata, datalen);
+-
++#endif
+ /* The system's host id: */
++#if !LINUX
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_HOSTID;
+ datalen = sizeof(sysdata);
+ sysctl(mib, 2, &sysdata, &datalen, NULL, 0);
+ SHA1_Update(&context, &sysdata, datalen);
+-
++#endif
+ /* The system's host name: */
++#if !LINUX
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_HOSTNAME;
+ datalen = sizeof(sysctlstring);
+ sysctl(mib, 2, sysctlstring, &datalen, NULL, 0);
+ SHA1_Update(&context, sysctlstring, datalen);
+-
++#endif
+ /* The running kernel's OS release string: */
++#if !LINUX
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_OSRELEASE;
+ datalen = sizeof(sysctlstring);
+ sysctl(mib, 2, sysctlstring, &datalen, NULL, 0);
+ SHA1_Update(&context, sysctlstring, datalen);
+-
++#endif
+ /* The running kernel's version string: */
++#if !LINUX
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_VERSION;
+ datalen = sizeof(sysctlstring);
+ sysctl(mib, 2, sysctlstring, &datalen, NULL, 0);
+ SHA1_Update(&context, sysctlstring, datalen);
+-
++#endif
+ /* The system's load average: */
+ datalen = sizeof(sysloadavg);
+ getloadavg(sysloadavg, 3);
+ SHA1_Update(&context, &sysloadavg, datalen);
+
+ /* The system's VM statistics: */
++#if !LINUX
+ mib[0] = CTL_VM;
+ mib[1] = VM_METER;
+ datalen = sizeof(sysvmtotal);
+ sysctl(mib, 2, &sysvmtotal, &datalen, NULL, 0);
+ SHA1_Update(&context, &sysvmtotal, datalen);
+-
++#endif
+ /* The current GMT (26 ASCII characters): */
+ time(&now);
+ strncpy(randomInputBuffer, asctime(gmtime(&now)), 26); /* "Mon Mar 27 13:46:26 2000" */
+--- a/newfs_hfs.tproj/newfs_hfs.c
++++ b/newfs_hfs.tproj/newfs_hfs.c
+@@ -38,8 +38,13 @@
+ #include <sys/mount.h>
+ #include <sys/param.h>
+ #include <sys/stat.h>
++#if LINUX
++#include <time.h>
++#endif
+
++#if !LINUX
+ #include <IOKit/storage/IOMediaBSDClient.h>
++#endif
+
+ #include <hfs/hfs_format.h>
+ #include "newfs_hfs.h"
+@@ -73,7 +78,9 @@ static void usage __P((void));
+
+ char *progname;
+ char gVolumeName[kHFSPlusMaxFileNameChars + 1] = {kDefaultVolumeNameStr};
++#if !LINUX
+ char rawdevice[MAXPATHLEN];
++#endif
+ char blkdevice[MAXPATHLEN];
+ UInt32 gBlockSize = 0;
+ UInt32 gNextCNID = kHFSFirstUserCatalogNodeID;
+@@ -158,8 +165,10 @@ main(argc, argv)
+ extern int optind;
+ int ch;
+ int forceHFS;
++#if !LINUX
+ char *cp, *special;
+ struct statfs *mp;
++#endif
+ int n;
+
+ if ((progname = strrchr(*argv, '/')))
+@@ -260,16 +269,19 @@ main(argc, argv)
+ usage();
+ }
+
+- argc -= optind;
+- argv += optind;
++ argc -= optind;
++ argv += optind;
+
+- if (gPartitionSize != 0) {
+- if (argc != 0)
+- usage();
+- } else {
+- if (argc != 1)
+- usage();
++ if (gPartitionSize != 0) {
++ if (argc != 0)
++ usage();
++ } else {
++ if (argc != 1)
++ usage();
+
++#if LINUX
++ (void) sprintf(blkdevice, "%s", argv[0]);
++#else
+ special = argv[0];
+ cp = strrchr(special, '/');
+ if (cp != 0)
+@@ -278,6 +290,7 @@ main(argc, argv)
+ special++;
+ (void) sprintf(rawdevice, "%sr%s", _PATH_DEV, special);
+ (void) sprintf(blkdevice, "%s%s", _PATH_DEV, special);
++#endif
+ }
+
+ if (forceHFS && gJournaled) {
+@@ -301,6 +314,9 @@ main(argc, argv)
+ /*
+ * Check if target device is aready mounted
+ */
++#if LINUX
++ // FIXME
++#else
+ n = getmntinfo(&mp, MNT_NOWAIT);
+ if (n == 0)
+ fatal("%s: getmntinfo: %s", blkdevice, strerror(errno));
+@@ -310,15 +326,20 @@ main(argc, argv)
+ fatal("%s is mounted on %s", blkdevice, mp->f_mntonname);
+ ++mp;
+ }
++#endif
+ }
+
+- if (hfs_newfs(rawdevice, forceHFS, true) < 0) {
++ if (hfs_newfs(blkdevice, forceHFS, true) < 0) {
++#if LINUX
++ err(1, NULL);
++#else
+ /* On ENXIO error use the block device (to get de-blocking) */
+ if (errno == ENXIO) {
+ if (hfs_newfs(blkdevice, forceHFS, false) < 0)
+ err(1, NULL);
+ } else
+ err(1, NULL);
++#endif
+ }
+
+ exit(0);
+@@ -506,7 +527,9 @@ hfs_newfs(char *device, int forceHFS, in
+ int fso = 0;
+ int retval = 0;
+ hfsparams_t defaults = {0};
++#if !LINUX
+ u_int64_t maxSectorsPerIO;
++#endif
+
+ if (gPartitionSize) {
+ dip.sectorSize = kBytesPerSector;
+@@ -526,6 +549,34 @@ hfs_newfs(char *device, int forceHFS, in
+
+ if (fstat( fso, &stbuf) < 0)
+ fatal("%s: %s", device, strerror(errno));
++#if LINUX
++ dip.sectorSize = 512;
++ dip.sectorsPerIO = 256;
++
++# ifndef BLKGETSIZE
++# define BLKGETSIZE _IO(0x12,96)
++# endif
++
++# ifndef BLKGETSIZE64
++# define BLKGETSIZE64 _IOR(0x12,114,size_t)
++# endif
++
++ if (S_ISREG(stbuf.st_mode)) {
++ dip.totalSectors = stbuf.st_size / 512;
++ }
++ else if (S_ISBLK(stbuf.st_mode)) {
++ unsigned long size;
++ u_int64_t size64;
++ if (!ioctl(fso, BLKGETSIZE64, &size64))
++ dip.totalSectors = size64 / 512;
++ else if (!ioctl(fso, BLKGETSIZE, &size))
++ dip.totalSectors = size;
++ else
++ fatal("%s: %s", device, strerror(errno));
++ }
++ else
++ fatal("%s: is not a block device", device);
++#else
+
+ if (ioctl(fso, DKIOCGETBLOCKCOUNT, &dip.totalSectors) < 0)
+ fatal("%s: %s", device, strerror(errno));
+@@ -537,11 +588,14 @@ hfs_newfs(char *device, int forceHFS, in
+ dip.sectorsPerIO = (128 * 1024) / dip.sectorSize; /* use 128K as default */
+ else
+ dip.sectorsPerIO = MIN(maxSectorsPerIO, (1024 * 1024) / dip.sectorSize);
++#endif
++
+ /*
+ * The make_hfs code currentlydoes 512 byte sized I/O.
+ * If the sector size is bigger than 512, start over
+ * using the block device (to get de-blocking).
+ */
++#if !LINUX
+ if (dip.sectorSize != kBytesPerSector) {
+ if (isRaw) {
+ close(fso);
+@@ -556,7 +610,9 @@ hfs_newfs(char *device, int forceHFS, in
+ dip.sectorSize = kBytesPerSector;
+ }
+ }
++#endif
+ }
++
+ dip.sectorOffset = 0;
+ time(&createtime);
+
+--- a/newfs_hfs.tproj/newfs_hfs.h
++++ b/newfs_hfs.tproj/newfs_hfs.h
+@@ -19,8 +19,12 @@
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+-
++
++#if LINUX
++#include "missing.h"
++#else
+ #include <CoreFoundation/CFBase.h>
++#endif
+
+ /*
+ * Mac OS Finder flags
+@@ -122,33 +126,33 @@ enum {
+ #define kDTDF_FileID 16
+ #define kDTDF_Name "Desktop DF"
+ #define kDTDF_Chars 10
+-#define kDTDF_Type 'DTFL'
+-#define kDTDF_Creator 'DMGR'
++#define kDTDF_Type 0x4454464C /* 'DTFL' */
++#define kDTDF_Creator 0x444D4752 /* 'DMGR' */
+
+ #define kDTDB_FileID 17
+ #define kDTDB_Name "Desktop DB"
+ #define kDTDB_Chars 10
+-#define kDTDB_Type 'BTFL'
+-#define kDTDB_Creator 'DMGR'
++#define kDTDB_Type 0x4254464C /* 'BTFL' */
++#define kDTDB_Creator 0x444D4752 /* 'DMGR' */
+ #define kDTDB_Size 1024
+
+ #define kReadMe_FileID 18
+ #define kReadMe_Name "ReadMe"
+ #define kReadMe_Chars 6
+-#define kReadMe_Type 'ttro'
+-#define kReadMe_Creator 'ttxt'
++#define kReadMe_Type 0x7474726F /* 'ttro' */
++#define kReadMe_Creator 0x74747974 /* 'ttxt' */
+
+ #define kFinder_FileID 19
+ #define kFinder_Name "Finder"
+ #define kFinder_Chars 6
+-#define kFinder_Type 'FNDR'
+-#define kFinder_Creator 'MACS'
++#define kFinder_Type 0x464E4452 /* 'FNDR' */
++#define kFinder_Creator 0x4D414353 /* 'MACS' */
+
+ #define kSystem_FileID 20
+ #define kSystem_Name "System"
+ #define kSystem_Chars 6
+-#define kSystem_Type 'zsys'
+-#define kSystem_Creator 'MACS'
++#define kSystem_Type 0x7A737973 /* 'zsys' */
++#define kSystem_Creator 0x4D414353 /* 'MACS' */
+
+
+
diff --git a/external/subpack/utils/hfsprogs/patches/0003-Add-helper-include-files-absent-from-the-upstream-pa.patch b/external/subpack/utils/hfsprogs/patches/0003-Add-helper-include-files-absent-from-the-upstream-pa.patch
new file mode 100644
index 0000000..02b4a6c
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0003-Add-helper-include-files-absent-from-the-upstream-pa.patch
@@ -0,0 +1,1012 @@
+From: =?UTF-8?q?Rog=C3=A9rio=20Brito?= <rbrito@ime.usp.br>
+Date: Thu, 24 Oct 2013 01:11:21 -0200
+Subject: Add helper include files absent from the upstream package
+
+Add some include files from an Apple system that contain the definition of
+the data structures used by the programs that manipulate the filesystems.
+---
+ include/bitstring.h | 164 +++++++++++
+ include/hfs/hfs_format.h | 689 +++++++++++++++++++++++++++++++++++++++++++++
+ include/hfs/hfs_mount.h | 78 +++++
+ include/sys/appleapiopts.h | 52 ++++
+ 4 files changed, 983 insertions(+)
+ create mode 100644 include/bitstring.h
+ create mode 100644 include/hfs/hfs_format.h
+ create mode 100644 include/hfs/hfs_mount.h
+ create mode 100644 include/sys/appleapiopts.h
+
+--- /dev/null
++++ b/include/bitstring.h
+@@ -0,0 +1,164 @@
++/*
++ * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
++ *
++ * @APPLE_LICENSE_HEADER_START@
++ *
++ * The contents of this file constitute Original Code as defined in and
++ * are subject to the Apple Public Source License Version 1.1 (the
++ * "License"). You may not use this file except in compliance with the
++ * License. Please obtain a copy of the License at
++ * http://www.apple.com/publicsource and read it before using this file.
++ *
++ * This Original Code and all software distributed under the License are
++ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
++ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
++ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
++ * License for the specific language governing rights and limitations
++ * under the License.
++ *
++ * @APPLE_LICENSE_HEADER_END@
++ */
++/*
++ * Copyright (c) 1989, 1993
++ * The Regents of the University of California. All rights reserved.
++ *
++ * This code is derived from software contributed to Berkeley by
++ * Paul Vixie.
++ *
++ * 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. All advertising materials mentioning features or use of this software
++ * must display the following acknowledgement:
++ * This product includes software developed by the University of
++ * California, Berkeley and its contributors.
++ * 4. 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.
++ *
++ * @(#)bitstring.h 8.1 (Berkeley) 7/19/93
++ */
++
++#ifndef _BITSTRING_H_
++#define _BITSTRING_H_
++
++typedef unsigned char bitstr_t;
++
++/* internal macros */
++ /* byte of the bitstring bit is in */
++#define _bit_byte(bit) \
++ ((bit) >> 3)
++
++ /* mask for the bit within its byte */
++#define _bit_mask(bit) \
++ (1 << ((bit)&0x7))
++
++/* external macros */
++ /* bytes in a bitstring of nbits bits */
++#define bitstr_size(nbits) \
++ ((((nbits) - 1) >> 3) + 1)
++
++ /* allocate a bitstring */
++#define bit_alloc(nbits) \
++ (bitstr_t *)calloc(1, \
++ (unsigned int)bitstr_size(nbits) * sizeof(bitstr_t))
++
++ /* allocate a bitstring on the stack */
++#define bit_decl(name, nbits) \
++ (name)[bitstr_size(nbits)]
++
++ /* is bit N of bitstring name set? */
++#define bit_test(name, bit) \
++ ((name)[_bit_byte(bit)] & _bit_mask(bit))
++
++ /* set bit N of bitstring name */
++#define bit_set(name, bit) \
++ (name)[_bit_byte(bit)] |= _bit_mask(bit)
++
++ /* clear bit N of bitstring name */
++#define bit_clear(name, bit) \
++ (name)[_bit_byte(bit)] &= ~_bit_mask(bit)
++
++ /* clear bits start ... stop in bitstring */
++#define bit_nclear(name, start, stop) { \
++ register bitstr_t *_name = name; \
++ register int _start = start, _stop = stop; \
++ register int _startbyte = _bit_byte(_start); \
++ register int _stopbyte = _bit_byte(_stop); \
++ if (_startbyte == _stopbyte) { \
++ _name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \
++ (0xff << ((_stop&0x7) + 1))); \
++ } else { \
++ _name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \
++ while (++_startbyte < _stopbyte) \
++ _name[_startbyte] = 0; \
++ _name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \
++ } \
++}
++
++ /* set bits start ... stop in bitstring */
++#define bit_nset(name, start, stop) { \
++ register bitstr_t *_name = name; \
++ register int _start = start, _stop = stop; \
++ register int _startbyte = _bit_byte(_start); \
++ register int _stopbyte = _bit_byte(_stop); \
++ if (_startbyte == _stopbyte) { \
++ _name[_startbyte] |= ((0xff << (_start&0x7)) & \
++ (0xff >> (7 - (_stop&0x7)))); \
++ } else { \
++ _name[_startbyte] |= 0xff << ((_start)&0x7); \
++ while (++_startbyte < _stopbyte) \
++ _name[_startbyte] = 0xff; \
++ _name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \
++ } \
++}
++
++ /* find first bit clear in name */
++#define bit_ffc(name, nbits, value) { \
++ register bitstr_t *_name = name; \
++ register int _byte, _nbits = nbits; \
++ register int _stopbyte = _bit_byte(_nbits), _value = -1; \
++ for (_byte = 0; _byte <= _stopbyte; ++_byte) \
++ if (_name[_byte] != 0xff) { \
++ _value = _byte << 3; \
++ for (_stopbyte = _name[_byte]; (_stopbyte&0x1); \
++ ++_value, _stopbyte >>= 1); \
++ break; \
++ } \
++ *(value) = _value; \
++}
++
++ /* find first bit set in name */
++#define bit_ffs(name, nbits, value) { \
++ register bitstr_t *_name = name; \
++ register int _byte, _nbits = nbits; \
++ register int _stopbyte = _bit_byte(_nbits), _value = -1; \
++ for (_byte = 0; _byte <= _stopbyte; ++_byte) \
++ if (_name[_byte]) { \
++ _value = _byte << 3; \
++ for (_stopbyte = _name[_byte]; !(_stopbyte&0x1); \
++ ++_value, _stopbyte >>= 1); \
++ break; \
++ } \
++ *(value) = _value; \
++}
++
++#endif /* !_BITSTRING_H_ */
+--- /dev/null
++++ b/include/hfs/hfs_format.h
+@@ -0,0 +1,689 @@
++/*
++ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
++ *
++ * @APPLE_LICENSE_HEADER_START@
++ *
++ * The contents of this file constitute Original Code as defined in and
++ * are subject to the Apple Public Source License Version 1.1 (the
++ * "License"). You may not use this file except in compliance with the
++ * License. Please obtain a copy of the License at
++ * http://www.apple.com/publicsource and read it before using this file.
++ *
++ * This Original Code and all software distributed under the License are
++ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
++ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
++ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
++ * License for the specific language governing rights and limitations
++ * under the License.
++ *
++ * @APPLE_LICENSE_HEADER_END@
++ */
++#ifndef __HFS_FORMAT__
++#define __HFS_FORMAT__
++
++#include "missing.h"
++
++#include <sys/appleapiopts.h>
++
++/*
++ * hfs_format.c
++ *
++ * This file describes the on-disk format for HFS and HFS Plus volumes.
++ * The HFS Plus volume format is desciibed in detail in Apple Technote 1150.
++ *
++ * http://developer.apple.com/technotes/tn/tn1150.html
++ *
++ */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* some on-disk hfs structures have 68K alignment (misaligned) */
++
++#define PACKED_S __attribute__((packed))
++
++/* Signatures used to differentiate between HFS and HFS Plus volumes */
++enum {
++ kHFSSigWord = 0x4244, /* 'BD' in ASCII */
++ kHFSPlusSigWord = 0x482B, /* 'H+' in ASCII */
++ kHFSXSigWord = 0x4858, /* 'HX' in ASCII */
++
++ kHFSPlusVersion = 0x0004, /* 'H+' volumes are version 4 only */
++ kHFSXVersion = 0x0005, /* 'HX' volumes start with version 5 */
++
++ kHFSPlusMountVersion = 0x31302E30, /* '10.0' for Mac OS X */
++ kHFSJMountVersion = 0x4846534a, /* 'HFSJ' for journaled HFS+ on OS X */
++ kFSKMountVersion = 0x46534b21 /* 'FSK!' for failed journal replay */
++}PACKED_S;
++
++
++#if 1
++/*
++ * Mac OS X has a special directory for linked and unlinked files (HFS Plus only).
++ * This directory and its contents are never exported from the filesystem under
++ * Mac OS X.
++ *
++ * To make this folder name sort last, it has embedded null prefix.
++ * (0xC0, 0x80 in UTF-8)
++ */
++#define HFSPLUSMETADATAFOLDER "\xC0\x80\xC0\x80\xC0\x80\xC0\x80HFS+ Private Data"
++
++/*
++ * Files in the HFS Private Data folder have one of the following prefixes
++ * followed by a decimal number (no leading zeros). For indirect nodes this
++ * number is a 32 bit random number. For unlinked (deleted) files that are
++ * still open, the number is the file ID for that file.
++ *
++ * e.g. iNode7182000 and temp3296
++ */
++#define HFS_INODE_PREFIX "iNode"
++#define HFS_DELETE_PREFIX "temp"
++
++#endif /* __APPLE_API_PRIVATE */
++
++/*
++ * Indirect link files (hard links) have the following type/creator.
++ */
++enum {
++ kHardLinkFileType = 0x686C6E6B, /* 'hlnk' */
++ kHFSPlusCreator = 0x6866732B /* 'hfs+' */
++}PACKED_S;
++
++
++#ifndef _HFSUNISTR255_DEFINED_
++#define _HFSUNISTR255_DEFINED_
++/* Unicode strings are used for HFS Plus file and folder names */
++struct HFSUniStr255 {
++ u_int16_t length; /* number of unicode characters */
++ u_int16_t unicode[255]; /* unicode characters */
++} PACKED_S;
++typedef struct HFSUniStr255 HFSUniStr255;
++typedef const HFSUniStr255 *ConstHFSUniStr255Param;
++#endif /* _HFSUNISTR255_DEFINED_ */
++
++enum {
++ kHFSMaxVolumeNameChars = 27,
++ kHFSMaxFileNameChars = 31,
++ kHFSPlusMaxFileNameChars = 255
++}PACKED_S;
++
++
++/* Extent overflow file data structures */
++
++/* HFS Extent key */
++struct HFSExtentKey {
++ u_int8_t keyLength; /* length of key, excluding this field */
++ u_int8_t forkType; /* 0 = data fork, FF = resource fork */
++ u_int32_t fileID; /* file ID */
++ u_int16_t startBlock; /* first file allocation block number in this extent */
++}PACKED_S;
++typedef struct HFSExtentKey HFSExtentKey;
++
++/* HFS Plus Extent key */
++struct HFSPlusExtentKey {
++ u_int16_t keyLength; /* length of key, excluding this field */
++ u_int8_t forkType; /* 0 = data fork, FF = resource fork */
++ u_int8_t pad; /* make the other fields align on 32-bit boundary */
++ u_int32_t fileID; /* file ID */
++ u_int32_t startBlock; /* first file allocation block number in this extent */
++}PACKED_S;
++typedef struct HFSPlusExtentKey HFSPlusExtentKey;
++
++/* Number of extent descriptors per extent record */
++enum {
++ kHFSExtentDensity = 3,
++ kHFSPlusExtentDensity = 8
++}PACKED_S;
++
++/* HFS extent descriptor */
++struct HFSExtentDescriptor {
++ u_int16_t startBlock; /* first allocation block */
++ u_int16_t blockCount; /* number of allocation blocks */
++}PACKED_S;
++typedef struct HFSExtentDescriptor HFSExtentDescriptor;
++
++/* HFS Plus extent descriptor */
++struct HFSPlusExtentDescriptor {
++ u_int32_t startBlock; /* first allocation block */
++ u_int32_t blockCount; /* number of allocation blocks */
++}PACKED_S;
++typedef struct HFSPlusExtentDescriptor HFSPlusExtentDescriptor;
++
++/* HFS extent record */
++typedef HFSExtentDescriptor HFSExtentRecord[3];
++
++/* HFS Plus extent record */
++typedef HFSPlusExtentDescriptor HFSPlusExtentRecord[8];
++
++
++/* Finder information */
++struct FndrFileInfo {
++ u_int32_t fdType; /* file type */
++ u_int32_t fdCreator; /* file creator */
++ u_int16_t fdFlags; /* Finder flags */
++ struct {
++ int16_t v; /* file's location */
++ int16_t h;
++ } PACKED_S fdLocation;
++ int16_t opaque;
++}PACKED_S;
++typedef struct FndrFileInfo FndrFileInfo;
++
++struct FndrDirInfo {
++ struct { /* folder's window rectangle */
++ int16_t top;
++ int16_t left;
++ int16_t bottom;
++ int16_t right;
++ }PACKED_S frRect;
++ unsigned short frFlags; /* Finder flags */
++ struct {
++ u_int16_t v; /* folder's location */
++ u_int16_t h;
++ }PACKED_S frLocation;
++ int16_t opaque;
++}PACKED_S;
++typedef struct FndrDirInfo FndrDirInfo;
++
++struct FndrOpaqueInfo {
++ int8_t opaque[16];
++}PACKED_S;
++typedef struct FndrOpaqueInfo FndrOpaqueInfo;
++
++
++/* HFS Plus Fork data info - 80 bytes */
++struct HFSPlusForkData {
++ u_int64_t logicalSize; /* fork's logical size in bytes */
++ u_int32_t clumpSize; /* fork's clump size in bytes */
++ u_int32_t totalBlocks; /* total blocks used by this fork */
++ HFSPlusExtentRecord extents; /* initial set of extents */
++}PACKED_S;
++typedef struct HFSPlusForkData HFSPlusForkData;
++
++
++/* Mac OS X has 16 bytes worth of "BSD" info.
++ *
++ * Note: Mac OS 9 implementations and applications
++ * should preserve, but not change, this information.
++ */
++struct HFSPlusBSDInfo {
++ u_int32_t ownerID; /* user or group ID of file/folder owner */
++ u_int32_t groupID; /* additional user of group ID */
++ u_int8_t adminFlags; /* super-user changeable flags */
++ u_int8_t ownerFlags; /* owner changeable flags */
++ u_int16_t fileMode; /* file type and permission bits */
++ union {
++ u_int32_t iNodeNum; /* indirect node number (hard links only) */
++ u_int32_t linkCount; /* links that refer to this indirect node */
++ u_int32_t rawDevice; /* special file device (FBLK and FCHR only) */
++ }PACKED_S special;
++}PACKED_S;
++typedef struct HFSPlusBSDInfo HFSPlusBSDInfo;
++
++
++/* Catalog file data structures */
++
++enum {
++ kHFSRootParentID = 1, /* Parent ID of the root folder */
++ kHFSRootFolderID = 2, /* Folder ID of the root folder */
++ kHFSExtentsFileID = 3, /* File ID of the extents file */
++ kHFSCatalogFileID = 4, /* File ID of the catalog file */
++ kHFSBadBlockFileID = 5, /* File ID of the bad allocation block file */
++ kHFSAllocationFileID = 6, /* File ID of the allocation file (HFS Plus only) */
++ kHFSStartupFileID = 7, /* File ID of the startup file (HFS Plus only) */
++ kHFSAttributesFileID = 8, /* File ID of the attribute file (HFS Plus only) */
++ kHFSRepairCatalogFileID = 14, /* Used when rebuilding Catalog B-tree */
++ kHFSBogusExtentFileID = 15, /* Used for exchanging extents in extents file */
++ kHFSFirstUserCatalogNodeID = 16
++}PACKED_S;
++
++/* HFS catalog key */
++struct HFSCatalogKey {
++ u_int8_t keyLength; /* key length (in bytes) */
++ u_int8_t reserved; /* reserved (set to zero) */
++ u_int32_t parentID; /* parent folder ID */
++ u_int8_t nodeName[kHFSMaxFileNameChars + 1]; /* catalog node name */
++}PACKED_S;
++typedef struct HFSCatalogKey HFSCatalogKey;
++
++/* HFS Plus catalog key */
++struct HFSPlusCatalogKey {
++ u_int16_t keyLength; /* key length (in bytes) */
++ u_int32_t parentID; /* parent folder ID */
++ HFSUniStr255 nodeName; /* catalog node name */
++}PACKED_S;
++typedef struct HFSPlusCatalogKey HFSPlusCatalogKey;
++
++/* Catalog record types */
++enum {
++ /* HFS Catalog Records */
++ kHFSFolderRecord = 0x0100, /* Folder record */
++ kHFSFileRecord = 0x0200, /* File record */
++ kHFSFolderThreadRecord = 0x0300, /* Folder thread record */
++ kHFSFileThreadRecord = 0x0400, /* File thread record */
++
++ /* HFS Plus Catalog Records */
++ kHFSPlusFolderRecord = 1, /* Folder record */
++ kHFSPlusFileRecord = 2, /* File record */
++ kHFSPlusFolderThreadRecord = 3, /* Folder thread record */
++ kHFSPlusFileThreadRecord = 4 /* File thread record */
++}PACKED_S;
++
++
++/* Catalog file record flags */
++enum {
++ kHFSFileLockedBit = 0x0000, /* file is locked and cannot be written to */
++ kHFSFileLockedMask = 0x0001,
++
++ kHFSThreadExistsBit = 0x0001, /* a file thread record exists for this file */
++ kHFSThreadExistsMask = 0x0002,
++
++ kHFSHasAttributesBit = 0x0002, /* object has extended attributes */
++ kHFSHasAttributesMask = 0x0004,
++
++ kHFSHasSecurityBit = 0x0003, /* object has security data (ACLs) */
++ kHFSHasSecurityMask = 0x0008
++}PACKED_S;
++
++
++/* HFS catalog folder record - 70 bytes */
++struct HFSCatalogFolder {
++ int16_t recordType; /* == kHFSFolderRecord */
++ u_int16_t flags; /* folder flags */
++ u_int16_t valence; /* folder valence */
++ u_int32_t folderID; /* folder ID */
++ u_int32_t createDate; /* date and time of creation */
++ u_int32_t modifyDate; /* date and time of last modification */
++ u_int32_t backupDate; /* date and time of last backup */
++ FndrDirInfo userInfo; /* Finder information */
++ FndrOpaqueInfo finderInfo; /* additional Finder information */
++ u_int32_t reserved[4]; /* reserved - initialized as zero */
++}PACKED_S;
++typedef struct HFSCatalogFolder HFSCatalogFolder;
++
++/* HFS Plus catalog folder record - 88 bytes */
++struct HFSPlusCatalogFolder {
++ int16_t recordType; /* == kHFSPlusFolderRecord */
++ u_int16_t flags; /* file flags */
++ u_int32_t valence; /* folder's valence (limited to 2^16 in Mac OS) */
++ u_int32_t folderID; /* folder ID */
++ u_int32_t createDate; /* date and time of creation */
++ u_int32_t contentModDate; /* date and time of last content modification */
++ u_int32_t attributeModDate; /* date and time of last attribute modification */
++ u_int32_t accessDate; /* date and time of last access (MacOS X only) */
++ u_int32_t backupDate; /* date and time of last backup */
++ HFSPlusBSDInfo bsdInfo; /* permissions (for MacOS X) */
++ FndrDirInfo userInfo; /* Finder information */
++ FndrOpaqueInfo finderInfo; /* additional Finder information */
++ u_int32_t textEncoding; /* hint for name conversions */
++ u_int32_t attrBlocks; /* cached count of attribute data blocks */
++}PACKED_S;
++typedef struct HFSPlusCatalogFolder HFSPlusCatalogFolder;
++
++/* HFS catalog file record - 102 bytes */
++struct HFSCatalogFile {
++ int16_t recordType; /* == kHFSFileRecord */
++ u_int8_t flags; /* file flags */
++ int8_t fileType; /* file type (unused ?) */
++ FndrFileInfo userInfo; /* Finder information */
++ u_int32_t fileID; /* file ID */
++ u_int16_t dataStartBlock; /* not used - set to zero */
++ int32_t dataLogicalSize; /* logical EOF of data fork */
++ int32_t dataPhysicalSize; /* physical EOF of data fork */
++ u_int16_t rsrcStartBlock; /* not used - set to zero */
++ int32_t rsrcLogicalSize; /* logical EOF of resource fork */
++ int32_t rsrcPhysicalSize; /* physical EOF of resource fork */
++ u_int32_t createDate; /* date and time of creation */
++ u_int32_t modifyDate; /* date and time of last modification */
++ u_int32_t backupDate; /* date and time of last backup */
++ FndrOpaqueInfo finderInfo; /* additional Finder information */
++ u_int16_t clumpSize; /* file clump size (not used) */
++ HFSExtentRecord dataExtents; /* first data fork extent record */
++ HFSExtentRecord rsrcExtents; /* first resource fork extent record */
++ u_int32_t reserved; /* reserved - initialized as zero */
++}PACKED_S;
++typedef struct HFSCatalogFile HFSCatalogFile;
++
++/* HFS Plus catalog file record - 248 bytes */
++struct HFSPlusCatalogFile {
++ int16_t recordType; /* == kHFSPlusFileRecord */
++ u_int16_t flags; /* file flags */
++ u_int32_t reserved1; /* reserved - initialized as zero */
++ u_int32_t fileID; /* file ID */
++ u_int32_t createDate; /* date and time of creation */
++ u_int32_t contentModDate; /* date and time of last content modification */
++ u_int32_t attributeModDate; /* date and time of last attribute modification */
++ u_int32_t accessDate; /* date and time of last access (MacOS X only) */
++ u_int32_t backupDate; /* date and time of last backup */
++ HFSPlusBSDInfo bsdInfo; /* permissions (for MacOS X) */
++ FndrFileInfo userInfo; /* Finder information */
++ FndrOpaqueInfo finderInfo; /* additional Finder information */
++ u_int32_t textEncoding; /* hint for name conversions */
++ u_int32_t attrBlocks; /* cached count of attribute data blocks */
++
++ /* Note: these start on double long (64 bit) boundary */
++ HFSPlusForkData dataFork; /* size and block data for data fork */
++ HFSPlusForkData resourceFork; /* size and block data for resource fork */
++}PACKED_S;
++typedef struct HFSPlusCatalogFile HFSPlusCatalogFile;
++
++/* HFS catalog thread record - 46 bytes */
++struct HFSCatalogThread {
++ int16_t recordType; /* == kHFSFolderThreadRecord or kHFSFileThreadRecord */
++ int32_t reserved[2]; /* reserved - initialized as zero */
++ u_int32_t parentID; /* parent ID for this catalog node */
++ u_int8_t nodeName[kHFSMaxFileNameChars + 1]; /* name of this catalog node */
++}PACKED_S;
++typedef struct HFSCatalogThread HFSCatalogThread;
++
++/* HFS Plus catalog thread record -- 264 bytes */
++struct HFSPlusCatalogThread {
++ int16_t recordType; /* == kHFSPlusFolderThreadRecord or kHFSPlusFileThreadRecord */
++ int16_t reserved; /* reserved - initialized as zero */
++ u_int32_t parentID; /* parent ID for this catalog node */
++ HFSUniStr255 nodeName; /* name of this catalog node (variable length) */
++}PACKED_S;
++typedef struct HFSPlusCatalogThread HFSPlusCatalogThread;
++
++#ifdef __APPLE_API_UNSTABLE
++/*
++ These are the types of records in the attribute B-tree. The values were
++ chosen so that they wouldn't conflict with the catalog record types.
++*/
++enum {
++ kHFSPlusAttrInlineData = 0x10, /* if size < kAttrOverflowSize */
++ kHFSPlusAttrForkData = 0x20, /* if size >= kAttrOverflowSize */
++ kHFSPlusAttrExtents = 0x30 /* overflow extents for large attributes */
++}PACKED_S;
++
++
++/*
++ HFSPlusAttrForkData
++ For larger attributes, whose value is stored in allocation blocks.
++ If the attribute has more than 8 extents, there will be additional
++ records (of type HFSPlusAttrExtents) for this attribute.
++*/
++struct HFSPlusAttrForkData {
++ u_int32_t recordType; /* == kHFSPlusAttrForkData*/
++ u_int32_t reserved;
++ HFSPlusForkData theFork; /* size and first extents of value*/
++}PACKED_S;
++typedef struct HFSPlusAttrForkData HFSPlusAttrForkData;
++
++/*
++ HFSPlusAttrExtents
++ This record contains information about overflow extents for large,
++ fragmented attributes.
++*/
++struct HFSPlusAttrExtents {
++ u_int32_t recordType; /* == kHFSPlusAttrExtents*/
++ u_int32_t reserved;
++ HFSPlusExtentRecord extents; /* additional extents*/
++}PACKED_S;
++typedef struct HFSPlusAttrExtents HFSPlusAttrExtents;
++
++/*
++ * Atrributes B-tree Data Record
++ *
++ * For small attributes, whose entire value is stored
++ * within a single B-tree record.
++ */
++struct HFSPlusAttrData {
++ u_int32_t recordType; /* == kHFSPlusAttrInlineData */
++ u_int32_t reserved[2];
++ u_int32_t attrSize; /* size of attribute data in bytes */
++ u_int8_t attrData[2]; /* variable length */
++}PACKED_S;
++typedef struct HFSPlusAttrData HFSPlusAttrData;
++
++
++/* HFSPlusAttrInlineData is obsolete use HFSPlusAttrData instead */
++struct HFSPlusAttrInlineData {
++ u_int32_t recordType;
++ u_int32_t reserved;
++ u_int32_t logicalSize;
++ u_int8_t userData[2];
++}PACKED_S;
++typedef struct HFSPlusAttrInlineData HFSPlusAttrInlineData;
++
++
++/* A generic Attribute Record*/
++union HFSPlusAttrRecord {
++ u_int32_t recordType;
++ HFSPlusAttrInlineData inlineData; /* NOT USED */
++ HFSPlusAttrData attrData;
++ HFSPlusAttrForkData forkData;
++ HFSPlusAttrExtents overflowExtents;
++}PACKED_S;
++typedef union HFSPlusAttrRecord HFSPlusAttrRecord;
++
++/* Attribute key */
++enum { kHFSMaxAttrNameLen = 127 };
++struct HFSPlusAttrKey {
++ u_int16_t keyLength; /* key length (in bytes) */
++ u_int16_t pad; /* set to zero */
++ u_int32_t fileID; /* file associated with attribute */
++ u_int32_t startBlock; /* first attribue allocation block number for extents */
++ u_int16_t attrNameLen; /* number of unicode characters */
++ u_int16_t attrName[127]; /* attribute name (Unicode) */
++}PACKED_S;
++typedef struct HFSPlusAttrKey HFSPlusAttrKey;
++
++#define kHFSPlusAttrKeyMaximumLength (sizeof(HFSPlusAttrKey) - sizeof(u_int16_t))
++#define kHFSPlusAttrKeyMinimumLength (kHFSPlusAttrKeyMaximumLength - (127 * sizeof(u_int16_t)))
++
++#endif /* __APPLE_API_UNSTABLE */
++
++
++/* Key and node lengths */
++enum {
++ kHFSPlusExtentKeyMaximumLength = sizeof(HFSPlusExtentKey) - sizeof(u_int16_t),
++ kHFSExtentKeyMaximumLength = sizeof(HFSExtentKey) - sizeof(u_int8_t),
++ kHFSPlusCatalogKeyMaximumLength = sizeof(HFSPlusCatalogKey) - sizeof(u_int16_t),
++ kHFSPlusCatalogKeyMinimumLength = kHFSPlusCatalogKeyMaximumLength - sizeof(HFSUniStr255) + sizeof(u_int16_t),
++ kHFSCatalogKeyMaximumLength = sizeof(HFSCatalogKey) - sizeof(u_int8_t),
++ kHFSCatalogKeyMinimumLength = kHFSCatalogKeyMaximumLength - (kHFSMaxFileNameChars + 1) + sizeof(u_int8_t),
++ kHFSPlusCatalogMinNodeSize = 4096,
++ kHFSPlusExtentMinNodeSize = 512,
++ kHFSPlusAttrMinNodeSize = 4096
++}PACKED_S;
++
++/* HFS and HFS Plus volume attribute bits */
++enum {
++ /* Bits 0-6 are reserved (always cleared by MountVol call) */
++ kHFSVolumeHardwareLockBit = 7, /* volume is locked by hardware */
++ kHFSVolumeUnmountedBit = 8, /* volume was successfully unmounted */
++ kHFSVolumeSparedBlocksBit = 9, /* volume has bad blocks spared */
++ kHFSVolumeNoCacheRequiredBit = 10, /* don't cache volume blocks (i.e. RAM or ROM disk) */
++ kHFSBootVolumeInconsistentBit = 11, /* boot volume is inconsistent (System 7.6 and later) */
++ kHFSCatalogNodeIDsReusedBit = 12,
++ kHFSVolumeJournaledBit = 13, /* this volume has a journal on it */
++ kHFSVolumeInconsistentBit = 14, /* serious inconsistencies detected at runtime */
++ kHFSVolumeSoftwareLockBit = 15, /* volume is locked by software */
++
++ kHFSVolumeHardwareLockMask = 1 << kHFSVolumeHardwareLockBit,
++ kHFSVolumeUnmountedMask = 1 << kHFSVolumeUnmountedBit,
++ kHFSVolumeSparedBlocksMask = 1 << kHFSVolumeSparedBlocksBit,
++ kHFSVolumeNoCacheRequiredMask = 1 << kHFSVolumeNoCacheRequiredBit,
++ kHFSBootVolumeInconsistentMask = 1 << kHFSBootVolumeInconsistentBit,
++ kHFSCatalogNodeIDsReusedMask = 1 << kHFSCatalogNodeIDsReusedBit,
++ kHFSVolumeJournaledMask = 1 << kHFSVolumeJournaledBit,
++ kHFSVolumeInconsistentMask = 1 << kHFSVolumeInconsistentBit,
++ kHFSVolumeSoftwareLockMask = 1 << kHFSVolumeSoftwareLockBit,
++ kHFSMDBAttributesMask = 0x8380
++}PACKED_S;
++
++
++/* HFS Master Directory Block - 162 bytes */
++/* Stored at sector #2 (3rd sector) and second-to-last sector. */
++struct HFSMasterDirectoryBlock {
++ u_int16_t drSigWord; /* == kHFSSigWord */
++ u_int32_t drCrDate; /* date and time of volume creation */
++ u_int32_t drLsMod; /* date and time of last modification */
++ u_int16_t drAtrb; /* volume attributes */
++ u_int16_t drNmFls; /* number of files in root folder */
++ u_int16_t drVBMSt; /* first block of volume bitmap */
++ u_int16_t drAllocPtr; /* start of next allocation search */
++ u_int16_t drNmAlBlks; /* number of allocation blocks in volume */
++ u_int32_t drAlBlkSiz; /* size (in bytes) of allocation blocks */
++ u_int32_t drClpSiz; /* default clump size */
++ u_int16_t drAlBlSt; /* first allocation block in volume */
++ u_int32_t drNxtCNID; /* next unused catalog node ID */
++ u_int16_t drFreeBks; /* number of unused allocation blocks */
++ u_int8_t drVN[kHFSMaxVolumeNameChars + 1]; /* volume name */
++ u_int32_t drVolBkUp; /* date and time of last backup */
++ u_int16_t drVSeqNum; /* volume backup sequence number */
++ u_int32_t drWrCnt; /* volume write count */
++ u_int32_t drXTClpSiz; /* clump size for extents overflow file */
++ u_int32_t drCTClpSiz; /* clump size for catalog file */
++ u_int16_t drNmRtDirs; /* number of directories in root folder */
++ u_int32_t drFilCnt; /* number of files in volume */
++ u_int32_t drDirCnt; /* number of directories in volume */
++ u_int32_t drFndrInfo[8]; /* information used by the Finder */
++ u_int16_t drEmbedSigWord; /* embedded volume signature (formerly drVCSize) */
++ HFSExtentDescriptor drEmbedExtent; /* embedded volume location and size (formerly drVBMCSize and drCtlCSize) */
++ u_int32_t drXTFlSize; /* size of extents overflow file */
++ HFSExtentRecord drXTExtRec; /* extent record for extents overflow file */
++ u_int32_t drCTFlSize; /* size of catalog file */
++ HFSExtentRecord drCTExtRec; /* extent record for catalog file */
++}PACKED_S;
++typedef struct HFSMasterDirectoryBlock HFSMasterDirectoryBlock;
++
++
++#ifdef __APPLE_API_UNSTABLE
++#define SET_HFS_TEXT_ENCODING(hint) \
++ (0x656e6300 | ((hint) & 0xff))
++#define GET_HFS_TEXT_ENCODING(hint) \
++ (((hint) & 0xffffff00) == 0x656e6300 ? (hint) & 0x000000ff : 0xffffffffU)
++#endif /* __APPLE_API_UNSTABLE */
++
++
++/* HFS Plus Volume Header - 512 bytes */
++/* Stored at sector #2 (3rd sector) and second-to-last sector. */
++struct HFSPlusVolumeHeader {
++ u_int16_t signature; /* == kHFSPlusSigWord */
++ u_int16_t version; /* == kHFSPlusVersion */
++ u_int32_t attributes; /* volume attributes */
++ u_int32_t lastMountedVersion; /* implementation version which last mounted volume */
++ u_int32_t journalInfoBlock; /* block addr of journal info (if volume is journaled, zero otherwise) */
++
++ u_int32_t createDate; /* date and time of volume creation */
++ u_int32_t modifyDate; /* date and time of last modification */
++ u_int32_t backupDate; /* date and time of last backup */
++ u_int32_t checkedDate; /* date and time of last disk check */
++
++ u_int32_t fileCount; /* number of files in volume */
++ u_int32_t folderCount; /* number of directories in volume */
++
++ u_int32_t blockSize; /* size (in bytes) of allocation blocks */
++ u_int32_t totalBlocks; /* number of allocation blocks in volume (includes this header and VBM*/
++ u_int32_t freeBlocks; /* number of unused allocation blocks */
++
++ u_int32_t nextAllocation; /* start of next allocation search */
++ u_int32_t rsrcClumpSize; /* default resource fork clump size */
++ u_int32_t dataClumpSize; /* default data fork clump size */
++ u_int32_t nextCatalogID; /* next unused catalog node ID */
++
++ u_int32_t writeCount; /* volume write count */
++ u_int64_t encodingsBitmap; /* which encodings have been use on this volume */
++
++ u_int8_t finderInfo[32]; /* information used by the Finder */
++
++ HFSPlusForkData allocationFile; /* allocation bitmap file */
++ HFSPlusForkData extentsFile; /* extents B-tree file */
++ HFSPlusForkData catalogFile; /* catalog B-tree file */
++ HFSPlusForkData attributesFile; /* extended attributes B-tree file */
++ HFSPlusForkData startupFile; /* boot file (secondary loader) */
++}PACKED_S;
++typedef struct HFSPlusVolumeHeader HFSPlusVolumeHeader;
++
++
++/* B-tree structures */
++
++enum BTreeKeyLimits{
++ kMaxKeyLength = 520
++}PACKED_S;
++
++union BTreeKey{
++ u_int8_t length8;
++ u_int16_t length16;
++ u_int8_t rawData [kMaxKeyLength+2];
++}PACKED_S;
++typedef union BTreeKey BTreeKey;
++
++/* BTNodeDescriptor -- Every B-tree node starts with these fields. */
++struct BTNodeDescriptor {
++ u_int32_t fLink; /* next node at this level*/
++ u_int32_t bLink; /* previous node at this level*/
++ int8_t kind; /* kind of node (leaf, index, header, map)*/
++ u_int8_t height; /* zero for header, map; child is one more than parent*/
++ u_int16_t numRecords; /* number of records in this node*/
++ u_int16_t reserved; /* reserved - initialized as zero */
++}PACKED_S;
++typedef struct BTNodeDescriptor BTNodeDescriptor;
++
++/* Constants for BTNodeDescriptor kind */
++enum {
++ kBTLeafNode = -1,
++ kBTIndexNode = 0,
++ kBTHeaderNode = 1,
++ kBTMapNode = 2
++}PACKED_S;
++
++/* BTHeaderRec -- The first record of a B-tree header node */
++struct BTHeaderRec {
++ u_int16_t treeDepth; /* maximum height (usually leaf nodes) */
++ u_int32_t rootNode; /* node number of root node */
++ u_int32_t leafRecords; /* number of leaf records in all leaf nodes */
++ u_int32_t firstLeafNode; /* node number of first leaf node */
++ u_int32_t lastLeafNode; /* node number of last leaf node */
++ u_int16_t nodeSize; /* size of a node, in bytes */
++ u_int16_t maxKeyLength; /* reserved */
++ u_int32_t totalNodes; /* total number of nodes in tree */
++ u_int32_t freeNodes; /* number of unused (free) nodes in tree */
++ u_int16_t reserved1; /* unused */
++ u_int32_t clumpSize; /* reserved */
++ u_int8_t btreeType; /* reserved */
++ u_int8_t keyCompareType; /* Key string Comparison Type */
++ u_int32_t attributes; /* persistent attributes about the tree */
++ u_int32_t reserved3[16]; /* reserved */
++}PACKED_S;
++typedef struct BTHeaderRec BTHeaderRec;
++
++/* Constants for BTHeaderRec attributes */
++enum {
++ kBTBadCloseMask = 0x00000001, /* reserved */
++ kBTBigKeysMask = 0x00000002, /* key length field is 16 bits */
++ kBTVariableIndexKeysMask = 0x00000004 /* keys in index nodes are variable length */
++}PACKED_S;
++
++
++/* Catalog Key Name Comparison Type */
++enum {
++ kHFSCaseFolding = 0xCF, /* case folding (case-insensitive) */
++ kHFSBinaryCompare = 0xBC /* binary compare (case-sensitive) */
++}PACKED_S;
++
++/* JournalInfoBlock - Structure that describes where our journal lives */
++struct JournalInfoBlock {
++ u_int32_t flags;
++ u_int32_t device_signature[8]; // signature used to locate our device.
++ u_int64_t offset; // byte offset to the journal on the device
++ u_int64_t size; // size in bytes of the journal
++ u_int32_t reserved[32];
++}PACKED_S;
++typedef struct JournalInfoBlock JournalInfoBlock;
++
++enum {
++ kJIJournalInFSMask = 0x00000001,
++ kJIJournalOnOtherDeviceMask = 0x00000002,
++ kJIJournalNeedInitMask = 0x00000004
++}PACKED_S;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* __HFS_FORMAT__ */
+--- /dev/null
++++ b/include/hfs/hfs_mount.h
+@@ -0,0 +1,78 @@
++/*
++ * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
++ *
++ * @APPLE_LICENSE_HEADER_START@
++ *
++ * The contents of this file constitute Original Code as defined in and
++ * are subject to the Apple Public Source License Version 1.1 (the
++ * "License"). You may not use this file except in compliance with the
++ * License. Please obtain a copy of the License at
++ * http://www.apple.com/publicsource and read it before using this file.
++ *
++ * This Original Code and all software distributed under the License are
++ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
++ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
++ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
++ * License for the specific language governing rights and limitations
++ * under the License.
++ *
++ * @APPLE_LICENSE_HEADER_END@
++ */
++/*
++ * Copyright (c) 1997-2002 Apple Computer, Inc. All Rights Reserved
++ *
++ */
++
++#ifndef _HFS_MOUNT_H_
++#define _HFS_MOUNT_H_
++
++#include <sys/appleapiopts.h>
++
++#include <sys/mount.h>
++#include <sys/time.h>
++
++/*
++ * Arguments to mount HFS-based filesystems
++ */
++
++#define OVERRIDE_UNKNOWN_PERMISSIONS 0
++
++#define UNKNOWNUID ((uid_t)99)
++#define UNKNOWNGID ((gid_t)99)
++#define UNKNOWNPERMISSIONS (S_IRWXU | S_IROTH | S_IXOTH) /* 705 */
++
++#ifdef __APPLE_API_UNSTABLE
++struct hfs_mount_args {
++#ifndef KERNEL
++ char *fspec; /* block special device to mount */
++#endif
++ uid_t hfs_uid; /* uid that owns hfs files (standard HFS only) */
++ gid_t hfs_gid; /* gid that owns hfs files (standard HFS only) */
++ mode_t hfs_mask; /* mask to be applied for hfs perms (standard HFS only) */
++ u_int32_t hfs_encoding; /* encoding for this volume (standard HFS only) */
++ struct timezone hfs_timezone; /* user time zone info (standard HFS only) */
++ int flags; /* mounting flags, see below */
++ int journal_tbuffer_size; /* size in bytes of the journal transaction buffer */
++ int journal_flags; /* flags to pass to journal_open/create */
++ int journal_disable; /* don't use journaling (potentially dangerous) */
++};
++
++#define HFSFSMNT_NOXONFILES 0x1 /* disable execute permissions for files */
++#define HFSFSMNT_WRAPPER 0x2 /* mount HFS wrapper (if it exists) */
++#define HFSFSMNT_EXTENDED_ARGS 0x4 /* indicates new fields after "flags" are valid */
++
++/*
++ * Sysctl values for HFS
++ */
++#define HFS_ENCODINGBIAS 1 /* encoding matching CJK bias */
++#define HFS_EXTEND_FS 2
++#define HFS_ENCODINGHINT 3 /* guess encoding for string */
++#define HFS_ENABLE_JOURNALING 0x082969
++#define HFS_DISABLE_JOURNALING 0x031272
++#define HFS_GET_JOURNAL_INFO 0x6a6e6c69
++#define HFS_SET_PKG_EXTENSIONS 0x121031
++
++#endif /* __APPLE_API_UNSTABLE */
++
++#endif /* ! _HFS_MOUNT_H_ */
+--- /dev/null
++++ b/include/sys/appleapiopts.h
+@@ -0,0 +1,52 @@
++/*
++ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
++ *
++ * @APPLE_LICENSE_HEADER_START@
++ *
++ * The contents of this file constitute Original Code as defined in and
++ * are subject to the Apple Public Source License Version 1.1 (the
++ * "License"). You may not use this file except in compliance with the
++ * License. Please obtain a copy of the License at
++ * http://www.apple.com/publicsource and read it before using this file.
++ *
++ * This Original Code and all software distributed under the License are
++ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
++ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
++ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
++ * License for the specific language governing rights and limitations
++ * under the License.
++ *
++ * @APPLE_LICENSE_HEADER_END@
++ */
++
++#ifndef __SYS_APPLEAPIOPTS_H__
++#define __SYS_APPLEAPIOPTS_H__
++
++
++#ifndef __APPLE_API_STANDARD
++#define __APPLE_API_STANDARD
++#endif /* __APPLE_API_STANDARD */
++
++#ifndef __APPLE_API_STABLE
++#define __APPLE_API_STABLE
++#endif /* __APPLE_API_STABLE */
++
++#ifndef __APPLE_API_STRICT_CONFORMANCE
++
++#ifndef __APPLE_API_EVOLVING
++#define __APPLE_API_EVOLVING
++#endif /* __APPLE_API_EVOLVING */
++
++#ifndef __APPLE_API_UNSTABLE
++#define __APPLE_API_UNSTABLE
++#endif /* __APPLE_API_UNSTABLE */
++
++#ifndef __APPLE_API_OBSOLETE
++#define __APPLE_API_OBSOLETE
++#endif /* __APPLE_API_OBSOLETE */
++
++#endif /* __APPLE_API_STRICT_CONFORMANCE */
++
++#endif /* __SYS_APPLEAPIOPTS_H__ */
++
diff --git a/external/subpack/utils/hfsprogs/patches/0004-Fix-compilation-on-64-bit-arches.patch b/external/subpack/utils/hfsprogs/patches/0004-Fix-compilation-on-64-bit-arches.patch
new file mode 100644
index 0000000..27912ef
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0004-Fix-compilation-on-64-bit-arches.patch
@@ -0,0 +1,123 @@
+From: =?UTF-8?q?Rog=C3=A9rio=20Brito?= <rbrito@ime.usp.br>
+Date: Thu, 24 Oct 2013 01:11:21 -0200
+Subject: Fix compilation on 64-bit arches
+
+---
+ fsck_hfs.tproj/dfalib/BTreePrivate.h | 5 ++++-
+ fsck_hfs.tproj/dfalib/SControl.c | 8 ++++----
+ fsck_hfs.tproj/dfalib/SVerify1.c | 14 +++++++-------
+ fsck_hfs.tproj/dfalib/hfs_endian.c | 2 +-
+ 4 files changed, 16 insertions(+), 13 deletions(-)
+
+--- a/fsck_hfs.tproj/dfalib/BTreePrivate.h
++++ b/fsck_hfs.tproj/dfalib/BTreePrivate.h
+@@ -104,6 +104,9 @@ typedef enum {
+
+ ///////////////////////////////////// Types /////////////////////////////////////
+
++// Forward declaration from Scavenger.h
++struct BTreeExtensionsRec;
++
+ typedef struct BTreeControlBlock { // fields specific to BTree CBs
+
+ UInt8 keyCompareType; /* Key string Comparison Type */
+@@ -144,7 +147,7 @@ typedef struct BTreeControlBlock { /
+ UInt32 numPossibleHints; // Looks like a formated hint
+ UInt32 numValidHints; // Hint used to find correct record.
+
+- UInt32 refCon; // Used by DFA to point to private data.
++ struct BTreeExtensionsRec *refCon; // Used by DFA to point to private data.
+ SFCB *fcbPtr; // fcb of btree file
+
+ } BTreeControlBlock, *BTreeControlBlockPtr;
+--- a/fsck_hfs.tproj/dfalib/SControl.c
++++ b/fsck_hfs.tproj/dfalib/SControl.c
+@@ -1034,7 +1034,7 @@ static int ScavTerm( SGlobPtr GPtr )
+ btcbP = (BTreeControlBlock*)fcbP->fcbBtree;
+ if ( btcbP != nil)
+ {
+- if( btcbP->refCon != (UInt32)nil )
++ if( btcbP->refCon != nil )
+ {
+ if(((BTreeExtensionsRec*)btcbP->refCon)->BTCBMPtr != nil)
+ {
+@@ -1043,13 +1043,13 @@ static int ScavTerm( SGlobPtr GPtr )
+ }
+ DisposeMemory( (Ptr)btcbP->refCon );
+ err = MemError();
+- btcbP->refCon = (UInt32)nil;
++ btcbP->refCon = nil;
+ }
+
+ fcbP = GPtr->calculatedCatalogFCB; // release catalog BTree bit map
+ btcbP = (BTreeControlBlock*)fcbP->fcbBtree;
+
+- if( btcbP->refCon != (UInt32)nil )
++ if( btcbP->refCon != nil )
+ {
+ if(((BTreeExtensionsRec*)btcbP->refCon)->BTCBMPtr != nil)
+ {
+@@ -1058,7 +1058,7 @@ static int ScavTerm( SGlobPtr GPtr )
+ }
+ DisposeMemory( (Ptr)btcbP->refCon );
+ err = MemError();
+- btcbP->refCon = (UInt32)nil;
++ btcbP->refCon = nil;
+ }
+ }
+ }
+--- a/fsck_hfs.tproj/dfalib/SVerify1.c
++++ b/fsck_hfs.tproj/dfalib/SVerify1.c
+@@ -789,8 +789,8 @@ OSErr CreateExtentsBTreeControlBlock( SG
+ //
+ // set up our DFA extended BTCB area. Will we have enough memory on all HFS+ volumes.
+ //
+- btcb->refCon = (UInt32) AllocateClearMemory( sizeof(BTreeExtensionsRec) ); // allocate space for our BTCB extensions
+- if ( btcb->refCon == (UInt32) nil ) {
++ btcb->refCon = AllocateClearMemory( sizeof(BTreeExtensionsRec) ); // allocate space for our BTCB extensions
++ if ( btcb->refCon == nil ) {
+ err = R_NoMem;
+ goto exit;
+ }
+@@ -1144,8 +1144,8 @@ OSErr CreateCatalogBTreeControlBlock( SG
+ // set up our DFA extended BTCB area. Will we have enough memory on all HFS+ volumes.
+ //
+
+- btcb->refCon = (UInt32) AllocateClearMemory( sizeof(BTreeExtensionsRec) ); // allocate space for our BTCB extensions
+- if ( btcb->refCon == (UInt32)nil ) {
++ btcb->refCon = AllocateClearMemory( sizeof(BTreeExtensionsRec) ); // allocate space for our BTCB extensions
++ if ( btcb->refCon == nil ) {
+ err = R_NoMem;
+ goto exit;
+ }
+@@ -1779,8 +1779,8 @@ OSErr CreateAttributesBTreeControlBlock(
+ //
+ // set up our DFA extended BTCB area. Will we have enough memory on all HFS+ volumes.
+ //
+- btcb->refCon = (UInt32) AllocateClearMemory( sizeof(BTreeExtensionsRec) ); // allocate space for our BTCB extensions
+- if ( btcb->refCon == (UInt32)nil ) {
++ btcb->refCon = AllocateClearMemory( sizeof(BTreeExtensionsRec) ); // allocate space for our BTCB extensions
++ if ( btcb->refCon == nil ) {
+ err = R_NoMem;
+ goto exit;
+ }
+@@ -1793,7 +1793,7 @@ OSErr CreateAttributesBTreeControlBlock(
+ }
+ else
+ {
+- if ( btcb->refCon == (UInt32)nil ) {
++ if ( btcb->refCon == nil ) {
+ err = R_NoMem;
+ goto exit;
+ }
+--- a/fsck_hfs.tproj/dfalib/hfs_endian.c
++++ b/fsck_hfs.tproj/dfalib/hfs_endian.c
+@@ -437,7 +437,7 @@ hfs_swap_HFSPlusBTInternalNode (
+ BTNodeDescriptor *srcDesc = src->buffer;
+ UInt16 *srcOffs = (UInt16 *)((char *)src->buffer + (src->blockSize - (srcDesc->numRecords * sizeof (UInt16))));
+ char *nextRecord; /* Points to start of record following current one */
+- UInt32 i;
++ int i;
+ UInt32 j;
+
+ if (fileID == kHFSExtentsFileID) {
diff --git a/external/subpack/utils/hfsprogs/patches/0005-Remove-Apple-specific-p-from-strings.patch b/external/subpack/utils/hfsprogs/patches/0005-Remove-Apple-specific-p-from-strings.patch
new file mode 100644
index 0000000..81714e9
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0005-Remove-Apple-specific-p-from-strings.patch
@@ -0,0 +1,287 @@
+From: =?UTF-8?q?Rog=C3=A9rio=20Brito?= <rbrito@ime.usp.br>
+Date: Thu, 24 Oct 2013 01:11:21 -0200
+Subject: Remove (Apple-specific?) \p from strings
+
+Modify the way that debug messages are sent to the user, by eliminating one
+character of them.
+---
+ fsck_hfs.tproj/dfalib/BTreeTreeOps.c | 48 ++++++++++++++++++------------------
+ fsck_hfs.tproj/dfalib/SBTree.c | 14 +++++------
+ 2 files changed, 31 insertions(+), 31 deletions(-)
+
+--- a/fsck_hfs.tproj/dfalib/BTreeTreeOps.c
++++ b/fsck_hfs.tproj/dfalib/BTreeTreeOps.c
+@@ -223,7 +223,7 @@ OSStatus SearchTree (BTreeControlBlockPt
+ //
+ if (curNodeNum == 0)
+ {
+-// Panic("\pSearchTree: curNodeNum is zero!");
++ Panic("SearchTree: curNodeNum is zero!");
+ err = fsBTInvalidNodeErr;
+ goto ErrorExit;
+ }
+@@ -433,7 +433,7 @@ OSStatus InsertLevel (BTreeControlBlockP
+ M_ExitOnError (err);
+
+ if ( DEBUG_BUILD && updateParent && newRoot )
+- DebugStr("\p InsertLevel: New root from primary key, update from secondary key...");
++ DebugStr("InsertLevel: New root from primary key, update from secondary key...");
+ }
+
+ //////////////////////// Update Parent(s) ///////////////////////////////
+@@ -448,7 +448,7 @@ OSStatus InsertLevel (BTreeControlBlockP
+
+ secondaryKey = nil;
+
+- PanicIf ( (level == btreePtr->treeDepth), "\p InsertLevel: unfinished insert!?");
++ PanicIf ( (level == btreePtr->treeDepth), "InsertLevel: unfinished insert!?");
+
+ ++level;
+
+@@ -456,7 +456,7 @@ OSStatus InsertLevel (BTreeControlBlockP
+ index = treePathTable [level].index;
+ parentNodeNum = treePathTable [level].node;
+
+- PanicIf ( parentNodeNum == 0, "\p InsertLevel: parent node is zero!?");
++ PanicIf ( parentNodeNum == 0, "InsertLevel: parent node is zero!?");
+
+ err = GetNode (btreePtr, parentNodeNum, &parentNode); // released as target node in next level up
+ M_ExitOnError (err);
+@@ -470,7 +470,7 @@ OSStatus InsertLevel (BTreeControlBlockP
+ {
+ //¥¥Êdebug: check if ptr == targetNodeNum
+ GetRecordByIndex (btreePtr, parentNode.buffer, index, &keyPtr, &recPtr, &recSize);
+- PanicIf( (*(UInt32 *) recPtr) != targetNodeNum, "\p InsertLevel: parent ptr doesn't match target node!");
++ PanicIf( (*(UInt32 *) recPtr) != targetNodeNum, "InsertLevel: parent ptr doesn't match target node!");
+
+ // need to delete and re-insert this parent key/ptr
+ // we delete it here and it gets re-inserted in the
+@@ -532,7 +532,7 @@ ErrorExit:
+ (void) ReleaseNode (btreePtr, targetNode);
+ (void) ReleaseNode (btreePtr, &siblingNode);
+
+- Panic ("\p InsertLevel: an error occured!");
++ Panic ("InsertLevel: an error occured!");
+
+ return err;
+
+@@ -566,7 +566,7 @@ static OSErr InsertNode (BTreeControlBlo
+
+ *rootSplit = false;
+
+- PanicIf ( targetNode->buffer == siblingNode->buffer, "\p InsertNode: targetNode == siblingNode, huh?");
++ PanicIf ( targetNode->buffer == siblingNode->buffer, "InsertNode: targetNode == siblingNode, huh?");
+
+ leftNodeNum = ((NodeDescPtr) targetNode->buffer)->bLink;
+ rightNodeNum = ((NodeDescPtr) targetNode->buffer)->fLink;
+@@ -606,7 +606,7 @@ static OSErr InsertNode (BTreeControlBlo
+
+ if ( leftNodeNum > 0 )
+ {
+- PanicIf ( siblingNode->buffer != nil, "\p InsertNode: siblingNode already aquired!");
++ PanicIf ( siblingNode->buffer != nil, "InsertNode: siblingNode already aquired!");
+
+ if ( siblingNode->buffer == nil )
+ {
+@@ -614,7 +614,7 @@ static OSErr InsertNode (BTreeControlBlo
+ M_ExitOnError (err);
+ }
+
+- PanicIf ( ((NodeDescPtr) siblingNode->buffer)->fLink != nodeNum, "\p InsertNode, RotateLeft: invalid sibling link!" );
++ PanicIf ( ((NodeDescPtr) siblingNode->buffer)->fLink != nodeNum, "InsertNode, RotateLeft: invalid sibling link!" );
+
+ if ( !key->skipRotate ) // are rotates allowed?
+ {
+@@ -703,7 +703,7 @@ OSStatus DeleteTree (BTreeControlBlock
+
+ targetNodeNum = treePathTable[level].node;
+ targetNodePtr = targetNode->buffer;
+- PanicIf (targetNodePtr == nil, "\pDeleteTree: targetNode has nil buffer!");
++ PanicIf (targetNodePtr == nil, "DeleteTree: targetNode has nil buffer!");
+
+ DeleteRecord (btreePtr, targetNodePtr, index);
+
+@@ -797,7 +797,7 @@ OSStatus DeleteTree (BTreeControlBlock
+
+ //¥¥Êdebug: check if ptr == targetNodeNum
+ GetRecordByIndex (btreePtr, parentNode.buffer, index, &keyPtr, &recPtr, &recSize);
+- PanicIf( (*(UInt32 *) recPtr) != targetNodeNum, "\p DeleteTree: parent ptr doesn't match targetNodeNum!!");
++ PanicIf( (*(UInt32 *) recPtr) != targetNodeNum, " DeleteTree: parent ptr doesn't match targetNodeNum!!");
+
+ // need to delete and re-insert this parent key/ptr
+ DeleteRecord (btreePtr, parentNode.buffer, index);
+@@ -1018,7 +1018,7 @@ static OSStatus RotateLeft (BTreeContro
+ keyPtr, keyLength, recPtr, recSize);
+ if ( !didItFit )
+ {
+- Panic ("\pRotateLeft: InsertKeyRecord (left) returned false!");
++ Panic ("RotateLeft: InsertKeyRecord (left) returned false!");
+ err = fsBTBadRotateErr;
+ goto ErrorExit;
+ }
+@@ -1031,7 +1031,7 @@ static OSStatus RotateLeft (BTreeContro
+ didItFit = RotateRecordLeft (btreePtr, leftNode, rightNode);
+ if ( !didItFit )
+ {
+- Panic ("\pRotateLeft: RotateRecordLeft returned false!");
++ Panic ("RotateLeft: RotateRecordLeft returned false!");
+ err = fsBTBadRotateErr;
+ goto ErrorExit;
+ }
+@@ -1048,7 +1048,7 @@ static OSStatus RotateLeft (BTreeContro
+ keyPtr, keyLength, recPtr, recSize);
+ if ( !didItFit )
+ {
+- Panic ("\pRotateLeft: InsertKeyRecord (right) returned false!");
++ Panic ("RotateLeft: InsertKeyRecord (right) returned false!");
+ err = fsBTBadRotateErr;
+ goto ErrorExit;
+ }
+@@ -1117,7 +1117,7 @@ static OSStatus SplitLeft (BTreeControl
+ right = rightNode->buffer;
+ left = leftNode->buffer;
+
+- PanicIf ( right->bLink != 0 && left == 0, "\p SplitLeft: left sibling missing!?" );
++ PanicIf ( right->bLink != 0 && left == 0, " SplitLeft: left sibling missing!?" );
+
+ //¥¥ type should be kLeafNode or kIndexNode
+
+@@ -1240,8 +1240,8 @@ static OSStatus AddNewRootNode (BTreeCon
+ Boolean didItFit;
+ UInt16 keyLength;
+
+- PanicIf (leftNode == nil, "\pAddNewRootNode: leftNode == nil");
+- PanicIf (rightNode == nil, "\pAddNewRootNode: rightNode == nil");
++ PanicIf (leftNode == nil, "AddNewRootNode: leftNode == nil");
++ PanicIf (rightNode == nil, "AddNewRootNode: rightNode == nil");
+
+
+ /////////////////////// Initialize New Root Node ////////////////////////////
+@@ -1264,7 +1264,7 @@ static OSStatus AddNewRootNode (BTreeCon
+ didItFit = InsertKeyRecord ( btreePtr, rootNode.buffer, 0, keyPtr, keyLength,
+ (UInt8 *) &rightNode->bLink, 4 );
+
+- PanicIf ( !didItFit, "\pAddNewRootNode:InsertKeyRecord failed for left index record");
++ PanicIf ( !didItFit, "AddNewRootNode:InsertKeyRecord failed for left index record");
+
+
+ //////////////////// Insert Right Node Index Record /////////////////////////
+@@ -1275,7 +1275,7 @@ static OSStatus AddNewRootNode (BTreeCon
+ didItFit = InsertKeyRecord ( btreePtr, rootNode.buffer, 1, keyPtr, keyLength,
+ (UInt8 *) &leftNode->fLink, 4 );
+
+- PanicIf ( !didItFit, "\pAddNewRootNode:InsertKeyRecord failed for right index record");
++ PanicIf ( !didItFit, "AddNewRootNode:InsertKeyRecord failed for right index record");
+
+
+ #if DEBUG_TREEOPS
+@@ -1355,7 +1355,7 @@ static OSStatus SplitRight (BTreeContro
+ }
+ rightPtr = rightNodePtr->buffer;
+
+- PanicIf ( leftPtr->fLink != 0 && rightPtr == 0, "\p SplitRight: right sibling missing!?" );
++ PanicIf ( leftPtr->fLink != 0 && rightPtr == 0, "SplitRight: right sibling missing!?" );
+
+ //¥¥ type should be kLeafNode or kIndexNode
+
+@@ -1557,7 +1557,7 @@ static OSStatus RotateRight (BTreeContr
+ keyPtr, keyLength, recPtr, recSize);
+ if ( !didItFit )
+ {
+- Panic ("\pRotateRight: InsertKeyRecord (left) returned false!");
++ Panic ("RotateRight: InsertKeyRecord (left) returned false!");
+ err = fsBTBadRotateErr;
+ goto ErrorExit;
+ }
+@@ -1572,7 +1572,7 @@ static OSStatus RotateRight (BTreeContr
+ didItFit = RotateRecordRight( btreePtr, leftNodePtr, rightNodePtr );
+ if ( !didItFit )
+ {
+- Panic ("\pRotateRight: RotateRecordRight returned false!");
++ Panic ("RotateRight: RotateRecordRight returned false!");
+ err = fsBTBadRotateErr;
+ goto ErrorExit;
+ }
+@@ -1583,7 +1583,7 @@ static OSStatus RotateRight (BTreeContr
+ keyPtr, keyLength, recPtr, recSize);
+ if ( !didItFit )
+ {
+- Panic ("\pRotateRight: InsertKeyRecord (left) returned false!");
++ Panic ("RotateRight: InsertKeyRecord (left) returned false!");
+ err = fsBTBadRotateErr;
+ goto ErrorExit;
+ }
+@@ -1607,7 +1607,7 @@ static OSStatus RotateRight (BTreeContr
+ keyPtr, keyLength, recPtr, recSize);
+ if ( !didItFit )
+ {
+- Panic ("\pRotateRight: InsertKeyRecord (right) returned false!");
++ Panic ("RotateRight: InsertKeyRecord (right) returned false!");
+ err = fsBTBadRotateErr;
+ goto ErrorExit;
+ }
+--- a/fsck_hfs.tproj/dfalib/SBTree.c
++++ b/fsck_hfs.tproj/dfalib/SBTree.c
+@@ -103,7 +103,7 @@ OSErr SearchBTreeRecord(SFCB *fcb, const
+ CopyMemory(&resultIterator->key, foundKey, CalcKeySize(btcb, &resultIterator->key)); //¥¥ warning, this could overflow user's buffer!!!
+
+ if ( DEBUG_BUILD && !ValidHFSRecord(data, btcb, *dataSize) )
+- DebugStr("\pSearchBTreeRecord: bad record?");
++ DebugStr("SearchBTreeRecord: bad record?");
+ }
+
+ ErrorExit:
+@@ -211,7 +211,7 @@ OSErr GetBTreeRecord(SFCB *fcb, SInt16 s
+ CopyMemory(&iterator->key, key, CalcKeySize(btcb, &iterator->key)); //¥¥ warning, this could overflow user's buffer!!!
+
+ if ( DEBUG_BUILD && !ValidHFSRecord(data, btcb, *dataSize) )
+- DebugStr("\pGetBTreeRecord: bad record?");
++ DebugStr("GetBTreeRecord: bad record?");
+
+ }
+
+@@ -243,7 +243,7 @@ OSErr InsertBTreeRecord(SFCB *fcb, const
+ CopyMemory(key, &iterator.key, CalcKeySize(btcb, (BTreeKey *) key)); //¥¥ should we range check against maxkeylen?
+
+ if ( DEBUG_BUILD && !ValidHFSRecord(data, btcb, dataSize) )
+- DebugStr("\pInsertBTreeRecord: bad record?");
++ DebugStr("InsertBTreeRecord: bad record?");
+
+ result = BTInsertRecord( fcb, &iterator, &btRecord, dataSize );
+
+@@ -305,7 +305,7 @@ OSErr ReplaceBTreeRecord(SFCB *fcb, cons
+ CopyMemory(key, &iterator.key, CalcKeySize(btcb, (BTreeKey *) key)); //¥¥ should we range check against maxkeylen?
+
+ if ( DEBUG_BUILD && !ValidHFSRecord(newData, btcb, dataSize) )
+- DebugStr("\pReplaceBTreeRecord: bad record?");
++ DebugStr("ReplaceBTreeRecord: bad record?");
+
+ result = BTReplaceRecord( fcb, &iterator, &btRecord, dataSize );
+
+@@ -344,7 +344,7 @@ SetEndOfForkProc ( SFCB *filePtr, FSSize
+ else
+ {
+ if ( DEBUG_BUILD )
+- DebugStr("\pSetEndOfForkProc: minEOF is smaller than current size!");
++ DebugStr("SetEndOfForkProc: minEOF is smaller than current size!");
+ return -1;
+ }
+
+@@ -370,7 +370,7 @@ SetEndOfForkProc ( SFCB *filePtr, FSSize
+ // Make sure we got at least as much space as we needed
+ //
+ if (filePtr->fcbLogicalSize < minEOF) {
+- Panic("\pSetEndOfForkProc: disk too full to extend B-tree file");
++ Panic("SetEndOfForkProc: disk too full to extend B-tree file");
+ return dskFulErr;
+ }
+
+@@ -442,7 +442,7 @@ static OSErr CheckBTreeKey(const BTreeKe
+ if ( (keyLen < 6) || (keyLen > btcb->maxKeyLength) )
+ {
+ if ( DEBUG_BUILD )
+- DebugStr("\pCheckBTreeKey: bad key length!");
++ DebugStr("CheckBTreeKey: bad key length!");
+ return fsBTInvalidKeyLengthErr;
+ }
+
diff --git a/external/subpack/utils/hfsprogs/patches/0006-Adjust-types-for-printing.patch b/external/subpack/utils/hfsprogs/patches/0006-Adjust-types-for-printing.patch
new file mode 100644
index 0000000..d4bb88b
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0006-Adjust-types-for-printing.patch
@@ -0,0 +1,33 @@
+From: =?UTF-8?q?Rog=C3=A9rio=20Brito?= <rbrito@ime.usp.br>
+Date: Thu, 24 Oct 2013 01:11:21 -0200
+Subject: Adjust types for printing
+
+Try to address the issues of a given integral type having different sizes
+in 32 and 64-bit architectures.
+---
+ fsck_hfs.tproj/dfalib/SControl.c | 2 +-
+ fsck_hfs.tproj/dfalib/hfs_endian.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fsck_hfs.tproj/dfalib/SControl.c
++++ b/fsck_hfs.tproj/dfalib/SControl.c
+@@ -776,7 +776,7 @@ static int ScavSetUp( SGlob *GPtr)
+ pointer = (ScavStaticStructures *) AllocateClearMemory( sizeof(ScavStaticStructures) );
+ if ( pointer == nil ) {
+ if ( GPtr->logLevel >= kDebugLog ) {
+- printf( "\t error %d - could not allocate %ld bytes of memory \n",
++ printf( "\t error %d - could not allocate %i bytes of memory \n",
+ R_NoMem, sizeof(ScavStaticStructures) );
+ }
+ return( R_NoMem );
+--- a/fsck_hfs.tproj/dfalib/hfs_endian.c
++++ b/fsck_hfs.tproj/dfalib/hfs_endian.c
+@@ -563,7 +563,7 @@ hfs_swap_HFSPlusBTInternalNode (
+ /* Make sure name length is consistent with key length */
+ if (keyLength < sizeof(srcKey->parentID) + sizeof(srcKey->nodeName.length) +
+ srcKey->nodeName.length*sizeof(srcKey->nodeName.unicode[0])) {
+- if (debug) printf("hfs_swap_HFSPlusBTInternalNode: catalog record #%d keyLength=%d expected=%lu\n",
++ if (debug) printf("hfs_swap_HFSPlusBTInternalNode: catalog record #%d keyLength=%d expected=%i\n",
+ srcDesc->numRecords-i, keyLength, sizeof(srcKey->parentID) + sizeof(srcKey->nodeName.length) +
+ srcKey->nodeName.length*sizeof(srcKey->nodeName.unicode[0]));
+ WriteError(fcb->fcbVolume->vcbGPtr, E_KeyLen, fcb->fcbFileID, src->blockNum);
diff --git a/external/subpack/utils/hfsprogs/patches/0007-Fix-path-for-HFS-wrapper-block.patch b/external/subpack/utils/hfsprogs/patches/0007-Fix-path-for-HFS-wrapper-block.patch
new file mode 100644
index 0000000..4cfab48
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0007-Fix-path-for-HFS-wrapper-block.patch
@@ -0,0 +1,21 @@
+From: =?UTF-8?q?Rog=C3=A9rio=20Brito?= <rbrito@ime.usp.br>
+Date: Thu, 24 Oct 2013 01:11:21 -0200
+Subject: Fix path for HFS wrapper block
+
+Fix the installation of the HFS wrapper block to be compliant in Linux
+systems (since it is arch independent).
+---
+ newfs_hfs.tproj/makehfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/newfs_hfs.tproj/makehfs.c
++++ b/newfs_hfs.tproj/makehfs.c
+@@ -70,7 +70,7 @@ extern Boolean _CFStringGetFileSystemRep
+ #include "readme.h"
+
+
+-#define HFS_BOOT_DATA "/usr/share/misc/hfsbootdata"
++#define HFS_BOOT_DATA "/usr/share/hfsprogs/hfsbootdata"
+
+ #define HFS_JOURNAL_FILE ".journal"
+ #define HFS_JOURNAL_INFO ".journal_info_block"
diff --git a/external/subpack/utils/hfsprogs/patches/0008-Provide-command-line-option-a.patch b/external/subpack/utils/hfsprogs/patches/0008-Provide-command-line-option-a.patch
new file mode 100644
index 0000000..26b94ab
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0008-Provide-command-line-option-a.patch
@@ -0,0 +1,38 @@
+From: =?UTF-8?q?Rog=C3=A9rio=20Brito?= <rbrito@ime.usp.br>
+Date: Thu, 24 Oct 2013 01:11:21 -0200
+Subject: Provide command line option -a
+
+Create a new command line option (-a) for the fsck.hfsplus that has the same
+behavior that the -p option has, for greater compatibility with other tools.
+---
+ fsck_hfs.tproj/fsck_hfs.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/fsck_hfs.tproj/fsck_hfs.c
++++ b/fsck_hfs.tproj/fsck_hfs.c
+@@ -104,7 +104,7 @@ main(argc, argv)
+ else
+ progname = *argv;
+
+- while ((ch = getopt(argc, argv, "c:D:dfglm:npqruy")) != EOF) {
++ while ((ch = getopt(argc, argv, "c:D:dfglm:napqruy")) != EOF) {
+ switch (ch) {
+ case 'c':
+ /* Cache size to use in fsck_hfs */
+@@ -169,6 +169,7 @@ main(argc, argv)
+ yflag = 0;
+ break;
+
++ case 'a':
+ case 'p':
+ preen++;
+ break;
+@@ -572,7 +573,7 @@ usage()
+ (void) fprintf(stderr, " l = live fsck (lock down and test-only)\n");
+ (void) fprintf(stderr, " m arg = octal mode used when creating lost+found directory \n");
+ (void) fprintf(stderr, " n = assume a no response \n");
+- (void) fprintf(stderr, " p = just fix normal inconsistencies \n");
++ (void) fprintf(stderr, " p, a = just fix normal inconsistencies \n");
+ (void) fprintf(stderr, " q = quick check returns clean, dirty, or failure \n");
+ (void) fprintf(stderr, " r = rebuild catalog btree \n");
+ (void) fprintf(stderr, " u = usage \n");
diff --git a/external/subpack/utils/hfsprogs/patches/0009-Rename-dprintf-to-dbg_printf.patch b/external/subpack/utils/hfsprogs/patches/0009-Rename-dprintf-to-dbg_printf.patch
new file mode 100644
index 0000000..a1a2b24
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0009-Rename-dprintf-to-dbg_printf.patch
@@ -0,0 +1,179 @@
+From: =?UTF-8?q?Rog=C3=A9rio=20Brito?= <rbrito@ime.usp.br>
+Date: Thu, 24 Oct 2013 01:11:21 -0200
+Subject: Rename dprintf to dbg_printf
+
+---
+ fsck_hfs.tproj/dfalib/SRepair.c | 18 +++++++++---------
+ fsck_hfs.tproj/dfalib/SVerify1.c | 6 +++---
+ fsck_hfs.tproj/fsck_debug.c | 10 +++++-----
+ fsck_hfs.tproj/fsck_debug.h | 10 +++++-----
+ 4 files changed, 22 insertions(+), 22 deletions(-)
+
+--- a/fsck_hfs.tproj/dfalib/SRepair.c
++++ b/fsck_hfs.tproj/dfalib/SRepair.c
+@@ -1825,13 +1825,13 @@ static OSErr FixAttrSize(SGlobPtr GPtr,
+ result = BTSearchRecord(GPtr->calculatedAttributesFCB, &iterator,
+ kInvalidMRUCacheKey, &btRecord, &recSize, &iterator);
+ if (result) {
+- dprintf (d_error|d_xattr, "%s: Cannot find attribute record (err = %d)\n", __FUNCTION__, result);
++ dbg_printf (d_error|d_xattr, "%s: Cannot find attribute record (err = %d)\n", __FUNCTION__, result);
+ goto out;
+ }
+
+ /* We should only get record of type kHFSPlusAttrForkData */
+ if (record.recordType != kHFSPlusAttrForkData) {
+- dprintf (d_error|d_xattr, "%s: Record found is not attribute fork data\n", __FUNCTION__);
++ dbg_printf (d_error|d_xattr, "%s: Record found is not attribute fork data\n", __FUNCTION__);
+ result = btNotFound;
+ goto out;
+ }
+@@ -1862,7 +1862,7 @@ static OSErr FixAttrSize(SGlobPtr GPtr,
+ result = BTReplaceRecord(GPtr->calculatedAttributesFCB, &iterator,
+ &btRecord, recSize);
+ if (result) {
+- dprintf (d_error|d_xattr, "%s: Cannot replace attribute record (err=%d)\n", __FUNCTION__, result);
++ dbg_printf (d_error|d_xattr, "%s: Cannot replace attribute record (err=%d)\n", __FUNCTION__, result);
+ goto out;
+ }
+ }
+@@ -2058,7 +2058,7 @@ del_overflow_extents:
+
+ /* Delete the extent record */
+ err = DeleteBTreeRecord(GPtr->calculatedExtentsFCB, &extentKey);
+- dprintf (d_info, "%s: Deleting extent overflow for fileID=%u, forkType=%u, startBlock=%u\n", __FUNCTION__, fileID, forkType, foundStartBlock);
++ dbg_printf (d_info, "%s: Deleting extent overflow for fileID=%u, forkType=%u, startBlock=%u\n", __FUNCTION__, fileID, forkType, foundStartBlock);
+ if (err) {
+ goto create_symlink;
+ }
+@@ -3227,12 +3227,12 @@ static OSErr MoveExtent(SGlobPtr GPtr, E
+ &extentData, &recordSize, &foundExtentIndex);
+ foundLocation = extentsBTree;
+ if (err != noErr) {
+- dprintf (d_error|d_overlap, "%s: No matching extent record found in extents btree for fileID = %d (err=%d)\n", __FUNCTION__, extentInfo->fileID, err);
++ dbg_printf (d_error|d_overlap, "%s: No matching extent record found in extents btree for fileID = %d (err=%d)\n", __FUNCTION__, extentInfo->fileID, err);
+ goto out;
+ }
+ } else {
+ /* No more extents exist for this file */
+- dprintf (d_error|d_overlap, "%s: No matching extent record found for fileID = %d\n", __FUNCTION__, extentInfo->fileID);
++ dbg_printf (d_error|d_overlap, "%s: No matching extent record found for fileID = %d\n", __FUNCTION__, extentInfo->fileID);
+ goto out;
+ }
+ }
+@@ -3241,7 +3241,7 @@ static OSErr MoveExtent(SGlobPtr GPtr, E
+ err = CopyDiskBlocks(GPtr, extentInfo->startBlock, extentInfo->blockCount,
+ extentInfo->newStartBlock);
+ if (err != noErr) {
+- dprintf (d_error|d_overlap, "%s: Error in copying disk blocks for fileID = %d (err=%d)\n", __FUNCTION__, extentInfo->fileID, err);
++ dbg_printf (d_error|d_overlap, "%s: Error in copying disk blocks for fileID = %d (err=%d)\n", __FUNCTION__, extentInfo->fileID, err);
+ goto out;
+ }
+
+@@ -3260,7 +3260,7 @@ static OSErr MoveExtent(SGlobPtr GPtr, E
+
+ }
+ if (err != noErr) {
+- dprintf (d_error|d_overlap, "%s: Error in updating extent record for fileID = %d (err=%d)\n", __FUNCTION__, extentInfo->fileID, err);
++ dbg_printf (d_error|d_overlap, "%s: Error in updating extent record for fileID = %d (err=%d)\n", __FUNCTION__, extentInfo->fileID, err);
+ goto out;
+ }
+
+@@ -3491,7 +3491,7 @@ static OSErr SearchExtentInAttributeBT(S
+ result = BTSearchRecord(GPtr->calculatedAttributesFCB, &iterator,
+ kInvalidMRUCacheKey, &btRecord, recordSize, &iterator);
+ if (result) {
+- dprintf (d_error|d_overlap, "%s: Error finding attribute record (err=%d) for fileID = %d, attrname = %d\n", __FUNCTION__, result, extentInfo->fileID, extentInfo->attrname);
++ dbg_printf (d_error|d_overlap, "%s: Error finding attribute record (err=%d) for fileID = %d, attrname = %d\n", __FUNCTION__, result, extentInfo->fileID, extentInfo->attrname);
+ goto out;
+ }
+
+--- a/fsck_hfs.tproj/dfalib/SVerify1.c
++++ b/fsck_hfs.tproj/dfalib/SVerify1.c
+@@ -2157,9 +2157,9 @@ CheckAttributeRecord(SGlobPtr GPtr, cons
+
+ if (doDelete == true) {
+ result = DeleteBTreeRecord(GPtr->calculatedAttributesFCB, key);
+- dprintf (d_info|d_xattr, "%s: Deleting attribute %s for fileID %d, type = %d\n", __FUNCTION__, attrname, key->fileID, rec->recordType);
++ dbg_printf (d_info|d_xattr, "%s: Deleting attribute %s for fileID %d, type = %d\n", __FUNCTION__, attrname, key->fileID, rec->recordType);
+ if (result) {
+- dprintf (d_error|d_xattr, "%s: Error in deleting record for %s for fileID %d, type = %d\n", __FUNCTION__, attrname, key->fileID, rec->recordType);
++ dbg_printf (d_error|d_xattr, "%s: Error in deleting record for %s for fileID %d, type = %d\n", __FUNCTION__, attrname, key->fileID, rec->recordType);
+ }
+
+ /* Set flags to mark header and map dirty */
+@@ -3034,7 +3034,7 @@ OSErr CheckFileExtents( SGlobPtr GPtr, U
+ // checkout the extent record first
+ err = ChkExtRec( GPtr, extents, &lastExtentIndex );
+ if (err != noErr) {
+- dprintf (d_info, "%s: Bad extent for fileID %u in extent %u for startblock %u\n", __FUNCTION__, fileNumber, lastExtentIndex, blockCount);
++ dbg_printf (d_info, "%s: Bad extent for fileID %u in extent %u for startblock %u\n", __FUNCTION__, fileNumber, lastExtentIndex, blockCount);
+
+ /* Stop verification if bad extent is found for system file or EA */
+ if ((fileNumber < kHFSFirstUserCatalogNodeID) ||
+--- a/fsck_hfs.tproj/fsck_debug.c
++++ b/fsck_hfs.tproj/fsck_debug.c
+@@ -25,18 +25,18 @@
+ #include <stdio.h>
+ #include <stdarg.h>
+
+-/* Current debug level of fsck_hfs for printing messages via dprintf */
++/* Current debug level of fsck_hfs for printing messages via dbg_printf */
+ unsigned long cur_debug_level;
+
+-/* Function: dprintf
++/* Function: dbg_printf
+ *
+ * Description: Debug function similar to printf except the first parameter
+- * which indicates the type of message to be printed by dprintf. Based on
++ * which indicates the type of message to be printed by dbg_printf. Based on
+ * current debug level and the type of message, the function decides
+ * whether to print the message or not.
+ *
+ * Each unique message type has a bit assigned to it. The message type
+- * passed to dprintf can be one or combination (OR-ed value) of pre-defined
++ * passed to dbg_printf can be one or combination (OR-ed value) of pre-defined
+ * debug message types. Only the messages whose type have one or more similar
+ * bits set in comparison with current global debug level are printed.
+ *
+@@ -56,7 +56,7 @@ unsigned long cur_debug_level;
+ * Output:
+ * Nothing
+ */
+-void dprintf (unsigned long type, char *fmt, ...)
++void dbg_printf (unsigned long type, char *fmt, ...)
+ {
+ if (cur_debug_level & type) {
+ va_list ap;
+--- a/fsck_hfs.tproj/fsck_debug.h
++++ b/fsck_hfs.tproj/fsck_debug.h
+@@ -36,18 +36,18 @@ enum debug_message_type {
+ d_overlap = 0x0020 /* Overlap extents related messages */
+ };
+
+-/* Current debug level of fsck_hfs for printing messages via dprintf */
++/* Current debug level of fsck_hfs for printing messages via dbg_printf */
+ extern unsigned long cur_debug_level;
+
+-/* Function: dprintf
++/* Function: dbg_printf
+ *
+ * Description: Debug function similar to printf except the first parameter
+- * which indicates the type of message to be printed by dprintf. Based on
++ * which indicates the type of message to be printed by dbg_printf. Based on
+ * current debug level and the type of message, the function decides
+ * whether to print the message or not.
+ *
+ * Each unique message type has a bit assigned to it. The message type
+- * passed to dprintf can be one or combination (OR-ed value) of pre-defined
++ * passed to dbg_printf can be one or combination (OR-ed value) of pre-defined
+ * debug message types. Only the messages whose type have one or more similar
+ * bits set in comparison with current global debug level are printed.
+ *
+@@ -67,6 +67,6 @@ extern unsigned long cur_debug_level;
+ * Output:
+ * Nothing
+ */
+-extern void dprintf (unsigned long message_type, char *format, ...);
++extern void dbg_printf (unsigned long message_type, char *format, ...);
+
+ #endif /* __FSCK_DEBUG__ */
diff --git a/external/subpack/utils/hfsprogs/patches/0010-Rename-custom-macro-nil-with-NULL.patch b/external/subpack/utils/hfsprogs/patches/0010-Rename-custom-macro-nil-with-NULL.patch
new file mode 100644
index 0000000..13ac4ed
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0010-Rename-custom-macro-nil-with-NULL.patch
@@ -0,0 +1,1299 @@
+From: =?UTF-8?q?Rog=C3=A9rio=20Brito?= <rbrito@ime.usp.br>
+Date: Thu, 24 Oct 2013 01:11:21 -0200
+Subject: Rename custom macro nil with NULL
+
+---
+ fsck_hfs.tproj/dfalib/BTree.c | 142 +++++++++++++++++-----------------
+ fsck_hfs.tproj/dfalib/BTreeAllocate.c | 14 ++--
+ fsck_hfs.tproj/dfalib/BTreeMiscOps.c | 26 +++----
+ fsck_hfs.tproj/dfalib/BTreeNodeOps.c | 30 +++----
+ fsck_hfs.tproj/dfalib/BTreeTreeOps.c | 38 ++++-----
+ fsck_hfs.tproj/dfalib/SControl.c | 56 +++++++-------
+ fsck_hfs.tproj/dfalib/SRepair.c | 6 +-
+ fsck_hfs.tproj/dfalib/SUtils.c | 6 +-
+ fsck_hfs.tproj/dfalib/SVerify1.c | 32 ++++----
+ fsck_hfs.tproj/dfalib/SVerify2.c | 4 +-
+ 10 files changed, 177 insertions(+), 177 deletions(-)
+
+--- a/fsck_hfs.tproj/dfalib/BTree.c
++++ b/fsck_hfs.tproj/dfalib/BTree.c
+@@ -163,21 +163,21 @@ OSStatus BTInitialize (FCB *filePtr
+
+ ////////////////////// Preliminary Error Checking ///////////////////////////
+
+- headerNode.buffer = nil;
++ headerNode.buffer = NULL;
+
+- if (pathPtr == nil) return paramErr;
++ if (pathPtr == NULL) return paramErr;
+
+ setEndOfForkProc = pathPtr->agentPtr->agent.setEndOfForkProc;
+ setBlockSizeProc = pathPtr->agentPtr->agent.setBlockSizeProc;
+
+- if (pathPtr->agentPtr->agent.getBlockProc == nil) return E_NoGetBlockProc;
+- if (pathPtr->agentPtr->agent.releaseBlockProc == nil) return E_NoReleaseBlockProc;
+- if (setEndOfForkProc == nil) return E_NoSetEndOfForkProc;
+- if (setBlockSizeProc == nil) return E_NoSetBlockSizeProc;
++ if (pathPtr->agentPtr->agent.getBlockProc == NULL) return E_NoGetBlockProc;
++ if (pathPtr->agentPtr->agent.releaseBlockProc == NULL) return E_NoReleaseBlockProc;
++ if (setEndOfForkProc == NULL) return E_NoSetEndOfForkProc;
++ if (setBlockSizeProc == NULL) return E_NoSetBlockSizeProc;
+
+ forkPtr = pathPtr->path.forkPtr;
+
+- if (forkPtr->fork.btreePtr != nil) return fsBTrFileAlreadyOpenErr;
++ if (forkPtr->fork.btreePtr != NULL) return fsBTrFileAlreadyOpenErr;
+
+ if ((maxKeyLength == 0) ||
+ (maxKeyLength > kMaxKeyLength)) return fsBTInvalidKeyLengthErr;
+@@ -209,7 +209,7 @@ OSStatus BTInitialize (FCB *filePtr
+ //////////////////////// Allocate Control Block /////////////////////////////
+
+ M_RESIDENT_ALLOCATE_FIXED_CLEAR( &btreePtr, sizeof( BTreeControlBlock ), kFSBTreeControlBlockType );
+- if (btreePtr == nil)
++ if (btreePtr == NULL)
+ {
+ err = memFullErr;
+ goto ErrorExit;
+@@ -220,7 +220,7 @@ OSStatus BTInitialize (FCB *filePtr
+ btreePtr->flags = 0;
+ btreePtr->attributes = 0;
+ btreePtr->forkPtr = forkPtr;
+- btreePtr->keyCompareProc = nil;
++ btreePtr->keyCompareProc = NULL;
+ btreePtr->keyDescPtr = keyDescPtr;
+ btreePtr->btreeType = btreeType;
+ btreePtr->treeDepth = 0;
+@@ -282,7 +282,7 @@ OSStatus BTInitialize (FCB *filePtr
+
+ ///////////////////// Copy Key Descriptor To Header /////////////////////////
+ #if SupportsKeyDescriptors
+- if (keyDescPtr != nil)
++ if (keyDescPtr != NULL)
+ {
+ err = CheckKeyDescriptor (keyDescPtr, maxKeyLength);
+ M_ExitOnError (err);
+@@ -309,7 +309,7 @@ OSStatus BTInitialize (FCB *filePtr
+ err = UpdateHeader (btreePtr);
+ M_ExitOnError (err);
+
+- pathPtr->path.forkPtr->fork.btreePtr = nil;
++ pathPtr->path.forkPtr->fork.btreePtr = NULL;
+ M_RESIDENT_DEALLOCATE_FIXED( btreePtr, sizeof( BTreeControlBlock ), kFSBTreeControlBlockType );
+
+ return noErr;
+@@ -320,7 +320,7 @@ OSStatus BTInitialize (FCB *filePtr
+ ErrorExit:
+
+ (void) ReleaseNode (btreePtr, &headerNode);
+- if (btreePtr != nil)
++ if (btreePtr != NULL)
+ M_RESIDENT_DEALLOCATE_FIXED( btreePtr, sizeof( BTreeControlBlock ), kFSBTreeControlBlockType );
+
+ return err;
+@@ -342,7 +342,7 @@ Input: filePtr - pointer to file to
+ setEndOfForkProc - pointer to client's SetEOF function
+
+ Result: noErr - success
+- paramErr - required ptr was nil
++ paramErr - required ptr was NULL
+ fsBTInvalidFileErr -
+ memFullErr -
+ != noErr - failure
+@@ -364,16 +364,16 @@ OSStatus BTOpenPath (SFCB *filePtr
+
+ ////////////////////// Preliminary Error Checking ///////////////////////////
+
+- if ( filePtr == nil ||
+- getBlockProc == nil ||
+- releaseBlockProc == nil ||
+- setEndOfForkProc == nil ||
+- setBlockSizeProc == nil )
++ if (filePtr == NULL ||
++ getBlockProc == NULL ||
++ releaseBlockProc == NULL ||
++ setEndOfForkProc == NULL ||
++ setBlockSizeProc == NULL)
+ {
+ return paramErr;
+ }
+
+- if ( filePtr->fcbBtree != nil ) // already has a BTreeCB
++ if (filePtr->fcbBtree != NULL) // already has a BTreeCB
+ return noErr;
+
+ // is file large enough to contain header node?
+@@ -384,7 +384,7 @@ OSStatus BTOpenPath (SFCB *filePtr
+ //////////////////////// Allocate Control Block /////////////////////////////
+
+ btreePtr = (BTreeControlBlock*) AllocateClearMemory( sizeof( BTreeControlBlock ) );
+- if (btreePtr == nil)
++ if (btreePtr == NULL)
+ {
+ Panic ("\pBTOpen: no memory for btreePtr.");
+ return memFullErr;
+@@ -397,7 +397,7 @@ OSStatus BTOpenPath (SFCB *filePtr
+
+ /////////////////////////// Read Header Node ////////////////////////////////
+
+- nodeRec.buffer = nil; // so we can call ReleaseNode
++ nodeRec.buffer = NULL; // so we can call ReleaseNode
+
+ btreePtr->fcbPtr = filePtr;
+ filePtr->fcbBtree = (void *) btreePtr; // attach btree cb to file
+@@ -487,7 +487,7 @@ OSStatus BTOpenPath (SFCB *filePtr
+
+ ////////////////////////// Get Key Descriptor ///////////////////////////////
+ #if SupportsKeyDescriptors
+- if ( keyCompareProc == nil ) // if no key compare proc then get key descriptor
++ if (keyCompareProc == NULL) // if no key compare proc then get key descriptor
+ {
+ err = GetKeyDescriptor (btreePtr, nodeRec.buffer); //¥¥ it should check amount of memory allocated...
+ M_ExitOnError (err);
+@@ -499,7 +499,7 @@ OSStatus BTOpenPath (SFCB *filePtr
+ else
+ #endif
+ {
+- btreePtr->keyDescPtr = nil; // clear it so we don't dispose garbage later
++ btreePtr->keyDescPtr = NULL; // clear it so we don't dispose garbage later
+ }
+
+ err = ReleaseNode (btreePtr, &nodeRec);
+@@ -528,7 +528,7 @@ OSStatus BTOpenPath (SFCB *filePtr
+
+ ErrorExit:
+
+- filePtr->fcbBtree = nil;
++ filePtr->fcbBtree = NULL;
+ (void) ReleaseNode (btreePtr, &nodeRec);
+ DisposeMemory( btreePtr );
+
+@@ -567,7 +567,7 @@ OSStatus BTClosePath (SFCB *filePt
+
+ btreePtr = (BTreeControlBlockPtr) filePtr->fcbBtree;
+
+- if (btreePtr == nil)
++ if (btreePtr == NULL)
+ return fsBTInvalidFileErr;
+
+ ////////////////////// Check for other BTree Paths //////////////////////////
+@@ -603,14 +603,14 @@ OSStatus BTClosePath (SFCB *filePt
+ M_ExitOnError (err);
+
+ #if SupportsKeyDescriptors
+- if (btreePtr->keyDescPtr != nil) // deallocate keyDescriptor, if any
++ if (btreePtr->keyDescPtr != NULL) // deallocate keyDescriptor, if any
+ {
+ DisposeMemory( btreePtr->keyDescPtr );
+ }
+ #endif
+
+ DisposeMemory( btreePtr );
+- filePtr->fcbBtree = nil;
++ filePtr->fcbBtree = NULL;
+
+ // LogEndTime(kTraceCloseBTree, noErr);
+
+@@ -643,7 +643,7 @@ Function: Search for position in B*Tree
+
+ Input: pathPtr - pointer to path for BTree file.
+ searchKey - pointer to search key to match.
+- hintPtr - pointer to hint (may be nil)
++ hintPtr - pointer to hint (may be NULL)
+
+ Output: record - pointer to BufferDescriptor containing record
+ recordLen - length of data at recordPtr
+@@ -678,14 +678,14 @@ OSStatus BTSearchRecord (SFCB *fil
+
+ // LogStartTime(kTraceSearchBTree);
+
+- if (filePtr == nil) return paramErr;
+- if (searchIterator == nil) return paramErr;
++ if (filePtr == NULL) return paramErr;
++ if (searchIterator == NULL) return paramErr;
+
+ btreePtr = (BTreeControlBlockPtr) filePtr->fcbBtree;
+- if (btreePtr == nil) return fsBTInvalidFileErr;
++ if (btreePtr == NULL) return fsBTInvalidFileErr;
+
+ #if SupportsKeyDescriptors
+- if (btreePtr->keyCompareProc == nil) // CheckKey if we using Key Descriptor
++ if (btreePtr->keyCompareProc == NULL) // CheckKey if we using Key Descriptor
+ {
+ err = CheckKey (&searchIterator->key, btreePtr->keyDescPtr, btreePtr->maxKeyLength);
+ M_ExitOnError (err);
+@@ -775,9 +775,9 @@ OSStatus BTSearchRecord (SFCB *fil
+ //¥¥ Should check for errors! Or BlockMove could choke on recordPtr!!!
+ GetRecordByIndex (btreePtr, node.buffer, index, &keyPtr, &recordPtr, &len);
+
+- if (recordLen != nil) *recordLen = len;
++ if (recordLen != NULL) *recordLen = len;
+
+- if (record != nil)
++ if (record != NULL)
+ {
+ ByteCount recordSize;
+
+@@ -794,7 +794,7 @@ OSStatus BTSearchRecord (SFCB *fil
+
+ /////////////////////// Success - Update Iterator ///////////////////////////
+
+- if (resultIterator != nil)
++ if (resultIterator != NULL)
+ {
+ resultIterator->hint.writeCount = btreePtr->writeCount;
+ resultIterator->hint.nodeNum = nodeNum;
+@@ -825,10 +825,10 @@ OSStatus BTSearchRecord (SFCB *fil
+
+ ErrorExit:
+
+- if (recordLen != nil)
++ if (recordLen != NULL)
+ *recordLen = 0;
+
+- if (resultIterator != nil)
++ if (resultIterator != NULL)
+ {
+ resultIterator->hint.writeCount = 0;
+ resultIterator->hint.nodeNum = 0;
+@@ -892,18 +892,18 @@ OSStatus BTIterateRecord (SFCB *fi
+
+ ////////////////////////// Priliminary Checks ///////////////////////////////
+
+- left.buffer = nil;
+- right.buffer = nil;
+- node.buffer = nil;
++ left.buffer = NULL;
++ right.buffer = NULL;
++ node.buffer = NULL;
+
+
+- if (filePtr == nil)
++ if (filePtr == NULL)
+ {
+ return paramErr;
+ }
+
+ btreePtr = (BTreeControlBlockPtr) filePtr->fcbBtree;
+- if (btreePtr == nil)
++ if (btreePtr == NULL)
+ {
+ return fsBTInvalidFileErr; //¥¥ handle properly
+ }
+@@ -968,7 +968,7 @@ OSStatus BTIterateRecord (SFCB *fi
+ }
+ else
+ {
+- if (left.buffer == nil)
++ if (left.buffer == NULL)
+ {
+ nodeNum = ((NodeDescPtr) node.buffer)->bLink;
+ if ( nodeNum > 0)
+@@ -981,13 +981,13 @@ OSStatus BTIterateRecord (SFCB *fi
+ }
+ }
+ // Before we stomp on "right", we'd better release it if needed
+- if (right.buffer != nil) {
++ if (right.buffer != NULL) {
+ err = ReleaseNode(btreePtr, &right);
+ M_ExitOnError(err);
+ }
+ right = node;
+ node = left;
+- left.buffer = nil;
++ left.buffer = NULL;
+ index = ((NodeDescPtr) node.buffer)->numRecords -1;
+ }
+ }
+@@ -1012,7 +1012,7 @@ OSStatus BTIterateRecord (SFCB *fi
+ }
+ else
+ {
+- if (right.buffer == nil)
++ if (right.buffer == NULL)
+ {
+ nodeNum = ((NodeDescPtr) node.buffer)->fLink;
+ if ( nodeNum > 0)
+@@ -1025,13 +1025,13 @@ OSStatus BTIterateRecord (SFCB *fi
+ }
+ }
+ // Before we stomp on "left", we'd better release it if needed
+- if (left.buffer != nil) {
++ if (left.buffer != NULL) {
+ err = ReleaseNode(btreePtr, &left);
+ M_ExitOnError(err);
+ }
+ left = node;
+ node = right;
+- right.buffer = nil;
++ right.buffer = NULL;
+ index = 0;
+ }
+ }
+@@ -1054,9 +1054,9 @@ CopyData:
+ err = GetRecordByIndex (btreePtr, node.buffer, index, &keyPtr, &recordPtr, &len);
+ M_ExitOnError (err);
+
+- if (recordLen != nil) *recordLen = len;
++ if (recordLen != NULL) *recordLen = len;
+
+- if (record != nil)
++ if (record != NULL)
+ {
+ ByteCount recordSize;
+
+@@ -1069,7 +1069,7 @@ CopyData:
+ CopyMemory (recordPtr, record->bufferAddress, len);
+ }
+
+- if (iterator != nil) // first & last do not require iterator
++ if (iterator != NULL) // first & last do not require iterator
+ {
+ iterator->hint.writeCount = btreePtr->writeCount;
+ iterator->hint.nodeNum = nodeNum;
+@@ -1089,13 +1089,13 @@ CopyData:
+ err = ReleaseNode (btreePtr, &node);
+ M_ExitOnError (err);
+
+- if (left.buffer != nil)
++ if (left.buffer != NULL)
+ {
+ err = ReleaseNode (btreePtr, &left);
+ M_ExitOnError (err);
+ }
+
+- if (right.buffer != nil)
++ if (right.buffer != NULL)
+ {
+ err = ReleaseNode (btreePtr, &right);
+ M_ExitOnError (err);
+@@ -1113,10 +1113,10 @@ ErrorExit:
+ (void) ReleaseNode (btreePtr, &node);
+ (void) ReleaseNode (btreePtr, &right);
+
+- if (recordLen != nil)
++ if (recordLen != NULL)
+ *recordLen = 0;
+
+- if (iterator != nil)
++ if (iterator != NULL)
+ {
+ iterator->hint.writeCount = 0;
+ iterator->hint.nodeNum = 0;
+@@ -1157,7 +1157,7 @@ OSStatus BTInsertRecord (SFCB *fil
+
+ ////////////////////////// Priliminary Checks ///////////////////////////////
+
+- nodeRec.buffer = nil; // so we can call ReleaseNode
++ nodeRec.buffer = NULL; // so we can call ReleaseNode
+
+ err = CheckInsertParams (filePtr, iterator, record, recordLen);
+ if (err != noErr)
+@@ -1317,7 +1317,7 @@ OSStatus BTSetRecord (SFCB *fileP
+
+ ////////////////////////// Priliminary Checks ///////////////////////////////
+
+- nodeRec.buffer = nil; // so we can call ReleaseNode
++ nodeRec.buffer = NULL; // so we can call ReleaseNode
+
+ err = CheckInsertParams (filePtr, iterator, record, recordLen);
+ if (err != noErr)
+@@ -1506,7 +1506,7 @@ OSStatus BTReplaceRecord (SFCB *fi
+
+ ////////////////////////// Priliminary Checks ///////////////////////////////
+
+- nodeRec.buffer = nil; // so we can call ReleaseNode
++ nodeRec.buffer = NULL; // so we can call ReleaseNode
+
+ err = CheckInsertParams (filePtr, iterator, record, recordLen);
+ if (err != noErr)
+@@ -1645,20 +1645,20 @@ OSStatus BTDeleteRecord (SFCB *fil
+
+ ////////////////////////// Priliminary Checks ///////////////////////////////
+
+- nodeRec.buffer = nil; // so we can call ReleaseNode
++ nodeRec.buffer = NULL; // so we can call ReleaseNode
+
+- M_ReturnErrorIf (filePtr == nil, paramErr);
+- M_ReturnErrorIf (iterator == nil, paramErr);
++ M_ReturnErrorIf (filePtr == NULL, paramErr);
++ M_ReturnErrorIf (iterator == NULL, paramErr);
+
+ btreePtr = (BTreeControlBlockPtr) filePtr->fcbBtree;
+- if (btreePtr == nil)
++ if (btreePtr == NULL)
+ {
+ err = fsBTInvalidFileErr;
+ goto ErrorExit;
+ }
+
+ #if SupportsKeyDescriptors
+- if (btreePtr->keyDescPtr != nil)
++ if (btreePtr->keyDescPtr != NULL)
+ {
+ err = CheckKey (&iterator->key, btreePtr->keyDescPtr, btreePtr->maxKeyLength);
+ M_ExitOnError (err);
+@@ -1712,12 +1712,12 @@ OSStatus BTGetInformation (SFCB *fil
+ BTreeControlBlockPtr btreePtr;
+
+
+- M_ReturnErrorIf (filePtr == nil, paramErr);
++ M_ReturnErrorIf (filePtr == NULL, paramErr);
+
+ btreePtr = (BTreeControlBlockPtr) filePtr->fcbBtree;
+
+- M_ReturnErrorIf (btreePtr == nil, fsBTInvalidFileErr);
+- M_ReturnErrorIf (info == nil, paramErr);
++ M_ReturnErrorIf (btreePtr == NULL, fsBTInvalidFileErr);
++ M_ReturnErrorIf (info == NULL, paramErr);
+
+ //¥¥ check version?
+
+@@ -1730,7 +1730,7 @@ OSStatus BTGetInformation (SFCB *fil
+ info->keyDescriptor = btreePtr->keyDescPtr; //¥¥ this won't do at all...
+ info->reserved = 0;
+
+- if (btreePtr->keyDescPtr == nil)
++ if (btreePtr->keyDescPtr == NULL)
+ info->keyDescLength = 0;
+ else
+ info->keyDescLength = (UInt32) btreePtr->keyDescPtr->length;
+@@ -1762,11 +1762,11 @@ OSStatus BTFlushPath (SFCB *fileP
+
+ // LogStartTime(kTraceFlushBTree);
+
+- M_ReturnErrorIf (filePtr == nil, paramErr);
++ M_ReturnErrorIf (filePtr == NULL, paramErr);
+
+ btreePtr = (BTreeControlBlockPtr) filePtr->fcbBtree;
+
+- M_ReturnErrorIf (btreePtr == nil, fsBTInvalidFileErr);
++ M_ReturnErrorIf (btreePtr == NULL, fsBTInvalidFileErr);
+
+ err = UpdateHeader (btreePtr);
+
+@@ -1788,13 +1788,13 @@ Input: iterator - pointer to BTreeItera
+ Output: iterator - iterator with the hint.nodeNum cleared
+
+ Result: noErr - success
+- paramErr - iterator == nil
++ paramErr - iterator == NULL
+ -------------------------------------------------------------------------------*/
+
+
+ OSStatus BTInvalidateHint (BTreeIterator *iterator )
+ {
+- if (iterator == nil)
++ if (iterator == NULL)
+ return paramErr;
+
+ iterator->hint.nodeNum = 0;
+--- a/fsck_hfs.tproj/dfalib/BTreeAllocate.c
++++ b/fsck_hfs.tproj/dfalib/BTreeAllocate.c
+@@ -83,7 +83,7 @@ OSStatus AllocateNode (BTreeControlBlock
+
+
+ nodeNumber = 0; // first node number of header map record
+- node.buffer = nil; // clear node.buffer to get header node
++ node.buffer = NULL; // clear node.buffer to get header node
+ // - and for ErrorExit
+
+ while (true)
+@@ -192,7 +192,7 @@ OSStatus FreeNode (BTreeControlBlockPtr
+
+ //////////////////////////// Find Map Record ////////////////////////////////
+ nodeIndex = 0; // first node number of header map record
+- node.buffer = nil; // invalidate node.buffer to get header node
++ node.buffer = NULL; // invalidate node.buffer to get header node
+
+ while (nodeNum >= nodeIndex)
+ {
+@@ -278,8 +278,8 @@ OSStatus ExtendBTree (BTreeControlBlockP
+ nodeSize = btreePtr->nodeSize;
+ filePtr = btreePtr->fcbPtr;
+
+- mapNode.buffer = nil;
+- newNode.buffer = nil;
++ mapNode.buffer = NULL;
++ newNode.buffer = NULL;
+
+ mapNodeRecSize = nodeSize - sizeof(BTNodeDescriptor) - 6; // 2 bytes of free space (see note)
+
+@@ -448,7 +448,7 @@ ErrorExit:
+ Routine: GetMapNode - Get the next map node and pointer to the map record.
+
+ Function: Given a BlockDescriptor to a map node in nodePtr, GetMapNode releases
+- it and gets the next node. If nodePtr->buffer is nil, then the header
++ it and gets the next node. If nodePtr->buffer is NULL, then the header
+ node is retrieved.
+
+
+@@ -474,7 +474,7 @@ OSStatus GetMapNode (BTreeControlBlockPt
+ UInt16 mapIndex;
+ UInt32 nextNodeNum;
+
+- if (nodePtr->buffer != nil) // if iterator is valid...
++ if (nodePtr->buffer != NULL) // if iterator is valid...
+ {
+ nextNodeNum = ((NodeDescPtr)nodePtr->buffer)->fLink;
+ if (nextNodeNum == 0)
+@@ -521,7 +521,7 @@ ErrorExit:
+
+ (void) ReleaseNode (btreePtr, nodePtr);
+
+- *mapPtr = nil;
++ *mapPtr = NULL;
+ *mapSize = 0;
+
+ return err;
+--- a/fsck_hfs.tproj/dfalib/BTreeMiscOps.c
++++ b/fsck_hfs.tproj/dfalib/BTreeMiscOps.c
+@@ -236,13 +236,13 @@ OSStatus FindIteratorPosition (BTreeCont
+ // assume index points to UInt16
+ // assume foundRecord points to Boolean
+
+- left->buffer = nil;
+- middle->buffer = nil;
+- right->buffer = nil;
++ left->buffer = NULL;
++ middle->buffer = NULL;
++ right->buffer = NULL;
+
+ foundIt = false;
+
+- if (iterator == nil) // do we have an iterator?
++ if (iterator == NULL) // do we have an iterator?
+ {
+ err = fsBTInvalidIteratorErr;
+ goto ErrorExit;
+@@ -250,7 +250,7 @@ OSStatus FindIteratorPosition (BTreeCont
+
+ #if SupportsKeyDescriptors
+ //¥¥ verify iterator key (change CheckKey to take btreePtr instead of keyDescPtr?)
+- if (btreePtr->keyDescPtr != nil)
++ if (btreePtr->keyDescPtr != NULL)
+ {
+ err = CheckKey (&iterator->key, btreePtr->keyDescPtr, btreePtr->maxKeyLength );
+ M_ExitOnError (err);
+@@ -309,7 +309,7 @@ OSStatus FindIteratorPosition (BTreeCont
+ {
+ *right = *middle;
+ *middle = *left;
+- left->buffer = nil;
++ left->buffer = NULL;
+ index = leftIndex;
+
+ goto SuccessfulExit;
+@@ -330,7 +330,7 @@ OSStatus FindIteratorPosition (BTreeCont
+ {
+ *right = *middle;
+ *middle = *left;
+- left->buffer = nil;
++ left->buffer = NULL;
+ index = leftIndex;
+
+ goto SuccessfulExit;
+@@ -363,7 +363,7 @@ OSStatus FindIteratorPosition (BTreeCont
+ {
+ *left = *middle;
+ *middle = *right;
+- right->buffer = nil;
++ right->buffer = NULL;
+ index = rightIndex;
+
+ goto SuccessfulExit;
+@@ -427,15 +427,15 @@ OSStatus CheckInsertParams (SFCB *
+ {
+ BTreeControlBlockPtr btreePtr;
+
+- if (filePtr == nil) return paramErr;
++ if (filePtr == NULL) return paramErr;
+
+ btreePtr = (BTreeControlBlockPtr) filePtr->fcbBtree;
+- if (btreePtr == nil) return fsBTInvalidFileErr;
+- if (iterator == nil) return paramErr;
+- if (record == nil) return paramErr;
++ if (btreePtr == NULL) return fsBTInvalidFileErr;
++ if (iterator == NULL) return paramErr;
++ if (record == NULL) return paramErr;
+
+ #if SupportsKeyDescriptors
+- if (btreePtr->keyDescPtr != nil)
++ if (btreePtr->keyDescPtr != NULL)
+ {
+ OSStatus err;
+
+--- a/fsck_hfs.tproj/dfalib/BTreeNodeOps.c
++++ b/fsck_hfs.tproj/dfalib/BTreeNodeOps.c
+@@ -105,7 +105,7 @@ Function: Gets an existing BTree node fr
+ Input: btreePtr - pointer to BTree control block
+ nodeNum - number of node to request
+
+-Output: nodePtr - pointer to beginning of node (nil if error)
++Output: nodePtr - pointer to beginning of node (NULL if error)
+
+ Result:
+ noErr - success
+@@ -139,7 +139,7 @@ OSStatus GetNode (BTreeControlBlockPtr
+ if (err != noErr)
+ {
+ Panic ("\pGetNode: getNodeProc returned error.");
+- nodePtr->buffer = nil;
++ nodePtr->buffer = NULL;
+ goto ErrorExit;
+ }
+ ++btreePtr->numGetNodes;
+@@ -156,8 +156,8 @@ OSStatus GetNode (BTreeControlBlockPtr
+ return noErr;
+
+ ErrorExit:
+- nodePtr->buffer = nil;
+- nodePtr->blockHeader = nil;
++ nodePtr->buffer = NULL;
++ nodePtr->blockHeader = NULL;
+
+ // LogEndTime(kTraceGetNode, err);
+
+@@ -176,7 +176,7 @@ Function: Gets a new BTree node from FS
+ Input: btreePtr - pointer to BTree control block
+ nodeNum - number of node to request
+
+-Output: returnNodePtr - pointer to beginning of node (nil if error)
++Output: returnNodePtr - pointer to beginning of node (NULL if error)
+
+ Result: noErr - success
+ != noErr - failure
+@@ -203,7 +203,7 @@ OSStatus GetNewNode (BTreeControlBlockPt
+ if (err != noErr)
+ {
+ Panic ("\pGetNewNode: getNodeProc returned error.");
+- returnNodePtr->buffer = nil;
++ returnNodePtr->buffer = NULL;
+ return err;
+ }
+ ++btreePtr->numGetNewNodes;
+@@ -248,7 +248,7 @@ OSStatus ReleaseNode (BTreeControlBlockP
+
+ err = noErr;
+
+- if (nodePtr->buffer != nil)
++ if (nodePtr->buffer != NULL)
+ {
+ /*
+ * The nodes must remain in the cache as big endian!
+@@ -267,8 +267,8 @@ OSStatus ReleaseNode (BTreeControlBlockP
+ ++btreePtr->numReleaseNodes;
+ }
+
+- nodePtr->buffer = nil;
+- nodePtr->blockHeader = nil;
++ nodePtr->buffer = NULL;
++ nodePtr->blockHeader = NULL;
+
+ // LogEndTime(kTraceReleaseNode, err);
+
+@@ -299,7 +299,7 @@ OSStatus TrashNode (BTreeControlBlockPtr
+
+ err = noErr;
+
+- if (nodePtr->buffer != nil)
++ if (nodePtr->buffer != NULL)
+ {
+ releaseNodeProc = btreePtr->releaseBlockProc;
+ err = releaseNodeProc (btreePtr->fcbPtr,
+@@ -309,8 +309,8 @@ OSStatus TrashNode (BTreeControlBlockPtr
+ ++btreePtr->numReleaseNodes;
+ }
+
+- nodePtr->buffer = nil;
+- nodePtr->blockHeader = nil;
++ nodePtr->buffer = NULL;
++ nodePtr->blockHeader = NULL;
+
+ return err;
+ }
+@@ -338,7 +338,7 @@ OSStatus UpdateNode (BTreeControlBlockPt
+
+ err = noErr;
+
+- if (nodePtr->buffer != nil) //¥¥ why call UpdateNode if nil ?!?
++ if (nodePtr->buffer != NULL) //¥¥ why call UpdateNode if NULL ?!?
+ {
+ // LogStartTime(kTraceReleaseNode);
+ err = hfs_swap_BTNode(nodePtr, btreePtr->fcbPtr, kSwapBTNodeHostToBig);
+@@ -358,8 +358,8 @@ OSStatus UpdateNode (BTreeControlBlockPt
+ ++btreePtr->numUpdateNodes;
+ }
+
+- nodePtr->buffer = nil;
+- nodePtr->blockHeader = nil;
++ nodePtr->buffer = NULL;
++ nodePtr->blockHeader = NULL;
+
+ return noErr;
+
+--- a/fsck_hfs.tproj/dfalib/BTreeTreeOps.c
++++ b/fsck_hfs.tproj/dfalib/BTreeTreeOps.c
+@@ -177,7 +177,7 @@ Output: nodeNum - number of the node
+
+ Result: noErr - key found, index is record index
+ fsBTRecordNotFoundErr - key not found, index is insert index
+- fsBTEmptyErr - key not found, return params are nil
++ fsBTEmptyErr - key not found, return params are NULL
+ otherwise - catastrophic failure (GetNode/ReleaseNode failed)
+ -------------------------------------------------------------------------------*/
+
+@@ -321,8 +321,8 @@ ReleaseAndExit:
+ ErrorExit:
+
+ *nodeNum = 0;
+- nodePtr->buffer = nil;
+- nodePtr->blockHeader = nil;
++ nodePtr->buffer = NULL;
++ nodePtr->blockHeader = NULL;
+ *returnIndex = 0;
+
+ return err;
+@@ -354,7 +354,7 @@ OSStatus InsertTree ( BTreeControlBlockP
+ primaryKey.replacingKey = replacingKey;
+ primaryKey.skipRotate = false;
+
+- err = InsertLevel (btreePtr, treePathTable, &primaryKey, nil,
++ err = InsertLevel (btreePtr, treePathTable, &primaryKey, NULL,
+ targetNode, index, level, insertNode );
+
+ return err;
+@@ -385,7 +385,7 @@ OSStatus InsertLevel (BTreeControlBlockP
+ #if defined(applec) && !defined(__SC__)
+ PanicIf ((level == 1) && (((NodeDescPtr)targetNode->buffer)->kind != kBTLeafNode), "\P InsertLevel: non-leaf at level 1! ");
+ #endif
+- siblingNode.buffer = nil;
++ siblingNode.buffer = NULL;
+ targetNodeNum = treePathTable [level].node;
+
+ insertParent = false;
+@@ -420,7 +420,7 @@ OSStatus InsertLevel (BTreeControlBlockP
+
+ ////// process second insert (if any) //////
+
+- if ( secondaryKey != nil )
++ if (secondaryKey != NULL)
+ {
+ Boolean temp;
+
+@@ -446,7 +446,7 @@ OSStatus InsertLevel (BTreeControlBlockP
+ UInt8 * recPtr;
+ UInt16 recSize;
+
+- secondaryKey = nil;
++ secondaryKey = NULL;
+
+ PanicIf ( (level == btreePtr->treeDepth), "InsertLevel: unfinished insert!?");
+
+@@ -606,9 +606,9 @@ static OSErr InsertNode (BTreeControlBlo
+
+ if ( leftNodeNum > 0 )
+ {
+- PanicIf ( siblingNode->buffer != nil, "InsertNode: siblingNode already aquired!");
++ PanicIf(siblingNode->buffer != NULL, "InsertNode: siblingNode already aquired!");
+
+- if ( siblingNode->buffer == nil )
++ if (siblingNode->buffer == NULL)
+ {
+ err = GetNode (btreePtr, leftNodeNum, siblingNode); // will be released by caller or a split below
+ M_ExitOnError (err);
+@@ -703,7 +703,7 @@ OSStatus DeleteTree (BTreeControlBlock
+
+ targetNodeNum = treePathTable[level].node;
+ targetNodePtr = targetNode->buffer;
+- PanicIf (targetNodePtr == nil, "DeleteTree: targetNode has nil buffer!");
++ PanicIf (targetNodePtr == NULL, "DeleteTree: targetNode has NULL buffer!");
+
+ DeleteRecord (btreePtr, targetNodePtr, index);
+
+@@ -766,7 +766,7 @@ OSStatus DeleteTree (BTreeControlBlock
+ deleteRequired = false;
+ updateRequired = false;
+
+- if ( targetNode->buffer == nil ) // then root was freed and the btree is empty
++ if (targetNode->buffer == NULL) // then root was freed and the btree is empty
+ {
+ btreePtr->rootNode = 0;
+ btreePtr->treeDepth = 0;
+@@ -1124,7 +1124,7 @@ static OSStatus SplitLeft (BTreeControl
+ if ( (right->height == 1) && (right->kind != kBTLeafNode) )
+ return fsBTInvalidNodeErr;
+
+- if ( left != nil )
++ if (left != NULL)
+ {
+ if ( left->fLink != rightNodeNum )
+ return fsBTInvalidNodeErr; //¥¥ E_BadSibling ?
+@@ -1145,7 +1145,7 @@ static OSStatus SplitLeft (BTreeControl
+
+ /////////////// Update Forward Link In Original Left Node ///////////////////
+
+- if ( left != nil )
++ if (left != NULL)
+ {
+ left->fLink = newNodeNum;
+ err = UpdateNode (btreePtr, leftNode);
+@@ -1240,8 +1240,8 @@ static OSStatus AddNewRootNode (BTreeCon
+ Boolean didItFit;
+ UInt16 keyLength;
+
+- PanicIf (leftNode == nil, "AddNewRootNode: leftNode == nil");
+- PanicIf (rightNode == nil, "AddNewRootNode: rightNode == nil");
++ PanicIf (leftNode == NULL, "AddNewRootNode: leftNode == NULL");
++ PanicIf (rightNode == NULL, "AddNewRootNode: rightNode == NULL");
+
+
+ /////////////////////// Initialize New Root Node ////////////////////////////
+@@ -1362,7 +1362,7 @@ static OSStatus SplitRight (BTreeContro
+ if ( (leftPtr->height == 1) && (leftPtr->kind != kBTLeafNode) )
+ return fsBTInvalidNodeErr;
+
+- if ( rightPtr != nil )
++ if (rightPtr != NULL)
+ {
+ if ( rightPtr->bLink != nodeNum )
+ return fsBTInvalidNodeErr; //¥¥ E_BadSibling ?
+@@ -1382,7 +1382,7 @@ static OSStatus SplitRight (BTreeContro
+
+ /////////////// Update backward Link In Original Right Node ///////////////////
+
+- if ( rightPtr != nil )
++ if (rightPtr != NULL)
+ {
+ rightPtr->bLink = newNodeNum;
+ err = UpdateNode (btreePtr, rightNodePtr);
+@@ -1739,7 +1739,7 @@ static int DoKeyCheck( NodeDescPtr nodeP
+ UInt16 keyLength;
+ KeyPtr keyPtr;
+ UInt8 *dataPtr;
+- KeyPtr prevkeyP = nil;
++ KeyPtr prevkeyP = NULL;
+
+
+ if ( nodeP->numRecords == 0 )
+@@ -1766,7 +1766,7 @@ static int DoKeyCheck( NodeDescPtr nodeP
+ return( -1 );
+ }
+
+- if ( prevkeyP != nil )
++ if (prevkeyP != NULL)
+ {
+ if ( CompareKeys( (BTreeControlBlockPtr)btcb, prevkeyP, keyPtr ) >= 0 )
+ {
+--- a/fsck_hfs.tproj/dfalib/SControl.c
++++ b/fsck_hfs.tproj/dfalib/SControl.c
+@@ -82,7 +82,7 @@ CheckHFS( int fsReadRef, int fsWriteRef
+ {
+ SGlob dataArea; // Allocate the scav globals
+ short temp;
+- FileIdentifierTable *fileIdentifierTable = nil;
++ FileIdentifierTable *fileIdentifierTable = NULL;
+ OSErr err = noErr;
+ OSErr scavError = 0;
+ int scanCount = 0;
+@@ -228,7 +228,7 @@ DoAgain:
+ }
+
+ // Set up structures for post processing
+- if ( (autoRepair == true) && (dataArea.fileIdentifierTable != nil) )
++ if ((autoRepair == true) && (dataArea.fileIdentifierTable != NULL))
+ {
+ // *repairInfo = *repairInfo | kVolumeHadOverlappingExtents; // Report back that volume has overlapping extents
+ fileIdentifierTable = (FileIdentifierTable *) AllocateMemory( GetHandleSize( (Handle) dataArea.fileIdentifierTable ) );
+@@ -239,7 +239,7 @@ DoAgain:
+ //
+ // Post processing
+ //
+- if ( fileIdentifierTable != nil )
++ if (fileIdentifierTable != NULL)
+ {
+ DisposeMemory( fileIdentifierTable );
+ }
+@@ -682,7 +682,7 @@ short CheckForStop( SGlob *GPtr )
+
+ //if ( ((ticks - 10) > GPtr->lastTickCount) || (dfaStage == kAboutToRepairStage) ) // To reduce cursor flicker on fast machines, call through on a timed interval
+ //{
+- if ( GPtr->userCancelProc != nil )
++ if (GPtr->userCancelProc != NULL)
+ {
+ UInt64 progress = 0;
+ Boolean progressChanged;
+@@ -761,7 +761,7 @@ static int ScavSetUp( SGlob *GPtr)
+ short ioRefNum;
+ #endif
+
+- GPtr->MinorRepairsP = nil;
++ GPtr->MinorRepairsP = NULL;
+
+ GPtr->itemsProcessed = 0;
+ GPtr->lastProgress = 0;
+@@ -774,7 +774,7 @@ static int ScavSetUp( SGlob *GPtr)
+ ScavStaticStructures *pointer;
+
+ pointer = (ScavStaticStructures *) AllocateClearMemory( sizeof(ScavStaticStructures) );
+- if ( pointer == nil ) {
++ if (pointer == NULL) {
+ if ( GPtr->logLevel >= kDebugLog ) {
+ printf( "\t error %d - could not allocate %i bytes of memory \n",
+ R_NoMem, sizeof(ScavStaticStructures) );
+@@ -831,7 +831,7 @@ static int ScavSetUp( SGlob *GPtr)
+ // Save current value of vcbWrCnt, to detect modifications to volume by other apps etc
+ if ( GPtr->volumeFeatures & volumeIsMountedMask )
+ {
+- FlushVol( nil, GPtr->realVCB->vcbVRefNum ); // Ask HFS to update all changes to disk
++ FlushVol(NULL, GPtr->realVCB->vcbVRefNum); // Ask HFS to update all changes to disk
+ GPtr->wrCnt = GPtr->realVCB->vcbWrCnt; // Remember write count after writing changes
+ }
+ #endif
+@@ -949,7 +949,7 @@ static int ScavSetUp( SGlob *GPtr)
+
+ // Keep a valid file id list for HFS volumes
+ GPtr->validFilesList = (UInt32**)NewHandle( 0 );
+- if ( GPtr->validFilesList == nil ) {
++ if (GPtr->validFilesList == NULL) {
+ if ( GPtr->logLevel >= kDebugLog ) {
+ printf( "\t error %d - could not allocate file ID list \n", R_NoMem );
+ }
+@@ -995,17 +995,17 @@ static int ScavTerm( SGlobPtr GPtr )
+
+ (void) BitMapCheckEnd();
+
+- while( (rP = GPtr->MinorRepairsP) != nil ) // loop freeing leftover (undone) repair orders
++ while((rP = GPtr->MinorRepairsP) != NULL) // loop freeing leftover (undone) repair orders
+ {
+ GPtr->MinorRepairsP = rP->link; // (in case repairs were not made)
+ DisposeMemory(rP);
+ err = MemError();
+ }
+
+- if( GPtr->validFilesList != nil )
++ if (GPtr->validFilesList != NULL)
+ DisposeHandle( (Handle) GPtr->validFilesList );
+
+- if( GPtr->overlappedExtents != nil ) {
++ if (GPtr->overlappedExtents != NULL) {
+ extentsTableH = GPtr->overlappedExtents;
+
+ /* Overlapped extents list also allocated memory for attribute name */
+@@ -1021,44 +1021,44 @@ static int ScavTerm( SGlobPtr GPtr )
+ DisposeHandle( (Handle) GPtr->overlappedExtents );
+ }
+
+- if( GPtr->fileIdentifierTable != nil )
++ if (GPtr->fileIdentifierTable != NULL)
+ DisposeHandle( (Handle) GPtr->fileIdentifierTable );
+
+- if( GPtr->calculatedVCB == nil ) // already freed?
++ if (GPtr->calculatedVCB == NULL) // already freed?
+ return( noErr );
+
+ // If the FCB's and BTCB's have been set up, dispose of them
+ fcbP = GPtr->calculatedExtentsFCB; // release extent file BTree bit map
+- if ( fcbP != nil )
++ if (fcbP != NULL)
+ {
+ btcbP = (BTreeControlBlock*)fcbP->fcbBtree;
+- if ( btcbP != nil)
++ if (btcbP != NULL)
+ {
+- if( btcbP->refCon != nil )
++ if (btcbP->refCon != NULL)
+ {
+- if(((BTreeExtensionsRec*)btcbP->refCon)->BTCBMPtr != nil)
++ if (((BTreeExtensionsRec*)btcbP->refCon)->BTCBMPtr != NULL)
+ {
+ DisposeMemory(((BTreeExtensionsRec*)btcbP->refCon)->BTCBMPtr);
+ err = MemError();
+ }
+ DisposeMemory( (Ptr)btcbP->refCon );
+ err = MemError();
+- btcbP->refCon = nil;
++ btcbP->refCon = NULL;
+ }
+
+ fcbP = GPtr->calculatedCatalogFCB; // release catalog BTree bit map
+ btcbP = (BTreeControlBlock*)fcbP->fcbBtree;
+
+- if( btcbP->refCon != nil )
++ if (btcbP->refCon != NULL)
+ {
+- if(((BTreeExtensionsRec*)btcbP->refCon)->BTCBMPtr != nil)
++ if (((BTreeExtensionsRec*)btcbP->refCon)->BTCBMPtr != NULL)
+ {
+ DisposeMemory(((BTreeExtensionsRec*)btcbP->refCon)->BTCBMPtr);
+ err = MemError();
+ }
+ DisposeMemory( (Ptr)btcbP->refCon );
+ err = MemError();
+- btcbP->refCon = nil;
++ btcbP->refCon = NULL;
+ }
+ }
+ }
+@@ -1066,7 +1066,7 @@ static int ScavTerm( SGlobPtr GPtr )
+ DisposeMemory( GPtr->calculatedVCB ); // Release our block of data structures
+ err = MemError();
+
+- GPtr->calculatedVCB = nil;
++ GPtr->calculatedVCB = NULL;
+
+ return( noErr );
+ }
+@@ -1113,7 +1113,7 @@ Boolean IsBlueBoxSharedDrive ( DrvQElPtr
+ // Now look at the name of the Driver name. If it is .BlueBoxShared keep it out of the list of available disks.
+ driverDCtlHandle = GetDCtlEntry(dqPtr->dQRefNum);
+ driverDCtlPtr = *driverDCtlHandle;
+- if((((driverDCtlPtr->dCtlFlags) & Is_Native_Mask) == 0) && (driverDCtlPtr->dCtlDriver != nil))
++ if((((driverDCtlPtr->dCtlFlags) & Is_Native_Mask) == 0) && (driverDCtlPtr->dCtlDriver != NULL))
+ {
+ if (((driverDCtlPtr->dCtlFlags) & Is_Ram_Based_Mask) == 0)
+ {
+@@ -1127,19 +1127,19 @@ Boolean IsBlueBoxSharedDrive ( DrvQElPtr
+
+ }
+ driverName = (StringPtr)&(drvrHeaderPtr->drvrName);
+- if (!(IdenticalString(driverName,blueBoxSharedDriverName,nil)))
++ if (!(IdenticalString(driverName,blueBoxSharedDriverName,NULL)))
+ {
+ return( true );
+ }
+
+ // Special case for the ".Sony" floppy driver which might be accessed in Shared mode inside the Blue Box
+ // Test its "where" string instead of the driver name.
+- if (!(IdenticalString(driverName,sonyDriverName,nil)))
++ if (!(IdenticalString(driverName,sonyDriverName,NULL)))
+ {
+ CntrlParam paramBlock;
+
+- paramBlock.ioCompletion = nil;
+- paramBlock.ioNamePtr = nil;
++ paramBlock.ioCompletion = NULL;
++ paramBlock.ioNamePtr = NULL;
+ paramBlock.ioVRefNum = dqPtr->dQDrive;
+ paramBlock.ioCRefNum = dqPtr->dQRefNum;
+ paramBlock.csCode = kDriveIcon; // return physical icon
+@@ -1152,7 +1152,7 @@ Boolean IsBlueBoxSharedDrive ( DrvQElPtr
+
+ iconAndStringRecPtr = * (IconAndStringRecPtr*) & paramBlock.csParam;
+ whereStringPtr = (StringPtr) & iconAndStringRecPtr->string;
+- if (!(IdenticalString(whereStringPtr,blueBoxFloppyWhereString,nil)))
++ if (!(IdenticalString(whereStringPtr,blueBoxFloppyWhereString,NULL)))
+ {
+ return( true );
+ }
+--- a/fsck_hfs.tproj/dfalib/SRepair.c
++++ b/fsck_hfs.tproj/dfalib/SRepair.c
+@@ -844,7 +844,7 @@ static int DelFThd( SGlobPtr GPtr, UInt3
+
+ isHFSPlus = VolumeObjectIsHFSPlus( );
+
+- BuildCatalogKey( fid, (const CatalogName*) nil, isHFSPlus, &key );
++ BuildCatalogKey(fid, NULL, isHFSPlus, &key);
+ result = SearchBTreeRecord( GPtr->calculatedCatalogFCB, &key, kNoHint, &foundKey, &record, &recSize, &hint );
+
+ if ( result ) return ( IntError( GPtr, result ) );
+@@ -910,7 +910,7 @@ static OSErr FixDirThread( SGlobPtr GPtr
+
+ isHFSPlus = VolumeObjectIsHFSPlus( );
+
+- BuildCatalogKey( did, (const CatalogName*) nil, isHFSPlus, &key );
++ BuildCatalogKey(did, NULL, isHFSPlus, &key);
+ result = SearchBTreeRecord( GPtr->calculatedCatalogFCB, &key, kNoHint, &foundKey, &record, &recSize, &hint );
+
+ if ( result )
+@@ -2171,7 +2171,7 @@ static OSErr FixOrphanedFiles ( SGlobPtr
+ }
+
+ //-- Build the key for the file thread
+- BuildCatalogKey( cNodeID, nil, isHFSPlus, &key );
++ BuildCatalogKey(cNodeID, NULL, isHFSPlus, &key);
+
+ err = SearchBTreeRecord( GPtr->calculatedCatalogFCB, &key, kNoHint,
+ &tempKey, &threadRecord, &recordSize, &hint2 );
+--- a/fsck_hfs.tproj/dfalib/SUtils.c
++++ b/fsck_hfs.tproj/dfalib/SUtils.c
+@@ -395,11 +395,11 @@ OSErr GetVolumeFeatures( SGlobPtr GPtr )
+ err = GetVCBDriveNum( &GPtr->realVCB, GPtr->DrvNum );
+ ReturnIfError( err );
+
+- if ( GPtr->realVCB != nil )
++ if (GPtr->realVCB != NULL)
+ {
+ GPtr->volumeFeatures |= volumeIsMountedMask;
+
+- pb.ioParam.ioNamePtr = nil;
++ pb.ioParam.ioNamePtr = NULL;
+ pb.ioParam.ioVRefNum = GPtr->realVCB->vcbVRefNum;
+ pb.ioParam.ioBuffer = (Ptr) &buffer;
+ pb.ioParam.ioReqCount = sizeof( buffer );
+@@ -2282,7 +2282,7 @@ void print_prime_buckets(PrimeBuckets *c
+ * 4. btreetye - can be kHFSPlusCatalogRecord or kHFSPlusAttributeRecord
+ * indicates which btree prime number bucket should be incremented
+ *
+- * Output: nil
++ * Output: NULL
+ */
+ void RecordXAttrBits(SGlobPtr GPtr, UInt16 flags, HFSCatalogNodeID fileid, UInt16 btreetype)
+ {
+--- a/fsck_hfs.tproj/dfalib/SVerify1.c
++++ b/fsck_hfs.tproj/dfalib/SVerify1.c
+@@ -790,13 +790,13 @@ OSErr CreateExtentsBTreeControlBlock( SG
+ // set up our DFA extended BTCB area. Will we have enough memory on all HFS+ volumes.
+ //
+ btcb->refCon = AllocateClearMemory( sizeof(BTreeExtensionsRec) ); // allocate space for our BTCB extensions
+- if ( btcb->refCon == nil ) {
++ if (btcb->refCon == NULL) {
+ err = R_NoMem;
+ goto exit;
+ }
+ size = (btcb->totalNodes + 7) / 8; // size of BTree bit map
+ ((BTreeExtensionsRec*)btcb->refCon)->BTCBMPtr = AllocateClearMemory(size); // get precleared bitmap
+- if ( ((BTreeExtensionsRec*)btcb->refCon)->BTCBMPtr == nil )
++ if (((BTreeExtensionsRec*)btcb->refCon)->BTCBMPtr == NULL)
+ {
+ err = R_NoMem;
+ goto exit;
+@@ -1145,13 +1145,13 @@ OSErr CreateCatalogBTreeControlBlock( SG
+ //
+
+ btcb->refCon = AllocateClearMemory( sizeof(BTreeExtensionsRec) ); // allocate space for our BTCB extensions
+- if ( btcb->refCon == nil ) {
++ if (btcb->refCon == NULL) {
+ err = R_NoMem;
+ goto exit;
+ }
+ size = (btcb->totalNodes + 7) / 8; // size of BTree bit map
+ ((BTreeExtensionsRec*)btcb->refCon)->BTCBMPtr = AllocateClearMemory(size); // get precleared bitmap
+- if ( ((BTreeExtensionsRec*)btcb->refCon)->BTCBMPtr == nil )
++ if (((BTreeExtensionsRec*)btcb->refCon)->BTCBMPtr == NULL)
+ {
+ err = R_NoMem;
+ goto exit;
+@@ -1339,7 +1339,7 @@ OSErr CatHChk( SGlobPtr GPtr )
+
+ //¥¥ Can we ignore this part by just taking advantage of setting the selCode = 0x8001;
+ {
+- BuildCatalogKey( 1, (const CatalogName *)nil, isHFSPlus, &key );
++ BuildCatalogKey(1, NULL, isHFSPlus, &key);
+ result = SearchBTreeRecord( GPtr->calculatedCatalogFCB, &key, kNoHint, &foundKey, &threadRecord, &recSize, &hint );
+
+ GPtr->TarBlock = hint; /* set target block */
+@@ -1443,7 +1443,7 @@ OSErr CatHChk( SGlobPtr GPtr )
+ /*
+ * Find thread record
+ */
+- BuildCatalogKey( dprP->directoryID, (const CatalogName *) nil, isHFSPlus, &key );
++ BuildCatalogKey(dprP->directoryID, NULL, isHFSPlus, &key);
+ result = SearchBTreeRecord( GPtr->calculatedCatalogFCB, &key, kNoHint, &foundKey, &threadRecord, &recSize, &hint );
+ if ( result != noErr ) {
+ char idStr[16];
+@@ -1780,26 +1780,26 @@ OSErr CreateAttributesBTreeControlBlock(
+ // set up our DFA extended BTCB area. Will we have enough memory on all HFS+ volumes.
+ //
+ btcb->refCon = AllocateClearMemory( sizeof(BTreeExtensionsRec) ); // allocate space for our BTCB extensions
+- if ( btcb->refCon == nil ) {
++ if (btcb->refCon == NULL) {
+ err = R_NoMem;
+ goto exit;
+ }
+
+ if (btcb->totalNodes == 0)
+ {
+- ((BTreeExtensionsRec*)btcb->refCon)->BTCBMPtr = nil;
++ ((BTreeExtensionsRec*)btcb->refCon)->BTCBMPtr = NULL;
+ ((BTreeExtensionsRec*)btcb->refCon)->BTCBMSize = 0;
+ ((BTreeExtensionsRec*)btcb->refCon)->realFreeNodeCount = 0;
+ }
+ else
+ {
+- if ( btcb->refCon == nil ) {
++ if (btcb->refCon == NULL) {
+ err = R_NoMem;
+ goto exit;
+ }
+ size = (btcb->totalNodes + 7) / 8; // size of BTree bit map
+ ((BTreeExtensionsRec*)btcb->refCon)->BTCBMPtr = AllocateClearMemory(size); // get precleared bitmap
+- if ( ((BTreeExtensionsRec*)btcb->refCon)->BTCBMPtr == nil )
++ if (((BTreeExtensionsRec*)btcb->refCon)->BTCBMPtr == NULL)
+ {
+ err = R_NoMem;
+ goto exit;
+@@ -2358,7 +2358,7 @@ static OSErr RcdMDBEmbededVolDescription
+ RcdError( GPtr, type ); // first, record the error
+
+ p = AllocMinorRepairOrder( GPtr, sizeof(EmbededVolDescription) ); // get the node
+- if ( p == nil ) return( R_NoMem );
++ if (p == NULL) return( R_NoMem );
+
+ p->type = type; // save error info
+ desc = (EmbededVolDescription *) &(p->name);
+@@ -2397,7 +2397,7 @@ static OSErr RcdInvalidWrapperExtents( S
+ RcdError( GPtr, type ); // first, record the error
+
+ p = AllocMinorRepairOrder( GPtr, 0 ); // get the node
+- if ( p == nil ) return( R_NoMem );
++ if (p == NULL) return( R_NoMem );
+
+ p->type = type; // save error info
+
+@@ -3029,7 +3029,7 @@ OSErr CheckFileExtents( SGlobPtr GPtr, U
+ foundBadExtent = false;
+ lastExtentIndex = GPtr->numExtents;
+
+- while ( (extents != nil) && (err == noErr) )
++ while ((extents != NULL) && (err == noErr))
+ {
+ // checkout the extent record first
+ err = ChkExtRec( GPtr, extents, &lastExtentIndex );
+@@ -3105,7 +3105,7 @@ OSErr CheckFileExtents( SGlobPtr GPtr, U
+ if ( err == btNotFound )
+ {
+ err = noErr; // no more extent records
+- extents = nil;
++ extents = NULL;
+ break;
+ }
+ else if ( err != noErr )
+@@ -3121,7 +3121,7 @@ OSErr CheckFileExtents( SGlobPtr GPtr, U
+ if ( err == btNotFound )
+ {
+ err = noErr; // no more extent records
+- extents = nil;
++ extents = NULL;
+ break;
+ }
+ else if ( err != noErr )
+@@ -3205,7 +3205,7 @@ static OSErr AddExtentToOverlapList( SGl
+ }
+
+ // If it's uninitialized
+- if ( GPtr->overlappedExtents == nil )
++ if (GPtr->overlappedExtents == NULL)
+ {
+ GPtr->overlappedExtents = (ExtentsTable **) NewHandleClear( sizeof(ExtentsTable) );
+ extentsTableH = GPtr->overlappedExtents;
+--- a/fsck_hfs.tproj/dfalib/SVerify2.c
++++ b/fsck_hfs.tproj/dfalib/SVerify2.c
+@@ -1013,7 +1013,7 @@ static int BTKeyChk( SGlobPtr GPtr, Node
+ UInt16 keyLength;
+ KeyPtr keyPtr;
+ UInt8 *dataPtr;
+- KeyPtr prevkeyP = nil;
++ KeyPtr prevkeyP = NULL;
+
+
+ if ( nodeP->numRecords == 0 )
+@@ -1044,7 +1044,7 @@ static int BTKeyChk( SGlobPtr GPtr, Node
+ return( E_KeyLen );
+ }
+
+- if ( prevkeyP != nil )
++ if (prevkeyP != NULL)
+ {
+ if ( CompareKeys( (BTreeControlBlockPtr)btcb, prevkeyP, keyPtr ) >= 0 )
+ {
diff --git a/external/subpack/utils/hfsprogs/patches/0011-Fix-types.patch b/external/subpack/utils/hfsprogs/patches/0011-Fix-types.patch
new file mode 100644
index 0000000..0bcfe25
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0011-Fix-types.patch
@@ -0,0 +1,69 @@
+From: =?UTF-8?q?Rog=C3=A9rio=20Brito?= <rbrito@ime.usp.br>
+Date: Thu, 24 Oct 2013 01:11:22 -0200
+Subject: Fix types
+
+---
+ fsck_hfs.tproj/cache.c | 30 ++++++++++++++++--------------
+ 1 file changed, 16 insertions(+), 14 deletions(-)
+
+--- a/fsck_hfs.tproj/cache.c
++++ b/fsck_hfs.tproj/cache.c
+@@ -961,20 +961,21 @@ int CacheLookup (Cache_t *cache, uint64_
+ */
+ int CacheRawRead (Cache_t *cache, uint64_t off, uint32_t len, void *buf)
+ {
+- uint64_t result;
++ off_t result1;
++ ssize_t result2;
+
+ /* Both offset and length must be multiples of the device block size */
+ if (off % cache->DevBlockSize) return (EINVAL);
+ if (len % cache->DevBlockSize) return (EINVAL);
+
+ /* Seek to the position */
+- result = lseek (cache->FD_R, off, SEEK_SET);
+- if (result < 0) return (errno);
+- if (result != off) return (ENXIO);
++ result1 = lseek(cache->FD_R, off, SEEK_SET);
++ if (result1 < 0) return (errno);
++ if (result1 != off) return (ENXIO);
+ /* Read into the buffer */
+- result = read (cache->FD_R, buf, len);
+- if (result < 0) return (errno);
+- if (result == 0) return (ENXIO);
++ result2 = read(cache->FD_R, buf, len);
++ if (result2 < 0) return (errno);
++ if (result2 == 0) return (ENXIO);
+
+ /* Update counters */
+ cache->DiskRead++;
+@@ -989,21 +990,22 @@ int CacheRawRead (Cache_t *cache, uint64
+ */
+ int CacheRawWrite (Cache_t *cache, uint64_t off, uint32_t len, void *buf)
+ {
+- uint64_t result;
++ off_t result1;
++ ssize_t result2;
+
+ /* Both offset and length must be multiples of the device block size */
+ if (off % cache->DevBlockSize) return (EINVAL);
+ if (len % cache->DevBlockSize) return (EINVAL);
+
+ /* Seek to the position */
+- result = lseek (cache->FD_W, off, SEEK_SET);
+- if (result < 0) return (errno);
+- if (result != off) return (ENXIO);
++ result1 = lseek (cache->FD_W, off, SEEK_SET);
++ if (result1 < 0) return (errno);
++ if (result1 != off) return (ENXIO);
+
+ /* Write into the buffer */
+- result = write (cache->FD_W, buf, len);
+- if (result < 0) return (errno);
+- if (result == 0) return (ENXIO);
++ result2 = write (cache->FD_W, buf, len);
++ if (result2 < 0) return (errno);
++ if (result2 == 0) return (ENXIO);
+
+ /* Update counters */
+ cache->DiskWrite++;
diff --git a/external/subpack/utils/hfsprogs/patches/0012-Fix-mkfs-not-creating-UUIDs-for-new-filesystems.patch b/external/subpack/utils/hfsprogs/patches/0012-Fix-mkfs-not-creating-UUIDs-for-new-filesystems.patch
new file mode 100644
index 0000000..0645fa7
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0012-Fix-mkfs-not-creating-UUIDs-for-new-filesystems.patch
@@ -0,0 +1,48 @@
+From: Matthew Garrett <mjg59@codon.org.uk>
+Date: Thu, 24 Oct 2013 01:11:22 -0200
+Subject: Fix mkfs not creating UUIDs for new filesystems.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Fix mkfs not creating UUIDs for new filesystems.
+
+Thanks to Lars Noodén for reporting the bug at
+ <https://bugs.launchpad.net/bugs/737002>.
+
+This closes LP: #737002.
+---
+ include/missing.h | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/include/missing.h
++++ b/include/missing.h
+@@ -71,7 +71,7 @@
+ #define NAME_MAX 255
+
+ /* Byteswap stuff */
+-#define NXSwapHostLongToBig(x) cpu_to_be64(x)
++#define NXSwapHostLongToBig(x) cpu_to_be32(x)
+ #define NXSwapBigShortToHost(x) be16_to_cpu(x)
+ #define OSSwapBigToHostInt16(x) be16_to_cpu(x)
+ #define NXSwapBigLongToHost(x) be32_to_cpu(x)
+@@ -87,6 +87,9 @@
+ #ifndef be32_to_cpu
+ #define be32_to_cpu(x) bswap_32(x)
+ #endif
++#ifndef cpu_to_be32
++#define cpu_to_be32(x) bswap_32(x)
++#endif
+ #ifndef be64_to_cpu
+ #define be64_to_cpu(x) bswap_64(x)
+ #endif
+@@ -101,6 +104,9 @@
+ #ifndef be32_to_cpu
+ #define be32_to_cpu(x) (x)
+ #endif
++#ifndef cpu_to_be32
++#define cpu_to_be32(x) (x)
++#endif
+ #ifndef be64_to_cpu
+ #define be64_to_cpu(x) (x)
+ #endif
diff --git a/external/subpack/utils/hfsprogs/patches/0013-Fix-manpages.patch b/external/subpack/utils/hfsprogs/patches/0013-Fix-manpages.patch
new file mode 100644
index 0000000..736841f
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0013-Fix-manpages.patch
@@ -0,0 +1,153 @@
+From: =?UTF-8?q?Rog=C3=A9rio=20Theodoro=20de=20Brito?= <rbrito@ime.usp.br>
+Date: Thu, 25 Nov 2010 00:00:00 -0200
+Subject: Fix manpages
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Remove typos, references in the "See also" sections of the manpages to
+commands that are not available in Debian systems (and, quite probably,
+other systems too) and non-Linux specific comments.
+
+Authored also by Christoph Hellwig <hch@lst.de> and "A. Costa" <agcosta@gis.net>
+
+Bug-Debian: http://bugs.debian.org/598714
+Bug-Debian: http://bugs.debian.org/575201
+Forwarded: no
+Reviewed-by: Rogério Theodoro de Brito <rbrito@ime.usp.br>
+---
+ fsck_hfs.tproj/fsck_hfs.8 | 18 +++++++-----------
+ newfs_hfs.tproj/newfs_hfs.8 | 23 ++++++++---------------
+ 2 files changed, 15 insertions(+), 26 deletions(-)
+
+--- a/fsck_hfs.tproj/fsck_hfs.8
++++ b/fsck_hfs.tproj/fsck_hfs.8
+@@ -19,18 +19,18 @@
+ .Dt FSCK_HFS 8
+ .Os "Mac OS X"
+ .Sh NAME
+-.Nm fsck_hfs
++.Nm fsck.hfs
+ .Nd HFS file system consistency check
+ .Sh SYNOPSIS
+-.Nm fsck_hfs
++.Nm fsck.hfs
+ .Fl q
+ .Op Fl df
+ .Ar special ...
+-.Nm fsck_hfs
++.Nm fsck.hfs
+ .Fl p
+ .Op Fl df
+ .Ar special ...
+-.Nm fsck_hfs
++.Nm fsck.hfs
+ .Op Fl n | y | r
+ .Op Fl dfgl
+ .Op Fl m Ar mode
+@@ -52,9 +52,7 @@ The second form of
+ preens the specified file systems.
+ It is normally started by
+ .Xr fsck 8
+-run from
+-.Pa /etc/rc.boot
+-during automatic reboot, when a HFS file system is detected.
++during systen boot, when a HFS file system is detected.
+ When preening file systems,
+ .Nm
+ will fix common inconsistencies for file systems that were not
+@@ -105,9 +103,9 @@ to check and repair journaled HFS+ file
+ .It Fl g
+ Causes
+ .Nm
+-to generate it's output strings in GUI format.
++to generate its output strings in GUI format.
+ This option is used when another application with a graphical user interface
+-(like Mac OS X Disk Utility) is envoking the
++(like Mac OS X Disk Utility) is invoking the
+ .Nm
+ tool.
+ .It Fl l
+@@ -144,8 +142,6 @@ specified file system for a new catalog
+ to the leaf nodes in the existing catalog file.
+ .El
+ .Pp
+-Because of inconsistencies between the block device and the buffer cache,
+-the raw device should always be used.
+ .Sh SEE ALSO
+ .Xr fsck 8
+ .Sh BUGS
+--- a/newfs_hfs.tproj/newfs_hfs.8
++++ b/newfs_hfs.tproj/newfs_hfs.8
+@@ -19,10 +19,10 @@
+ .Dt NEWFS_HFS 8
+ .Os "Mac OS X"
+ .Sh NAME
+-.Nm newfs_hfs
++.Nm mkfs.hfs
+ .Nd construct a new HFS Plus file system
+ .Sh SYNOPSIS
+-.Nm newfs_hfs
++.Nm mkfs.hfs
+ .Op Fl N Ar [partition-size]
+ .Op Fl U Ar uid
+ .Op Fl G Ar gid
+@@ -37,19 +37,13 @@
+ .Op Fl v Ar volume-name
+ .Ar special
+ .Sh DESCRIPTION
+-.Nm Newfs_hfs
++.Nm mkfs.hfs
+ builds an HFS Plus file system on the specified special device.
+-Before running
+-.Nm newfs_hfs
+-the disk should be partitioned using the
+-.Em Disk Utility
+-application or
+-.Xr pdisk 8 .
+ .Pp
+ The file system default parameters are calculated based on
+ the size of the disk partition. Typically the defaults are
+ reasonable, however
+-.Nm newfs_hfs
++.Nm mkfs.hfs
+ has several options to allow the defaults to be selectively overridden.
+ The options are as follows:
+ .Bl -tag -width Fl
+@@ -66,7 +60,7 @@ Set the group of the file system's root
+ Specify the access permissions mask for the file system's root directory.
+ .It Fl h
+ Creates a legacy HFS format filesystem. This option
+-is not recomended for file systems that will be
++is not recommended for file systems that will be
+ primarily used with Mac OS X or Darwin.
+ .It Fl s
+ Creates a case-sensitive HFS Plus filesystem. By
+@@ -93,7 +87,7 @@ sizes are specified with the
+ option followed by a comma
+ separated list of the form arg=blocks.
+ .Pp
+-Example: -c c=5000,e=500
++Example: \-c c=5000,e=500
+ .Bl -tag -width Fl
+ .It Em a=blocks
+ Set the attribute file clump size.
+@@ -126,7 +120,7 @@ the form arg=bytes. The
+ size must be a power of two and no larger than
+ 32768 bytes.
+ .Pp
+-Example: -n c=8192,e=4096
++Example: \-n c=8192,e=4096
+ .Bl -tag -width Fl
+ .It Em a=bytes
+ Set the attribute b-tree node size.
+@@ -139,8 +133,7 @@ Set the extent overflow b-tree node size
+ Volume name (file system name) in ascii or UTF-8 format.
+ .El
+ .Sh SEE ALSO
+-.Xr mount 8 ,
+-.Xr pdisk 8
++.Xr mount 8
+ .Sh HISTORY
+ The
+ .Nm
diff --git a/external/subpack/utils/hfsprogs/patches/0014-uClibc_no_loadavg.patch b/external/subpack/utils/hfsprogs/patches/0014-uClibc_no_loadavg.patch
new file mode 100644
index 0000000..7d5e975
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0014-uClibc_no_loadavg.patch
@@ -0,0 +1,15 @@
+--- a/newfs_hfs.tproj/makehfs.c
++++ b/newfs_hfs.tproj/makehfs.c
+@@ -2119,10 +2119,12 @@ void GenerateVolumeUUID(VolumeUUID *newV
+ sysctl(mib, 2, sysctlstring, &datalen, NULL, 0);
+ SHA1_Update(&context, sysctlstring, datalen);
+ #endif
++#ifndef __UCLIBC__
+ /* The system's load average: */
+ datalen = sizeof(sysloadavg);
+ getloadavg(sysloadavg, 3);
+ SHA1_Update(&context, &sysloadavg, datalen);
++#endif
+
+ /* The system's VM statistics: */
+ #if !LINUX
diff --git a/external/subpack/utils/hfsprogs/patches/0015-sysctl-only-on-glibc.patch b/external/subpack/utils/hfsprogs/patches/0015-sysctl-only-on-glibc.patch
new file mode 100644
index 0000000..257bbca
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0015-sysctl-only-on-glibc.patch
@@ -0,0 +1,91 @@
+--- a/newfs_hfs.tproj/makehfs.c
++++ b/newfs_hfs.tproj/makehfs.c
+@@ -37,7 +37,9 @@
+ #endif
+ #include <sys/errno.h>
+ #include <sys/stat.h>
++#if 0
+ #include <sys/sysctl.h>
++#endif
+ #if !LINUX
+ #include <sys/vmmeter.h>
+ #endif
+@@ -2039,6 +2041,7 @@ getencodinghint(unsigned char *name)
+ if (getvfsbyname("hfs", &vfc) < 0)
+ goto error;
+
++#ifdef __GLIBC__
+ mib[0] = CTL_VFS;
+ mib[1] = vfc.vfc_typenum;
+ mib[2] = HFS_ENCODINGHINT;
+@@ -2046,6 +2049,7 @@ getencodinghint(unsigned char *name)
+ if (sysctl(mib, 3, &hint, &buflen, name, strlen((char *)name) + 1) < 0)
+ goto error;
+ return (hint);
++#endif
+ error:
+ hint = GetDefaultEncoding();
+ return (0);
+@@ -2062,7 +2066,7 @@ void GenerateVolumeUUID(VolumeUUID *newV
+ clock_t uptime;
+ size_t datalen;
+ double sysloadavg[3];
+-#if !LINUX
++#if !LINUX && defined(__GLIBC__)
+ int sysdata;
+ int mib[2];
+ char sysctlstring[128];
+@@ -2080,7 +2084,7 @@ void GenerateVolumeUUID(VolumeUUID *newV
+ SHA1_Update(&context, &uptime, sizeof(uptime));
+
+ /* The kernel's boot time: */
+-#if !LINUX
++#if !LINUX && defined(__GLIBC__)
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_BOOTTIME;
+ datalen = sizeof(sysdata);
+@@ -2088,7 +2092,7 @@ void GenerateVolumeUUID(VolumeUUID *newV
+ SHA1_Update(&context, &sysdata, datalen);
+ #endif
+ /* The system's host id: */
+-#if !LINUX
++#if !LINUX && defined(__GLIBC__)
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_HOSTID;
+ datalen = sizeof(sysdata);
+@@ -2096,7 +2100,7 @@ void GenerateVolumeUUID(VolumeUUID *newV
+ SHA1_Update(&context, &sysdata, datalen);
+ #endif
+ /* The system's host name: */
+-#if !LINUX
++#if !LINUX && defined(__GLIBC__)
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_HOSTNAME;
+ datalen = sizeof(sysctlstring);
+@@ -2104,7 +2108,7 @@ void GenerateVolumeUUID(VolumeUUID *newV
+ SHA1_Update(&context, sysctlstring, datalen);
+ #endif
+ /* The running kernel's OS release string: */
+-#if !LINUX
++#if !LINUX && defined(__GLIBC__)
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_OSRELEASE;
+ datalen = sizeof(sysctlstring);
+@@ -2112,7 +2116,7 @@ void GenerateVolumeUUID(VolumeUUID *newV
+ SHA1_Update(&context, sysctlstring, datalen);
+ #endif
+ /* The running kernel's version string: */
+-#if !LINUX
++#if !LINUX && defined(__GLIBC__)
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_VERSION;
+ datalen = sizeof(sysctlstring);
+@@ -2127,7 +2131,7 @@ void GenerateVolumeUUID(VolumeUUID *newV
+ #endif
+
+ /* The system's VM statistics: */
+-#if !LINUX
++#if !LINUX && defined(__GLIBC__)
+ mib[0] = CTL_VM;
+ mib[1] = VM_METER;
+ datalen = sizeof(sysvmtotal);
diff --git a/external/subpack/utils/hfsprogs/patches/0016-Fix-fsckhfs-wide-literal.patch b/external/subpack/utils/hfsprogs/patches/0016-Fix-fsckhfs-wide-literal.patch
new file mode 100644
index 0000000..3d4c404
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/0016-Fix-fsckhfs-wide-literal.patch
@@ -0,0 +1,11 @@
+--- a/fsck_hfs.tproj/dfalib/SVerify1.c
++++ b/fsck_hfs.tproj/dfalib/SVerify1.c
+@@ -2848,7 +2848,7 @@ OSErr VLockedChk( SGlobPtr GPtr )
+ }
+ else // Because we don't have the unicode converters, just fill it with a dummy name.
+ {
+- CopyMemory( "\x0dPure HFS Plus", calculatedVCB->vcbVN, sizeof(Str27) );
++ CopyMemory( u"\x0dPure HFS Plus", calculatedVCB->vcbVN, sizeof(Str27) );
+ }
+
+ GPtr->TarBlock = hint;
diff --git a/external/subpack/utils/hfsprogs/patches/010-valloc-to-memalign.patch b/external/subpack/utils/hfsprogs/patches/010-valloc-to-memalign.patch
new file mode 100644
index 0000000..9cc9a6d
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/010-valloc-to-memalign.patch
@@ -0,0 +1,20 @@
+--- a/newfs_hfs.tproj/makehfs.c
++++ b/newfs_hfs.tproj/makehfs.c
+@@ -376,7 +376,7 @@ make_hfsplus(const DriveInfo *driveInfo,
+ if ( (temp & 0x01FF) != 0 )
+ temp = (temp + kBytesPerSector) & 0xFFFFFE00;
+
+- nodeBuffer = valloc((size_t)temp);
++ (void)posix_memalign(&nodeBuffer, sysconf(_SC_PAGESIZE), (size_t)temp);
+ if (nodeBuffer == NULL)
+ err(1, NULL);
+
+@@ -1814,7 +1814,7 @@ ClearDisk(const DriveInfo *driveInfo, UI
+
+ bufferSize = bufferSizeInSectors << kLog2SectorSize;
+
+- tempBuffer = valloc((size_t)bufferSize);
++ (void)posix_memalign(&tempBuffer, sysconf(_SC_PAGESIZE), (size_t)bufferSize);
+ if (tempBuffer == NULL)
+ err(1, NULL);
+
diff --git a/external/subpack/utils/hfsprogs/patches/020-cdefs.patch b/external/subpack/utils/hfsprogs/patches/020-cdefs.patch
new file mode 100644
index 0000000..0610df7
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/020-cdefs.patch
@@ -0,0 +1,30 @@
+--- a/fsck_hfs.tproj/fsck_hfs.h
++++ b/fsck_hfs.tproj/fsck_hfs.h
+@@ -24,6 +24,7 @@
+
+ #include "cache.h"
+
++#include <sys/cdefs.h>
+
+ const extern char *cdevname; /* name of device being checked */
+ extern char *progname;
+--- a/newfs_hfs.tproj/makehfs.c
++++ b/newfs_hfs.tproj/makehfs.c
+@@ -28,6 +28,7 @@
+
+ */
+
++#include <sys/cdefs.h>
+ #include <sys/param.h>
+ #include <sys/types.h>
+ #include <sys/time.h>
+--- a/newfs_hfs.tproj/newfs_hfs.c
++++ b/newfs_hfs.tproj/newfs_hfs.c
+@@ -34,6 +34,7 @@
+ #include <syslog.h>
+ #include <unistd.h>
+
++#include <sys/cdefs.h>
+ #include <sys/ioctl.h>
+ #include <sys/mount.h>
+ #include <sys/param.h>
diff --git a/external/subpack/utils/hfsprogs/patches/030-no-cdefs.patch b/external/subpack/utils/hfsprogs/patches/030-no-cdefs.patch
new file mode 100644
index 0000000..4783d69
--- /dev/null
+++ b/external/subpack/utils/hfsprogs/patches/030-no-cdefs.patch
@@ -0,0 +1,199 @@
+--- a/disklib/dump.h
++++ b/disklib/dump.h
+@@ -110,9 +110,7 @@ extern long dev_bsize; /* block size of
+ extern int dev_bshift; /* log2(dev_bsize) */
+ extern int tp_bshift; /* log2(TP_BSIZE) */
+
+-#ifndef __P
+-#include <sys/cdefs.h>
+-#endif
++#define __P(x) x
+
+ /* operator interface functions */
+ void broadcast __P((char *message));
+--- a/dump.tproj/unctime.c
++++ b/dump.tproj/unctime.c
+@@ -64,9 +64,7 @@
+ #include <string.h>
+ #endif
+
+-#ifndef __P
+-#include <sys/cdefs.h>
+-#endif
++#define __P(x) x
+
+ /*
+ * Convert a ctime(3) format string into a system format date.
+--- a/fdisk.tproj/getrawpartition.c
++++ b/fdisk.tproj/getrawpartition.c
+@@ -59,7 +59,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-#include <sys/cdefs.h>
+ #if defined(LIBC_SCCS) && !defined(lint)
+ __RCSID("$NetBSD: getrawpartition.c,v 1.4 1999/07/02 15:49:12 simonb Exp $");
+ #endif
+--- a/fdisk.tproj/util.h
++++ b/fdisk.tproj/util.h
+@@ -59,9 +59,10 @@
+ #ifndef _UTIL_H_
+ #define _UTIL_H_
+
+-#include <sys/cdefs.h>
+ #include <sys/types.h>
+
++#define __P(x) x
++
+ /*
+ * fparseln() specific operation flags.
+ */
+--- a/fsck_hfs.tproj/fsck_hfs.h
++++ b/fsck_hfs.tproj/fsck_hfs.h
+@@ -24,7 +24,7 @@
+
+ #include "cache.h"
+
+-#include <sys/cdefs.h>
++#define __P(x) x
+
+ const extern char *cdevname; /* name of device being checked */
+ extern char *progname;
+--- a/fsck_msdos.tproj/boot.c
++++ b/fsck_msdos.tproj/boot.c
+@@ -54,8 +54,6 @@
+ */
+
+
+-#include <sys/cdefs.h>
+-
+ #include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+--- a/fsck_msdos.tproj/check.c
++++ b/fsck_msdos.tproj/check.c
+@@ -54,8 +54,6 @@
+ */
+
+
+-#include <sys/cdefs.h>
+-
+ #include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+--- a/fsck_msdos.tproj/dir.c
++++ b/fsck_msdos.tproj/dir.c
+@@ -56,8 +56,6 @@
+ */
+
+
+-#include <sys/cdefs.h>
+-
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -109,6 +107,7 @@
+ #define DD_YEAR_MASK 0xFE00 /* year - 1980 */
+ #define DD_YEAR_SHIFT 9
+
++#define __P(x) x
+
+ /* dir.c */
+ static struct dosDirEntry *newDosDirEntry __P((void));
+--- a/fsck_msdos.tproj/fat.c
++++ b/fsck_msdos.tproj/fat.c
+@@ -54,8 +54,6 @@
+ */
+
+
+-#include <sys/cdefs.h>
+-
+ #include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+@@ -67,6 +65,8 @@
+ #include "ext.h"
+ #include "fsutil.h"
+
++#define __P(x) x
++
+ /*
+ * The following value should be a multiple of the sector size in bytes. The
+ * Microsoft supported sector sizes are 512, 1024, 2048, and 4096, which means
+--- a/fsck_msdos.tproj/fsutil.c
++++ b/fsck_msdos.tproj/fsutil.c
+@@ -54,8 +54,6 @@
+ * SUCH DAMAGE.
+ */
+
+-#include <sys/cdefs.h>
+-
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+@@ -74,6 +72,8 @@
+ #include "ext.h"
+ #include "fsutil.h"
+
++#define __P(x) x
++
+ static const char *dev = NULL;
+ static int hot = 0;
+ /*static int preen = 0;*/
+--- a/fsck_msdos.tproj/main.c
++++ b/fsck_msdos.tproj/main.c
+@@ -54,8 +54,6 @@
+ */
+
+
+-#include <sys/cdefs.h>
+-
+ #include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+@@ -68,6 +66,8 @@
+ #include <varargs.h>
+ #endif
+
++#define __P(x) x
++
+ #include "fsutil.h"
+ #include "ext.h"
+
+--- a/newfs_hfs.tproj/makehfs.c
++++ b/newfs_hfs.tproj/makehfs.c
+@@ -28,7 +28,6 @@
+
+ */
+
+-#include <sys/cdefs.h>
+ #include <sys/param.h>
+ #include <sys/types.h>
+ #include <sys/time.h>
+@@ -80,6 +79,7 @@ extern Boolean _CFStringGetFileSystemRep
+
+ #define kJournalFileType 0x6a726e6c /* 'jrnl' */
+
++#define __P(x) x
+
+ typedef HFSMasterDirectoryBlock HFS_MDB;
+
+--- a/newfs_hfs.tproj/newfs_hfs.c
++++ b/newfs_hfs.tproj/newfs_hfs.c
+@@ -34,7 +34,6 @@
+ #include <syslog.h>
+ #include <unistd.h>
+
+-#include <sys/cdefs.h>
+ #include <sys/ioctl.h>
+ #include <sys/mount.h>
+ #include <sys/param.h>
+@@ -62,6 +61,8 @@
+
+ #define ROUNDUP(x,y) (((x)+(y)-1)/(y)*(y))
+
++#define __P(x) x
++
+ static void getnodeopts __P((char* optlist));
+ static void getclumpopts __P((char* optlist));
+ static gid_t a_gid __P((char *));
diff --git a/external/subpack/utils/hplip/Makefile b/external/subpack/utils/hplip/Makefile
new file mode 100644
index 0000000..d31aa5e
--- /dev/null
+++ b/external/subpack/utils/hplip/Makefile
@@ -0,0 +1,114 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hplip
+PKG_VERSION:=3.21.2
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/hplip
+PKG_HASH:=410421a13e62205d41bacd3215993c89e513fb4d7fab07e23e2720465aea7c41
+
+PKG_MAINTAINER:=Luiz Angelo Daros de Luca <luizluca@gmail.com>
+PKG_LICENSE:=GPL-2.0 GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING LICENSE
+
+PKG_BUILD_PARALLEL:=1
+PKG_BUILD_DEPENDS:=libcups
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/hplip/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=HP Linux Imaging and Printing
+ URL:=https://sourceforge.net/projects/hplip/
+endef
+
+define Package/hplip/Default/description
+ HPLIP is an HP developed solution for printing, scanning, and faxing with HP inkjet and laser based printers in Linux.
+endef
+
+define Package/hplip-common
+$(call Package/hplip/Default)
+ TITLE+= (common files)
+ DEPENDS+=+libusb-1.0
+endef
+
+define Package/hplip-common/description
+$(call Package/hplip/Default/description)
+
+These are common files shared between subpackages
+endef
+
+define Package/hplip-sane
+$(call Package/hplip/Default)
+ TITLE+= (scanner drivers)
+ DEPENDS+=+libsane +hplip-common
+endef
+
+define Package/hplip-sane/description
+$(call Package/hplip/Default/description)
+
+S.A.N.E backend for HP Scanners
+endef
+
+CONFIGURE_ARGS += \
+ --disable-gui-build \
+ --disable-network-build \
+ --disable-fax-build \
+ --disable-pp-build \
+ --disable-doc-build \
+ --disable-dbus-build \
+ --disable-hpijs-only-build \
+ --disable-hpcups-install \
+ --disable-hpps-install \
+ --disable-cups-drv-install \
+ --enable-lite-build
+
+define Build/Install
+ mkdir -p $(PKG_INSTALL_DIR)/usr/share/sane
+ sed -n -e '/key="usb.product_id"/{s/.*int_outof="0x//;s/;0x/\n/g;s/".*//;p}' \
+ $(PKG_BUILD_DIR)/data/rules/20-hplip-devices.fdi | sort -u > \
+ $(PKG_INSTALL_DIR)/usr/share/sane/03f0-hplip.usbid
+endef
+
+define Package/hplip-common/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/.libs/libhpip.so* $(1)/usr/lib/
+ $(CP) $(PKG_BUILD_DIR)/.libs/libhpmud.so* $(1)/usr/lib/
+
+ $(INSTALL_DIR) $(1)/etc/hp
+ $(CP) $(PKG_BUILD_DIR)/hplip.conf $(1)/etc/hp/hplip.conf
+
+ $(INSTALL_DIR) $(1)/usr/share/hplip/data/models/
+ $(CP) $(PKG_BUILD_DIR)/data/models/models.dat $(1)/usr/share/hplip/data/models/
+endef
+
+define Package/hplip-sane/install
+ $(INSTALL_DIR) $(1)/usr/lib/sane
+ $(CP) $(PKG_BUILD_DIR)/.libs/libsane-hpaio.so* $(1)/usr/lib/sane
+
+ $(INSTALL_DIR) $(1)/etc/sane.d/dll.d/
+ $(INSTALL_DATA) ./files/hplib.conf $(1)/etc/sane.d/dll.d/hplib
+
+ $(INSTALL_DIR) $(1)/usr/share/sane
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/sane/03f0-hplip.usbid \
+ $(1)/usr/share/sane/03f0-hplip.usbid
+endef
+
+define Package/hplip-common/conffiles
+/etc/hp/hplip.conf
+endef
+
+define Package/hplip-sane/conffiles
+/etc/sane.d/dll.d/hplib
+endef
+
+$(eval $(call BuildPackage,hplip-common))
+$(eval $(call BuildPackage,hplip-sane))
diff --git a/external/subpack/utils/hplip/files/hplib.conf b/external/subpack/utils/hplip/files/hplib.conf
new file mode 100644
index 0000000..d67d370
--- /dev/null
+++ b/external/subpack/utils/hplip/files/hplib.conf
@@ -0,0 +1,2 @@
+# Load the hplib driver
+hpaio
diff --git a/external/subpack/utils/hplip/patches/010-libusb_fix.patch b/external/subpack/utils/hplip/patches/010-libusb_fix.patch
new file mode 100644
index 0000000..b630c1c
--- /dev/null
+++ b/external/subpack/utils/hplip/patches/010-libusb_fix.patch
@@ -0,0 +1,33 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -110,7 +110,7 @@ libhpmud_la_SOURCES += io/hpmud/musb_lib
+ libhpmud_la_LDFLAGS += -lusb
+ else
+ libhpmud_la_SOURCES += io/hpmud/musb.c
+-libhpmud_la_CFLAGS += -I/usr/include/libusb-1.0
++libhpmud_la_CFLAGS += ${LIBUSB_1_0_CFLAGS}
+ libhpmud_la_LDFLAGS += -lusb-1.0
+ endif
+
+@@ -363,7 +363,7 @@ hpmudext_la_CFLAGS += -Iprotocol/discove
+ endif
+
+ if !LIBUSB01_BUILD
+-hpmudext_la_CFLAGS +=-I/usr/include/libusb-1.0
++hpmudext_la_CFLAGS += ${LIBUSB_1_0_CFLAGS}
+ endif
+ endif #!HPLIP_CLASS_DRIVER
+ # ui (qt3)
+--- a/configure.in
++++ b/configure.in
+@@ -611,6 +611,10 @@ if test "$class_driver" = "no" && test "
+ else
+ AC_CHECK_LIB([usb-1.0], [libusb_init], [LIBS="$LIBS"], [AC_MSG_ERROR([cannot find libusb 1.0 support], 2)])
+ AC_CHECK_HEADERS(libusb-1.0/libusb.h, ,[AC_MSG_ERROR([cannot find libusb-1.0-devel support], 11)])
++ PKG_CHECK_MODULES(LIBUSB_1_0, [ libusb-1.0 >= 1.0.0 ], have_libusb_1_0=yes, have_libusb_1_0=no)
++ if test "$have_libusb_1_0" = "yes"; then
++ CFLAGS="$CFLAGS $LIBUSB_1_0_CFLAGS"
++ fi
+ fi
+ fi
+
diff --git a/external/subpack/utils/hplip/patches/020-remove_cups_dep_on_scan.patch b/external/subpack/utils/hplip/patches/020-remove_cups_dep_on_scan.patch
new file mode 100644
index 0000000..b7dd6c0
--- /dev/null
+++ b/external/subpack/utils/hplip/patches/020-remove_cups_dep_on_scan.patch
@@ -0,0 +1,167 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -71,7 +71,7 @@ else
+ libsane_hpaio_la_LDFLAGS = -version-info 1:0:0
+ endif
+ # The following is a interlibrary dependency that must be compiled first.
+-libsane_hpaio_la_LIBADD = libhpip.la libhpmud.la libhpipp.la $(DBUS_LIBS) -lcups -ldl
++libsane_hpaio_la_LIBADD = libhpip.la libhpmud.la libhpipp.la $(DBUS_LIBS) -ldl
+ #libsane_hpaio_la_CFLAGS = -DWITH_NONAMESPACES -DSOAP_DEBUG
+ libsane_hpaio_la_CFLAGS = $(DBUS_CFLAGS) -Iprotocol
+
+--- a/scan/sane/hpaio.c
++++ b/scan/sane/hpaio.c
+@@ -34,7 +34,6 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+-#include <cups/cups.h>
+ #include "hpmud.h"
+
+ #ifdef HAVE_LIBAVAHI
+@@ -150,98 +149,6 @@ static int GetUriLine(char *buf, char *u
+ return i;
+ }
+
+-static int AddCupsList(char *uri, char ***printer)
+-{
+- int i, stat=1;
+-
+- /* Look for hp network URIs only. */
+- if (strncasecmp(uri, "hp:/net/", 8) !=0)
+- goto bugout;
+-
+- if (*printer == NULL)
+- {
+- /* Allocate array of string pointers. */
+- *printer = malloc(sizeof(char *) * MAX_DEVICE);
+- memset(*printer, 0, sizeof(char *) * MAX_DEVICE);
+- }
+-
+- /* Ignor duplicates (ie: printer queues using the same device). */
+- for (i=0; (*printer)[i] != NULL && i<MAX_DEVICE; i++)
+- {
+- if (strcmp((*printer)[i], uri) == 0)
+- goto bugout;
+- }
+-
+- /* Find empty slot in array of pointers. */
+- for (i=0; i<MAX_DEVICE; i++)
+- {
+- if ((*printer)[i] == NULL)
+- {
+- (*printer)[i] = strdup(uri);
+- break;
+- }
+- }
+-
+- stat = 0;
+-
+-bugout:
+-
+- return stat;
+-}
+-
+-
+-static int GetCupsPrinters(char ***printer)
+-{
+- http_t *http=NULL; /* HTTP object */
+- ipp_t *request=NULL; /* IPP request object */
+- ipp_t *response=NULL; /* IPP response object */
+- ipp_attribute_t *attr; /* Current IPP attribute */
+- int cnt=0;
+-
+- /* Connect to the HTTP server */
+- if ((http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption())) == NULL)
+- goto bugout;
+-
+- /* Assemble the IPP request */
+- request = ippNew();
+-
+- ippSetOperation( request, CUPS_GET_PRINTERS );
+- ippSetRequestId( request, 1 );
+-
+- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, "utf-8");
+- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, "en");
+- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", NULL, "device-uri");
+-
+- /* Send the request and get a response. */
+- if ((response = cupsDoRequest(http, request, "/")) == NULL)
+- goto bugout;
+-
+- for (attr = ippFirstAttribute ( response ); attr != NULL; attr = ippNextAttribute( response ))
+- {
+- /* Skip leading attributes until we hit a printer. */
+- while (attr != NULL && ippGetGroupTag( attr ) != IPP_TAG_PRINTER)
+- attr = ippNextAttribute( response );
+-
+- if (attr == NULL)
+- break;
+-
+- while (attr != NULL && ippGetGroupTag( attr ) == IPP_TAG_PRINTER)
+- {
+- if (strcmp(ippGetName( attr ), "device-uri") == 0 && ippGetValueTag( attr ) == IPP_TAG_URI && AddCupsList(ippGetString( attr, 0, NULL ), printer) == 0)
+- cnt++;
+- attr = ippNextAttribute( response );
+- }
+-
+- if (attr == NULL)
+- break;
+- }
+-
+- ippDelete(response);
+-
+- bugout:
+- return cnt;
+-}
+-
+ static int AddDevice(char *uri)
+ {
+ struct hpmud_model_attributes ma;
+@@ -294,7 +201,6 @@ static int DevDiscovery(int localOnly)
+ char uri[HPMUD_LINE_SIZE];
+ char *tail = message;
+ int i, scan_type, cnt=0, total=0, bytes_read;
+- char **cups_printer=NULL; /* list of printers */
+ char* token = NULL;
+ enum HPMUD_RESULT stat;
+
+@@ -308,38 +214,6 @@ static int DevDiscovery(int localOnly)
+ GetUriLine(tail, uri, &tail);
+ total += AddDevice(uri);
+ }
+- /* Look for Network Scan devices if localonly flag if FALSE. */
+- if (!localOnly)
+- {
+- /* Look for all-in-one scan devices for which print queue created */
+- cnt = GetCupsPrinters(&cups_printer);
+- for (i=0; i<cnt; i++)
+- {
+- total += AddDevice(cups_printer[i]);
+- free(cups_printer[i]);
+- }
+- if (cups_printer)
+- free(cups_printer);
+-#ifdef HAVE_LIBAVAHI
+- /* Discover NW scanners using Bonjour*/
+- if( (avahi_probe_nw_scanners() == AVAHI_STATUS_OK) && (aUriBuf != NULL) )
+- {
+- token = strtok(aUriBuf, ";");
+- while (token)
+- {
+- total += AddDevice(token);
+- token = strtok(NULL, ";");
+- }
+- free(aUriBuf);
+- aUriBuf = NULL;
+- }
+-#endif
+- if(!total)
+- {
+- SendScanEvent("hpaio:/net/HP_Scan_Devices?ip=1.1.1.1", EVENT_ERROR_NO_PROBED_DEVICES_FOUND);
+- }
+- }
+-
+ bugout:
+ return total;
+ }
diff --git a/external/subpack/utils/hplip/patches/030-replace_unsafe_memcpy_with_memmove.patch b/external/subpack/utils/hplip/patches/030-replace_unsafe_memcpy_with_memmove.patch
new file mode 100644
index 0000000..2babb2b
--- /dev/null
+++ b/external/subpack/utils/hplip/patches/030-replace_unsafe_memcpy_with_memmove.patch
@@ -0,0 +1,15 @@
+https://bugs.launchpad.net/hplip/+bug/1672256
+
+memcpy should never be used with overlapping memory regions
+
+--- a/io/hpmud/musb.c
++++ b/io/hpmud/musb.c
+@@ -775,7 +775,7 @@ static int device_id(int fd, unsigned ch
+ len = size-1; /* leave byte for zero termination */
+ if (len > 2)
+ len -= 2;
+- memcpy(buffer, buffer+2, len); /* remove length */
++ memmove(buffer, buffer+2, len); /* remove length */
+ buffer[len]=0;
+ DBG("read actual device_id successfully fd=%d len=%d\n", fd, len);
+
diff --git a/external/subpack/utils/hplip/patches/050-fix-glibcisms.patch b/external/subpack/utils/hplip/patches/050-fix-glibcisms.patch
new file mode 100644
index 0000000..82bb382
--- /dev/null
+++ b/external/subpack/utils/hplip/patches/050-fix-glibcisms.patch
@@ -0,0 +1,15 @@
+--- a/scan/sane/OrbliteScan/LinuxCommon.h
++++ b/scan/sane/OrbliteScan/LinuxCommon.h
+@@ -18,10 +18,8 @@ typedef u_int32_t UInt32;
+ typedef int32_t SInt32;
+ //typedef unsigned long UInt32;
+ //typedef signed long SInt32;
+-typedef __S64_TYPE SInt64;
+-typedef __U64_TYPE UInt64;
+-typedef __S64_TYPE int64_t;
+-typedef __U64_TYPE uint64_t;
++typedef int64_t SInt64;
++typedef uint64_t UInt64;
+
+ //typedef unsigned long ULONG;
+ //typedef void* LPVOID;
diff --git a/external/subpack/utils/hplip/patches/060-fix-glibc.patch b/external/subpack/utils/hplip/patches/060-fix-glibc.patch
new file mode 100644
index 0000000..6a35c74
--- /dev/null
+++ b/external/subpack/utils/hplip/patches/060-fix-glibc.patch
@@ -0,0 +1,15 @@
+Fix missing definition of uint64_t while compiling
+under uclibc or glibc
+
+https://bugs.launchpad.net/hplip/+bug/1826965
+
+--- a/scan/sane/OrbliteScan/LinuxCommon.h
++++ b/scan/sane/OrbliteScan/LinuxCommon.h
+@@ -2,6 +2,7 @@
+ #define H_LinuxCommon
+
+ #include <sys/types.h>
++#include <stdint.h>
+
+ /* Common typedefs for Linux */
+
diff --git a/external/subpack/utils/hplip/patches/070-respect-cflags.patch b/external/subpack/utils/hplip/patches/070-respect-cflags.patch
new file mode 100644
index 0000000..b76a673
--- /dev/null
+++ b/external/subpack/utils/hplip/patches/070-respect-cflags.patch
@@ -0,0 +1,29 @@
+--- a/configure.in
++++ b/configure.in
+@@ -618,14 +618,14 @@ if test "$class_driver" = "no" && test "
+ fi
+ fi
+
+-SAVE_CPPFLAGS="$CPPFLAGS"
++SAVE_CFLAGS="$CFLAGS"
+ CFLAGS=`python-config --includes`
+-if [ $? -eq 0 ]
++if test $? -eq 0
+ then
+ echo $FLAGS
+ else
+ CFLAGS=`python3-config --includes`
+- if [ $? -eq 0 ]
++ if test $? -eq 0
+ then
+ echo $FLAGS
+ fi
+@@ -645,7 +645,7 @@ if test "$class_driver" = "no" && test "
+ AS_IF([test "x$FOUND_HEADER" != "xyes"],
+ [AC_MSG_ERROR([cannot find python-devel support], 6)])
+ fi
+-CFLAGS="$save_CFLAGS"
++CFLAGS="$SAVE_CFLAGS"
+
+ if test "$hpijs_only_build" = "no" && test "$scan_build" = "yes" && test "$hpcups_only_build" = "no"; then
+ AC_CHECK_LIB([sane], [sane_open], [LIBS="$LIBS"], [AC_MSG_ERROR([cannot find sane-backends-devel support (or --disable-scan-build)], 12)])
diff --git a/external/subpack/utils/hub-ctrl/Makefile b/external/subpack/utils/hub-ctrl/Makefile
new file mode 100644
index 0000000..31ea254
--- /dev/null
+++ b/external/subpack/utils/hub-ctrl/Makefile
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hub-ctrl
+PKG_VERSION:=1.0
+PKG_RELEASE:=2
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/codazoda/hub-ctrl.c.git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=3eef0240fac90067d081551e9f73dfa741d94a9e
+PKG_LICENSE:=GPL-2.0-or-later
+
+PKG_MAINTAINER:=Simon Peter <probono@puredarwin.org>
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_MIRROR_HASH:=98ffd9ead07d6208acf7f713dc6574877d4967bdfb47bf70444ec9d44399faaa
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/hub-ctrl
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Control USB power on a port by port basis
+ URL:=https://github.com/codazoda/hub-ctrl.c
+ DEPENDS:=+libusb-compat
+endef
+
+define Package/hub-ctrl/description
+ Control USB power on a port by port basis on some USB hubs.
+ This only works on USB hubs that have the hardware necessary
+ to allow software controlled power switching.
+ Most hubs DO NOT include the hardware.
+endef
+
+define Build/Compile
+ $(TARGET_CC) $(TARGET_CFLAGS) -I$(STAGING_DIR)/usr/include \
+ -L$(STAGING_DIR)/usr/lib -lusb \
+ -o $(PKG_BUILD_DIR)/hub-ctrl $(PKG_BUILD_DIR)/hub-ctrl.c
+endef
+
+define Package/hub-ctrl/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/hub-ctrl $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,hub-ctrl))
diff --git a/external/subpack/utils/hwinfo/Makefile b/external/subpack/utils/hwinfo/Makefile
new file mode 100644
index 0000000..03871f9
--- /dev/null
+++ b/external/subpack/utils/hwinfo/Makefile
@@ -0,0 +1,90 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hwinfo
+PKG_VERSION:=21.71
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/openSUSE/hwinfo/tar.gz/$(PKG_VERSION)?
+PKG_HASH:=c4c573eb15cbc10103f5044b485d7e4ff941500ed559743a1c98e6a6deb0ebda
+
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=Alberto Bursi <bobafetthotmail@gmail.com>
+
+PKG_BUILD_DEPENDS:= hwinfo/host
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/host-build.mk
+
+# Execute in host build directory
+HOST_MAKE_FLAGS += -C $(HOST_BUILD_DIR)
+
+define Host/Configure
+ # copy uuid.h to another location in host build dir as that's where this package expects it
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/include/uuid/
+ $(CP) $(STAGING_DIR_HOST)/include/e2fsprogs/uuid/uuid.h $(STAGING_DIR_HOST)/include/uuid/uuid.h
+endef
+
+define Host/Compile
+ # Build using host compiler and let it generate the files we need
+ # CFLAGS, CPPFLAGS & LDFLAGS need to be passed with CC because they are being ingored
+ CC="$(HOSTCC) $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(HOST_LDFLAGS)" $(MAKE) $(HOST_MAKE_FLAGS)
+endef
+
+define Host/Install
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/share/hwinfo
+ $(CP) $(HOST_BUILD_DIR)/src/isdn/cdb/isdn_cdb $(STAGING_DIR_HOST)/share/hwinfo/
+ $(CP) $(HOST_BUILD_DIR)/src/isdn/cdb/mk_isdnhwdb $(STAGING_DIR_HOST)/share/hwinfo/
+
+ $(CP) $(HOST_BUILD_DIR)/src/ids/check_hd $(STAGING_DIR_HOST)/share/hwinfo/
+endef
+
+define Build/Configure
+ # Fetch prebuilt files from host build dir
+ $(INSTALL_DIR) $(PKG_BUILD_DIR)/src/isdn/cdb/
+ $(CP) $(STAGING_DIR_HOST)/share/hwinfo/isdn_cdb $(PKG_BUILD_DIR)/src/isdn/cdb/
+ $(CP) $(STAGING_DIR_HOST)/share/hwinfo/mk_isdnhwdb $(PKG_BUILD_DIR)/src/isdn/cdb/
+
+ $(INSTALL_DIR) $(PKG_BUILD_DIR)/src/ids/
+ $(CP) $(STAGING_DIR_HOST)/share/hwinfo/check_hd $(PKG_BUILD_DIR)/src/ids/
+
+
+ # Set copied files modtime to one day in the future
+ # to prevent rebuilding them
+ perl -e 'utime(time() + 86400, time() + 86400, $$$$ARGV[0])' \
+ $(PKG_BUILD_DIR)/src/isdn/cdb/isdn_cdb
+ perl -e 'utime(time() + 86400, time() + 86400, $$$$ARGV[0])' \
+ $(PKG_BUILD_DIR)/src/isdn/cdb/mk_isdnhwdb
+ perl -e 'utime(time() + 86400, time() + 86400, $$$$ARGV[0])' \
+ $(PKG_BUILD_DIR)/src/ids/check_hd
+endef
+
+
+define Package/hwinfo
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=probe the hardware present in the system
+ URL:=https://github.com/openSUSE/hwinfo
+ DEPENDS:= +libuuid
+endef
+
+define Package/hwinfo/description
+ hwinfo/libhd are used to probe for the hardware present in the system.
+ It can be used to generate a system overview log which can be later
+ used for support.
+ This project provides a hardware probing library libhd.so and a
+ command line tool hwinfo using it. A major project using this library
+ is YaST, the SUSE installation tool.
+endef
+
+
+define Package/hwinfo/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_BUILD_DIR)/hwinfo $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/src/libhd.so* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,hwinfo))
+$(eval $(call HostBuild))
diff --git a/external/subpack/utils/hwinfo/patches/010-hardcoding-version.patch b/external/subpack/utils/hwinfo/patches/010-hardcoding-version.patch
new file mode 100644
index 0000000..96f85fd
--- /dev/null
+++ b/external/subpack/utils/hwinfo/patches/010-hardcoding-version.patch
@@ -0,0 +1,19 @@
+hardcode version of hwinfo, this must be changed in sync
+with hwinfo version changes when updating the package
+--- a/Makefile
++++ b/Makefile
+@@ -12,12 +12,8 @@ export SO_LIBS
+
+ GIT2LOG := $(shell if [ -x ./git2log ] ; then echo ./git2log --update ; else echo true ; fi)
+ GITDEPS := $(shell [ -d .git ] && echo .git/HEAD .git/refs/heads .git/refs/tags)
+-BRANCH := $(shell [ -d .git ] && git branch | perl -ne 'print $$_ if s/^\*\s*//')
+-ifdef HWINFO_VERSION
+-VERSION := $(shell echo ${HWINFO_VERSION} > VERSION; cat VERSION)
+-else
+-VERSION := $(shell $(GIT2LOG) --version VERSION ; cat VERSION)
+-endif
++BRANCH := master
++VERSION := $(shell echo 21.71 > VERSION; cat VERSION)
+ PREFIX := hwinfo-$(VERSION)
+
+ include Makefile.common
diff --git a/external/subpack/utils/hwinfo/patches/020-remove_libx8emu_dependency.patch b/external/subpack/utils/hwinfo/patches/020-remove_libx8emu_dependency.patch
new file mode 100644
index 0000000..579dc6b
--- /dev/null
+++ b/external/subpack/utils/hwinfo/patches/020-remove_libx8emu_dependency.patch
@@ -0,0 +1,65 @@
+the library libx86emu is used only for manipulating VBIOS
+firmware to get some information from it.
+Since it's not crucial for OpenWrt usecase and it's a pain
+to compile this package with this dependency in OpenWrt due to
+host builds and whatnot, we simply remove it and disable this
+functionality in hwinfo.
+This also saves some space.
+--- a/Makefile
++++ b/Makefile
+@@ -25,13 +25,14 @@ LIBDIR ?= /usr/lib
+ endif
+ ULIBDIR = $(LIBDIR)
+
++# this library has been removed from the code, disabling it here too
+ # ia64
+-ifneq ($(filter i386 x86_64, $(ARCH)),)
+-SLIBS += -lx86emu
+-TLIBS += -lx86emu
+-SO_LIBS += -lx86emu
+-TSO_LIBS += -lx86emu
+-endif
++#ifneq ($(filter i386 x86_64, $(ARCH)),)
++#SLIBS += -lx86emu
++#TLIBS += -lx86emu
++#SO_LIBS += -lx86emu
++#TSO_LIBS += -lx86emu
++#endif
+
+ SHARED_FLAGS =
+ OBJS_NO_TINY = names.o parallel.o modem.o
+--- a/src/hd/bios.c
++++ b/src/hd/bios.c
+@@ -447,9 +447,10 @@ void hd_scan_bios(hd_data_t *hd_data)
+ }
+ }
+
+-#if defined(__i386__) || defined (__x86_64__)
+- get_vbe_info(hd_data, vbe);
+-#endif
++//disabled as we removed the library needed for this function
++//#if defined(__i386__) || defined (__x86_64__)
++// get_vbe_info(hd_data, vbe);
++//#endif
+
+ if(vbe->ok) {
+ bt->vbe_ver = vbe->version;
+--- a/src/hd/bios.h
++++ b/src/hd/bios.h
+@@ -5,4 +5,5 @@
+ #define BIOS_RAM_SIZE 0x100
+
+ void hd_scan_bios(hd_data_t *hd_data);
+-void get_vbe_info(hd_data_t *hd_data, vbe_info_t *vbe);
++//disabled as we removed the lib needed by this function
++//void get_vbe_info(hd_data_t *hd_data, vbe_info_t *vbe);
+--- a/src/hd/mdt.c
++++ b/src/hd/mdt.c
+@@ -1,4 +1,6 @@
+-#if defined(__i386__) || defined (__x86_64__)
++//disabling this whole thing as it's using the lib we have removed
++//#if defined(__i386__) || defined (__x86_64__)
++#if defined(__disabled__) || defined (__disabled__)
+
+ #define _GNU_SOURCE
+
diff --git a/external/subpack/utils/hwinfo/patches/030-enable-hw-ids-and-disable-generation-of-tiny-hwinfo-headers.patch b/external/subpack/utils/hwinfo/patches/030-enable-hw-ids-and-disable-generation-of-tiny-hwinfo-headers.patch
new file mode 100644
index 0000000..6aa9c80
--- /dev/null
+++ b/external/subpack/utils/hwinfo/patches/030-enable-hw-ids-and-disable-generation-of-tiny-hwinfo-headers.patch
@@ -0,0 +1,75 @@
+>>enable all IDs for hwinfo
+>>changes to make it respect compile flags
+>>disable the generation of "tiny hwinfo ID tables" because it is a long
+process and has no purpose, it seems I cannot even build the "tiny" version of hwinfo
+on my OpenSUSE system, so I guess that it is just legacy stuff that bitrotted.
+
+--- a/src/ids/Makefile
++++ b/src/ids/Makefile
+@@ -17,47 +17,47 @@ IDFILES += src/bus src/class src/extra s
+ src/usb src/usb2 src/isapnp src/monitor src/camera src/tv2 src/tv src/dvb2 src/dvb \
+ src/chipcard src/modem src/pcmcia src/s390 src/sdio
+
+-ifeq "$(ARCH)" "i386"
++#ifeq "$(ARCH)" "i386"
+ IDFILES += src/x11.i386 src/modem.i386
+-endif
++#endif
+
+-ifeq "$(ARCH)" "ppc"
++#ifeq "$(ARCH)" "ppc"
+ IDFILES += src/x11.ppc src/x11.ppc.special
+-endif
++#endif
+
+-ifeq "$(ARCH)" "alpha"
++#ifeq "$(ARCH)" "alpha"
+ IDFILES += src/x11.axp
+-endif
++#endif
+
+-ifeq "$(ARCH)" "sparc"
++#ifeq "$(ARCH)" "sparc"
+ IDFILES += src/x11.sparc
+-endif
++#endif
+
+-ifeq "$(ARCH)" "sparc64"
++#ifeq "$(ARCH)" "sparc64"
+ IDFILES += src/x11.sparc
+-endif
++#endif
+
+-ifeq "$(ARCH)" "ia64"
++#ifeq "$(ARCH)" "ia64"
+ IDFILES += src/x11.ia64
+-endif
++#endif
+
+-ifeq "$(ARCH)" "x86_64"
++#ifeq "$(ARCH)" "x86_64"
+ IDFILES += src/x11.amd64
+-endif
++#endif
+
+ IDFILES += src/pci src/storage src/sound src/mouse src/braille
+
+ $(LIBHD_D): hd_ids.o
+- ar r $(LIBHD) $?
++ $(AR) r $(LIBHD) $?
+
+ check_hd: check_hd.c
+- $(CC) $(CFLAGS) $< -o $@
++ $(CC) $(LDFLAGS) $(CFLAGS) $< -o $@
+
+-hd_ids.c: hd_ids.h hd_ids_tiny.h
++hd_ids.c: hd_ids.h
+
+ hd_ids.h hd.ids: check_hd $(IDFILES)
+ ./check_hd --check --sort --cfile hd_ids.h $(IDFILES)
+
+-hd_ids_tiny.h: check_hd hd.ids
+- ./check_hd --mini --cfile hd_ids_tiny.h --log=hd_tiny.log --out=hd_tiny.ids hd.ids
++#hd_ids_tiny.h: check_hd hd.ids
++# ./check_hd --mini --cfile hd_ids_tiny.h --log=hd_tiny.log --out=hd_tiny.ids hd.ids
+
diff --git a/external/subpack/utils/hwinfo/patches/040-assorted-Makefile-butchery.patch b/external/subpack/utils/hwinfo/patches/040-assorted-Makefile-butchery.patch
new file mode 100644
index 0000000..03bc4a6
--- /dev/null
+++ b/external/subpack/utils/hwinfo/patches/040-assorted-Makefile-butchery.patch
@@ -0,0 +1,193 @@
+Some makefile modifications to:
+>>disable the logic that detects and sets architecture (it screws up cross-compiling)
+>>disable some secondary build functions like creating changelogs or report files for other tools
+>>disable the install functionality as we take the files we need with OpenWrt build system
+>>changes to all makefiles to respect the compile flags
+
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ TOPDIR = $(CURDIR)
+ SUBDIRS = src
+-TARGETS = hwinfo hwinfo.pc changelog
++TARGETS = hwinfo
+ CLEANFILES = hwinfo hwinfo.pc hwinfo.static hwscan hwscan.static hwscand hwscanqueue doc/libhd doc/*~
+ LIBS = -lhd
+ SLIBS = -lhd -luuid
+@@ -18,11 +18,11 @@ PREFIX := hwinfo-$(VERSION)
+
+ include Makefile.common
+
+-ifeq "$(ARCH)" "x86_64"
+-LIBDIR ?= /usr/lib64
+-else
++#ifeq "$(ARCH)" "x86_64"
++#LIBDIR ?= /usr/lib64
++#else
+ LIBDIR ?= /usr/lib
+-endif
++#endif
+ ULIBDIR = $(LIBDIR)
+
+ # this library has been removed from the code, disabling it here too
+@@ -39,13 +39,13 @@ OBJS_NO_TINY = names.o parallel.o modem.
+
+ .PHONY: fullstatic static shared tiny doc diet tinydiet uc tinyuc
+
+-ifdef HWINFO_VERSION
++#ifdef HWINFO_VERSION
+ changelog:
+ @true
+-else
+-changelog: $(GITDEPS)
+- $(GIT2LOG) --changelog changelog
+-endif
++#else
++#changelog: $(GITDEPS)
++# $(GIT2LOG) --changelog changelog
++#endif
+
+ hwscan: hwscan.o $(LIBHD)
+ $(CC) hwscan.o $(LDFLAGS) $(CFLAGS) $(LIBS) -o $@
+@@ -99,28 +99,29 @@ doc:
+ @cd doc ; doxygen libhd.doxy
+
+ install:
+- install -d -m 755 $(DESTDIR)/sbin $(DESTDIR)/usr/sbin $(DESTDIR)$(ULIBDIR) \
+- $(DESTDIR)$(ULIBDIR)/pkgconfig $(DESTDIR)/usr/include
+- install -m 755 hwinfo $(DESTDIR)/usr/sbin
+- install -m 755 src/ids/check_hd $(DESTDIR)/usr/sbin
+- install -m 755 src/ids/convert_hd $(DESTDIR)/usr/sbin
+- if [ -f $(LIBHD_SO) ] ; then \
+- install $(LIBHD_SO) $(DESTDIR)$(ULIBDIR) ; \
+- ln -snf $(LIBHD_NAME) $(DESTDIR)$(ULIBDIR)/$(LIBHD_SONAME) ; \
+- ln -snf $(LIBHD_SONAME) $(DESTDIR)$(ULIBDIR)/$(LIBHD_BASE).so ; \
+- else \
+- install -m 644 $(LIBHD) $(DESTDIR)$(ULIBDIR) ; \
+- fi
+- install -m 644 hwinfo.pc $(DESTDIR)$(ULIBDIR)/pkgconfig
+- install -m 644 src/hd/hd.h $(DESTDIR)/usr/include
+- perl -pi -e "s/define\s+HD_VERSION\b.*/define HD_VERSION\t\t$(LIBHD_MAJOR_VERSION)/" $(DESTDIR)/usr/include/hd.h
+- perl -pi -e "s/define\s+HD_MINOR_VERSION\b.*/define HD_MINOR_VERSION\t$(LIBHD_MINOR_VERSION)/" $(DESTDIR)/usr/include/hd.h
+- install -m 755 getsysinfo $(DESTDIR)/usr/sbin
+- install -m 755 src/isdn/cdb/mk_isdnhwdb $(DESTDIR)/usr/sbin
+- install -d -m 755 $(DESTDIR)/usr/share/hwinfo
+- install -d -m 755 $(DESTDIR)/var/lib/hardware/udi
+- install -m 644 src/isdn/cdb/ISDN.CDB.txt $(DESTDIR)/usr/share/hwinfo
+- install -m 644 src/isdn/cdb/ISDN.CDB.hwdb $(DESTDIR)/usr/share/hwinfo
++# install -d -m 755 $(DESTDIR)/sbin $(DESTDIR)/usr/sbin $(DESTDIR)$(ULIBDIR) \
++# $(DESTDIR)$(ULIBDIR)/pkgconfig $(DESTDIR)/usr/include
++# install -m 755 hwinfo $(DESTDIR)/usr/sbin
++# install -m 755 src/ids/check_hd $(DESTDIR)/usr/sbin
++# install -m 755 src/ids/convert_hd $(DESTDIR)/usr/sbin
++# if [ -f $(LIBHD_SO) ] ; then \
++# install $(LIBHD_SO) $(DESTDIR)$(ULIBDIR) ; \
++# ln -snf $(LIBHD_NAME) $(DESTDIR)$(ULIBDIR)/$(LIBHD_SONAME) ; \
++# ln -snf $(LIBHD_SONAME) $(DESTDIR)$(ULIBDIR)/$(LIBHD_BASE).so ; \
++# else \
++# install -m 644 $(LIBHD) $(DESTDIR)$(ULIBDIR) ; \
++# fi
++# install -m 644 hwinfo.pc $(DESTDIR)$(ULIBDIR)/pkgconfig
++# install -m 644 src/hd/hd.h $(DESTDIR)/usr/include
++# perl -pi -e "s/define\s+HD_VERSION\b.*/define HD_VERSION\t\t$(LIBHD_MAJOR_VERSION)/" $(DESTDIR)/usr/include/hd.h
++# perl -pi -e "s/define\s+HD_MINOR_VERSION\b.*/define HD_MINOR_VERSION\t$(LIBHD_MINOR_VERSION)/" $(DESTDIR)/usr/include/hd.h
++# install -m 755 getsysinfo $(DESTDIR)/usr/sbin
++# install -m 755 src/isdn/cdb/mk_isdnhwdb $(DESTDIR)/usr/sbin
++# install -d -m 755 $(DESTDIR)/usr/share/hwinfo
++# install -d -m 755 $(DESTDIR)/var/lib/hardware/udi
++# install -m 644 src/isdn/cdb/ISDN.CDB.txt $(DESTDIR)/usr/share/hwinfo
++# install -m 644 src/isdn/cdb/ISDN.CDB.hwdb $(DESTDIR)/usr/share/hwinfo
++ @true
+
+ archive: changelog
+ @if [ ! -d .git ] ; then echo no git repo ; false ; fi
+--- a/Makefile.common
++++ b/Makefile.common
+@@ -1,28 +1,26 @@
+ # libhd/Makefile.common
+
+-ARCH := $(shell uname -m)
+-ifeq "$(ARCH)" "i486"
+-ARCH := i386
+-endif
+-ifeq "$(ARCH)" "i586"
+-ARCH := i386
+-endif
+-ifeq "$(ARCH)" "i686"
+-ARCH := i386
+-endif
+-ifeq "$(ARCH)" "parisc"
+-EXTRA_FLAGS := -fPIC $(EXTRA_FLAGS)
+-endif
++#ARCH := $(shell uname -m)
++#ifeq "$(ARCH)" "i486"
++#ARCH := i386
++#endif
++#ifeq "$(ARCH)" "i586"
++#ARCH := i386
++#endif
++#ifeq "$(ARCH)" "i686"
++#ARCH := i386
++#endif
++#ifeq "$(ARCH)" "parisc"
++#EXTRA_FLAGS := -fPIC $(EXTRA_FLAGS)
++#endif
+
+ LIBHD_VERSION := $(shell cat $(TOPDIR)/VERSION)
+ LIBHD_MINOR_VERSION := $(shell cut -d . -f 2 $(TOPDIR)/VERSION)
+ LIBHD_MAJOR_VERSION := $(shell cut -d . -f 1 $(TOPDIR)/VERSION)
+
+-RPM_OPT_FLAGS ?= -O2
+-
+ CC ?= gcc
+ LD = ld
+-CFLAGS += $(RPM_OPT_FLAGS) -Wall -Wno-pointer-sign -pipe -g $(SHARED_FLAGS) $(EXTRA_FLAGS) -I$(TOPDIR)/src/hd
++CFLAGS += -Wall -Wno-pointer-sign $(SHARED_FLAGS) $(EXTRA_FLAGS) -I$(TOPDIR)/src/hd
+ SHARED_FLAGS = -fPIC
+
+ LDFLAGS += -Lsrc
+@@ -36,7 +34,7 @@ LIBHD_NAME = $(LIBHD_BASE).so.$(LIBHD_VE
+ LIBHD_SO = $(TOPDIR)/src/$(LIBHD_NAME)
+ LIBHD_D = $(TOPDIR)/src/.lib
+
+-export CC TOPDIR CFLAGS LIBHD ARCH
++export CC TOPDIR CFLAGS LIBHD
+
+ .PHONY: all distclean clean install subdirs
+
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -12,7 +12,7 @@ include $(TOPDIR)/Makefile.common
+ #endif
+
+ $(LIBHD): $(OBJS)
+- ar r $@ $?
++ $(AR) r $@ $?
+ @rm -f $(LIBHD_D)
+
+ ifdef SHARED_FLAGS
+--- a/src/hd/Makefile
++++ b/src/hd/Makefile
+@@ -8,4 +8,4 @@ version.h: $(TOPDIR)/VERSION
+ @echo "#define HD_VERSION_STRING \"`cat $(TOPDIR)/VERSION`\"" >$@
+
+ $(LIBHD_D): $(OBJS)
+- ar r $(LIBHD) $?
++ $(AR) r $(LIBHD) $?
+--- a/src/isdn/Makefile
++++ b/src/isdn/Makefile
+@@ -5,5 +5,5 @@ SUBDIRS = cdb
+ include $(TOPDIR)/Makefile.common
+
+ $(LIBHD_D): $(OBJS)
+- ar r $(LIBHD) $?
++ $(AR) r $(LIBHD) $?
+
+--- a/src/smp/Makefile
++++ b/src/smp/Makefile
+@@ -4,4 +4,4 @@ TARGETS = $(LIBHD_D)
+ include $(TOPDIR)/Makefile.common
+
+ $(LIBHD_D): $(OBJS)
+- ar r $(LIBHD) $?
++ $(AR) r $(LIBHD) $?
diff --git a/external/subpack/utils/hwinfo/patches/050-arc.patch b/external/subpack/utils/hwinfo/patches/050-arc.patch
new file mode 100644
index 0000000..07010c8
--- /dev/null
+++ b/external/subpack/utils/hwinfo/patches/050-arc.patch
@@ -0,0 +1,13 @@
+--- a/src/hd/hd.c
++++ b/src/hd/hd.c
+@@ -156,6 +156,10 @@
+ #define HD_ARCH "riscv"
+ #endif
+
++#ifdef __arc__
++#define HD_ARCH "arc"
++#endif
++
+ typedef struct disk_s {
+ struct disk_s *next;
+ unsigned crc;
diff --git a/external/subpack/utils/i2c-tools/Makefile b/external/subpack/utils/i2c-tools/Makefile
new file mode 100644
index 0000000..9d11fa3
--- /dev/null
+++ b/external/subpack/utils/i2c-tools/Makefile
@@ -0,0 +1,106 @@
+#
+# Copyright (C) 2007-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=i2c-tools
+PKG_VERSION:=4.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/software/utils/i2c-tools
+PKG_HASH:=1f899e43603184fac32f34d72498fc737952dbc9c97a8dd9467fadfdf4600cf9
+
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+PKG_LICENSE:=GPL-2.0-or-later LGPL-2.1-or-later
+PKG_LICENSE_FILES:=COPYING COPYING.LGPL
+PKG_CPE_ID:=cpe:/a:i2c-tools_project:i2c-tools
+
+PKG_BUILD_PARALLEL:=1
+PYTHON3_PKG_BUILD:=0
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/python/python3-package.mk
+
+define Package/i2c/Default
+ URL:=https://i2c.wiki.kernel.org/index.php/I2C_Tools
+ TITLE:=I2C
+endef
+
+define Package/libi2c
+ $(call Package/i2c/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+=library for i2c-tools
+endef
+
+define Package/i2c-tools
+ $(call Package/i2c/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE+=tools for Linux
+ DEPENDS:=+libi2c
+endef
+
+define Package/python3-smbus
+ $(call Package/i2c/Default)
+ SUBMENU:=Python
+ SECTION:=lang
+ CATEGORY:=Languages
+ TITLE:=Python bindings for the SMBUS
+ DEPENDS:=+libi2c +python3-light
+endef
+
+define Package/libi2c/description
+ This package contains i2c functionality needed by i2c-tools.
+endef
+
+define Package/i2c-tools/description
+ This package contains an heterogeneous set of I2C tools for Linux. These tools
+ were originally part of the lm-sensors package.
+endef
+
+define Package/python3-smbus/description
+ This package contain the Python3 bindings for Linux SMBus access through i2c-dev.
+endef
+
+PYTHON3_PKG_SETUP_ARGS:=
+PYTHON3_PKG_SETUP_DIR:=py-smbus
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ LINUX="$(LINUX_DIR)" \
+ CC="$(TARGET_CC)" \
+ STAGING_DIR="$(STAGING_DIR)" \
+ LDFLAGS="$(TARGET_LDFLAGS)" \
+ CFLAGS="$(TARGET_CFLAGS)"
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/include/i2c $(1)/usr/include/
+ $(CP) $(PKG_BUILD_DIR)/lib/libi2c.{a,so*} $(1)/usr/lib/
+endef
+
+define Package/libi2c/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/lib/libi2c.so* $(1)/usr/lib/
+endef
+
+define Package/i2c-tools/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/tools/i2cdetect $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/tools/i2cdump $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/tools/i2cset $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/tools/i2cget $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/tools/i2ctransfer $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,libi2c))
+$(eval $(call BuildPackage,i2c-tools))
+#$(eval $(call Py3Package,python3-smbus))
+#$(eval $(call BuildPackage,python3-smbus))
diff --git a/external/subpack/utils/idevicerestore/Makefile b/external/subpack/utils/idevicerestore/Makefile
new file mode 100644
index 0000000..6138da0
--- /dev/null
+++ b/external/subpack/utils/idevicerestore/Makefile
@@ -0,0 +1,47 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=idevicerestore
+PKG_VERSION:=1.0.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://www.libimobiledevice.org/downloads
+PKG_HASH:=32712e86315397fd2e8999e77a2d2f790c67f6b4aa50d4d1c64cb2c4609836f7
+
+PKG_MAINTAINER:=Rosen Penev <rosenp@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/idevicerestore
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=libimobiledevice
+ TITLE:=Restore/upgrade firmware of iOS devices
+ URL:=https://github.com/libimobiledevice/idevicerestore
+ DEPENDS:=+libirecovery +libzip +libcurl +usbmuxd
+endef
+
+define Package/idevicerestore/description
+ The idevicerestore tool allows to restore firmware files to iOS devices.
+ It is a full reimplementation of all granular steps which are performed
+ during restore of a firmware to a device.
+endef
+
+TARGET_LDFLAGS += $(if $(CONFIG_USE_GLIBC),-lpthread)
+
+define Package/idevicerestore/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/idevicerestore $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,idevicerestore))
diff --git a/external/subpack/utils/inotify-tools/Makefile b/external/subpack/utils/inotify-tools/Makefile
new file mode 100644
index 0000000..1a81c5e
--- /dev/null
+++ b/external/subpack/utils/inotify-tools/Makefile
@@ -0,0 +1,113 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=inotify-tools
+PKG_VERSION:=4.23.9.0
+PKG_HASH:=1dfa33f80b6797ce2f6c01f454fd486d30be4dca1b0c5c2ea9ba3c30a5c39855
+PKG_RELEASE:=2
+
+PKG_SOURCE_URL:=https://codeload.github.com/rvoicilas/inotify-tools/tar.gz/$(PKG_VERSION)?
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+PKG_LICENSE:=GPLv2
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+CONFIGURE_ARGS+= --disable-doxygen
+
+ifneq ($(CONFIG_USE_MUSL),)
+ TARGET_CFLAGS += -D_LARGEFILE64_SOURCE
+endif
+
+## Avoid linking with libstdcpp
+TARGET_CXXFLAGS+= -nodefaultlibs -lc -fno-exceptions
+TARGET_LDFLAGS+= $(if $(CONFIG_USE_MUSL),-lssp_nonshared)
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(CP) $(PKG_BUILD_DIR)/README.md $(PKG_BUILD_DIR)/README
+endef
+
+define Package/inotify-tools/Default
+ URL:=https://github.com/rvoicilas/inotify-tools/wiki
+endef
+
+define Package/libinotifytools
+ $(call Package/inotify-tools/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE=libinotifytools
+endef
+
+define Package/inotifywait
+ $(call Package/inotify-tools/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libinotifytools
+ TITLE=inotifywait tool
+endef
+
+define Package/inotifywatch
+ $(call Package/inotify-tools/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libinotifytools
+ TITLE=inotifywatch tool
+endef
+
+define Package/inotify-tools/description
+inotify-tools is a C library and a set of command-line programs for
+Linux providing a simple interface to inotify. These programs can be
+used to monitor and act upon filesystem events. A more detailed
+description of the programs is further down the page. The programs are
+written in C and have no dependencies other than a Linux kernel
+supporting inotify.
+endef
+
+define Package/inotifywait/description
+ $(call Package/inotify-tools/description)
+
+ This package provides the inotifywait tool.
+endef
+
+define Package/inotifywatch/description
+ $(call Package/inotify-tools/description)
+
+ This package provides the inotifywatch tool.
+endef
+
+define Package/libinotifytools/description
+ $(call Package/inotify-tools/description)
+
+ This package provides the libinotifytools shared library.
+endef
+
+define Package/inotifywait/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/inotifywait $(1)/usr/bin/
+endef
+
+define Package/inotifywatch/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/inotifywatch $(1)/usr/bin/
+endef
+
+define Package/libinotifytools/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/inotifytools
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/include/inotifytools/* $(1)/usr/include/inotifytools/
+ $(INSTALL_DIR) $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.{so*,a,la} $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libinotifytools))
+$(eval $(call BuildPackage,inotifywait))
+$(eval $(call BuildPackage,inotifywatch))
diff --git a/external/subpack/utils/io/Makefile b/external/subpack/utils/io/Makefile
new file mode 100644
index 0000000..b588b33
--- /dev/null
+++ b/external/subpack/utils/io/Makefile
@@ -0,0 +1,37 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=io
+PKG_RELEASE:=4
+
+include $(INCLUDE_DIR)/package.mk
+
+PKG_MAINTAINER:=Hauke Mehrtens <hauke@hauke-m.de>
+
+define Package/io
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Raw memory i/o utility
+ URL:=http://www.sleepie.demon.co.uk/linuxvme/io.c
+endef
+
+define Package/io/description
+ This tool can be used to access physical memory addresses from userspace.
+ It can be useful to access hardware for which no device driver exists!
+endef
+
+define Build/Compile
+ $(TARGET_CC) $(TARGET_CFLAGS) $(TARGET_LDFLAGS) -Wall \
+ $(PKG_BUILD_DIR)/io.c -o $(PKG_BUILD_DIR)/$(PKG_NAME)
+endef
+
+define Package/io/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/io $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,io))
diff --git a/external/subpack/utils/io/src/io.c b/external/subpack/utils/io/src/io.c
new file mode 100644
index 0000000..be861e3
--- /dev/null
+++ b/external/subpack/utils/io/src/io.c
@@ -0,0 +1,428 @@
+/*
+ * Simple app. to do memory accesses via /dev/mem.
+ *
+ *
+ * Copyright (c) Richard Hirst <rhirst@linuxcare.com>
+ * Copyright (c) Thomas Langer <thomas.langer@infineon.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#define MEM_READ 0
+#define MEM_WRITE 1
+#define MEM_AND 2
+#define MEM_OR 3
+
+static void
+usage (char *argv0)
+{
+ fprintf(stderr,
+"Raw memory i/o utility - $Revision: 2.0 $\n\n"
+"%s -v -1|2|4 -r|w|a|o [-l <len>] [-f <file>] <addr> [<value>]\n\n"
+" -v Verbose, asks for confirmation\n"
+" -1|2|4 Sets memory access size in bytes (default byte)\n"
+" -l <len> Length in bytes of area to access (defaults to\n"
+" one access, or whole file length)\n"
+" -r|w|a|o Read from or Write to memory (default read)\n"
+" optional write with modify (and/or)\n"
+" -f <file> File to write on memory read, or\n"
+" to read on memory write\n"
+" <addr> The memory address to access\n"
+" <val> The value to write (implies -w)\n\n"
+"Examples:\n"
+" %s 0x1000 Reads one byte from 0x1000\n"
+" %s 0x1000 0x12 Writes 0x12 to location 0x1000\n"
+" %s -2 -l 8 0x1000 Reads 8 words from 0x1000\n"
+" %s -r -f dmp -l 100 200 Reads 100 bytes from addr 200 to file\n"
+" %s -w -f img 0x10000 Writes the whole of file to memory\n"
+"\n"
+"Note access size (-1|2|4) does not apply to file based accesses.\n\n",
+ argv0, argv0, argv0, argv0, argv0, argv0);
+ exit(1);
+}
+
+
+static void
+memread_memory(unsigned long phys_addr, void *addr, int len, int iosize)
+{
+ int i;
+
+ while (len) {
+ printf("%08lx: ", phys_addr);
+ i = 0;
+ while (i < 16 && len) {
+ switch(iosize) {
+ case 1:
+ printf(" %02x", *(unsigned char *)addr);
+ break;
+ case 2:
+ printf(" %04x", *(unsigned short *)addr);
+ break;
+ case 4:
+ printf(" %08x", *(unsigned int *)addr);
+ break;
+ }
+ i += iosize;
+ addr += iosize;
+ len -= iosize;
+ }
+ phys_addr += 16;
+ printf("\n");
+ }
+}
+
+
+static void
+write_memory(unsigned long phys_addr, void *addr, int len, int iosize, unsigned long value)
+{
+ switch(iosize) {
+ case 1:
+ while (len) {
+ *(unsigned char *)addr = value;
+ len -= iosize;
+ addr += iosize;
+ }
+ break;
+ case 2:
+ while (len) {
+ *(unsigned short *)addr = value;
+ len -= iosize;
+ addr += iosize;
+ }
+ break;
+ case 4:
+ while (len) {
+ *(unsigned long *)addr = value;
+ len -= iosize;
+ addr += iosize;
+ }
+ break;
+ }
+}
+
+
+static void
+and_write_memory(unsigned long phys_addr, void *addr, int len, int iosize, unsigned long value)
+{
+ switch(iosize) {
+ case 1:
+ while (len) {
+ *(unsigned char *)addr &= value;
+ len -= iosize;
+ addr += iosize;
+ }
+ break;
+ case 2:
+ while (len) {
+ *(unsigned short *)addr &= value;
+ len -= iosize;
+ addr += iosize;
+ }
+ break;
+ case 4:
+ while (len) {
+ *(unsigned long *)addr &= value;
+ len -= iosize;
+ addr += iosize;
+ }
+ break;
+ }
+}
+
+
+static void
+or_write_memory(unsigned long phys_addr, void *addr, int len, int iosize, unsigned long value)
+{
+ switch(iosize) {
+ case 1:
+ while (len) {
+ *(unsigned char *)addr |= value;
+ len -= iosize;
+ addr += iosize;
+ }
+ break;
+ case 2:
+ while (len) {
+ *(unsigned short *)addr |= value;
+ len -= iosize;
+ addr += iosize;
+ }
+ break;
+ case 4:
+ while (len) {
+ *(unsigned long *)addr |= value;
+ len -= iosize;
+ addr += iosize;
+ }
+ break;
+ }
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int mfd, ffd = 0, req_len = 0, opt;
+ void *real_io;
+ unsigned long real_len, real_addr, req_addr, req_value = 0, offset;
+ char *endptr;
+ int memfunc = MEM_READ;
+ int iosize = 1;
+ char *filename = NULL;
+ int verbose = 0;
+
+ opterr = 0;
+ if (argc == 1)
+ usage(argv[0]);
+
+ while ((opt = getopt(argc, argv, "hv124rwaol:f:")) > 0) {
+ switch (opt) {
+ case 'h':
+ usage(argv[0]);
+ case 'v':
+ verbose = 1;
+ break;
+ case '1':
+ case '2':
+ case '4':
+ iosize = opt - '0';
+ break;
+ case 'r':
+ memfunc = MEM_READ;
+ break;
+ case 'a':
+ memfunc = MEM_AND;
+ break;
+ case 'o':
+ memfunc = MEM_OR;
+ break;
+ case 'w':
+ memfunc = MEM_WRITE;
+ break;
+ case 'l':
+ req_len = strtoul(optarg, &endptr, 0);
+ if (*endptr) {
+ fprintf(stderr, "Bad <size> value '%s'\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'f':
+ filename = strdup(optarg);
+ break;
+ default:
+ fprintf(stderr, "Unknown option: %c\n", opt);
+ usage(argv[0]);
+ }
+ }
+
+ if (optind == argc) {
+ fprintf(stderr, "No address given\n");
+ exit(1);
+ }
+ req_addr = strtoul(argv[optind], &endptr, 0);
+ if (*endptr) {
+ fprintf(stderr, "Bad <addr> value '%s'\n", argv[optind]);
+ exit(1);
+ }
+ optind++;
+ if (!filename && (memfunc == MEM_READ) && optind < argc) {
+ memfunc = MEM_WRITE;
+ }
+ if (filename && optind > argc) {
+ fprintf(stderr, "Filename AND value given\n");
+ exit(1);
+ }
+ if (!filename && (memfunc != MEM_READ) && optind == argc) {
+ fprintf(stderr, "No value given for WRITE\n");
+ exit(1);
+ }
+ if (!filename && (memfunc != MEM_READ)) {
+ req_value = strtoul(argv[optind], &endptr, 0);
+ if (*endptr) {
+ fprintf(stderr, "Bad <value> value '%s'\n", argv[optind]);
+ exit(1);
+ }
+ if ((iosize == 1 && (req_value & 0xffffff00)) ||
+ (iosize == 2 && (req_value & 0xffff0000))) {
+ fprintf(stderr, "<value> too large\n");
+ exit(1);
+ }
+ optind++;
+ }
+ if (filename && (memfunc == MEM_READ) && !req_len) {
+ fprintf(stderr, "No size given for file memread\n");
+ exit(1);
+ }
+ if (optind < argc) {
+ fprintf(stderr, "Too many arguments '%s'...\n", argv[optind]);
+ exit(1);
+ }
+ if (filename && (memfunc == MEM_READ)) {
+ ffd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (ffd < 0) {
+ fprintf(stderr, "Failed to open destination file '%s': %s\n", filename, strerror(errno));
+ exit(1);
+ }
+ }
+ if (filename && (memfunc != MEM_READ)) {
+ ffd = open(filename, O_RDONLY);
+ if (ffd < 0) {
+ fprintf(stderr, "Failed to open source file '%s': %s\n", filename, strerror(errno));
+ exit(1);
+ }
+ }
+
+ if (filename && !req_len) {
+ req_len = lseek(ffd, 0, SEEK_END);
+ if (req_len < 0) {
+ fprintf(stderr, "Failed to seek on '%s': %s\n",
+ filename, strerror(errno));
+ exit(1);
+ }
+ if (lseek(ffd, 0, SEEK_SET)) {
+ fprintf(stderr, "Failed to seek on '%s': %s\n",
+ filename, strerror(errno));
+ exit(1);
+ }
+ }
+ if (!req_len)
+ req_len = iosize;
+
+ if ((iosize == 2 && (req_addr & 1)) ||
+ (iosize == 4 && (req_addr & 3))) {
+ fprintf(stderr, "Badly aligned <addr> for access size\n");
+ exit(1);
+ }
+ if ((iosize == 2 && (req_len & 1)) ||
+ (iosize == 4 && (req_len & 3))) {
+ fprintf(stderr, "Badly aligned <size> for access size\n");
+ exit(1);
+ }
+
+ if (!verbose)
+ /* Nothing */;
+ else if (filename && (memfunc == MEM_READ))
+ printf("Request to read 0x%x bytes from address 0x%08lx\n"
+ "\tto file %s, using %d byte accesses\n",
+ req_len, req_addr, filename, iosize);
+ else if (filename)
+ printf("Request to write 0x%x bytes to address 0x%08lx\n"
+ "\tfrom file %s, using %d byte accesses\n",
+ req_len, req_addr, filename, iosize);
+ else if (memfunc == MEM_READ)
+ printf("Request to read 0x%x bytes from address 0x%08lx\n"
+ "\tusing %d byte accesses\n",
+ req_len, req_addr, iosize);
+ else
+ printf("Request to write 0x%x bytes to address 0x%08lx\n"
+ "\tusing %d byte accesses of value 0x%0*lx\n",
+ req_len, req_addr, iosize, iosize*2, req_value);
+
+ real_addr = req_addr & ~4095;
+ if (real_addr == 0xfffff000) {
+ fprintf(stderr, "Sorry, cannot map the top 4K page\n");
+ exit(1);
+ }
+ offset = req_addr - real_addr;
+ real_len = req_len + offset;
+ real_len = (real_len + 4095) & ~ 4095;
+ if (real_addr + real_len < real_addr) {
+ fprintf(stderr, "Aligned addr+len exceeds top of address space\n");
+ exit(1);
+ }
+ if (verbose)
+ printf("Attempting to map 0x%lx bytes at address 0x%08lx\n",
+ real_len, real_addr);
+
+ mfd = open("/dev/mem", (memfunc == MEM_READ) ? (O_RDONLY | O_SYNC) : (O_RDWR | O_SYNC));
+ if (mfd == -1) {
+ perror("open /dev/mem");
+ fprintf(stderr, "Is CONFIG_DEVMEM activated?\n");
+ exit(1);
+ }
+ if (verbose)
+ printf("open(/dev/mem) ok\n");
+ real_io = mmap(NULL, real_len,
+ (memfunc == MEM_READ) ? PROT_READ:PROT_READ|PROT_WRITE,
+ MAP_SHARED, mfd, real_addr);
+ if (real_io == (void *)(-1)) {
+ fprintf(stderr, "mmap() failed: %s\n", strerror(errno));
+ exit(1);
+ }
+ if (verbose)
+ printf("mmap() ok\n");
+
+ if (verbose) {
+ int c;
+
+ printf("OK? ");
+ fflush(stdout);
+ c = getchar();
+ if (c != 'y' && c != 'Y') {
+ printf("Aborted\n");
+ exit(1);
+ }
+ }
+
+ if (filename && (memfunc == MEM_READ)) {
+ int n = write(ffd, real_io + offset, req_len);
+
+ if (n < 0) {
+ fprintf(stderr, "File write failed: %s\n", strerror(errno));
+ exit(1);
+ }
+ else if (n != req_len) {
+ fprintf(stderr, "Only wrote %d of %d bytes to file\n",
+ n, req_len);
+ exit(1);
+ }
+ }
+ else if (filename) {
+ int n = read(ffd, real_io + offset, req_len);
+
+ if (n < 0) {
+ fprintf(stderr, "File read failed: %s\n", strerror(errno));
+ exit(1);
+ }
+ else if (n != req_len) {
+ fprintf(stderr, "Only read %d of %d bytes from file\n",
+ n, req_len);
+ exit(1);
+ }
+ }
+ else {
+ switch (memfunc)
+ {
+ case MEM_READ:
+ memread_memory(req_addr, real_io + offset, req_len, iosize);
+ break;
+ case MEM_WRITE:
+ write_memory(req_addr, real_io + offset, req_len, iosize, req_value);
+ break;
+ case MEM_AND:
+ and_write_memory(req_addr, real_io + offset, req_len, iosize, req_value);
+ break;
+ case MEM_OR:
+ or_write_memory(req_addr, real_io + offset, req_len, iosize, req_value);
+ break;
+ }
+ }
+
+ munmap(real_io, real_len);
+
+ if (filename)
+ close(ffd);
+ close (mfd);
+
+ return 0;
+}
+
diff --git a/external/subpack/utils/irqbalance/Makefile b/external/subpack/utils/irqbalance/Makefile
new file mode 100644
index 0000000..d84bad3
--- /dev/null
+++ b/external/subpack/utils/irqbalance/Makefile
@@ -0,0 +1,57 @@
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=irqbalance
+PKG_VERSION:=1.9.4
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/Irqbalance/irqbalance.git
+PKG_SOURCE_VERSION:=v$(PKG_VERSION)
+PKG_MIRROR_HASH:=0521b15bb15ad46704ccf65f7ae683a47d54e7bae57fbe4e2a4341da6d424e58
+
+PKG_MAINTAINER:=Hannu Nyman <hannu.nyman@iki.fi>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+include $(INCLUDE_DIR)/meson.mk
+
+PKG_BUILD_DEPENDS += glib2
+
+define Package/irqbalance
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=$(ICONV_DEPENDS) $(INTL_DEPENDS)
+ TITLE:=IRQ usage balancing for multi-core systems
+ URL:=https://github.com/Irqbalance/irqbalance
+endef
+
+define Package/irqbalance/description
+ The purpose of irqbalance is to distribute hardware interrupts across
+ processors/cores on a multiprocessor/multicore system in order to
+ increase performance.
+endef
+
+define Package/irqbalance/conffiles
+/etc/config/irqbalance
+endef
+
+MESON_ARGS += \
+ -Dcapng=disabled \
+ -Dui=disabled
+
+define Package/irqbalance/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/irqbalance $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/irqbalance.init $(1)/etc/init.d/irqbalance
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/irqbalance.config $(1)/etc/config/irqbalance
+endef
+
+$(eval $(call BuildPackage,irqbalance))
diff --git a/external/subpack/utils/irqbalance/files/irqbalance.config b/external/subpack/utils/irqbalance/files/irqbalance.config
new file mode 100644
index 0000000..967b14d
--- /dev/null
+++ b/external/subpack/utils/irqbalance/files/irqbalance.config
@@ -0,0 +1,17 @@
+config irqbalance 'irqbalance'
+ option enabled '0'
+
+ # Level at which irqbalance partitions cache domains.
+ # Default is 2 (L2$).
+ #option deepestcache '2'
+
+ # The default value is 10 seconds
+ #option interval '10'
+
+ # Specify excluded cpulist
+ #option banned_cpulist '0'
+
+ # List of IRQ's to ignore
+ #list banirq '36'
+ #list banirq '69'
+
diff --git a/external/subpack/utils/irqbalance/files/irqbalance.init b/external/subpack/utils/irqbalance/files/irqbalance.init
new file mode 100644
index 0000000..05145ca
--- /dev/null
+++ b/external/subpack/utils/irqbalance/files/irqbalance.init
@@ -0,0 +1,51 @@
+#!/bin/sh /etc/rc.common
+
+START=90
+STOP=10
+
+USE_PROCD=1
+
+service_triggers()
+{
+ procd_add_reload_trigger "irqbalance"
+}
+
+start_service() {
+ local enabled
+ config_load 'irqbalance'
+ config_get_bool enabled irqbalance enabled 0
+ [ "$enabled" -gt 0 ] || return 0
+
+ config_get deepestcache irqbalance deepestcache 2
+ config_get interval irqbalance interval 10
+ config_get banned_cpulist irqbalance banned_cpulist ''
+ config_get debug irqbalance debug 0
+
+ procd_open_instance "irqbalance"
+ if [ -n "$banned_cpulist" ]; then
+ procd_set_param env IRQBALANCE_BANNED_CPULIST="$banned_cpulist"
+ fi
+
+ procd_add_jail_mount_rw /proc
+ procd_set_param command /usr/sbin/irqbalance
+ procd_append_param command -f
+ procd_append_param command "-c $deepestcache"
+ procd_append_param command "-t $interval"
+
+ # add banned IRQs
+ handle_banirq_value()
+ {
+ procd_append_param command "-i $1"
+ }
+ config_list_foreach irqbalance banirq handle_banirq_value
+
+ # debug
+ if [ "$debug" -gt 0 ]; then
+ procd_append_param command -d
+ procd_set_param stdout 1
+ fi
+ procd_set_param stderr 1
+
+ procd_set_param respawn
+ procd_close_instance
+}
diff --git a/external/subpack/utils/irqbalance/patches/010-meson.patch b/external/subpack/utils/irqbalance/patches/010-meson.patch
new file mode 100644
index 0000000..9418e1c
--- /dev/null
+++ b/external/subpack/utils/irqbalance/patches/010-meson.patch
@@ -0,0 +1,76 @@
+From 35072fc06b9efe923f6ac1bd73b67c33d3ae619b Mon Sep 17 00:00:00 2001
+From: Rosen Penev <rosenp@gmail.com>
+Date: Fri, 10 Jun 2022 23:14:27 -0700
+Subject: [PATCH] add meson
+
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+
+[update version string to 1.9.4]
+
+---
+ meson.build | 43 +++++++++++++++++++++++++++++++++++++++++++
+ meson_options.txt | 11 +++++++++++
+ 2 files changed, 54 insertions(+)
+ create mode 100644 meson.build
+ create mode 100644 meson_options.txt
+
+--- /dev/null
++++ b/meson.build
+@@ -0,0 +1,43 @@
++project('irqbalance', 'c',
++ version : '1.9.4',
++ default_options : ['warning_level=1']
++)
++
++cc = meson.get_compiler('c')
++
++glib_dep = dependency('glib-2.0', static: true)
++m_dep = cc.find_library('m', required: false)
++capng_dep = dependency('libcap-ng', required: get_option('capng'))
++ncurses_dep = dependency('curses', required: get_option('ui'))
++systemd_dep = dependency('libsystemd', required: get_option('systemd'))
++
++cdata = configuration_data()
++cdata.set('HAVE_GETOPT_LONG', cc.has_function('getopt_long'))
++cdata.set('HAVE_IRQBALANCEUI', ncurses_dep.found())
++cdata.set('HAVE_NUMA_H', cc.has_header('numa.h'))
++cdata.set('HAVE_LIBCAP_NG', capng_dep.found())
++cdata.set('HAVE_LIBSYSTEMD', systemd_dep.found())
++cdata.set_quoted('VERSION', meson.project_version())
++cfile = configure_file(
++ output: 'config.h',
++ configuration: cdata
++)
++
++if cdata.get('HAVE_IRQBALANCEUI')
++ add_project_arguments('-D_GNU_SOURCE', language: 'c')
++endif
++
++
++executable('irqbalance',
++ 'activate.c',
++ 'bitmap.c',
++ 'classify.c',
++ 'cputree.c',
++ 'irqbalance.c',
++ 'irqlist.c',
++ 'numa.c',
++ 'placement.c',
++ 'procinterrupts.c',
++ dependencies: [ glib_dep, m_dep, capng_dep, ncurses_dep, systemd_dep ],
++ install : true
++)
+--- /dev/null
++++ b/meson_options.txt
+@@ -0,0 +1,11 @@
++option('capng', type : 'feature',
++ description : 'Build with libcap-ng support',
++)
++
++option('systemd', type : 'feature',
++ description : 'Build with systemd support',
++)
++
++option('ui', type : 'feature',
++ description : 'Build the UI component',
++)
diff --git a/external/subpack/utils/irqbalance/patches/100-remove-libncursesw-dependency.patch b/external/subpack/utils/irqbalance/patches/100-remove-libncursesw-dependency.patch
new file mode 100644
index 0000000..917a46d
--- /dev/null
+++ b/external/subpack/utils/irqbalance/patches/100-remove-libncursesw-dependency.patch
@@ -0,0 +1,11 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -41,7 +41,7 @@ PKG_CHECK_MODULES([NCURSESW], [ncursesw]
+ AS_IF([test "x$has_ncursesw" = "xyes"], [
+ AC_SUBST([NCURSESW_CFLAGS])
+ AC_SUBST([NCURSESW_LIBS])
+- LIBS="$LIBS $NCURSESW_LIBS"
++ LIBS="$LIBS"
+ AC_SUBST([LIBS])
+ ])
+
diff --git a/external/subpack/utils/joe/Makefile b/external/subpack/utils/joe/Makefile
new file mode 100644
index 0000000..6684307
--- /dev/null
+++ b/external/subpack/utils/joe/Makefile
@@ -0,0 +1,61 @@
+#
+# Copyright (C) 2007-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+# changes by David Kuehling <dvdkhlng TA gmx TOD de>:
+#
+# - include support for all emulation modes jmacs jpico etc.
+# - see patches/002-builtinrc.patch
+#
+# changes by Vitaly Prosko <villy TA sft TOD ru>:
+#
+# - updated for new build system rules
+# - added static joerc config - no more defaults for native mode
+# - got maintenance role
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=joe
+PKG_VERSION:=4.6
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/joe-editor
+PKG_HASH:=495a0a61f26404070fe8a719d80406dc7f337623788e445b92a9f6de512ab9de
+
+PKG_MAINTAINER:=Vitaly Protsko <villy@sft.ru>
+PKG_LICENCE:=GPL-2.0
+PKG_CPE_ID:=cpe:/a:joseph_allen:joe
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/joe
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Editors
+ TITLE:=JOE - Joes own editor
+ URL:=https://sourceforge.net/projects/joe-editor/
+ DEPENDS:=+libncurses
+endef
+
+define Package/joe/description
+Joe is world-famous Wordstar like text editor, that also features
+Emacs and Pico emulation
+endef
+
+define Package/joe/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/joe/joe $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/joe
+ $(INSTALL_CONF) ./files/joerc $(1)/etc/joe/joerc
+endef
+
+define Package/joe/conffiles
+/etc/joe/joerc
+endef
+
+$(eval $(call BuildPackage,joe))
diff --git a/external/subpack/utils/joe/files/joerc b/external/subpack/utils/joe/files/joerc
new file mode 100644
index 0000000..403cce6
--- /dev/null
+++ b/external/subpack/utils/joe/files/joerc
Binary files differ
diff --git a/external/subpack/utils/jq/Makefile b/external/subpack/utils/jq/Makefile
new file mode 100644
index 0000000..d5ffdd0
--- /dev/null
+++ b/external/subpack/utils/jq/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=jq
+PKG_VERSION:=1.6
+PKG_RELEASE:=1
+PKG_LICENSE:=BSD
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/stedolan/jq/releases/download/jq-$(PKG_VERSION)/
+PKG_HASH:=9625784cf2e4fd9842f1d407681ce4878b5b0dcddbcd31c6135114a30c71e6a8
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+ifdef CONFIG_USE_MIPS16
+ TARGET_CFLAGS += -fno-ipa-sra
+endif
+
+TARGET_CFLAGS += -std=c99 -D_GNU_SOURCE
+
+CONFIGURE_ARGS+= \
+ --disable-docs \
+ --disable-valgrind \
+ --without-oniguruma
+
+define Package/jq
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Lightweight and flexible command-line JSON processor.
+ URL:=https://stedolan.github.io/jq/
+ MAINTAINER:=Marko Ratkaj <marko.ratkaj@sartura.hr>
+endef
+
+define Package/jq/description
+ Lightweight and flexible command-line JSON processor.
+endef
+
+define Package/jq/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,jq))
diff --git a/external/subpack/utils/jupp/Makefile b/external/subpack/utils/jupp/Makefile
new file mode 100644
index 0000000..d7108df
--- /dev/null
+++ b/external/subpack/utils/jupp/Makefile
@@ -0,0 +1,97 @@
+# Copyright (c) 2018 Thorsten Glaser <tg@mirbsd.org>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=jupp
+PKG_VERSION:=3.1.40
+PKG_RELEASE:=1
+PKG_LICENSE:=GPL-1.0
+PKG_LICENSE_FILES:=COPYING
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+PKG_BUILD_PARALLEL:=1
+PKG_CONFIG_DEPENDS:=CONFIG_PACKAGE_libncurses
+
+PKG_SOURCE:=joe-$(basename ${PKG_VERSION})jupp$(subst .,,$(suffix ${PKG_VERSION})).tgz
+PKG_SOURCE_URL:=http://www.mirbsd.org/MirOS/dist/jupp/ \
+ http://pub.allbsd.org/MirOS/dist/jupp/
+PKG_HASH:=4bed439cde7f2be294e96e49ef3e913ea90fbe5e914db888403e3a27e8035b1a
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/jupp/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Editors
+ URL:=http://www.mirbsd.org/jupp.htm
+ MAINTAINER:=Thorsten Glaser <tg@mirbsd.org>
+endef
+
+define Package/jupp
+$(call Package/jupp/Default)
+ TITLE:=WordStar-inspired text editor
+ DEPENDS:=+PACKAGE_libncurses:libncurses
+endef
+
+define Package/jupp/description
+jupp is a WordStar-inspired text and hex editor,
+for programmers and regular end users.
+endef
+
+define Package/jupp/chmod_plus_x
+ # work around automagic check for +x
+ chmod +x ${PKG_BUILD_DIR}/configure
+endef
+Hooks/Configure/Pre += Package/jupp/chmod_plus_x
+
+CONFIGURE_ARGS+= \
+ --disable-selinux \
+ --disable-termidx \
+ --enable-sysconfjoesubdir=/jupp
+
+ifeq (,${CONFIG_PACKAGE_libncurses})
+CONFIGURE_ARGS+= \
+ --disable-curses \
+ --disable-termcap \
+ --disable-terminfo
+endif
+
+define Package/jupp/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/joe $(1)/usr/bin/jupp
+endef
+
+define Package/jupp-data
+$(call Package/jupp/Default)
+ TITLE:=jupp Emacs/JOE/Pico emulations, syntax highlighting
+ PKGARCH:=all
+ DEPENDS:=jupp
+ CONFLICTS:=joe
+endef
+
+define Package/jupp-data/install
+ $(INSTALL_DIR) $(1)/etc/jupp
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/jmacsrc $(1)/etc/jupp/
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/joerc $(1)/etc/jupp/
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/jpicorc $(1)/etc/jupp/
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/jstarrc $(1)/etc/jupp/
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/jupprc $(1)/etc/jupp/
+ $(INSTALL_DIR) $(1)/etc/jupp/charmaps
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/charmaps/klingon $(1)/etc/jupp/charmaps/
+ $(INSTALL_DIR) $(1)/etc/jupp/syntax
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/syntax/*.jsf $(1)/etc/jupp/syntax/
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(LN) jupp $(1)/usr/bin/jmacs
+ $(LN) jupp $(1)/usr/bin/joe
+ $(LN) jupp $(1)/usr/bin/jpico
+ $(LN) jupp $(1)/usr/bin/jstar
+endef
+
+define Package/jupp-data/conffiles
+/etc/jupp
+endef
+
+$(eval $(call BuildPackage,jupp))
+$(eval $(call BuildPackage,jupp-data))
diff --git a/external/subpack/utils/klish/Makefile b/external/subpack/utils/klish/Makefile
new file mode 100644
index 0000000..dd77ffd
--- /dev/null
+++ b/external/subpack/utils/klish/Makefile
@@ -0,0 +1,92 @@
+
+#
+# Copyright (C) 2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=klish
+PKG_VERSION:=2.2.0
+PKG_RELEASE:=4
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=http://libcode.org/attachments/download/77/
+PKG_HASH:=a069ef06bb485e15b2ff27b856e46cd76fee1eac7e0f62a8d8ac0ad413694614
+
+PKG_MAINTAINER:=Takashi Umeno <umeno.takashi@gmail.com>
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=LICENCE
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/klish/default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Shells
+ TITLE:=Kommand Line Interface SHell ($(1))
+ URL:=https://libcode.org/projects/klish/
+endef
+
+define Package/klish
+$(call Package/klish/default,main tool)
+ DEPENDS:=+libxml2
+endef
+
+define Package/klish/description
+ The klish is a framework for implementing a CISCO-like CLI on a UNIX
+ systems. It is configurable by XML files. The KLISH stands for Kommand
+ Line Interface Shell.
+ The klish is a fork of clish 0.7.3 developed by Graeme McKerrell.
+ It defines new features but it's compatible (as much as possible) with
+ clish's XML configuration files.
+ klish is able to run using clish XML configuration files although
+ current clish users may expect some changes in behavior.
+ Konf and konfd are klish utilities that are used to store configuration
+ informations in a way which is similar to what's found on CISCO devices.
+ More information about these tools is to be found on the klish web site.
+endef
+
+CONFIGURE_ARGS += --with-libxml2
+
+TARGET_CFLAGS += -D_GNU_SOURCE
+
+define Package/klish/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/clish $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/konf $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/konfd $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/sigexec $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,klish))
+
+define Package/klish-xml-files
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=klish
+ TITLE:=klish sample XML files
+ URL:=https://libcode.org/projects/klish/
+endef
+
+define Package/klish-xml-files/description
+ This is a set of sample XML files for klish.
+endef
+
+define Package/klish-xml-files/install
+ $(INSTALL_DIR) $(1)/etc/clish
+ $(CP) $(PKG_BUILD_DIR)/xml-examples/clish $(1)/etc/clish/
+ $(CP) $(PKG_BUILD_DIR)/xml-examples/klish $(1)/etc/clish/
+ $(CP) $(PKG_BUILD_DIR)/xml-examples/lua $(1)/etc/clish/
+ $(CP) $(PKG_BUILD_DIR)/xml-examples/test $(1)/etc/clish/
+endef
+
+$(eval $(call BuildPackage,klish-xml-files))
diff --git a/external/subpack/utils/klish/patches/010-shell_execute_fix.patch b/external/subpack/utils/klish/patches/010-shell_execute_fix.patch
new file mode 100644
index 0000000..f74e91c
--- /dev/null
+++ b/external/subpack/utils/klish/patches/010-shell_execute_fix.patch
@@ -0,0 +1,17 @@
+--- a/clish/shell/shell_execute.c
++++ b/clish/shell/shell_execute.c
+@@ -19,12 +19,14 @@
+ #include <signal.h>
+ #include <fcntl.h>
+
++#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_OBSOLETE_BSD_SIGNAL__)
+ /* Empty signal handler to ignore signal but don't use SIG_IGN. */
+ static void sigignore(int signo)
+ {
+ signo = signo; /* Happy compiler */
+ return;
+ }
++#endif
+
+ /*-------------------------------------------------------- */
+ static int clish_shell_lock(const char *lock_path)
diff --git a/external/subpack/utils/lcdproc/Makefile b/external/subpack/utils/lcdproc/Makefile
new file mode 100644
index 0000000..b34a2d8
--- /dev/null
+++ b/external/subpack/utils/lcdproc/Makefile
@@ -0,0 +1,160 @@
+#
+# Copyright (C) 2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=lcdproc
+PKG_VERSION:=0.5.9
+PKG_RELEASE:=5
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/lcdproc/lcdproc/releases/download/v$(PKG_VERSION)/
+PKG_HASH:=d48a915496c96ff775b377d2222de3150ae5172bfb84a6ec9f9ceab962f97b83
+
+PKG_MAINTAINER:=Harald Geyer <harald@ccbib.org>, \
+ Philip Prindeville <philipp@redfish-solutions.com>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:lcdproc:lcdproc
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/lcdproc/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ URL:=http://lcdproc.org/
+endef
+
+define Package/lcdproc/Default-description
+LCDProc is a daemon and clients for displaying system information
+on various LCD displays
+endef
+
+
+define Package/lcdproc-clients
+ $(call Package/lcdproc/Default)
+ TITLE:=LCD Display clients
+endef
+
+define Package/lcdproc-clients/description
+$(call Package/lcdproc/Default-description)
+
+This package contains the clients distributed by the official lcdproc
+project:
+* lcdproc -- displays system information
+* lcdexec -- displays a menu structure to execute commands
+* lcdvc -- shows the content of the system console
+endef
+
+define Package/lcdproc-clients/conffiles
+/etc/lcdproc.conf
+/etc/lcdexec.conf
+/etc/lcdvc.conf
+endef
+
+
+define Package/lcdproc-server
+ $(call Package/lcdproc/Default)
+ TITLE:=LCD Display server
+ DEPENDS:=+libpthread
+endef
+
+define LCDPROC_CORE_DRIVERS_TEXT
+bayrad CFontzPacket CFontz CwLnx ea65 EyeboxOne glk icp_a106 imonlcd
+imon irtrans joy lb216 lcdm001 lcterm linux_input MD8800 ms6931
+mtc_s16209x MtxOrb NoritakeVFD Olimex_MOD_LCD1x9 pyramid rawserial
+serialPOS serialVFD sli SureElec text tyan vlsys_m428 yard2LCD
+endef
+
+LCDPROC_CORE_DRIVERS:=$(strip $(LCDPROC_CORE_DRIVERS_TEXT))
+
+define Package/lcdproc-server/description
+$(call Package/lcdproc/Default-description)
+
+This package contains the server and a core set of display drivers
+without external dependencies:
+$(LCDPROC_CORE_DRIVERS_TEXT)
+endef
+
+define Package/lcdproc-server/conffiles
+/etc/LCDd.conf
+endef
+
+
+define Package/lcdproc-drivers
+ $(call Package/lcdproc/Default)
+ TITLE:=LCD Display extra drivers
+ DEPENDS:=+lcdproc-server +libncurses +libusb-1.0 +libusb-compat +libftdi1 \
+ +GPIO_SUPPORT:libugpio +serdisplib
+endef
+
+define LCDPROC_OTHER_DRIVERS_TEXT
+curses futaba glcd hd44780 IOWarrior i2500vfd lis picolcd shuttleVFD ula200
+endef
+
+ifeq ($(CONFIG_PACKAGE_kmod-lp),y)
+LCDPROC_OTHER_DRIVERS_TEXT+=sdeclcd sed1330 sed1520 stv5730 t6963
+endif
+
+LCDPROC_OTHER_DRIVERS:=$(strip $(LCDPROC_OTHER_DRIVERS_TEXT))
+
+define Package/lcdproc-drivers/description
+$(call Package/lcdproc/Default-description)
+
+This package contains display drivers with external dependencies:
+$(LCDPROC_OTHER_DRIVERS_TEXT)
+endef
+
+CONFIGURE_ARGS += \
+ --disable-libX11 \
+ --disable-libhid \
+ --disable-libpng \
+ --disable-freetype \
+ --enable-drivers='all,!g15,!g15driver,!glcdlib,!irman,!lirc,!mdm166a,!mx5000,!svga,!xosd'
+
+MAKE_FLAGS += \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ LDFLAGS="$(TARGET_LDFLAGS)"
+
+
+define Package/lcdproc-clients/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/clients/lcdproc/lcdproc $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/clients/lcdexec/lcdexec $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/clients/lcdvc/lcdvc $(1)/usr/bin/
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/clients/lcdproc/lcdproc.conf $(1)/etc/
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/clients/lcdexec/lcdexec.conf $(1)/etc/
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/clients/lcdvc/lcdvc.conf $(1)/etc/
+ $(INSTALL_BIN) ./files/lcd* $(1)/etc/init.d/
+endef
+
+define Package/lcdproc-server/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_DIR) $(1)/usr/lib/lcdproc
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/server/LCDd $(1)/usr/sbin/
+ $(CP) $(foreach driver,$(LCDPROC_CORE_DRIVERS),$(PKG_BUILD_DIR)/server/drivers/$(driver).so) $(1)/usr/lib/lcdproc/
+ $(CP) -p $(PKG_BUILD_DIR)/LCDd.conf $(PKG_BUILD_DIR)/LCDd.conf.orig
+ sed -i -r \
+ -e 's!^(DriverPath=).*$$$$!\1/usr/lib/lcdproc/!' \
+ -e 's!^(Driver=)curses$$$$!\1sdeclcd!' \
+ $(PKG_BUILD_DIR)/LCDd.conf
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/LCDd.conf $(1)/etc/
+ $(INSTALL_BIN) ./files/LCDd $(1)/etc/init.d/
+endef
+
+define Package/lcdproc-drivers/install
+ $(INSTALL_DIR) $(1)/usr/lib/lcdproc
+ $(CP) $(foreach driver,$(LCDPROC_OTHER_DRIVERS),$(PKG_BUILD_DIR)/server/drivers/$(driver).so) $(1)/usr/lib/lcdproc/
+endef
+
+
+$(eval $(call BuildPackage,lcdproc-clients))
+$(eval $(call BuildPackage,lcdproc-server))
+$(eval $(call BuildPackage,lcdproc-drivers))
+
diff --git a/external/subpack/utils/lcdproc/files/LCDd b/external/subpack/utils/lcdproc/files/LCDd
new file mode 100755
index 0000000..595407f
--- /dev/null
+++ b/external/subpack/utils/lcdproc/files/LCDd
@@ -0,0 +1,14 @@
+#!/bin/sh /etc/rc.common
+
+START=22
+USE_PROCD=1
+PROG=/usr/sbin/LCDd
+
+config_file=/etc/LCDd.conf
+
+start_service() {
+ procd_open_instance
+ procd_set_param command $PROG -f -c $config_file
+ procd_close_instance
+}
+
diff --git a/external/subpack/utils/lcdproc/files/lcdexec b/external/subpack/utils/lcdproc/files/lcdexec
new file mode 100755
index 0000000..e6a76f6
--- /dev/null
+++ b/external/subpack/utils/lcdproc/files/lcdexec
@@ -0,0 +1,14 @@
+#!/bin/sh /etc/rc.common
+
+START=50
+USE_PROCD=1
+PROG=/usr/bin/lcdexec
+
+config_file=/etc/lcdexec.conf
+
+start_service() {
+ procd_open_instance
+ procd_set_param command $PROG -f -c $config_file
+ procd_close_instance
+}
+
diff --git a/external/subpack/utils/lcdproc/files/lcdproc b/external/subpack/utils/lcdproc/files/lcdproc
new file mode 100755
index 0000000..15eb997
--- /dev/null
+++ b/external/subpack/utils/lcdproc/files/lcdproc
@@ -0,0 +1,14 @@
+#!/bin/sh /etc/rc.common
+
+START=50
+USE_PROCD=1
+PROG=/usr/bin/lcdproc
+
+config_file=/etc/lcdproc.conf
+
+start_service() {
+ procd_open_instance
+ procd_set_param command $PROG -f -c $config_file
+ procd_close_instance
+}
+
diff --git a/external/subpack/utils/lcdproc/files/lcdvc b/external/subpack/utils/lcdproc/files/lcdvc
new file mode 100755
index 0000000..0362815
--- /dev/null
+++ b/external/subpack/utils/lcdproc/files/lcdvc
@@ -0,0 +1,14 @@
+#!/bin/sh /etc/rc.common
+
+START=50
+USE_PROCD=1
+PROG=/usr/bin/lcdvc
+
+config_file=/etc/lcdvc.conf
+
+start_service() {
+ procd_open_instance
+ procd_set_param command $PROG -f -c $config_file
+ procd_close_instance
+}
+
diff --git a/external/subpack/utils/lcdproc/patches/100-remove-build-timestamp.patch b/external/subpack/utils/lcdproc/patches/100-remove-build-timestamp.patch
new file mode 100644
index 0000000..1c6c84d
--- /dev/null
+++ b/external/subpack/utils/lcdproc/patches/100-remove-build-timestamp.patch
@@ -0,0 +1,31 @@
+--- a/clients/lcdproc/main.c
++++ b/clients/lcdproc/main.c
+@@ -58,7 +58,6 @@ int Quit = 0;
+ int sock = -1;
+
+ char *version = VERSION;
+-char *build_date = __DATE__;
+
+ int lcd_wid = 0;
+ int lcd_hgt = 0;
+--- a/server/main.c
++++ b/server/main.c
+@@ -104,7 +104,6 @@
+ char *version = VERSION;
+ char *protocol_version = PROTOCOL_VERSION;
+ char *api_version = API_VERSION;
+-char *build_date = __DATE__;
+
+
+ /**** Configuration variables ****/
+@@ -197,8 +196,8 @@ main(int argc, char **argv)
+
+ /* Report that server is starting (report will be delayed) */
+ report(RPT_NOTICE, "LCDd version %s starting", version);
+- report(RPT_INFO, "Built on %s, protocol version %s, API version %s",
+- build_date, protocol_version, api_version);
++ report(RPT_INFO, "Protocol version %s, API version %s",
++ protocol_version, api_version);
+
+ clear_settings();
+
diff --git a/external/subpack/utils/lcdproc/patches/110-in-outb.patch b/external/subpack/utils/lcdproc/patches/110-in-outb.patch
new file mode 100644
index 0000000..cd87e18
--- /dev/null
+++ b/external/subpack/utils/lcdproc/patches/110-in-outb.patch
@@ -0,0 +1,11 @@
+--- a/server/drivers/port.h
++++ b/server/drivers/port.h
+@@ -94,7 +94,7 @@ static inline int port_deny_multiple(uns
+ /* ---------------------------- Linux ------------------------------------ */
+ /* Use ioperm, inb and outb in <sys/io.h> (Linux) */
+ /* And iopl for higher addresses of PCI LPT cards */
+-#if defined HAVE_IOPERM
++#if defined(__GLIBC__) || (defined(__x86__) || defined(__x86_64__))
+
+ /* Glibc2 and Glibc1 */
+ # ifdef HAVE_SYS_IO_H
diff --git a/external/subpack/utils/lcdproc/patches/120-gcc10.patch b/external/subpack/utils/lcdproc/patches/120-gcc10.patch
new file mode 100644
index 0000000..d33e8e4
--- /dev/null
+++ b/external/subpack/utils/lcdproc/patches/120-gcc10.patch
@@ -0,0 +1,21 @@
+--- a/clients/lcdproc/iface.c
++++ b/clients/lcdproc/iface.c
+@@ -32,6 +32,7 @@
+ #define UNSET_INT -1
+ #define UNSET_STR "\01"
+
++IfaceInfo iface[MAX_INTERFACES];
+
+ static int iface_count = 0; /* number of interfaces */
+ static char unit_label[10] = "B"; /* default unit label is Bytes */
+--- a/clients/lcdproc/iface.h
++++ b/clients/lcdproc/iface.h
+@@ -18,7 +18,7 @@
+ /** max number of interfaces in multi-interface mode */
+ #define MAX_INTERFACES 3
+
+-IfaceInfo iface[MAX_INTERFACES]; /* interface info */
++extern IfaceInfo iface[MAX_INTERFACES]; /* interface info */
+
+ /** Update screen content */
+ int iface_screen(int rep, int display, int *flags_ptr);
diff --git a/external/subpack/utils/less/Makefile b/external/subpack/utils/less/Makefile
new file mode 100644
index 0000000..b67a243
--- /dev/null
+++ b/external/subpack/utils/less/Makefile
@@ -0,0 +1,80 @@
+#
+# Copyright (C) 2010-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=less
+PKG_VERSION:=563
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.greenwoodsoftware.com/less
+PKG_HASH:=ce5b6d2b9fc4442d7a07c93ab128d2dff2ce09a1d4f2d055b95cf28dd0dc9a9a
+
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=Julen Landa Alustiza <julen@zokormazo.info>
+PKG_CPE_ID:=cpe:/a:gnu:less
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/less/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Pager program similar to more
+ URL:=http://www.greenwoodsoftware.com/less/
+ ALTERNATIVES:=200:/usr/bin/less:/usr/libexec/less-gnu
+endef
+
+define Package/less/Default/description
+ Full version of GNU less utility
+endef
+
+define Package/less
+ $(call Package/less/Default)
+ DEPENDS:=+libncurses
+ VARIANT:=narrow
+endef
+
+define Package/less/description
+ $(call Package/less/Default/description)
+endef
+
+define Package/less-wide
+ $(call Package/less/Default)
+ TITLE+= (Unicode)
+ DEPENDS:=+libncursesw
+ VARIANT:=wide
+endef
+
+define Package/less-wide/description
+ $(call Package/less/Default/description)
+ This package contains the Unicode enabled version of less.
+endef
+
+ifeq ($(BUILD_VARIANT),narrow)
+ CONFIGURE_VARS += \
+ ac_cv_lib_ncursesw_initscr=no
+endif
+
+ifeq ($(BUILD_VARIANT),wide)
+ CONFIGURE_VARS += \
+ ac_cv_lib_ncursesw_initscr=yes
+endif
+
+define Package/less/install
+ $(INSTALL_DIR) $(1)/usr/libexec
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/less $(1)/usr/libexec/less-gnu
+endef
+
+Package/less-wide/install = $(Package/less/install)
+
+$(eval $(call BuildPackage,less))
+$(eval $(call BuildPackage,less-wide))
diff --git a/external/subpack/utils/libnetwork/Makefile b/external/subpack/utils/libnetwork/Makefile
new file mode 100644
index 0000000..4bd865c
--- /dev/null
+++ b/external/subpack/utils/libnetwork/Makefile
@@ -0,0 +1,52 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libnetwork
+PKG_RELEASE:=1
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+GO_PKG:=github.com/docker/libnetwork
+GO_PKG_BUILD_PKG:= \
+ $(GO_PKG)/cmd/proxy \
+ $(GO_PKG)/cmd/dnet
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://$(GO_PKG)
+PKG_SOURCE_VERSION:=f6ccccb1c082a432c2a5814aaedaca56af33d9ea
+PKG_SOURCE_DATE:=2022-06-02
+PKG_MIRROR_HASH:=92a23ff620c3cf3b05bc01a06721a9f78dfb6bc5b048dbcf70ea9542cec8e7a2
+
+PKG_MAINTAINER:=Gerard Ryan <G.M0N3Y.2503@gmail.com>
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/libnetwork
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=networking for containers
+ URL:=https://github.com/docker/libnetwork
+ DEPENDS:=$(GO_ARCH_DEPENDS)
+endef
+
+define Package/libnetwork/description
+Libnetwork provides a native Go implementation for connecting containers.
+The goal of libnetwork is to deliver a robust Container Network Model that provides a consistent programming interface and the required network abstractions for applications.
+endef
+
+GO_PKG_BUILD_VARS += GO111MODULE=auto
+
+define Package/libnetwork/install
+ $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
+
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dnet $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/proxy $(1)/usr/bin/docker-proxy
+endef
+
+$(eval $(call GoBinPackage,libnetwork))
+$(eval $(call BuildPackage,libnetwork))
diff --git a/external/subpack/utils/lm-sensors/Makefile b/external/subpack/utils/lm-sensors/Makefile
new file mode 100644
index 0000000..ee81b6c
--- /dev/null
+++ b/external/subpack/utils/lm-sensors/Makefile
@@ -0,0 +1,128 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=lm-sensors
+PKG_VERSION:=3.6.0
+PKG_RELEASE:=1
+
+PKG_VERSION_SUBST=$(subst .,-,$(PKG_VERSION))
+PKG_SOURCE_URL:=https://codeload.github.com/lm-sensors/lm-sensors/tar.gz/V$(PKG_VERSION_SUBST)?
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_HASH:=0591f9fa0339f0d15e75326d0365871c2d4e2ed8aa1ff759b3a55d3734b7d197
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION_SUBST)
+
+PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+PKG_LICENSE:=GPL-2.0-or-later LGPL-2.1-or-later
+PKG_CPE_ID:=cpe:/a:lm_sensors:lm_sensors
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/lm-sensors/Default
+ DEPENDS:=+sysfsutils
+ URL:=https://hwmon.wiki.kernel.org/lm_sensors
+endef
+
+define Package/lm-sensors
+ $(call Package/lm-sensors/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=lm-sensors
+ DEPENDS+=+libsensors
+endef
+
+define Package/lm-sensors-detect
+ $(call Package/lm-sensors/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=lm-sensors-detect
+ DEPENDS+=+lm-sensors \
+ +PACKAGE_lm-sensors-detect:perl \
+ +PACKAGE_lm-sensors-detect:perlbase-essential \
+ +PACKAGE_lm-sensors-detect:perlbase-fcntl \
+ +PACKAGE_lm-sensors-detect:perlbase-file \
+ +PACKAGE_lm-sensors-detect:perlbase-xsloader
+endef
+
+define Package/libsensors
+ $(call Package/lm-sensors/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=libsensors
+ ABI_VERSION:=5
+endef
+
+define Package/lm-sensors/description
+ utility to read hardware sensor data
+endef
+
+define Package/lm-sensors-detect/description
+ script to autodetect sensor hardware
+endef
+
+define Package/libsensors/description
+ lm-sensors libraries
+endef
+
+define Package/lm-sensors/conffiles
+/etc/sensors.conf
+/etc/sensors3.conf
+endef
+
+define Build/Compile
+ +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) \
+ KERNELVERSION="$(LINUX_VERSION)" \
+ LINUX="$(LINUX_DIR)" \
+ CC="$(TARGET_CC)" \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ CPPFLAGS="$(TARGET_CPPFLAGS)" \
+ STAGING_DIR="$(STAGING_DIR)" \
+ PREFIX="/usr" \
+ MACHINE="$(ARCH)" \
+ EXLDFLAGS="" \
+ user
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/sensors
+ $(CP) \
+ $(PKG_BUILD_DIR)/lib/sensors.h \
+ $(1)/usr/include/sensors
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) \
+ $(PKG_BUILD_DIR)/lib/libsensors.{a,so*} \
+ $(1)/usr/lib
+endef
+
+define Package/lm-sensors/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/prog/sensors/sensors $(1)/usr/sbin
+ifeq ($(ARCH),i386)
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_CONF) ./files/sensors.conf $(1)/etc/sensors.conf
+endif
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/lm-sensors.init $(1)/etc/init.d/lm-sensors
+endef
+
+define Package/lm-sensors-detect/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/prog/detect/sensors-detect $(1)/usr/sbin
+endef
+
+define Package/libsensors/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/lib/libsensors.so* $(1)/usr/lib
+endef
+
+$(eval $(call BuildPackage,libsensors))
+$(eval $(call BuildPackage,lm-sensors))
+$(eval $(call BuildPackage,lm-sensors-detect))
diff --git a/external/subpack/utils/lm-sensors/files/lm-sensors.init b/external/subpack/utils/lm-sensors/files/lm-sensors.init
new file mode 100644
index 0000000..5ac7a72
--- /dev/null
+++ b/external/subpack/utils/lm-sensors/files/lm-sensors.init
@@ -0,0 +1,14 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2017 Philip Prindeville, Redfish Solutions LLC
+
+START=28
+STOP=
+
+PROG=/usr/sbin/sensors
+
+start() {
+ [ -f /etc/sensors.conf -o -f /etc/sensors3.conf ] || return
+
+ $PROG -s
+}
+
diff --git a/external/subpack/utils/lm-sensors/files/sensors.conf b/external/subpack/utils/lm-sensors/files/sensors.conf
new file mode 100644
index 0000000..505b9d9
--- /dev/null
+++ b/external/subpack/utils/lm-sensors/files/sensors.conf
@@ -0,0 +1,117 @@
+chip "pc87366-*"
+
+# Soekris net4801 configuration
+
+# Written by Henrik Brix Andersen <henrik@brixandersen.dk>
+# Latest version can be found at http://www.brixandersen.dk/
+
+# The configuration is partly based on the PC87366 datasheet and
+# partly borrowed from the env4801 utility by Poul-Henning
+# Kamp <phk@phk.freebsd.dk>
+
+# Datasheet: http://www.winbond.com/PDF/APCsheet/PC87366.pdf
+# env4801: http://phk.freebsd.dk/soekris/env4801/
+
+
+# Voltage inputs
+ ignore vid
+
+ # Unknown
+ # label in0 "avi0"
+ ignore in0
+
+
+ # Core Voltage, +2.0V
+ label in1 "VCORE"
+ set in1_min 1.9
+ set in1_max 2.1
+
+
+ # VCC, +5.0V
+ label in2 "VCC"
+ compute in2 @*2, @/2
+
+
+ # Power Supply Input, +6.0V - +28.0V
+ label in3 "VPWR"
+ compute in3 @*20.1, @/20.1
+ set in3_min 6.0
+ set in3_max 28.0
+
+
+ # +12V
+ label in4 "+12V"
+ compute in4 @*4.83, @/4.83
+ set in4_min 11
+ set in4_max 13
+
+
+ # -12V
+ label in5 "-12V"
+ # If in10 on your net4801 doesn't have the 3.3V reference, use this
+ # compute line instead:
+ # compute in5 (@-3.3)*19.2+3.3, (@-3.3)/19.2+3.3
+ compute in5 (@-in10)*19.2+in10, (@-in10)/19.2+in10
+ set in5_min -13
+ set in5_max -11
+
+
+ # GND, 0V
+ label in6 "GND"
+ set in6_min 0
+ set in6_max 0
+
+
+ # Standby Voltage, +3.3V
+ # Internally divided by 2
+ label in7 "Vsb"
+ compute in7 @*2, @/2
+ set in7_min 3.0
+ set in7_max 3.6
+
+
+ # Supply Voltage, +3.3V
+ # Internally divided by 2
+ label in8 "Vdd"
+ compute in8 @*2, @/2
+ set in8_min 3.0
+ set in8_max 3.6
+
+
+ # Battery Backup Supply Voltage, +3.0V
+ label in9 "Vbat"
+ set in9_min 2.4
+ set in9_max 3.6
+
+
+ # Analog Supply Voltage, +3.3V
+ # Internally divided by 2
+ label in10 "AVdd"
+ compute in10 @*2, @/2
+ set in10_min 3.0
+ set in10_max 3.6
+
+
+# Temperature inputs
+ ignore temp1
+ ignore temp2
+
+ # PC87366 Internal Temperature
+ # PC87366 Recommended Operating Conditions: 0 - 70C
+ # SC1100 Recommended Operating Conditions: 0 - 85C
+ label temp3 "Temp"
+ label temp3_crit "Critical"
+ set temp3_min 0
+ set temp3_max 70
+ set temp3_crit 85
+
+
+ ignore temp4
+ ignore temp5
+ ignore temp6
+
+
+# Fan inputs
+ ignore fan1
+ ignore fan2
+ ignore fan3
diff --git a/external/subpack/utils/lm-sensors/patches/001-Add_support_for_dev_name_formatted_like_a000000.wifi.patch b/external/subpack/utils/lm-sensors/patches/001-Add_support_for_dev_name_formatted_like_a000000.wifi.patch
new file mode 100644
index 0000000..a29b4ce
--- /dev/null
+++ b/external/subpack/utils/lm-sensors/patches/001-Add_support_for_dev_name_formatted_like_a000000.wifi.patch
@@ -0,0 +1,23 @@
+From 6da486d7415e426ec983baa5f8edafe0ff4c4171 Mon Sep 17 00:00:00 2001
+From: 7217043955 <85880133+7217043955@users.noreply.github.com>
+Date: Tue, 6 Sep 2022 15:48:11 +0800
+Subject: [PATCH] Add support for dev_name formatted like "a000000.wifi"
+
+---
+ lib/sysfs.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/lib/sysfs.c
++++ b/lib/sysfs.c
+@@ -663,8 +663,9 @@ static int classify_device(const char *d
+ if ((!subsys || !strcmp(subsys, "platform") ||
+ !strcmp(subsys, "of_platform"))) {
+ /* must be new ISA (platform driver) */
+- if (sscanf(dev_name, "%*[a-z0-9_].%d", &entry->chip.addr) != 1)
+- entry->chip.addr = 0;
++ if (sscanf(dev_name, "%*[a-zA-Z0-9_]%*1[.:]%d", &entry->chip.addr) == 1);
++ else if (sscanf(dev_name, "%x.%*s", &entry->chip.addr) == 1);
++ else entry->chip.addr = 0;
+ entry->chip.bus.type = SENSORS_BUS_TYPE_ISA;
+ entry->chip.bus.nr = 0;
+ } else if (subsys && !strcmp(subsys, "acpi")) {
diff --git a/external/subpack/utils/logrotate/Makefile b/external/subpack/utils/logrotate/Makefile
new file mode 100644
index 0000000..d577a53
--- /dev/null
+++ b/external/subpack/utils/logrotate/Makefile
@@ -0,0 +1,75 @@
+#
+# Copyright (C) 2006-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=logrotate
+PKG_VERSION:=3.22.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://github.com/logrotate/logrotate/releases/download/$(PKG_VERSION)
+PKG_HASH:=42b4080ee99c9fb6a7d12d8e787637d057a635194e25971997eebbe8d5e57618
+
+PKG_MAINTAINER:=Christian Beier <cb@shoutrlabs.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:gentoo:logrotate
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/logrotate
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libpopt +LOGROTATE_ACL:libacl
+ TITLE:=rotates, compresses, and mails system logs
+ URL:=https://github.com/logrotate/logrotate
+ MENU:=1
+endef
+
+define Package/logrotate/config
+ if PACKAGE_logrotate
+ config LOGROTATE_ACL
+ bool
+ prompt "Enable ACL support"
+ default y if USE_FS_ACL_ATTR
+ endif
+endef
+
+define Package/logrotate/description
+ logrotate is designed to ease administration of systems that generate large
+ numbers of log files. It allows auto-matic rotation, compression, removal and
+ mailing of log files. Each log file may be handled daily, weekly, monthly or
+ when it grows too large.
+endef
+
+define Package/logrotate/conffiles
+/etc/logrotate.conf
+/etc/logrotate.d
+endef
+
+CONFIGURE_ARGS += \
+ $(if $(CONFIG_LOGROTATE_ACL),--with,--without)-acl \
+ --without-selinux
+
+define Build/Compile
+ $(call Build/Compile/Default, \
+ RPM_OPT_FLAGS:="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
+ LDFLAGS="$(TARGET_LDFLAGS)" \
+ logrotate \
+ )
+endef
+
+define Package/logrotate/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) ${PKG_BUILD_DIR}/logrotate $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_DATA) ./files/logrotate.conf $(1)/etc/
+ $(INSTALL_DIR) $(1)/etc/logrotate.d
+endef
+
+$(eval $(call BuildPackage,logrotate))
diff --git a/external/subpack/utils/logrotate/files/logrotate.conf b/external/subpack/utils/logrotate/files/logrotate.conf
new file mode 100644
index 0000000..9a91db9
--- /dev/null
+++ b/external/subpack/utils/logrotate/files/logrotate.conf
@@ -0,0 +1,30 @@
+# rotate log files weekly
+weekly
+#daily
+
+# keep 4 weeks worth of backlogs
+rotate 4
+
+# create new (empty) log files after rotating old ones
+create
+
+notifempty
+nomail
+#olddir /var/log/backup/
+missingok
+#dateext
+
+# uncomment this if you want your log files compressed
+#compress
+
+# packages can drop log rotation information into this directory
+include /etc/logrotate.d
+
+# no packages own lastlog or wtmp -- we'll rotate them here
+#/var/log/wtmp {
+# monthly
+# create 0664 root utmp
+# rotate 1
+#}
+
+# system-specific logs may be also be configured here.
diff --git a/external/subpack/utils/logrotate/test.sh b/external/subpack/utils/logrotate/test.sh
new file mode 100644
index 0000000..6102136
--- /dev/null
+++ b/external/subpack/utils/logrotate/test.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+logrotate --version 2>&1 | grep "$2"
diff --git a/external/subpack/utils/lrzsz/Makefile b/external/subpack/utils/lrzsz/Makefile
new file mode 100644
index 0000000..7de52aa
--- /dev/null
+++ b/external/subpack/utils/lrzsz/Makefile
@@ -0,0 +1,69 @@
+#
+# Copyright (C) 2006-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=lrzsz
+PKG_VERSION:=0.12.21
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.gz
+PKG_SOURCE_URL:=@DEBIAN/pool/main/l/lrzsz/
+PKG_HASH:=3262e5df47b108d33e184ff3bf5af14ddca1ac15118ac4ed9171a57c1593ae00
+PKG_BUILD_DIR=$(BUILD_DIR)/lrzsz-990823
+
+PKG_MAINTAINER:=Hsing-Wang Liao <kuoruan@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:lrzsz_project:lrzsz
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/lrzsz
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Tools for zmodem/xmodem/ymodem file transfer
+ URL:=https://ohse.de/uwe/software/lrzsz.html
+endef
+
+define Package/lrzsz/description
+ lrzsz is a cosmetically modified zmodem/ymodem/xmodem package built
+ from the public-domain version of Chuck Forsberg's rzsz package.
+
+ These programs use error correcting protocols ({z,x,y}modem) to send
+ (sz, sx, sb) and receive (rz, rx, rb) files over a dial-in serial port
+ from a variety of programs running under various operating systems.
+endef
+
+# to stop automake from running, the bundled autohell crap is too old
+define Build/Configure
+ touch $(PKG_BUILD_DIR)/*
+ touch $(PKG_BUILD_DIR)/*/*
+ $(call Build/Configure/Default)
+endef
+
+define Package/lrzsz/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lrz $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lsz $(1)/usr/bin/
+ (cd $(1)/usr/bin; \
+ ln -fs lrz lrx; \
+ ln -fs lrz lrb; \
+ ln -fs lrz rz; \
+ ln -fs lrz rx; \
+ ln -fs lrz rb; \
+ ln -fs lsz lsx; \
+ ln -fs lsz lsb; \
+ ln -fs lsz sz; \
+ ln -fs lsz sx; \
+ ln -fs lsz sb; \
+ );
+endef
+
+$(eval $(call BuildPackage,lrzsz))
diff --git a/external/subpack/utils/lrzsz/patches/001-siginterrupt-after-the-call-to-signal-otherwise-ymod.patch b/external/subpack/utils/lrzsz/patches/001-siginterrupt-after-the-call-to-signal-otherwise-ymod.patch
new file mode 100644
index 0000000..730d466
--- /dev/null
+++ b/external/subpack/utils/lrzsz/patches/001-siginterrupt-after-the-call-to-signal-otherwise-ymod.patch
@@ -0,0 +1,22 @@
+From 89fef6d8dc539ed6225b46b8e755e08bbf48d27b Mon Sep 17 00:00:00 2001
+From: Uwe Ohse <uwe@ohse.de>
+Date: Sun, 1 Mar 2020 22:34:24 +0000
+Subject: [PATCH] siginterrupt after the call to signal, otherwise ymodem
+ transfer hangs. WTF?
+
+---
+ src/zreadline.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/src/zreadline.c
++++ b/src/zreadline.c
+@@ -71,6 +71,9 @@ readline_internal(unsigned int timeout)
+ vstringf("Calling read: alarm=%d Readnum=%d ",
+ n, readline_readnum);
+ signal(SIGALRM, zreadline_alarm_handler);
++#ifdef HAVE_SIGINTERRUPT
++ siginterrupt(SIGALRM,1);
++#endif
+ alarm(n);
+ }
+ else if (Verbose > 5)
diff --git a/external/subpack/utils/lrzsz/patches/002-may-be-security-fix-avoid-possible-underflow.patch b/external/subpack/utils/lrzsz/patches/002-may-be-security-fix-avoid-possible-underflow.patch
new file mode 100644
index 0000000..81ec959
--- /dev/null
+++ b/external/subpack/utils/lrzsz/patches/002-may-be-security-fix-avoid-possible-underflow.patch
@@ -0,0 +1,28 @@
+From a7c525191aa725f4ebb7b489cdd7dd854a4e42fb Mon Sep 17 00:00:00 2001
+From: Uwe Ohse <uwe@ohse.de>
+Date: Sun, 1 Mar 2020 22:35:28 +0000
+Subject: [PATCH] may-be-security-fix: avoid possible underflow
+
+Fixes: CVE-2018-10195
+
+[a.heider: mention CVE in commit message]
+---
+ src/zm.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/src/zm.c
++++ b/src/zm.c
+@@ -432,10 +432,11 @@ zsdata(const char *buf, size_t length, i
+ VPRINTF(3,("zsdata: %lu %s", (unsigned long) length,
+ Zendnames[(frameend-ZCRCE)&3]));
+ crc = 0;
+- do {
++ while (length>0) {
+ zsendline(*buf); crc = updcrc((0377 & *buf), crc);
+ buf++;
+- } while (--length>0);
++ length--;
++ }
+ xsendline(ZDLE); xsendline(frameend);
+ crc = updcrc(frameend, crc);
+
diff --git a/external/subpack/utils/lrzsz/patches/100-install_delete_fix.patch b/external/subpack/utils/lrzsz/patches/100-install_delete_fix.patch
new file mode 100644
index 0000000..7263ab8
--- /dev/null
+++ b/external/subpack/utils/lrzsz/patches/100-install_delete_fix.patch
@@ -0,0 +1,19 @@
+--- a/src/Makefile.in
++++ b/src/Makefile.in
+@@ -414,13 +414,13 @@ install-exec-local:
+ rm -f $(DESTDIR)/$(bindir)/`echo lsb | sed -e '$(transform)'`
+ ln $(DESTDIR)/$(bindir)/`echo lsz |sed -e '$(transform)'` \
+ $(DESTDIR)/$(bindir)/`echo lsb |sed -e '$(transform)'`
+- rm -f $(bindir)/`echo lsx | sed -e '$(transform)'`
++ rm -f $(DESTDIR)/$(bindir)/`echo lsx | sed -e '$(transform)'`
+ ln $(DESTDIR)/$(bindir)/`echo lsz |sed -e '$(transform)'` \
+ $(DESTDIR)/$(bindir)/`echo lsx |sed -e '$(transform)'`
+- rm -f $(bindir)/`echo lrb | sed -e '$(transform)'`
++ rm -f $(DESTDIR)/$(bindir)/`echo lrb | sed -e '$(transform)'`
+ ln $(DESTDIR)/$(bindir)/`echo lrz |sed -e '$(transform)'` \
+ $(DESTDIR)/$(bindir)/`echo lrb |sed -e '$(transform)'`
+- rm -f $(bindir)/`echo lrx | sed -e '$(transform)'`
++ rm -f $(DESTDIR)/$(bindir)/`echo lrx | sed -e '$(transform)'`
+ ln $(DESTDIR)/$(bindir)/`echo lrz |sed -e '$(transform)'` \
+ $(DESTDIR)/$(bindir)/`echo lrx |sed -e '$(transform)'`
+ # rm -f $(bindir)/`echo lrzszbug | sed -e '$(transform)'`
diff --git a/external/subpack/utils/lrzsz/patches/200-format.patch b/external/subpack/utils/lrzsz/patches/200-format.patch
new file mode 100644
index 0000000..26b86c1
--- /dev/null
+++ b/external/subpack/utils/lrzsz/patches/200-format.patch
@@ -0,0 +1,73 @@
+--- a/lib/long-options.c
++++ b/lib/long-options.c
+@@ -22,6 +22,7 @@
+ #endif
+
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <getopt.h>
+ #include "long-options.h"
+
+--- a/src/lrz.c
++++ b/src/lrz.c
+@@ -2296,7 +2296,7 @@ exec2(const char *s)
+ if (*s == '!')
+ ++s;
+ io_mode(0,0);
+- execl("/bin/sh", "sh", "-c", s);
++ execl("/bin/sh", "sh", "-c", s, NULL);
+ zpfatal("execl");
+ exit(1);
+ }
+--- a/src/lsyslog.c
++++ b/src/lsyslog.c
+@@ -22,6 +22,7 @@
+ #ifdef ENABLE_SYSLOG
+ #include "zglobal.h"
+ #include <pwd.h>
++#include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #endif
+--- a/src/lsz.c
++++ b/src/lsz.c
+@@ -1988,7 +1988,7 @@ zsendfdata (struct zm_fileinfo *zi)
+ blklen = calc_blklen (total_sent);
+ total_sent += blklen + OVERHEAD;
+ if (Verbose > 2 && blklen != old)
+- vstringf (_("blklen now %d\n"), blklen);
++ vstringf (_("blklen now %zu\n"), blklen);
+ #ifdef HAVE_MMAP
+ if (mm_addr) {
+ if (zi->bytes_sent + blklen < mm_size)
+--- a/src/zm.c
++++ b/src/zm.c
+@@ -453,7 +453,7 @@ zsda32(const char *buf, size_t length, i
+ int c;
+ unsigned long crc;
+ int i;
+- VPRINTF(3,("zsdat32: %d %s", length, Zendnames[(frameend-ZCRCE)&3]));
++ VPRINTF(3,("zsdat32: %zu %s", length, Zendnames[(frameend-ZCRCE)&3]));
+
+ crc = 0xFFFFFFFFL;
+ zsendline_s(buf,length);
+--- a/src/zreadline.c
++++ b/src/zreadline.c
+@@ -68,7 +68,7 @@ readline_internal(unsigned int timeout)
+ else if (n==0)
+ n=1;
+ if (Verbose > 5)
+- vstringf("Calling read: alarm=%d Readnum=%d ",
++ vstringf("Calling read: alarm=%u Readnum=%zu ",
+ n, readline_readnum);
+ signal(SIGALRM, zreadline_alarm_handler);
+ #ifdef HAVE_SIGINTERRUPT
+@@ -77,7 +77,7 @@ readline_internal(unsigned int timeout)
+ alarm(n);
+ }
+ else if (Verbose > 5)
+- vstringf("Calling read: Readnum=%d ",
++ vstringf("Calling read: Readnum=%zu ",
+ readline_readnum);
+
+ readline_ptr=readline_buffer;
diff --git a/external/subpack/utils/lsof/Makefile b/external/subpack/utils/lsof/Makefile
new file mode 100644
index 0000000..939fd71
--- /dev/null
+++ b/external/subpack/utils/lsof/Makefile
@@ -0,0 +1,39 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=lsof
+PKG_VERSION:=4.99.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/lsof-org/lsof/releases/download/$(PKG_VERSION)
+PKG_HASH:=180e6284aff184d94d273e34f7264edc2af849c07b1c5d6a4183d4d402734245
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+PKG_MAINTAINER:=Maxim Storchak <m.storchak@gmail.com>
+PKG_LICENSE:=lsof
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/lsof
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libtirpc
+ TITLE:=LiSt Open Files - a diagnostic tool
+ URL:=http://people.freebsd.org/~abe/
+endef
+
+CONFIGURE_ARGS += --without-selinux
+
+define Package/lsof/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/lsof $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,lsof))
diff --git a/external/subpack/utils/lsof/patches/000-disable-man.patch b/external/subpack/utils/lsof/patches/000-disable-man.patch
new file mode 100644
index 0000000..cf9a391
--- /dev/null
+++ b/external/subpack/utils/lsof/patches/000-disable-man.patch
@@ -0,0 +1,18 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -208,13 +208,8 @@ EXTRA_DIST += 00.README.FIRST 00CREDITS
+ # Testing
+ EXTRA_DIST += tests/00README tests/TestDB tests/CkTestDB tests/Makefile tests/LsofTest.h check.bash
+
+-# Manpages
+-lsof.man: Lsof.8 version 00DIALECTS
+- soelim < Lsof.8 > $@
+-man8_MANS = lsof.man
+-EXTRA_DIST += Lsof.8
+ # Fix distcheck error
+ clean-local:
+ rm -rf lsof.man
+ distclean-local:
+- rm -rf lockf_owner.h lockf.h
+\ No newline at end of file
++ rm -rf lockf_owner.h lockf.h
diff --git a/external/subpack/utils/lvm2/Makefile b/external/subpack/utils/lvm2/Makefile
new file mode 100644
index 0000000..b307cc5
--- /dev/null
+++ b/external/subpack/utils/lvm2/Makefile
@@ -0,0 +1,163 @@
+#
+# Copyright (C) 2009-2010 Stefan Monnier
+# Copyright (C) 2011-2018 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v3+.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=LVM2
+PKG_VERSION:=2.03.16
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME).$(PKG_VERSION).tgz
+PKG_SOURCE_URL:=https://sourceware.org/pub/lvm2
+PKG_HASH:=e661ece15b5d88d8abe39a4c1e1db2f43e1896f019948bb98b0e15d777680786
+PKG_BUILD_DIR:=$(BUILD_DIR)/lvm2-$(BUILD_VARIANT)/$(PKG_NAME).$(PKG_VERSION)
+
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+PKG_LICENSE:=GPL-2.0 LGPL-2.1
+PKG_LICENSE_FILES:=COPYING COPYING.lib
+PKG_CPE_ID:=cpe:/a:heinz_mauelshagen:lvm2
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libdevmapper/Default
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=The Linux Kernel Device Mapper userspace library
+ URL:=https://sourceware.org/dm/
+ DEPENDS:=+kmod-dm +libpthread +libuuid +librt +libblkid
+endef
+
+
+define Package/libdevmapper
+ $(call Package/libdevmapper/Default)
+ VARIANT := normal
+endef
+
+define Package/libdevmapper-selinux
+ $(call Package/libdevmapper/Default)
+ VARIANT := selinux
+ DEPENDS += +libselinux
+ PROVIDES := libdevmapper
+endef
+
+define Package/libdevmapper/description
+ The device-mapper is a component of the 2.6 linux kernel that supports logical
+ volume management. It is required by LVM2 and EVMS.
+endef
+
+define Package/libdevmapper-selinux/description
+$(call Package/libdevmapper/description)
+ This variant supports SELinux
+
+endef
+
+define Package/lvm2/default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Disc
+ TITLE:=The Linux Logical Volume Manager
+ URL:=https://sourceware.org/lvm2/
+ DEPENDS:=+libreadline +libncurses +libaio
+endef
+
+define Package/lvm2
+ $(call Package/lvm2/default)
+ VARIANT := normal
+ DEPENDS += +libdevmapper
+endef
+
+define Package/lvm2-selinux
+ $(call Package/lvm2/default)
+ VARIANT := selinux
+ DEPENDS += +libdevmapper-selinux
+ PROVIDES := lvm2
+endef
+
+define Package/lvm2/description
+ LVM2 refers to a new userspace toolset that provide logical volume management
+ facilities on linux. It is reasonably backwards-compatible with the original
+ LVM toolset.
+endef
+
+define Package/lvm2-selinux/description
+$(call Package/lvm2/description)
+ This variant supports SELinux
+
+endef
+
+
+CONFIGURE_ARGS += \
+ --disable-o_direct \
+ --with-default-pid-dir=/var/run \
+ --with-default-dm-run-dir=/var/run \
+ --with-default-run-dir=/var/run/lvm \
+ --with-default-locking-dir=/var/lock/lvm \
+ --$(if $(findstring selinux,$(BUILD_VARIANT)),en,dis)able-selinux
+
+ifneq ($(shell /bin/sh -c "echo -n 'X'"),X)
+MAKE_SHELL = SHELL=/bin/bash
+endif
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS) $(FPIC)" \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ $(MAKE_SHELL) \
+ install
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/include/libdevmapper.h $(1)/usr/include
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libdevmapper.so* $(1)/usr/lib
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_BUILD_DIR)/libdm/libdevmapper.pc $(1)/usr/lib/pkgconfig
+endef
+
+define Package/libdevmapper/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libdevmapper.so.* $(1)/usr/lib
+endef
+
+Package/libdevmapper-selinux/install = $(Package/libdevmapper/install)
+
+define Package/lvm2/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/lvm $(1)/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/dmsetup $(1)/sbin
+ $(INSTALL_DIR) $(1)/etc/lvm
+ $(SED) '/^[[:space:]]*\(#\|$$$$\)/d; /cache_dir/s@.*@ cache_dir = "/tmp/lvm/cache"@' $(PKG_INSTALL_DIR)/etc/lvm/lvm.conf
+ $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/lvm/lvm.conf $(1)/etc/lvm/
+ $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/lvm/lvmlocal.conf $(1)/etc/lvm/
+ $(INSTALL_DIR) $(1)/etc/lvm/profile
+ $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/lvm/profile/* $(1)/etc/lvm/profile/
+ $(INSTALL_DIR) $(1)/lib/preinit
+ $(INSTALL_DATA) ./files/lvm2.preinit $(1)/lib/preinit/80_lvm2
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/lvm2.init $(1)/etc/init.d/lvm2
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/block
+ $(INSTALL_DATA) ./files/lvm2.hotplug $(1)/etc/hotplug.d/block/20-lvm2
+ $(FIND) $(PKG_INSTALL_DIR)/usr/sbin/ -type l -exec $(CP) -a {} $(1)/sbin/ \;
+endef
+
+Package/lvm2-selinux/install = $(Package/lvm2/install)
+
+define Package/lvm2/conffiles
+/etc/lvm/lvm.conf
+endef
+
+Package/lvm2-selinux/conffiles = $(Package/lvm2/conffiles)
+
+$(eval $(call BuildPackage,libdevmapper))
+$(eval $(call BuildPackage,libdevmapper-selinux))
+$(eval $(call BuildPackage,lvm2))
+$(eval $(call BuildPackage,lvm2-selinux))
diff --git a/external/subpack/utils/lvm2/files/lvm2.hotplug b/external/subpack/utils/lvm2/files/lvm2.hotplug
new file mode 100644
index 0000000..0ef48c5
--- /dev/null
+++ b/external/subpack/utils/lvm2/files/lvm2.hotplug
@@ -0,0 +1,6 @@
+
+[ "$ACTION" = "add" ] || return 0
+[ -e "/dev/$DEVNAME" ] || return 0
+
+/sbin/lvm vgscan --mknodes --devices /dev/$DEVNAME || :
+/sbin/lvm vgchange -aly --devices /dev/$DEVNAME || :
diff --git a/external/subpack/utils/lvm2/files/lvm2.init b/external/subpack/utils/lvm2/files/lvm2.init
new file mode 100644
index 0000000..4faf5d5
--- /dev/null
+++ b/external/subpack/utils/lvm2/files/lvm2.init
@@ -0,0 +1,14 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2009 Stefan Monnier
+START=15
+
+start () {
+ mkdir -p /tmp/lvm/cache
+ /sbin/lvm vgscan --ignorelockingfailure --mknodes || :
+ /sbin/lvm vgchange -aly --ignorelockingfailure || return 2
+}
+
+stop () {
+ mkdir -p /tmp/lvm/cache
+ /sbin/lvm vgchange -aln --ignorelockingfailure || return 2
+}
diff --git a/external/subpack/utils/lvm2/files/lvm2.preinit b/external/subpack/utils/lvm2/files/lvm2.preinit
new file mode 100644
index 0000000..b654e79
--- /dev/null
+++ b/external/subpack/utils/lvm2/files/lvm2.preinit
@@ -0,0 +1,25 @@
+#!/bin/sh
+# Copyright (C) 2019 Harrie Rooijackers
+
+# The make proecess copies this file to the /lib/preinit/80_lvm2
+# As a result it is executed just before 80_mount_root and makes lvm
+# entities available during the mount_root process that handles any
+# overlays. This allows overlays to be lvm2 partitions.
+
+# Note that /lib/preinit/80_lvm2 needs to be on the initial "lower"
+# partition for this to work.
+
+do_startlvm() {
+ echo "Starting lvm2 during preinit" > /dev/kmsg
+ # The following 3 lines are copied from from the start function
+ # in /etc/rc.d/S15lvm2 which is copyright by Stefan Monnier
+ mkdir -p /tmp/lvm/cache
+ /sbin/lvm vgscan --ignorelockingfailure --mknodes > /dev/kmsg || :
+ /sbin/lvm vgchange -aly --ignorelockingfailure > /dev/kmsg || return 2
+}
+
+# Perform the function only if lvm2 is enabled by the user
+# Not sure if the test is that useful since it tests the existance
+# of /etc/rc.d/S15lvm2 on the initial "lower" partition only so
+# changes made after the overlay is created are not taken into account
+[ -f /etc/rc.d/S15lvm2 ] && boot_hook_add preinit_main do_startlvm
diff --git a/external/subpack/utils/lvm2/patches/002-const-stdio.patch b/external/subpack/utils/lvm2/patches/002-const-stdio.patch
new file mode 100644
index 0000000..070e834
--- /dev/null
+++ b/external/subpack/utils/lvm2/patches/002-const-stdio.patch
@@ -0,0 +1,43 @@
+--- a/lib/commands/toolcontext.c
++++ b/lib/commands/toolcontext.c
+@@ -1673,7 +1673,7 @@ struct cmd_context *create_toolcontext(u
+ /* FIXME Make this configurable? */
+ reset_lvm_errno(1);
+
+-#ifndef VALGRIND_POOL
++#if defined(__GLIBC__) && !defined(VALGRIND_POOL)
+ /* Set in/out stream buffering before glibc */
+ if (set_buffering
+ #ifdef SYS_gettid
+@@ -2053,7 +2053,7 @@ void destroy_toolcontext(struct cmd_cont
+ dm_hash_destroy(cmd->cft_def_hash);
+
+ dm_device_list_destroy(&cmd->cache_dm_devs);
+-#ifndef VALGRIND_POOL
++#if defined(__GLIBC__) && !defined(VALGRIND_POOL)
+ if (cmd->linebuffer) {
+ /* Reset stream buffering to defaults */
+ if (is_valid_fd(STDIN_FILENO) &&
+--- a/tools/lvmcmdline.c
++++ b/tools/lvmcmdline.c
+@@ -3398,6 +3398,7 @@ int lvm_split(char *str, int *argc, char
+ /* Make sure we have always valid filedescriptors 0,1,2 */
+ static int _check_standard_fds(void)
+ {
++#ifdef __GLIBC__
+ int err = is_valid_fd(STDERR_FILENO);
+
+ if (!is_valid_fd(STDIN_FILENO) &&
+@@ -3424,6 +3425,12 @@ static int _check_standard_fds(void)
+ strerror(errno));
+ return 0;
+ }
++#else
++ if (!is_valid_fd(STDERR_FILENO) ||
++ !is_valid_fd(STDOUT_FILENO) ||
++ !is_valid_fd(STDIN_FILENO))
++ return 0;
++#endif
+
+ return 1;
+ }
diff --git a/external/subpack/utils/lvm2/patches/003-no-mallinfo.patch b/external/subpack/utils/lvm2/patches/003-no-mallinfo.patch
new file mode 100644
index 0000000..e46ead5
--- /dev/null
+++ b/external/subpack/utils/lvm2/patches/003-no-mallinfo.patch
@@ -0,0 +1,45 @@
+--- a/lib/mm/memlock.c
++++ b/lib/mm/memlock.c
+@@ -187,12 +187,15 @@ static void _allocate_memory(void)
+ * memory on free(), this is good enough for our purposes.
+ */
+ while (missing > 0) {
++#ifdef __GLIBC__
+ struct mallinfo inf = mallinfo();
+ hblks = inf.hblks;
++#endif
+
+ if ((areas[area] = malloc(_size_malloc_tmp)))
+ _touch_memory(areas[area], _size_malloc_tmp);
+
++#ifdef __GLIBC__
+ inf = mallinfo();
+
+ if (hblks < inf.hblks) {
+@@ -202,9 +205,12 @@ static void _allocate_memory(void)
+ free(areas[area]);
+ _size_malloc_tmp /= 2;
+ } else {
++#endif
+ ++ area;
+ missing -= _size_malloc_tmp;
++#ifdef __GLIBC__
+ }
++#endif
+
+ if (area == max_areas && missing > 0) {
+ /* Too bad. Warn the user and proceed, as things are
+@@ -525,8 +531,13 @@ static void _lock_mem(struct cmd_context
+ * will not block memory locked thread
+ * Note: assuming _memlock_count_daemon is updated before _memlock_count
+ */
++#ifdef __GLIBC__
+ _use_mlockall = _memlock_count_daemon ? 1 :
+ find_config_tree_bool(cmd, activation_use_mlockall_CFG, NULL);
++#else
++ /* always use mlockall on musl */
++ _use_mlockall = 1;
++#endif
+
+ if (!_use_mlockall) {
+ if (!*_procselfmaps &&
diff --git a/external/subpack/utils/lxc/Config.in b/external/subpack/utils/lxc/Config.in
new file mode 100644
index 0000000..53d7ba5
--- /dev/null
+++ b/external/subpack/utils/lxc/Config.in
@@ -0,0 +1,56 @@
+menu "Configuration"
+ depends on PACKAGE_lxc
+
+config LXC_KERNEL_OPTIONS
+ bool "Enable kernel support for LXC"
+ default n
+ select KERNEL_CGROUPS
+ select KERNEL_NAMESPACES
+ select KERNEL_DEVPTS_MULTIPLE_INSTANCES
+ select KERNEL_POSIX_MQUEUE
+ select KERNEL_CGROUP_SCHED
+ select KERNEL_FAIR_GROUP_SCHED
+ select KERNEL_RT_GROUP_SCHED
+ select KERNEL_CGROUP_CPUACCT
+ select KERNEL_MEMCG
+ select KERNEL_MEMCG_KMEM
+ select KERNEL_CPUSETS
+ select PACKAGE_kmod-ikconfig
+ help
+ Select needed kernel options for LXC related utilities. Options
+ include cgroups, namespaces and other miscellaneous options. These
+ options unfortunately can not be installed as a module.
+
+config LXC_BUSYBOX_OPTIONS
+ bool "Enable busybox support for lxc-create tool"
+ default n
+ select BUSYBOX_CUSTOM
+ select BUSYBOX_CONFIG_HAVE_DOT_CONFIG
+ select BUSYBOX_CONFIG_FEATURE_SEAMLESS_XZ
+ select BUSYBOX_CONFIG_FEATURE_TAR_LONG_OPTIONS
+ select BUSYBOX_CONFIG_UNXZ
+ select BUSYBOX_CONFIG_XZ
+ select BUSYBOX_CONFIG_GETOPT
+ select BUSYBOX_CONFIG_FEATURE_GETOPT_LONG
+ select BUSYBOX_CONFIG_MOUNTPOINT
+ help
+ Select needed busybox options for lxc-create utility. This include XZ tar
+ compression, long option support for tar and built-in getopt support.
+
+config LXC_SECCOMP
+ bool "Enable support for seccomp in LXC"
+ default KERNEL_SECCOMP
+ depends on !arc
+ help
+ Build LXC with support for seccomp filters.
+ Select libseccomp which also pulls-in the needed kernel features.
+
+config LXC_NETWORKING
+ bool "Enable networking support for LXC containers"
+ default n
+ select PACKAGE_kmod-veth
+ select PACKAGE_kmod-macvlan
+ help
+ Enable "veth pair device" and "macvlan"
+
+endmenu
diff --git a/external/subpack/utils/lxc/Makefile b/external/subpack/utils/lxc/Makefile
new file mode 100644
index 0000000..7a5f41c
--- /dev/null
+++ b/external/subpack/utils/lxc/Makefile
@@ -0,0 +1,277 @@
+#
+# Copyright (C) 2013-2015 OpenWrt.org
+# Copyright (C) 2020 Sartura
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=lxc
+PKG_VERSION:=4.0.10
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://linuxcontainers.org/downloads/lxc/
+PKG_HASH:=a10c518056d2e497bd600e4ffac2853bdeab1e835bf455a6d87cc8df128bfae9
+
+PKG_MAINTAINER:=Marko Ratkaj <marko.ratkaj@sartura.hr>
+PKG_LICENSE:=LGPL-2.1-or-later BSD-2-Clause GPL-2.0
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+include $(INCLUDE_DIR)/package.mk
+
+LXC_APPLETS_BIN += \
+ attach autostart cgroup copy config console create destroy device \
+ execute freeze info monitor snapshot start stop unfreeze unshare \
+ usernsexec wait top ls
+
+LXC_APPLETS_LIB += \
+ monitord user-nic
+
+LXC_SCRIPTS += \
+ checkconfig
+
+DEPENDS_APPLETS = +libpthread +libcap +liblxc
+
+DEPENDS_create = +lxc-configs +lxc-hooks +lxc-templates +flock
+
+define Package/lxc/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=LXC userspace tools
+ URL:=https://linuxcontainers.org/
+ DEPENDS:=lxc
+endef
+
+define Package/lxc
+ $(call Package/lxc/Default)
+ DEPENDS:=@!arc
+ MENU:=1
+endef
+
+define Package/lxc-auto
+ $(call Package/lxc/Default)
+ TITLE:= (initscript)
+ DEPENDS+=+lxc-start +lxc-stop
+endef
+
+define Package/lxc-auto/postinst
+[ -n "$${IPKG_INSTROOT}" ] || [ "$${PKG_UPGRADE}" = 1 ] || /etc/init.d/lxc-auto boot
+endef
+
+define Package/lxc-auto/description
+ LXC is the userspace control package for Linux Containers, a lightweight
+ virtual system mechanism sometimes described as "chroot on steroids".
+ This package adds an initscript for starting and stopping the containers
+ on boot and shutdown.
+endef
+
+define Package/lxc-auto/conffiles
+/etc/config/lxc-auto
+endef
+
+define Package/lxc-unprivileged
+ $(call Package/lxc/Default)
+ TITLE:=Helper script for unprivileged containers support
+ DEPENDS+=+shadow-utils +shadow-newuidmap +shadow-newgidmap
+endef
+
+define Package/lxc-unprivileged/description
+ Support for unprivileged containers requires newuidmap and newguidmap.
+ This package makes sure they are available & have correct permissions.
+endef
+
+define Package/lxc-unprivileged/install
+ $(INSTALL_DIR) $(1)/etc/uci-defaults
+ $(INSTALL_DATA) ./files/lxc-unprivileged.defaults $(1)/etc/uci-defaults/lxc-unprivileged
+endef
+
+define Package/lxc/config
+ source "$(SOURCE)/Config.in"
+endef
+
+define Package/lxc/description
+ LXC is the userspace control package for Linux Containers, a lightweight
+ virtual system mechanism sometimes described as "chroot on steroids".
+endef
+
+define Package/lxc-common
+ $(call Package/lxc/Default)
+ TITLE:=LXC common files
+endef
+
+define Package/lxc-hooks
+ $(call Package/lxc/Default)
+ TITLE:=LXC virtual machine hooks
+endef
+
+define Package/lxc-templates
+ $(call Package/lxc/Default)
+ TITLE:=LXC virtual machine templates
+endef
+
+define Package/lxc-configs
+ $(call Package/lxc/Default)
+ TITLE:=LXC virtual machine common config files
+endef
+
+define Package/liblxc
+ $(call Package/lxc/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=LXC userspace library
+ DEPENDS+= +libcap +libpthread +LXC_SECCOMP:libseccomp +libopenssl
+endef
+
+define Package/lxc-init
+ $(call Package/lxc/Default)
+ TITLE:=LXC Lua bindings
+ DEPENDS+= +liblxc
+endef
+
+CONFIGURE_ARGS += \
+ --disable-werror \
+ --disable-rpath \
+ --disable-doc \
+ --disable-api-docs \
+ --disable-apparmor \
+ --disable-selinux \
+ --$(if $(CONFIG_LXC_SECCOMP),en,dis)able-seccomp \
+ --enable-capabilities \
+ --disable-examples
+
+ifdef CONFIG_USE_MIPS16
+ TARGET_CFLAGS += -minterlink-mips16
+endif
+TARGET_LDFLAGS += -lgcc_eh
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/lxc/
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/include/lxc/* \
+ $(1)/usr/include/lxc/
+
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/lib/liblxc.so* \
+ $(1)/usr/lib/
+
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/lxc.pc \
+ $(1)/usr/lib/pkgconfig/
+ $(SED) 's,/usr/include,$$$${prefix}/include,g' $(1)/usr/lib/pkgconfig/lxc.pc
+ $(SED) 's,/usr/lib,$$$${prefix}/lib,g' $(1)/usr/lib/pkgconfig/lxc.pc
+endef
+
+
+define Package/lxc/install
+ true
+endef
+
+define Package/lxc-auto/install
+ $(INSTALL_DIR) $(1)/etc/config $(1)/etc/init.d
+ $(INSTALL_CONF) ./files/lxc-auto.config $(1)/etc/config/lxc-auto
+ $(INSTALL_BIN) ./files/lxc-auto.init $(1)/etc/init.d/lxc-auto
+endef
+
+define Package/lxc-common/conffiles
+/etc/lxc/default.conf
+/etc/lxc/lxc.conf
+endef
+
+define Package/lxc-common/install
+ $(INSTALL_DIR) $(1)/usr/lib/lxc/rootfs
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/lib/lxc/rootfs/README \
+ $(1)/usr/lib/lxc/rootfs/
+
+ $(INSTALL_DIR) $(1)/usr/share/lxc
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/share/lxc/lxc.functions \
+ $(1)/usr/share/lxc/
+
+ $(INSTALL_DIR) $(1)/etc/lxc/
+ $(CP) \
+ $(PKG_INSTALL_DIR)/etc/lxc/default.conf \
+ $(1)/etc/lxc/default.conf
+
+ $(INSTALL_DIR) $(1)/etc/lxc/
+ $(CP) \
+ ./files/lxc.conf \
+ $(1)/etc/lxc/lxc.conf
+
+ $(INSTALL_DIR) $(1)/srv/lxc/
+endef
+
+define Package/lxc-hooks/install
+ $(INSTALL_DIR) $(1)/usr/share/lxc/hooks
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/share/lxc/hooks/* \
+ $(1)/usr/share/lxc/hooks/
+endef
+
+define Package/lxc-templates/install
+ $(INSTALL_DIR) $(1)/usr/share/lxc/templates/
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/share/lxc/templates/lxc-* \
+ $(1)/usr/share/lxc/templates/
+endef
+
+define Package/lxc-configs/install
+ $(INSTALL_DIR) $(1)/usr/share/lxc/config/
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/share/lxc/config/* \
+ $(1)/usr/share/lxc/config/
+endef
+
+define Package/liblxc/install
+ $(INSTALL_DIR) $(1)/usr/lib/
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/lib/liblxc.so* \
+ $(1)/usr/lib/
+endef
+
+define Package/lxc-init/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/sbin/init.lxc \
+ $(1)/sbin/
+endef
+
+define GenPlugin
+ define Package/lxc-$(1)
+ $(call Package/lxc/Default)
+ TITLE:=Utility lxc-$(1) from the LXC userspace tools
+ DEPENDS+= +lxc-common $(2) $(DEPENDS_$(1))
+ endef
+
+ define Package/lxc-$(1)/install
+ $(INSTALL_DIR) $$(1)$(3)
+ $(INSTALL_BIN) \
+ $(PKG_INSTALL_DIR)$(3)/lxc-$(1) \
+ $$(1)$(3)/
+ endef
+
+ $$(eval $$(call BuildPackage,lxc-$(1)))
+endef
+
+
+$(eval $(call BuildPackage,lxc))
+$(eval $(call BuildPackage,lxc-common))
+$(eval $(call BuildPackage,lxc-hooks))
+$(eval $(call BuildPackage,lxc-configs))
+$(eval $(call BuildPackage,lxc-templates))
+$(eval $(call BuildPackage,liblxc))
+$(eval $(call BuildPackage,lxc-init))
+$(eval $(call BuildPackage,lxc-auto))
+$(eval $(call BuildPackage,lxc-unprivileged))
+$(foreach u,$(LXC_APPLETS_BIN),$(eval $(call GenPlugin,$(u),$(DEPENDS_APPLETS),"/usr/bin")))
+$(foreach u,$(LXC_APPLETS_LIB),$(eval $(call GenPlugin,$(u),$(DEPENDS_APPLETS),"/usr/lib/lxc")))
+$(foreach u,$(LXC_SCRIPTS),$(eval $(call GenPlugin,$(u),,"/usr/bin")))
diff --git a/external/subpack/utils/lxc/files/lxc-auto.config b/external/subpack/utils/lxc/files/lxc-auto.config
new file mode 100644
index 0000000..b5a7ec9
--- /dev/null
+++ b/external/subpack/utils/lxc/files/lxc-auto.config
@@ -0,0 +1,5 @@
+#config container
+ #option name container1
+ #option timeout 300
+ #list command '/bin/command --option'
+
diff --git a/external/subpack/utils/lxc/files/lxc-auto.init b/external/subpack/utils/lxc/files/lxc-auto.init
new file mode 100755
index 0000000..1c36483
--- /dev/null
+++ b/external/subpack/utils/lxc/files/lxc-auto.init
@@ -0,0 +1,73 @@
+#!/bin/sh /etc/rc.common
+
+. /lib/functions.sh
+
+START=99
+STOP=00
+
+run_command() {
+ local command="$1"
+ $command
+}
+
+start_container() {
+ local cfg="$1"
+ local name
+
+ config_get name "$cfg" name
+ config_list_foreach "$cfg" command run_command
+ if [ -n "$name" ]; then
+ /usr/bin/lxc-start -n "$name"
+ fi
+}
+
+max_timeout=0
+
+stop_container() {
+ local cfg="$1"
+ local name timeout
+
+ config_get name "$cfg" name
+ config_get timeout "$cfg" timeout 300
+
+ if [ "$max_timeout" -lt "$timeout" ]; then
+ max_timeout=$timeout
+ fi
+
+ if [ -n "$name" ]; then
+ if [ "$timeout" = "0" ]; then
+ /usr/bin/lxc-stop -n "$name" &
+ else
+ /usr/bin/lxc-stop -n "$name" -t $timeout &
+ fi
+ fi
+}
+
+start() {
+ config_load lxc-auto
+ config_foreach start_container container
+}
+
+stop() {
+ config_load lxc-auto
+ config_foreach stop_container container
+ # ensure e.g. shutdown doesn't occur before maximum timeout on
+ # containers that are shutting down
+ if [ $max_timeout -gt 0 ]; then
+ sleep $max_timeout
+ fi
+}
+
+#Export systemd cgroups
+boot() {
+ if [ ! -d /sys/fs/cgroup/systemd ]; then
+ mkdir -p /sys/fs/cgroup/systemd
+ mount -t cgroup -o rw,nosuid,nodev,noexec,relatime,none,name=systemd cgroup /sys/fs/cgroup/systemd
+ fi
+
+ if [ ! -d /run ]; then
+ ln -s /var/run /run
+ fi
+
+ start
+}
diff --git a/external/subpack/utils/lxc/files/lxc-unprivileged.defaults b/external/subpack/utils/lxc/files/lxc-unprivileged.defaults
new file mode 100644
index 0000000..45c9839
--- /dev/null
+++ b/external/subpack/utils/lxc/files/lxc-unprivileged.defaults
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+chmod u+s /usr/bin/newuidmap && \
+chmod u+s /usr/bin/newgidmap
diff --git a/external/subpack/utils/lxc/files/lxc.conf b/external/subpack/utils/lxc/files/lxc.conf
new file mode 100644
index 0000000..77841cc
--- /dev/null
+++ b/external/subpack/utils/lxc/files/lxc.conf
@@ -0,0 +1 @@
+lxc.lxcpath = /srv/lxc
diff --git a/external/subpack/utils/lxc/patches/010-Remove-distro-check.patch b/external/subpack/utils/lxc/patches/010-Remove-distro-check.patch
new file mode 100644
index 0000000..44610f0
--- /dev/null
+++ b/external/subpack/utils/lxc/patches/010-Remove-distro-check.patch
@@ -0,0 +1,47 @@
+From 9f550ca53801b2b9c6c1c7a4d02ad525c704b145 Mon Sep 17 00:00:00 2001
+From: Robert Marko <robert.marko@sartura.hr>
+Date: Thu, 14 May 2020 13:40:53 +0200
+Subject: [PATCH] Remove distro check
+
+Signed-off-by: Robert Marko <robert.marko@sartura.hr>
+---
+ configure.ac | 28 ----------------------------
+ 1 file changed, 28 deletions(-)
+
+--- a/configure.ac
++++ b/configure.ac
+@@ -78,34 +78,6 @@ esac
+ LT_INIT
+ AC_SUBST([LIBTOOL_DEPS])
+
+-# Detect the distribution. This is used for the default configuration and
+-# for some distro-specific build options.
+-AC_MSG_CHECKING([host distribution])
+-AC_ARG_WITH(distro, AS_HELP_STRING([--with-distro=DISTRO], [Specify the Linux distribution to target: One of redhat, redhatenterpriseserver, oracle, centos, fedora, suse, gentoo, debian, arch, slackware, plamo, paldo, openmandriva, pardus, sparclinux, altlinux.]))
+-if type lsb_release >/dev/null 2>&1 && test "z$with_distro" = "z"; then
+- with_distro=`lsb_release -is`
+-fi
+-if test "z$with_distro" = "z"; then
+- AC_CHECK_FILE(/etc/redhat-release,with_distro="redhat")
+- AC_CHECK_FILE(/etc/oracle-release,with_distro="oracle")
+- AC_CHECK_FILE(/etc/sparclinux-release,with_distro="sparclinux")
+- AC_CHECK_FILE(/etc/centos-release,with_distro="centos")
+- AC_CHECK_FILE(/etc/fedora-release,with_distro="fedora")
+- AC_CHECK_FILE(/etc/SuSE-release,with_distro="suse")
+- AC_CHECK_FILE(/etc/gentoo-release,with_distro="gentoo")
+- AC_CHECK_FILE(/etc/debian_version,with_distro="debian")
+- AC_CHECK_FILE(/etc/arch-release,with_distro="arch")
+- AC_CHECK_FILE(/etc/slackware-version,with_distro="slackware")
+- AC_CHECK_FILE(/etc/plamo-version,with_distro="plamo")
+- AC_CHECK_FILE(/etc/frugalware-release,with_distro="frugalware")
+- AC_CHECK_FILE(/etc/mandrakelinux-release, with_distro="openmandriva")
+- AC_CHECK_FILE(/etc/mandriva-release,with_distro="openmandriva")
+- AC_CHECK_FILE(/etc/pardus-release,with_distro="pardus")
+- AC_CHECK_FILE(/etc/altlinux-release,with_distro="altlinux")
+- AC_CHECK_FILE(/etc/pld-release,with_distro="pld")
+-fi
+-with_distro=`echo ${with_distro} | tr '[[:upper:]]' '[[:lower:]]'`
+-
+ if test "z$with_distro" = "zforsparc"; then
+ with_distro="sparclinux"
+ fi
diff --git a/external/subpack/utils/lxc/patches/020-lxc-checkconfig.patch b/external/subpack/utils/lxc/patches/020-lxc-checkconfig.patch
new file mode 100644
index 0000000..682cf9a
--- /dev/null
+++ b/external/subpack/utils/lxc/patches/020-lxc-checkconfig.patch
@@ -0,0 +1,20 @@
+--- a/src/lxc/cmd/lxc-checkconfig.in
++++ b/src/lxc/cmd/lxc-checkconfig.in
+@@ -4,6 +4,17 @@
+ # Allow environment variables to override config
+ : ${CONFIG:=/proc/config.gz}
+ : ${MODNAME:=configs}
++: ${ZGREP:=zgrep}
++: ${GUNZIP:=gunzip}
++
++if [ -z $(command -v $ZGREP) ] && ! [ -z $(command -v $GUNZIP) ] && [ -x $(command -v $GUNZIP) ] && [ -f $CONFIG ] && [ "$CONFIG" == "/proc/config.gz" ] ; then
++
++ CONFIG_NEW="/tmp/config-$(uname -r)"
++ $GUNZIP -c $CONFIG > $CONFIG_NEW
++ CONFIG=$CONFIG_NEW
++
++ GREP=grep
++fi
+
+ CAT="cat"
+
diff --git a/external/subpack/utils/lxc/patches/021-remove-legacy-cgroup-support.patch b/external/subpack/utils/lxc/patches/021-remove-legacy-cgroup-support.patch
new file mode 100644
index 0000000..081b45f
--- /dev/null
+++ b/external/subpack/utils/lxc/patches/021-remove-legacy-cgroup-support.patch
@@ -0,0 +1,38 @@
+--- a/config/templates/common.conf.in
++++ b/config/templates/common.conf.in
+@@ -15,35 +15,6 @@ lxc.cap.drop = mac_admin mac_override sy
+ # Ensure hostname is changed on clone
+ lxc.hook.clone = @LXCHOOKDIR@/clonehostname
+
+-# Default legacy cgroup configuration
+-#
+-# CGroup allowlist
+-lxc.cgroup.devices.deny = a
+-## Allow any mknod (but not reading/writing the node)
+-lxc.cgroup.devices.allow = c *:* m
+-lxc.cgroup.devices.allow = b *:* m
+-## Allow specific devices
+-### /dev/null
+-lxc.cgroup.devices.allow = c 1:3 rwm
+-### /dev/zero
+-lxc.cgroup.devices.allow = c 1:5 rwm
+-### /dev/full
+-lxc.cgroup.devices.allow = c 1:7 rwm
+-### /dev/tty
+-lxc.cgroup.devices.allow = c 5:0 rwm
+-### /dev/console
+-lxc.cgroup.devices.allow = c 5:1 rwm
+-### /dev/ptmx
+-lxc.cgroup.devices.allow = c 5:2 rwm
+-### /dev/random
+-lxc.cgroup.devices.allow = c 1:8 rwm
+-### /dev/urandom
+-lxc.cgroup.devices.allow = c 1:9 rwm
+-### /dev/pts/*
+-lxc.cgroup.devices.allow = c 136:* rwm
+-### fuse
+-lxc.cgroup.devices.allow = c 10:229 rwm
+-
+ # Default unified cgroup configuration
+ #
+ # CGroup allowlist
diff --git a/external/subpack/utils/lxc/patches/025-remove-unsupported-option.patch b/external/subpack/utils/lxc/patches/025-remove-unsupported-option.patch
new file mode 100644
index 0000000..747e78d
--- /dev/null
+++ b/external/subpack/utils/lxc/patches/025-remove-unsupported-option.patch
@@ -0,0 +1,24 @@
+--- a/templates/lxc-download.in
++++ b/templates/lxc-download.in
+@@ -512,20 +512,7 @@ fi
+ # Unpack the rootfs
+ echo "Unpacking the rootfs"
+
+-EXCLUDES=""
+-excludelist=$(relevant_file excludes)
+-if [ -f "${excludelist}" ]; then
+- while read -r line; do
+- EXCLUDES="${EXCLUDES} --exclude=${line}"
+- done < "${excludelist}"
+-fi
+-
+-# Do not surround ${EXCLUDES} by quotes. This does not work. The solution could
+-# use array but this is not POSIX compliant. The only POSIX compliant solution
+-# is to use a function wrapper, but the latter can't be used here as the args
+-# are dynamic. We thus need to ignore the warning brought by shellcheck.
+-# shellcheck disable=SC2086
+-tar --anchored ${EXCLUDES} --numeric-owner -xpJf "${LXC_CACHE_PATH}/rootfs.tar.xz" -C "${LXC_ROOTFS}"
++tar --numeric-owner -xpJf "${LXC_CACHE_PATH}/rootfs.tar.xz" -C "${LXC_ROOTFS}"
+
+ mkdir -p "${LXC_ROOTFS}/dev/pts/"
+
diff --git a/external/subpack/utils/macchanger/Makefile b/external/subpack/utils/macchanger/Makefile
new file mode 100644
index 0000000..c2ca58f
--- /dev/null
+++ b/external/subpack/utils/macchanger/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=macchanger
+PKG_VERSION:=1.7.0
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/alobbs/macchanger/releases/download/$(PKG_VERSION)/
+PKG_HASH:=dae2717c270fd5f62d790dbf80c19793c651b1b26b62c101b82d5fdf25a845bf
+
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=Nicolas Thill <nico@openwrt.org>
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/macchanger
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=utility for viewing/manipulating the MAC address
+ URL:=https://github.com/alobbs/macchanger/
+endef
+
+define Package/macchanger/description
+ This is a GNU/Linux utility for viewing/manipulating the MAC address
+ of network interfaces.
+endef
+
+define Package/macchanger/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/macchanger $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/share
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/macchanger $(1)/usr/share/
+endef
+
+$(eval $(call BuildPackage,macchanger))
diff --git a/external/subpack/utils/macchanger/patches/0001-fix-build-with-musl.patch b/external/subpack/utils/macchanger/patches/0001-fix-build-with-musl.patch
new file mode 100644
index 0000000..23fa560
--- /dev/null
+++ b/external/subpack/utils/macchanger/patches/0001-fix-build-with-musl.patch
@@ -0,0 +1,11 @@
+--- a/src/netinfo.c
++++ b/src/netinfo.c
+@@ -113,7 +113,7 @@ mc_net_info_get_permanent_mac (const net
+ epa->size = IFHWADDRLEN;
+
+ memcpy(&req, &(net->dev), sizeof(struct ifreq));
+- req.ifr_data = (caddr_t)epa;
++ req.ifr_data = (char *)epa;
+
+ if (ioctl(net->sock, SIOCETHTOOL, &req) < 0) {
+ perror ("[ERROR] Could not read permanent MAC");
diff --git a/external/subpack/utils/mariadb/Makefile b/external/subpack/utils/mariadb/Makefile
new file mode 100644
index 0000000..d201b3b
--- /dev/null
+++ b/external/subpack/utils/mariadb/Makefile
@@ -0,0 +1,573 @@
+#
+# Copyright (C) 2018 Sebastian Kemper <sebastian_ml@gmx.net>
+# Copyright (C) 2021-2022 Michal Hrusecky <michal@hrusecky.net>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mariadb
+PKG_VERSION:=10.4.26
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL := https://archive.mariadb.org/$(PKG_NAME)-$(PKG_VERSION)/source
+
+PKG_HASH:=715ac7e23afc3b8a559c6cc998cdb1973d90f621b2bdd7603e2c6e53860b2ddf
+PKG_MAINTAINER:=Michal Hrusecky <Michal@Hrusecky.net>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING THIRDPARTY
+
+PKG_CPE_ID:=cpe:/a:mariadb:mariadb
+
+HOST_BUILD_PARALLEL:=1
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+HOST_BUILD_DEPENDS:=libxml2/host
+# Without libevent2 tests/async_queries sporadically fails on the bots
+PKG_BUILD_DEPENDS:=libevent2 mariadb/host
+
+CONF_DIR:=/etc/mysql
+PLUGIN_DIR:=/usr/lib/mariadb/plugin
+SHARE_DIR:=/usr/share/mariadb
+
+MARIADB_SOCKET=/var/run/mysql/mysql.sock
+
+MARIADB_DISABLE_ENGINES := \
+ cassandra \
+ example \
+ mroonga \
+ oqgraph \
+ rocksdb \
+ test_sql_discovery \
+ tokudb
+
+MARIADB_DISABLE_PLUGINS := \
+ audit_null \
+ auth_examples \
+ aws_key_management \
+ cracklib_password_check \
+ daemon_example \
+ debug_key_management \
+ example_key_management \
+ fulltext \
+ versioning
+
+MARIADB_SERVER_PLUGINS := \
+ auth_ed25519 \
+ auth_gssapi \
+ auth_pam \
+ auth_pam_v1 \
+ disks \
+ feedback \
+ file_key_management \
+ ha_archive \
+ ha_blackhole \
+ ha_connect \
+ ha_federated \
+ ha_federatedx \
+ ha_sphinx \
+ ha_spider \
+ handlersocket \
+ locales \
+ metadata_lock_info \
+ query_cache_info \
+ query_response_time \
+ server_audit \
+ simple_password_check \
+ sql_errlog \
+ wsrep_info
+
+PKG_CONFIG_DEPENDS := \
+ $(patsubst %,CONFIG_PACKAGE_$(PKG_NAME)-server-plugin-%,$(subst _,-,$(MARIADB_SERVER_PLUGINS))) \
+ CONFIG_PACKAGE_mariadb-server
+
+plugin-auth_ed25519 := PLUGIN_AUTH_ED25519
+plugin-auth_gssapi := PLUGIN_AUTH_GSSAPI
+plugin-auth_pam := PLUGIN_AUTH_PAM
+plugin-auth_pam_v1 := PLUGIN_AUTH_PAM_V1
+plugin-disks := PLUGIN_DISKS
+plugin-feedback := PLUGIN_FEEDBACK
+plugin-file_key_management := PLUGIN_FILE_KEY_MANAGEMENT
+plugin-ha_archive := PLUGIN_ARCHIVE
+plugin-ha_blackhole := PLUGIN_BLACKHOLE
+plugin-ha_connect := PLUGIN_CONNECT
+plugin-ha_federated := PLUGIN_FEDERATED
+plugin-ha_federatedx := PLUGIN_FEDERATEDX
+plugin-ha_sphinx := PLUGIN_SPHINX
+plugin-ha_spider := PLUGIN_SPIDER
+plugin-handlersocket := PLUGIN_HANDLERSOCKET
+plugin-locales := PLUGIN_LOCALES
+plugin-metadata_lock_info := PLUGIN_METADATA_LOCK_INFO
+plugin-query_cache_info := PLUGIN_QUERY_CACHE_INFO
+plugin-query_response_time := PLUGIN_QUERY_RESPONSE_TIME
+plugin-server_audit := PLUGIN_SERVER_AUDIT
+plugin-simple_password_check := PLUGIN_SIMPLE_PASSWORD_CHECK
+plugin-sql_errlog := PLUGIN_SQL_ERRLOG
+plugin-wsrep_info := PLUGIN_WSREP_INFO
+
+MARIADB_CLIENT := \
+ mysql \
+ mysqlcheck
+
+MARIADB_CLIENT_EXTRA := \
+ msql2mysql \
+ mysql_find_rows \
+ mysql_plugin \
+ mysql_waitpid \
+ mysqlaccess \
+ mysqlbinlog \
+ mysqldump \
+ mysqlimport \
+ mysqlshow \
+ mysqlslap \
+ mytop
+
+MARIADB_SERVER := \
+ innochecksum \
+ my_print_defaults \
+ mysql_install_db \
+ mysql_upgrade \
+ mysqladmin \
+ mysqld
+
+MARIADB_SERVER_EXTRA := \
+ aria_chk \
+ aria_dump_log \
+ aria_ftdump \
+ aria_pack \
+ aria_read_log \
+ mariabackup \
+ myisam_ftdump \
+ myisamchk \
+ myisamlog \
+ myisampack \
+ mysql_convert_table_format \
+ mysql_fix_extensions \
+ mysql_secure_installation \
+ mysql_setpermission \
+ mysql_tzinfo_to_sql \
+ mysqld_multi \
+ mysqld_safe \
+ mysqld_safe_helper \
+ mysqldumpslow \
+ mysqlhotcopy \
+ perror \
+ replace \
+ resolve_stack_dump \
+ wsrep_sst_mariabackup \
+ wsrep_sst_mysqldump \
+ wsrep_sst_rsync \
+ wsrep_sst_rsync_wan
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/host-build.mk
+include $(INCLUDE_DIR)/cmake.mk
+include $(INCLUDE_DIR)/nls.mk
+
+MARIADB_COMMON_DEPENDS := \
+ $(ICONV_DEPENDS) \
+ +libatomic \
+ +libopenssl \
+ +libstdcpp \
+ +zlib
+
+# Pass CPPFLAGS in the CFLAGS as otherwise the build system will
+# ignore them.
+TARGET_CFLAGS+=$(TARGET_CPPFLAGS)
+
+define Package/mariadb/disable/engine
+ echo > $(1)/storage/$(2)/CMakeLists.txt
+endef
+
+define Package/mariadb/disable/plugin
+ echo > $(1)/plugin/$(2)/CMakeLists.txt
+endef
+
+define Package/mariadb/install/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/$(2) $(1)/usr/bin
+ [ $(2) = $(subst mysql,mariadb,$(2)) ] || ln -s $(2) $(1)/usr/bin/$(subst mysql,mariadb,$(2))
+ [ $(2) = $(subst mariadb,mysql,$(2)) ] || ln -s $(2) $(1)/usr/bin/$(subst mariadb,mysql,$(2))
+endef
+
+define Package/mariadb/install/plugin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)$(PLUGIN_DIR)/$(2).so $(1)$(PLUGIN_DIR)
+endef
+
+define Package/mariadb/description/Default
+MariaDB is a very fast and robust SQL database server.
+endef
+
+define Package/mariadb/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ URL:=https://mariadb.org/
+ SUBMENU:=Database
+endef
+
+define Package/mariadb-client
+ $(call Package/mariadb/Default)
+ TITLE:=MariaDB database client
+ MENU:=1
+ DEPENDS:=$(MARIADB_COMMON_DEPENDS) \
+ +libedit
+endef
+
+define Package/mariadb-client/description
+$(call Package/mariadb/description/Default)
+
+This package includes the following core client binaries:
+
+$(subst $(space),$(newline),$(MARIADB_CLIENT))
+
+endef
+
+define Package/mariadb-client-extra
+ $(call Package/mariadb/Default)
+ TITLE:=MariaDB database client extra
+ DEPENDS:=mariadb-client
+endef
+
+define Package/mariadb-client-extra/description
+$(call Package/mariadb/description/Default)
+
+This package includes the following extra client binaries:
+
+$(subst $(space),$(newline),$(MARIADB_CLIENT_EXTRA))
+
+endef
+
+define Package/mariadb-server
+ $(call Package/mariadb/Default)
+ DEPENDS:=mariadb-server-base
+ TITLE:=MariaDB database server
+ MENU:=1
+ PROVIDES:=mysql-server
+endef
+
+define Package/mariadb-server/description
+$(call Package/mariadb/description/Default)
+
+This package includes the following core server binaries:
+
+$(subst $(space),$(newline),$(MARIADB_SERVER))
+
+endef
+
+define Package/mariadb-server-base
+ $(call Package/mariadb/Default)
+ DEPENDS:= \
+ $(MARIADB_COMMON_DEPENDS) \
+ +libaio \
+ +liblzma \
+ +libpcre \
+ +resolveip \
+ +sudo
+ TITLE:=MariaDB database server base
+ USERID:=mariadb=376:mariadb=376
+endef
+
+define Package/mariadb-server-base/conffiles
+$(CONF_DIR)/my.cnf
+$(CONF_DIR)/conf.d/50-server.cnf
+$(CONF_DIR)/conf.d/60-galera.cnf
+/etc/config/mysqld
+endef
+
+define Package/mariadb-server-base/description
+$(call Package/mariadb/description/Default)
+
+This package provides the foundation for mariadb-server. It installs the
+init script, support files (configuration etc.), the user "mariadb" and
+the dependencies.
+
+endef
+
+define Package/mariadb-server-extra
+ $(call Package/mariadb/Default)
+ TITLE:=MariaDB database server extra
+ DEPENDS:=mariadb-server
+endef
+
+define Package/mariadb-server-extra/description
+$(call Package/mariadb/description/Default)
+
+This package includes the following extra server binaries:
+
+$(subst $(space),$(newline),$(MARIADB_SERVER_EXTRA))
+
+endef
+
+# We won't need unit tests
+CMAKE_OPTIONS += -DWITH_UNIT_TESTS=0
+
+# This value is determined automatically during straight compile by compiling
+# and running a test code. You cannot do that during cross-compile. However the
+# stack grows downward in most if not all modern systems. The only exception
+# according to buildroot is PA-RISC which is not supported by OpenWrt as far as
+# I know. Therefore it makes sense to hardcode the value. If an arch is added
+# the stack of which grows up one should expect unpredictable behavior at run
+# time.
+CMAKE_OPTIONS += -DSTACK_DIRECTION=-1
+
+# Make it explicit that we are cross-compiling
+CMAKE_OPTIONS += -DCMAKE_CROSSCOMPILING=1
+
+# Explicitly disable dtrace to avoid detection of a host version
+CMAKE_OPTIONS += -DENABLE_DTRACE=0
+
+# Prevent MariaDB from messing with OpenWrt's C(XX)FLAGS
+CMAKE_OPTIONS += -DSECURITY_HARDENED=OFF
+
+ifeq ($(CONFIG_PACKAGE_mariadb-server),)
+CMAKE_OPTIONS += -DWITHOUT_SERVER=ON
+else
+# Enable the auth_socket plugin and let unix user root access MariaDB without a
+# separate password.
+CMAKE_OPTIONS += -DWITHOUT_SERVER=OFF -DPLUGIN_AUTH_SOCKET=STATIC
+endif
+
+CMAKE_OPTIONS += \
+ -DCONNECT_WITH_JDBC=NO \
+ -DCONNECT_WITH_LIBXML2=system \
+ -DCONNECT_WITH_MONGO=NO \
+ -DCONNECT_WITH_ODBC=NO \
+ -DDISABLE_SHARED=NO \
+ -DDEFAULT_CHARSET=utf8mb4 \
+ -DDEFAULT_COLLATION=utf8mb4_general_ci \
+ -DENABLED_PROFILING=OFF \
+ -DENABLE_STATIC_LIBS=OFF \
+ -DINSTALL_DOCDIR=share/doc/mariadb \
+ -DINSTALL_DOCREADMEDIR=share/doc/mariadb \
+ -DINSTALL_INFODIR=share/info \
+ -DINSTALL_MANDIR=share/man \
+ -DINSTALL_MYSQLSHAREDIR=share/mariadb \
+ -DINSTALL_MYSQLTESTDIR="" \
+ -DINSTALL_PAMDATADIR="/etc/security" \
+ -DINSTALL_PAMDIR="/lib/security" \
+ -DINSTALL_PLUGINDIR=lib/mariadb/plugin \
+ -DINSTALL_PREFIX="/usr" \
+ -DINSTALL_SBINDIR=bin \
+ -DINSTALL_SCRIPTDIR=bin \
+ -DINSTALL_SQLBENCHDIR="" \
+ -DINSTALL_SUPPORTFILESDIR=share/mariadb \
+ -DINSTALL_UNIX_ADDRDIR=$(MARIADB_SOCKET) \
+ -DMYSQL_DATADIR=/srv/mysql \
+ -DMYSQL_UNIX_ADDR=$(MARIADB_SOCKET) \
+ -DSKIP_TESTS=ON \
+ -DWITH_DEBUG=OFF \
+ -DWITH_EMBEDDED_SERVER=OFF \
+ -DWITH_INNODB_BZIP2=OFF \
+ -DWITH_INNODB_LZ4=OFF \
+ -DWITH_INNODB_LZMA=ON \
+ -DWITH_INNODB_LZO=OFF \
+ -DWITH_INNODB_SNAPPY=OFF \
+ -DWITH_JEMALLOC=OFF \
+ -DWITH_LIBARCHIVE=OFF \
+ -DWITH_LIBWRAP=OFF \
+ -DWITH_MARIABACKUP=ON \
+ -DWITH_NUMA=OFF \
+ -DWITH_PCRE=system \
+ -DWITH_SAFEMALLOC=OFF \
+ -DWITH_SSL=system \
+ -DWITH_SYSTEMD=no \
+ -DWITH_VALGRIND=OFF \
+ -DWITH_ZLIB=system
+
+# Help MariaDB find the correct libiconv.
+# nls.mk sets it up so that with CONFIG_BUILD_NLS libiconv-full would be used,
+# otherwise libiconv-stub (independent of the selected libc). MariaDB needs a
+# leg up to find/pick the right lib.
+CMAKE_OPTIONS += \
+ -DICONV_INCLUDE_DIR=$(ICONV_PREFIX)/include \
+ -DICONV_LIBRARIES=$(ICONV_PREFIX)/lib/libiconv.$(if $(CONFIG_BUILD_NLS),so,a)
+
+CMAKE_OPTIONS += \
+ $(foreach p,$(MARIADB_SERVER_PLUGINS),-D$(plugin-$(p))=$(if $(CONFIG_PACKAGE_$(PKG_NAME)-server-plugin-$(subst _,-,$(p))),DYNAMIC,NO))
+
+# Disable some client library plugins
+CMAKE_OPTIONS += \
+ -DCLIENT_PLUGIN_AUTH_GSSAPI_CLIENT=OFF \
+ -DCLIENT_PLUGIN_REMOTE_IO=OFF
+
+# Set CMAKE_FIND_ROOT_PATH_MODE_INCLUDE and CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
+# to BOTH as otherwise the host build will not find some required dependencies
+# installed on the host machine, like ncurses.
+#
+# Add "$(STAGING_DIR_HOSTPKG)/lib" to the RPATH of the host helpers,
+# otherwise they might not find the location of a library at run time.
+CMAKE_HOST_OPTIONS += \
+ -DCMAKE_BUILD_WITH_INSTALL_RPATH=TRUE \
+ -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH \
+ -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH \
+ -DCMAKE_INSTALL_RPATH="$(STAGING_DIR_HOSTPKG)/lib" \
+ -DCMAKE_SKIP_RPATH=FALSE \
+ -DWITHOUT_SERVER=OFF
+
+# Some helpers must be compiled for host in order to crosscompile MariaDB for
+# the target. They are then included by import_executables.cmake which is
+# generated during the build of the host helpers. It is not necessary to build
+# the whole host package, only the "import_executables" target.
+# -DIMPORT_EXECUTABLES=$(HOST_BUILD_DIR)/import_executables.cmake
+# must then be passed to cmake during target build.
+# See also https://mariadb.com/kb/en/mariadb/cross-compiling-mariadb/
+
+CMAKE_OPTIONS += -DIMPORT_EXECUTABLES=$(STAGING_DIR_HOSTPKG)/share/mariadb/import_executables.cmake
+
+# Disable some engines/plugins here as well - decreases the number of cmake checks.
+define Host/Prepare
+ $(call Host/Prepare/Default)
+ $(foreach e,$(MARIADB_DISABLE_ENGINES),$(call Package/mariadb/disable/engine,$(HOST_BUILD_DIR),$(e));)
+ $(foreach p,$(MARIADB_DISABLE_PLUGINS),$(call Package/mariadb/disable/plugin,$(HOST_BUILD_DIR),$(p));)
+endef
+
+define Host/Compile
+ $(call Host/Compile/Default,import_executables)
+endef
+
+define Host/Install
+ $(SED) 's|$(HOST_BUILD_DIR)|$(STAGING_DIR_HOSTPKG)/share/mariadb|' $(HOST_BUILD_DIR)/import_executables.cmake
+ $(INSTALL_DIR) $(1)/share/mariadb/{dbug,extra,scripts,sql}
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/dbug/factorial $(1)/share/mariadb/dbug
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/extra/comp_err $(1)/share/mariadb/extra
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/scripts/comp_sql $(1)/share/mariadb/scripts
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/sql/{gen_lex_hash,gen_lex_token} $(1)/share/mariadb/sql
+ $(INSTALL_DATA) $(HOST_BUILD_DIR)/import_executables.cmake $(1)/share/mariadb
+endef
+
+# LIBICONV_PLUG is used in GNU's libiconv for redefinition of exports [e.g.
+# from libiconv_open() to iconv_open()]. But in OpenWrt this variable is not set
+# when building libiconv-full. So when MariaDB sets LIBICONV_PLUG it expects
+# iconv_open() to be available for example, which is not the case - only
+# libiconv_open() is. To address this prevent the variable from being set.
+# libiconv-stub does not use this variable, so there is no harm in always doing
+# this.
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(SED) '/ADD_DEFINITIONS(-DLIBICONV_PLUG)/d' $(PKG_BUILD_DIR)/libmariadb/libmariadb/CMakeLists.txt
+ $(foreach e,$(MARIADB_DISABLE_ENGINES),$(call Package/mariadb/disable/engine,$(PKG_BUILD_DIR),$(e));)
+ $(foreach p,$(MARIADB_DISABLE_PLUGINS),$(call Package/mariadb/disable/plugin,$(PKG_BUILD_DIR),$(p));)
+endef
+
+define Package/mariadb-client/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(foreach b,$(MARIADB_CLIENT),$(call Package/mariadb/install/bin,$(1),$(b));)
+ # Install convenience links for mysqlcheck multi-call binary
+ cd $(1)/usr/bin; $(LN) mysqlcheck mysqlanalyze
+ cd $(1)/usr/bin; $(LN) mysqlcheck mysqlrepair
+ cd $(1)/usr/bin; $(LN) mysqlcheck mysqloptimize
+endef
+
+define Package/mariadb-client-extra/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(foreach b,$(MARIADB_CLIENT_EXTRA),$(call Package/mariadb/install/bin,$(1),$(b));)
+endef
+
+define Package/mariadb-server/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(foreach b,$(MARIADB_SERVER),$(call Package/mariadb/install/bin,$(1),$(b));)
+endef
+
+define Package/mariadb-server-base/install
+ $(INSTALL_DIR) $(1)$(CONF_DIR)/conf.d
+ $(INSTALL_DIR) $(1)$(SHARE_DIR)/charsets
+ $(INSTALL_DIR) $(1)$(SHARE_DIR)/english
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) files/mysqld.init $(1)/etc/init.d/mysqld
+ $(SED) '/^[a-z]/s/^/#/' $(PKG_INSTALL_DIR)$(SHARE_DIR)/wsrep.cnf
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)$(SHARE_DIR)/wsrep.cnf $(1)$(CONF_DIR)/conf.d/60-galera.cnf
+ $(INSTALL_DATA) conf/50-server.cnf $(1)$(CONF_DIR)/conf.d
+ $(INSTALL_DATA) conf/my.cnf $(1)$(CONF_DIR)
+ $(INSTALL_CONF) files/mysqld.config $(1)/etc/config/mysqld
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)$(SHARE_DIR)/charsets/* $(1)$(SHARE_DIR)/charsets
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)$(SHARE_DIR)/english/errmsg.sys $(1)$(SHARE_DIR)/english
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)$(SHARE_DIR)/*.sql $(1)$(SHARE_DIR)
+endef
+
+define Package/mariadb-server-extra/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/bin/wsrep_sst_common $(1)/usr/bin
+ $(SED) 's,/bin/bash,/bin/sh,g' $(PKG_INSTALL_DIR)/usr/bin/wsrep_sst_*
+ $(foreach b,$(MARIADB_SERVER_EXTRA),$(call Package/mariadb/install/bin,$(1),$(b));)
+ cd $(1)/usr/bin; $(LN) mariabackup mariadb-backup
+endef
+
+define BuildPlugin
+ define Package/mariadb-server-plugin-$(subst _,-,$(1))
+ $(call Package/mariadb/Default)
+ TITLE:=mariadb-server plugin
+ DEPENDS:=mariadb-server $(patsubst +%,+PACKAGE_mariadb-server-plugin-$(subst _,-,$(1)):%,$(2))
+ifeq ($(1),auth_pam)
+ # Directory "auth_pam_tool_dir" is installed with mode 0750 and is only
+ # accessible by root and the group mariadb. This way mariadb can access
+ # the SUID binary "auth_pam_tool" contained within while others cannot.
+ FILE_MODES:=/usr/lib/mariadb/plugin/auth_pam_tool_dir:root:mariadb:0750
+endif
+ endef
+ define Package/mariadb-server-plugin-$(subst _,-,$(1))/description
+ $(call Package/mariadb/description/Default)
+
+This package provides the $(1) plugin.
+
+ endef
+ define Package/mariadb-server-plugin-$(subst _,-,$(1))/install
+ $(INSTALL_DIR) $$(1)$(PLUGIN_DIR)
+ $(call Package/mariadb/install/plugin,$$(1),$(1))
+ifeq ($(1),auth_pam)
+ $(INSTALL_DIR) $$(1)$(PLUGIN_DIR)/auth_pam_tool_dir
+ $(INSTALL_SUID) \
+ $(PKG_INSTALL_DIR)$(PLUGIN_DIR)/auth_pam_tool_dir/auth_pam_tool \
+ $$(1)$(PLUGIN_DIR)/auth_pam_tool_dir
+ $(INSTALL_DIR) $$(1)/etc/security
+ $(INSTALL_DATA) \
+ $(PKG_INSTALL_DIR)/etc/security/user_map.conf \
+ $$(1)/etc/security
+ $(INSTALL_DIR) $$(1)/lib/security
+ $(INSTALL_DATA) \
+ $(PKG_INSTALL_DIR)/lib/security/pam_user_map.so \
+ $$(1)/lib/security
+endif
+ifeq ($(1),ha_spider)
+ $(INSTALL_DIR) $$(1)$(SHARE_DIR)
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)$(SHARE_DIR)/install_spider.sql \
+ $$(1)$(SHARE_DIR)
+endif
+ endef
+ $$(eval $$(call BuildPackage,mariadb-server-plugin-$(subst _,-,$(1))))
+endef
+
+$(eval $(call HostBuild))
+$(eval $(call BuildPackage,mariadb-client))
+$(eval $(call BuildPackage,mariadb-client-extra))
+$(eval $(call BuildPackage,mariadb-server))
+$(eval $(call BuildPackage,mariadb-server-base))
+$(eval $(call BuildPackage,mariadb-server-extra))
+
+$(eval $(call BuildPlugin,auth_ed25519,))
+$(eval $(call BuildPlugin,auth_gssapi,+krb5-libs))
+$(eval $(call BuildPlugin,auth_pam,+libpam))
+$(eval $(call BuildPlugin,auth_pam_v1,+libpam))
+$(eval $(call BuildPlugin,disks,))
+$(eval $(call BuildPlugin,feedback,))
+$(eval $(call BuildPlugin,file_key_management,))
+$(eval $(call BuildPlugin,ha_archive,))
+$(eval $(call BuildPlugin,ha_blackhole,))
+$(eval $(call BuildPlugin,ha_connect,+libxml2))
+$(eval $(call BuildPlugin,ha_federated,))
+$(eval $(call BuildPlugin,ha_federatedx,))
+$(eval $(call BuildPlugin,ha_sphinx,))
+$(eval $(call BuildPlugin,ha_spider,))
+$(eval $(call BuildPlugin,handlersocket,))
+$(eval $(call BuildPlugin,locales,))
+$(eval $(call BuildPlugin,metadata_lock_info,))
+$(eval $(call BuildPlugin,query_cache_info,))
+$(eval $(call BuildPlugin,query_response_time,))
+$(eval $(call BuildPlugin,server_audit,))
+$(eval $(call BuildPlugin,simple_password_check,))
+$(eval $(call BuildPlugin,sql_errlog,))
+$(eval $(call BuildPlugin,wsrep_info,))
diff --git a/external/subpack/utils/mariadb/conf/50-server.cnf b/external/subpack/utils/mariadb/conf/50-server.cnf
new file mode 100644
index 0000000..ab8057f
--- /dev/null
+++ b/external/subpack/utils/mariadb/conf/50-server.cnf
@@ -0,0 +1,123 @@
+#
+# These groups are read by MariaDB server.
+# Use it for options that only the server (but not clients) should see
+#
+# See the examples of server my.cnf files in /usr/share/mysql/
+#
+
+# this is read by the standalone daemon and embedded servers
+[server]
+
+# this is only for the mysqld standalone daemon
+[mysqld]
+
+#
+# * Basic Settings
+#
+port = 3306
+# Don't put this on flash memory
+# datadir = /srv/mysql
+# tmpdir should also not go on flash memory, but needs to exist and have correct rights
+# tmpdir = /tmp
+
+skip-external-locking
+
+# Instead of skip-networking the default is now to listen only on
+# localhost which is more compatible and is not less secure.
+bind-address = 127.0.0.1
+
+#
+# * Fine Tuning
+#
+key_buffer_size = 16M
+max_allowed_packet = 16M
+thread_stack = 192K
+thread_cache_size = 8
+# This replaces the startup script and checks MyISAM tables if needed
+# the first time they are touched
+myisam_recover_options = BACKUP
+#max_connections = 100
+#table_cache = 64
+#thread_concurrency = 10
+
+#
+# * Query Cache Configuration
+#
+query_cache_limit = 1M
+query_cache_min_res_unit = 1k
+query_cache_size = 16M
+
+#
+# * Logging and Replication
+#
+# Be aware that this log type is a performance killer.
+# As of 5.1 you can enable the log at runtime!
+#general_log_file = /var/log/mysql/mysql.log
+#general_log = 1
+#
+# Error log - should be very few entries.
+# Note that if unset the errors will go to stdout and can be seen in syslog
+# (check "logread")
+#
+#log_error = /var/log/mysql/error.log
+#
+# Enable the slow query log to see queries with especially long duration
+#slow_query_log_file = /var/log/mysql/mariadb-slow.log
+#long_query_time = 10
+#log_slow_rate_limit = 1000
+#log_slow_verbosity = query_plan
+#
+#log-queries-not-using-indexes
+#
+# The following can be used as easy to replay backup logs or for replication.
+#server-id = 1
+#log_bin = /var/log/mysql/mysql-bin.log
+expire_logs_days = 10
+max_binlog_size = 100M
+#binlog_do_db = include_database_name
+#binlog_ignore_db = exclude_database_name
+
+#
+# * InnoDB
+#
+# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
+# Read the manual for more InnoDB related options. There are many!
+innodb_file_per_table=1
+innodb_buffer_pool_size=64M
+innodb_flush_log_at_trx_commit=2
+innodb_log_buffer_size=32M
+innodb_max_dirty_pages_pct=90
+# You can set .._buffer_pool_size up to 50 - 80 %
+# of RAM but beware of setting memory usage too high
+#innodb_buffer_pool_size = 16M
+# Set .._log_file_size to 25 % of buffer pool size
+#innodb_log_file_size = 5M
+#innodb_log_buffer_size = 8M
+#innodb_flush_log_at_trx_commit = 1
+#innodb_lock_wait_timeout = 50
+
+#
+# * Security Features
+#
+# Read the manual, too, if you want chroot!
+# chroot = /var/lib/mysql/
+#
+# For generating SSL certificates you can use for example the GUI tool "tinyca".
+#
+# ssl-ca=/etc/mysql/cacert.pem
+# ssl-cert=/etc/mysql/server-cert.pem
+# ssl-key=/etc/mysql/server-key.pem
+#
+# Accept only connections using the latest and most secure TLS protocol version.
+# ..when MariaDB is compiled with OpenSSL:
+# ssl-cipher=TLSv1.2
+
+#
+# * Unix socket authentication plugin is built-in
+#
+# Needed so the root database user can authenticate without a password but
+# only when running as the unix root user.
+#
+# Also available for other users if required.
+# See https://mariadb.com/kb/en/unix_socket-authentication-plugin/
+
diff --git a/external/subpack/utils/mariadb/conf/my.cnf b/external/subpack/utils/mariadb/conf/my.cnf
new file mode 100644
index 0000000..7583c7c
--- /dev/null
+++ b/external/subpack/utils/mariadb/conf/my.cnf
@@ -0,0 +1,22 @@
+# The MariaDB configuration file
+#
+# The MariaDB/MySQL tools read configuration files in the following order:
+# 1. "/etc/mysql/my.cnf" (this file) to set global defaults,
+# 2. "/etc/mysql/conf.d/*.cnf" to set global options.
+# 3. "~/.my.cnf" to set user-specific options.
+#
+# If the same option is defined multiple times, the last one will apply.
+#
+# One can use all long options that the program supports.
+# Run program with --help to get a list of available options and with
+# --print-defaults to see which it would actually understand and use.
+
+#
+# This group is read both both by the client and the server
+# use it for options that affect everything
+#
+[client-server]
+
+# Import all .cnf files from configuration directory
+!includedir /etc/mysql/conf.d/
+
diff --git a/external/subpack/utils/mariadb/files/mysqld.config b/external/subpack/utils/mariadb/files/mysqld.config
new file mode 100644
index 0000000..e33adef
--- /dev/null
+++ b/external/subpack/utils/mariadb/files/mysqld.config
@@ -0,0 +1,13 @@
+
+config mysqld 'general'
+ # Unless enable, MariaDB will not start without this
+ option enabled '0'
+ # User to run MariaDB as
+ option user 'mariadb'
+ # Group to run MariaDB
+ option group 'mariadb'
+ # If there is now database, create an empty one automatically
+ option init '1'
+ # If upgrading old database, run mysql_upgrade during restart
+ option upgrade '1'
+
diff --git a/external/subpack/utils/mariadb/files/mysqld.init b/external/subpack/utils/mariadb/files/mysqld.init
new file mode 100644
index 0000000..52def2d
--- /dev/null
+++ b/external/subpack/utils/mariadb/files/mysqld.init
@@ -0,0 +1,203 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2010-2018 OpenWrt.org
+
+# shellcheck disable=SC2034
+START=95
+# shellcheck disable=SC2034
+STOP=10
+# shellcheck disable=SC2034
+USE_PROCD=1
+
+NAME=mysqld
+
+LOGGER="/usr/bin/logger -p user.err -s -t $NAME --"
+[ -x "$LOGGER" ] || LOGGER="echo"
+
+MYSQLD="/usr/bin/$NAME"
+
+pidfile=""
+
+# mysqladmin likes to read /root/.my.cnf which could cause issues.
+export HOME="/etc/mysql"
+
+# Safeguard (relative paths, core dumps...)
+cd /
+
+mysqld_get_param() {
+ "$MYSQLD" --help --verbose | sed -n 's|^'"$1"'[[:blank:]]\+||p'
+}
+
+# Send kill signal to MariaDB process
+#
+# Usage: boolean mysqld_kill signal
+mysql_kill() {
+ [ -n "$pidfile" ] || pidfile="$(mysqld_get_param pid-file)"
+ [ -f "$pidfile" ] || return 1
+ pid="$(cat "$pidfile")"
+ [ -n "$pid" ] || return 2
+ kill "$1" "$pid"
+}
+
+# Checks if a server is running and accessible.
+#
+# Supported modes are 'check_alive' and 'check_dead'.
+# Both check for pidfile and whether the specified process is running and is
+# indeed mysqld. We could use mysqladmin for the check, but to be able to do
+# so, mysqladmin requires access to the database, which sounds like overkill
+# and potential security issue.
+#
+# Usage: boolean mysqld_status [check_alive|check_dead]
+mysqld_status() {
+ ps_alive=0
+ pidfile="$(mysqld_get_param pid-file)"
+ if [ -f "$pidfile" ] && mysql_kill -0 2> /dev/null && \
+ [ "$(readlink "/proc/$(cat "$pidfile")/exe")" = "$MYSQLD" ]; then
+ ps_alive=1
+ fi
+
+ if { [ "$1" = check_alive ] && [ $ps_alive = 1 ]; } || \
+ { [ "$1" = check_dead ] && [ $ps_alive = 0 ]; }
+ then
+ return 0 # EXIT_SUCCESS
+ else
+ return 1 # EXIT_FAILURE
+ fi
+}
+
+start_service() {
+ conf=/etc/mysql/my.cnf
+ logdir=/var/log/mysql
+ version="$(mysqld --version | sed -n 's|.*Ver[[:blank:]]*\([0-9.]*\)-.*|\1|p')"
+
+ # Few basic checks
+ if [ ! -x "$MYSQLD" ]; then
+ $LOGGER "$MYSQLD is missing"
+ exit 1
+ fi
+
+ if [ -z "$version" ]; then
+ $LOGGER "Can't get MariaDB version, something is seriously wrong"
+ exit 1
+ fi
+
+ if [ ! -r "$conf" ]; then
+ $LOGGER "$conf cannot be read"
+ exit 1
+ fi
+
+ if mysqld_status check_alive; then
+ $LOGGER "server is already running"
+ exit 0
+ fi
+
+ # Get various config options
+ config_load "$NAME"
+ config_get my_user general user "mariadb"
+ config_get my_group general group "mariadb"
+ config_get_bool enabled general enabled 0
+ config_get_bool init_db general init 1
+ config_get_bool autoupgrade general upgrade 1
+ config_get options general options
+
+ # shellcheck disable=SC2154
+ if [ "$enabled" -eq 0 ]; then
+ $LOGGER "service not enabled in /etc/config/$NAME"
+ exit 1
+ fi
+
+ datadir="$(mysqld_get_param datadir)"
+ tmpdir="$(mysqld_get_param tmpdir)"
+ sockdir="$(dirname "$(mysqld_get_param socket)")"
+
+ # Make sure we have a working database in datadir
+ if [ ! -f "$datadir/mysql/tables_priv.MAD" ]; then
+ args="--force"
+ basedir="$(mysqld_get_param basedir)"
+ [ -n "$basedir" ] && args="$args --basedir=$basedir"
+
+ # shellcheck disable=SC2154
+ if [ "$init_db" -gt 0 ]; then
+ # shellcheck disable=SC2154
+ mysql_install_db $args --skip-name-resolve --skip-test-db --datadir="$datadir" || exit 1
+ echo "$version" > "$datadir"/.version
+ chown -Rh "$my_user:$my_group" "$datadir"
+ else
+ $LOGGER "Cannot detect privileges table. You might need to run"
+ $LOGGER "'mysql_install_db \"$args\"'"
+ $LOGGER "to initialize the system tables."
+ $LOGGER "Then hand it ower to MariaDB user"
+ # shellcheck disable=SC2154
+ $LOGGER "'chown -Rh \"$my_user:$my_group\" \"$datadir\"'"
+ exit 1
+ fi
+ fi
+
+ # Make sure all required directories exists and have correct rights
+ for i in "$logdir" "$sockdir"; do
+ opts="-m 0750"
+ if ! [ -e "$i" ]; then
+ # $sockdir needs to be accessible for clients
+ [ "$i" = "$sockdir" ] && opts="-m 0755"
+ # shellcheck disable=SC2086
+ mkdir -p $opts "$i"
+ fi
+ # shellcheck disable=SC2154
+ [ -d "$i" ] && chown -Rh "$my_user:$my_group" "$i"
+ done
+
+ # Migration from old versions
+ # shellcheck disable=SC2154
+ if [ "$(cat "$datadir"/.version 2> /dev/null)" \!= "$version" ] && [ "$autoupgrade" -gt 0 ]; then
+ # Check for correct owner
+ local owner="$(stat --format %U:%G "$datadir" 2> /dev/null)"
+ if [ -n "$owner" ] && [ "$owner" != "$my_user:$my_group" ]; then
+ chown -Rh "$my_user:$my_group" "$datadir"
+ fi
+
+ # Start upgrade instance without credentials
+ sudo -u "$my_user" mysqld --skip-networking --skip-grant-tables --socket=/tmp/mysql_upgrade.sock &
+ PID="$!"
+ i=0
+ # Wait for upgrade instance of db to start
+ while [ "$i" -lt 15 ] && test \! -S /tmp/mysql_upgrade.sock; do
+ sleep 1
+ i="$((i + 1))"
+ done
+ [ -S /tmp/mysql_upgrade.sock ] || {
+ $LOGGER "Failed to start upgrading instance of MariaDB."
+ exit 1
+ }
+ # Upgrade the database
+ mysql_upgrade --upgrade-system-tables --socket=/tmp/mysql_upgrade.sock
+ echo "$version" > "$datadir"/.version
+ # Stop the upgrade instance
+ kill "$PID"
+ i=0
+ while [ "$i" -lt 60 ] && grep -q mysql "/proc/$PID/cmdline"; do
+ sleep 1
+ [ "$i" -lt 30 ] || kill "$PID"
+ i="$((i + 1))"
+ done
+ # Use force
+ if grep -q mysql "/proc/$PID/cmdline"; then
+ kill -9 "$PID"
+ fi
+ fi
+
+ # Start daemon
+ procd_open_instance
+
+ # shellcheck disable=SC2154 disable=SC2086
+ procd_set_param command "$MYSQLD" $options
+ procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}"
+ # run as user
+ procd_set_param user "$my_user"
+ # forward stderr to logd
+ procd_set_param stderr 1
+ # use HUP to reload
+ procd_set_param reload_signal HUP
+ # terminate using signals
+ procd_set_param term_timeout 60
+
+ procd_close_instance
+}
diff --git a/external/subpack/utils/mariadb/patches/100-fix_hostname.patch b/external/subpack/utils/mariadb/patches/100-fix_hostname.patch
new file mode 100644
index 0000000..408651d
--- /dev/null
+++ b/external/subpack/utils/mariadb/patches/100-fix_hostname.patch
@@ -0,0 +1,11 @@
+--- a/scripts/mysql_install_db.sh
++++ b/scripts/mysql_install_db.sh
+@@ -424,7 +424,7 @@ fi
+
+
+ # Try to determine the hostname
+-hostname=`@HOSTNAME@`
++hostname=`cat /proc/sys/kernel/hostname`
+
+ # Check if hostname is valid
+ if test "$cross_bootstrap" -eq 0 -a "$in_rpm" -eq 0 -a "$force" -eq 0
diff --git a/external/subpack/utils/mariadb/patches/110-pcre.cmake.patch b/external/subpack/utils/mariadb/patches/110-pcre.cmake.patch
new file mode 100644
index 0000000..2d370a3
--- /dev/null
+++ b/external/subpack/utils/mariadb/patches/110-pcre.cmake.patch
@@ -0,0 +1,36 @@
+From: =?utf-8?q?Ond=C5=99ej_Sur=C3=BD?= <ondrej@debian.org>
+Date: Wed, 22 Nov 2017 06:05:45 +0000
+Subject: Revert to using system pcre library
+
+---
+ cmake/pcre.cmake | 16 ++--------------
+ 1 file changed, 2 insertions(+), 14 deletions(-)
+
+--- a/cmake/pcre.cmake
++++ b/cmake/pcre.cmake
+@@ -1,23 +1,11 @@
+-INCLUDE (CheckCSourceRuns)
+-
+ SET(WITH_PCRE "auto" CACHE STRING
+ "Which pcre to use (possible values are 'bundled', 'system', or 'auto')")
+
+ MACRO (CHECK_PCRE)
+ IF(WITH_PCRE STREQUAL "system" OR WITH_PCRE STREQUAL "auto")
+- CHECK_LIBRARY_EXISTS(pcre pcre_stack_guard "" HAVE_PCRE_STACK_GUARD)
+- IF(NOT CMAKE_CROSSCOMPILING)
+- SET(CMAKE_REQUIRED_LIBRARIES "pcre")
+- CHECK_C_SOURCE_RUNS("
+- #include <pcre.h>
+- int main() {
+- return -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0) < 256;
+- }" PCRE_STACK_SIZE_OK)
+- SET(CMAKE_REQUIRED_LIBRARIES)
+- ENDIF()
++ CHECK_LIBRARY_EXISTS(pcre pcre_stack_guard "" HAVE_PCRE)
+ ENDIF()
+- IF(NOT HAVE_PCRE_STACK_GUARD OR NOT PCRE_STACK_SIZE_OK OR
+- WITH_PCRE STREQUAL "bundled")
++ IF(NOT HAVE_PCRE OR WITH_PCRE STREQUAL "bundled")
+ IF (WITH_PCRE STREQUAL "system")
+ MESSAGE(FATAL_ERROR "system pcre is not found or unusable")
+ ENDIF()
diff --git a/external/subpack/utils/mariadb/patches/160-mips-machine.patch b/external/subpack/utils/mariadb/patches/160-mips-machine.patch
new file mode 100644
index 0000000..06d6dd5
--- /dev/null
+++ b/external/subpack/utils/mariadb/patches/160-mips-machine.patch
@@ -0,0 +1,21 @@
+From: Debian MySQL Maintainers <pkg-mysql-maint@lists.alioth.debian.org>
+Date: Thu, 10 Aug 2017 20:40:29 +0200
+Subject: mips-machine
+
+---
+ cmake/package_name.cmake | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/cmake/package_name.cmake
++++ b/cmake/package_name.cmake
+@@ -34,6 +34,10 @@ IF(NOT VERSION)
+ SET(DEFAULT_MACHINE "mips")
+ ENDIF()
+
++ IF(NOT 64BIT AND CMAKE_SYSTEM_PROCESSOR MATCHES "^mips64")
++ SET(DEFAULT_MACHINE "mips")
++ ENDIF()
++
+ IF(CMAKE_SYSTEM_NAME MATCHES "Windows")
+ SET(NEED_DASH_BETWEEN_PLATFORM_AND_MACHINE 0)
+ SET(DEFAULT_PLATFORM "win")
diff --git a/external/subpack/utils/mariadb/patches/170-ppc-remove-glibc-dep.patch b/external/subpack/utils/mariadb/patches/170-ppc-remove-glibc-dep.patch
new file mode 100644
index 0000000..46431d3
--- /dev/null
+++ b/external/subpack/utils/mariadb/patches/170-ppc-remove-glibc-dep.patch
@@ -0,0 +1,45 @@
+--- a/include/my_cpu.h
++++ b/include/my_cpu.h
+@@ -24,17 +24,16 @@
+ */
+
+ #ifdef _ARCH_PWR8
+-#include <sys/platform/ppc.h>
+ /* Very low priority */
+-#define HMT_very_low() __ppc_set_ppr_very_low()
++#define HMT_very_low() asm volatile("or 31,31,31")
+ /* Low priority */
+-#define HMT_low() __ppc_set_ppr_low()
++#define HMT_low() asm volatile ("or 1,1,1")
+ /* Medium low priority */
+-#define HMT_medium_low() __ppc_set_ppr_med_low()
++#define HMT_medium_low() asm volatile ("or 6,6,6")
+ /* Medium priority */
+-#define HMT_medium() __ppc_set_ppr_med()
++#define HMT_medium() asm volatile ("or 2,2,2")
+ /* Medium high priority */
+-#define HMT_medium_high() __ppc_set_ppr_med_high()
++#define HMT_medium_high() asm volatile("or 5,5,5")
+ /* High priority */
+ #define HMT_high() asm volatile("or 3,3,3")
+ #else
+@@ -80,7 +79,7 @@ static inline void MY_RELAX_CPU(void)
+ __asm__ __volatile__ ("pause");
+ #endif
+ #elif defined(_ARCH_PWR8)
+- __ppc_get_timebase();
++ __builtin_ppc_get_timebase();
+ #elif defined __GNUC__ && (defined __arm__ || defined __aarch64__)
+ /* Mainly, prevent the compiler from optimizing away delay loops */
+ __asm__ __volatile__ ("":::"memory");
+--- a/storage/tokudb/PerconaFT/portability/toku_time.h
++++ b/storage/tokudb/PerconaFT/portability/toku_time.h
+@@ -124,7 +124,7 @@ static inline tokutime_t toku_time_now(v
+ __asm __volatile__ ("mrs %[rt], cntvct_el0" : [rt] "=r" (result));
+ return result;
+ #elif defined(__powerpc__)
+- return __ppc_get_timebase();
++ return __builtin_ppc_get_timebase();
+ #else
+ #error No timer implementation for this platform
+ #endif
diff --git a/external/subpack/utils/mariadb/patches/180-relax-mysql_install-db-wrt-pam-tool.patch b/external/subpack/utils/mariadb/patches/180-relax-mysql_install-db-wrt-pam-tool.patch
new file mode 100644
index 0000000..fe9adbd
--- /dev/null
+++ b/external/subpack/utils/mariadb/patches/180-relax-mysql_install-db-wrt-pam-tool.patch
@@ -0,0 +1,39 @@
+--- a/scripts/mysql_install_db.sh
++++ b/scripts/mysql_install_db.sh
+@@ -364,6 +364,14 @@ then
+ exit 1
+ fi
+ plugindir=`find_in_dirs --dir auth_pam.so $basedir/lib*/plugin $basedir/lib*/mysql/plugin $basedir/lib/*/mariadb19/plugin`
++ # Upstream assumes all plugins will be always installed, but in OpenWrt we can
++ # install a server without plugins if we want to.
++ if test -z "$plugindir"
++ then
++ echo "Could not find plugin directory." >&2
++ echo "Will continue with \"/usr/lib/mariadb/plugin\"." >&2
++ plugindir=/usr/lib/mariadb/plugin
++ fi
+ pamtooldir=$plugindir
+ # relative from where the script was run for a relocatable install
+ elif test -n "$dirname0" -a -x "$rel_mysqld" -a ! "$rel_mysqld" -ef "@sbindir@/mysqld"
+@@ -488,7 +496,9 @@ do
+ fi
+ done
+
+-if test -n "$user"
++# There should be no need for this on OpenWrt. If this turns out to be a wrong guess then
++# we can revisit.
++if test -n ""
+ then
+ if test -z "$srcdir" -a "$in_rpm" -eq 0
+ then
+@@ -509,6 +519,10 @@ then
+ echo
+ fi
+ fi
++fi
++
++if test -n "$user"
++then
+ args="$args --user=$user"
+ fi
+
diff --git a/external/subpack/utils/mariadb/patches/190-replace-hostname-in-mysqld_safe.patch b/external/subpack/utils/mariadb/patches/190-replace-hostname-in-mysqld_safe.patch
new file mode 100644
index 0000000..3532a79
--- /dev/null
+++ b/external/subpack/utils/mariadb/patches/190-replace-hostname-in-mysqld_safe.patch
@@ -0,0 +1,29 @@
+--- a/scripts/mysqld_safe.sh
++++ b/scripts/mysqld_safe.sh
+@@ -247,7 +247,7 @@ wsrep_recover_position() {
+ return 1
+ fi
+
+- local wr_pidfile="$DATADIR/"`@HOSTNAME@`"-recover.pid"
++ local wr_pidfile="$DATADIR/"$(uci get 'system.@system[0].hostname')"-recover.pid"
+
+ local wr_options="--disable-log-error --pid-file='$wr_pidfile'"
+
+@@ -668,7 +668,7 @@ then
+ * ) err_log="$DATADIR/$err_log" ;;
+ esac
+ else
+- err_log=$DATADIR/`@HOSTNAME@`.err
++ err_log=$DATADIR/$(uci get 'system.@system[0].hostname').err
+ fi
+ fi
+
+@@ -754,7 +754,7 @@ fi
+
+ if test -z "$pid_file"
+ then
+- pid_file="`@HOSTNAME@`.pid"
++ pid_file="$(uci get 'system.@system[0].hostname').pid"
+ fi
+ # MariaDB wants pid file without datadir
+ append_arg_to_args "--pid-file=$pid_file"
diff --git a/external/subpack/utils/mariadb/patches/200-no-selinux.patch b/external/subpack/utils/mariadb/patches/200-no-selinux.patch
new file mode 100644
index 0000000..e984000
--- /dev/null
+++ b/external/subpack/utils/mariadb/patches/200-no-selinux.patch
@@ -0,0 +1,11 @@
+--- a/support-files/CMakeLists.txt
++++ b/support-files/CMakeLists.txt
+@@ -62,7 +62,7 @@ IF(UNIX)
+ INSTALL(FILES magic DESTINATION ${inst_location} COMPONENT SupportFiles)
+ INSTALL(DIRECTORY policy DESTINATION ${inst_location} COMPONENT SupportFiles)
+ FIND_PROGRAM(CHECKMODULE checkmodule)
+- FIND_PROGRAM(SEMODULE_PACKAGE semodule_package)
++# FIND_PROGRAM(SEMODULE_PACKAGE semodule_package)
+ MARK_AS_ADVANCED(CHECKMODULE SEMODULE_PACKAGE)
+
+ # Build pp files in policy/selinux
diff --git a/external/subpack/utils/mariadb/test.sh b/external/subpack/utils/mariadb/test.sh
new file mode 100755
index 0000000..cb33bba
--- /dev/null
+++ b/external/subpack/utils/mariadb/test.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# shellcheck disable=SC1090
+. "$CI_HELPER"
+
+check_version() {
+ bin="$1"
+ ver="$2"
+ com="$3"
+
+ if [ -x "$bin" ]; then
+ if "$bin" --version | grep " $ver-MariaDB"; then
+ success "MariaDB $com is in version $2"
+ else
+ err_die "MariaDB $com seems to be in wrong version"
+ fi
+ else
+ err_die "Can't find $com server binary"
+ fi
+}
+
+case "$PKG_NAME" in
+ mariadb-server) check_version /usr/bin/mysqld "$PKG_VERSION" "server" ;;
+ mariadb-client) check_version /usr/bin/mysql "$PKG_VERSION" "client";;
+ *) info "Skipping $PKG_NAME" ;;
+esac
diff --git a/external/subpack/utils/mbtools/Makefile b/external/subpack/utils/mbtools/Makefile
new file mode 100644
index 0000000..f88b794
--- /dev/null
+++ b/external/subpack/utils/mbtools/Makefile
@@ -0,0 +1,58 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mbtools
+PKG_SOURCE_DATE:=2014-10-29
+PKG_SOURCE_VERSION:=149e9c69cec180f18cf8781cf5285b97352bf719
+PKG_RELEASE:=2
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/webstack/mbtools
+PKG_MIRROR_HASH:=3f6a452d59a62b4f582020ebf1e371f0f0c94d99b1b056af3c4e124426a7a772
+
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/mbtools
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Modbus tools
+ DEPENDS:=+glib2 +libmodbus $(INTL_DEPENDS)
+endef
+
+define Package/mbtools/description
+ Modbus tools based on libmodbus to log data fetched by a master/client or
+ received by a slave/server (writing of registers). mbcollect is able to act
+ as client or server (in TCP or RTU)
+endef
+
+ifneq ($(INTL_FULL),)
+TARGET_LDFLAGS += \
+ -L$(INTL_PREFIX)/lib \
+ -Wl,-rpath-link=$(STAGING_DIR)/usr/lib
+
+endif
+
+define Package/mbtools/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mbrecorder $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mbcollect $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/src/mbcollect.ini $(1)/etc
+endef
+
+$(eval $(call BuildPackage,mbtools))
diff --git a/external/subpack/utils/mbtools/patches/010-glib.patch b/external/subpack/utils/mbtools/patches/010-glib.patch
new file mode 100644
index 0000000..0da203c
--- /dev/null
+++ b/external/subpack/utils/mbtools/patches/010-glib.patch
@@ -0,0 +1,11 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -21,7 +21,7 @@ AC_CHECK_HEADERS([stdio.h stdlib.h strin
+
+ MBTOOLS_REQUIRES="glib-2.0 >= 2.10.0 libmodbus >= 3.1.0"
+ PKG_CHECK_MODULES(MBTOOLS_DEPS, [$MBTOOLS_REQUIRES])
+-MBTOOLS_CFLAGS="-Wall -Werror $MBTOOLS_DEPS_CFLAGS"
++MBTOOLS_CFLAGS="-Wall $MBTOOLS_DEPS_CFLAGS"
+ MBTOOLS_LIBS="$MBTOOLS_DEPS_LIBS"
+ AC_SUBST(MBTOOLS_CFLAGS)
+ AC_SUBST(MBTOOLS_LIBS)
diff --git a/external/subpack/utils/mbtools/patches/100-fix-unit-test-server-return-value.patch b/external/subpack/utils/mbtools/patches/100-fix-unit-test-server-return-value.patch
new file mode 100644
index 0000000..eb89881
--- /dev/null
+++ b/external/subpack/utils/mbtools/patches/100-fix-unit-test-server-return-value.patch
@@ -0,0 +1,8 @@
+--- a/tests/unit-test-server.c
++++ b/tests/unit-test-server.c
+@@ -117,4 +117,5 @@ int main(int argc, char *argv[])
+ }
+ printf("Quit the loop: %s\n", modbus_strerror(errno));
+ signal_handler(0);
++ return 0;
+ }
diff --git a/external/subpack/utils/mc/Config.in b/external/subpack/utils/mc/Config.in
new file mode 100644
index 0000000..fcd8fad
--- /dev/null
+++ b/external/subpack/utils/mc/Config.in
@@ -0,0 +1,59 @@
+menu "Configuration"
+ depends on PACKAGE_mc
+
+config MC_DIFFVIEWER
+ bool "Enable internal diff viewer"
+ default n
+ help
+ This option enables the built-in diff viewer.
+ Disabled by default.
+
+config MC_EDITOR
+ bool "Enable internal editor"
+ default y
+ help
+ This option enables the built-in file editor.
+ Enabled by default.
+
+config MC_SUBSHELL
+ bool "Enable concurrent subshell"
+ default y
+ help
+ This option enables concurrent subshell support.
+ Enabled by default.
+
+config MC_LARGEFILE
+ bool "Enable largefile support"
+ default n
+ help
+ This option enables support for large files (> 2 GB).
+ Disabled by default.
+
+config MC_BACKGROUND
+ bool "Enable background operations"
+ default n
+ help
+ This option enables support for background operations which
+ allow to perform some tasks such as copying files in a
+ separate background process. Background code is known
+ to be less stable than the rest of the code.
+ Disabled by default.
+
+config MC_CHARSET
+ bool "Enable charset support"
+ default y
+ help
+ This option adds support for selecting character set of the text in
+ the internal viewer and editor and converting it on the fly.
+ Enabled by default.
+
+config MC_VFS
+ bool "Enable virtual filesystem support"
+ default y
+ help
+ This option enables the Virtual File System switch code to get
+ transparent access to the following file systems:
+ cpio, tar, fish, sfs, ftp, sftp, extfs.
+ Enabled by default.
+
+endmenu
diff --git a/external/subpack/utils/mc/Makefile b/external/subpack/utils/mc/Makefile
new file mode 100644
index 0000000..5df1078
--- /dev/null
+++ b/external/subpack/utils/mc/Makefile
@@ -0,0 +1,129 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mc
+PKG_VERSION:=4.8.27
+PKG_RELEASE:=2
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_CPE_ID:=cpe:/a:midnight_commander:midnight_commander
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=http://ftp.midnight-commander.org/
+PKG_HASH:=31be59225ffa9920816e9a8b3be0ab225a16d19e4faf46890f25bdffa02a4ff4
+PKG_BUILD_PARALLEL:=1
+PKG_FIXUP:=autoreconf gettext-version
+PKG_BUILD_DEPENDS:=MC_VFS:libtirpc
+
+PKG_CONFIG_DEPENDS := \
+ CONFIG_PACKAGE_MC \
+ CONFIG_MC_DIFFVIEWER \
+ CONFIG_MC_EDITOR \
+ CONFIG_MC_SUBSHELL \
+ CONFIG_MC_LARGEFILE \
+ CONFIG_MC_BACKGROUND \
+ CONFIG_MC_CHARSET \
+ CONFIG_MC_VFS
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/mc
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+glib2 +libncurses +libmount +MC_VFS:libssh2 $(ICONV_DEPENDS)
+ TITLE:=Midnight Commander - a powerful visual file manager
+ URL:=https://www.midnight-commander.org/
+ MENU:=1
+endef
+
+define Package/mc/config
+ source "$(SOURCE)/Config.in"
+endef
+
+define Package/mc/description
+GNU Midnight Commander is a visual file manager.
+It's a feature rich full-screen text mode application that allows you to copy,
+move and delete files and whole directory trees, search for files and run commands in the subshell.
+Internal viewer and editor are included as well.
+
+endef
+
+CONFIGURE_ARGS += \
+ --enable-silent-rules \
+ --disable-tests \
+ --disable-doxygen-doc \
+ --with-homedir=/etc/mc \
+ --with-screen=ncurses \
+ --without-x \
+
+CONFIGURE_VARS += \
+ ac_cv_search_addwstr=no \
+
+ifeq ($(CONFIG_MC_DIFFVIEWER),)
+CONFIGURE_ARGS += --without-diff-viewer
+endif
+
+ifeq ($(CONFIG_MC_EDITOR),)
+CONFIGURE_ARGS += --without-internal-edit
+endif
+
+ifeq ($(CONFIG_MC_SUBSHELL),)
+CONFIGURE_ARGS += --without-subshell
+endif
+
+ifeq ($(CONFIG_MC_LARGEFILE),)
+CONFIGURE_ARGS += --disable-largefile
+endif
+
+ifeq ($(CONFIG_MC_BACKGROUND),)
+CONFIGURE_ARGS += --disable-background
+endif
+
+ifeq ($(CONFIG_MC_CHARSET),)
+CONFIGURE_ARGS += --disable-charset
+endif
+
+ifeq ($(CONFIG_MC_VFS),)
+CONFIGURE_ARGS += --disable-vfs
+else
+TARGET_CPPFLAGS += -I$(STAGING_DIR)/usr/include/tirpc
+endif
+
+define Package/mc/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/mc $(1)/usr/bin
+ $(INSTALL_DIR) $(1)/etc/mc
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.charsets $(1)/etc/mc
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.ext $(1)/etc/mc
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.default.keymap $(1)/etc/mc/mc.keymap
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/filehighlight.ini $(1)/etc/mc
+ $(INSTALL_DIR) $(1)/usr/share/mc/help
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/doc/hlp/mc.hlp $(1)/usr/share/mc/help
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/mc.menu $(1)/etc/mc
+ $(INSTALL_DIR) $(1)/etc/mc/skins
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/misc/skins/default.ini $(1)/etc/mc/skins
+ $(INSTALL_DIR) $(1)/usr/share/mc/syntax
+ touch $(1)/usr/share/mc/syntax/Syntax
+ifeq ($(CONFIG_MC_DIFFVIEWER),y)
+ ln -sf mc $(1)/usr/bin/mcdiff
+endif
+ifeq ($(CONFIG_MC_EDITOR),y)
+ ln -sf mc $(1)/usr/bin/mcedit
+endif
+ifeq ($(CONFIG_MC_VFS),y)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/src/vfs/sfs/sfs.ini $(1)/etc/mc
+ $(INSTALL_DIR) $(1)/usr/lib/mc/extfs.d
+endif
+endef
+
+define Package/mc/conffiles
+/etc/mc/mc.menu
+/etc/mc/skins/default.ini
+endef
+
+$(eval $(call BuildPackage,mc))
diff --git a/external/subpack/utils/mc/patches/010-subshell.patch b/external/subpack/utils/mc/patches/010-subshell.patch
new file mode 100644
index 0000000..bc7ddee
--- /dev/null
+++ b/external/subpack/utils/mc/patches/010-subshell.patch
@@ -0,0 +1,11 @@
+--- a/src/subshell/common.c
++++ b/src/subshell/common.c
+@@ -1140,7 +1140,7 @@ init_subshell_precmd (char *precmd, size
+ "else "
+ "[ \"${PWD##$HOME/}\" = \"$PWD\" ] && MC_PWD=\"$PWD\" || MC_PWD=\"~/${PWD##$HOME/}\"; "
+ "fi; "
+- "echo \"$USER@$(hostname -s):$MC_PWD\"; "
++ "echo \"$USER@$HOSTNAME:$MC_PWD\"; "
+ "pwd>&%d; "
+ "kill -STOP $$; "
+ "}; " "PRECMD=precmd; " "PS1='$($PRECMD)$ '\n", subshell_pipe[WRITE]);
diff --git a/external/subpack/utils/mc/patches/020-fix-mouse-handling-newer-terminfo.patch b/external/subpack/utils/mc/patches/020-fix-mouse-handling-newer-terminfo.patch
new file mode 100644
index 0000000..bf6853a
--- /dev/null
+++ b/external/subpack/utils/mc/patches/020-fix-mouse-handling-newer-terminfo.patch
@@ -0,0 +1,11 @@
+--- a/lib/tty/tty.c
++++ b/lib/tty/tty.c
+@@ -402,7 +402,7 @@ tty_init_xterm_support (gboolean is_xter
+ if (xmouse_seq != NULL)
+ {
+ if (strcmp (xmouse_seq, ESC_STR "[<") == 0)
+- xmouse_seq = ESC_STR "[M";
++ xmouse_seq = NULL;
+
+ xmouse_extended_seq = ESC_STR "[<";
+ }
diff --git a/external/subpack/utils/mg/Makefile b/external/subpack/utils/mg/Makefile
new file mode 100644
index 0000000..ba6d931
--- /dev/null
+++ b/external/subpack/utils/mg/Makefile
@@ -0,0 +1,43 @@
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mg
+PKG_VERSION:=7.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/ibara/mg/tar.gz/$(PKG_NAME)-$(PKG_VERSION)?
+PKG_HASH:=c9251d3313663568ac0a571018bc142ef8a533c079e9e9e29bf8088fc0a7d181
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_NAME)-$(PKG_VERSION)
+
+PKG_MAINTAINER:=Hirokazu MORIKAWA <morikw2@gmail.com>
+PKG_LICENSE:=PUBLICDOMAIN ISC BSD VARIOUS
+PKG_LICENSE_FILES:=README.md
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mg
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libncurses +libpcre
+ TITLE:=microscopic EMACS style editor
+ URL:=https://github.com/ibara/mg
+ SUBMENU:=Editors
+endef
+
+define Package/mg/description
+ Mg is intended to be a small, fast, and portable editor for people who
+ can't (or don't want to) run emacs for one reason or another, or are not
+ familiar with the vi editor. It is compatible with emacs because there
+ shouldn't be any reason to learn more editor types than emacs or vi.
+endef
+
+define Package/mg/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/mg $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,mg))
diff --git a/external/subpack/utils/mg/patches/001-cross_compile_openwrt.patch b/external/subpack/utils/mg/patches/001-cross_compile_openwrt.patch
new file mode 100644
index 0000000..a32ce2e
--- /dev/null
+++ b/external/subpack/utils/mg/patches/001-cross_compile_openwrt.patch
@@ -0,0 +1,175 @@
+--- a/configure
++++ b/configure
+@@ -3,66 +3,7 @@
+ # This configure script written by Brian Callahan <bcallah@openbsd.org>
+ # and released into the Public Domain.
+
+-cccheck() {
+- if [ ! -z "$CC" ] ; then
+-cat << EOF > conftest.c
+-int main(void){return 0;}
+-EOF
+- $CC -o conftest conftest.c > /dev/null 2>&1
+- if [ $? -eq 0 ] ; then
+- ./conftest
+- if [ $? -eq 0 ] ; then
+- rm -f conftest conftest.c
+- cc="$CC"
+- return 0
+- else
+- echo "could not build working executables"
+- echo "Please ensure your C compiler is a native compiler"
+- exit 1
+- fi
+- else
+- rm -f conftest conftest.c
+- fi
+- fi
+-
+- for compiler in cc clang pcc xlc gcc ; do
+-cat << EOF > conftest.c
+-int main(void){return 0;}
+-EOF
+-
+- $compiler -o conftest conftest.c > /dev/null 2>&1
+-
+- if [ $? -eq 0 ] ; then
+- ./conftest
+- if [ $? -eq 0 ] ; then
+- rm -f conftest conftest.c
+- cc="$compiler"
+- return 0
+- else
+- echo "could not build working executables"
+- echo "Please ensure your C compiler is a native compiler"
+- exit 1
+- fi
+- else
+- rm -f conftest conftest.c
+- fi
+- done
+- return 1
+-}
+-
+-defaultcflagscheck() {
+- cat << EOF > conftest.c
+-int main(void){return 0;}
+-EOF
+- $cc $cflags -g -O2 -o conftest.o -c conftest.c > /dev/null 2>&1
+- if [ $? -eq 0 ] ; then
+- rm -f conftest conftest.o conftest.c
+- return 1
+- else
+- rm -f conftest conftest.o conftest.c
+- return 0
+- fi
+-}
++cc="$CC"
+
+ fparselncheck() {
+ cat << EOF > conftest.c
+@@ -229,20 +170,6 @@ EOF
+ fi
+ }
+
+-wflagcheck() {
+- cat << EOF > conftest.c
+-int main(void){return 0;}
+-EOF
+- $cc $cflags -w -o conftest conftest.c > /dev/null 2>&1
+- if [ $? -eq 0 ] ; then
+- rm -f conftest conftest.o conftest.c
+- return 1
+- else
+- rm -f conftest conftest.o conftest.c
+- return 0
+- fi
+-}
+-
+ # Option variables
+ if [ ! -z "$PREFIX" ] ; then
+ prefix="$PREFIX"
+@@ -327,80 +254,9 @@ if [ $static -ne 0 ] ; then
+ ldflags="${ldflags}-static"
+ fi
+
+-printf "checking for C compiler... "
+-cccheck
+-if [ $? -ne 0 ] ; then
+- echo "not found"
+- echo "Please install a C compiler and re-run configure."
+- exit 1
+-else
+- echo "$cc"
+-fi
+-
+-if [ "x$cflags" = "x-DREGEX" ] ; then
+- printf "checking if the compiler accepts -g -O2... "
+- defaultcflagscheck
+- if [ $? -eq 0 ] ; then
+- echo "no"
+- else
+- cflags="-g -O2 $cflags"
+- echo "yes"
+- fi
+-fi
+-
+-printf "checking for -w compiler flag... "
+-wflagcheck
+-if [ $? -eq 0 ] ; then
+- echo "no"
+-else
+- cflags="$cflags -w"
+- echo "yes"
+-fi
+-
+-printf "checking for OS... "
+-
+-if [ $terminfo -eq 0 ] ; then
+- libs="-lncursesw"
+-else
+- libs=""
+-fi
+-
+-os=`uname -s`
+-echo "$os"
+-
+-case "x$os" in
+- "xLinux"|"xCYGWIN"*)
+- cflags="$cflags -D_GNU_SOURCE -D__dead=\"__attribute__((__noreturn__))\" -Dst_mtimespec=st_mtim"
+- libs="$libs -lutil"
+- ;;
+- "xDarwin")
+- cflags="$cflags -DMSG_NOSIGNAL=SO_NOSIGPIPE -DLOGIN_NAME_MAX=MAXLOGNAME"
+- if [ $terminfo -eq 0 ] ; then
+- libs="-lncurses -lutil"
+- else
+- libs="-lutil"
+- fi
+- ;;
+- "xFreeBSD")
+- cflags="$cflags -D__dead=__dead2 -DLOGIN_NAME_MAX=MAXLOGNAME"
+- libs="$libs -lutil"
+- ;;
+- "xOpenBSD")
+- libs="$libs -lutil"
+- ;;
+- "xNetBSD")
+- cflags="$cflags -D_OPENBSD_SOURCE"
+- if [ $terminfo -eq 0 ] ; then
+- libs="-lcurses -lutil"
+- else
+- libs="-lutil"
+- fi
+- ;;
+- "xDragonFly")
+- cflags="$cflags -D__dead=__dead2 -DLOGIN_NAME_MAX=MAXLOGNAME"
+- libs="$libs -lutil"
+- ;;
+-esac
++# OpenWrt
++libs='-lncurses -lpcreposix -lutil'
++cflags="$cflags -D_GNU_SOURCE -D__dead=\"__attribute__((__noreturn__))\" -Dst_mtimespec=st_mtim"
+
+ cat << EOF > config.h
+ /* This file generated automatically by configure. */
diff --git a/external/subpack/utils/mg/patches/900-musl_compatibility.patch b/external/subpack/utils/mg/patches/900-musl_compatibility.patch
new file mode 100644
index 0000000..26aaa98
--- /dev/null
+++ b/external/subpack/utils/mg/patches/900-musl_compatibility.patch
@@ -0,0 +1,13 @@
+--- a/fileio.c
++++ b/fileio.c
+@@ -23,6 +23,10 @@
+ #include <string.h>
+ #include <unistd.h>
+
++#ifndef DEFFILEMODE
++#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
++#endif
++
+ #include "def.h"
+ #include "kbd.h"
+ #include "pathnames.h"
diff --git a/external/subpack/utils/mg/patches/901-use_pcre.patch b/external/subpack/utils/mg/patches/901-use_pcre.patch
new file mode 100644
index 0000000..292f2eb
--- /dev/null
+++ b/external/subpack/utils/mg/patches/901-use_pcre.patch
@@ -0,0 +1,11 @@
+--- a/re_search.c
++++ b/re_search.c
+@@ -16,7 +16,7 @@
+ #ifdef REGEX
+ #include <sys/queue.h>
+ #include <sys/types.h>
+-#include <regex.h>
++#include <pcreposix.h>
+ #include <signal.h>
+ #include <stdio.h>
+ #include <string.h>
diff --git a/external/subpack/utils/mhz/Makefile b/external/subpack/utils/mhz/Makefile
new file mode 100644
index 0000000..7ebf26c
--- /dev/null
+++ b/external/subpack/utils/mhz/Makefile
@@ -0,0 +1,33 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mhz
+PKG_RELEASE:=2
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL=https://github.com/wtarreau/mhz.git
+PKG_SOURCE_DATE:=2023-06-17
+PKG_SOURCE_VERSION:=11aac2399780a1f7ea9f007b14af0464797d5cf1
+PKG_MIRROR_HASH:=3accbc6ff26b029d257686e1a7c7f9a40ef5d914a031d31f4d46a807edbad7c3
+
+PKG_MAINTAINER:=Robert Marko <robimarko@gmail.com>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mhz
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=CPU frequency measurement utility
+endef
+
+define Package/mhz/description
+ Tool to mathematically calculate the current CPU frequency.
+endef
+
+define Package/mhz/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/mhz $(1)/usr/sbin/mhz
+endef
+
+$(eval $(call BuildPackage,mhz))
diff --git a/external/subpack/utils/mhz/patches/0001-Makefile-allow-overriding-CC-and-CFLAGS.patch b/external/subpack/utils/mhz/patches/0001-Makefile-allow-overriding-CC-and-CFLAGS.patch
new file mode 100644
index 0000000..569bc99
--- /dev/null
+++ b/external/subpack/utils/mhz/patches/0001-Makefile-allow-overriding-CC-and-CFLAGS.patch
@@ -0,0 +1,29 @@
+From d55f7b578eb2126d2e4a7f045321f6ba7df3800a Mon Sep 17 00:00:00 2001
+From: Robert Marko <robimarko@gmail.com>
+Date: Wed, 30 Aug 2023 20:31:07 +0200
+Subject: [PATCH] Makefile: allow overriding CC and CFLAGS
+
+For OpenWrt and Buildroot which support really large amount of different
+architectures and cores it is sometimes required to pass our own CFLAGS.
+This is especially true if hardening options are to be respected.
+
+Also, for cross-compiling CC should be respected as currently it is
+working since both OpenWrt and Buildroot symlink gcc to the cross compiler.
+
+So, lets set the current values as defaults but allow them to be overriden.
+
+Signed-off-by: Robert Marko <robimarko@gmail.com>
+---
+ Makefile | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/Makefile
++++ b/Makefile
+@@ -1,5 +1,5 @@
+-CC := gcc
+-CFLAGS := -O3 -Wall -fomit-frame-pointer
++CC ?= gcc
++CFLAGS ?= -O3 -Wall -fomit-frame-pointer
+
+ all: mhz
+
diff --git a/external/subpack/utils/micrond/Makefile b/external/subpack/utils/micrond/Makefile
new file mode 100644
index 0000000..9fb42ca
--- /dev/null
+++ b/external/subpack/utils/micrond/Makefile
@@ -0,0 +1,23 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=micrond
+PKG_VERSION:=1
+PKG_RELEASE:=2
+PKG_LICENSE:=BSD-2-Clause
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/micrond
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Small Cron daemon providing a cron.d directory other packages can install their crontabs into
+ DEPENDS:=
+endef
+
+define Package/micrond/install
+ $(CP) ./files/* $(1)/
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/micrond $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,micrond))
diff --git a/external/subpack/utils/micrond/files/etc/init.d/micrond b/external/subpack/utils/micrond/files/etc/init.d/micrond
new file mode 100755
index 0000000..35a3b9e
--- /dev/null
+++ b/external/subpack/utils/micrond/files/etc/init.d/micrond
@@ -0,0 +1,15 @@
+#!/bin/sh /etc/rc.common
+
+START=50
+USE_PROCD=1
+
+CRONDIR=/usr/lib/micron.d
+
+start_service() {
+ procd_open_instance
+ procd_set_param command /usr/sbin/micrond "$CRONDIR"
+ procd_set_param respawn
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_close_instance
+}
diff --git a/external/subpack/utils/micrond/files/usr/lib/micron.d/.keep b/external/subpack/utils/micrond/files/usr/lib/micron.d/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/external/subpack/utils/micrond/files/usr/lib/micron.d/.keep
diff --git a/external/subpack/utils/micrond/src/Makefile b/external/subpack/utils/micrond/src/Makefile
new file mode 100644
index 0000000..40059ef
--- /dev/null
+++ b/external/subpack/utils/micrond/src/Makefile
@@ -0,0 +1,3 @@
+all: micrond
+
+micrond: micrond.c
diff --git a/external/subpack/utils/micrond/src/micrond.c b/external/subpack/utils/micrond/src/micrond.c
new file mode 100644
index 0000000..cb16c12
--- /dev/null
+++ b/external/subpack/utils/micrond/src/micrond.c
@@ -0,0 +1,316 @@
+/*
+ Copyright (c) 2013, Matthias Schiffer <mschiffer@universe-factory.net>
+ 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+*/
+
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <dirent.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+
+typedef struct job {
+ struct job *next;
+
+ uint64_t minutes;
+ uint32_t hours;
+ uint32_t doms;
+ uint16_t months;
+ uint8_t dows;
+
+ char *command;
+} job_t;
+
+
+static const char const *const MONTHS[12] = {
+ "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"
+};
+
+static const char const *const WEEKDAYS[7] = {
+ "sun", "mon", "tue", "wed", "thu", "fri", "sat"
+};
+
+
+static const char *crondir;
+
+static job_t *jobs = NULL;
+
+
+static void usage(void) {
+ fprintf(stderr, "Usage: micrond <crondir>\n");
+}
+
+
+static inline uint64_t bit(unsigned b) {
+ return ((uint64_t)1) << b;
+}
+
+static int strict_atoi(const char *s) {
+ char *end;
+ int ret = strtol(s, &end, 10);
+
+ if (*end)
+ return -1;
+ else
+ return ret;
+}
+
+static uint64_t parse_strings(const char *input, const char *const *strings, size_t n) {
+ size_t i;
+ for (i = 0; i < n; i++) {
+ if (strcasecmp(input, strings[i]) == 0)
+ return bit(i);
+ }
+
+ return 0;
+}
+
+static uint64_t parse_times(char *input, int min, int n) {
+ uint64_t ret = 0;
+ int step = 1;
+
+ char *comma = strchr(input, ',');
+ if (comma) {
+ *comma = 0;
+ ret = parse_times(comma+1, min, n);
+
+ if (!ret)
+ return 0;
+ }
+
+ char *slash = strchr(input, '/');
+ if (slash) {
+ *slash = 0;
+ step = strict_atoi(slash+1);
+
+ if (step <= 0)
+ return 0;
+ }
+
+ int begin, end;
+ char *minus = strchr(input, '-');
+ if (minus) {
+ *minus = 0;
+ begin = strict_atoi(input);
+ end = strict_atoi(minus+1);
+ }
+ else if (strcmp(input, "*") == 0) {
+ begin = min;
+ end = min+n-1;
+ }
+ else {
+ begin = end = strict_atoi(input);
+ }
+
+ if (begin < min || end < min)
+ return 0;
+
+ int i;
+ for (i = begin-min; i <= end-min; i += step)
+ ret |= bit(i % n);
+
+ return ret;
+}
+
+static int handle_line(const char *line) {
+ job_t job = {};
+ int ret = -1;
+ char *columns[5];
+ int i;
+ int len;
+
+ int matches = sscanf(line, "%ms %ms %ms %ms %ms %n", &columns[0], &columns[1], &columns[2], &columns[3], &columns[4], &len);
+ if (matches != 5 && matches != 6) {
+ if (matches <= 0)
+ ret = 0;
+
+ goto end;
+ }
+
+ job.minutes = parse_times(columns[0], 0, 60);
+ if (!job.minutes)
+ goto end;
+
+ job.hours = parse_times(columns[1], 0, 24);
+ if (!job.hours)
+ goto end;
+
+ job.doms = parse_times(columns[2], 1, 31);
+ if (!job.doms)
+ goto end;
+
+
+ job.months = parse_strings(columns[3], MONTHS, 12);
+
+ if (!job.months)
+ job.months = parse_times(columns[3], 1, 12);
+ if (!job.months)
+ goto end;
+
+ job.dows = parse_strings(columns[4], WEEKDAYS, 7);
+ if (!job.dows)
+ job.dows = parse_times(columns[4], 0, 7);
+ if (!job.dows)
+ goto end;
+
+ job.command = strdup(line+len);
+
+ job_t *jobp = malloc(sizeof(job_t));
+ *jobp = job;
+
+ jobp->next = jobs;
+ jobs = jobp;
+
+ ret = 0;
+
+ end:
+ for (i = 0; i < matches && i < 5; i++)
+ free(columns[i]);
+
+ return ret;
+}
+
+
+static void read_crontab(const char *name) {
+ FILE *file = fopen(name, "r");
+ if (!file) {
+ syslog(LOG_WARNING, "unable to read crontab `%s'", name);
+ return;
+ }
+
+ char line[16384];
+ unsigned lineno = 0;
+
+ while (fgets(line, sizeof(line), file)) {
+ lineno++;
+
+ char *comment = strchr(line, '#');
+ if (comment)
+ *comment = 0;
+
+ if (handle_line(line))
+ syslog(LOG_WARNING, "syntax error in `%s', line %u", name, lineno);
+ }
+
+ fclose(file);
+}
+
+
+static void read_crondir(void) {
+ DIR *dir;
+
+ if (chdir(crondir) || ((dir = opendir(".")) == NULL)) {
+ fprintf(stderr, "Unable to read crondir `%s'\n", crondir);
+ usage();
+ exit(1);
+ }
+
+ struct dirent *ent;
+ while ((ent = readdir(dir)) != NULL) {
+ if (ent->d_name[0] == '.')
+ continue;
+
+ read_crontab(ent->d_name);
+ }
+
+ closedir(dir);
+}
+
+
+static void run_job(const job_t *job) {
+ pid_t pid = fork();
+ if (pid == 0) {
+ execl("/bin/sh", "/bin/sh", "-c", job->command, (char*)NULL);
+ syslog(LOG_ERR, "unable to run job: exec failed");
+ _exit(1);
+ }
+ else if (pid < 0) {
+ syslog(LOG_ERR, "unable to run job: fork failed");
+ }
+}
+
+
+static void check_job(const job_t *job, const struct tm *tm) {
+ if (!(job->minutes & bit(tm->tm_min)))
+ return;
+
+ if (!(job->hours & bit(tm->tm_hour)))
+ return;
+
+ if (!(job->doms & bit(tm->tm_mday-1)))
+ return;
+
+ if (!(job->months & bit(tm->tm_mon)))
+ return;
+
+ if (!(job->dows & bit(tm->tm_wday)))
+ return;
+
+ run_job(job);
+}
+
+
+int main(int argc, char *argv[]) {
+ if (argc != 2) {
+ usage();
+
+ exit(argc < 2 ? 0 : 1);
+ }
+
+ crondir = argv[1];
+
+ signal(SIGCHLD, SIG_IGN);
+
+ read_crondir();
+
+ time_t t = time(NULL);
+ struct tm *tm = localtime(&t);
+ int minute = tm->tm_min;
+
+ while (1) {
+ sleep(60 - t%60);
+
+ t = time(NULL);
+ tm = localtime(&t);
+
+ minute = (minute+1)%60;
+ if (tm->tm_min != minute) {
+ /* clock has moved, don't execute jobs */
+ minute = tm->tm_min;
+ continue;
+ }
+
+ job_t *job;
+ for (job = jobs; job; job = job->next)
+ check_job(job, tm);
+ }
+}
diff --git a/external/subpack/utils/minicom/Makefile b/external/subpack/utils/minicom/Makefile
new file mode 100644
index 0000000..0184c89
--- /dev/null
+++ b/external/subpack/utils/minicom/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2006-2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=minicom
+PKG_VERSION:=2.9
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://salsa.debian.org/minicom-team/minicom/-/archive/$(PKG_VERSION)
+PKG_HASH:=9efbb6458140e5a0de445613f0e76bcf12cbf7a9892b2f53e075c2e7beaba86c
+PKG_MAINTAINER:=Álvaro Fernández Rojas <noltari@gmail.com>
+
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:minicom:minicom
+
+include $(INCLUDE_DIR)/nls.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/minicom
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=$(ICONV_DEPENDS) $(INTL_DEPENDS) +libncurses
+ TITLE:=Terminal emulation program
+ URL:=https://salsa.debian.org/minicom-team/minicom
+ SUBMENU:=Terminal
+endef
+
+define Package/minicom/conffiles
+/etc/minirc.dfl
+endef
+
+define Package/minicom/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/$(PKG_NAME) $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ascii-xfr $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,minicom))
diff --git a/external/subpack/utils/minicom/patches/110-reproducible-builds.patch b/external/subpack/utils/minicom/patches/110-reproducible-builds.patch
new file mode 100644
index 0000000..b72d783
--- /dev/null
+++ b/external/subpack/utils/minicom/patches/110-reproducible-builds.patch
@@ -0,0 +1,20 @@
+--- a/src/minicom.c
++++ b/src/minicom.c
+@@ -1323,7 +1323,7 @@ int main(int argc, char **argv)
+ switch(c) {
+ case 'v':
+ printf(_("%s version %s"), PACKAGE, VERSION);
+-#ifdef __DATE__
++#if 0
+ printf(_(" (compiled %s)"), __DATE__);
+ #endif
+ printf("\n");
+@@ -1659,7 +1659,7 @@ int main(int argc, char **argv)
+
+ mc_wprintf(us, "\n%s %s\r\n", _("Welcome to minicom"), VERSION);
+ mc_wprintf(us, "\n%s: %s\r\n", _("OPTIONS"), option_string);
+-#if defined (__DATE__) && defined (__TIME__)
++#if 0
+ mc_wprintf(us, "%s %s, %s.\r\n",_("Compiled on"), __DATE__,__TIME__);
+ #endif
+ {
diff --git a/external/subpack/utils/miniflux/Makefile b/external/subpack/utils/miniflux/Makefile
new file mode 100644
index 0000000..5283710
--- /dev/null
+++ b/external/subpack/utils/miniflux/Makefile
@@ -0,0 +1,59 @@
+#
+# Copyright (C) 2021 CZ.NIC, z. s. p. o. (https://www.nic.cz/)
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=miniflux
+PKG_VERSION:=2.0.33
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/miniflux/v2/tar.gz/${PKG_VERSION}?
+PKG_HASH:=b61c9ddb62be8f1cc15a70a1c916d55f8ac47299df9c2323552eb275a36d2cc3
+
+PKG_MAINTAINER:=Michal Vasilek <michal.vasilek@nic.cz>
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/v2-$(PKG_VERSION)
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=miniflux.app
+GO_PKG_LDFLAGS_X:=miniflux.app/version.Version=$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/miniflux
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Feed reader
+ USERID:=miniflux=1120:miniflux=1120
+ URL:=https://miniflux.app
+ DEPENDS:=$(GO_ARCH_DEPENDS) +pgsql-server
+endef
+
+define Package/miniflux/description
+ Miniflux is a small and simple feed reader.
+endef
+
+define Package/miniflux/install
+ $(call GoPackage/Package/Install/Bin,$(1))
+ $(INSTALL_DIR) $(1)/etc/config/
+ $(INSTALL_CONF) ./files/miniflux.conf $(1)/etc/config/miniflux
+ $(INSTALL_DIR) $(1)/etc/init.d/
+ $(INSTALL_BIN) ./files/miniflux.init $(1)/etc/init.d/miniflux
+endef
+
+define Package/miniflux/conffiles
+/etc/config/miniflux
+endef
+
+$(eval $(call GoBinPackage,miniflux))
+$(eval $(call BuildPackage,miniflux))
diff --git a/external/subpack/utils/miniflux/files/miniflux.conf b/external/subpack/utils/miniflux/files/miniflux.conf
new file mode 100644
index 0000000..ec448a2
--- /dev/null
+++ b/external/subpack/utils/miniflux/files/miniflux.conf
@@ -0,0 +1,20 @@
+package miniflux
+
+config miniflux main
+ # if set, all other uci settings are ignored
+ option config_file ''
+
+ option listen_address '127.0.0.1:5433'
+
+ # run migrations on each start, disabling this will make miniflux fail to
+ # start on the next upgrade until migrations are ran manually
+ option migrate 1
+
+config miniflux database
+ # if set, all other options in this section will be ignored
+ option url ''
+
+ option user miniflux
+ option password ''
+ option sslmode disable
+ option dbname miniflux
diff --git a/external/subpack/utils/miniflux/files/miniflux.init b/external/subpack/utils/miniflux/files/miniflux.init
new file mode 100644
index 0000000..6c71869
--- /dev/null
+++ b/external/subpack/utils/miniflux/files/miniflux.init
@@ -0,0 +1,44 @@
+#!/bin/sh /etc/rc.common
+
+# Copyright (C) 2021 CZ.NIC z.s.p.o. (https://www.nic.cz/)
+
+START=70
+
+USE_PROCD=1
+PROG=/usr/bin/miniflux.app
+
+start_service() {
+ local config_file
+ config_load miniflux
+
+ procd_open_instance
+ procd_set_param command "$PROG"
+ procd_append_param user miniflux
+
+ config_get config_file main config_file
+ if [ -n "$config_file" ]; then
+ procd_append_param command -config-file="$config_file"
+ else
+ local listen_address run_migrations database_url
+ config_get listen_address main listen_address
+ procd_append_param env LISTEN_ADDR="$listen_address"
+ config_get run_migrations main run_migrations
+ [ "$run_migrations" = 1 ] && procd_append_param env RUN_MIGRATIONS=1
+
+ config_get database_url database url
+ if [ -z "$database_url" ]; then
+ local database_user database_password database_dbname database_sslmode
+ config_get database_user database user
+ config_get database_password database password
+ config_get database_dbname database dbname
+ config_get database_sslmode database sslmode
+ database_url="user=$database_user password=$database_password dbname=$database_dbname sslmode=$database_sslmode"
+ fi
+ procd_append_param env DATABASE_URL="$database_url"
+ fi
+
+ procd_set_param file "$config_file"
+ procd_set_param respawn
+ procd_set_param stderr 1
+ procd_close_instance
+}
diff --git a/external/subpack/utils/miniflux/test.sh b/external/subpack/utils/miniflux/test.sh
new file mode 100644
index 0000000..42ff319
--- /dev/null
+++ b/external/subpack/utils/miniflux/test.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+miniflux.app -version | grep "$2"
diff --git a/external/subpack/utils/mksh/Makefile b/external/subpack/utils/mksh/Makefile
new file mode 100644
index 0000000..ad665ac
--- /dev/null
+++ b/external/subpack/utils/mksh/Makefile
@@ -0,0 +1,92 @@
+#
+# Copyright (C) 2007-2011 OpenWrt.org
+# Copyright (c) 2009-2014 Thorsten Glaser <tg@mirbsd.org>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mksh
+PKG_VERSION:=59c
+PKG_RELEASE:=1
+
+PKG_MAINTAINER:=Thorsten Glaser <tg@mirbsd.org>, \
+ Alif M. Ahmad <alive4ever@live.com>
+PKG_LICENSE:=MirOS
+
+PKG_SOURCE:=$(PKG_NAME)-R$(PKG_VERSION).tgz
+PKG_SOURCE_URL:=http://www.mirbsd.org/MirOS/dist/mir/mksh \
+ http://pub.allbsd.org/MirOS/dist/mir/mksh
+PKG_HASH:=77ae1665a337f1c48c61d6b961db3e52119b38e58884d1c89684af31f87bc506
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mksh
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Shells
+ TITLE:=MirBSD Korn Shell
+ DEPENDS:=$(DEP)
+ URL:=http://mirbsd.de/mksh
+endef
+
+define Package/mksh/description
+mksh is the MirBSD enhanced version of the Public Domain Korn
+shell (pdksh), a Bourne-compatible shell which is largely si-
+milar to the original AT&T Korn shell; mksh is the only pdksh
+derivate currently being actively developed. It includes bug
+fixes and feature improvements, in order to produce a modern,
+robust shell good for interactive and especially script use.
+mksh has UTF-8 support (in substring operations and the Emacs
+editing mode) and - while R59 corresponds to OpenBSD 5.7-cur-
+rent ksh (without GNU bash-like PS1 and fancy character clas-
+ses) - adheres to SUSv4 and is much more robust. The code has
+been cleaned up and simplified, bugs fixed, standards compli-
+ance added, and several enhancements (for extended compatibi-
+lity to other modern shells - as well as a couple of its own)
+are available. It has sensible defaults as usual with BSD.
+endef
+
+define Build/Compile
+ # -DMKSH_SMALL=1 ⇒ reduce functionality quite a lot
+ # -DMKSH_ASSUME_UTF8=0 ⇒ never automatically enable
+ # UTF-8 mode, neither use setlocale/nl_langinfo
+ # nor look at $LC_* and $LANG (not recommended)
+ # -DMKSH_BINSHPOSIX ⇒ enable POSIX mode if called as sh
+ #XXX maybe change to -DMKSH_ASSUME_UTF8=1 now (which
+ #XXX is always assume UTF-8 mode)
+ # HAVE_CAN_FSTACKPROTECTORALL=0 ⇒ nuke libssp dependency
+ # HAVE_CAN_FSTACKPROTECTORSTRONG=0 ⇒ same, for gcc 4.9+
+ cd $(PKG_BUILD_DIR); \
+ CC="$(TARGET_CC)" \
+ TARGET_OS="$(shell uname -s)" \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ CPPFLAGS="$(TARGET_CPPFLAGS) -DMKSH_SMALL=1 -DMKSH_ASSUME_UTF8=0 -DMKSH_BINSHPOSIX -DMKSHRC_PATH=\\\"/etc/mkshrc\\\"" \
+ HAVE_CAN_FSTACKPROTECTORALL=0 \
+ HAVE_CAN_FSTACKPROTECTORSTRONG=0 \
+ LDFLAGS="$(TARGET_LDFLAGS)" \
+ $(BASH) Build.sh -Q -r
+endef
+
+define Package/mksh/postinst
+#!/bin/sh
+grep mksh $${IPKG_INSTROOT}/etc/shells || \
+ echo "/bin/mksh" >> $${IPKG_INSTROOT}/etc/shells
+endef
+
+define Package/mksh/install
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/dot.mkshrc $(1)/etc/mkshrc
+ $(INSTALL_DIR) $(1)/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/mksh $(1)/bin/
+endef
+
+define Package/mksh/conffiles
+/etc/mkshrc
+endef
+
+$(eval $(call BuildPackage,mksh))
diff --git a/external/subpack/utils/mksh/patches/100-dot_mkshrc b/external/subpack/utils/mksh/patches/100-dot_mkshrc
new file mode 100644
index 0000000..1debb44
--- /dev/null
+++ b/external/subpack/utils/mksh/patches/100-dot_mkshrc
@@ -0,0 +1,47 @@
+From 23712cea8e2a623fd952eb781df0011c501703d0 Mon Sep 17 00:00:00 2001
+From: Thorsten Glaser <tg@mirbsd.org>
+Date: Thu, 25 Jul 2013 22:07:33 +0200
+Subject: [PATCH] Make default mkshrc file suitable for OpenWrt environment:
+
+* Part of the FreeWRT patches:
+ - no hostname(1)
+ - ls(1) has no -o option
+* OpenWrt and FreeWRT-1.0 fix:
+ - since this is not ~/.mkshrc make sure subshells find it
+
+From: Alif M. A. <alive4ever@live.com>
+Date: Thu, 20 Jul 2017 14:52:39 +0000
+Subject: [PATCH] Refresh 100-dot_mkshrc for mksh-R55
+
+Additional changes of the patch as of mksh-R55
+* Use content of `/proc/sys/kernel/hostname` to set `$HOSTNAME`, since
+ `hostname` applet isn't compiled into `busybox`.
+* Use `/bin/vi` as fallback `$EDITOR`.
+* Use `/etc/mkshrc` as default startup file, so there is no need to
+ manually source it during interactive session.
+
+From: Alif M. A. <alive4ever@live.com>
+Date: Thu, 11 Jan 2018 02:13:46 +0000
+Subject: [PATCH] Refresh 100-dot_mkshrc for mksh-R55
+
+Refreshed 100-dot_mkshrc for mksh-r56b
+
+---
+Reviewed-by: Thorsten Glaser <tg at mirbsd.org>
+Signed-off-by: Alif M. A. <alive4ever at live.com>
+
+--- a/dot.mkshrc
++++ b/dot.mkshrc
+@@ -64,9 +64,9 @@ for EDITOR in "${EDITOR:-}" jupp jstar m
+ EDITOR=
+ done
+
+-\\builtin alias ls=ls l='ls -F' la='l -a' ll='l -l' lo='l -alo'
+-\: "${EDITOR:=/bin/ed}${TERM:=vt100}${USER:=$(\\builtin ulimit -c 0; id -un \
+- 2>/dev/null)}${HOSTNAME:=$(\\builtin ulimit -c 0; hostname 2>/dev/null)}"
++\\builtin alias ls=ls l='ls -F' la='l -a' ll='l -l' lo='l -al'
++\: "${EDITOR:=/bin/vi}${TERM:=vt100}${USER:=$(\\builtin ulimit -c 0; id -un \
++ 2>/dev/null)}${HOSTNAME:=$(</proc/sys/kernel/hostname)}"
+ [[ $HOSTNAME = ?(?(ip6-)localhost?(6)) ]] && HOSTNAME=nil; \\builtin unalias ls
+ \\builtin export EDITOR HOSTNAME TERM USER="${USER:-?}"
+
diff --git a/external/subpack/utils/mktorrent/Makefile b/external/subpack/utils/mktorrent/Makefile
new file mode 100644
index 0000000..3bc241a
--- /dev/null
+++ b/external/subpack/utils/mktorrent/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2006-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mktorrent
+PKG_VERSION:=1.1
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://github.com/Rudde/$(PKG_NAME)
+PKG_SOURCE_VERSION:=b20ef699b4ee5ded2f078ead776c7deac969e19a
+PKG_MIRROR_HASH:=abe5f96d1a91c00bd6dcf86640a205583e8607d2b0e9299a588cec76c556a8e8
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mktorrent
+ SUBMENU:=BitTorrent
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=mktorrent
+ URL:=https://github.com/Rudde/mktorrent
+endef
+
+define Package/mktorrent/Description
+ mktorrent is a simple command line utility to create BitTorrent metainfo files.
+endef
+
+
+define Package/mktorrent/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/mktorrent $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,mktorrent))
diff --git a/external/subpack/utils/mmc-utils/Makefile b/external/subpack/utils/mmc-utils/Makefile
new file mode 100644
index 0000000..9bd1a6f
--- /dev/null
+++ b/external/subpack/utils/mmc-utils/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2015-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mmc-utils
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git
+PKG_SOURCE_DATE:=2024-03-05
+PKG_SOURCE_VERSION:=e1281d4de9166b7254ba30bb58f9191fc2c9e7fb
+PKG_MIRROR_HASH:=cea063fbdb9f48c7a928bd940260fc9152447797a8dff4bbf71d5b342144f17c
+
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=
+
+PKG_MAINTAINER:=Michael Heimpold <mhei@heimpold.de>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mmc-utils
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Userspace tools for MMC/SD devices
+ URL:=https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git
+endef
+
+define Package/mmc-utils/description
+ This package contains the userspace mmc utils, the userspace
+ counterpart to the Linux MMC/SD subsystem.
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ $(TARGET_CONFIGURE_OPTS) CFLAGS="$(TARGET_CFLAGS) -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 \
+ -UVERSION -DVERSION=\\\"$(shell echo $(PKG_SOURCE_VERSION) | cut -c -6)\\\"" \
+ mmc
+endef
+
+define Package/mmc-utils/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/mmc $(1)/sbin
+endef
+
+$(eval $(call BuildPackage,mmc-utils))
diff --git a/external/subpack/utils/mmc-utils/patches/0000-properly-set-fortify-source-in-makefile.patch b/external/subpack/utils/mmc-utils/patches/0000-properly-set-fortify-source-in-makefile.patch
new file mode 100644
index 0000000..de976ca
--- /dev/null
+++ b/external/subpack/utils/mmc-utils/patches/0000-properly-set-fortify-source-in-makefile.patch
@@ -0,0 +1,10 @@
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ CC ?= gcc
+ GIT_VERSION := "$(shell git describe --abbrev=6 --always --tags)"
+-AM_CFLAGS = -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 \
++AM_CFLAGS = -D_FILE_OFFSET_BITS=64 \
+ -DVERSION=\"$(GIT_VERSION)\"
+ CFLAGS ?= -g -O2
+ objects = \
diff --git a/external/subpack/utils/moreutils/Makefile b/external/subpack/utils/moreutils/Makefile
new file mode 100644
index 0000000..fd8c438
--- /dev/null
+++ b/external/subpack/utils/moreutils/Makefile
@@ -0,0 +1,62 @@
+#
+# Copyright (C) 2016 Nikil Mehta <nikil.mehta@gmail.com>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=moreutils
+PKG_VERSION:=0.69
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://git.kitenet.net/index.cgi/moreutils.git/snapshot
+PKG_HASH:=0f795d25356ca61544966646fb707d5be0b9864116be0269df5433f62d4e05d1
+
+PKG_MAINTAINER:=Nikil Mehta <nikil.mehta@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/moreutils
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=additional Unix utilities
+ URL:=https://joeyh.name/code/moreutils/
+ DEPENDS:=+perl +perlbase-file +perlbase-getopt +perlbase-io +perlbase-ipc +perlbase-posix +perlbase-time
+endef
+
+define Package/moreutils/description
+ This is a growing collection of the Unix tools that nobody thought
+ to write long ago, when Unix was young.
+ .
+ So far, it includes the following utilities:
+ - chronic: runs a command quietly unless it fails
+ - combine: combine the lines in two files using boolean operations
+ - errno: look up errno names and descriptions
+ - ifdata: get network interface info without parsing ifconfig output
+ - ifne: run a program if the standard input is not empty
+ - isutf8: check if a file or standard input is utf-8
+ - lckdo: execute a program with a lock held
+ - mispipe: pipe two commands, returning the exit status of the first
+ - parallel: run multiple jobs at once
+ - pee: tee standard input to pipes
+ - sponge: soak up standard input and write to a file
+ - ts: timestamp standard input
+ - vidir: edit a directory in your text editor
+ - vipe: insert a text editor into a pipe
+ - zrun: automatically uncompress arguments to command
+endef
+
+define Package/moreutils/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,moreutils))
diff --git a/external/subpack/utils/moreutils/patches/001_disable-manuals.patch b/external/subpack/utils/moreutils/patches/001_disable-manuals.patch
new file mode 100644
index 0000000..99393af
--- /dev/null
+++ b/external/subpack/utils/moreutils/patches/001_disable-manuals.patch
@@ -0,0 +1,21 @@
+--- a/Makefile
++++ b/Makefile
+@@ -13,7 +13,7 @@ endif
+
+ DOCBOOK2XMAN=xsltproc --param man.authors.section.enabled 0 $(DOCBOOKXSL)/manpages/docbook.xsl
+
+-all: $(BINS) $(MANS)
++all: $(BINS)
+
+ clean:
+ rm -f $(BINS) $(MANS) dump.c errnos.h errno.o \
+@@ -33,9 +33,6 @@ install:
+ $(INSTALL_BIN) $(BINS) $(DESTDIR)$(PREFIX)/bin
+ install $(PERLSCRIPTS) $(DESTDIR)$(PREFIX)/bin
+
+- mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1
+- install -m 644 $(MANS) $(DESTDIR)$(PREFIX)/share/man/man1
+-
+ uninstall:
+ for i in $(BINS) $(PERLSCRIPTS); do rm -f $(DESTDIR)$(PREFIX)/bin/$$i; done
+ for i in $(MANS); do rm -f $(DESTDIR)$(PREFIX)/share/man/man1/$$i; done
diff --git a/external/subpack/utils/moreutils/patches/002_no-install-strip.patch b/external/subpack/utils/moreutils/patches/002_no-install-strip.patch
new file mode 100644
index 0000000..ecc1403
--- /dev/null
+++ b/external/subpack/utils/moreutils/patches/002_no-install-strip.patch
@@ -0,0 +1,11 @@
+--- a/Makefile
++++ b/Makefile
+@@ -2,7 +2,7 @@ BINS=isutf8 ifdata ifne pee sponge mispi
+ PERLSCRIPTS=vidir vipe ts combine zrun chronic
+ MANS=sponge.1 vidir.1 vipe.1 isutf8.1 ts.1 combine.1 ifdata.1 ifne.1 pee.1 zrun.1 chronic.1 mispipe.1 lckdo.1 parallel.1 errno.1
+ CFLAGS?=-O2 -g -Wall
+-INSTALL_BIN?=install -s
++INSTALL_BIN?=install
+ PREFIX?=/usr
+
+ ifneq (,$(findstring CYGWIN,$(shell uname)))
diff --git a/external/subpack/utils/mpack/Makefile b/external/subpack/utils/mpack/Makefile
new file mode 100644
index 0000000..237e143
--- /dev/null
+++ b/external/subpack/utils/mpack/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2007-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mpack
+PKG_VERSION:=1.6
+PKG_RELEASE:=1
+PKG_LICENSE:=NLPL
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://fossies.org/linux/misc/old
+PKG_HASH:=274108bb3a39982a4efc14fb3a65298e66c8e71367c3dabf49338162d207a94c
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mpack
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=mpack/munpack MIME format mail messages
+ URL:=https://gitlab.com/osdp/mpack
+ MAINTAINER:=Dmitry V. Zimin <pfzim@mail.ru>
+endef
+
+define Package/mpack/description
+ Mpack and munpack are utilities for encoding and decoding
+ (respectively) binary files in MIME (Multipurpose Internet Mail
+ Extensions) format mail messages. For compatibility with older forms
+ of transferring binary files, the munpack program can also decode
+ messages in split-uuencoded format.
+endef
+
+define Package/mpack/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,mpack))
+
diff --git a/external/subpack/utils/mpack/patches/001-use-stdlib.patch b/external/subpack/utils/mpack/patches/001-use-stdlib.patch
new file mode 100644
index 0000000..96b928a
--- /dev/null
+++ b/external/subpack/utils/mpack/patches/001-use-stdlib.patch
@@ -0,0 +1,30 @@
+--- a/unixos.c
++++ b/unixos.c
+@@ -25,6 +25,7 @@
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <string.h>
++#include <stdlib.h>
+ #include <errno.h>
+ #include <sys/types.h>
+ #include <sys/param.h>
+@@ -39,8 +40,6 @@
+ #endif
+
+ extern int errno;
+-extern char *malloc();
+-extern char *getenv();
+
+ int overwrite_files = 0;
+ int didchat;
+--- a/xmalloc.c
++++ b/xmalloc.c
+@@ -24,7 +24,7 @@
+ */
+ #include <stdio.h>
+ #include <string.h>
+-extern char *malloc(), *realloc();
++#include <stdlib.h>
+
+ char *xmalloc (int size)
+ {
diff --git a/external/subpack/utils/mt-st/Makefile b/external/subpack/utils/mt-st/Makefile
new file mode 100644
index 0000000..71bfdcf
--- /dev/null
+++ b/external/subpack/utils/mt-st/Makefile
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mt-st
+PKG_VERSION:=1.1
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=ftp://ftp.ibiblio.org/pub/Linux/system/backup/
+PKG_HASH:=945cb4f3d9957dabe768f5941a9148b746396836c797b25f020c84319ba8170d
+
+PKG_MAINTAINER:=Giuseppe Magnotta <giuseppe.magnotta@gmail.com>
+PKG_LICENSE:=GPL-2.0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mt-st
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Magnetic tape control tools for Linux SCSI tapes
+ URL:=http://ftp.ibiblio.org/pub/Linux/system/backup/
+endef
+
+define Package/mt-st/description
+ Includes a mt-like program supporting additional commands using ioctls
+ specific to the Linux SCSI tape driver (up to kernel 2.6.26), and the program
+ stinit to define the SCSI tape devices in system startup scripts.
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ LDFLAGS="$(TARGET_LDFLAGS)" \
+ CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
+ CC="$(TARGET_CC)"
+endef
+
+define Package/mt-st/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/mt $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/stinit $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,mt-st))
diff --git a/external/subpack/utils/mt-st/patches/010-sysmacros.patch b/external/subpack/utils/mt-st/patches/010-sysmacros.patch
new file mode 100644
index 0000000..94abc2e
--- /dev/null
+++ b/external/subpack/utils/mt-st/patches/010-sysmacros.patch
@@ -0,0 +1,20 @@
+--- a/mt.c
++++ b/mt.c
+@@ -20,6 +20,7 @@
+ #include <fcntl.h>
+ #include <sys/types.h>
+ #include <sys/ioctl.h>
++#include <sys/sysmacros.h>
+ #include <sys/stat.h>
+ #include <sys/utsname.h>
+
+--- a/stinit.c
++++ b/stinit.c
+@@ -16,6 +16,7 @@
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <dirent.h>
++#include <limits.h>
+ #include <sys/stat.h>
+ #include <sys/ioctl.h>
+ #include <sys/sysmacros.h>
diff --git a/external/subpack/utils/nano/Makefile b/external/subpack/utils/nano/Makefile
new file mode 100644
index 0000000..5cbd349
--- /dev/null
+++ b/external/subpack/utils/nano/Makefile
@@ -0,0 +1,150 @@
+#
+# Copyright (C) 2007-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=nano
+PKG_VERSION:=8.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/nano
+PKG_HASH:=d5ad07dd862facae03051c54c6535e54c7ed7407318783fcad1ad2d7076fffeb
+
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=Hannu Nyman <hannu.nyman@iki.fi>
+PKG_CPE_ID:=cpe:/a:gnu:nano
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/nano/Default
+ SUBMENU:=Editors
+ SECTION:=utils
+ CATEGORY:=Utilities
+ URL:=https://www.nano-editor.org/
+ DEPENDS:=+libncurses
+endef
+
+define Package/nano
+ $(call Package/nano/Default)
+ TITLE:=GNU nano text editor (minimal features)
+ VARIANT:=tiny
+ DEFAULT_VARIANT:=1
+endef
+
+define Package/nano-plus
+ $(call Package/nano/Default)
+ TITLE:=GNU nano text editor (more features, Unicode)
+ VARIANT:=plus
+endef
+
+define Package/nano-full
+ $(call Package/nano/Default)
+ TITLE:=GNU nano text editor (all features, Unicode)
+ VARIANT:=full
+endef
+
+define Package/nano/description
+ Nano is a small and simple text editor for use on the terminal.
+
+ Nano started as an enhanced clone of the Pico text editor.
+ Nowadays Nano wants to be a generally useful editor with sensible
+ defaults (linewise scrolling, no automatic line breaking).
+
+ Nano is an official GNU package.
+endef
+
+define Package/nano-plus/description
+ nano-plus - Additional features enabled, larger size than default nano.
+ (multibuffer, Unicode/UTF-8, help, justify, nanorc, some key bindings)
+
+ $(call Package/nano/description)
+endef
+
+define Package/nano-full/description
+ nano-full - all features, including syntax highlighting (also uci),
+ multibuffer, Unicode/UTF-8, nanorc, some key bindings.
+ (libmagic-based file type detection is disabled)
+
+ Example /etc/nanorc is included. nanorc documentation at
+ https://www.nano-editor.org/dist/latest/nanorc.5.html
+
+ $(call Package/nano/description)
+endef
+
+ifeq ($(BUILD_VARIANT),full)
+# full variant with almost all features included
+ CONFIGURE_ARGS += \
+ --disable-extra \
+ --disable-libmagic \
+ --enable-utf8
+else ifeq ($(BUILD_VARIANT),plus)
+# plus variant with some features included
+ CONFIGURE_ARGS += \
+ --enable-help \
+ --enable-linenumbers \
+ --enable-multibuffer \
+ --enable-nanorc \
+ --enable-utf8 \
+ --disable-browser \
+ --disable-color \
+ --disable-comment \
+ --disable-extra \
+ --disable-histories \
+ --disable-justify \
+ --disable-libmagic \
+ --disable-mouse \
+ --disable-operatingdir \
+ --disable-speller \
+ --disable-tabcomp \
+ --disable-wordcomp
+else
+# default tiny variant
+ CONFIGURE_ARGS += \
+ --enable-tiny \
+ --enable-linenumbers \
+ --disable-color \
+ --disable-utf8
+endif
+
+CONFIGURE_VARS += \
+ ac_cv_header_regex_h=no \
+
+define Package/nano-plus/conffiles
+/etc/nanorc
+endef
+
+define Package/nano-full/conffiles
+/etc/nanorc
+endef
+
+define Package/nano/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/$(PKG_NAME) $(1)/usr/bin/
+endef
+
+define Package/nano-plus/install
+ $(call Package/nano/install,$1)
+endef
+
+define Package/nano-full/install
+ $(call Package/nano/install,$1)
+ $(INSTALL_DIR) $(1)/etc $(1)/usr/share/nano
+ $(INSTALL_DATA) ./files/nanorc $(1)/etc/nanorc
+ $(INSTALL_DATA) ./files/uci.nanorc $(1)/usr/share/nano
+ $(INSTALL_DATA) ./files/ucode.nanorc $(1)/usr/share/nano
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/nano/* $(1)/usr/share/nano
+endef
+
+$(eval $(call BuildPackage,nano))
+$(eval $(call BuildPackage,nano-plus))
+$(eval $(call BuildPackage,nano-full))
+
diff --git a/external/subpack/utils/nano/files/nanorc b/external/subpack/utils/nano/files/nanorc
new file mode 100644
index 0000000..fd5260c
--- /dev/null
+++ b/external/subpack/utils/nano/files/nanorc
@@ -0,0 +1,8 @@
+## General Settings ##
+set multibuffer # Open multiple files
+set linenumbers # show line numbers Alt+N to toggle
+
+## Syntax highlighting ##
+include /usr/share/nano/*.nanorc
+include /usr/share/nano/extra/*.nanorc
+
diff --git a/external/subpack/utils/nano/files/uci.nanorc b/external/subpack/utils/nano/files/uci.nanorc
new file mode 100644
index 0000000..8d27836
--- /dev/null
+++ b/external/subpack/utils/nano/files/uci.nanorc
@@ -0,0 +1,17 @@
+## Syntax highlighting for OpenWrt uci config files.
+
+syntax uci "/etc/config/*"
+comment "#"
+
+# Keywords
+color green "\<(package|config|option|list)\>"
+
+# Comments.
+color cyan "(^|[[:blank:]])#.*"
+
+# Strings.
+color yellow ""([^"\]|\\.)*"|'([^'\]|\\.)*'"
+
+# Trailing whitespace.
+color ,green "[[:space:]]+$"
+
diff --git a/external/subpack/utils/nano/files/ucode.nanorc b/external/subpack/utils/nano/files/ucode.nanorc
new file mode 100644
index 0000000..647f21d
--- /dev/null
+++ b/external/subpack/utils/nano/files/ucode.nanorc
@@ -0,0 +1,51 @@
+## Syntax highlighting for OpenWrt ucode scripts.
+
+syntax ucode "/ucode/|\.u[ct]$"
+header "^#!.*\<ucode\>"
+comment "//"
+
+# Declarations
+color green "\<(let|const|function|this)\>"
+
+# Arrow functions
+color green "(\<\w+\>|\([[:alnum:][:space:]_,.]*\))[[:space:]]*=>"
+
+# Flow control and keywords
+color brightyellow "\<(while|if|else|elif|switch|case|default|for|in|endif|endfor|endwhile|endfunction)\>"
+color brightyellow "\<(export|import|try|catch|delete)\>"
+
+# Exit points
+color magenta "\<(break|continue|return)\>"
+
+# Numeric literals
+color cyan "\<([0-9]+\.[0-9]+([eE][+-]?[0-9]+)?|[0-9]+[eE][+-]?[0-9]+)\>"
+color cyan "\<0[xX][[:xdigit:]]+(\.[[:xdigit:]]+)?\>"
+color cyan "\<(0[oO][0-7]+|0[bB][01]+|[0-9]+)\>"
+
+# Special values
+color cyan "\<(true|false|null|NaN|Infinity)\>"
+
+# Strings
+color brightmagenta ""([^"\{%#}]|\\.|\{[^"\{%#]|[%#}][^"\}]|[{%#}]\\.)*[{%#}]?""
+color brightmagenta "'([^'\{%#}]|\\.|\{[^'\{%#]|[%#}][^'\}]|[{%#}]\\.)*[{%#}]?'"
+color brightmagenta "`([^`\{%#}]|\\.|\{[^`\{%#]|[%#}][^`\}]|[{%#}]\\.)*[{%#}]?`"
+
+# Template string expressions
+color normal start="\$\{" end="}"
+
+# Comments
+color brightblue "(^|[[:blank:]])//.*"
+color brightblue start="(^|[[:space:]])/\*" end="\*/"
+color brightblue start="\{#" end="#\}"
+
+# Trailing whitespace.
+color ,green "[[:space:]]+$"
+
+# Text outside template directives
+color slate start="[}%#]\}" end="\{[{%#]"
+color slate start="^#!.*(\<utpl\>|[[:space:]]-[[:alnum:]]*T[[:alnum:]]*\>)" end="\{[{%#]"
+color slate "^([^{%#}]|\{[^{%#]|[%#}][^}])+\{[{%#]"
+
+# Template tags
+color white "\{[{%][+-]?|-?[%}]\}"
+color brightblue "\{#[+-]?|-?#\}"
diff --git a/external/subpack/utils/ncdu/Makefile b/external/subpack/utils/ncdu/Makefile
new file mode 100644
index 0000000..bebc50c
--- /dev/null
+++ b/external/subpack/utils/ncdu/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ncdu
+PKG_VERSION:=1.15.1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://dev.yorhel.nl/download
+PKG_HASH:=b02ddc4dbf1db139cc6fbbe2f54a282770380f0ca5c17089855eab52a9ea3fb0
+
+PKG_MAINTAINER:=Charles E. Lehner <cel@celehner.com>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ncdu
+ SUBMENU:=Filesystem
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libncurses
+ TITLE:=ncurses disk usage viewer
+ URL:=https://dev.yorhel.nl/ncdu
+endef
+
+define Package/ncdu/description
+ Ncdu is a ncurses-based du viewer. It provides a fast and easy-to-use
+ interface through famous du utility. It allows one to browse through the
+ directories and show percentages of disk usage with ncurses library.
+endef
+
+define Package/ncdu/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ncdu $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,ncdu))
diff --git a/external/subpack/utils/netwhere/Makefile b/external/subpack/utils/netwhere/Makefile
new file mode 100644
index 0000000..1de3a82
--- /dev/null
+++ b/external/subpack/utils/netwhere/Makefile
@@ -0,0 +1,40 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=netwhere
+PKG_VERSION:=0.9
+PKG_RELEASE:=2
+
+PKG_SOURCE:=netwhere-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/benhsmith/netwhere/archive/$(PKG_VERSION)/
+PKG_HASH:=94a672bdcd9d4455b85429dddd81ffc778e0b26fe87af19ad75c27858ec9dbe2
+
+PKG_MAINTAINER:=Ben Smith <le.ben.smith@gmail.com>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_DEPENDS:=boost
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/netwhere
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Netwhere
+ URL:=https://github.com/benhsmith/netwhere
+ DEPENDS:=+libtins +libmicrohttpd
+endef
+
+define Package/netwhere/description
+ Network monitor
+endef
+
+define Package/netwhere/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/netwhere $(1)/usr/bin/netwhere
+ $(INSTALL_DIR) $(1)/www/netwhere
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/html/index.html $(1)/www/netwhere/
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/html/netwhere.js $(1)/www/netwhere/
+endef
+
+$(eval $(call BuildPackage,netwhere))
diff --git a/external/subpack/utils/netwhere/patches/010-libmicrohttpd.patch b/external/subpack/utils/netwhere/patches/010-libmicrohttpd.patch
new file mode 100644
index 0000000..8592e24
--- /dev/null
+++ b/external/subpack/utils/netwhere/patches/010-libmicrohttpd.patch
@@ -0,0 +1,27 @@
+--- a/webservice.hpp
++++ b/webservice.hpp
+@@ -38,13 +38,13 @@ class WebService {
+ MHD_Daemon* daemon;
+ Functor functor;
+
+- static int on_request(void * cls, struct MHD_Connection * connection, const char * url, const char * method, const char * version,
++ static enum MHD_Result on_request(void * cls, struct MHD_Connection * connection, const char * url, const char * method, const char * version,
+ const char * upload_data, size_t * upload_data_size,
+ void ** ptr);
+ };
+
+ template <typename Functor>
+-int WebService<Functor>::on_request(void * cls,
++enum MHD_Result WebService<Functor>::on_request(void * cls,
+ struct MHD_Connection * connection,
+ const char * url,
+ const char * method,
+@@ -53,7 +53,7 @@ int WebService<Functor>::on_request(void
+ size_t * upload_data_size,
+ void ** ptr) {
+ static int dummy;
+- int ret;
++ enum MHD_Result ret;
+
+ if (std::string("GET") != method)
+ return MHD_NO; /* unexpected method */
diff --git a/external/subpack/utils/nnn/Makefile b/external/subpack/utils/nnn/Makefile
new file mode 100644
index 0000000..1db0b32
--- /dev/null
+++ b/external/subpack/utils/nnn/Makefile
@@ -0,0 +1,38 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=nnn
+PKG_VERSION:=4.2
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/jarun/nnn/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=5675f9fe53bddfd92681ef88bf6c0fab3ad897f9e74dd6cdff32fe1fa62c687f
+
+PKG_MAINTAINER:=Josef Schlehofer <pepe.schlehofer@gmail.com>
+PKG_LICENSE:=BSD-2-Clause
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/nnn
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Full-featured terminal file manager
+ URL:=https://github.com/jarun/nnn
+ DEPENDS:=+libncurses +libreadline +musl-fts
+endef
+
+define Package/nnn/description
+ nnn is full-featured tiny terminal file manager and
+ disk usage analyzer, fuzzy app launcher, batch file renamer
+ and file picker.
+endef
+
+define Package/nnn/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/nnn $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,nnn))
diff --git a/external/subpack/utils/nnn/patches/musl-fts.patch b/external/subpack/utils/nnn/patches/musl-fts.patch
new file mode 100644
index 0000000..5f15c57
--- /dev/null
+++ b/external/subpack/utils/nnn/patches/musl-fts.patch
@@ -0,0 +1,11 @@
+--- a/Makefile
++++ b/Makefile
+@@ -129,7 +129,7 @@ CFLAGS += -std=c11 -Wall -Wextra -Wshado
+ CFLAGS += $(CFLAGS_OPTIMIZATION)
+ CFLAGS += $(CFLAGS_CURSES)
+
+-LDLIBS += $(LDLIBS_CURSES) -lpthread
++LDLIBS += $(LDLIBS_CURSES) -lpthread -lfts
+
+ # static compilation needs libgpm development package
+ ifeq ($(strip $(O_STATIC)),1)
diff --git a/external/subpack/utils/ntfs-3g/Makefile b/external/subpack/utils/ntfs-3g/Makefile
new file mode 100644
index 0000000..d237c25
--- /dev/null
+++ b/external/subpack/utils/ntfs-3g/Makefile
@@ -0,0 +1,217 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ntfs-3g
+PKG_VERSION:=2022.10.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)_ntfsprogs-$(PKG_VERSION).tgz
+PKG_SOURCE_URL:=https://www.tuxera.com/opensource/
+PKG_HASH:=f20e36ee68074b845e3629e6bced4706ad053804cbaf062fbae60738f854170c
+
+PKG_MAINTAINER:=Ted Hess <thess@kitschensync.net>
+PKG_LICENSE:=GPL-2.0-only LGPL-2.1-or-later
+PKG_LICENSE_FILES:=COPYING COPYING.LIB
+PKG_CPE_ID:=cpe:/a:tuxera:ntfs-3g
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+# release contains fuseext/int hint
+PKG_RELEASE:=$(PKG_RELEASE)$(if $(CONFIG_PACKAGE_NTFS-3G_USE_LIBFUSE),-fuseext,-fuseint)
+
+# define build dir, respect fuseext/int
+PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ntfs-3g/common
+ SECTION:=utils
+ CATEGORY:=Utilities
+ URL:=https://www.tuxera.com
+ SUBMENU:=Filesystem
+ TITLE:=Stable Read/Write NTFS Driver
+endef
+
+define Package/ntfs-3g
+ $(call Package/ntfs-3g/common)
+ DEPENDS+= +kmod-fuse +PACKAGE_NTFS-3G_USE_LIBFUSE:libfuse +libpthread
+endef
+
+define Package/ntfs-3g/description
+ Ntfs-3g is a NTFS driver, which can create, remove, rename,
+ move files, directories, hard links, and streams. It can read
+ and write files, including streams and sparse files. It can
+ handle special files like symbolic links, devices, and FIFOs.
+ Moreover it can also read transparently compressed files.
+
+ Contains:
+ - ntfs-3g
+ - ntfs-3g.probe
+ - mount.ntfs-3g (symlink to ntfs-3g)
+
+endef
+
+define Package/ntfs-3g/config
+config PACKAGE_NTFS-3G_USE_LIBFUSE
+ bool "use external FUSE library, selects package libfuse"
+ depends on PACKAGE_ntfs-3g
+ help
+ Ntfs-3g by default uses a minimalized lite version of FUSE.
+ If libfuse is part of your filesystem anyway (because of sshfs, owfs
+ etc.) it makes sense to activate this option and save some kilobytes
+ of space.
+
+config PACKAGE_NTFS-3G_HAS_PROBE
+ bool "install the ntfs-3g.probe utility"
+ depends on PACKAGE_ntfs-3g
+ default y
+endef
+
+define Package/ntfs-3g-low
+ $(call Package/ntfs-3g/common)
+ TITLE:=lowntfs-3g (alternative using the fuse low-level interface)
+ DEPENDS+= +ntfs-3g
+endef
+
+define Package/ntfs-3g-low/description
+ Contains:
+ - lowntfs-3g
+ - mount.lowntfs-3g (symlink to lowntfs-3g)
+
+ A driver variant using the fuse low-level interface missing some of the
+ enhanced functionality for streams or the like. You might want to check:
+ http://www.tuxera.com/community/ntfs-3g-manual/
+
+endef
+
+
+define Package/ntfs-3g-utils/description
+ Suite of NTFS utilities for doing neat things with NTFS.
+ Contains:
+ - mkntfs - Create an NTFS filesystem.
+ - ntfscat - Dump a file's content to the standard output.
+ - ntfsclone - Efficiently clone, backup, restore or rescue NTFS.
+ - ntfscluster - Locate the files which use the given sectors or clusters.
+ - ntfscmp - Compare two NTFS filesystems and tell the differences.
+ - ntfscp - Copy a file to an NTFS volume.
+ - ntfssecaudit - Display ownership and permissions, check consistency
+ - ntfsfix - Check and fix some common errors, clear the LogFile.
+ - ntfsinfo - Show information about NTFS or one of the files or directories within it.
+ - ntfslabel - Show, or set, an NTFS filesystem's volume label.
+ - ntfsls - List information about files in a directory residing on an NTFS.
+ - ntfsresize - Resize NTFS without losing data.
+ - ntfsundelete - Recover deleted files from NTFS.
+ - ntfsusermap - Define mapping of Windows accounts to Linux logins
+endef
+
+define Package/ntfs-3g-utils
+ $(call Package/ntfs-3g/common)
+ TITLE:=ntfs-3g utilities
+ DEPENDS+= +ntfs-3g +libgcrypt +libuuid
+endef
+
+CONFIGURE_ARGS += \
+ --enable-shared \
+ --enable-static \
+ --with-uuid
+
+# configure/make according selection
+ifdef CONFIG_PACKAGE_NTFS-3G_USE_LIBFUSE
+ CONFIGURE_ARGS += --with-fuse=external
+ TARGET_CPPFLAGS:=-I$(STAGING_DIR)/usr/include/fuse $(TARGET_CPPFLAGS)
+else
+ CONFIGURE_ARGS += --with-fuse=internal
+ TARGET_CPPFLAGS:=-I../include/fuse-lite $(TARGET_CPPFLAGS)
+endif
+
+# enable ntfsprogs and extras
+ifneq ($(CONFIG_PACKAGE_ntfs-3g-utils)$(SDK)$(DEVELOPER),)
+ CONFIGURE_ARGS += --enable-ntfsprogs --enable-extras
+else
+ CONFIGURE_ARGS += --disable-ntfsprogs --disable-extras
+endif
+
+# redefine prepare to extract to our build dir
+# apply patches
+define Build/Prepare
+ rm -rf $(PKG_BUILD_DIR)/
+ mkdir -p $(PKG_BUILD_DIR)/
+ $(TAR) -xzf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR) --strip 1
+ $(Build/Patch)
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/ntfs-3g $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libntfs-3g.{la,a,so*} $(1)/usr/lib/
+endef
+
+define Package/ntfs-3g/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ntfs-3g $(1)/usr/bin/
+ $(if $(CONFIG_PACKAGE_NTFS-3G_HAS_PROBE),$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ntfs-3g.probe $(1)/usr/bin/,)
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libntfs-3g.so.* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/sbin
+ $(LN) ../usr/bin/ntfs-3g $(1)/sbin/mount.ntfs-3g
+endef
+
+define Package/ntfs-3g/postinst
+#!/bin/sh
+FILE="$${IPKG_INSTROOT}/etc/filesystems"
+ID="ntfs-3g"
+
+if ! [ -f '/etc/filesystems' ]; then
+ echo "Create '$$FILE'."
+ touch "$$FILE"
+fi
+
+if ! grep -q -e '^ntfs-3g$$' "$$FILE"; then
+ echo "Add '$$ID' to known filesystems."
+ echo "$$ID" >> "$$FILE"
+fi
+
+endef
+
+define Package/ntfs-3g-low/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lowntfs-3g $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/sbin
+ $(LN) ../usr/bin/lowntfs-3g $(1)/sbin/mount.lowntfs-3g
+endef
+
+define Package/ntfs-3g-low/postinst
+#!/bin/sh
+FILE="$${IPKG_INSTROOT}/etc/filesystems"
+ID="lowntfs-3g"
+
+if ! [ -f '/etc/filesystems' ]; then
+ echo "Create '$$FILE'."
+ touch "$$FILE"
+fi
+
+if ! grep -q -e '^ntfs-3g$$' "$$FILE"; then
+ echo "Add '$$ID' to known filesystems."
+ echo "$$ID" >> "$$FILE"
+fi
+
+endef
+
+define Package/ntfs-3g-utils/install
+ rm -f $(PKG_INSTALL_DIR)/usr/sbin/mkfs.ntfs
+ $(INSTALL_DIR) $(1)/usr/{bin,sbin}
+ $(FIND) $(PKG_INSTALL_DIR)/usr/bin/ -type f ! -regex '.*[^/]*ntfs-3g[^/]*' -exec $(INSTALL_BIN) {} $(1)/usr/bin/ \;
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/* $(1)/usr/sbin/
+ $(LN) mkntfs $(1)/usr/sbin/mkfs.ntfs
+endef
+
+$(eval $(call BuildPackage,ntfs-3g))
+$(eval $(call BuildPackage,ntfs-3g-low))
+$(eval $(call BuildPackage,ntfs-3g-utils))
diff --git a/external/subpack/utils/ntfs-3g/patches/001-fuseint-fix-path-mounted-on-musl.patch b/external/subpack/utils/ntfs-3g/patches/001-fuseint-fix-path-mounted-on-musl.patch
new file mode 100644
index 0000000..96cbb1e
--- /dev/null
+++ b/external/subpack/utils/ntfs-3g/patches/001-fuseint-fix-path-mounted-on-musl.patch
@@ -0,0 +1,26 @@
+--- a/libfuse-lite/fusermount.c
++++ b/libfuse-lite/fusermount.c
+@@ -37,6 +37,10 @@
+
+ #define FUSE_DEV_NEW "/dev/fuse"
+
++#ifndef _PATH_MOUNTED
++#define _PATH_MOUNTED "/proc/mounts"
++#endif
++
+ #ifndef MS_DIRSYNC
+ #define MS_DIRSYNC 128
+ #endif
+--- a/libfuse-lite/mount_util.c
++++ b/libfuse-lite/mount_util.c
+@@ -264,6 +264,10 @@ int fuse_mnt_check_fuseblk(void)
+
+ #else /* __SOLARIS__ */
+
++#ifndef _PATH_MOUNTED
++#define _PATH_MOUNTED "/proc/mounts"
++#endif /* _PATH_MOUNTED */
++
+ static int mtab_needs_update(const char *mnt)
+ {
+ int res;
diff --git a/external/subpack/utils/oath-toolkit/Makefile b/external/subpack/utils/oath-toolkit/Makefile
new file mode 100644
index 0000000..ebee2ec
--- /dev/null
+++ b/external/subpack/utils/oath-toolkit/Makefile
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=oath-toolkit
+PKG_VERSION:=2.6.5
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SAVANNAH/oath-toolkit
+PKG_HASH:=d207120c7e7fdd540142d04ca06d83fb3277c8f2fb794a74535d04b2aa0ec219
+
+PKG_MAINTAINER:=Fam Zheng <fam@euphon.net>
+PKG_LICENSE:=LGPL-2.0-or-later GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:nongnu:oath_toolkit
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+CONFIGURE_ARGS += \
+ --disable-xmltest \
+ --disable-pskc
+
+define Package/oath-toolkit
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Toolkit for building one-time password authentication
+ URL:=http://www.nongnu.org/oath-toolkit/index.html
+ DEPENDS:=
+endef
+
+define Package/oath-toolkit/description
+ The OATH Toolkit provide components for building one-time password
+ authentication systems. It contains shared libraries, command line
+ tools and a PAM module. Supported technologies include the event-based
+ HOTP algorithm (RFC4226) and the time-based TOTP algorithm (RFC6238).
+endef
+
+define Package/oath-toolkit/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/oathtool $(1)/usr/bin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/liboath.so* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,oath-toolkit))
diff --git a/external/subpack/utils/oci-runtime-tools/Makefile b/external/subpack/utils/oci-runtime-tools/Makefile
new file mode 100644
index 0000000..6621ece
--- /dev/null
+++ b/external/subpack/utils/oci-runtime-tools/Makefile
@@ -0,0 +1,85 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=oci-runtime-tools
+PKG_VERSION:=1.0.0-pre20210122
+PKG_RELEASE:=2
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_NAME:=runtime-tools
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/opencontainers/runtime-tools.git
+PKG_SOURCE_VERSION:=453547deb724af135587e654f52d86b8619f21b9
+PKG_MIRROR_HASH:=34f3aefc4f6f3bb93330ec7cbeb2eb987b82184da53d453e8b04b5750faa8728
+
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/opencontainers/runtime-tools/
+GO_PKG_LDFLAGS_X:=main.gitCommit=$(PKG_SOURCE_VERSION) main.version=$(PKG_SOURCE_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/oci-runtime-tool
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=oci-runtime-tool
+ URL:=https://github.com/opencontainers/runtime-tools
+ DEPENDS:=$(GO_ARCH_DEPENDS)
+endef
+
+define Package/oci-runtime-tool/description
+ OCI (Open Container Initiative) runtime tools
+ Generate OCI runtime spec configuration files and validate OCI bundles.
+endef
+
+define Package/oci-runtime-tests
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=OCI runtimetest tool
+ URL:=https://github.com/opencontainers/runtime-tools
+ DEPENDS:=@(i386||i686||x86_64) oci-runtime-tool +tar
+endef
+
+define Package/oci-runtime-tests/description
+ OCI (Open Container Initiative) runtime tools
+ This package provides test cases as well as artifacts required to
+ validate an OCI runtime.
+ Best used in combination with a TAP consumer like 'node-tap',
+ installable via npm.
+endef
+
+GO_PKG_BUILD_VARS += GO111MODULE=auto
+
+define Build/Compile
+ $(call GoPackage/Build/Compile)
+ $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
+endef
+
+define Package/oci-runtime-tool/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/oci-runtime-tool $(1)/usr/bin
+endef
+
+define Package/oci-runtime-tests/install
+ $(INSTALL_DIR) $(1)/usr/libexec/oci-runtime-test
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/runtimetest $(1)/usr/libexec/oci-runtime-test/
+ ( cd $(PKG_BUILD_DIR) ; $(FIND) ./validation/ -name *.go | grep -v util | \
+ xargs -I'%' -n 1 basename % .go | while read testbin; do \
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/$$$${testbin} \
+ $(1)/usr/libexec/oci-runtime-test/$$$${testbin}.t ; \
+ done )
+ifdef CONFIG_x86_64
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/rootfs-amd64.tar.gz $(1)/usr/libexec/oci-runtime-test
+endif
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/rootfs-386.tar.gz $(1)/usr/libexec/oci-runtime-test
+endef
+
+$(eval $(call GoBinPackage,oci-runtime-tools))
+$(eval $(call BuildPackage,oci-runtime-tool))
+$(eval $(call BuildPackage,oci-runtime-tests))
diff --git a/external/subpack/utils/oci-runtime-tools/patches/001-fix-32-bit-build.patch b/external/subpack/utils/oci-runtime-tools/patches/001-fix-32-bit-build.patch
new file mode 100644
index 0000000..7bb6c9c
--- /dev/null
+++ b/external/subpack/utils/oci-runtime-tools/patches/001-fix-32-bit-build.patch
@@ -0,0 +1,39 @@
+From 6502e57dbebcacd9b55fc7a80655c8f31d7dae8f Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Mon, 8 Feb 2021 01:26:31 +0000
+Subject: [PATCH] Fix build of hugetlb tests on 32-bit platforms
+
+https://github.com/opencontainers/runtime-tools/pull/712
+
+Use explicit 64-bit types to avoid fall-back on incompatible 32-bit
+types on 32-bit platforms.
+
+Fixes: #711
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+---
+ validation/linux_cgroups_hugetlb/linux_cgroups_hugetlb.go | 2 +-
+ .../linux_cgroups_relative_hugetlb.go | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/validation/linux_cgroups_hugetlb/linux_cgroups_hugetlb.go
++++ b/validation/linux_cgroups_hugetlb/linux_cgroups_hugetlb.go
+@@ -24,7 +24,7 @@ func testHugetlbCgroups() error {
+ // When setting the limit just for checking if writing works, the amount of memory
+ // requested does not matter, as all insigned integers will be accepted.
+ // Use 2GiB as an example
+- const limit = 2 * (1 << 30)
++ var limit uint64 = 2 * (1 << 30)
+
+ for _, pageSize := range pageSizes {
+ g, err := util.GetDefaultGenerator()
+--- a/validation/linux_cgroups_relative_hugetlb/linux_cgroups_relative_hugetlb.go
++++ b/validation/linux_cgroups_relative_hugetlb/linux_cgroups_relative_hugetlb.go
+@@ -21,7 +21,7 @@ func main() {
+ // When setting the limit just for checking if writing works, the amount of memory
+ // requested does not matter, as all insigned integers will be accepted.
+ // Use 2GiB as an example
+- const limit = 2 * (1 << 30)
++ var limit uint64 = 2 * (1 << 30)
+
+ for _, pageSize := range pageSizes {
+ g, err := util.GetDefaultGenerator()
diff --git a/external/subpack/utils/open-plc-utils/Makefile b/external/subpack/utils/open-plc-utils/Makefile
new file mode 100644
index 0000000..d607b3d
--- /dev/null
+++ b/external/subpack/utils/open-plc-utils/Makefile
@@ -0,0 +1,103 @@
+#
+# Copyright (C) 2013-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=open-plc-utils
+PKG_RELEASE:=4
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/qca/open-plc-utils.git
+PKG_SOURCE_VERSION:=bb50f635ef6cec8b52898051e0d18f4ac3fdd331
+PKG_MIRROR_HASH:=1fc202ee33fd768d631e5834ac62461e7b544251914d797d868b0de7f33b785b
+
+PKG_MAINTAINER:=Michael Heimpold <mhei@heimpold.de>
+
+PKG_LICENSE:=ISC
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/open-plc-utils/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Qualcomm Atheros Power Line Communication utilities
+ URL:=https://github.com/qca/open-plc-utils/blob/master/README
+endef
+
+define Package/open-plc-utils
+ $(call Package/open-plc-utils/Default)
+ MENU:=1
+endef
+
+define GenPlugin
+ define Package/$(addprefix open-plc-utils-,$(1))
+ $(call Package/open-plc-utils/Default)
+ DEPENDS:=open-plc-utils
+ TITLE:=Utility $(1) from the Open PLC utilities
+ endef
+
+ define Package/$(addprefix open-plc-utils-,$(1))/description
+ Utility $(1) from the Open PLC utilities package.
+ endef
+endef
+
+OPEN_PLC_UTILS_APPS:=efbu efeu efru efsu edru edsu nics \
+ hpavkey hpavkeys rkey mac2pw mac2pwd \
+ mdioblock mdioblock2 mdiodump mdiogen \
+ hpav mme \
+ chknvm chknvm2 nvmsplit nvmmerge \
+ chkpib chkpib2 setpib getpib modpib pib2xml \
+ pibcomp pibdump pibruin xml2pib psin psout pskey \
+ psgraph psnotch pibrump \
+ int6k int6kboot int6keth int6kf int6khost \
+ int64host int6kid int6klist int6klog int6kmdio \
+ int6kmdio2 int6kmod int6kstat int6ktest int6krate \
+ int6krule int6ktone int6kwait CMEncrypt sada \
+ coqos_add coqos_info coqos_man coqos_mod coqos_rel \
+ mdustats ampboot amphost ampID amplist amprate amprule \
+ ampstat amptest amptool amptone ampwait \
+ plcboot plchost plcID plclist plcrate plcrule \
+ plcstat plctest plctool plctone \
+ plcwait plchostd plcget plcset plcotst plcfwd \
+ plcdevs plclog plcmdio16 plcmdio32 \
+ config2cfg sdram \
+ int6kuart int6kbaud ttysig ptsctl weeder ttysend \
+ ttyrecv ttycat int6kdetect \
+ pev evse
+
+$(foreach a,$(OPEN_PLC_UTILS_APPS),$(eval $(call GenPlugin,$(a))))
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ EXTRA_CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
+ LDFLAGS="$(TARGET_CFLAGS) $(TARGET_LDFLAGS)" \
+ CROSS="$(TARGET_CROSS)" \
+ ROOTFS="$(PKG_INSTALL_DIR)" \
+ OWNER="$(shell id -u $(shell whoami))" \
+ GROUP="$(shell id -g $(shell whoami))" \
+ all install
+endef
+
+define Package/open-plc-utils/install
+ true
+endef
+
+define BuildPlugin
+ define Package/$(1)/install
+ $(INSTALL_DIR) $$(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/local/bin/$(subst open-plc-utils-,,$(1)) \
+ $$(1)/usr/bin/
+ endef
+
+ $$(eval $$(call BuildPackage,$(1)))
+endef
+
+$(eval $(call BuildPackage,open-plc-utils))
+$(foreach a,$(OPEN_PLC_UTILS_APPS),$(eval $(call BuildPlugin,open-plc-utils-$(a))))
diff --git a/external/subpack/utils/open2300/Makefile b/external/subpack/utils/open2300/Makefile
new file mode 100644
index 0000000..fcbf5d8
--- /dev/null
+++ b/external/subpack/utils/open2300/Makefile
@@ -0,0 +1,62 @@
+#
+# Copyright (C) 2010 segal.ubi.pt
+# Copyright (C) 2014 nunojpg@gmail.com
+# Copyright (C) 2015 dev@localnet.hu
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=open2300
+PKG_SOURCE_DATE:=2014-03-04
+PKG_SOURCE_VERSION:=1af8ae609da66f8e1b745533c19095c9758bfb0b
+PKG_RELEASE:=2
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/wezm/open2300
+PKG_MIRROR_HASH:=3287ca1c70e736dd1c6c3abb01e0d986f91573c7c54b9adabdc437309dc4fd56
+
+PKG_MAINTAINER:=Gabor SZOLLOSI <dev@localnet.hu>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/open2300
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=WS23XX weather station utilities
+ URL:=http://www.lavrsen.dk/foswiki/bin/view/Open2300
+endef
+
+define Package/open2300/description
+ This is an utility suite used to communicate with and collect data from a WS23XX wheather station.
+endef
+
+define Package/open2300/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/bin2300 $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/cw2300 $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/dump2300 $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/fetch2300 $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/histlog2300 $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/history2300 $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/interval2300 $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/light2300 $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/log2300 $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/minmax2300 $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/open2300 $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/wu2300 $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/xml2300 $(1)/usr/bin/
+
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_DATA) ./files/open2300.conf $(1)/etc/
+
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/lib2300.so.1.11 $(1)/usr/lib/
+ $(LN) lib2300.so.1.11 $(1)/usr/lib/lib2300.so
+endef
+
+$(eval $(call BuildPackage,open2300))
diff --git a/external/subpack/utils/open2300/files/open2300.conf b/external/subpack/utils/open2300/files/open2300.conf
new file mode 100644
index 0000000..6414b49
--- /dev/null
+++ b/external/subpack/utils/open2300/files/open2300.conf
@@ -0,0 +1,65 @@
+# open2300.conf
+#
+# Configuration files for open2300 weather station tools
+#
+# Default locations in which the programs will search for this file:
+# Programs search in this sequence:
+# 1. Path to config file including filename given as parameter (not supported by all tools)
+# 2. ./open2300.conf (current working directory)
+# 3. /jffs/etc/open2300.conf (typical DD-WRT location)
+# 4. /etc/open2300.conf (typical Linux location)
+#
+# All names are case sensitive!!!
+
+
+# Set to your serial port and time zone
+# For Windows use COM1, COM2, COM2 etc
+# For Linux use /dev/ttyS0, /dev/ttyS1 etc
+
+SERIAL_DEVICE /dev/tts/1 # /dev/ttyS0, /dev/ttyS1, COM1, COM2 etc
+TIMEZONE 1 # Hours Relative to UTC. East is positive, west is negative
+
+
+# Units of measure (set them to your preference)
+# The units of measure are ignored by wu2300 and cw2300 because both requires specific units
+
+WIND_SPEED m/s # select MPH (miles/hour), m/s, or km/h
+TEMPERATURE C # Select C or F
+RAIN mm # Select mm or IN
+PRESSURE hPa # Select hPa, mb or INHG
+
+
+#### Citizens Weather variables (used only by cw2300)
+# Format for latitude is
+# [2 digit degrees][2 digit minutes].[2 decimals minutes - NOT seconds][N for north or S for south]
+# Format for longitude is
+# [3 digit degrees][2 digit minutes].[2 decimals minutes - NOT seconds][E for east or W for west]
+# Use leading zeros to get the format ####.##N (lat) and #####.##E (long)
+
+CITIZEN_WEATHER_ID CW0000 # CW0000 should be replaced by HAM call or actual CW number
+CITIZEN_WEATHER_LATITUDE 5540.12N # DDMM.mmN or S - example 55 deg, 40.23 minutes north
+CITIZEN_WEATHER_LONGITUDE 01224.60E # DDDMM.mmE or W - example 12 deg, 24.60 minutes east
+
+APRS_SERVER rotate.aprs.net 14580 # These are the APRS servers and ports for
+APRS_SERVER first.aprs.net 14580 # Citizens Weather reporting.
+APRS_SERVER second.aprs.net 14580 # They they are tried in the entered order
+APRS_SERVER third.aprs.net 14580 # you may enter up to 5 alternate servers
+
+
+#### WEATHER UNDERGROUND variables (used only by wu2300)
+
+WEATHER_UNDERGROUND_ID WUID # ID received from Weather Underground
+WEATHER_UNDERGROUND_PASSWORD WUPASSWORD # Password for Weather Underground
+
+
+### MYSQL Settings (only used by mysql2300)
+
+#MYSQL_HOST localhost # Localhost or IP address/host name
+#MYSQL_USERNAME open2300 # Name of the MySQL user that has access to the database
+#MYSQL_PASSWORD mysql2300 # Password for the MySQL user
+#MYSQL_DATABASE open2300 # Named of your database
+#MYSQL_PORT 0 # TCP/IP Port number. Zero means default
+
+#PGSQL_CONNECT hostaddr='127.0.0.1'dbname='open2300'user='postgres'password='sql' # Connection string
+#PGSQL_TABLE weather # Table name
+#PGSQL_STATION open2300 # Unique station id
diff --git a/external/subpack/utils/openobex/Makefile b/external/subpack/utils/openobex/Makefile
new file mode 100644
index 0000000..2501bfa
--- /dev/null
+++ b/external/subpack/utils/openobex/Makefile
@@ -0,0 +1,90 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=openobex
+PKG_VERSION:=1.7.2
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-Source.tar.gz
+PKG_SOURCE_URL:=@SF/openobex
+PKG_HASH:=158860aaea52f0fce0c8e4b64550daaae06df2689e05834697b7e8c7d73dd4fc
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-Source
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-2.0-or-later LGPL-2.1-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:openobex:openobex
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/openobex/Default
+ TITLE:=Open Source impl of the OBject EXchange protocol
+ URL:=https://www.gitorious.org/openobex
+endef
+
+define Package/openobex
+$(call Package/openobex/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE+= (meta)
+ DEPENDS:=+openobex-apps +libopenobex
+endef
+
+define Package/openobex-apps
+$(call Package/openobex/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE+= (apps)
+ DEPENDS:=+libopenobex +bluez-libs
+endef
+
+define Package/libopenobex
+$(call Package/openobex/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+= (library)
+ DEPENDS:=+libusb-1.0
+endef
+
+CMAKE_OPTIONS += \
+ -DBUILD_DOCUMENTATION:BOOL=OFF \
+
+MAKE_FLAGS += \
+ openobex openobex-apps \
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/openobex $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libopenobex.so* $(1)/usr/lib/
+ $(CP) $(PKG_BUILD_DIR)/apps/lib/libopenobex-apps-common.a $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/openobex.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/openobex/install
+ :
+endef
+
+define Package/openobex-apps/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/* $(1)/usr/sbin/
+endef
+
+define Package/libopenobex/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libopenobex.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,openobex))
+$(eval $(call BuildPackage,openobex-apps))
+$(eval $(call BuildPackage,libopenobex))
diff --git a/external/subpack/utils/openobex/patches/001-cxx.patch b/external/subpack/utils/openobex/patches/001-cxx.patch
new file mode 100644
index 0000000..2b41b08
--- /dev/null
+++ b/external/subpack/utils/openobex/patches/001-cxx.patch
@@ -0,0 +1,11 @@
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -1,7 +1,7 @@
+ cmake_minimum_required ( VERSION 3.1 FATAL_ERROR )
+
+ project ( openobex
+- LANGUAGES C
++ LANGUAGES C CXX
+ VERSION 1.7.2
+ )
+
diff --git a/external/subpack/utils/openocd/Makefile b/external/subpack/utils/openocd/Makefile
new file mode 100644
index 0000000..2581fe6
--- /dev/null
+++ b/external/subpack/utils/openocd/Makefile
@@ -0,0 +1,92 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=openocd
+PKG_SOURCE_VERSION:=v0.11.0-rc1
+PKG_VERSION:=$(PKG_SOURCE_VERSION)
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_URL:=git://git.code.sf.net/p/openocd/code
+PKG_MIRROR_HASH:=c4a0a6cad821946608c843f557b993e7cfeb0f193e4c0f149ebfbfbfd57054a6
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=COPYING
+
+PKG_MAINTAINER:=Paul Fertser <fercerpav@gmail.com>
+PKG_CPE_ID:=cpe:/a:openocd:open_on-chip_debugger
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+PKG_FIXUP:=autoreconf
+
+PKG_CONFIG_DEPENDS:=CONFIG_PACKAGE_openocd_with_usb
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/openocd
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=OpenOCD Utility
+ URL:=http://openocd.sf.net/
+ DEPENDS:=+libusb-1.0 \
+ +libusb-compat \
+ +libftdi1 \
+ +hidapi \
+ +libgpiod
+endef
+
+define Package/openocd/description
+OpenOCD provides on-chip programming and debugging support with a
+layered architecture of JTAG interface and TAP support including:
+
+- (X)SVF playback to facilitate automated boundary scan and FPGA/CPLD
+ programming;
+- debug target support (e.g. ARM, MIPS): single-stepping,
+ breakpoints/watchpoints, gprof profiling, etc;
+- flash chip drivers (e.g. CFI, NAND, internal flash);
+- embedded TCL interpreter for easy scripting.
+
+Several network interfaces are available for interacting with OpenOCD:
+telnet, TCL, and GDB. The GDB server enables OpenOCD to function as a
+"remote target" for source-level debugging of embedded systems using
+the GNU GDB program (and the others who talk GDB protocol, e.g. IDA
+Pro).
+endef
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ -$(RM) $(PKG_BUILD_DIR)/guess-rev.sh
+endef
+
+CONFIGURE_ARGS += \
+ --prefix="/usr" \
+ --disable-werror \
+ MAKEINFO=true \
+ --enable-dummy \
+ --enable-sysfsgpio \
+ --enable-linuxgpiod
+
+TARGET_CFLAGS += -DRELSTR=\\\"-$(PKG_VERSION)-$(PKG_RELEASE)-OpenWrt\\\"
+
+define Build/Compile
+ +$(MAKE_VARS) \
+ $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/$(MAKE_PATH)
+endef
+
+define Package/openocd/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_DIR) $(1)/usr/share/openocd
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/openocd $(1)/usr/bin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/openocd/scripts $(1)/usr/share/openocd
+endef
+
+$(eval $(call BuildPackage,openocd))
diff --git a/external/subpack/utils/opensc/Makefile b/external/subpack/utils/opensc/Makefile
new file mode 100644
index 0000000..1d84b1f
--- /dev/null
+++ b/external/subpack/utils/opensc/Makefile
@@ -0,0 +1,228 @@
+#
+# Copyright (C) 2011-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=opensc
+PKG_VERSION:=0.22.0
+PKG_RELEASE:=$(AUTORELEASE)
+PKG_HASH:=8d4e5347195ebea332be585df61dcc470331c26969e4b0447c851fb0844c7186
+
+PKG_LICENSE:=LGPL-2.1-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+PKG_SOURCE_URL:=https://github.com/OpenSC/OpenSC/releases/download/$(PKG_VERSION)/
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+
+PKG_BUILD_DEPENDS:=pcsc-lite
+PKG_FIXUP:=libtool
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libopensc
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=OpenSC libraries for smart cards
+ URL:=https://github.com/OpenSC/OpenSC/wiki
+ DEPENDS:=+libopenssl +libpthread +zlib
+ MENU:=1
+endef
+
+define Package/libopensc/description
+ OpenSC provides a set of libraries and utilities to work with smart cards.
+ Its main focus is on cards that support cryptographic operations, and
+ facilitate their use in security applications such as authentication,
+ mail encryption and digital signatures.
+endef
+
+define Package/libopensc-pkcs11
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=OpenSC - PKCS11 provider
+ URL:=https://github.com/OpenSC/OpenSC/wiki
+ DEPENDS:=libopensc
+endef
+
+define Package/libopensc-pkcs11/description
+ OpenSC PKCS#11 provider
+endef
+
+define Package/libpkcs11-spy
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=PKCS11 spying wrapper
+ URL:=https://github.com/OpenSC/OpenSC/wiki
+ DEPENDS:=+libopenssl +libpthread
+endef
+
+define Package/libpkcs11-spy/dscription
+ PKCS#11 spying wrapper
+endef
+
+define Package/opensc-utils
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=OpenSC - tools for smart cards
+ URL:=https://github.com/OpenSC/OpenSC/wiki
+ DEPENDS:=+libopensc
+ MENU:=1
+endef
+
+define Package/opensc-utils/description
+ OpenSC utilities
+endef
+
+define ToolGen
+define Package/opensc-utils-$(subst _,-,$(firstword $(subst :, ,$(1))))
+ TITLE:=$(firstword $(subst :, ,$(1))) utility from opensc
+ URL:=https://github.com/OpenSC/OpenSC/wiki
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=opensc-utils $(wordlist 2,$(words $(subst :, ,$(1))),$(subst :, ,$(1)))
+endef
+endef
+
+define ProfileGen
+define Package/libopensc-profile-$(subst _,-,$(firstword $(subst :, ,$(1))))
+ TITLE:=$(firstword $(subst :, ,$(1))) card profile for opensc
+ URL:=https://github.com/OpenSC/OpenSC/wiki
+ SECTION:=libs
+ CATEGORY:=Libraries
+ DEPENDS:=libopensc
+endef
+endef
+
+CONFIGURE_ARGS += \
+ --disable-notify \
+ --disable-strict
+
+TOOLS:= \
+ cardos-tool \
+ cryptoflex-tool \
+ dnie-tool \
+ eidenv \
+ iasecc-tool \
+ netkey-tool \
+ openpgp-tool \
+ opensc-tool \
+ opensc-explorer:+libncurses:+libreadline \
+ piv-tool \
+ pkcs11-tool \
+ pkcs15-crypt \
+ pkcs15-init \
+ pkcs15-tool \
+ sc-hsm-tool \
+ westcos-tool
+
+PROFILES:= \
+ asepcos \
+ authentic \
+ cardos \
+ cyberflex \
+ entersafe \
+ epass2003 \
+ flex \
+ gpk \
+ ias_adele_admin1 \
+ ias_adele_admin2 \
+ ias_adele_common \
+ iasecc_admin_eid \
+ iasecc_generic_oberthur \
+ iasecc_generic_pki \
+ iasecc \
+ incrypto34 \
+ jcop \
+ miocos \
+ muscle \
+ myeid \
+ oberthur \
+ openpgp \
+ pkcs15 \
+ rutoken_ecp \
+ rutoken \
+ sc-hsm \
+ setcos \
+ starcos \
+ westcos
+
+$(foreach file,$(TOOLS),$(eval $(call ToolGen,$(file))))
+$(foreach file,$(PROFILES),$(eval $(call ProfileGen,$(file))))
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libopensc.{la,so}* $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libsmm-local.{la,so}* $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/opensc-pkcs11.so $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkcs11-spy.so $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkcs11
+ $(LN) ../pkcs11-spy.so $(1)/usr/lib/pkcs11/
+ $(LN) ../opensc-pkcs11.so $(1)/usr/lib/pkcs11/
+ $(INSTALL_DIR) $(1)/usr/share/opensc
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/opensc/* $(1)/usr/share/opensc/
+endef
+
+define Package/libopensc/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libopensc.so* $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libsmm-local.so* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/etc
+ $(CP) $(PKG_INSTALL_DIR)/etc/opensc.conf $(1)/etc/
+endef
+
+define Package/libopensc-pkcs11/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/opensc-pkcs11.so $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkcs11
+ $(LN) ../opensc-pkcs11.so $(1)/usr/lib/pkcs11/
+endef
+
+define Package/libpkcs11-spy/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkcs11-spy.so $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkcs11
+ $(LN) ../pkcs11-spy.so $(1)/usr/lib/pkcs11/
+endef
+
+define Package/opensc-card-profiles
+ $(INSTALL_DIR) $(1)/usr/share/opensc
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/opensc/* $(1)/usr/share/opensc/
+endef
+
+define Package/opensc-utils/install
+ true
+endef
+
+define ToolInstall
+define Package/opensc-utils-$(subst _,-,$(firstword $(subst :, ,$(1))))/install
+ $(INSTALL_DIR) $$(1)/usr/bin
+ $(INSTALL_BIN) \
+ $(PKG_INSTALL_DIR)/usr/bin/$(firstword $(subst :, ,$(1))) \
+ $$(1)/usr/bin/
+endef
+endef
+
+define ProfileInstall
+define Package/libopensc-profile-$(subst _,-,$(firstword $(subst :, ,$(1))))/install
+ $(INSTALL_DIR) $$(1)/usr/share/opensc
+ $(INSTALL_BIN) \
+ $(PKG_INSTALL_DIR)/usr/share/opensc/$(firstword $(subst :, ,$(1))).profile \
+ $$(1)/usr/share/opensc
+endef
+endef
+
+$(foreach file,$(TOOLS),$(eval $(call ToolInstall,$(file))))
+$(foreach file,$(PROFILES),$(eval $(call ProfileInstall,$(file))))
+
+$(eval $(call BuildPackage,libopensc))
+$(eval $(call BuildPackage,libopensc-pkcs11))
+$(eval $(call BuildPackage,libpkcs11-spy))
+
+$(eval $(call BuildPackage,opensc-utils))
+$(foreach file,$(TOOLS),$(eval $(call BuildPackage,opensc-utils-$(subst _,-,$(firstword $(subst :, ,$(file)))))))
+$(foreach file,$(PROFILES),$(eval $(call BuildPackage,libopensc-profile-$(subst _,-,$(firstword $(subst :, ,$(file)))))))
diff --git a/external/subpack/utils/opensc/patches/010-openssl-deprecated.patch b/external/subpack/utils/opensc/patches/010-openssl-deprecated.patch
new file mode 100644
index 0000000..4bdd9db
--- /dev/null
+++ b/external/subpack/utils/opensc/patches/010-openssl-deprecated.patch
@@ -0,0 +1,24 @@
+--- a/src/libopensc/sc-ossl-compat.h
++++ b/src/libopensc/sc-ossl-compat.h
+@@ -101,6 +101,21 @@ extern "C" {
+ #endif
+
+ /*
++ * 1.1.0 depracated ERR_load_crypto_strings(), SSL_load_error_strings(), ERR_free_strings()
++ * and ENGINE_load_dynamic.EVP_CIPHER_CTX_cleanup and EVP_CIPHER_CTX_init are replaced
++ * by EVP_CIPHER_CTX_reset.
++ * But for compatability with LibreSSL and older OpenSSL. OpenSC uses the older functions
++ */
++#if OPENSSL_API_COMPAT >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
++#define ERR_load_crypto_strings(x) {}
++#define SSL_load_error_strings(x) {}
++#define ERR_free_strings(x) {}
++#define ENGINE_load_dynamic(x) {}
++#define EVP_CIPHER_CTX_cleanup(x) EVP_CIPHER_CTX_reset(x)
++#define EVP_CIPHER_CTX_init(x) EVP_CIPHER_CTX_reset(x)
++#endif
++
++/*
+ * OpenSSL-1.1.0-pre5 has hidden the RSA and DSA structures
+ * One can no longer use statements like rsa->n = ...
+ * Macros and defines don't work on all systems, so use inline versions
diff --git a/external/subpack/utils/openzwave/Makefile b/external/subpack/utils/openzwave/Makefile
new file mode 100644
index 0000000..b21d666
--- /dev/null
+++ b/external/subpack/utils/openzwave/Makefile
@@ -0,0 +1,99 @@
+#
+# Copyright (C) 2017 Hauke Mehrtens <hauke@hauke-m.de>
+# Copyright (C) 2016 - 2020 Stijn Tintel <stijn@linux-ipv6.be>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=openzwave
+PKG_VERSION:=1.6.1149
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://old.openzwave.com/downloads
+PKG_HASH:=dc747c24cae11e4aa121252cc38ea92d1fbc587dc514737dd0e2b24191521c48
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/openzwave/default
+ URL:=http://openzwave.com
+ MAINTAINER:=David Woodhouse <dwmw2@infradead.org>
+ DEPENDS:=+libpthread +libstdcpp
+endef
+
+define Package/openzwave/description
+ Open-ZWave is a library that interfaces with selected Z-Wave PC controllers
+endef
+
+define Package/libopenzwave
+$(call Package/openzwave/default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Open-ZWave Library
+endef
+
+define Package/openzwave
+$(call Package/openzwave/default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Open-ZWave MinOZW test utility
+ DEPENDS:=+libopenzwave +openzwave-config
+endef
+
+define Package/openzwave-config
+$(call Package/openzwave/default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Open-ZWave Device Configs
+endef
+
+TARGET_CPPFLAGS+=-Wno-format -Wno-format-security
+
+MAKE_FLAGS += \
+ LD="$(TARGET_CROSS)g++" \
+ LIBDIR="$(PKG_BUILD_DIR)" \
+ PREFIX=$(CONFIGURE_PREFIX) \
+ USE_HID="no" \
+ ar_option="q" \
+ instlibdir=/usr/lib \
+ pkgconfigdir=/usr/lib/pkgconfig \
+ sysconfdir=/etc/openzwave
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ sed -i -e 's/-O3 //;s/-Werror //' $(PKG_BUILD_DIR)/cpp/build/Makefile
+endef
+
+define Package/libopenzwave/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libopenzwave.so* $(1)/usr/lib/
+endef
+
+define Package/openzwave/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/MinOZW $(1)/usr/bin/
+endef
+
+define Package/openzwave-config/install
+ $(INSTALL_DIR) $(1)/etc/
+ $(CP) $(PKG_INSTALL_DIR)/etc/openzwave $(1)/etc/
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/openzwave $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libopenzwave.* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libopenzwave.pc $(1)/usr/lib/pkgconfig/
+ $(SED) 's,/usr/include,$$$${prefix}/include,g' $(1)/usr/lib/pkgconfig/libopenzwave.pc
+ $(SED) 's,/usr/lib,$$$${exec_prefix}/lib,g' $(1)/usr/lib/pkgconfig/libopenzwave.pc
+endef
+
+$(eval $(call BuildPackage,libopenzwave))
+$(eval $(call BuildPackage,openzwave))
+$(eval $(call BuildPackage,openzwave-config))
diff --git a/external/subpack/utils/owfs/Config.in b/external/subpack/utils/owfs/Config.in
new file mode 100644
index 0000000..a6508e8
--- /dev/null
+++ b/external/subpack/utils/owfs/Config.in
@@ -0,0 +1,49 @@
+ menu "Customize libow"
+ depends on PACKAGE_libow
+
+ menu "Bus master and adapter support"
+ config LIBOW_MASTER_USB
+ bool "USB bus master support (requires libusb)"
+ help
+ Include support for USB adapters (NOT usb-serial adapters, which use
+ kernel driver and are supported anyway).
+ Turning this off will save ~13kB (and ~50kB weighting libusb dependency).
+ default y
+
+ config LIBOW_MASTER_I2C
+ bool "I2C bus master (DS2482) support"
+ default y
+ help
+ Include support for I2C adapters.
+ Turning this feature off will save ~6kB.
+
+ config LIBOW_MASTER_W1
+ bool "Kernel W1 bus master support (requires kmod-w1)"
+ help
+ Support kernel 1-Wire bus masters (requires KConfig CONFIG_CONNECTOR=y
+ and CONFIG_W1_CON=y).
+ Turning this on will increase libow size by about 10kB.
+ default n
+ endmenu
+
+ config LIBOW_ZEROCONF
+ bool "Zeroconf/bonjour support"
+ default y
+ help
+ Enable server process announcement using Zeroconf (Bonjour) protocol.
+ Turning this feature on will increase owlib size by about 12kB.
+
+ config LIBOW_DEBUG
+ bool "Enable debug output (100+ kB)"
+ default y
+ help
+ If you don't need to debug your 1-wire network, you can save as much as
+ 137kB disabling debug output.
+
+ config LIBOW_OWTRAFFIC
+ bool "Enable bus traffic reports"
+ default n
+ help
+ Enable owfs traffic monitor. It's here purely for debugging purposes.
+ Turning this on will increase libow size by about 3kB.
+ endmenu
diff --git a/external/subpack/utils/owfs/Makefile b/external/subpack/utils/owfs/Makefile
new file mode 100644
index 0000000..0cb620e
--- /dev/null
+++ b/external/subpack/utils/owfs/Makefile
@@ -0,0 +1,302 @@
+#
+# Copyright (C) 2008-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=owfs
+PKG_VERSION:=3.2p4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/owfs/owfs/releases/download/v$(PKG_VERSION)
+PKG_HASH:=af0a5035f3f3df876ca15aea13486bfed6b3ef5409dee016db0be67755c35fcc
+
+PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+PKG_LICENSE:=GPL-2.0
+PKG_CPE_ID:=cpe:/a:owfs:owfs
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+
+PKG_CONFIG_DEPENDS:= \
+ CONFIG_LIBOW_MASTER_USB \
+ CONFIG_LIBOW_MASTER_I2C \
+ CONFIG_LIBOW_MASTER_W1 \
+ CONFIG_LIBOW_ZEROCONF \
+ CONFIG_LIBOW_DEBUG \
+ CONFIG_LIBOW_OWTRAFFIC
+
+include $(INCLUDE_DIR)/package.mk
+
+#
+# templates
+#
+
+define Package/owfs/Default
+ TITLE:=OWFS (1-Wire File System)
+ URL:=https://github.com/owfs/owfs
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=Filesystem
+endef
+
+define Package/owfs/Default/description
+ OWFS is a suite of programs that designed to make the 1-wire bus and its
+ devices easily accessible. The underlying principle is to create a virtual
+ filesystem, with the unique ID being the directory, and the individual
+ properties of the device are represented as simple files that can be read
+ and written.
+
+ Details of the individual slave or master design are hidden behind a
+ consistent interface. The goal is to provide an easy set of tools for a
+ software designer to create monitoring or control applications. There are
+ some performance enhancements in the implementation, including data caching,
+ parallel access to bus masters, and aggregation of device communication.
+ Still the fundemental goal has been ease of use, flexibility and correctness
+ rather than speed.
+endef
+
+define Package/owfs/Server
+ $(call Package/owfs/Default)
+ DEPENDS:=+libow +libpthread
+endef
+
+define Package/owfs/Library
+ $(call Package/owfs/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+endef
+
+define Package/owfs/Utility
+ $(call Package/owfs/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libow
+endef
+
+#
+# shared libraries
+#
+
+define Package/libow
+ $(call Package/owfs/Library)
+ DEPENDS:= \
+ +libpthread \
+ +LIBOW_MASTER_USB:libusb-compat \
+ +LIBOW_MASTER_W1:kmod-w1
+ TITLE:=OWFS - common shared library
+endef
+
+define Package/libow/config
+ source "$(SOURCE)/Config.in"
+endef
+
+define Package/libow/description
+ $(call Package/owfs/Default/description)
+
+ This package contains the OWFS library.
+endef
+
+define Package/libow-capi
+ $(call Package/owfs/Library)
+ DEPENDS:=+libow
+ TITLE:=OWFS - C-API library
+endef
+
+define Package/libow-capi/description
+ $(call Package/owfs/Default/description)
+
+ This package contains the OWFS C-API library.
+endef
+
+#
+# utilities
+#
+
+define Package/owshell
+ $(call Package/owfs/Utility)
+ TITLE:=OWFS - shell utilities
+endef
+
+define Package/owshell/description
+ $(call Package/owfs/Default/description)
+
+ This package contains the OWFS shell utilities.
+endef
+
+define Package/owfs
+ $(call Package/owfs/Utility)
+ # libfuse depends on kmod-fuse, no need to declare dependency
+ DEPENDS+= +libfuse +fuse-utils
+ TITLE:=OWFS - fuse file system
+endef
+
+define Package/owfs/description
+ $(call Package/owfs/Default/description)
+
+ This package contains the OWFS fuse filesystem.
+endef
+
+#
+# network daemons
+#
+
+define Package/owhttpd
+ $(call Package/owfs/Server)
+ TITLE:=OWFS - http server
+endef
+
+define Package/owhttpd/description
+ $(call Package/owfs/Default/description)
+
+ This package contains the OWFS http server.
+endef
+
+define Package/owftpd
+ $(call Package/owfs/Server)
+ TITLE:=OWFS - ftp server
+endef
+
+define Package/owftpd/description
+ $(call Package/owfs/Default/description)
+
+ This package contains the OWFS ftp server.
+endef
+
+define Package/owserver
+ $(call Package/owfs/Server)
+ TITLE:=OWFS - network server
+endef
+
+define Package/owserver/description
+ $(call Package/owfs/Default/description)
+
+ This package contains the OWFS network server.
+endef
+
+CONFIGURE_ARGS += \
+ --enable-owftpd \
+ --enable-owserver \
+ --enable-owhttpd \
+ --enable-owfs \
+ --with-fuseinclude="$(STAGING_DIR)/usr/include" \
+ --with-fuselib="$(STAGING_DIR)/usr/lib" \
+ --enable-shared \
+ --disable-parport \
+ --disable-ownet \
+ --disable-owpython \
+ --disable-owphp \
+ --disable-owtcl \
+ --disable-swig \
+ --disable-avahi \
+ $(if $(CONFIG_LIBOW_MASTER_USB),--enable-usb,--disable-usb) \
+ $(if $(CONFIG_LIBOW_MASTER_W1),--enable-w1,--disable-w1) \
+ $(if $(CONFIG_LIBOW_MASTER_I2C),--enable-i2c,--disable-i2c) \
+ $(if $(CONFIG_LIBOW_ZEROCONF),--enable-zero,--disable-zero) \
+ $(if $(CONFIG_LIBOW_DEBUG),--enable-debug,--disable-debug) \
+ $(if $(CONFIG_LIBOW_OWTRAFFIC),--enable-owtraffic,--disable-owtraffic)
+
+CONFIGURE_VARS += \
+ LDFLAGS="$(TARGET_LDFLAGS) -Wl,-rpath-link=$(STAGING_DIR)/usr/lib -Wl,-rpath-link=$(TOOLCHAIN_DIR)/usr/lib" \
+ lt_cv_sys_lib_dlsearch_path_spec="$(STAGING_DIR)/lib $(STAGING_DIR)/usr/lib" \
+ lt_cv_sys_lib_search_path_spec="$(STAGING_DIR)/lib $(STAGING_DIR)/usr/lib" \
+ shrext_cmds=".so" \
+
+MAKE_FLAGS += \
+ CC="$(TARGET_CC)" \
+ HOST_CPU="$(PKGARCH)"
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(STAGING_DIR)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/ow{capi,fs_config}.h $(STAGING_DIR)/usr/include/
+ $(INSTALL_DIR) $(STAGING_DIR)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libow{,capi}*.so* $(STAGING_DIR)/usr/lib/
+endef
+
+define Package/owfs/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/owfs $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/owfs.conf $(1)/etc/config/owfs
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/owfs.init $(1)/etc/init.d/owfs
+ mkdir -p $(1)/mnt/owfs
+endef
+
+define Package/owfs/conffiles
+/etc/config/owfs
+endef
+
+define Package/owshell/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/owget $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/owread $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/owwrite $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/owdir $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/owpresent $(1)/usr/bin/
+endef
+
+
+define Package/owserver/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/owserver $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/owserver.conf $(1)/etc/config/owserver
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/owserver.init $(1)/etc/init.d/owserver
+endef
+
+define Package/owserver/conffiles
+/etc/config/owserver
+endef
+
+define Package/owhttpd/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/owhttpd $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/owhttpd.conf $(1)/etc/config/owhttpd
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/owhttpd.init $(1)/etc/init.d/owhttpd
+endef
+
+define Package/owhttpd/conffiles
+/etc/config/owhttpd
+endef
+
+define Package/owftpd/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/owftpd $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/owftpd.conf $(1)/etc/config/owftpd
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/owftpd.init $(1)/etc/init.d/owftpd
+endef
+
+define Package/owftpd/conffiles
+/etc/config/owftpd
+endef
+
+define Package/libow/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libow-*.so.* $(1)/usr/lib/
+endef
+
+define Package/libow-capi/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libowcapi-*.so.* $(1)/usr/lib/
+endef
+
+
+$(eval $(call BuildPackage,owfs))
+$(eval $(call BuildPackage,owshell))
+
+$(eval $(call BuildPackage,owserver))
+$(eval $(call BuildPackage,owhttpd))
+$(eval $(call BuildPackage,owftpd))
+
+$(eval $(call BuildPackage,libow))
+$(eval $(call BuildPackage,libow-capi))
diff --git a/external/subpack/utils/owfs/files/owfs.conf b/external/subpack/utils/owfs/files/owfs.conf
new file mode 100644
index 0000000..b485989
--- /dev/null
+++ b/external/subpack/utils/owfs/files/owfs.conf
@@ -0,0 +1,10 @@
+config owfs 'owfs'
+ option enabled 0
+ option user root
+ option readonly 0
+ option mountpoint '/mnt/owfs'
+ option fuse_allow_other 0
+ option fuse_open_opt ''
+ option error_level 0
+ list devices '-s'
+ list devices 'localhost:4304'
diff --git a/external/subpack/utils/owfs/files/owfs.init b/external/subpack/utils/owfs/files/owfs.init
new file mode 100644
index 0000000..83c8913
--- /dev/null
+++ b/external/subpack/utils/owfs/files/owfs.init
@@ -0,0 +1,82 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2009-2015 OpenWrt.org
+
+START=95
+USE_PROCD=1
+
+PROG=/usr/bin/owfs
+
+append_arg() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get val "$cfg" "$var"
+ [ -n "$val" -o -n "$def" ] && procd_append_param command $opt "${val:-$def}"
+}
+
+append_bool() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get_bool val "$cfg" "$var" "$def"
+ [ "$val" = 1 ] && procd_append_param command "$opt"
+}
+
+append_plain() {
+ procd_append_param command "$1"
+}
+
+append_param() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get val "$cfg" "$var"
+ [ -n "$val" -o -n "$def" ] && procd_append_param "$opt" "${val:-$def}"
+}
+
+start_instance() {
+ local cfg="$1"
+ local enabled
+
+ config_get_bool enabled "$cfg" 'enabled' '0'
+ [ "$enabled" = 0 ] && return 1
+
+ procd_open_instance
+
+ procd_set_param command "$PROG" --foreground --error_print=1
+
+ # common parameters
+ append_bool "$cfg" readonly "--readonly"
+ append_arg "$cfg" error_level "--error_level"
+ config_list_foreach "$cfg" options append_plain
+ config_list_foreach "$cfg" devices append_plain
+ append_param "$cfg" user user
+
+ # owfs-specific
+ append_arg "$cfg" mountpoint "--mountpoint" /mnt/owfs
+ append_bool "$cfg" fuse_allow_other "--allow_other"
+ append_arg "$cfg" fuse_open_opt "--fuse_open_opt"
+
+ # don't respawn fuse
+
+ procd_close_instance
+
+}
+
+service_triggers() {
+ procd_add_reload_trigger owfs
+}
+
+start_service() {
+ config_load owfs
+ config_foreach start_instance owfs
+}
diff --git a/external/subpack/utils/owfs/files/owftpd.conf b/external/subpack/utils/owfs/files/owftpd.conf
new file mode 100644
index 0000000..100162e
--- /dev/null
+++ b/external/subpack/utils/owfs/files/owftpd.conf
@@ -0,0 +1,8 @@
+config owftpd 'owftpd'
+ option enabled 0
+ option user root
+ option readonly 0
+ option port 21
+ option error_level 0
+ list devices '-s'
+ list devices 'localhost:4304'
diff --git a/external/subpack/utils/owfs/files/owftpd.init b/external/subpack/utils/owfs/files/owftpd.init
new file mode 100644
index 0000000..a7e17c9
--- /dev/null
+++ b/external/subpack/utils/owfs/files/owftpd.init
@@ -0,0 +1,81 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2009-2015 OpenWrt.org
+
+START=95
+USE_PROCD=1
+
+PROG=/usr/bin/owftpd
+
+append_arg() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get val "$cfg" "$var"
+ [ -n "$val" -o -n "$def" ] && procd_append_param command $opt "${val:-$def}"
+}
+
+append_bool() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get_bool val "$cfg" "$var" "$def"
+ [ "$val" = 1 ] && procd_append_param command "$opt"
+}
+
+append_plain() {
+ procd_append_param command "$1"
+}
+
+append_param() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get val "$cfg" "$var"
+ [ -n "$val" -o -n "$def" ] && procd_append_param "$opt" "${val:-$def}"
+}
+
+start_instance() {
+ local cfg="$1"
+ local enabled
+
+ config_get_bool enabled "$cfg" 'enabled' '0'
+ [ "$enabled" = 0 ] && return 1
+
+ procd_open_instance
+
+ procd_set_param command "$PROG" --foreground --error_print=1
+
+ # common parameters
+ append_bool "$cfg" readonly "--readonly"
+ append_arg "$cfg" error_level "--error_level"
+ config_list_foreach "$cfg" options append_plain
+ config_list_foreach "$cfg" devices append_plain
+ append_param "$cfg" user user
+
+ # owftpd-specific
+ append_arg "$cfg" port "--port"
+ append_arg "$cfg" max_connections "--max_connections"
+
+ procd_set_param respawn
+
+ procd_close_instance
+
+}
+
+service_triggers() {
+ procd_add_reload_trigger owftpd
+}
+
+start_service() {
+ config_load owftpd
+ config_foreach start_instance owftpd
+}
diff --git a/external/subpack/utils/owfs/files/owhttpd.conf b/external/subpack/utils/owfs/files/owhttpd.conf
new file mode 100644
index 0000000..a314cd1
--- /dev/null
+++ b/external/subpack/utils/owfs/files/owhttpd.conf
@@ -0,0 +1,8 @@
+config owhttpd 'owhttpd'
+ option enabled 0
+ option user root
+ option readonly 0
+ option port 3001
+ option error_level 0
+ list devices '-s'
+ list devices 'localhost:4304'
diff --git a/external/subpack/utils/owfs/files/owhttpd.init b/external/subpack/utils/owfs/files/owhttpd.init
new file mode 100644
index 0000000..868c9b4
--- /dev/null
+++ b/external/subpack/utils/owfs/files/owhttpd.init
@@ -0,0 +1,81 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2009-2015 OpenWrt.org
+
+START=95
+USE_PROCD=1
+
+PROG=/usr/bin/owhttpd
+
+append_arg() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get val "$cfg" "$var"
+ [ -n "$val" -o -n "$def" ] && procd_append_param command $opt "${val:-$def}"
+}
+
+append_bool() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get_bool val "$cfg" "$var" "$def"
+ [ "$val" = 1 ] && procd_append_param command "$opt"
+}
+
+append_plain() {
+ procd_append_param command "$1"
+}
+
+append_param() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get val "$cfg" "$var"
+ [ -n "$val" -o -n "$def" ] && procd_append_param "$opt" "${val:-$def}"
+}
+
+start_instance() {
+ local cfg="$1"
+ local enabled
+
+ config_get_bool enabled "$cfg" 'enabled' '0'
+ [ "$enabled" = 0 ] && return 1
+
+ procd_open_instance
+
+ procd_set_param command "$PROG" --foreground --error_print=1
+
+ # common parameters
+ append_bool "$cfg" readonly "--readonly"
+ append_arg "$cfg" error_level "--error_level"
+ config_list_foreach "$cfg" options append_plain
+ config_list_foreach "$cfg" devices append_plain
+ append_param "$cfg" user user
+
+ # owhttpd-specific
+ append_arg "$cfg" port "--port"
+ append_arg "$cfg" max_connections "--max_connections"
+
+ procd_set_param respawn
+
+ procd_close_instance
+
+}
+
+service_triggers() {
+ procd_add_reload_trigger owhttpd
+}
+
+start_service() {
+ config_load owhttpd
+ config_foreach start_instance owhttpd
+}
diff --git a/external/subpack/utils/owfs/files/owserver.conf b/external/subpack/utils/owfs/files/owserver.conf
new file mode 100644
index 0000000..ceb8a61
--- /dev/null
+++ b/external/subpack/utils/owfs/files/owserver.conf
@@ -0,0 +1,8 @@
+config owserver 'owserver'
+ option enabled 0
+ option user root
+ option readonly 0
+ option port 4304
+ option error_level 0
+ list devices '-d'
+ list devices '/dev/ttyUSB0'
diff --git a/external/subpack/utils/owfs/files/owserver.init b/external/subpack/utils/owfs/files/owserver.init
new file mode 100644
index 0000000..7f91aee
--- /dev/null
+++ b/external/subpack/utils/owfs/files/owserver.init
@@ -0,0 +1,81 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2009-2015 OpenWrt.org
+
+START=90
+USE_PROCD=1
+
+PROG=/usr/bin/owserver
+
+append_arg() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get val "$cfg" "$var"
+ [ -n "$val" -o -n "$def" ] && procd_append_param command $opt "${val:-$def}"
+}
+
+append_bool() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get_bool val "$cfg" "$var" "$def"
+ [ "$val" = 1 ] && procd_append_param command "$opt"
+}
+
+append_plain() {
+ procd_append_param command "$1"
+}
+
+append_param() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get val "$cfg" "$var"
+ [ -n "$val" -o -n "$def" ] && procd_append_param "$opt" "${val:-$def}"
+}
+
+start_instance() {
+ local cfg="$1"
+ local enabled
+
+ config_get_bool enabled "$cfg" 'enabled' '0'
+ [ "$enabled" = 0 ] && return 1
+
+ procd_open_instance
+
+ procd_set_param command "$PROG" --foreground --error_print=1
+
+ # common parameters
+ append_bool "$cfg" readonly "--readonly"
+ append_arg "$cfg" error_level "--error_level"
+ config_list_foreach "$cfg" options append_plain
+ config_list_foreach "$cfg" devices append_plain
+ append_param "$cfg" user user
+
+ # owserver-specific
+ append_arg "$cfg" port "--port"
+ append_arg "$cfg" max_connections "--max_connections"
+
+ procd_set_param respawn
+
+ procd_close_instance
+
+}
+
+service_triggers() {
+ procd_add_reload_trigger owserver
+}
+
+start_service() {
+ config_load owserver
+ config_foreach start_instance owserver
+}
diff --git a/external/subpack/utils/owut/Makefile b/external/subpack/utils/owut/Makefile
new file mode 100644
index 0000000..e6b361a
--- /dev/null
+++ b/external/subpack/utils/owut/Makefile
@@ -0,0 +1,70 @@
+#
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright (C) 2024 Eric Fahlgren <ericfahlgren@gmail.com>
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=owut
+PKG_SOURCE_DATE:=2024-10-27
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_VERSION:=8c7e42f02749ff8ffee44d8f7f1e1a4260072cc1
+PKG_SOURCE_URL:=https://github.com/efahl/owut.git
+PKG_MIRROR_HASH:=fc3745ea6625c7f4f3baa81a8afee19480a41a16d8417d7580e73592ad9e6f36
+
+PKG_MAINTAINER:=Eric Fahlgren <ericfahlgren@gmail.com>
+PKG_LICENSE:=GPL-2.0-only
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/owut
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=owut - an OpenWrt Upgrade Tool
+ URL:=http://github.com/efahl/owut
+ DEPENDS:=+attendedsysupgrade-common \
+ +rpcd-mod-file \
+ +ucode +ucode-mod-fs +ucode-mod-ubus \
+ +ucode-mod-uci +ucode-mod-uclient +ucode-mod-uloop
+ PKGARCH:=all
+endef
+
+define Package/owut/description
+ The OpenWrt Upgrade Tool (owut) is a command line program that
+ checks for new packages, package build breakages, generates
+ sysupgrade images containing installed packages and installs
+ images. It is written in ucode for easy end-user customization.
+
+ Documentation is available at
+ https://openwrt.org/docs/guide-user/installation/sysupgrade.owut
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+define Package/owut/conffiles
+/etc/owut.d/
+endef
+
+define Package/owut/install
+ $(INSTALL_DIR) $(1)/etc/uci-defaults
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/files/owut.defaults $(1)/etc/uci-defaults/51-attendedsysupgrade-owut
+
+ $(INSTALL_DIR) $(1)/etc/owut.d
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/files/pre-install.sh $(1)/etc/owut.d/pre-install.sh
+
+ $(INSTALL_DIR) $(1)/usr/share/ucode/utils
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/files/argparse.uc $(1)/usr/share/ucode/utils
+
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/files/owut $(1)/usr/bin
+
+ sed -i -e "s/%%VERSION%%/$(PKG_VERSION)-r$(PKG_RELEASE)/" $(1)/usr/bin/owut
+endef
+
+$(eval $(call BuildPackage,owut))
diff --git a/external/subpack/utils/parted/Config.in b/external/subpack/utils/parted/Config.in
new file mode 100644
index 0000000..2a90b63
--- /dev/null
+++ b/external/subpack/utils/parted/Config.in
@@ -0,0 +1,14 @@
+menu "Configuration"
+ depends on PACKAGE_parted
+
+config PARTED_READLINE
+ bool "Use readline library"
+ depends on PACKAGE_parted
+ default y
+
+config PARTED_LVM2
+ bool "Support LVM"
+ depends on PACKAGE_parted
+ default n
+
+endmenu
diff --git a/external/subpack/utils/parted/Makefile b/external/subpack/utils/parted/Makefile
new file mode 100644
index 0000000..f163ab7
--- /dev/null
+++ b/external/subpack/utils/parted/Makefile
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=parted
+PKG_VERSION:=3.4
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=http://ftp.gnu.org/gnu/parted/
+PKG_HASH:=e1298022472da5589b7f2be1d5ee3c1b66ec3d96dfbad03dc642afd009da5342
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+PKG_MAINTAINER:=Oskari Rauta <oskari.rauta@gmail.com>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/parted
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=GNU Parted
+ SUBMENU:=Disc
+ DEPENDS:=+libblkid +libuuid +PARTED_READLINE:libreadline +CONFIG_PARTED_READLINE:libncurses +PARTED_LVM2:libdevmapper
+endef
+
+define Package/parted/description
+ GNU Parted manipulates partition tables. This is useful for
+ creating space for new operating systems, reorganizing
+ disk usage, copying data on hard disks and disk imaging.
+endef
+
+define Package/parted/config
+ source "$(SOURCE)/Config.in"
+endef
+
+ifneq ($(CONFIG_PARTED_READLINE),y)
+ CONFIGURE_ARGS += --without-readline
+endif
+
+ifneq ($(CONFIG_PARTED_LVM2),y)
+ CONFIGURE_ARGS += --disable-device-mapper
+endif
+
+define Package/parted/install
+ $(INSTALL_DIR) $(1)/usr/lib $(1)/sbin
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so** $(1)/usr/lib/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/parted $(1)/sbin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/partprobe $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,parted))
diff --git a/external/subpack/utils/parted/test.sh b/external/subpack/utils/parted/test.sh
new file mode 100644
index 0000000..7b01158
--- /dev/null
+++ b/external/subpack/utils/parted/test.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+case "$1" in
+ "partprobe")
+ test $(/sbin/partprobe --version | grep '^Copyright' | wc -l) -gt 0
+ ;;
+ "parted")
+ test $(/sbin/parted --version | grep '^Copyright' | wc -l) -gt 0
+ ;;
+esac
diff --git a/external/subpack/utils/pcmciautils/Makefile b/external/subpack/utils/pcmciautils/Makefile
new file mode 100644
index 0000000..026089b
--- /dev/null
+++ b/external/subpack/utils/pcmciautils/Makefile
@@ -0,0 +1,57 @@
+#
+# Copyright (C) 2008-2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=pcmciautils
+PKG_VERSION:=018
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=@KERNEL/linux/utils/kernel/pcmcia
+PKG_HASH:=79e6ae441278e178c07501d492394ed2c0326fdb66894f6d040ec811b0dc8ed5
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINATINER:=Tomasz Maciej Nowak <tomek_n@o2.pl>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/pcmciautils
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libsysfs @PCMCIA_SUPPORT
+ TITLE:=PCMCIA Utilities
+ URL:=http://www.kernel.org/pub/linux/utils/kernel/pcmcia/pcmcia.html
+endef
+
+define Build/Compile
+ $(call Build/Compile/Default, \
+ LD="$(TARGET_CC)" UDEV=false \
+ CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS) \
+ -DPCMCIAUTILS_VERSION=\\\"$(PKG_VERSION)\\\"" \
+ prefix=/usr all \
+ )
+endef
+
+define Package/pcmciautils/install
+ $(INSTALL_DIR) $(1)/usr/sbin/
+ $(CP) $(PKG_BUILD_DIR)/pccardctl $(1)/usr/sbin/
+ $(CP) $(PKG_BUILD_DIR)/pcmcia-check-broken-cis $(1)/usr/sbin/
+ $(CP) $(PKG_BUILD_DIR)/pcmcia-socket-startup $(1)/usr/sbin/
+ rm -f $(1)/usr/sbin/lspcmcia
+ ln -s pccardctl $(1)/usr/sbin/lspcmcia
+ $(INSTALL_DIR) $(1)/etc/pcmcia/
+ $(CP) $(PKG_BUILD_DIR)/config/config.opts $(1)/etc/pcmcia/
+ $(CP) files/* $(1)/
+endef
+
+define Package/pcmciautils/conffiles
+/etc/pcmcia/config.opts
+endef
+
+$(eval $(call BuildPackage,pcmciautils))
diff --git a/external/subpack/utils/pcmciautils/files/etc/hotplug.d/pcmcia/pcmcia.agent b/external/subpack/utils/pcmciautils/files/etc/hotplug.d/pcmcia/pcmcia.agent
new file mode 100644
index 0000000..537c50a
--- /dev/null
+++ b/external/subpack/utils/pcmciautils/files/etc/hotplug.d/pcmcia/pcmcia.agent
@@ -0,0 +1,28 @@
+#!/bin/sh
+# Copyright (C) 2008 OpenWrt.org
+
+case "$ACTION" in
+ add)
+ SYSFS=/sys/bus/pcmcia/devices/
+ DEVPATH=$SOCKET_NO.$((0x$DEVICE_NO))
+
+ # check whether the CIS is completely broken
+ if [ ! -h $SYSFS$DEVPATH/driver ]; then
+ CISFILE=$(/usr/sbin/pcmcia-check-broken-cis $SOCKET_NO)
+ echo PCMCIA: $CISFILE;
+ if [ ! -z $CISFILE ]; then
+ if [ -f /lib/firmware/$CISFILE ]; then
+ cat /lib/firmware/$CISFILE > $SYSFS/class/pcmcia_socket/pcmcia_socket$(SOCKET_NO)/cis
+ fi;
+ fi;
+ fi;
+
+ # allow a match solely based on the "function ID" field
+ if [ ! -h $SYSFS$DEVPATH/driver ]; then
+ if [ -w $SYSFS$DEVPATH/allow_func_id_match ]; then
+ echo PCMCIA: allowing func_id based match for PCMCIA device $SOCKET_NO.$DEVICE_NO
+ echo -n "42" > $SYSFS$DEVPATH/allow_func_id_match;
+ fi;
+ fi;
+ ;;
+esac
diff --git a/external/subpack/utils/pcmciautils/files/etc/hotplug.d/pcmcia_socket/pcmcia_socket.agent b/external/subpack/utils/pcmciautils/files/etc/hotplug.d/pcmcia_socket/pcmcia_socket.agent
new file mode 100644
index 0000000..79b3524
--- /dev/null
+++ b/external/subpack/utils/pcmciautils/files/etc/hotplug.d/pcmcia_socket/pcmcia_socket.agent
@@ -0,0 +1,18 @@
+#!/bin/sh
+# Copyright (C) 2008 OpenWrt.org
+
+case "$ACTION" in
+ add)
+ echo PCMCIA: socket number: $SOCKET_NO
+
+ sleep 1;
+ /usr/sbin/pcmcia-socket-startup $SOCKET_NO
+ DONE_FILE=/sys/class/pcmcia_socket/pcmcia_socket$SOCKET_NO/available_resources_setup_done
+ if [ -f $DONE_FILE ]; then
+ if [ -w $DONE_FILE ]; then
+ echo -n "42" > $DONE_FILE
+ fi;
+ fi;
+ ;;
+
+esac
diff --git a/external/subpack/utils/pcmciautils/files/etc/init.d/pcmcia b/external/subpack/utils/pcmciautils/files/etc/init.d/pcmcia
new file mode 100755
index 0000000..16f2276
--- /dev/null
+++ b/external/subpack/utils/pcmciautils/files/etc/init.d/pcmcia
@@ -0,0 +1,25 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2008 OpenWrt.org
+
+START=42
+start() {
+ if [ -d /sys/bus/pcmcia/devices/ ]; then
+ # 2.6 kernels
+ cd /sys/bus/pcmcia/devices/
+ for PCMCIA_DEVICE in *; do
+ if [ $PCMCIA_DEVICE == \* ]; then
+ continue;
+ fi;
+ MODALIAS=$(cat $PCMCIA_DEVICE/modalias)
+ echo PCMCIA: $MODALIAS $PCMCIA_DEVICE
+ if [ -z $MODALIAS ]; then
+ continue;
+ fi;
+ ACTION=add
+ SOCKET_NO=$(echo $PCMCIA_DEVICE | cut -d. -f1)
+ DEVICE_NO=$(echo $MODALIAS | sed 's/.*pfn\(..\).*/\1/')
+ export MODALIAS ACTION SOCKET_NO DEVICE_NO
+ /sbin/hotplug-call pcmcia
+ done;
+ fi;
+}
diff --git a/external/subpack/utils/pcmciautils/files/etc/init.d/pcmcia_socket b/external/subpack/utils/pcmciautils/files/etc/init.d/pcmcia_socket
new file mode 100755
index 0000000..fdd0b8c
--- /dev/null
+++ b/external/subpack/utils/pcmciautils/files/etc/init.d/pcmcia_socket
@@ -0,0 +1,19 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2008 OpenWrt.org
+
+START=41
+start() {
+ if [ -d /sys/class/pcmcia_socket/ ]; then
+ # 2.6 kernels
+ cd /sys/class/pcmcia_socket/
+ for PCMCIA_SOCKET in *; do
+ if [ $PCMCIA_SOCKET == \* ]; then
+ continue;
+ fi;
+ SOCKET_NO=$(echo $PCMCIA_SOCKET | cut -b14-)
+ ACTION=add
+ export SOCKET_NO ACTION
+ /sbin/hotplug-call pcmcia_socket
+ done;
+ fi;
+}
diff --git a/external/subpack/utils/pcmciautils/patches/001-switch_unsigned.patch b/external/subpack/utils/pcmciautils/patches/001-switch_unsigned.patch
new file mode 100644
index 0000000..32d97f4
--- /dev/null
+++ b/external/subpack/utils/pcmciautils/patches/001-switch_unsigned.patch
@@ -0,0 +1,11 @@
+--- a/src/yacc_config.y
++++ b/src/yacc_config.y
+@@ -40,7 +40,7 @@ int yylex(void);
+
+ %union {
+ char *str;
+- u_long num;
++ unsigned long num;
+ struct adjust_list_t *adjust;
+ }
+
diff --git a/external/subpack/utils/pcmciautils/patches/002-disable_yywrap.patch b/external/subpack/utils/pcmciautils/patches/002-disable_yywrap.patch
new file mode 100644
index 0000000..41895d2
--- /dev/null
+++ b/external/subpack/utils/pcmciautils/patches/002-disable_yywrap.patch
@@ -0,0 +1,21 @@
+--- a/src/lex_config.l
++++ b/src/lex_config.l
+@@ -1,6 +1,6 @@
+ /* Special state for handling include files */
+ %x src
+-%option noinput nounput
++%option noinput nounput noyywrap
+
+ %{
+ /*
+@@ -77,10 +77,6 @@ module /* skip */ ;
+
+ %%
+
+-#ifndef yywrap
+-int yywrap() { return 1; }
+-#endif
+-
+ /*======================================================================
+
+ Stuff to parse basic data types
diff --git a/external/subpack/utils/pcsc-lite/Makefile b/external/subpack/utils/pcsc-lite/Makefile
new file mode 100644
index 0000000..62aefa7
--- /dev/null
+++ b/external/subpack/utils/pcsc-lite/Makefile
@@ -0,0 +1,104 @@
+#
+# Copyright (C) 2009-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=pcsc-lite
+PKG_VERSION:=1.9.9
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://pcsclite.apdu.fr/files/
+PKG_HASH:=cbcc3b34c61f53291cecc0d831423c94d437b188eb2b97b7febc08de1c914e8a
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:muscle:pcsc-lite
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/pcsc-lite/Default
+ TITLE:=Access a smart card using SCard API (PC/SC)
+ URL:=https://pcsclite.apdu.fr/
+endef
+
+define Package/pcsc-lite/Default/description
+ The purpose of PC/SC Lite is to provide a Windows(R) SCard
+ interface in a very small form factor for communicating to
+ smart cards and smart cards readers.
+endef
+
+define Package/libpcsclite
+ $(call Package/pcsc-lite/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+= (library)
+ DEPENDS:=+libusb-1.0 +libpthread +librt
+endef
+
+define Package/libpcsclite/description
+ $(call Package/pcsc-lite/Default/description)
+ .
+ This package contains the PC/SC shared library.
+endef
+
+define Package/pcscd
+ $(call Package/pcsc-lite/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE+= (daemon)
+ DEPENDS:=+libpcsclite
+endef
+
+define Package/pcscd/description
+ $(call Package/pcsc-lite/Default/description)
+ .
+ This package contains the PC/SC daemon.
+endef
+
+TARGET_CFLAGS += $(FPIC)
+TARGET_LDFLAGS += -lpthread
+
+CONFIGURE_ARGS += \
+ --disable-libudev \
+ --disable-libsystemd \
+ --enable-libusb \
+ --enable-static \
+ --enable-ipcdir=/var/run/pcscd \
+ --enable-usbdropdir=/usr/lib/pcsc/drivers
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/PCSC
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/PCSC/* $(1)/usr/include/PCSC/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libpcsclite.{a,so*} $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libpcsclite.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/libpcsclite/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libpcsclite.so.* $(1)/usr/lib/
+endef
+
+define Package/pcscd/conffiles
+/etc/reader.conf.d/reader.conf
+endef
+
+define Package/pcscd/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/pcscd $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/pcscd.init $(1)/etc/init.d/pcscd
+ $(INSTALL_DIR) $(1)/etc/reader.conf.d
+endef
+
+$(eval $(call BuildPackage,libpcsclite))
+$(eval $(call BuildPackage,pcscd))
diff --git a/external/subpack/utils/pcsc-lite/files/pcscd.init b/external/subpack/utils/pcsc-lite/files/pcscd.init
new file mode 100644
index 0000000..497a740
--- /dev/null
+++ b/external/subpack/utils/pcsc-lite/files/pcscd.init
@@ -0,0 +1,15 @@
+#!/bin/sh /etc/rc.common
+
+START=50
+
+USE_PROCD=1
+
+start_service() {
+ procd_open_instance
+ procd_set_param command /usr/sbin/pcscd --foreground
+ procd_close_instance
+}
+
+reload_service() {
+ /usr/sbin/pcscd --hotplug
+}
diff --git a/external/subpack/utils/pcsc-tools/Makefile b/external/subpack/utils/pcsc-tools/Makefile
new file mode 100644
index 0000000..76ad658
--- /dev/null
+++ b/external/subpack/utils/pcsc-tools/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2017 Daniel Engberg <daniel.engberg.lists@pyret.net>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=pcsc-tools
+PKG_VERSION:=1.5.7
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://ludovic.rousseau.free.fr/softwares/pcsc-tools/
+PKG_HASH:=e0ea8f8496d5bcf5316da913869ba95b925d0405c2aaade801c0d6ce7697699d
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/pcsc-tools
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libpcsclite
+ TITLE:=pcsc-tools
+ URL:=http://ludovic.rousseau.free.fr/softwares/pcsc-tools/
+endef
+
+define Package/pcsc-tools/description
+ Tools that are used to test a PC/SC driver, card or reader.
+ Only includes pcsc_scan without ATR analysis for now.
+endef
+
+define Package/pcsc-tools/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/pcsc_scan $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,pcsc-tools))
diff --git a/external/subpack/utils/pcsc-tools/patches/001-disable-atr.patch b/external/subpack/utils/pcsc-tools/patches/001-disable-atr.patch
new file mode 100644
index 0000000..fcca4cd
--- /dev/null
+++ b/external/subpack/utils/pcsc-tools/patches/001-disable-atr.patch
@@ -0,0 +1,14 @@
+Disable the analyze ATR perl-script and as we don't want to pull in perl
+as a dependency.
+
+--- a/pcsc_scan.c
++++ b/pcsc_scan.c
+@@ -241,7 +241,7 @@ static void initialize_options(options_t
+ #ifdef WIN32
+ options->analyse_atr = False;
+ #else
+- options->analyse_atr = True;
++ options->analyse_atr = False;
+ #endif
+ options->stress_card = False;
+ options->print_version = False;
diff --git a/external/subpack/utils/picocom/Makefile b/external/subpack/utils/picocom/Makefile
new file mode 100644
index 0000000..40f152d
--- /dev/null
+++ b/external/subpack/utils/picocom/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=picocom
+PKG_VERSION:=3.1
+PKG_RELEASE:=5
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/npat-efault/picocom/tar.gz/$(PKG_VERSION)?
+PKG_HASH:=e6761ca932ffc6d09bd6b11ff018bdaf70b287ce518b3282d29e0270e88420bb
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE:=LICENSE.txt
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/picocom
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=A minimal dumb-terminal emulation program
+ URL:=https://github.com/npat-efault/picocom
+ SUBMENU:=Terminal
+endef
+
+define Package/picocom/description
+ minimal dumb-terminal emulation program
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS) \
+ CFLAGS="$(TARGET_CFLAGS)" LDFLAGS="$(TARGET_LDFLAGS)" \
+ picocom
+endef
+
+define Package/picocom/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/picocom $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,picocom))
diff --git a/external/subpack/utils/picocom/patches/010-fix-compile.patch b/external/subpack/utils/picocom/patches/010-fix-compile.patch
new file mode 100644
index 0000000..b05231f
--- /dev/null
+++ b/external/subpack/utils/picocom/patches/010-fix-compile.patch
@@ -0,0 +1,10 @@
+--- a/Makefile
++++ b/Makefile
+@@ -51,7 +51,6 @@ linenoise-1.0/linenoise.o : linenoise-1.
+
+ OBJS += picocom.o term.o fdio.o split.o termios2.o custbaud_bsd.o
+ picocom : $(OBJS)
+- $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
+
+ picocom.o : picocom.c term.h fdio.h split.h custbaud.h
+ term.o : term.c term.h termios2.h custbaud_bsd.h custbaud.h
diff --git a/external/subpack/utils/picocom/patches/020-fix-compile-x86.patch b/external/subpack/utils/picocom/patches/020-fix-compile-x86.patch
new file mode 100644
index 0000000..92b0400
--- /dev/null
+++ b/external/subpack/utils/picocom/patches/020-fix-compile-x86.patch
@@ -0,0 +1,39 @@
+From 6fad89a36968fe1bf6aed63f44b7e2e375271e76 Mon Sep 17 00:00:00 2001
+From: Nick Patavalis <npat@efault.net>
+Date: Thu, 12 Apr 2018 15:16:04 +0300
+Subject: [PATCH] Compile with libc's without cispeed / cospeed
+
+Some libc implementations (e.g. musl) do not define the cispeed and
+cospeed struct termios fields. So we have to check the
+_HAVE_STRUCT_TERMIOS_C_ISPEED and _HAVE_STRUCT_TERMIOS_C_OSPEED
+macros. If not defined, we disable custom baudrate support.
+---
+ custbaud.h | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/custbaud.h
++++ b/custbaud.h
+@@ -26,6 +26,8 @@
+ #ifndef CUSTBAUD_H
+ #define CUSTBAUD_H
+
++#include <termios.h>
++
+ #ifndef NO_CUSTOM_BAUD
+
+ #if defined (__linux__)
+@@ -33,7 +35,13 @@
+ /* Enable by-default for kernels > 2.6.0 on x86 and x86_64 only */
+ #include <linux/version.h>
+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
+-#if defined (__i386__) || defined (__x86_64__) || defined (USE_CUSTOM_BAUD)
++/* Some libc implementations (e.g. musl) do not define the cispeed and
++ cospeed struct termios fields. We do not support custom baudrates
++ on them. */
++#if ( (defined (__i386__) || defined (__x86_64__)) \
++ && defined (_HAVE_STRUCT_TERMIOS_C_ISPEED) \
++ && defined (_HAVE_STRUCT_TERMIOS_C_OSPEED) ) \
++ || defined (USE_CUSTOM_BAUD)
+ #ifndef USE_CUSTOM_BAUD
+ #define USE_CUSTOM_BAUD
+ #endif
diff --git a/external/subpack/utils/picocom/patches/030-usleep.patch b/external/subpack/utils/picocom/patches/030-usleep.patch
new file mode 100644
index 0000000..27b20d1
--- /dev/null
+++ b/external/subpack/utils/picocom/patches/030-usleep.patch
@@ -0,0 +1,63 @@
+From 84fdd943aee9fdf199f6668145246d3021527c29 Mon Sep 17 00:00:00 2001
+From: Rosen Penev <rosenp@gmail.com>
+Date: Sun, 11 Oct 2020 22:10:45 -0700
+Subject: [PATCH] remove usleep
+
+usleep is removed in POSIX 2008.
+
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+---
+ term.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/term.c
++++ b/term.c
+@@ -33,6 +33,7 @@
+ #include <stdio.h>
+ #include <string.h>
+ #include <errno.h>
++#include <time.h>
+ #include <unistd.h>
+ #include <termios.h>
+ #ifdef USE_FLOCK
+@@ -1588,6 +1589,8 @@ term_drain(int fd)
+
+ rval = 0;
+
++ struct timespec s;
++
+ do { /* dummy */
+
+ r = term_find(fd);
+@@ -1614,7 +1617,10 @@ term_drain(int fd)
+ the port is immediately reconfigured, even after a
+ drain. (I guess, drain does not wait for everything to
+ actually be transitted on the wire). */
+- if ( DRAIN_DELAY ) usleep(DRAIN_DELAY);
++ if ( DRAIN_DELAY ) {
++ struct timespec d = {0, DRAIN_DELAY * 1000};
++ nanosleep(&d, &s);
++ }
+
+ } while (0);
+
+@@ -1627,6 +1633,7 @@ int
+ term_fake_flush(int fd)
+ {
+ struct termios tio;
++ struct timespec s;
+ int rval, i, r;
+
+ rval = 0;
+@@ -1666,7 +1673,10 @@ term_fake_flush(int fd)
+ break;
+ }
+ /* see comment in term_drain */
+- if ( DRAIN_DELAY ) usleep(DRAIN_DELAY);
++ if ( DRAIN_DELAY ) {
++ struct timespec d = {0, DRAIN_DELAY * 1000};
++ nanosleep(&d, &s);
++ }
+ /* Reset flow-control to original setting. */
+ r = tcsetattr(fd, TCSANOW, &term.currtermios[i]);
+ if ( r < 0 ) {
diff --git a/external/subpack/utils/pigz/Makefile b/external/subpack/utils/pigz/Makefile
new file mode 100644
index 0000000..7f76a08
--- /dev/null
+++ b/external/subpack/utils/pigz/Makefile
@@ -0,0 +1,35 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=pigz
+PKG_VERSION:=2.4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://zlib.net/pigz/
+PKG_HASH:=a4f816222a7b4269bd232680590b579ccc72591f1bb5adafcd7208ca77e14f73
+
+PKG_MAINTAINER:=Ken Wong <xinxijishuwyq@gmail.com>
+PKG_LICENSE:=CUSTOM
+PKG_LICENSE_FILES:=README
+PKG_CPE_ID:=cpe:/a:zlib:pigz
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/pigz
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Compression
+ TITLE:=pigz
+ URL:=https://zlib.net/pigz
+ DEPENDS:=+zlib
+endef
+
+define Package/pigz/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/pigz $(1)/usr/bin/pigz
+endef
+
+$(eval $(call BuildPackage,pigz))
+
diff --git a/external/subpack/utils/pigz/patches/001.patch b/external/subpack/utils/pigz/patches/001.patch
new file mode 100644
index 0000000..bdd910c
--- /dev/null
+++ b/external/subpack/utils/pigz/patches/001.patch
@@ -0,0 +1,14 @@
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+-CC=gcc
+-CFLAGS=-O3 -Wall -Wextra -Wno-unknown-pragmas
+-LDFLAGS=
+-LIBS=-lm -lpthread -lz
++CC?=gcc
++CFLAGS?=-O3 -Wall -Wextra -Wno-unknown-pragmas
++LDFLAGS?=
++LIBS?=-lm -lpthread -lz
+ ZOPFLI=zopfli/src/zopfli/
+ ZOP=deflate.o blocksplitter.o tree.o lz77.o cache.o hash.o util.o squeeze.o katajainen.o
+
diff --git a/external/subpack/utils/podman/Makefile b/external/subpack/utils/podman/Makefile
new file mode 100644
index 0000000..e8323d4
--- /dev/null
+++ b/external/subpack/utils/podman/Makefile
@@ -0,0 +1,114 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=podman
+PKG_VERSION:=3.4.1
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/containers/podman/archive/v$(PKG_VERSION)
+PKG_HASH:=3fa70c499a4733524354518e839eefa3f14b630a519393418d082880535c1e33
+
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+PKG_MAINTAINER:=Oskari Rauta <oskari.rauta@gmail.com>
+
+PKG_BUILD_DEPENDS:=golang/host protobuf/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/containers/podman/
+GO_PKG_BUILD_PKG:=github.com/containers/podman/v3/cmd/podman/
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Download/default-registries
+ URL:=https://raw.githubusercontent.com/projectatomic/registries/da9a9c87781823f45401ca49da04e269c9e3100e
+ URL_FILE:=registries.fedora
+ FILE:=registries.fedora-da9a9c8778
+ HASH:=bc2b58c209aa8ca35b6814ec9a3c64716d4970b884ade460b65000e56024dfee
+endef
+
+define Download/default-policy
+ URL:=https://raw.githubusercontent.com/containers/skopeo/362f70b056a1f5d2bd4184527a0ae0d20c4d35d3
+ URL_FILE:=default-policy.json
+ FILE:=default-policy.json-362f70b056
+ HASH:=cddfaa8e6a7e5497b67cc0dd8e8517058d0c97de91bf46fff867528415f2d946
+endef
+
+define Package/podman/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Podman
+ URL:=https://podman.io
+endef
+
+define Package/podman
+ $(call Package/podman/Default)
+ DEPENDS:=$(GO_ARCH_DEPENDS) +conmon +cni +cni-plugins +btrfs-progs +glib2 +gnupg2 +iptables +libgpg-error +libseccomp +libgpgme +nsenter +zoneinfo-simple +kmod-veth
+ CONFLICTS:=podman-selinux
+ VARIANT:=default
+ PROVIDES:=podman
+endef
+
+define Package/podman-selinux
+ $(call Package/podman/Default)
+ TITLE += with SELinux support
+ DEPENDS:=$(GO_ARCH_DEPENDS) +conmon +cni +cni-plugins +btrfs-progs +glib2 +gnupg2 +iptables +libgpg-error +libseccomp +libgpgme +nsenter +zoneinfo-simple +kmod-veth +libselinux
+ VARIANT:=selinux
+ PROVIDES:=podman
+endef
+
+define Package/podman/description
+ Podman: A tool for managing OCI containers and pods
+endef
+
+define Package/podman-selinux/description
+ Podman: A tool for managing OCI containers and pods
+ SELinux enabled.
+endef
+
+define Package/podman/conffiles
+/etc/containers/policy.json
+/etc/containers/storage.conf
+/etc/containers/registries.conf
+/etc/containers/containers.conf
+/etc/cni/net.d/87-podman-bridge.conflist
+endef
+
+Package/podman-selinux/conffiles = $(Package/podman/conffiles)
+
+ifeq ($(BUILD_VARIANT),selinux)
+ GO_PKG_TAGS=seccomp,exclude_graphdriver_devicemapper,selinux,apparmor
+else
+ GO_PKG_TAGS=seccomp,exclude_graphdriver_devicemapper,apparmor
+endif
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(eval $(call Download,default-registries))
+ $(eval $(call Download,default-policy))
+endef
+
+define Package/podman/install
+ $(call GoPackage/Package/Install/Bin,$(1))
+ $(INSTALL_DIR) $(1)/etc/containers
+ $(INSTALL_DATA) $(DL_DIR)/default-policy.json-362f70b056 $(1)/etc/containers/policy.json
+ $(INSTALL_DATA) $(DL_DIR)/registries.fedora-da9a9c8778 $(1)/etc/containers/registries.conf
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/vendor/github.com/containers/storage/storage.conf $(1)/etc/containers/storage.conf
+ $(INSTALL_DATA) ./files/containers.conf $(1)/etc/containers/containers.conf
+ $(INSTALL_DIR) $(1)/etc/cni/net.d
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/cni/87-podman-bridge.conflist $(1)/etc/cni/net.d/
+ $(INSTALL_DIR) $(1)/usr/share/containers
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/vendor/github.com/containers/common/pkg/seccomp/seccomp.json $(1)/usr/share/containers/
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/podman.init $(1)/etc/init.d/podman
+ $(SED) 's/driver = \"\"/driver = \"overlay\"/g' $(1)/etc/containers/storage.conf
+endef
+
+Package/podman-selinux/install = $(Package/podman/install)
+
+$(eval $(call GoBinPackage,podman))
+$(eval $(call BuildPackage,podman))
+$(eval $(call GoBinPackage,podman-selinux))
+$(eval $(call BuildPackage,podman-selinux))
diff --git a/external/subpack/utils/podman/files/containers.conf b/external/subpack/utils/podman/files/containers.conf
new file mode 100644
index 0000000..3dbaab1
--- /dev/null
+++ b/external/subpack/utils/podman/files/containers.conf
@@ -0,0 +1,76 @@
+#https://github.com/containers/common/blob/main/pkg/config/containers.conf
+
+[containers]
+#annotations = []
+#apparmor_profile = "container-default"
+cgroupns = "private"
+cgroups = "enabled"
+netns = "private"
+#pidns = "private"
+#rootless_networking = "slirp4netns"
+#seccomp_profile = "/usr/share/containers/seccomp.json"
+#shm_size = "65536k"
+
+default_capabilities = [
+ "CHOWN",
+ "DAC_OVERRIDE",
+ "FOWNER",
+ "FSETID",
+ "KILL",
+ "NET_BIND_SERVICE",
+ "SETFCAP",
+ "SETGID",
+ "SETPCAP",
+ "SETUID",
+ "SYS_CHROOT"
+]
+
+default_sysctls = [
+ "net.ipv4.ping_group_range=0 0",
+]
+
+[network]
+cni_plugin_dirs = [
+ "/usr/lib/cni"
+]
+network_config_dir = "/etc/cni/net.d/"
+default_network = "podman"
+
+[engine]
+cgroup_manager = "cgroupfs"
+events_logger = "none"
+#image_default_transport = "docker://"
+#image_parallel_copies = 0
+#infra_command = "/pause"
+#infra_image = "k8s.gcr.io/pause:3.4.1"
+#lock_type** = "shm"
+#namespace = ""
+#network_cmd_path = ""
+
+runtime = "crun"
+# runtime = "runc"
+# runtime = "uxc"
+
+runtime_supports_json = ["crun", "runc", "kata", "uxc"]
+#runtime_supports_kvm = ["kata", "krun"]
+#runtime_supports_nocgroups = ["crun", "krun", "uxc"]
+#static_dir = "/var/lib/containers/storage/libpod"
+
+[engine.runtimes]
+crun = [
+ "/usr/bin/crun",
+]
+
+runc = [
+ "/usr/sbin/runc",
+]
+
+uxc = [
+ "/sbin/uxc",
+]
+
+[machine]
+#cpus = 1
+#disk_size = 10
+#image = "testing"
+#memory = 2048
diff --git a/external/subpack/utils/podman/files/podman.init b/external/subpack/utils/podman/files/podman.init
new file mode 100755
index 0000000..fe85646
--- /dev/null
+++ b/external/subpack/utils/podman/files/podman.init
@@ -0,0 +1,20 @@
+#!/bin/sh /etc/rc.common
+
+START=99
+STOP=10
+USE_PROCD=1
+NAME=podman
+PROG=/usr/bin/podman
+
+start_service() {
+ [ -d /run/podman ] || mkdir -p /run/podman
+ procd_open_instance "podman"
+ procd_set_param command "$PROG" system service --time=0
+ procd_append_param command $command
+ procd_close_instance
+}
+
+shutdown() {
+ ${PROG} pod stop -a
+ ${PROG} container stop -a
+}
diff --git a/external/subpack/utils/powertop/Makefile b/external/subpack/utils/powertop/Makefile
new file mode 100644
index 0000000..68953d4
--- /dev/null
+++ b/external/subpack/utils/powertop/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2019 Lucian Cristain <lucian.cristian@gmail.com>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=powertop
+PKG_VERSION:=2.10
+PKG_RELEASE:=4
+
+PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://01.org/sites/default/files/downloads/
+PKG_HASH:=d3b7459eaba7d01c8841dd33a3b4d369416c01e9bd8951b0d88234cf18fe4a75
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-v$(PKG_VERSION)
+PKG_MAINTAINER:=Lucian Cristain <lucian.cristian@gmail.com>
+PKG_LICENSE:=GPL-2.0
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/uclibc++.mk
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/powertop
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=$(CXX_DEPENDS) $(INTL_DEPENDS) +libpci +libncursesw +libnl-genl
+ TITLE:=Power consumption monitor
+ URL:=https://01.org/powertop
+endef
+
+define Package/powertop/description
+ PowerTOP is a Linux tool to diagnose issues with power consumption
+ and power management.
+endef
+
+TARGET_LDFLAGS += \
+ $(if $(INTL_FULL),-lintl) \
+ $(if $(CONFIG_USE_GLIBC),-lm) \
+ $(if $(CONFIG_USE_GLIBC),-lpthread)
+
+define Package/powertop/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/powertop \
+ $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,powertop))
diff --git a/external/subpack/utils/powertop/patches/002-strerror_r.patch b/external/subpack/utils/powertop/patches/002-strerror_r.patch
new file mode 100644
index 0000000..7612a85
--- /dev/null
+++ b/external/subpack/utils/powertop/patches/002-strerror_r.patch
@@ -0,0 +1,20 @@
+--- a/traceevent/event-parse.c
++++ b/traceevent/event-parse.c
+@@ -5121,12 +5121,17 @@ int pevent_strerror(struct pevent *peven
+ const char *msg;
+
+ if (errnum >= 0) {
++#if defined(__GLIBC__)
+ msg = strerror_r(errnum, buf, buflen);
+ if (msg != buf) {
+ size_t len = strlen(msg);
+ memcpy(buf, msg, min(buflen - 1, len));
+ *(buf + min(buflen - 1, len)) = '\0';
+ }
++#else
++ if (strerror_r(errnum, buf, buflen))
++ snprintf(buf, buflen, "errnum %i", errnum);
++#endif
+ return 0;
+ }
+
diff --git a/external/subpack/utils/powertop/patches/010-src-main-Add-missing-pthread-header.patch b/external/subpack/utils/powertop/patches/010-src-main-Add-missing-pthread-header.patch
new file mode 100644
index 0000000..7af8efe
--- /dev/null
+++ b/external/subpack/utils/powertop/patches/010-src-main-Add-missing-pthread-header.patch
@@ -0,0 +1,33 @@
+From 7235a786ea30ae5ca7c1b3458ef5b2388c08dfd9 Mon Sep 17 00:00:00 2001
+From: Rosen Penev <rosenp@gmail.com>
+Date: Thu, 28 Mar 2019 18:44:27 -0700
+Subject: [PATCH] src/main: Add missing pthread header
+
+Otherwise compilation can fail with:
+
+main.cpp: In function 'void one_measurement(int, int, char*)':
+main.cpp:226:3: error: 'pthread_t' was not declared in this scope
+ pthread_t thread = 0UL;
+ ^~~~~~~~~
+main.cpp:226:3: note: suggested alternative: 'pread'
+ pthread_t thread = 0UL;
+ ^~~~~~~~~
+ pread
+
+et al.
+
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+---
+ src/main.cpp | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/src/main.cpp
++++ b/src/main.cpp
+@@ -39,6 +39,7 @@
+ #include <locale.h>
+ #include <sys/resource.h>
+ #include <limits.h>
++#include <pthread.h>
+
+ #include "cpu/cpu.h"
+ #include "process/process.h"
diff --git a/external/subpack/utils/powertop/patches/020-intel_cpus.cpp-Change-open-parameter-to-const-char.patch b/external/subpack/utils/powertop/patches/020-intel_cpus.cpp-Change-open-parameter-to-const-char.patch
new file mode 100644
index 0000000..6dd77ef
--- /dev/null
+++ b/external/subpack/utils/powertop/patches/020-intel_cpus.cpp-Change-open-parameter-to-const-char.patch
@@ -0,0 +1,25 @@
+From 8cdf846922ffb3e0d2a828be473fdf9c45a56e7c Mon Sep 17 00:00:00 2001
+From: Rosen Penev <rosenp@gmail.com>
+Date: Sat, 30 Mar 2019 20:19:17 -0700
+Subject: [PATCH] intel_cpus.cpp: Change open parameter to const char *
+
+ifstream::open takes std::string starting with C++11, not before.
+
+This fixes compilation with uClibc++ and potentially other older libraries
+
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+---
+ src/cpu/intel_cpus.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/src/cpu/intel_cpus.cpp
++++ b/src/cpu/intel_cpus.cpp
+@@ -92,7 +92,7 @@ int is_supported_intel_cpu(int model, in
+
+ int is_intel_pstate_driver_loaded()
+ {
+- const string filename("/sys/devices/system/cpu/cpu0/cpufreq/scaling_driver");
++ const char *filename = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_driver";
+ const string intel_pstate("intel_pstate");
+ char line[32] = { '\0' };
+ ifstream file;
diff --git a/external/subpack/utils/pps-tools/Makefile b/external/subpack/utils/pps-tools/Makefile
new file mode 100644
index 0000000..cbcb82b
--- /dev/null
+++ b/external/subpack/utils/pps-tools/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=pps-tools
+PKG_VERSION:=1.0.2
+PKG_RELEASE:=2
+
+PKG_SOURCE_URL:=https://codeload.github.com/redlab-i/pps-tools/tar.gz/v$(PKG_VERSION)?
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_HASH:=1a7efd66152e5439b69143f1f380b40ac5decbbbef516b37a017410b8ba7dff4
+
+PKG_MAINTAINER:=Zoltan HERPAI <wigyori@uid0.hu>
+PKG_LICENSE:=GPL-2.0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/pps-tools
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=PPS-tools
+endef
+
+define Package/pps-tools/description
+ Userland tools for GPS and DCF-77 Clock synchronization. PPS support in Kernel must be enabled.
+endef
+
+TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/sys
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/timepps.h $(1)/usr/include/sys/
+endef
+
+define Package/pps-tools/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ppsctl $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ppstest $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ppswatch $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,pps-tools))
diff --git a/external/subpack/utils/pps-tools/patches/001-time_t_64bit.patch b/external/subpack/utils/pps-tools/patches/001-time_t_64bit.patch
new file mode 100644
index 0000000..aacd8be
--- /dev/null
+++ b/external/subpack/utils/pps-tools/patches/001-time_t_64bit.patch
@@ -0,0 +1,31 @@
+--- a/ppstest.c
++++ b/ppstest.c
+@@ -110,13 +110,13 @@ retry:
+ }
+
+ printf("source %d - "
+- "assert %ld.%09ld, sequence: %ld - "
+- "clear %ld.%09ld, sequence: %ld\n",
++ "assert %lld.%09ld, sequence: %ld - "
++ "clear %lld.%09ld, sequence: %ld\n",
+ i,
+- infobuf.assert_timestamp.tv_sec,
++ (long long)infobuf.assert_timestamp.tv_sec,
+ infobuf.assert_timestamp.tv_nsec,
+ infobuf.assert_sequence,
+- infobuf.clear_timestamp.tv_sec,
++ (long long)infobuf.clear_timestamp.tv_sec,
+ infobuf.clear_timestamp.tv_nsec, infobuf.clear_sequence);
+ fflush(stdout);
+
+--- a/ppswatch.c
++++ b/ppswatch.c
+@@ -145,7 +145,7 @@ int fetch_source(pps_handle_t handle, in
+ if (max_divergence < div)
+ max_divergence = div;
+ if (div >= margin) {
+- printf("timestamp: %ld, sequence: %ld, offset: % 6ld\n", ts.tv_sec, seq, ts.tv_nsec);
++ printf("timestamp: %lld, sequence: %ld, offset: % 6ld\n", (long long)ts.tv_sec, seq, ts.tv_nsec);
+ fflush(stdout);
+ overflows++;
+ curr_unsync++;
diff --git a/external/subpack/utils/procps-ng/Makefile b/external/subpack/utils/procps-ng/Makefile
new file mode 100644
index 0000000..2ded481
--- /dev/null
+++ b/external/subpack/utils/procps-ng/Makefile
@@ -0,0 +1,116 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=procps-ng
+PKG_VERSION:=4.0.4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@SF/procps-ng
+PKG_HASH:=22870d6feb2478adb617ce4f09a787addaf2d260c5a8aa7b17d889a962c5e42e
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING COPYING.LIB
+PKG_CPE_ID:=cpe:/a:procps-ng_project:procps-ng
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+CONFIGURE_ARGS += --enable-skill
+
+# most of these have alternatives provided by busybox applets
+PROCPS_APPLETS := \
+ free kill pgrep pkill pmap ps pwdx skill slabtop \
+ snice sysctl tload top uptime vmstat w watch
+
+# procps-ng will be configured with "--bindir=/usr/bin --sbindir=/usr/sbin" and
+# as such executables will be installed there by default, but some of them need
+# to reside in locations such as /bin and /sbin to be in accordance with
+# busybox alternatives which is also other distributions like debian and centos
+# are doing
+PROCPS_APPLETS_SRC_DIR_SBIN:=sysctl
+procps-applets-src-dir=$(if $(filter $(PROCPS_APPLETS_SRC_DIR_SBIN),$(1)),/usr/sbin,/usr/bin)
+
+PROCPS_APPLETS_DIR_BIN:=kill ps watch
+PROCPS_APPLETS_DIR_SBIN:=sysctl
+procps-applets-dir=$(if $(filter $(PROCPS_APPLETS_DIR_BIN),$(1)),/bin,$(if $(filter $(PROCPS_APPLETS_DIR_SBIN),$(1)),/sbin,/usr/bin))
+
+define Package/procps-ng/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libncurses
+ TITLE:=procps-ng utilities
+ URL:=https://gitlab.com/procps-ng/procps
+endef
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ echo "$(PKG_VERSION)" > "$(PKG_BUILD_DIR)/.tarball-version"
+endef
+
+define Package/procps-ng
+ $(call Package/procps-ng/Default)
+ MENU:=1
+endef
+
+define Package/procps-ng/description
+ procps is a set of command line and full-screen utilities that provide information out of the pseudo-filesystem
+ most commonly located at /proc. This filesystem provides a simple interface to the kernel data structures.
+ The programs of procps generally concentrate on the structures that describe the processess running on the system.
+
+ NOTE: some utilities provided by procps-ng packages (ps, uptime, kill, ...) are installed as busybox applets, by default.
+ Conflicting applets should be removed from the build to avoid file conflicts.
+endef
+
+define GenPlugin
+ define Package/procps-ng-$(1)
+ $(call Package/procps-ng/Default)
+ DEPENDS:=procps-ng
+ TITLE:=Applet $(1) from the procps-ng package
+ ALTERNATIVES:=200:$(2)/$(1):/usr/libexec/$(1)-procps-ng
+ endef
+
+ define Package/procps-ng-$(1)/description
+ Installs the applet $(1).
+ endef
+endef
+
+$(foreach a,$(PROCPS_APPLETS),$(eval $(call GenPlugin,$(a),$(call procps-applets-dir,$(a)))))
+
+MAKE_FLAGS += \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ CPPFLAGS="$(TARGET_CPPFLAGS)" \
+ LDFLAGS="$(TARGET_LDFLAGS)" \
+
+define Package/procps-ng/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libproc2.so* $(1)/usr/lib/
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/* $(1)/usr/lib/
+endef
+
+define BuildPlugin
+ define Package/procps-ng-$(1)/install
+ $(INSTALL_DIR) $$(1)/usr/libexec
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)$(2)/$(1) $$(1)/usr/libexec/$(1)-procps-ng
+ endef
+
+ $$(eval $$(call BuildPackage,procps-ng-$(1)))
+endef
+
+$(foreach a,$(PROCPS_APPLETS),$(eval $(call BuildPlugin,$(a),$(call procps-applets-src-dir,$(a)))))
+$(eval $(call BuildPackage,procps-ng))
diff --git a/external/subpack/utils/procps-ng/patches/100-no-tests-docs.patch b/external/subpack/utils/procps-ng/patches/100-no-tests-docs.patch
new file mode 100644
index 0000000..d9dd229
--- /dev/null
+++ b/external/subpack/utils/procps-ng/patches/100-no-tests-docs.patch
@@ -0,0 +1,26 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -18,10 +18,7 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
+
+ ACLOCAL_AMFLAGS = -I m4
+ SUBDIRS = \
+- local \
+- po-man \
+- po \
+- testsuite
++ local
+
+ AM_CFLAGS = -Ilibrary/include
+ LDADD = ./library/libproc2.la $(CYGWINFLAGS)
+--- a/configure.ac
++++ b/configure.ac
+@@ -421,8 +421,5 @@ AC_CHECK_FUNCS([__fpending alarm atexit
+
+ AC_CONFIG_FILES([Makefile
+ local/Makefile
+- po-man/Makefile
+- po/Makefile.in
+- library/libproc2.pc
+- testsuite/Makefile])
++ library/libproc2.pc])
+ AC_OUTPUT
diff --git a/external/subpack/utils/procps-ng3/Makefile b/external/subpack/utils/procps-ng3/Makefile
new file mode 100644
index 0000000..1235dd6
--- /dev/null
+++ b/external/subpack/utils/procps-ng3/Makefile
@@ -0,0 +1,63 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=procps-ng3
+PKG_VERSION:=3.3.17
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/procps-$(PKG_VERSION)
+PKG_SOURCE:=procps-ng-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@SF/procps-ng
+PKG_HASH:=4518b3e7aafd34ec07d0063d250fd474999b20b200218c3ae56f5d2113f141b4
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING COPYING.LIB
+PKG_CPE_ID:=cpe:/a:procps-ng_project:procps-ng
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/procps-ng3
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libncurses
+ TITLE:=procps-ng old compatibility library
+ URL:=https://gitlab.com/procps-ng/procps
+endef
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ echo "$(PKG_VERSION)" > "$(PKG_BUILD_DIR)/.tarball-version"
+endef
+
+define Package/procps-ng3/description
+ Compatibility library of old 3.x version of procps-ng utilities.
+endef
+
+MAKE_FLAGS += \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ CPPFLAGS="$(TARGET_CPPFLAGS)" \
+ LDFLAGS="$(TARGET_LDFLAGS)" \
+
+define Package/procps-ng3/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libprocps.so* $(1)/usr/lib/
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,procps-ng3))
diff --git a/external/subpack/utils/procps-ng3/patches/100-no-tests-docs.patch b/external/subpack/utils/procps-ng3/patches/100-no-tests-docs.patch
new file mode 100644
index 0000000..e4277c9
--- /dev/null
+++ b/external/subpack/utils/procps-ng3/patches/100-no-tests-docs.patch
@@ -0,0 +1,26 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -15,10 +15,7 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
+
+ ACLOCAL_AMFLAGS = -I m4
+ SUBDIRS = \
+- include \
+- man-po \
+- po \
+- testsuite
++ include
+
+ AM_CFLAGS = -Iproc
+ LDADD = ./proc/libprocps.la $(CYGWINFLAGS)
+--- a/configure.ac
++++ b/configure.ac
+@@ -323,8 +323,5 @@ AC_CHECK_FUNCS([__fpending alarm atexit
+
+ AC_CONFIG_FILES([Makefile
+ include/Makefile
+- man-po/Makefile
+- po/Makefile.in
+- proc/libprocps.pc
+- testsuite/Makefile])
++ proc/libprocps.pc])
+ AC_OUTPUT
diff --git a/external/subpack/utils/procps-ng3/patches/110-musl-fixes.patch b/external/subpack/utils/procps-ng3/patches/110-musl-fixes.patch
new file mode 100644
index 0000000..b8830f1
--- /dev/null
+++ b/external/subpack/utils/procps-ng3/patches/110-musl-fixes.patch
@@ -0,0 +1,27 @@
+From https://git.alpinelinux.org/aports/tree/community/procps-compat/musl-fixes.patch?id=781a465d3d41af56a6e4bf9d52b7273c87899e25
+
+--- a/w.c
++++ b/w.c
+@@ -55,11 +55,7 @@
+ #include <termios.h>
+ #include <time.h>
+ #include <unistd.h>
+-#ifdef HAVE_UTMPX_H
+-# include <utmpx.h>
+-#else
+-# include <utmp.h>
+-#endif
++#include <utmp.h>
+ #include <arpa/inet.h>
+
+ static int ignoreuser = 0; /* for '-u' */
+--- a/proc/escape.c
++++ b/proc/escape.c
+@@ -21,6 +21,7 @@
+ #include <sys/types.h>
+ #include <string.h>
+ #include <limits.h>
++#include <langinfo.h>
+ #include "procps.h"
+ #include "escape.h"
+ #include "readproc.h"
diff --git a/external/subpack/utils/progress/Makefile b/external/subpack/utils/progress/Makefile
new file mode 100644
index 0000000..6ed0c31
--- /dev/null
+++ b/external/subpack/utils/progress/Makefile
@@ -0,0 +1,55 @@
+#
+# Copyright (C) 2016 Nikil Mehta <nikil.mehta@gmail.com>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=progress
+PKG_VERSION:=0.15
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/Xfennec/progress/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=1ed0ac65a912ef1aa605d524eaddaacae92079cf71182096a7c65cbc61687d1b
+
+PKG_MAINTAINER:=Nikil Mehta <nikil.mehta@gmail.com>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/progress
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Coreutils Progress Viewer (formerly known as 'cv')
+ URL:=https://github.com/Xfennec/progress
+ DEPENDS:=+libncursesw
+endef
+
+define Package/progress/description
+ This tool can be described as a Tiny, Dirty, Linux-and-OSX-Only
+ C command that looks for coreutils basic commands (cp, mv, dd, tar,
+ gzip/gunzip, cat, etc.) currently running on your system and
+ displays the percentage of copied data. It can also show estimated
+ time and throughput, and provide a "top-like" mode (monitoring).
+ .
+ It simply scans `/proc` for interesting commands, and then looks at
+ directories `fd` and `fdinfo` to find opened files and seek positions,
+ and reports status for the largest file.
+ .
+ It's very light, and compatible with virtually any command.
+ This program was formerly known as 'cv' on github.
+endef
+
+define Package/progress/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/local/bin/progress $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,progress))
diff --git a/external/subpack/utils/progress/patches/001_set-ncurses-lib.patch b/external/subpack/utils/progress/patches/001_set-ncurses-lib.patch
new file mode 100644
index 0000000..558a12c
--- /dev/null
+++ b/external/subpack/utils/progress/patches/001_set-ncurses-lib.patch
@@ -0,0 +1,25 @@
+--- a/Makefile
++++ b/Makefile
+@@ -1,21 +1,7 @@
+ OBJ = progress
+ CFLAGS ?= -g
+ override CFLAGS += -Wall -D_FILE_OFFSET_BITS=64
+-override LDFLAGS += -lm
+-UNAME := $(shell uname)
+-PKG_CONFIG ?= pkg-config
+-ifeq ($(UNAME), Linux)
+- ifeq (, $(shell which $(PKG_CONFIG) 2> /dev/null))
+- $(error "pkg-config command not found")
+- endif
+- ifeq (, $(shell $(PKG_CONFIG) ncurses --libs 2> /dev/null))
+- $(error "ncurses package not found")
+- endif
+- override LDFLAGS += $(shell $(PKG_CONFIG) ncurses --libs)
+-endif
+-ifeq ($(UNAME), Darwin)
+- override LDFLAGS += -lncurses
+-endif
++override LDFLAGS += -lm -lncursesw
+ PREFIX ?= /usr/local
+ BINDIR = $(PREFIX)/bin
+ MANDIR = $(PREFIX)/share/man/man1
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/Makefile b/external/subpack/utils/prometheus-node-exporter-lua/Makefile
new file mode 100644
index 0000000..843b22f
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/Makefile
@@ -0,0 +1,243 @@
+#
+# Copyright (C) 2013-2017 OpenWrt.org
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=prometheus-node-exporter-lua
+PKG_VERSION:=2022.04.18
+PKG_RELEASE:=1
+
+PKG_MAINTAINER:=Etienne CHAMPETIER <champetier.etienne@gmail.com>
+PKG_LICENSE:=Apache-2.0
+
+include $(INCLUDE_DIR)/package.mk
+
+Build/Compile=
+
+define Package/prometheus-node-exporter-lua/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Prometheus node exporter
+ PKGARCH:=all
+endef
+
+define Package/prometheus-node-exporter-lua
+ $(call Package/prometheus-node-exporter-lua/Default)
+ DEPENDS:=+luasocket +lua
+endef
+
+define Package/prometheus-node-exporter-lua/install
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) ./files/etc/config/prometheus-node-exporter-lua $(1)/etc/config/prometheus-node-exporter-lua
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/etc/init.d/prometheus-node-exporter-lua $(1)/etc/init.d/prometheus-node-exporter-lua
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) ./files/usr/bin/prometheus-node-exporter-lua $(1)/usr/bin/prometheus-node-exporter-lua
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/cpu.lua $(1)/usr/lib/lua/prometheus-collectors/
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/conntrack.lua $(1)/usr/lib/lua/prometheus-collectors/
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/filefd.lua $(1)/usr/lib/lua/prometheus-collectors/
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/loadavg.lua $(1)/usr/lib/lua/prometheus-collectors/
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/meminfo.lua $(1)/usr/lib/lua/prometheus-collectors/
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/netdev.lua $(1)/usr/lib/lua/prometheus-collectors/
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/time.lua $(1)/usr/lib/lua/prometheus-collectors/
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/uname.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua/conffiles
+/etc/config/prometheus-node-exporter-lua
+endef
+
+define Package/prometheus-node-exporter-lua/description
+ Provides node metrics as Prometheus scraping endpoint.
+
+ This service is a lightweight rewrite in LUA of the offical Prometheus node_exporter.
+endef
+
+# Additional optional exporters:
+
+define Package/prometheus-node-exporter-lua-bmx6
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (bmx6 links collector)
+ DEPENDS:=prometheus-node-exporter-lua bmx6 +lua-cjson +bmx6-json
+endef
+
+define Package/prometheus-node-exporter-lua-bmx6/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/bmx6.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-bmx7
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (bmx7 links collector)
+ DEPENDS:=prometheus-node-exporter-lua bmx7 +lua-cjson +bmx7-json
+endef
+
+define Package/prometheus-node-exporter-lua-bmx7/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/bmx7.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-dawn
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (dawn collector)
+ DEPENDS:=prometheus-node-exporter-lua +libiwinfo-lua +libubus-lua
+endef
+
+define Package/prometheus-node-exporter-lua-dawn/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/dawn.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-hostapd_stations
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (hostapd_stations collector) - Requires a full hostapd / wpad build
+ DEPENDS:=prometheus-node-exporter-lua +hostapd-utils +lua-bit32 +libubus-lua
+endef
+
+define Package/prometheus-node-exporter-lua-hostapd_stations/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/hostapd_stations.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-hostapd_ubus_stations
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (hostapd_ubus_stations collector)
+ DEPENDS:=prometheus-node-exporter-lua +luabitop +libubus-lua
+endef
+
+define Package/prometheus-node-exporter-lua-hostapd_ubus_stations/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/hostapd_ubus_stations.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-ltq-dsl
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (lantiq dsl collector)
+ DEPENDS:=prometheus-node-exporter-lua @(PACKAGE_ltq-adsl-app||PACKAGE_ltq-vdsl-app)
+endef
+
+define Package/prometheus-node-exporter-lua-ltq-dsl/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/ltq-dsl.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-nat_traffic
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (nat_traffic collector)
+ DEPENDS:=prometheus-node-exporter-lua
+endef
+
+define Package/prometheus-node-exporter-lua-nat_traffic/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/nat_traffic.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-netstat
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (netstat collector)
+ DEPENDS:=prometheus-node-exporter-lua
+endef
+
+define Package/prometheus-node-exporter-lua-netstat/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/netstat.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-openwrt
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (openwrt collector)
+ DEPENDS:=prometheus-node-exporter-lua +libubus-lua
+endef
+
+define Package/prometheus-node-exporter-lua-openwrt/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/openwrt.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-textfile
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (textfile collector)
+ifeq (0,)
+ DEPENDS:=prometheus-node-exporter-lua +luci-lib-nixio
+else
+ DEPENDS:=prometheus-node-exporter-lua
+endif
+endef
+
+define Package/prometheus-node-exporter-lua-textfile/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/textfile.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-ubnt-manager
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (ubnt-manager collector)
+ DEPENDS:=prometheus-node-exporter-lua +ubnt-manager +lua-cjson
+endef
+
+define Package/prometheus-node-exporter-lua-ubnt-manager/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/ubnt-manager.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-uci_dhcp_host
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (uci_dhcp_host collector)
+ DEPENDS:=prometheus-node-exporter-lua +libuci-lua
+endef
+
+define Package/prometheus-node-exporter-lua-uci_dhcp_host/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/uci_dhcp_host.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-wifi
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (wifi collector)
+ DEPENDS:=prometheus-node-exporter-lua +libiwinfo-lua +libubus-lua
+endef
+
+define Package/prometheus-node-exporter-lua-wifi/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/wifi.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-wifi_stations
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (wifi_stations collector)
+ DEPENDS:=prometheus-node-exporter-lua +libiwinfo-lua +libubus-lua
+endef
+
+define Package/prometheus-node-exporter-lua-wifi_stations/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/wifi_stations.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+define Package/prometheus-node-exporter-lua-snmp6
+ $(call Package/prometheus-node-exporter-lua/Default)
+ TITLE+= (snmp6 collector)
+ DEPENDS:=prometheus-node-exporter-lua +libubus-lua
+endef
+
+define Package/prometheus-node-exporter-lua-snmp6/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/prometheus-collectors
+ $(INSTALL_BIN) ./files/usr/lib/lua/prometheus-collectors/snmp6.lua $(1)/usr/lib/lua/prometheus-collectors/
+endef
+
+$(eval $(call BuildPackage,prometheus-node-exporter-lua))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-bmx6))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-bmx7))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-dawn))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-hostapd_stations))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-hostapd_ubus_stations))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-ltq-dsl))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-nat_traffic))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-netstat))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-openwrt))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-textfile))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-ubnt-manager))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-uci_dhcp_host))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-wifi))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-wifi_stations))
+$(eval $(call BuildPackage,prometheus-node-exporter-lua-snmp6))
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/etc/config/prometheus-node-exporter-lua b/external/subpack/utils/prometheus-node-exporter-lua/files/etc/config/prometheus-node-exporter-lua
new file mode 100644
index 0000000..585e29b
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/etc/config/prometheus-node-exporter-lua
@@ -0,0 +1,4 @@
+config prometheus-node-exporter-lua 'main'
+ option listen_interface 'loopback'
+ option listen_ipv6 '0'
+ option listen_port '9100'
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/etc/init.d/prometheus-node-exporter-lua b/external/subpack/utils/prometheus-node-exporter-lua/files/etc/init.d/prometheus-node-exporter-lua
new file mode 100644
index 0000000..582e211
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/etc/init.d/prometheus-node-exporter-lua
@@ -0,0 +1,59 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2013-2017 OpenWrt.org
+
+START=60
+USE_PROCD=1
+
+_log() {
+ logger -p daemon.info -t prometheus-node-exporter-lua "$@"
+}
+
+start_service() {
+ . /lib/functions/network.sh
+
+ local interface ipv6 port bind
+
+ config_load prometheus-node-exporter-lua.main
+ config_get interface "main" listen_interface "loopback"
+ config_get_bool ipv6 "main" listen_ipv6 0
+ config_get port "main" listen_port 9100
+
+ if [ "$interface" = "*" ]; then
+ [ "$ipv6" = 1 ] && bind="::" || bind="0.0.0.0"
+ else
+ if [ "$ipv6" = 1 ]; then
+ network_get_ipaddr6 bind "$interface"
+ else
+ network_get_ipaddr bind "$interface"
+ fi
+
+ network_is_up "$interface" && [ -n "$bind" ] || {
+ _log "defering start until listen interface $interface becomes ready"
+ return 0
+ }
+ fi
+
+ procd_open_instance
+
+ procd_set_param command /usr/bin/prometheus-node-exporter-lua
+ procd_append_param command --bind ${bind}
+ procd_append_param command --port ${port}
+
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_set_param respawn
+
+ procd_close_instance
+}
+
+service_triggers()
+{
+ local interface
+
+ procd_add_reload_trigger "prometheus-node-exporter-lua"
+
+ config_load prometheus-node-exporter-lua.main
+ config_get interface "main" listen_interface "loopback"
+
+ [ "$interface" = "*" ] || procd_add_reload_interface_trigger "$interface"
+}
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/bin/prometheus-node-exporter-lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/bin/prometheus-node-exporter-lua
new file mode 100755
index 0000000..35addf1
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/bin/prometheus-node-exporter-lua
@@ -0,0 +1,148 @@
+#!/usr/bin/lua
+
+-- Metrics web server
+
+-- Copyright (c) 2016 Jeff Schornick <jeff@schornick.org>
+-- Copyright (c) 2015 Kevin Lyda
+-- Licensed under the Apache License, Version 2.0
+
+socket = require("socket")
+
+-- Parsing
+
+function space_split(s)
+ local elements = {}
+ for element in s:gmatch("%S+") do
+ table.insert(elements, element)
+ end
+ return elements
+end
+
+function get_contents(filename)
+ local f = io.open(filename, "rb")
+ local contents = ""
+ if f then
+ contents = f:read "*a"
+ f:close()
+ end
+
+ return contents
+end
+
+-- Metric printing
+
+function print_metric(metric, labels, value)
+ local label_string = ""
+ if labels then
+ for label,value in pairs(labels) do
+ label_string = label_string .. label .. '="' .. value .. '",'
+ end
+ label_string = "{" .. string.sub(label_string, 1, -2) .. "}"
+ end
+ output(string.format("%s%s %s", metric, label_string, value))
+end
+
+function metric(name, mtype, labels, value)
+ output("# TYPE " .. name .. " " .. mtype)
+ local outputter = function(labels, value)
+ print_metric(name, labels, value)
+ end
+ if value then
+ outputter(labels, value)
+ end
+ return outputter
+end
+
+function timed_scrape(collector)
+ local start_time = socket.gettime()
+ local success = 1
+ local status, err = pcall(collector.scrape)
+ if not status then
+ success = 0
+ print(err)
+ end
+ return (socket.gettime() - start_time), success
+end
+
+function run_all_collectors(collectors)
+ local metric_duration = metric("node_scrape_collector_duration_seconds", "gauge")
+ local metric_success = metric("node_scrape_collector_success", "gauge")
+ for _,cname in pairs(collectors) do
+ if col_mods[cname] ~= nil then
+ local duration, success = timed_scrape(col_mods[cname])
+ local labels = {collector=cname}
+ metric_duration(labels, duration)
+ metric_success(labels, success)
+ end
+ end
+end
+
+-- Web server-specific functions
+
+function http_ok_header()
+ output("HTTP/1.0 200 OK\r\nServer: lua-metrics\r\nContent-Type: text/plain; version=0.0.4\r\n\r")
+end
+
+function http_not_found()
+ output("HTTP/1.0 404 Not Found\r\nServer: lua-metrics\r\nContent-Type: text/plain\r\n\r\nERROR: File Not Found.")
+end
+
+function serve(request)
+ local q = request:match("^GET /metrics%??([^ ]*) HTTP/1%.[01]$")
+ if q == nil then
+ http_not_found()
+ else
+ http_ok_header()
+ local cols = {}
+ for c in q:gmatch("collect[^=]*=([^&]+)") do
+ cols[#cols+1] = c
+ end
+ if #cols == 0 then
+ cols = col_names
+ end
+ run_all_collectors(cols)
+ end
+ client:close()
+ return true
+end
+
+-- Main program
+
+for k,v in ipairs(arg) do
+ if (v == "-p") or (v == "--port") then
+ port = arg[k+1]
+ end
+ if (v == "-b") or (v == "--bind") then
+ bind = arg[k+1]
+ end
+end
+
+col_mods = {}
+col_names = {}
+ls_fd = io.popen("ls -1 /usr/lib/lua/prometheus-collectors/*.lua")
+for c in ls_fd:lines() do
+ c = c:match("([^/]+)%.lua$")
+ col_mods[c] = require('prometheus-collectors.'..c)
+ col_names[#col_names+1] = c
+end
+ls_fd:close()
+
+if port then
+ server = assert(socket.bind(bind, port))
+
+ while 1 do
+ client = server:accept()
+ client:settimeout(60)
+ local request, err = client:receive()
+
+ if not err then
+ output = function (str) client:send(str.."\n") end
+ if not serve(request) then
+ break
+ end
+ end
+ end
+else
+ output = print
+ run_all_collectors(col_names)
+end
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/bmx6.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/bmx6.lua
new file mode 100644
index 0000000..6b6c118
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/bmx6.lua
@@ -0,0 +1,39 @@
+#!/usr/bin/lua
+
+local json = require "cjson"
+
+local function interpret_suffix(rate)
+ local value = string.sub(rate, 1, -2)
+ local suffix = string.sub(rate, -1)
+ if suffix == "K" then return tonumber(value) * 10^3 end
+ if suffix == "M" then return tonumber(value) * 10^6 end
+ if suffix == "G" then return tonumber(value) * 10^9 end
+ return rate
+end
+
+local function scrape()
+ local status = json.decode(get_contents("/var/run/bmx6/json/status")).status
+ local labels = {
+ version = status.version,
+ id = status.name,
+ address = status.primaryIp
+ }
+
+ metric("bmx6_status", "gauge", labels, 1)
+
+ local links = json.decode(get_contents("/var/run/bmx6/json/links")).links
+ local metric_bmx6_rxRate = metric("bmx6_link_rxRate","gauge")
+ local metric_bmx6_txRate = metric("bmx6_link_txRate","gauge")
+
+ for _, link in pairs(links) do
+ local labels = {
+ source = status.name,
+ target = link.name,
+ dev = link.viaDev
+ }
+ metric_bmx6_rxRate(labels, interpret_suffix(link.rxRate))
+ metric_bmx6_txRate(labels, interpret_suffix(link.txRate))
+ end
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/bmx7.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/bmx7.lua
new file mode 100644
index 0000000..d384d71
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/bmx7.lua
@@ -0,0 +1,66 @@
+#!/usr/bin/lua
+
+local json = require "cjson"
+
+local function interpret_suffix(rate)
+ if rate ~= nil then
+ local value = string.sub(rate, 1, -2)
+ local suffix = string.sub(rate, -1)
+ if suffix == "K" then return tonumber(value) * 10^3 end
+ if suffix == "M" then return tonumber(value) * 10^6 end
+ if suffix == "G" then return tonumber(value) * 10^9 end
+ end
+ return rate
+end
+
+local function scrape()
+ local status = json.decode(get_contents("/var/run/bmx7/json/status")).status
+ local labels = {
+ id = status.shortId,
+ name = status.name,
+ address = status.primaryIp,
+ revision = status.revision,
+ }
+
+ metric("bmx7_status", "gauge", labels, 1)
+ metric("bmx7_cpu_usage", "gauge", nil, status.cpu)
+ metric("bmx7_mem_usage", "gauge", nil, interpret_suffix(status.mem))
+
+ local links = json.decode(get_contents("/var/run/bmx7/json/links")).links
+ local metric_bmx7_rxRate = metric("bmx7_link_rxRate","gauge")
+ local metric_bmx7_txRate = metric("bmx7_link_txRate","gauge")
+
+ for _, link in pairs(links) do
+ local labels = {
+ source = status.shortId,
+ target = link.shortId,
+ name = link.name,
+ dev = link.dev
+ }
+ metric_bmx7_rxRate(labels, interpret_suffix(link.rxRate))
+ metric_bmx7_txRate(labels, interpret_suffix(link.txRate))
+ end
+
+ local metric_bmx7_tunIn = metric("bmx7_tunIn", "gauge")
+ local parameters = json.decode(get_contents("/var/run/bmx7/json/parameters")).OPTIONS
+ for _, option in pairs(parameters) do
+ if option.name == "tunIn" then
+ for _, instance in pairs(option.INSTANCES) do
+ for _, child_instance in pairs(instance.CHILD_INSTANCES) do
+ local labels = {
+ name = instance.value,
+ network = child_instance.value
+ }
+ metric_bmx7_tunIn(labels, 1)
+ end
+ end
+ elseif option.name == "plugin" then
+ local metric_bmx7_plugin = metric("bmx7_plugin", "gauge")
+ for _, instance in pairs(option.INSTANCES) do
+ metric_bmx7_plugin({ name = instance.value }, 1)
+ end
+ end
+ end
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/conntrack.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/conntrack.lua
new file mode 100644
index 0000000..1abb7a1
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/conntrack.lua
@@ -0,0 +1,12 @@
+local function scrape()
+ local count = get_contents("/proc/sys/net/netfilter/nf_conntrack_count")
+ local max = get_contents("/proc/sys/net/netfilter/nf_conntrack_max")
+ if count ~= "" then
+ metric("node_nf_conntrack_entries", "gauge", nil, string.sub(count, 1, -2))
+ end
+ if max ~= "" then
+ metric("node_nf_conntrack_entries_limit", "gauge", nil, string.sub(max, 1, -2))
+ end
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/cpu.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/cpu.lua
new file mode 100644
index 0000000..17e35bf
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/cpu.lua
@@ -0,0 +1,47 @@
+-- stat/cpu collector
+local function scrape()
+ local stat = get_contents("/proc/stat")
+
+ -- system boot time, seconds since epoch
+ metric("node_boot_time_seconds", "gauge", nil,
+ string.match(stat, "btime ([0-9]+)"))
+
+ -- context switches since boot (all CPUs)
+ metric("node_context_switches_total", "counter", nil,
+ string.match(stat, "ctxt ([0-9]+)"))
+
+ -- cpu times, per CPU, per mode
+ local cpu_mode = {"user", "nice", "system", "idle", "iowait", "irq",
+ "softirq", "steal", "guest", "guest_nice"}
+ local i = 0
+ local cpu_metric = metric("node_cpu_seconds_total", "counter")
+ while true do
+ local cpu = {string.match(stat,
+ "cpu"..i.." (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+) (%d+)")}
+ if #cpu ~= 10 then
+ break
+ end
+ for ii, mode in ipairs(cpu_mode) do
+ cpu_metric({cpu="cpu"..i, mode=mode}, cpu[ii] / 100)
+ end
+ i = i + 1
+ end
+
+ -- interrupts served
+ metric("node_intr_total", "counter", nil,
+ string.match(stat, "intr ([0-9]+)"))
+
+ -- processes forked
+ metric("node_forks_total", "counter", nil,
+ string.match(stat, "processes ([0-9]+)"))
+
+ -- processes running
+ metric("node_procs_running_total", "gauge", nil,
+ string.match(stat, "procs_running ([0-9]+)"))
+
+ -- processes blocked for I/O
+ metric("node_procs_blocked_total", "gauge", nil,
+ string.match(stat, "procs_blocked ([0-9]+)"))
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/dawn.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/dawn.lua
new file mode 100644
index 0000000..8c3c4d2
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/dawn.lua
@@ -0,0 +1,53 @@
+local ubus = require "ubus"
+
+local function scrape()
+ local metric_dawn_ap_channel_utilization_ratio = metric("dawn_ap_channel_utilization_ratio","gauge")
+ local metric_dawn_ap_stations_total = metric("dawn_ap_stations_total","gauge")
+ local metric_dawn_station_signal_dbm = metric("dawn_station_signal_dbm","gauge")
+
+ local u = ubus.connect()
+ local network = u:call("dawn", "get_network", {})
+
+ for ssid, ssid_table in pairs(network) do
+ for ap, ap_table in pairs(ssid_table) do
+
+ if (ap_table['local'] == true) then
+
+ local ht_support = (ap_table['ht_support'] == true) and 1 or 0
+ local vht_support = (ap_table['vht_support'] == true) and 1 or 0
+
+ local labels = {
+ ssid = ssid,
+ bssid = ap,
+ freq = ap_table['freq'],
+ hostname = ap_table['hostname'],
+ ht_support = ht_support,
+ vht_support = vht_support,
+ neighbor_report = ap_table['neighbor_report'],
+ }
+ metric_dawn_ap_channel_utilization_ratio(labels, ap_table['channel_utilization'] / 255)
+ metric_dawn_ap_stations_total(labels, ap_table['num_sta'])
+
+ for client, client_table in pairs(ap_table) do
+ if (type(client_table) == "table") then
+
+ local client_ht_support = (client_table['ht'] == true) and 1 or 0
+ local client_vht_support = (client_table['vht'] == true) and 1 or 0
+ local client_signal = client_table['signal'] or -255
+
+ local labels_client_signal = {
+ ssid = ssid,
+ bssid = ap,
+ mac = client,
+ ht_support = client_ht_support,
+ vht_support = client_vht_support,
+ }
+ metric_dawn_station_signal_dbm(labels_client_signal, client_signal)
+ end
+ end
+ end
+ end
+ end
+end
+
+return { scrape = scrape }
\ No newline at end of file
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/filefd.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/filefd.lua
new file mode 100644
index 0000000..7e2ff63
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/filefd.lua
@@ -0,0 +1,8 @@
+local function scrape()
+ local file_nr = space_split(get_contents("/proc/sys/fs/file-nr"))
+
+ metric("node_filefd_allocated", "gauge", nil, file_nr[1])
+ metric("node_filefd_maximum", "gauge", nil, file_nr[3])
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/hostapd_stations.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/hostapd_stations.lua
new file mode 100644
index 0000000..5e141e6
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/hostapd_stations.lua
@@ -0,0 +1,110 @@
+local ubus = require "ubus"
+local bit32 = require "bit32"
+
+local function get_wifi_interfaces()
+ local u = ubus.connect()
+ local status = u:call("network.wireless", "status", {})
+ local interfaces = {}
+
+ for _, dev_table in pairs(status) do
+ for _, intf in ipairs(dev_table['interfaces']) do
+ table.insert(interfaces, intf['ifname'])
+ end
+ end
+
+ return interfaces
+end
+
+local function scrape()
+ local metric_hostapd_station_vht = metric("hostapd_station_vht", "gauge")
+ local metric_hostapd_station_ht = metric("hostapd_station_ht", "gauge")
+ local metric_hostapd_station_wmm = metric("hostapd_station_wmm", "gauge")
+ local metric_hostapd_station_mfp = metric("hostapd_station_mfp", "gauge")
+
+ local metric_hostapd_station_rx_packets = metric("hostapd_station_rx_packets", "counter")
+ local metric_hostapd_station_rx_bytes = metric("hostapd_station_rx_bytes", "counter")
+ local metric_hostapd_station_tx_packets = metric("hostapd_station_tx_packets", "counter")
+ local metric_hostapd_station_tx_bytes = metric("hostapd_station_tx_bytes", "counter")
+
+ local metric_hostapd_station_inactive_msec = metric("hostapd_station_inactive_msec", "counter")
+
+ local metric_hostapd_station_signal = metric("hostapd_station_signal", "gauge")
+ local metric_hostapd_station_connected_time = metric("hostapd_station_connected_time", "counter")
+
+ local metric_hostapd_station_wpa = metric("hostapd_station_wpa", "gauge")
+ local metric_hostapd_station_sae_group = metric("hostapd_station_sae_group", "gauge")
+
+ local metric_hostapd_station_vht_capb_su_beamformee = metric("hostapd_station_vht_capb_su_beamformee", "gauge")
+ local metric_hostapd_station_vht_capb_mu_beamformee = metric("hostapd_station_vht_capb_mu_beamformee", "gauge")
+
+ local function evaluate_metrics(ifname, station, vals)
+ local label_station = {
+ ifname = ifname,
+ station = station,
+ }
+
+ for k, v in pairs(vals) do
+ if k == "flags" then
+ if string.match(v, "[VHT]") then
+ metric_hostapd_station_vht(label_station, 1)
+ end
+ if string.match(v, "[HT]") then
+ metric_hostapd_station_ht(label_station, 1)
+ end
+ if string.match(v, "[WMM]") then
+ metric_hostapd_station_wmm(label_station, 1)
+ end
+ if string.match(v, "[MFP]") then
+ metric_hostapd_station_mfp(label_station, 1)
+ end
+ elseif k == "wpa" then
+ metric_hostapd_station_wpa(label_station, v)
+ elseif k == "rx_packets" then
+ metric_hostapd_station_rx_packets(label_station, v)
+ elseif k == "rx_bytes" then
+ metric_hostapd_station_rx_bytes(label_station, v)
+ elseif k == "tx_packets" then
+ metric_hostapd_station_tx_packets(label_station, v)
+ elseif k == "tx_bytes" then
+ metric_hostapd_station_tx_bytes(label_station, v)
+ elseif k == "inactive_msec" then
+ metric_hostapd_station_inactive_msec(label_station, v)
+ elseif k == "signal" then
+ metric_hostapd_station_signal(label_station, v)
+ elseif k == "connected_time" then
+ metric_hostapd_station_connected_time(label_station, v)
+ elseif k == "sae_group" then
+ metric_hostapd_station_sae_group(label_station, v)
+ elseif k == "vht_caps_info" then
+ local caps = tonumber(string.gsub(v, "0x", ""), 16)
+ metric_hostapd_station_vht_capb_su_beamformee(label_station, bit32.band(bit32.lshift(1, 12), caps) > 0 and 1 or 0)
+ metric_hostapd_station_vht_capb_mu_beamformee(label_station, bit32.band(bit32.lshift(1, 20), caps) > 0 and 1 or 0)
+ end
+ end
+ end
+
+ for _, ifname in ipairs(get_wifi_interfaces()) do
+ local handle = io.popen("hostapd_cli -i " .. ifname .." all_sta")
+ local all_sta = handle:read("*a")
+ handle:close()
+
+ local current_station = nil
+ local current_station_values = {}
+
+ for line in all_sta:gmatch("[^\r\n]+") do
+ if string.match(line, "^%x[0123456789aAbBcCdDeE]:%x%x:%x%x:%x%x:%x%x:%x%x$") then
+ if current_station ~= nil then
+ evaluate_metrics(ifname, current_station, current_station_values)
+ end
+ current_station = line
+ current_station_values = {}
+ else
+ local name, value = string.match(line, "(.+)=(.+)")
+ current_station_values[name] = value
+ end
+ end
+ evaluate_metrics(ifname, current_station, current_station_values)
+ end
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/hostapd_ubus_stations.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/hostapd_ubus_stations.lua
new file mode 100644
index 0000000..88a993c
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/hostapd_ubus_stations.lua
@@ -0,0 +1,68 @@
+local ubus = require "ubus"
+local bit = require "bit"
+
+local function get_wifi_interfaces() -- based on hostapd_stations.lua
+ local u = ubus.connect()
+ local status = u:call("network.wireless", "status", {})
+ local interfaces = {}
+
+ for _, dev_table in pairs(status) do
+ for _, intf in ipairs(dev_table['interfaces']) do
+ table.insert(interfaces, intf['ifname'])
+ end
+ end
+
+ return interfaces
+end
+
+local function scrape()
+ local metric_hostapd_ubus_station_rrm_caps_link_measurement =
+ metric("hostapd_ubus_station_rrm_caps_link_measurement", "gauge")
+ local metric_hostapd_ubus_station_rrm_caps_neighbor_report =
+ metric("hostapd_ubus_station_rrm_caps_neighbor_report", "gauge")
+ local metric_hostapd_ubus_station_rrm_caps_beacon_report_passive =
+ metric("hostapd_ubus_station_rrm_caps_beacon_report_passive", "gauge")
+ local metric_hostapd_ubus_station_rrm_caps_beacon_report_active =
+ metric("hostapd_ubus_station_rrm_caps_beacon_report_active", "gauge")
+ local metric_hostapd_ubus_station_rrm_caps_beacon_report_table =
+ metric("hostapd_ubus_station_rrm_caps_beacon_report_table", "gauge")
+ local metric_hostapd_ubus_station_rrm_caps_lci_measurement =
+ metric("hostapd_ubus_station_rrm_caps_lci_measurement", "gauge")
+ local metric_hostapd_ubus_station_rrm_caps_ftm_range_report =
+ metric("hostapd_ubus_station_rrm_caps_ftm_range_report", "gauge")
+
+ local function evaluate_metrics(ifname, freq, station, vals)
+ local label_station = {
+ ifname = ifname,
+ freq = freq,
+ station = station
+ }
+ local rrm_caps_link_measurement = bit.band(bit.lshift(1, 0), vals['rrm'][1]) > 0 and 1 or 0
+ local rrm_caps_neighbor_report = bit.band(bit.lshift(1, 1), vals['rrm'][1]) > 0 and 1 or 0
+ local rrm_caps_beacon_report_passive = bit.band(bit.lshift(1, 4), vals['rrm'][1]) > 0 and 1 or 0
+ local rrm_caps_beacon_report_active = bit.band(bit.lshift(1, 5), vals['rrm'][1]) > 0 and 1 or 0
+ local rrm_caps_beacon_report_table = bit.band(bit.lshift(1, 6), vals['rrm'][1]) > 0 and 1 or 0
+ local rrm_caps_lci_measurement = bit.band(bit.lshift(1, 4), vals['rrm'][2]) > 0 and 1 or 0
+ local rrm_caps_ftm_range_report = bit.band(bit.lshift(1, 2), vals['rrm'][5]) > 0 and 1 or 0
+
+ metric_hostapd_ubus_station_rrm_caps_link_measurement(label_station, rrm_caps_link_measurement)
+ metric_hostapd_ubus_station_rrm_caps_neighbor_report(label_station, rrm_caps_neighbor_report)
+ metric_hostapd_ubus_station_rrm_caps_beacon_report_passive(label_station, rrm_caps_beacon_report_passive)
+ metric_hostapd_ubus_station_rrm_caps_beacon_report_active(label_station, rrm_caps_beacon_report_active)
+ metric_hostapd_ubus_station_rrm_caps_beacon_report_table(label_station, rrm_caps_beacon_report_table)
+
+ metric_hostapd_ubus_station_rrm_caps_lci_measurement(label_station, rrm_caps_lci_measurement)
+ metric_hostapd_ubus_station_rrm_caps_ftm_range_report(label_station, rrm_caps_ftm_range_report)
+ end
+
+ for _, ifname in ipairs(get_wifi_interfaces()) do
+ local u = ubus.connect()
+ local clients_call = u:call("hostapd." .. ifname, "get_clients", {})
+
+ for client, client_table in pairs(clients_call['clients']) do
+ evaluate_metrics(ifname, clients_call['freq'], client, client_table)
+ end
+ end
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/loadavg.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/loadavg.lua
new file mode 100644
index 0000000..6bfab89
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/loadavg.lua
@@ -0,0 +1,9 @@
+local function scrape()
+ local loadavg = space_split(get_contents("/proc/loadavg"))
+
+ metric("node_load1", "gauge", nil, loadavg[1])
+ metric("node_load5", "gauge", nil, loadavg[2])
+ metric("node_load15", "gauge", nil, loadavg[3])
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/ltq-dsl.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/ltq-dsl.lua
new file mode 100644
index 0000000..0a33fa4
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/ltq-dsl.lua
@@ -0,0 +1,86 @@
+local ubus = require "ubus"
+
+local function scrape()
+ local dsl_line_attenuation = metric("dsl_line_attenuation_db", "gauge")
+ local dsl_signal_attenuation = metric("dsl_signal_attenuation_db", "gauge")
+ local dsl_snr = metric("dsl_signal_to_noise_margin_db", "gauge")
+ local dsl_aggregated_transmit_power = metric("dsl_aggregated_transmit_power_db", "gauge")
+ local dsl_latency = metric("dsl_latency_seconds", "gauge")
+ local dsl_datarate = metric("dsl_datarate", "gauge")
+ local dsl_max_datarate = metric("dsl_max_datarate", "gauge")
+ local dsl_error_seconds_total = metric("dsl_error_seconds_total", "counter")
+ local dsl_errors_total = metric("dsl_errors_total", "counter")
+
+ local u = ubus.connect()
+ local m = u:call("dsl", "metrics", {})
+
+ -- dsl hardware/firmware information
+ metric("dsl_info", "gauge", {
+ atuc_vendor = m.atu_c.vendor,
+ atuc_system_vendor = m.atu_c.system_vendor,
+ chipset = m.chipset,
+ firmware_version = m.firmware_version,
+ api_version = m.api_version,
+ }, 1)
+
+ -- dsl line settings information
+ metric("dsl_line_info", "gauge", {
+ annex = m.annex,
+ mode = m.mode,
+ profile = m.profile,
+ }, 1)
+
+ local dsl_up
+ if m.up then
+ dsl_up = 1
+ else
+ dsl_up = 0
+ end
+
+ metric("dsl_up", "gauge", {
+ detail = m.state,
+ }, dsl_up)
+
+ -- dsl line status data
+ metric("dsl_uptime_seconds", "gauge", {}, m.uptime)
+
+ -- dsl db measurements
+ dsl_line_attenuation({direction="down"}, m.downstream.latn)
+ dsl_line_attenuation({direction="up"}, m.upstream.latn)
+ dsl_signal_attenuation({direction="down"}, m.downstream.satn)
+ dsl_signal_attenuation({direction="up"}, m.upstream.satn)
+ dsl_snr({direction="down"}, m.downstream.snr)
+ dsl_snr({direction="up"}, m.upstream.snr)
+ dsl_aggregated_transmit_power({direction="down"}, m.downstream.actatp)
+ dsl_aggregated_transmit_power({direction="up"}, m.upstream.actatp)
+
+ -- dsl performance data
+ if m.downstream.interleave_delay ~= nil then
+ dsl_latency({direction="down"}, m.downstream.interleave_delay / 1000000)
+ dsl_latency({direction="up"}, m.upstream.interleave_delay / 1000000)
+ end
+ dsl_datarate({direction="down"}, m.downstream.data_rate)
+ dsl_datarate({direction="up"}, m.upstream.data_rate)
+ dsl_max_datarate({direction="down"}, m.downstream.attndr)
+ dsl_max_datarate({direction="up"}, m.upstream.attndr)
+
+ -- dsl errors
+ dsl_error_seconds_total({err="forward error correction", loc="near"}, m.errors.near.fecs)
+ dsl_error_seconds_total({err="forward error correction", loc="far"}, m.errors.far.fecs)
+ dsl_error_seconds_total({err="errored", loc="near"}, m.errors.near.es)
+ dsl_error_seconds_total({err="errored", loc="far"}, m.errors.far.es)
+ dsl_error_seconds_total({err="severely errored", loc="near"}, m.errors.near.ses)
+ dsl_error_seconds_total({err="severely errored", loc="far"}, m.errors.far.ses)
+ dsl_error_seconds_total({err="loss of signal", loc="near"}, m.errors.near.loss)
+ dsl_error_seconds_total({err="loss of signal", loc="far"}, m.errors.far.loss)
+ dsl_error_seconds_total({err="unavailable", loc="near"}, m.errors.near.uas)
+ dsl_error_seconds_total({err="unavailable", loc="far"}, m.errors.far.uas)
+ dsl_errors_total({err="header error code error", loc="near"}, m.errors.near.hec)
+ dsl_errors_total({err="header error code error", loc="far"}, m.errors.far.hec)
+ dsl_errors_total({err="non pre-emptive crc error", loc="near"}, m.errors.near.crc_p)
+ dsl_errors_total({err="non pre-emptive crc error", loc="far"}, m.errors.far.crc_p)
+ dsl_errors_total({err="pre-emptive crc error", loc="near"}, m.errors.near.crcp_p)
+ dsl_errors_total({err="pre-emptive crc error", loc="far"}, m.errors.far.crcp_p)
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/meminfo.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/meminfo.lua
new file mode 100644
index 0000000..cf836e3
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/meminfo.lua
@@ -0,0 +1,12 @@
+local function scrape()
+ for line in io.lines("/proc/meminfo") do
+ local name, size, unit = string.match(line, "([^:]+):%s+(%d+)%s?(k?B?)")
+ if unit == 'kB' then
+ size = size * 1024
+ end
+ metric("node_memory_"..name:gsub("[):]", ""):gsub("[(]", "_").."_bytes",
+ "gauge", nil, size)
+ end
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/nat_traffic.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/nat_traffic.lua
new file mode 100644
index 0000000..0b2da7d
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/nat_traffic.lua
@@ -0,0 +1,31 @@
+local function scrape()
+ -- documetation about nf_conntrack:
+ -- https://www.frozentux.net/iptables-tutorial/chunkyhtml/x1309.html
+ nat_metric = metric("node_nat_traffic", "gauge" )
+ for e in io.lines("/proc/net/nf_conntrack") do
+ -- output(string.format("%s\n",e ))
+ local fields = space_split(e)
+ local src, dest, bytes;
+ bytes = 0;
+ for _, field in ipairs(fields) do
+ if src == nil and string.match(field, '^src') then
+ src = string.match(field,"src=([^ ]+)");
+ elseif dest == nil and string.match(field, '^dst') then
+ dest = string.match(field,"dst=([^ ]+)");
+ elseif string.match(field, '^bytes') then
+ local b = string.match(field, "bytes=([^ ]+)");
+ bytes = bytes + b;
+ -- output(string.format("\t%d %s",ii,field ));
+ end
+
+ end
+ -- local src, dest, bytes = string.match(natstat[i], "src=([^ ]+) dst=([^ ]+) .- bytes=([^ ]+)");
+ -- local src, dest, bytes = string.match(natstat[i], "src=([^ ]+) dst=([^ ]+) sport=[^ ]+ dport=[^ ]+ packets=[^ ]+ bytes=([^ ]+)")
+
+ local labels = { src = src, dest = dest }
+ -- output(string.format("src=|%s| dest=|%s| bytes=|%s|", src, dest, bytes ))
+ nat_metric(labels, bytes )
+ end
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/netdev.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/netdev.lua
new file mode 100644
index 0000000..679b2f3
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/netdev.lua
@@ -0,0 +1,39 @@
+
+local netdevsubstat = {
+ "receive_bytes_total",
+ "receive_packets_total",
+ "receive_errs_total",
+ "receive_drop_total",
+ "receive_fifo_total",
+ "receive_frame_total",
+ "receive_compressed_total",
+ "receive_multicast_total",
+ "transmit_bytes_total",
+ "transmit_packets_total",
+ "transmit_errs_total",
+ "transmit_drop_total",
+ "transmit_fifo_total",
+ "transmit_colls_total",
+ "transmit_carrier_total",
+ "transmit_compressed_total"
+}
+
+local pattern = "([^%s:]+):%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)"
+
+local function scrape()
+ local nds_table = {}
+ for line in io.lines("/proc/net/dev") do
+ local t = {string.match(line, pattern)}
+ if #t == 17 then
+ nds_table[t[1]] = t
+ end
+ end
+ for i, ndss in ipairs(netdevsubstat) do
+ netdev_metric = metric("node_network_" .. ndss, "counter")
+ for dev, nds_dev in pairs(nds_table) do
+ netdev_metric({device=dev}, nds_dev[i+1])
+ end
+ end
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/netstat.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/netstat.lua
new file mode 100644
index 0000000..d30a14c
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/netstat.lua
@@ -0,0 +1,28 @@
+local netsubstat = {
+ "IcmpMsg",
+ "Icmp",
+ "IpExt",
+ "Ip",
+ "TcpExt",
+ "Tcp",
+ "UdpLite",
+ "Udp"
+}
+
+local function scrape()
+ local netstat = get_contents("/proc/net/netstat") .. get_contents("/proc/net/snmp")
+
+ -- all devices
+ for i, nss in ipairs(netsubstat) do
+ local substat_s = string.match(netstat, nss .. ": ([A-Z][A-Za-z0-9 ]+)")
+ if substat_s then
+ local substat = space_split(substat_s)
+ local substatv = space_split(string.match(netstat, nss .. ": ([0-9 -]+)"))
+ for ii, ss in ipairs(substat) do
+ metric("node_netstat_" .. nss .. "_" .. ss, "gauge", nil, substatv[ii])
+ end
+ end
+ end
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/openwrt.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/openwrt.lua
new file mode 100644
index 0000000..8d44792
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/openwrt.lua
@@ -0,0 +1,24 @@
+local ubus = require "ubus"
+local u = ubus.connect()
+local b = u:call("system", "board", {})
+
+local labels = {
+ board_name = b.board_name,
+ id = b.release.distribution,
+ model = b.model,
+ release = b.release.version,
+ revision = b.release.revision,
+ system = b.system,
+ target = b.release.target
+}
+
+b = nil
+u = nil
+ubus = nil
+
+local function scrape()
+ metric("node_openwrt_info", "gauge", labels, 1)
+end
+
+return { scrape = scrape }
+
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/snmp6.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/snmp6.lua
new file mode 100644
index 0000000..663d1b5
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/snmp6.lua
@@ -0,0 +1,39 @@
+local ubus = require "ubus"
+
+local function get_devices() -- based on hostapd_stations.lua
+ local u = ubus.connect()
+ local status = u:call("network.device", "status", {})
+ local devices = {}
+
+ for dev, dev_table in pairs(status) do
+ table.insert(devices, dev)
+ end
+ return devices
+end
+
+local function get_metric(device)
+ local label = {
+ device = device
+ }
+
+ if device == "all" then
+ for e in io.lines("/proc/net/snmp6") do
+ local snmp6 = space_split(e)
+ metric("snmp6_" .. snmp6[1], "counter", label, tonumber(snmp6[2]))
+ end
+ else
+ for e in io.lines("/proc/net/dev_snmp6/" .. device) do
+ local snmp6 = space_split(e)
+ metric("snmp6_" .. snmp6[1], "counter", label, tonumber(snmp6[2]))
+ end
+ end
+end
+
+local function scrape()
+ get_metric("all")
+ for _, devicename in ipairs(get_devices()) do
+ get_metric(devicename)
+ end
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/textfile.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/textfile.lua
new file mode 100644
index 0000000..118177f
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/textfile.lua
@@ -0,0 +1,11 @@
+#!/usr/bin/lua
+
+local fs = require "nixio.fs"
+
+local function scrape()
+ for metrics in fs.glob("/var/prometheus/*.prom") do
+ output(get_contents(metrics), '\n')
+ end
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/time.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/time.lua
new file mode 100644
index 0000000..2cd68c0
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/time.lua
@@ -0,0 +1,6 @@
+local function scrape()
+ -- current time
+ metric("node_time_seconds", "gauge", nil, os.time())
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/ubnt-manager.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/ubnt-manager.lua
new file mode 100644
index 0000000..0093859
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/ubnt-manager.lua
@@ -0,0 +1,145 @@
+local function get_devices()
+ local handle = io.popen("ubnt-manager -l")
+ local result = handle:read("*a")
+ handle:close()
+
+ local devices = {}
+ for device in result:gmatch("%S+") do table.insert(devices, device) end
+ return devices
+end
+
+local function get_metric_airos6(device_data, label, label_full)
+ -- host
+ metric("ubnt_uptime", "counter", label_full, device_data['host']['uptime'])
+ metric("ubnt_totalram", "gauge", label, device_data['host']['totalram'])
+ metric("ubnt_freeram", "gauge", label, device_data['host']['freeram'])
+ metric("ubnt_cpuload", "gauge", label, device_data['host']['cpuload'])
+ metric("ubnt_cpubusy", "gauge", label, device_data['host']['cpubusy'])
+ metric("ubnt_cputotal", "gauge", label, device_data['host']['cputotal'])
+
+ -- wireless
+ metric("ubnt_channel", "gauge", label, device_data['wireless']['channel'])
+ local freqstring = {}
+ for freq in device_data['wireless']['frequency']:gmatch("%S+") do
+ table.insert(freqstring, freq)
+ end
+ if freqstring[1] then
+ metric("ubnt_frequency", "gauge", label, tonumber(freqstring[1]))
+ end
+
+ metric("ubnt_dfs", "gauge", label, tonumber(device_data['wireless']['dfs']))
+ metric("ubnt_signal", "gauge", label, device_data['wireless']['signal'])
+ metric("ubnt_rssi", "gauge", label, device_data['wireless']['rssi'])
+ metric("ubnt_noisef", "gauge", label, device_data['wireless']['noisef'])
+ metric("ubnt_txpower", "gauge", label, device_data['wireless']['txpower'])
+ metric("ubnt_distance", "gauge", label, device_data['wireless']['distance'])
+ metric("ubnt_txrate", "gauge", label,
+ tonumber(device_data['wireless']['txrate']))
+ metric("ubnt_rxrate", "gauge", label,
+ tonumber(device_data['wireless']['rxrate']))
+ metric("ubnt_count", "gauge", label, device_data['wireless']['count'])
+end
+
+local function get_metric_airos8(device_data, label, label_full)
+ -- host
+ metric("ubnt_uptime", "counter", label_full, device_data['host']['uptime'])
+ metric("ubnt_loadavg", "gauge", label, device_data['host']['loadavg'])
+ metric("ubnt_totalram", "gauge", label, device_data['host']['totalram'])
+ metric("ubnt_freeram", "gauge", label, device_data['host']['freeram'])
+ metric("ubnt_temperature", "gauge", label,
+ device_data['host']['temperature'])
+ metric("ubnt_cpuload", "gauge", label, device_data['host']['cpuload'])
+ metric("ubnt_timestamp", "counter", label, device_data['host']['timestamp'])
+
+ -- wireless
+ metric("ubnt_band", "gauge", label, device_data['wireless']['band'])
+ metric("ubnt_frequency", "gauge", label,
+ device_data['wireless']['frequency'])
+ metric("ubnt_center1_freq", "gauge", label,
+ device_data['wireless']['center1_freq'])
+ metric("ubnt_dfs", "gauge", label, device_data['wireless']['dfs'])
+ metric("ubnt_distance", "gauge", label, device_data['wireless']['distance'])
+ metric("ubnt_noisef", "gauge", label, device_data['wireless']['noisef'])
+ metric("ubnt_txpower", "gauge", label, device_data['wireless']['txpower'])
+ metric("ubnt_aprepeater", "gauge", label,
+ device_data['wireless']['aprepeater'])
+ metric("ubnt_rstatus", "gauge", label, device_data['wireless']['rstatus'])
+ metric("ubnt_chanbw", "gauge", label, device_data['wireless']['chanbw'])
+ metric("ubnt_rx_chainmask", "gauge", label,
+ device_data['wireless']['rx_chainmask'])
+ metric("ubnt_tx_chainmask", "gauge", label,
+ device_data['wireless']['tx_chainmask'])
+ metric("ubnt_cac_state", "gauge", label,
+ device_data['wireless']['cac_state'])
+ metric("ubnt_cac_timeout", "gauge", label,
+ device_data['wireless']['cac_timeout'])
+ metric("ubnt_rx_idx", "gauge", label, device_data['wireless']['rx_idx'])
+ metric("ubnt_rx_nss", "gauge", label, device_data['wireless']['rx_nss'])
+ metric("ubnt_tx_idx", "gauge", label, device_data['wireless']['tx_idx'])
+ metric("ubnt_tx_nss", "gauge", label, device_data['wireless']['tx_nss'])
+ metric("ubnt_count", "gauge", label, device_data['wireless']['count'])
+
+ -- wireless throughput
+ metric("ubnt_throughput_tx", "gauge", label,
+ device_data['wireless']['throughput']['tx'])
+ metric("ubnt_throughput_rx", "gauge", label,
+ device_data['wireless']['throughput']['rx'])
+
+ -- wireless polling
+ metric("ubnt_polling_cb_capacity", "gauge", label,
+ device_data['wireless']['polling']['cb_capacity'])
+ metric("ubnt_polling_dl_capacity", "gauge", label,
+ device_data['wireless']['polling']['dl_capacity'])
+ metric("ubnt_polling_ul_capacity", "gauge", label,
+ device_data['wireless']['polling']['ul_capacity'])
+ metric("ubnt_use", "gauge", label, device_data['wireless']['polling']['use'])
+ metric("ubnt_tx_use", "gauge", label,
+ device_data['wireless']['polling']['tx_use'])
+ metric("ubnt_rx_use", "gauge", label,
+ device_data['wireless']['polling']['rx_use'])
+ metric("ubnt_atpc_status", "gauge", label,
+ device_data['wireless']['polling']['atpc_status'])
+ metric("ubnt_atpc_status", "gauge", label,
+ device_data['wireless']['polling']['atpc_status'])
+end
+
+local function get_metric(device)
+ local json = require('cjson')
+ local handle = io.popen("ubnt-manager -j -t " .. device)
+ local result = handle:read("*a")
+ handle:close()
+ local device_data = json.decode(result)
+
+ if not device_data['host'] then return end
+ if not device_data['wireless'] then return end
+
+ local hostname = device_data['host']['hostname']
+ local devmodel = device_data['host']['devmodel']
+ local fwversion = device_data['host']['fwversion']
+ local essid = device_data['wireless']['essid']
+
+ local label_short = {
+ device = device
+ }
+
+ local label_full = {
+ device = device,
+ hostname = hostname,
+ devmodel = devmodel,
+ fwversion = fwversion,
+ essid = essid
+ }
+
+ -- v6. vs v8.
+ if fwversion:find("v8.", 1, true) then
+ get_metric_airos8(device_data, label_short, label_full)
+ elseif fwversion:find("v6.", 1, true) then
+ get_metric_airos6(device_data, label_short, label_full)
+ end
+end
+
+local function scrape()
+ for _, device in ipairs(get_devices()) do get_metric(device) end
+end
+
+return {scrape = scrape}
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/uci_dhcp_host.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/uci_dhcp_host.lua
new file mode 100644
index 0000000..9509625
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/uci_dhcp_host.lua
@@ -0,0 +1,15 @@
+local uci=require("uci")
+
+local function scrape()
+ local curs=uci.cursor()
+ local metric_uci_host = metric("uci_dhcp_host", "gauge")
+
+ curs:foreach("dhcp", "host", function(s)
+ if s[".type"] == "host" then
+ labels = {name=s["name"], mac=string.upper(s["mac"]), dns=s["dns"], ip=s["ip"]}
+ metric_uci_host(labels, 1)
+ end
+ end)
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/uname.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/uname.lua
new file mode 100644
index 0000000..75a366e
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/uname.lua
@@ -0,0 +1,20 @@
+local uname_fd = io.popen("uname -m")
+
+local labels = {
+ domainname = "",
+ nodename = "",
+ release = string.sub(get_contents("/proc/sys/kernel/osrelease"), 1, -2),
+ sysname = string.sub(get_contents("/proc/sys/kernel/ostype"), 1, -2),
+ version = string.sub(get_contents("/proc/sys/kernel/version"), 1, -2),
+ machine = string.sub(uname_fd:read("*a"), 1, -2)
+}
+
+uname_fd:close()
+
+local function scrape()
+ labels["domainname"] = string.sub(get_contents("/proc/sys/kernel/domainname"), 1, -2)
+ labels["nodename"] = string.sub(get_contents("/proc/sys/kernel/hostname"), 1, -2)
+ metric("node_uname_info", "gauge", labels, 1)
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/wifi.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/wifi.lua
new file mode 100644
index 0000000..05b0ba1
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/wifi.lua
@@ -0,0 +1,45 @@
+local ubus = require "ubus"
+local iwinfo = require "iwinfo"
+
+local function scrape()
+ local metric_wifi_network_quality = metric("wifi_network_quality","gauge")
+ local metric_wifi_network_bitrate = metric("wifi_network_bitrate","gauge")
+ local metric_wifi_network_noise = metric("wifi_network_noise_dbm","gauge")
+ local metric_wifi_network_signal = metric("wifi_network_signal_dbm","gauge")
+
+ local u = ubus.connect()
+ local status = u:call("network.wireless", "status", {})
+
+ for dev, dev_table in pairs(status) do
+ for _, intf in ipairs(dev_table['interfaces']) do
+ local ifname = intf['ifname']
+ if ifname ~= nil then
+ local iw = iwinfo[iwinfo.type(ifname)]
+ local labels = {
+ channel = iw.channel(ifname),
+ ssid = iw.ssid(ifname),
+ bssid = iw.bssid(ifname),
+ mode = iw.mode(ifname),
+ ifname = ifname,
+ country = iw.country(ifname),
+ frequency = iw.frequency(ifname),
+ device = dev,
+ }
+
+ local qc = iw.quality(ifname) or 0
+ local qm = iw.quality_max(ifname) or 0
+ local quality = 0
+ if qc > 0 and qm > 0 then
+ quality = math.floor((100 / qm) * qc)
+ end
+
+ metric_wifi_network_quality(labels, quality)
+ metric_wifi_network_noise(labels, iw.noise(ifname) or 0)
+ metric_wifi_network_bitrate(labels, iw.bitrate(ifname) or 0)
+ metric_wifi_network_signal(labels, iw.signal(ifname) or -255)
+ end
+ end
+ end
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/wifi_stations.lua b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/wifi_stations.lua
new file mode 100644
index 0000000..c632f94
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/wifi_stations.lua
@@ -0,0 +1,71 @@
+local ubus = require "ubus"
+local iwinfo = require "iwinfo"
+
+local function scrape()
+ local metric_wifi_stations = metric("wifi_stations", "gauge")
+
+ local metric_wifi_station_signal = metric("wifi_station_signal_dbm","gauge")
+
+ local metric_wifi_station_inactive = metric('wifi_station_inactive_milliseconds', 'gauge')
+
+ local metric_wifi_station_exp_thr = metric('wifi_station_expected_throughput_kilobits_per_second', 'gauge')
+
+ local metric_wifi_station_tx_bitrate = metric('wifi_station_transmit_kilobits_per_second', 'gauge')
+ local metric_wifi_station_rx_bitrate = metric('wifi_station_receive_kilobits_per_second', 'gauge')
+
+ local metric_wifi_station_tx_packets = metric("wifi_station_transmit_packets_total","counter")
+ local metric_wifi_station_rx_packets = metric("wifi_station_receive_packets_total","counter")
+
+ local metric_wifi_station_tx_bytes = metric('wifi_station_transmit_bytes_total', 'counter')
+ local metric_wifi_station_rx_bytes = metric('wifi_station_receive_bytes_total', 'counter')
+
+
+ local u = ubus.connect()
+ local status = u:call("network.wireless", "status", {})
+
+ for dev, dev_table in pairs(status) do
+ for _, intf in ipairs(dev_table['interfaces']) do
+ local ifname = intf['ifname']
+ if ifname ~= nil then
+ local iw = iwinfo[iwinfo.type(ifname)]
+ local count = 0
+
+ local assoclist = iw.assoclist(ifname)
+ for mac, station in pairs(assoclist) do
+ local labels = {
+ ifname = ifname,
+ mac = mac,
+ }
+ if station.signal and station.signal ~= 0 then
+ metric_wifi_station_signal(labels, station.signal)
+ end
+ if station.inactive then
+ metric_wifi_station_inactive(labels, station.inactive)
+ end
+ if station.expected_throughput and station.expected_throughput ~= 0 then
+ metric_wifi_station_exp_thr(labels, station.expected_throughput)
+ end
+ if station.tx_rate and station.tx_rate ~= 0 then
+ metric_wifi_station_tx_bitrate(labels, station.tx_rate)
+ end
+ if station.rx_rate and station.rx_rate ~= 0 then
+ metric_wifi_station_rx_bitrate(labels, station.rx_rate)
+ end
+ metric_wifi_station_tx_packets(labels, station.tx_packets)
+ metric_wifi_station_rx_packets(labels, station.rx_packets)
+ if station.tx_bytes then
+ metric_wifi_station_tx_bytes(labels, station.tx_bytes)
+ end
+ if station.rx_bytes then
+ metric_wifi_station_rx_bytes(labels, station.rx_bytes)
+ end
+
+ count = count + 1
+ end
+ metric_wifi_stations({ifname = ifname}, count)
+ end
+ end
+ end
+end
+
+return { scrape = scrape }
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/Makefile b/external/subpack/utils/prometheus-node-exporter-ucode/Makefile
new file mode 100644
index 0000000..6a626d9
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/Makefile
@@ -0,0 +1,74 @@
+# Copyright (C) 2013-2017 OpenWrt.org
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=prometheus-node-exporter-ucode
+PKG_VERSION:=2024.02.07
+PKG_RELEASE:=1
+
+PKG_MAINTAINER:=Andre Heider <a.heider@gmail.com>
+PKG_LICENSE:=Apache-2.0
+
+include $(INCLUDE_DIR)/package.mk
+
+Build/Compile=
+
+define Package/$(PKG_NAME)/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Prometheus node exporter
+ PKGARCH:=all
+endef
+
+define Package/$(PKG_NAME)
+ $(call Package/$(PKG_NAME)/Default)
+ DEPENDS:=+uhttpd +uhttpd-mod-ucode +rpcd +ucode-mod-fs +ucode-mod-ubus
+endef
+
+define Package/$(PKG_NAME)/install
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) ./files/config $(1)/etc/config/$(PKG_NAME)
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/init $(1)/etc/init.d/$(PKG_NAME)
+ $(INSTALL_DIR) $(1)/usr/share/ucode/node-exporter/lib
+ $(INSTALL_DATA) ./files/metrics.uc $(1)/usr/share/ucode/node-exporter/
+ $(INSTALL_DATA) ./files/base/*.uc $(1)/usr/share/ucode/node-exporter/lib/
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) ./files/run.sh $(1)/usr/bin/$(PKG_NAME)
+endef
+
+define Package/$(PKG_NAME)/conffiles
+/etc/config/$(PKG_NAME)
+endef
+
+define Package/$(PKG_NAME)/description
+ Provides node metrics as Prometheus scraping endpoint.
+
+ This service is a lightweight rewrite in ucode of the offical Prometheus node_exporter.
+endef
+
+$(eval $(call BuildPackage,prometheus-node-exporter-ucode))
+
+define Collector
+ define Package/$(PKG_NAME)-$(1)
+ $$(call Package/$(PKG_NAME)/Default)
+ TITLE+= ($(2))
+ DEPENDS:=$(PKG_NAME) $(3)
+ endef
+
+ define Package/$(PKG_NAME)-$(1)/install
+ $$(INSTALL_DIR) $$(1)/usr/share/ucode/node-exporter/lib
+ $$(INSTALL_DATA) ./files/extra/$(1).uc $$(1)/usr/share/ucode/node-exporter/lib/
+ endef
+
+ $$(eval $$(call BuildPackage,$(PKG_NAME)-$(1)))
+endef
+
+$(eval $(call Collector,dnsmasq,Dnsmasq collector,@dnsmasq))
+$(eval $(call Collector,ltq-dsl,Lantiq/Intel/MaxLinear DSL collector,@ltq-dsl-app))
+$(eval $(call Collector,netstat,netstat collector,))
+$(eval $(call Collector,openwrt,OpenWrt collector,))
+$(eval $(call Collector,snmp6,snmp6 collector,))
+$(eval $(call Collector,uci_dhcp_host,UCI DHCP host collector,))
+$(eval $(call Collector,wifi,Wi-Fi collector,+ucode-mod-nl80211))
+$(eval $(call Collector,wireguard,Wireguard collector,+rpcd-mod-wireguard))
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/base/conntrack.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/conntrack.uc
new file mode 100644
index 0000000..b3ee3f3
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/conntrack.uc
@@ -0,0 +1,4 @@
+gauge("node_nf_conntrack_entries")
+ (null, oneline("/proc/sys/net/netfilter/nf_conntrack_count"));
+gauge("node_nf_conntrack_entries_limit")
+ (null, oneline("/proc/sys/net/netfilter/nf_conntrack_max"));
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/base/cpu.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/cpu.uc
new file mode 100644
index 0000000..574655d
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/cpu.uc
@@ -0,0 +1,44 @@
+let f = fs.open("/proc/stat");
+
+if (!f)
+ return false;
+
+const desc = [
+ null,
+ "user",
+ "nice",
+ "system",
+ "idle",
+ "iowait",
+ "irq",
+ "softirq",
+ "steal",
+ "guest",
+ "guest_nice",
+];
+const m_cpu = counter("node_cpu_seconds_total");
+
+let line;
+while (line = nextline(f)) {
+ const x = wsplit(line);
+
+ if (length(x) < 2)
+ continue;
+
+ if (match(x[0], /^cpu\d+/)) {
+ const count = min(length(x), length(desc));
+ for (let i = 1; i < count; i++)
+ m_cpu({ cpu: x[0], mode: desc[i] }, x[i] / 100.0);
+ } else if (x[0] == "intr")
+ counter("node_intr_total")(null, x[1]);
+ else if (x[0] == "ctxt")
+ counter("node_context_switches_total")(null, x[1]);
+ else if (x[0] == "btime")
+ gauge("node_boot_time_seconds")(null, x[1]);
+ else if (x[0] == "processes")
+ counter("node_forks_total")(null, x[1]);
+ else if (x[0] == "procs_running")
+ gauge("node_procs_running_total")(null, x[1]);
+ else if (x[0] == "procs_blocked")
+ gauge("node_procs_blocked_total")(null, x[1]);
+}
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/base/entropy.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/entropy.uc
new file mode 100644
index 0000000..2df4426
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/entropy.uc
@@ -0,0 +1,4 @@
+gauge("node_entropy_available_bits")
+ (null, oneline("/proc/sys/kernel/random/entropy_avail"));
+gauge("node_entropy_pool_size_bits")
+ (null, oneline("/proc/sys/kernel/random/poolsize"));
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/base/filefd.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/filefd.uc
new file mode 100644
index 0000000..359cffd
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/filefd.uc
@@ -0,0 +1,7 @@
+const x = wsplit(oneline("/proc/sys/fs/file-nr"));
+
+if (length(x) < 3)
+ return false;
+
+gauge("node_filefd_allocated")(null, x[0]);
+gauge("node_filefd_maximum")(null, x[2]);
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/base/loadavg.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/loadavg.uc
new file mode 100644
index 0000000..ba67daf
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/loadavg.uc
@@ -0,0 +1,8 @@
+const x = wsplit(oneline("/proc/loadavg"));
+
+if (length(x) < 3)
+ return false;
+
+gauge("node_load1")(null, x[0]);
+gauge("node_load5")(null, x[1]);
+gauge("node_load15")(null, x[2]);
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/base/meminfo.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/meminfo.uc
new file mode 100644
index 0000000..3cecb12
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/meminfo.uc
@@ -0,0 +1,24 @@
+let f = fs.open("/proc/meminfo");
+
+if (!f)
+ return false;
+
+let line;
+while (line = nextline(f)) {
+ const x = wsplit(line);
+
+ if (length(x) < 2)
+ continue;
+
+ if (substr(x[0], -1) != ":")
+ continue;
+
+ let name;
+ if (substr(x[0], -2) == "):")
+ name = replace(substr(x[0], 0, -2), "(", "_");
+ else
+ name = substr(x[0], 0, -1);
+
+ gauge(`node_memory_${name}_bytes`)
+ (null, x[2] == "kB" ? x[1] * 1024 : x[1]);
+}
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/base/netclass.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/netclass.uc
new file mode 100644
index 0000000..10b3cfd
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/netclass.uc
@@ -0,0 +1,48 @@
+const root = "/sys/class/net/";
+const devices = fs.lsdir(root);
+
+if (length(devices) < 1)
+ return false;
+
+const m_info = gauge("node_network_info");
+const m_speed = gauge("node_network_speed_bytes");
+const metrics = {
+ addr_assign_type: gauge("node_network_address_assign_type"),
+ carrier: gauge("node_network_carrier"),
+ carrier_changes: counter("node_network_carrier_changes_total"),
+ carrier_down_count: counter("node_network_carrier_down_changes_total"),
+ carrier_up_count: counter("node_network_carrier_up_changes_total"),
+ dev_id: gauge("node_network_device_id"),
+ dormant: gauge("node_network_dormant"),
+ flags: gauge("node_network_flags"),
+ ifindex: gauge("node_network_iface_id"),
+ iflink: gauge("node_network_iface_link"),
+ link_mode: gauge("node_network_iface_link_mode"),
+ mtu: gauge("node_network_mtu_bytes"),
+ name_assign_type: gauge("node_network_name_assign_type"),
+ netdev_group: gauge("node_network_net_dev_group"),
+ type: gauge("node_network_protocol_type"),
+ tx_queue_len: gauge("node_network_transmit_queue_length"),
+};
+
+for (let device in devices) {
+ const devroot = root + device + "/";
+
+ m_info({
+ device,
+ address: oneline(devroot + "address"),
+ broadcast: oneline(devroot + "broadcast"),
+ duplex: oneline(devroot + "duplex"),
+ operstate: oneline(devroot + "operstate"),
+ ifalias: oneline(devroot + "ifalias"),
+ }, 1);
+
+ for (let m in metrics) {
+ let line = oneline(devroot + m);
+ metrics[m]({ device }, line);
+ }
+
+ const speed = int(oneline(devroot + "speed"));
+ if (speed > 0)
+ m_speed({ device }, speed * 1000 * 1000 / 8);
+}
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/base/netdev.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/netdev.uc
new file mode 100644
index 0000000..f8fc68d
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/netdev.uc
@@ -0,0 +1,40 @@
+let f = fs.open("/proc/net/dev");
+
+if (!f)
+ return false;
+
+const m = [
+ null,
+ counter("node_network_receive_bytes_total"),
+ counter("node_network_receive_packets_total"),
+ counter("node_network_receive_errs_total"),
+ counter("node_network_receive_drop_total"),
+ counter("node_network_receive_fifo_total"),
+ counter("node_network_receive_frame_total"),
+ counter("node_network_receive_compressed_total"),
+ counter("node_network_receive_multicast_total"),
+ counter("node_network_transmit_bytes_total"),
+ counter("node_network_transmit_packets_total"),
+ counter("node_network_transmit_errs_total"),
+ counter("node_network_transmit_drop_total"),
+ counter("node_network_transmit_fifo_total"),
+ counter("node_network_transmit_colls_total"),
+ counter("node_network_transmit_carrier_total"),
+ counter("node_network_transmit_compressed_total"),
+];
+
+let line;
+while (line = nextline(f)) {
+ const x = wsplit(ltrim(line), " ");
+
+ if (length(x) < 2)
+ continue;
+
+ if (substr(x[0], -1) != ":")
+ continue;
+
+ const count = min(length(x), length(m));
+ const labels = { device: substr(x[0], 0, -1) };
+ for (let i = 1; i < count; i++)
+ m[i](labels, x[i]);
+}
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/base/selinux.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/selinux.uc
new file mode 100644
index 0000000..11840a8
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/selinux.uc
@@ -0,0 +1,10 @@
+const mode = oneline("/sys/fs/selinux/enforce");
+const enabled = gauge("node_selinux_enabled");
+
+if (mode == null) {
+ enabled(null, 0);
+ return;
+}
+
+enabled(null, 1);
+gauge("node_selinux_current_mode")(null, mode);
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/base/time.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/time.uc
new file mode 100644
index 0000000..7d13ea8
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/time.uc
@@ -0,0 +1 @@
+gauge("node_time_seconds")(null, time());
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/base/uname.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/uname.uc
new file mode 100644
index 0000000..50cb352
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/base/uname.uc
@@ -0,0 +1,8 @@
+gauge("node_uname_info")({
+ sysname: oneline("/proc/sys/kernel/ostype"),
+ nodename: oneline("/proc/sys/kernel/hostname"),
+ release: oneline("/proc/sys/kernel/osrelease"),
+ version: oneline("/proc/sys/kernel/version"),
+ machine: poneline("uname -m"), // TODO lame
+ domainname: oneline("/proc/sys/kernel/domainname"),
+}, 1);
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/config b/external/subpack/utils/prometheus-node-exporter-ucode/files/config
new file mode 100644
index 0000000..8741f4a
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/config
@@ -0,0 +1,7 @@
+config prometheus-node-exporter-ucode 'main'
+ option listen_interface 'loopback'
+ option listen_port '9101'
+ option http_keepalive '70'
+
+config collector 'wifi'
+ option stations '1'
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/dnsmasq.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/dnsmasq.uc
new file mode 100644
index 0000000..3644b20
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/dnsmasq.uc
@@ -0,0 +1,6 @@
+const x = ubus.call("dnsmasq", "metrics");
+if (!x)
+ return false;
+
+for (let i in x)
+ gauge(`dnsmasq_${i}_total`)(null, x[i]);
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/ltq-dsl.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/ltq-dsl.uc
new file mode 100644
index 0000000..1644497
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/ltq-dsl.uc
@@ -0,0 +1,72 @@
+const x = ubus.call("dsl", "metrics");
+
+if (!x)
+ return false;
+
+gauge("dsl_info")({
+ atuc_vendor: x.atu_c.vendor,
+ atuc_system_vendor: x.atu_c.system_vendor,
+ chipset: x.chipset,
+ firmware_version: x.firmware_version,
+ api_version: x.api_version,
+ driver_version: x.driver_version,
+}, 1);
+
+gauge("dsl_line_info")({
+ annex: x.annex,
+ standard: x.standard,
+ mode: x.mode,
+ profile: x.profile,
+}, 1);
+
+gauge("dsl_up")({ detail: x.state }, x.up);
+gauge("dsl_uptime_seconds")(null, x.uptime);
+
+gauge("dsl_line_attenuation_db")
+ ({ direction: "down" }, x.downstream.latn)
+ ({ direction: "up" }, x.upstream.latn);
+gauge("dsl_signal_attenuation_db")
+ ({ direction: "down" }, x.downstream.satn)
+ ({ direction: "up" }, x.upstream.satn);
+gauge("dsl_signal_to_noise_margin_db")
+ ({ direction: "down" }, x.downstream.snr)
+ ({ direction: "up" }, x.upstream.snr);
+gauge("dsl_aggregated_transmit_power_db")
+ ({ direction: "down" }, x.downstream.actatp)
+ ({ direction: "up" }, x.upstream.actatp);
+
+if (x.downstream.interleave_delay)
+ gauge("dsl_latency_seconds")
+ ({ direction: "down" }, x.downstream.interleave_delay / 1000000.0)
+ ({ direction: "up" }, x.upstream.interleave_delay / 1000000.0);
+gauge("dsl_datarate")
+ ({ direction: "down" }, x.downstream.data_rate)
+ ({ direction: "up" }, x.upstream.data_rate);
+gauge("dsl_max_datarate")
+ ({ direction: "down" }, x.downstream.attndr)
+ ({ direction: "up" }, x.upstream.attndr);
+
+counter("dsl_error_seconds_total")
+ ({ err: "forward error correction", loc: "near" }, x.errors.near.fecs)
+ ({ err: "forward error correction", loc: "far" }, x.errors.far.fecs)
+ ({ err: "errored", loc: "near" }, x.errors.near.es)
+ ({ err: "errored", loc: "far" }, x.errors.far.es)
+ ({ err: "severely errored", loc: "near" }, x.errors.near.ses)
+ ({ err: "severely errored", loc: "far" }, x.errors.far.ses)
+ ({ err: "loss of signal", loc: "near" }, x.errors.near.loss)
+ ({ err: "loss of signal", loc: "far" }, x.errors.far.loss)
+ ({ err: "unavailable", loc: "near" }, x.errors.near.uas)
+ ({ err: "unavailable", loc: "far" }, x.errors.far.uas);
+
+counter("dsl_errors_total")
+ ({ err: "header error code error", loc: "near" }, x.errors.near.hec)
+ ({ err: "header error code error", loc: "far" }, x.errors.far.hec)
+ ({ err: "non pre-emptive crc error", loc: "near" }, x.errors.near.crc_p)
+ ({ err: "non pre-emptive crc error", loc: "far" }, x.errors.far.crc_p)
+ ({ err: "pre-emptive crc error", loc: "near" }, x.errors.near.crcp_p)
+ ({ err: "pre-emptive crc error", loc: "far" }, x.errors.far.crcp_p);
+
+if (x.erb)
+ counter("dsl_erb_total")
+ ({ counter: "sent" }, x.erb.sent)
+ ({ counter: "discarded" }, x.erb.discarded);
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/netstat.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/netstat.uc
new file mode 100644
index 0000000..7449305
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/netstat.uc
@@ -0,0 +1,30 @@
+function parse(fn) {
+ let f = fs.open(fn);
+
+ if (!f)
+ return false;
+
+ let names, values;
+ while (names = nextline(f), values = nextline(f)) {
+ const name = wsplit(names);
+ const value = wsplit(values);
+
+ if (name[0] != value[0])
+ continue;
+
+ if (length(name) != length(value))
+ continue;
+
+ let prefix = substr(name[0], 0, -1);
+ for (let i = 1; i < length(name); i++)
+ gauge(`node_netstat_${prefix}_${name[i]}`)(null, value[i]);
+ }
+
+ return true;
+}
+
+let n = parse("/proc/net/netstat");
+let s = parse("/proc/net/snmp");
+
+if (!n && !s)
+ return false;
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/openwrt.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/openwrt.uc
new file mode 100644
index 0000000..10c15a1
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/openwrt.uc
@@ -0,0 +1,14 @@
+const x = ubus.call("system", "board");
+
+if (!x)
+ return false;
+
+gauge("node_openwrt_info")({
+ board_name: x.board_name,
+ id: x.release.distribution,
+ model: x.model,
+ release: x.release.version,
+ revision: x.release.revision,
+ system: x.system,
+ target: x.release.target,
+}, 1);
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/snmp6.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/snmp6.uc
new file mode 100644
index 0000000..d440a88
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/snmp6.uc
@@ -0,0 +1,23 @@
+function parse(fn, device, skipdecl) {
+ let f = fs.open(fn);
+
+ if (!f)
+ return false;
+
+ const labels = { device };
+ let line;
+ while (line = nextline(f)) {
+ const x = wsplit(line);
+
+ if (length(x) < 2)
+ continue;
+
+ counter(`snmp6_${x[0]}`, null, skipdecl)(labels, x[1]);
+ }
+}
+
+parse("/proc/net/snmp6", "all");
+
+const root = "/proc/net/dev_snmp6/";
+for (let device in fs.lsdir(root))
+ parse(root + device, device, true);
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/uci_dhcp_host.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/uci_dhcp_host.uc
new file mode 100644
index 0000000..0d55724
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/uci_dhcp_host.uc
@@ -0,0 +1,14 @@
+import { cursor } from "uci";
+
+const uci = cursor();
+uci.load("dhcp");
+
+let m = gauge("dhcp_host_info");
+
+uci.foreach('dhcp', `host`, (s) => {
+ m({
+ name: s.name,
+ mac: s.mac,
+ ip: s.ip,
+ }, 1);
+});
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/wifi.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/wifi.uc
new file mode 100644
index 0000000..fb46b55
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/wifi.uc
@@ -0,0 +1,121 @@
+import { request, 'const' as wlconst } from 'nl80211';
+
+const x = ubus.call("network.wireless", "status");
+
+if (!x)
+ return false;
+
+const iftypes = [
+ "Unknown",
+ "Ad-Hoc",
+ "Client",
+ "Master",
+ "Master (VLAN)",
+ "WDS",
+ "Monitor",
+ "Mesh Point",
+ "P2P Client",
+ "P2P Go",
+ "P2P Device",
+ "OCB",
+];
+
+let m_radio_info = gauge("wifi_radio_info");
+let m_network_info = gauge("wifi_network_info");
+let m_network_quality = gauge("wifi_network_quality");
+let m_network_bitrate = gauge("wifi_network_bitrate");
+let m_network_noise = gauge("wifi_network_noise_dbm");
+let m_network_signal = gauge("wifi_network_signal_dbm");
+let m_stations_total = counter("wifi_stations_total");
+let m_station_inactive = gauge("wifi_station_inactive_milliseconds");
+let m_station_rx_bytes = counter("wifi_station_receive_bytes_total");
+let m_station_tx_bytes = counter("wifi_station_transmit_bytes_total");
+let m_station_rx_packets = counter("wifi_station_receive_packets_total");
+let m_station_tx_packets = counter("wifi_station_transmit_packets_total");
+let m_station_signal = gauge("wifi_station_signal_dbm");
+let m_station_rx_bitrate = gauge("wifi_station_receive_kilobits_per_second");
+let m_station_tx_bitrate = gauge("wifi_station_transmit_kilobits_per_second");
+let m_station_exp_tp = gauge("wifi_station_expected_throughput_kilobits_per_second");
+
+for (let radio in x) {
+ const rc = x[radio]["config"];
+
+ m_radio_info({
+ radio,
+ htmode: rc["htmode"],
+ channel: rc["channel"],
+ country: rc["country"],
+ } ,1);
+
+ for (let iface in x[radio]["interfaces"]) {
+ const ifname = iface["ifname"];
+ const nc = iface["config"];
+ const wif = request(wlconst.NL80211_CMD_GET_INTERFACE, 0, { dev: ifname });
+
+ if (!wif)
+ continue;
+
+ m_network_info({
+ radio,
+ ifname,
+ ssid: nc["ssid"] || nc["mesh_id"],
+ bssid: wif["mac"],
+ mode: iftypes[wif["iftype"]],
+ }, 1);
+
+ const wsta = request(wlconst.NL80211_CMD_GET_STATION, wlconst.NLM_F_DUMP, { dev: ifname });
+ let signal = 0;
+ let bitrate = 0;
+ const stations = length(wsta) || 0;
+ if (stations) {
+ for (let sta in wsta) {
+ signal += sta["sta_info"].signal;
+ bitrate += sta["sta_info"]["tx_bitrate"].bitrate32;
+ }
+ bitrate /= stations * 0.01;
+ signal /= stations;
+ }
+
+ let labels = { radio, ifname };
+ m_network_bitrate(labels, bitrate || NaN);
+ m_network_signal(labels, signal || NaN);
+ m_network_quality(labels, signal ? 100.0 / 70 * (signal + 110) : NaN);
+
+ const wsur = request(wlconst.NL80211_CMD_GET_SURVEY, wlconst.NLM_F_DUMP, { dev: ifname });
+ let noise = 0;
+ for (let i in wsur) {
+ if (i["survey_info"]["frequency"] != wif["wiphy_freq"])
+ continue;
+
+ noise = i["survey_info"]["noise"];
+ break;
+ }
+
+ m_network_noise(labels, noise || NaN);
+
+ if (config["stations"] != "1")
+ continue;
+
+ m_stations_total(labels, stations);
+ if (!stations)
+ continue;
+
+ for (let sta in wsta) {
+ labels["mac"] = sta["mac"];
+ const info = sta["sta_info"];
+
+ m_station_inactive(labels, info["inactive_time"]);
+ m_station_rx_bytes(labels, info["rx_bytes64"]);
+ m_station_tx_bytes(labels, info["tx_bytes64"]);
+ m_station_rx_packets(labels, info["rx_packets"]);
+ m_station_tx_packets(labels, info["tx_packets"]);
+ m_station_signal(labels, info["signal"]);
+ if (info["rx_bitrate"] && info["rx_bitrate"]["bitrate32"])
+ m_station_rx_bitrate(labels, info["rx_bitrate"]["bitrate32"] * 100);
+ if (info["tx_bitrate"] && info["tx_bitrate"]["bitrate32"])
+ m_station_tx_bitrate(labels, info["tx_bitrate"]["bitrate32"] * 100);
+ if (info["expected_throughput"])
+ m_station_exp_tp(labels, info["expected_throughput"]);
+ }
+ }
+}
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/wireguard.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/wireguard.uc
new file mode 100644
index 0000000..12ae56a
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/extra/wireguard.uc
@@ -0,0 +1,49 @@
+import { cursor } from "uci";
+
+const x = ubus.call("wireguard", "status");
+if (!x)
+ return false;
+
+const uci = cursor();
+uci.load("network");
+
+let m_wg_iface_info = gauge("wireguard_interface_info");
+let m_wg_peer_info = gauge("wireguard_peer_info");
+let m_wg_handshake = gauge ("wireguard_latest_handshake_seconds");
+let m_wg_rx = gauge ("wireguard_received_bytes_total");
+let m_wg_tx = gauge ("wireguard_sent_bytes_total");
+
+for (let iface in x) {
+ const wc = x[iface];
+
+ m_wg_iface_info({
+ name: iface,
+ public_key: wc["public_key"],
+ listen_port: wc["listen_port"],
+ fwmark: wc["fwmark"] || NaN,
+ }, 1);
+
+ for (let peer in wc["peers"]) {
+ let description;
+ uci.foreach('network', `wireguard_${iface}`, (s) => {
+ if (s.public_key == peer)
+ description = s.description;
+ });
+
+ const pc = wc["peers"][peer];
+
+ m_wg_peer_info({
+ interface: iface,
+ public_key: peer,
+ description,
+ endpoint: pc["endpoint"],
+ persistent_keepalive_interval: pc["persistent_keepalive_interval"] || NaN,
+ }, 1);
+
+ const labels = { public_key: peer };
+
+ m_wg_handshake(labels, pc["last_handshake"]);
+ m_wg_rx(labels, pc["rx_bytes"]);
+ m_wg_tx(labels, pc["tx_bytes"]);
+ }
+}
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/init b/external/subpack/utils/prometheus-node-exporter-ucode/files/init
new file mode 100644
index 0000000..1735236
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/init
@@ -0,0 +1,73 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2013-2017 OpenWrt.org
+
+START=60
+USE_PROCD=1
+
+_log() {
+ logger -p daemon.info -t prometheus-node-exporter-ucode "$@"
+}
+
+start_service() {
+ . /lib/functions/network.sh
+
+ local interface port bind4 bind6
+
+ config_load prometheus-node-exporter-ucode.main
+ config_get interface "main" listen_interface "loopback"
+ config_get port "main" listen_port 9101
+ config_get keepalive "main" http_keepalive 70
+
+ [ "$interface" = "*" ] || {
+ network_get_ipaddr bind4 "$interface"
+ network_get_ipaddr6 bind6 "$interface"
+ [ -n "$bind4$bind6" ] || {
+ _log "defering start until listen interface $interface becomes ready"
+ return 0
+ }
+ }
+
+ procd_open_instance
+
+ procd_set_param command /usr/sbin/uhttpd -f -c /dev/null -h /dev/null -S -D -o /metrics -O /usr/share/ucode/node-exporter/metrics.uc
+
+ if [ "$interface" = "*" ]; then
+ procd_append_param command -p $port
+ else
+ [ -n "$bind4" ] && procd_append_param command -p $bind4:$port
+ [ -n "$bind6" ] && procd_append_param command -p [$bind6]:$port
+ fi
+ [ $keepalive -gt 0 ] && procd_append_param command -k $keepalive
+
+ procd_add_jail prometheus-node-exporter-ucode log procfs sysfs ubus
+ procd_add_jail_mount "/usr/lib/uhttpd_ucode.so"
+ procd_add_jail_mount "/lib/libubus.so*"
+ procd_add_jail_mount "/lib/libuci.so"
+ procd_add_jail_mount "/usr/lib/ucode"
+ procd_add_jail_mount "/usr/lib/libnl*.so*"
+ procd_add_jail_mount "/usr/share/ucode/node-exporter"
+ procd_add_jail_mount "/etc/config"
+
+ # TODO breaks the dsl collector?
+ #procd_set_param user nobody
+ #procd_set_param group nogroup
+ procd_set_param no_new_privs 1
+
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_set_param respawn
+
+ procd_close_instance
+}
+
+service_triggers()
+{
+ local interface
+
+ procd_add_reload_trigger "prometheus-node-exporter-ucode"
+
+ config_load prometheus-node-exporter-ucode.main
+ config_get interface "main" listen_interface "loopback"
+
+ [ "$interface" = "*" ] || procd_add_reload_interface_trigger "$interface"
+}
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/metrics.uc b/external/subpack/utils/prometheus-node-exporter-ucode/files/metrics.uc
new file mode 100644
index 0000000..3dce77a
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/metrics.uc
@@ -0,0 +1,227 @@
+{%
+'use strict';
+
+import * as fs from "fs";
+import { connect } from "ubus";
+import { cursor } from "uci";
+
+function debug(...s) {
+ if (global.debug)
+ warn("DEBUG: ", ...s, "\n");
+}
+
+function puts(...s) {
+ return uhttpd.send(...s, "\n");
+}
+
+function govalue(value) {
+ if (value == Infinity)
+ return "+Inf";
+ else if (value == -Infinity)
+ return "-Inf";
+ else if (value != value)
+ return "NaN";
+ else if (type(value) in [ "int", "double" ])
+ return value;
+ else if (type(value) in [ "bool", "string" ])
+ return +value;
+
+ return null;
+}
+
+function metric(name, mtype, help, skipdecl) {
+ let func;
+ let decl = skipdecl == true ? false : true;
+
+ let yield = function(labels, value) {
+ let v = govalue(value);
+
+ if (v == null) {
+ debug(`skipping metric: unsupported value '${value}' (${name})`);
+ return func;
+ }
+
+ let labels_str = "";
+ if (length(labels)) {
+ let sep = "";
+ let s;
+ labels_str = "{";
+ for (let l in labels) {
+ if (labels[l] == null)
+ s = "";
+ else if (type(labels[l]) == "string") {
+ s = labels[l];
+ s = replace(labels[l], "\\", "\\\\");
+ s = replace(s, "\"", "\\\"");
+ s = replace(s, "\n", "\\n");
+ } else {
+ s = govalue(labels[l]);
+
+ if (!s)
+ continue;
+ }
+
+ labels_str += sep + l + "=\"" + s + "\"";
+ sep = ",";
+ }
+ labels_str += "}";
+ }
+
+ if (decl) {
+ if (help)
+ puts("# HELP ", name, " ", help);
+ puts("# TYPE ", name, " ", mtype);
+ decl = false;
+ }
+
+ puts(name, labels_str, " ", v);
+ return func;
+ };
+
+ func = yield;
+ return func;
+}
+
+function counter(name, help, skipdecl) {
+ return metric(name, "counter", help, skipdecl);
+}
+
+function gauge(name, help, skipdecl) {
+ return metric(name, "gauge", help, skipdecl);
+}
+
+function httpstatus(status) {
+ puts("Status: ", status, "\nContent-Type: text/plain; version=0.0.4; charset=utf-8\n");
+}
+
+function clockdiff(t1, t2) {
+ return (t2[0] - t1[0]) * 1000000000 + t2[1] - t1[1];
+}
+
+let collectors = {};
+
+global.handle_request = function(env) {
+ let scope = {
+ config: null,
+ fs,
+ ubus: connect(),
+ counter,
+ gauge,
+ wsplit: function(line) {
+ return split(line, /\s+/);
+ },
+ nextline: function(f) {
+ return rtrim(f.read("line"), "\n");
+ },
+ oneline: function(fn) {
+ let f = fs.open(fn);
+
+ if (!f)
+ return null;
+
+ return nextline(f);
+ },
+ poneline: function(cmd) {
+ let f = fs.popen(cmd);
+
+ if (!f)
+ return null;
+
+ return nextline(f);
+ },
+ };
+
+ if (length(collectors) < 1) {
+ httpstatus("404 No Collectors found");
+ return;
+ }
+
+ let cols = [];
+ for (let q in split(env.QUERY_STRING, "&")) {
+ let s = split(q, "=", 2);
+ if (length(s) == 2 && s[0] == "collect") {
+ if (!(s[1] in collectors)) {
+ httpstatus(`404 Collector ${s[1]} not found`);
+ return;
+ }
+
+ push(cols, s[1]);
+ }
+ }
+
+ if (length(cols) > 0)
+ cols = uniq(cols);
+ else
+ cols = keys(collectors);
+
+ httpstatus("200 OK");
+
+ let duration = gauge("node_scrape_collector_duration_seconds");
+ let success = gauge("node_scrape_collector_success");
+
+ for (let col in cols) {
+ let ok = false;
+ let t1, t2;
+
+ scope["config"] = collectors[col].config;
+ t1 = clock(true);
+ try {
+ ok = call(collectors[col].func, null, scope) != false;
+ } catch(e) {
+ warn(`error running collector '${col}':\n${e.message}\n`);
+ }
+ t2 = clock(true);
+
+ duration({ collector: col }, clockdiff(t1, t2) / 1000000000.0);
+ success({ collector: col }, ok);
+ }
+};
+
+const lib = "/usr/share/ucode/node-exporter/lib";
+const opts = {
+ strict_declarations: true,
+ raw_mode: true,
+};
+
+let cols = fs.lsdir(lib, "*.uc");
+for (let col in cols) {
+ let func;
+ let uci = cursor();
+
+ try {
+ func = loadfile(lib + "/" + col, opts);
+ } catch(e) {
+ warn(`error compiling collector '${col}':\n${e.message}\n`);
+ continue;
+ }
+
+ let name = substr(col, 0, -3);
+ let config = uci.get_all("prometheus-node-exporter-ucode", name);
+ if (!config || config[".type"] != "collector")
+ config = {};
+ else {
+ delete config[".anonymous"];
+ delete config[".type"];
+ delete config[".name"];
+ }
+
+ collectors[name] = {
+ func,
+ config,
+ };
+}
+
+warn(`prometheus-node-exporter-ucode now serving requests with ${length(collectors)} collectors\n`);
+
+if (!("uhttpd" in global)) {
+ global.debug = true;
+
+ puts = function(...s) {
+ return print(...s, "\n");
+ };
+
+ handle_request({
+ QUERY_STRING: join("&", map(ARGV, v => "collect=" + v)),
+ });
+}
+%}
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/files/run.sh b/external/subpack/utils/prometheus-node-exporter-ucode/files/run.sh
new file mode 100755
index 0000000..a7cefef
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/files/run.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /usr/bin/ucode -T /usr/share/ucode/node-exporter/metrics.uc $*
diff --git a/external/subpack/utils/prometheus-node-exporter-ucode/test.sh b/external/subpack/utils/prometheus-node-exporter-ucode/test.sh
new file mode 100755
index 0000000..e72942b
--- /dev/null
+++ b/external/subpack/utils/prometheus-node-exporter-ucode/test.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+prometheus-node-exporter-ucode time
diff --git a/external/subpack/utils/prometheus-statsd-exporter/Makefile b/external/subpack/utils/prometheus-statsd-exporter/Makefile
new file mode 100644
index 0000000..e9682a5
--- /dev/null
+++ b/external/subpack/utils/prometheus-statsd-exporter/Makefile
@@ -0,0 +1,50 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=prometheus-statsd-exporter
+PKG_VERSION:=0.15.0
+PKG_RELEASE:=2
+
+PKG_SOURCE:=statsd_exporter-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/prometheus/statsd_exporter/tar.gz/v${PKG_VERSION}?
+PKG_HASH:=4bd4df20898b25f9c315060b3f80cf375f5fb0d0bb2705440e1b9f0932055c8d
+PKG_BUILD_DIR:=$(BUILD_DIR)/statsd_exporter-$(PKG_VERSION)
+
+PKG_MAINTAINER:=Andre Heider <a.heider@gmail.com>
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/prometheus/statsd_exporter
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/prometheus-statsd-exporter
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=StatsD to Prometheus metrics exporter
+ URL:=http://prometheus.io
+ DEPENDS:=$(GO_ARCH_DEPENDS)
+endef
+
+define Package/prometheus-statsd-exporter/description
+statsd_exporter receives StatsD-style metrics and exports them as Prometheus
+metrics.
+endef
+
+define Package/prometheus-statsd-exporter/install
+ $(call GoPackage/Package/Install/Bin,$(1))
+
+ $(CP) ./files/* $(1)/
+endef
+
+define Package/prometheus-statsd-exporter/conffiles
+/etc/config/prometheus-statsd-exporter
+/etc/prometheus-statsd-exporter.yml
+endef
+
+$(eval $(call GoBinPackage,prometheus-statsd-exporter))
+$(eval $(call BuildPackage,prometheus-statsd-exporter))
diff --git a/external/subpack/utils/prometheus-statsd-exporter/files/etc/config/prometheus-statsd-exporter b/external/subpack/utils/prometheus-statsd-exporter/files/etc/config/prometheus-statsd-exporter
new file mode 100644
index 0000000..395f9bb
--- /dev/null
+++ b/external/subpack/utils/prometheus-statsd-exporter/files/etc/config/prometheus-statsd-exporter
@@ -0,0 +1,12 @@
+config prometheus-statsd-exporter 'main'
+ option web_interface 'loopback'
+ option web_port '9102'
+ option web_ipv6 '0'
+ option web_telemetry_path '/metrics'
+ option statsd_udp_interface 'loopback'
+ option statsd_udp_port '9125'
+ option statsd_udp_ipv6 '0'
+ option statsd_tcp_interface 'loopback'
+ option statsd_tcp_port '9125'
+ option statsd_tcp_ipv6 '0'
+ option statsd_mapping_config '/etc/prometheus-statsd-exporter.yml'
diff --git a/external/subpack/utils/prometheus-statsd-exporter/files/etc/init.d/prometheus-statsd-exporter b/external/subpack/utils/prometheus-statsd-exporter/files/etc/init.d/prometheus-statsd-exporter
new file mode 100755
index 0000000..73e6a77
--- /dev/null
+++ b/external/subpack/utils/prometheus-statsd-exporter/files/etc/init.d/prometheus-statsd-exporter
@@ -0,0 +1,99 @@
+#!/bin/sh /etc/rc.common
+
+START=60
+
+USE_PROCD=1
+PROG=/usr/bin/statsd_exporter
+CONFFILE=/etc/prometheus-statsd-exporter.yml
+
+. /lib/functions/network.sh
+
+_log() {
+ logger -p daemon.info -t prometheus-statsd-exporter "$@"
+}
+
+start_service() {
+ local web_interface web_port web_ipv6
+ local web_telemetry_path
+ local statsd_udp_interface statsd_udp_port statsd_udp_ipv6
+ local statsd_tcp_interface statsd_tcp_port statsd_tcp_ipv6
+ local statsd_mapping_config
+ local web_ip statsd_udp_ip statsd_tcp_ip
+
+ config_load "prometheus-statsd-exporter"
+ config_get web_interface main web_interface "loopback"
+ config_get web_port main web_port "9102"
+ config_get web_ipv6 main web_ipv6 "0"
+ config_get web_telemetry_path main web_telemetry_path "/metrics"
+ config_get statsd_udp_interface main statsd_udp_interface "loopback"
+ config_get statsd_udp_port main statsd_udp_port "9125"
+ config_get statsd_udp_ipv6 main statsd_udp_ipv6 "0"
+ config_get statsd_tcp_interface main statsd_tcp_interface "loopback"
+ config_get statsd_tcp_port main statsd_tcp_port "9125"
+ config_get statsd_tcp_ipv6 main statsd_tcp_ipv6 "0"
+ config_get statsd_mapping_config main statsd_mapping_config "$CONFFILE"
+
+ if [ "$web_ipv6" = 1 ]; then
+ network_get_ipaddr6 web_ip "$web_interface"
+ else
+ network_get_ipaddr web_ip "$web_interface"
+ fi
+
+ network_is_up "$web_interface" && [ -n "$web_ip" ] || {
+ _log "defering start until web interface $web_interface becomes ready"
+ return 0
+ }
+
+ if [ "$statsd_udp_ipv6" = 1 ]; then
+ network_get_ipaddr6 statsd_udp_ip "$statsd_udp_interface"
+ else
+ network_get_ipaddr statsd_udp_ip "$statsd_udp_interface"
+ fi
+
+ network_is_up "$statsd_udp_interface" && [ -n "$statsd_udp_ip" ] || {
+ _log "defering start until statsd udp interface $statsd_udp_interface becomes ready"
+ return 0
+ }
+
+ if [ "$statsd_tcp_ipv6" = 1 ]; then
+ network_get_ipaddr6 statsd_tcp_ip "$statsd_tcp_interface"
+ else
+ network_get_ipaddr statsd_tcp_ip "$statsd_tcp_interface"
+ fi
+
+ network_is_up "$statsd_tcp_interface" && [ -n "$statsd_tcp_ip" ] || {
+ _log "defering start until statsd tcp interface $statsd_tcp_interface becomes ready"
+ return 0
+ }
+
+ procd_open_instance
+ procd_set_param command "$PROG"
+ procd_append_param command --web.listen-address="${web_ip}:${web_port}"
+ procd_append_param command --web.telemetry-path="$web_telemetry_path"
+ procd_append_param command --statsd.listen-udp="${statsd_udp_ip}:${statsd_udp_port}"
+ procd_append_param command --statsd.listen-tcp="${statsd_tcp_ip}:${statsd_tcp_port}"
+ procd_append_param command --statsd.mapping-config="$statsd_mapping_config"
+ procd_append_param command --log.level="warn"
+
+ procd_set_param file "$config_file"
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_set_param respawn
+ procd_close_instance
+}
+
+service_triggers()
+{
+ local web_interface statsd_udp_interface statsd_tcp_interface
+
+ procd_add_reload_trigger "prometheus-statsd-exporter"
+
+ config_load "prometheus-statsd-exporter"
+ config_get web_interface main web_interface "loopback"
+ config_get statsd_udp_interface main statsd_udp_interface "loopback"
+ config_get statsd_tcp_interface main statsd_tcp_interface "loopback"
+
+ procd_add_reload_interface_trigger "$web_interface"
+ procd_add_reload_interface_trigger "$statsd_udp_interface"
+ procd_add_reload_interface_trigger "$statsd_tcp_interface"
+}
diff --git a/external/subpack/utils/prometheus-statsd-exporter/files/etc/prometheus-statsd-exporter.yml b/external/subpack/utils/prometheus-statsd-exporter/files/etc/prometheus-statsd-exporter.yml
new file mode 100644
index 0000000..e1bfde7
--- /dev/null
+++ b/external/subpack/utils/prometheus-statsd-exporter/files/etc/prometheus-statsd-exporter.yml
@@ -0,0 +1,24 @@
+mappings:
+ # asterisk mappings
+ # use "prefix = asterisk" in asterisk's statsd.conf
+ - match: asterisk.PJSIP.registrations.state.*
+ name: "asterisk_PJSIP_registrations_state"
+ labels:
+ state: "$1"
+ - match: asterisk.PJSIP.endpoints.state.*
+ name: "asterisk_PJSIP_endpoints_state"
+ labels:
+ state: "$1"
+ - match: asterisk.PJSIP.contacts.states.*
+ name: "asterisk_PJSIP_contacts_states"
+ labels:
+ state: "$1"
+ - match: asterisk.endpoints.state.*
+ name: "asterisk_endpoints_state"
+ labels:
+ state: "$1"
+ - match: asterisk.endpoints.*.*.channels
+ name: "asterisk_endpoints_channels"
+ labels:
+ tech: "$1"
+ resource: "$2"
diff --git a/external/subpack/utils/prometheus/Makefile b/external/subpack/utils/prometheus/Makefile
new file mode 100644
index 0000000..6cfb9b8
--- /dev/null
+++ b/external/subpack/utils/prometheus/Makefile
@@ -0,0 +1,63 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=prometheus
+PKG_VERSION:=2.22.0
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/prometheus/prometheus/tar.gz/v${PKG_VERSION}?
+PKG_HASH:=9390cbd338d253956184d0f0a6719d21cb5719f0319fc48ee08d5bd48fc87cc2
+
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+PKG_MAINTAINER:=Paul Spooren <mail@aparcar.org>
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/prometheus/prometheus/
+GO_PKG_BUILD_PKG:=github.com/prometheus/prometheus/cmd/prometheus/
+
+GO_PKG_LDFLAGS_X:=\
+ github.com/prometheus/common/version.Version=v$(PKG_VERSION) \
+ github.com/prometheus/common/version.Revision=$(PKG_VERSION) \
+ github.com/prometheus/common/version.Branch="release" \
+ github.com/prometheus/common/version.BuildUser=openwrt \
+ github.com/prometheus/common/version.BuildDate=$(SOURCE_DATE_EPOCH)
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/prometheus/Default
+ TITLE:=Monitoring system & time series database
+ USERID:=prometheus=112:prometheus=112
+ URL:=http://prometheus.io
+ DEPENDS:=$(GO_ARCH_DEPENDS)
+endef
+
+define Package/prometheus
+$(call Package/prometheus/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+endef
+
+define Package/prometheus/description
+Prometheus, a Cloud Native Computing Foundation project, is a systems and
+service monitoring system. It collects metrics from configured targets at given
+intervals, evaluates rule expressions, displays the results, and can trigger
+alerts if some condition is observed to be true.
+endef
+
+define Package/prometheus/install
+ $(call GoPackage/Package/Install/Bin,$(1))
+
+ $(CP) ./files/* $(1)/
+endef
+
+define Package/prometheus/conffiles
+/etc/prometheus.yml
+endef
+
+$(eval $(call GoBinPackage,prometheus))
+$(eval $(call BuildPackage,prometheus))
diff --git a/external/subpack/utils/prometheus/files/etc/init.d/prometheus b/external/subpack/utils/prometheus/files/etc/init.d/prometheus
new file mode 100755
index 0000000..a652ddf
--- /dev/null
+++ b/external/subpack/utils/prometheus/files/etc/init.d/prometheus
@@ -0,0 +1,27 @@
+#!/bin/sh /etc/rc.common
+
+START=70
+
+USE_PROCD=1
+PROG=/usr/bin/prometheus
+CONFFILE=/etc/prometheus.yml
+
+start_service() {
+ local config_file
+ local storage_tsdb_path
+ local web_listen_address
+ config_load "prometheus"
+ config_get config_file prometheus config_file "$CONFFILE"
+ config_get storage_tsdb_path prometheus storage_tsdb_path "/data"
+ config_get web_listen_address prometheus web_listen_address "127.0.0.1:9090"
+
+ procd_open_instance
+ procd_set_param command "$PROG"
+ procd_append_param command --config.file="$config_file"
+ procd_append_param command --storage.tsdb.path="$storage_tsdb_path"
+ procd_append_param command --web.listen-address="$web_listen_address"
+ procd_append_param user "prometheus"
+ procd_set_param file "$config_file"
+ procd_set_param respawn
+ procd_close_instance
+}
diff --git a/external/subpack/utils/prometheus/files/etc/prometheus.yml b/external/subpack/utils/prometheus/files/etc/prometheus.yml
new file mode 100644
index 0000000..af33d87
--- /dev/null
+++ b/external/subpack/utils/prometheus/files/etc/prometheus.yml
@@ -0,0 +1,29 @@
+# my global config
+global:
+ scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
+ evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
+ # scrape_timeout is set to the global default (10s).
+
+# Alertmanager configuration
+alerting:
+ alertmanagers:
+ - static_configs:
+ - targets:
+ # - alertmanager:9093
+
+# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
+rule_files:
+ # - "first_rules.yml"
+ # - "second_rules.yml"
+
+# A scrape configuration containing exactly one endpoint to scrape:
+# Here it's Prometheus itself.
+scrape_configs:
+ # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
+ - job_name: 'prometheus'
+
+ # metrics_path defaults to '/metrics'
+ # scheme defaults to 'http'.
+
+ static_configs:
+ - targets: ['localhost:9090']
diff --git a/external/subpack/utils/prometheus/files/etc/uci-defaults/prometheus-defaults b/external/subpack/utils/prometheus/files/etc/uci-defaults/prometheus-defaults
new file mode 100755
index 0000000..2ce7452
--- /dev/null
+++ b/external/subpack/utils/prometheus/files/etc/uci-defaults/prometheus-defaults
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+[ -e /etc/config/prometheus ] || touch /etc/config/prometheus
+
+uci -q get prometheus.prometheus || {
+ uci -q batch <<EOF
+ set prometheus.prometheus=prometheus
+ set prometheus.prometheus.config_file='/etc/prometheus.yml'
+ set prometheus.prometheus.storage_tsdb_path='/data'
+ set prometheus.prometheus.web_listen_address='127.0.0.1:9090'
+ commit prometheus
+EOF
+}
diff --git a/external/subpack/utils/prometheus/files/prometheus.yml b/external/subpack/utils/prometheus/files/prometheus.yml
new file mode 100644
index 0000000..af33d87
--- /dev/null
+++ b/external/subpack/utils/prometheus/files/prometheus.yml
@@ -0,0 +1,29 @@
+# my global config
+global:
+ scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
+ evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
+ # scrape_timeout is set to the global default (10s).
+
+# Alertmanager configuration
+alerting:
+ alertmanagers:
+ - static_configs:
+ - targets:
+ # - alertmanager:9093
+
+# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
+rule_files:
+ # - "first_rules.yml"
+ # - "second_rules.yml"
+
+# A scrape configuration containing exactly one endpoint to scrape:
+# Here it's Prometheus itself.
+scrape_configs:
+ # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
+ - job_name: 'prometheus'
+
+ # metrics_path defaults to '/metrics'
+ # scheme defaults to 'http'.
+
+ static_configs:
+ - targets: ['localhost:9090']
diff --git a/external/subpack/utils/prometheus/test.sh b/external/subpack/utils/prometheus/test.sh
new file mode 100644
index 0000000..2089454
--- /dev/null
+++ b/external/subpack/utils/prometheus/test.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+prometheus --version 2>&1 | grep "$2"
diff --git a/external/subpack/utils/pservice/Makefile b/external/subpack/utils/pservice/Makefile
new file mode 100644
index 0000000..c6b87c1
--- /dev/null
+++ b/external/subpack/utils/pservice/Makefile
@@ -0,0 +1,32 @@
+# Copyright (C) 2017 Yousong Zhou
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=pservice
+PKG_VERSION:=2017.08.29
+PKG_RELEASE=3
+
+PKG_MAINTAINER:=Yousong Zhou <yszhou4tech@gmail.com>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/pservice
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Wrap commands as procd services
+endef
+
+define Build/Compile
+endef
+
+define Package/pservice/conffiles
+/etc/config/pservice
+endef
+
+define Package/pservice/install
+ $(INSTALL_DIR) $(1)/usr/bin $(1)/etc/init.d $(1)/etc/config
+ $(INSTALL_BIN) ./files/pservice.init $(1)/etc/init.d/pservice
+ $(INSTALL_DATA) ./files/pservice.config $(1)/etc/config/pservice
+endef
+
+$(eval $(call BuildPackage,pservice))
diff --git a/external/subpack/utils/pservice/README.md b/external/subpack/utils/pservice/README.md
new file mode 100644
index 0000000..85fbd6c
--- /dev/null
+++ b/external/subpack/utils/pservice/README.md
@@ -0,0 +1,44 @@
+# uci
+
+`disabled`, bool, default `0`
+
+`name`, string, name of the service instance
+
+`command`, file, the service instance executable
+
+`args`, list of args
+
+`stderr`, bool, default `0`, log stderr output of the service instance
+
+`stdout`, bool, default `0`, log stdout output of the service instance
+
+`env`, list of environment variable settings of the form `var=val`
+
+`file`, list of file names. Service instances will be restarted if content of
+these files have changed on service reload event.
+
+`respawn_threshold`, uinteger, default `3600`, time in seconds the instances
+have to be in running state to be considered a valid run
+
+`respawn_timeout`, uinteger, default `5`, time in seconds the instance should
+be delayed to start again after the last crash
+
+`respawn_maxfail`, uinteger, default `5`, maximum times the instances can
+crash/fail in a row and procd will not try to bring it up again after this
+limit has been reached
+
+# notes and faq
+
+Initial environment variables presented to service instances may be different
+from what was observed on the interactive terminal. E.g. `HOME=/` may affect
+reading `~/.ssh/known_hosts` of dropbear ssh instance.
+
+ PATH=/usr/sbin:/usr/bin:/sbin:/bin PWD=/ HOME=/
+
+If `list args xxx` seems to be too long causing pain, consider using `/bin/sh`
+as the `command`. It is also worth noting that uci supports multi-line option
+value.
+
+Child processes will keep running when their parent process was killed. This
+is especially the case and should be taken into account with option `command`
+being `/bin/sh` and it is recommended to use `exec` as the last shell command.
diff --git a/external/subpack/utils/pservice/files/pservice.config b/external/subpack/utils/pservice/files/pservice.config
new file mode 100644
index 0000000..0f505b3
--- /dev/null
+++ b/external/subpack/utils/pservice/files/pservice.config
@@ -0,0 +1,24 @@
+config pservice
+ option disabled 1
+ option name 'demo0'
+ option command /bin/sh
+ option respawn_maxfail 0
+ list args -c
+ list args 'env | logger -t $name; exec sleep $time'
+ list env 'v0=0'
+ list env 'v1=val with space'
+ list env 'name=demo0'
+ list env 'time=1799'
+ list file /tmp/sleep.conf
+
+config pservice
+ option disabled 1
+ option name 8021x
+ option command /usr/sbin/wpa_supplicant
+ option stdout 1
+ list args -i
+ list args eth0.1
+ list args -D
+ list args wired
+ list args -c
+ list args /etc/wpa_supplicant-eth0.1.conf
diff --git a/external/subpack/utils/pservice/files/pservice.init b/external/subpack/utils/pservice/files/pservice.init
new file mode 100755
index 0000000..3a3ce02
--- /dev/null
+++ b/external/subpack/utils/pservice/files/pservice.init
@@ -0,0 +1,63 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2017-2019 Yousong Zhou
+
+START=99
+
+USE_PROCD=1
+
+pservice_list_cb() {
+ local val="$1"; shift
+ local param="$1"; shift
+
+ procd_append_param "$param" "$val"
+}
+
+pservice_instance() {
+ local cfg="$1"
+
+ [ "$disabled" = 0 ] || return 0
+ [ -x "$command" ] || {
+ echo "$command is not executable" >&2
+ return 1
+ }
+
+ procd_open_instance "$name"
+ procd_set_param command "$command"
+ procd_set_param stderr "$stderr"
+ procd_set_param stdout "$stdout"
+ procd_set_param respawn "$respawn_threshold" "$respawn_timeout" "$respawn_maxfail"
+ [ -z "$args" ] || config_list_foreach "$cfg" args pservice_list_cb command
+ if [ -n "$env" ]; then
+ procd_set_param env
+ config_list_foreach "$cfg" env pservice_list_cb env
+ fi
+ if [ -n "$file" ]; then
+ procd_set_param file
+ config_list_foreach "$cfg" file pservice_list_cb file
+ fi
+ procd_close_instance
+}
+
+start_service() {
+ config_load 'pservice'
+ config_foreach validate_pservice_section pservice pservice_instance
+}
+
+service_triggers() {
+ procd_add_validation validate_pservice_section
+}
+
+validate_pservice_section() {
+ uci_load_validate pservice pservice "$1" "$2" \
+ "disabled:bool:0" \
+ "name:string" \
+ "env:regex('^[a-zA-Z_][a-zA-Z0-9_]*=.*$')" \
+ "command:file" \
+ "args:string" \
+ "stderr:bool:0" \
+ "stdout:bool:0" \
+ "respawn_threshold:uinteger:3600" \
+ "respawn_timeout:uinteger:5" \
+ "respawn_maxfail:uinteger:5" \
+ "file:string"
+}
diff --git a/external/subpack/utils/psmisc/Makefile b/external/subpack/utils/psmisc/Makefile
new file mode 100644
index 0000000..126edf4
--- /dev/null
+++ b/external/subpack/utils/psmisc/Makefile
@@ -0,0 +1,49 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=psmisc
+PKG_VERSION:=23.4
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@SF/psmisc
+PKG_HASH:=7f0cceeace2050c525f3ebb35f3ba01d618b8d690620580bdb8cd8269a0c1679
+
+PKG_MAINTAINER:=Josef Schlehofer <pepe.schlehofer@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/psmisc
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=proc utilities
+ URL:=https://gitlab.com/psmisc/psmisc/
+ DEPENDS:=+libncurses
+ ALTERNATIVES:=300:/usr/bin/killall:/usr/libexec/killall
+endef
+
+define Package/psmisc/description
+ psmisc is a set of additional small useful utilities that use
+ the proc filesystem like fuser, killall, prtstat, pstree.
+endef
+
+CONFIGURE_ARGS += \
+ --disable-harden-flags
+
+MAKE_FLAGS += \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ CPPFLAGS="$(TARGET_CPPFLAGS)" \
+ LDFLAGS="$(TARGET_LDFLAGS)"
+
+define Package/psmisc/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/{fuser,prtstat,pstree} $(1)/usr/bin
+ $(INSTALL_DIR) $(1)/usr/libexec
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/killall $(1)/usr/libexec
+endef
+
+$(eval $(call BuildPackage,psmisc))
diff --git a/external/subpack/utils/pv/Makefile b/external/subpack/utils/pv/Makefile
new file mode 100644
index 0000000..7348812
--- /dev/null
+++ b/external/subpack/utils/pv/Makefile
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2008 David Cooper
+# Copyright (C) 2008-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=pv
+PKG_VERSION:=1.6.6
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://www.ivarch.com/programs/sources
+PKG_HASH:=608ef935f7a377e1439c181c4fc188d247da10d51a19ef79bcdee5043b0973f1
+PKG_LICENSE:=Artistic-2.0
+PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/pv
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Shell pipeline element to meter data passing through
+ URL:=https://www.ivarch.com/programs/pv.shtml
+endef
+
+define Package/pv/description
+ Pipe Viewer is a terminal-based tool for monitoring the progress of data
+ through a pipeline. It can be inserted into any normal pipeline between
+ two processes to give a visual indication of how quickly data is passing
+ through, how long it has taken, how near to completion it is, and an
+ estimate of how long it will be until completion.
+endef
+
+define Package/pv/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/pv $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,pv))
+
diff --git a/external/subpack/utils/quectel-timesync/Makefile b/external/subpack/utils/quectel-timesync/Makefile
new file mode 100644
index 0000000..9b0167f
--- /dev/null
+++ b/external/subpack/utils/quectel-timesync/Makefile
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=quectel-timesync
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL=https://github.com/freifunk-darmstadt/quectel-timesync.git
+PKG_SOURCE_DATE:=2023-10-08
+PKG_SOURCE_VERSION:=4333888cb8025b92511597a95859943fae0a0bc8
+PKG_MIRROR_HASH:=49b2e24cd23b430a8d2815b10ce1bc2df1a6a6128cb0da1693807ebc130a51e7
+
+PKG_MAINTAINER:=David Bauer <mail@david-bauer.net>
+PKG_LICENSE:=GPL-2.0-only
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/quectel-timesync
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Tool for configuring system clock using Quectel cellular modems
+ DEPENDS:=+kmod-usb-serial-option
+endef
+
+define Package/quectel-timesync/description
+This tool allows for acquiring the current time from
+the cellular network for configuring the local clock.
+Compared to NTP, this has the advantage of nut using up
+mobile traffic.
+
+It takes advantage of the AT+QLTS command found on Quectel
+modems. This functionality depends on support of the mobile
+network.
+endef
+
+define Package/quectel-timesync/conffiles
+/etc/config/quectel-timesync
+endef
+
+define Package/quectel-timesync/install
+ $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d $(1)/etc/config
+
+ $(CP) $(PKG_BUILD_DIR)/openwrt/quectel-timesync/files/quectel-timesync.config $(1)/etc/config/quectel-timesync
+
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/openwrt/quectel-timesync/files/quectel-timesync.init $(1)/etc/init.d/quectel-timesync
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/quectel-timesync $(1)/usr/sbin/quectel-timesync
+endef
+
+$(eval $(call BuildPackage,quectel-timesync))
diff --git a/external/subpack/utils/quota/Makefile b/external/subpack/utils/quota/Makefile
new file mode 100644
index 0000000..74b5942
--- /dev/null
+++ b/external/subpack/utils/quota/Makefile
@@ -0,0 +1,52 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=quota
+PKG_VERSION:=4.06
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/linuxquota
+PKG_HASH:=2f3e03039f378d4f0d97acdb49daf581dcaad64d2e1ddf129495fd579fbd268d
+
+PKG_MAINTAINER:=W. Michael Petullo <mike@flyn.org>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/quota
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:= quota
+ URL:=https://sourceforge.net/projects/linuxquota/
+endef
+
+define Package/quota/description
+ Utility for managing Linux filesystem quotas
+endef
+
+CONFIGURE_ARGS += \
+ --disable-bsd-behaviour \
+ --disable-ext2direct \
+ --disable-ldapmail \
+ --disable-libwrap \
+ --disable-netlink \
+ --disable-rpath \
+ --disable-rpc
+
+define Package/quota/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/* $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,quota))
diff --git a/external/subpack/utils/quota/patches/010-cdefs.patch b/external/subpack/utils/quota/patches/010-cdefs.patch
new file mode 100644
index 0000000..a44978e
--- /dev/null
+++ b/external/subpack/utils/quota/patches/010-cdefs.patch
@@ -0,0 +1,18 @@
+--- a/quota.h
++++ b/quota.h
+@@ -1,7 +1,6 @@
+ #ifndef GUARD_QUOTA_H
+ #define GUARD_QUOTA_H
+
+-#include <sys/cdefs.h>
+ #include <sys/types.h>
+ #include <stdint.h>
+
+@@ -182,6 +181,6 @@ enum {
+ #endif
+ #endif
+
+-long quotactl __P((int, const char *, qid_t, caddr_t));
++long quotactl (int, const char *, qid_t, caddr_t);
+
+ #endif /* _QUOTA_ */
diff --git a/external/subpack/utils/quota/patches/020-remove-reallocarray.patch b/external/subpack/utils/quota/patches/020-remove-reallocarray.patch
new file mode 100644
index 0000000..75c7a5d
--- /dev/null
+++ b/external/subpack/utils/quota/patches/020-remove-reallocarray.patch
@@ -0,0 +1,11 @@
+--- a/quota.c
++++ b/quota.c
+@@ -385,7 +385,7 @@ int main(int argc, char **argv)
+ break;
+ case 259:
+ fscount++;
+- fsnames = reallocarray(fsnames, fscount, sizeof(char *));
++ fsnames = realloc(fsnames, fscount * sizeof(char *));
+ if (!fsnames)
+ die(1, _("Not enough memory for filesystem names"));
+ fsnames[fscount - 1] = optarg;
diff --git a/external/subpack/utils/readsb/Makefile b/external/subpack/utils/readsb/Makefile
new file mode 100644
index 0000000..dc46e98
--- /dev/null
+++ b/external/subpack/utils/readsb/Makefile
@@ -0,0 +1,73 @@
+# Copyright (C) 2020 Stijn Tintel <stijn@linux-ipv6.be>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=readsb
+PKG_VERSION:=3.8.3
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/Mictronics/readsb/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=bf59b8ecd0ff66945b210c55a5b824aa63ff8cbb1704249528d30a4902e716b2
+
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING LICENSE
+
+PKG_MAINTAINER:=Stijn Tintel <stijn@linux-ipv6.be>
+
+PKG_BUILD_DEPENDS:=!USE_GLIBC:argp-standalone
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/readsb/default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libncurses
+ TITLE:=Mode-S/ADSB/TIS decoder for various devices
+ URL:=https://github.com/Mictronic/readsb
+endef
+
+define Package/readsb
+ $(call Package/readsb/default)
+ TITLE+= (readsb)
+ DEPENDS+=+librtlsdr
+endef
+
+define Package/viewadsb
+ $(call Package/readsb/default)
+ TITLE+= (viewadsb)
+endef
+
+MAKE_FLAGS += \
+ BLADERF=no \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ RTLSDR=yes \
+ UNAME="Linux"
+
+TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto
+TARGET_LDFLAGS += \
+ $(if $(CONFIG_LIBC_USE_GLIBC),,-largp) \
+ -Wl,--gc-sections,--as-needed
+
+define Package/readsb/conffiles
+/etc/config/readsb
+endef
+
+define Package/readsb/install
+ $(INSTALL_DIR) $(1)/etc/{config,init.d} $(1)/usr/bin
+ $(INSTALL_CONF) ./files/readsb.config $(1)/etc/config/readsb
+ $(INSTALL_BIN) ./files/readsb.init $(1)/etc/init.d/readsb
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/readsb $(1)/usr/bin
+endef
+
+define Package/viewadsb/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/viewadsb $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,readsb))
+$(eval $(call BuildPackage,viewadsb))
diff --git a/external/subpack/utils/readsb/files/readsb.config b/external/subpack/utils/readsb/files/readsb.config
new file mode 100644
index 0000000..1799c95
--- /dev/null
+++ b/external/subpack/utils/readsb/files/readsb.config
@@ -0,0 +1,46 @@
+config readsb main
+ option enabled '0'
+ option beast_crc_off '0'
+ option beast_df045_on '0'
+ option beast_df1117_on '0'
+ option beast_fec_off '0'
+ option beast_mlat_off '0'
+ option beast_modeac '0'
+ option beast_serial ''
+ option dcfilter '0'
+ option debug ''
+ option device ''
+ option device_type ''
+ option enable_agc '0'
+ option enable_biastee '0'
+ option fix '1'
+ option freq ''
+ option forward_mlat '0'
+ option gain ''
+ option gnss '0'
+ option json_location_accuracy ''
+ option lat ''
+ option lon ''
+ option max_range ''
+ option metric '0'
+ option mlat '0'
+ option modeac '0'
+ option net '1'
+ option net_beast_reduce_interval ''
+ option net_beast_reduce_out_port ''
+ option net_bi_port ''
+ option net_bind_address ''
+ option net_bo_port ''
+ option net_buffer ''
+ list net_connector ''
+ option net_only '0'
+ option net_verbatim '0'
+ option no_crc_check '0'
+ option no_modeac_auto '0'
+ option onlyaddr '0'
+ option ppm ''
+ option stats '0'
+ option stats_every ''
+ option stats_range '0'
+ option write_json ''
+ option write_json_every ''
diff --git a/external/subpack/utils/readsb/files/readsb.init b/external/subpack/utils/readsb/files/readsb.init
new file mode 100644
index 0000000..7577609
--- /dev/null
+++ b/external/subpack/utils/readsb/files/readsb.init
@@ -0,0 +1,105 @@
+#!/bin/sh /etc/rc.common
+
+START=90
+STOP=10
+USE_PROCD=1
+
+append_bool() {
+ config_get_bool tbool "$1" "$2"
+ v=$(echo "$2" | sed 's/_/-/g')
+ [ -z "$tbool" ] && tbool="$3"
+ [ "$tbool" -eq 1 ] && procd_append_param command "--${v}"
+}
+
+append_bool_no() {
+ config_get_bool tbool "$1" "$2"
+ v=$(echo "$2" | sed 's/_/-/g')
+ [ -z "$tbool" ] && tbool="$3"
+ [ "$tbool" -eq 0 ] && procd_append_param command "--no-${v}"
+ [ "$tbool" -eq 1 ] && procd_append_param command "--${v}"
+}
+
+append_param() {
+ config_get tparam "$1" "$2"
+ name=$(echo "$2" | sed 's/_/-/g')
+ [ -n "$tparam" ] && procd_append_param command "--${name}=${tparam}"
+}
+
+start_instance() {
+ cfg=$1
+
+ config_get_bool enabled "$cfg" "enabled" 0
+ [ "$enabled" -eq 1 ] || return 0
+
+ procd_open_instance "$cfg"
+ procd_set_param command /usr/bin/readsb
+ procd_append_param command "--quiet"
+
+ procd_set_param respawn
+ procd_set_param stderr "1"
+ procd_set_param stdout "1"
+
+ append_bool "$cfg" beast_crc_off 0
+ append_bool "$cfg" beast_df045_on 0
+ append_bool "$cfg" beast_df1117_on 0
+ append_bool "$cfg" beast_fec_off 0
+ append_bool "$cfg" beast_mlat_off 0
+ append_bool "$cfg" beast_modeac 0
+ append_bool "$cfg" dcfilter 0
+ append_bool "$cfg" enable_agc 0
+ append_bool "$cfg" enable_biastee 0
+ append_bool "$cfg" forward_mlat 0
+ append_bool "$cfg" gnss 0
+ append_bool "$cfg" metric 0
+ append_bool "$cfg" mlat 0
+ append_bool "$cfg" modeac 0
+ append_bool "$cfg" net 1
+ append_bool "$cfg" net_only 0
+ append_bool "$cfg" net_verbatim 0
+ append_bool "$cfg" no_crc_check 0
+ append_bool "$cfg" no_modeac_auto 0
+ append_bool "$cfg" onlyaddr 0
+ append_bool "$cfg" stats 0
+ append_bool "$cfg" stats_range 0
+
+ append_bool_no "$cfg" fix 1
+
+ for param in \
+ beast_serial \
+ debug \
+ device \
+ device_type \
+ freq \
+ gain \
+ json_location_accuracy \
+ lat \
+ lon \
+ max_range \
+ net_beast_reduce_interval \
+ net_beast_reduce_out_port \
+ net_bi_port \
+ net_bind_address \
+ net_bo_port \
+ net_buffer \
+ ppm \
+ stats_every \
+ write_json \
+ write_json_every
+ do
+ append_param "$cfg" "$param"
+ done
+
+ config_get net_connector "$cfg" "net_connector"
+ [ -z "$net_connector" ] || {
+ for conn in $net_connector; do
+ procd_append_param command --net-connector="$conn"
+ done
+ }
+
+ procd_close_instance
+}
+
+start_service() {
+ config_load readsb
+ config_foreach start_instance readsb
+}
diff --git a/external/subpack/utils/readsb/patches/001-network-avoid-segfault-in-freeaddrinfo.patch b/external/subpack/utils/readsb/patches/001-network-avoid-segfault-in-freeaddrinfo.patch
new file mode 100644
index 0000000..a389475
--- /dev/null
+++ b/external/subpack/utils/readsb/patches/001-network-avoid-segfault-in-freeaddrinfo.patch
@@ -0,0 +1,80 @@
+From 82014a5fa9930b0875e57869265acf011772277c Mon Sep 17 00:00:00 2001
+From: Stijn Tintel <stijn@linux-ipv6.be>
+Date: Sun, 3 May 2020 20:56:58 +0300
+Subject: [PATCH] network: avoid segfault in freeaddrinfo
+
+Calling freeaddrinfo(NULL) when using musl libc causes a segfault.
+
+Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
+---
+ anet.c | 15 ++++++++++++---
+ net_io.c | 5 ++++-
+ viewadsb.c | 5 ++++-
+ 3 files changed, 20 insertions(+), 5 deletions(-)
+
+--- a/anet.c
++++ b/anet.c
+@@ -212,7 +212,10 @@ static int anetTcpGenericConnect(char *e
+ if (ss) {
+ memcpy(ss, p->ai_addr, sizeof(*ss));
+ }
+- freeaddrinfo(gai_result);
++ if (gai_result) {
++ freeaddrinfo(gai_result);
++ gai_result = NULL;
++ }
+ return s;
+ }
+
+@@ -220,7 +223,10 @@ static int anetTcpGenericConnect(char *e
+ anetCloseSocket(s);
+ }
+
+- freeaddrinfo(gai_result);
++ if (gai_result) {
++ freeaddrinfo(gai_result);
++ gai_result = NULL;
++ }
+ return ANET_ERR;
+ }
+
+@@ -368,7 +374,10 @@ int anetTcpServer(char *err, char *servi
+ fds[i++] = s;
+ }
+
+- freeaddrinfo(gai_result);
++ if (gai_result) {
++ freeaddrinfo(gai_result);
++ gai_result = NULL;
++ }
+ return (i > 0 ? i : ANET_ERR);
+ }
+
+--- a/net_io.c
++++ b/net_io.c
+@@ -3285,7 +3285,10 @@ void cleanupNetwork(void) {
+ for (int i = 0; i < Modes.net_connectors_count; i++) {
+ struct net_connector *con = Modes.net_connectors[i];
+ free(con->address);
+- freeaddrinfo(con->addr_info);
++ if (con->addr_info) {
++ freeaddrinfo(con->addr_info);
++ con->addr_info = NULL;
++ }
+ if (con->mutex) {
+ pthread_mutex_unlock(con->mutex);
+ pthread_mutex_destroy(con->mutex);
+--- a/viewadsb.c
++++ b/viewadsb.c
+@@ -308,7 +308,10 @@ int main(int argc, char **argv) {
+ }
+ // Free local service and client
+ if (s) free(s);
+- freeaddrinfo(con->addr_info);
++ if (con->addr_info) {
++ freeaddrinfo(con->addr_info);
++ con->addr_info = NULL;
++ }
+ pthread_mutex_unlock(con->mutex);
+ pthread_mutex_destroy(con->mutex);
+ free(con->mutex);
diff --git a/external/subpack/utils/readsb/patches/010-gcc10.patch b/external/subpack/utils/readsb/patches/010-gcc10.patch
new file mode 100644
index 0000000..ffa7a37
--- /dev/null
+++ b/external/subpack/utils/readsb/patches/010-gcc10.patch
@@ -0,0 +1,55 @@
+From 5119c21ae56f1c7fd0b10250d1beca9634bf74af Mon Sep 17 00:00:00 2001
+From: Mictronics <github@mictronics.de>
+Date: Sun, 14 Jun 2020 18:06:22 +0200
+Subject: [PATCH] Clean up linkage of struct Modes.
+
+---
+ readsb.c | 2 ++
+ readsb.h | 6 ++++--
+ viewadsb.c | 2 ++
+ 3 files changed, 8 insertions(+), 2 deletions(-)
+
+--- a/readsb.c
++++ b/readsb.c
+@@ -57,6 +57,8 @@
+
+ #include <stdarg.h>
+
++struct _Modes Modes;
++
+ //
+ // ============================= Program options help ==========================
+ //
+--- a/readsb.h
++++ b/readsb.h
+@@ -312,7 +312,7 @@ struct mag_buf
+
+ // Program global state
+
+-struct
++struct _Modes
+ { // Internal state
+ pthread_cond_t data_cond; // Conditional variable associated
+ pthread_t reader_thread;
+@@ -412,7 +412,9 @@ struct
+ struct stats stats_15min;
+ struct timespec reader_cpu_accumulator; // CPU time used by the reader thread, copied out and reset by the main thread under the mutex
+ struct mag_buf mag_buffers[MODES_MAG_BUFFERS]; // Converted magnitude buffers from RTL or file input
+-} Modes;
++};
++
++extern struct _Modes Modes;
+
+ // The struct we use to store information about a decoded message.
+
+--- a/viewadsb.c
++++ b/viewadsb.c
+@@ -54,6 +54,8 @@
+ #include "readsb.h"
+ #include "help.h"
+
++struct _Modes Modes;
++
+ #define _stringize(x) x
+ #define verstring(x) _stringize(x)
+
diff --git a/external/subpack/utils/relayctl/Makefile b/external/subpack/utils/relayctl/Makefile
new file mode 100644
index 0000000..e9f351d
--- /dev/null
+++ b/external/subpack/utils/relayctl/Makefile
@@ -0,0 +1,47 @@
+# Copyright (C) 2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=relayctl
+PKG_VERSION:=0.1
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/relayctl/relayctl-$(PKG_VERSION)
+PKG_MAINTAINER:=Heinrich Schuchardt <xypron.glpk@gmx.de>
+PKG_HASH:=74ce41ebd5d18816d52b5f9b1071f658f5a814b8194257f20700214bbee9de1e
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/relayctl
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Simple command-line control of SainSmart USB relay boards
+ URL:=https://github.com/darryln/relayctl
+ DEPENDS:= +libftdi1
+endef
+
+define Package/relayctl/description
+ Simple command-line control of SainSmart USB relay boards based on
+ FTDI chips using bitbang mode.
+endef
+
+TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include/libftdi1
+
+define Package/relayctl/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/$(PKG_NAME) $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/lib/udev/rules.d/
+ $(CP) $(PKG_BUILD_DIR)/examples/60-relayctl.rules $(1)/lib/udev/rules.d/
+endef
+
+$(eval $(call BuildPackage,relayctl))
diff --git a/external/subpack/utils/relayctl/patches/0001-ftdi1.patch b/external/subpack/utils/relayctl/patches/0001-ftdi1.patch
new file mode 100644
index 0000000..f13267a
--- /dev/null
+++ b/external/subpack/utils/relayctl/patches/0001-ftdi1.patch
@@ -0,0 +1,20 @@
+From 13556aaf94a2b0738a835a29f76be41d775a2d33 Mon Sep 17 00:00:00 2001
+From: Heinrich Schuchardt <xypron.glpk@gmx.de>
+Date: Sun, 3 Jul 2016 15:51:43 +0200
+Subject: [PATCH] Use -lftdi1
+
+Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
+---
+ src/Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -1,6 +1,6 @@
+ bin_PROGRAMS = \
+ relayctl
+
+-relayctl_LDFLAGS = -lftdi
++relayctl_LDFLAGS = -lftdi1
+
+ relayctl_SOURCES = relayctl.c
diff --git a/external/subpack/utils/reptyr/Makefile b/external/subpack/utils/reptyr/Makefile
new file mode 100644
index 0000000..83dd6ba
--- /dev/null
+++ b/external/subpack/utils/reptyr/Makefile
@@ -0,0 +1,44 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=reptyr
+PKG_VERSION:=0.8.0
+PKG_RELEASE:=4
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/nelhage/reptyr/archive/
+PKG_HASH:=4b470ed2a0d25fed591739fa9613ce7ad3d0377891eb56cbe914e3c85db46ca8
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_NAME)-$(PKG_VERSION)
+
+PKG_MAINTAINER:=Josef Schlehofer <josef.schlehofer@nic.cz>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=COPYING
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/reptyr
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Tool for reparenting running programs
+ URL:=https://github.com/nelhage/reptyr
+ DEPENDS:=@!(arc||mips||mipsel||mips64||mips64el)
+endef
+
+define Package/reptyr/description
+ reptyr is a utility for taking an existing running program and attaching it
+ to a new terminal. Started a long-running process over ssh, but have to
+ leave and don't want to interrupt it? Just start a screen, use reptyr to
+ grab it, and then kill the ssh session and head on home.
+endef
+
+MAKE_FLAGS+= \
+ PREFIX=/usr
+
+define Package/reptyr/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/reptyr $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,reptyr))
diff --git a/external/subpack/utils/reptyr/test.sh b/external/subpack/utils/reptyr/test.sh
new file mode 100644
index 0000000..6c4effe
--- /dev/null
+++ b/external/subpack/utils/reptyr/test.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+reptyr -version 2>&1 | grep "$2"
diff --git a/external/subpack/utils/restic/Makefile b/external/subpack/utils/restic/Makefile
new file mode 100644
index 0000000..2eb6785
--- /dev/null
+++ b/external/subpack/utils/restic/Makefile
@@ -0,0 +1,41 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=restic
+PKG_VERSION:=0.9.6
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/restic/restic/tar.gz/v${PKG_VERSION}?
+PKG_HASH:=1cc8655fa99f06e787871a9f8b5ceec283c856fa341a5b38824a0ca89420b0fe
+
+PKG_LICENSE:=BSD-2-Clause
+PKG_LICENSE_FILES:=LICENSE
+PKG_MAINTAINER:=Markus Weippert <markus@gekmihesg.de>
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/restic/restic/
+GO_PKG_BUILD_PKG:=github.com/restic/restic/cmd/restic/
+GO_PKG_LDFLAGS_X:=main.version=$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/restic
+ TITLE:=restic backup program
+ URL:=http://github.com/restic/restic
+ DEPENDS:=$(GO_ARCH_DEPENDS)
+ SECTION:=utils
+ CATEGORY:=Utilities
+endef
+
+define Package/restic/description
+restic is a backup program that is fast, efficient and secure. It supports the
+three major operating systems (Linux, macOS, Windows) and a few smaller ones
+(FreeBSD, OpenBSD).
+endef
+
+$(eval $(call GoBinPackage,restic))
+$(eval $(call BuildPackage,restic))
diff --git a/external/subpack/utils/rng-tools/Makefile b/external/subpack/utils/rng-tools/Makefile
new file mode 100644
index 0000000..3e6a9c5
--- /dev/null
+++ b/external/subpack/utils/rng-tools/Makefile
@@ -0,0 +1,69 @@
+#
+# Copyright (C) 2011-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=rng-tools
+PKG_VERSION:=6.10
+PKG_RELEASE:=3
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/nhorman/rng-tools
+PKG_SOURCE_VERSION:=v$(PKG_VERSION)
+PKG_MIRROR_HASH:=853341a3be05164616ba11a8cf983847477e02d6d43a259fc2352dbec262d649
+
+PKG_MAINTAINER:=Nathaniel Wesley Filardo <nwfilardo@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+PKG_BUILD_DEPENDS:=!USE_GLIBC:argp-standalone
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/rng-tools
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Daemon for adding entropy to kernel entropy pool
+ URL:=https://github.com/nhorman/rng-tools
+ DEPENDS:=+libsysfs +libopenssl
+endef
+
+define Package/rng-tools/description
+ Daemon for adding entropy to kernel entropy pool. By default it uses
+ /dev/urandom as the source but the init script can be modified
+ to use a hardware source like /dev/hwrng if present
+endef
+
+CONFIGURE_ARGS += \
+ --without-nistbeacon \
+ --without-pkcs11 \
+ --without-rtlsdr
+
+ifndef CONFIG_USE_GLIBC
+ CONFIGURE_VARS += LIBS="-largp"
+endif
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ (cd $(PKG_BUILD_DIR); ln -s README.md README)
+endef
+
+define Package/rng-tools/install
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/rngd.init $(1)/etc/init.d/rngd
+ $(INSTALL_DIR) $(1)/etc/uci-defaults
+ $(INSTALL_BIN) ./files/rngd.uci_defaults $(1)/etc/uci-defaults/rngd
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/rngtest $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/rngd $(1)/sbin/
+endef
+
+$(eval $(call BuildPackage,rng-tools))
diff --git a/external/subpack/utils/rng-tools/files/rngd.init b/external/subpack/utils/rng-tools/files/rngd.init
new file mode 100644
index 0000000..ab457db
--- /dev/null
+++ b/external/subpack/utils/rng-tools/files/rngd.init
@@ -0,0 +1,26 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2011-2014 OpenWrt.org
+
+START=00
+
+USE_PROCD=1
+PROG=/sbin/rngd
+
+start_service() {
+ local enabled=$(uci -q get system.@rngd[0].enabled)
+ local precmd=$(uci -q get system.@rngd[0].precmd)
+ local device=$(uci -q get system.@rngd[0].device)
+ local watermark=$(uci -q get system.@rngd[0].fill_watermark)
+
+ [ "$enabled" = "1" ] || return
+
+ [ -z "$precmd" ] || ${precmd} ${device}
+
+ [ -z "$device" ] || device="-r ${device}"
+ [ -z "$watermark" ] || watermark="-W ${watermark}"
+
+ procd_open_instance
+ procd_set_param command "$PROG" -f ${device} ${watermark}
+ procd_set_param stderr 1
+ procd_close_instance
+}
diff --git a/external/subpack/utils/rng-tools/files/rngd.uci_defaults b/external/subpack/utils/rng-tools/files/rngd.uci_defaults
new file mode 100644
index 0000000..6a26cf0
--- /dev/null
+++ b/external/subpack/utils/rng-tools/files/rngd.uci_defaults
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+uci -q show system.@rngd[0] || {
+ uci add system rngd
+ uci set system.@rngd[0].enabled=0
+ uci set system.@rngd[0].device=/dev/urandom
+ uci commit
+}
diff --git a/external/subpack/utils/rpcd-mod-lxc/Makefile b/external/subpack/utils/rpcd-mod-lxc/Makefile
new file mode 100644
index 0000000..289b2d1
--- /dev/null
+++ b/external/subpack/utils/rpcd-mod-lxc/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=rpcd-mod-lxc
+PKG_RELEASE=20201208
+
+PKG_LICENSE:=ISC
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/rpcd-mod-lxc
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=LXC rpcd module
+ DEPENDS:=+rpcd +liblxc
+ MAINTAINER:=Luka Perkov <luka@openwrt.org>
+endef
+
+define Build/Prepare
+ $(CP) ./files/* $(PKG_BUILD_DIR)/
+endef
+
+define Package/rpcd-mod-lxc/install
+ $(INSTALL_DIR) $(1)/usr/lib/rpcd
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/lxc.so $(1)/usr/lib/rpcd/
+endef
+
+define Package/rpcd-mod-lxc/postinst
+#!/bin/sh
+[ -n "$$IPKG_INSTROOT" ] || /etc/init.d/rpcd reload
+endef
+
+$(eval $(call BuildPackage,rpcd-mod-lxc))
diff --git a/external/subpack/utils/rpcd-mod-lxc/files/CMakeLists.txt b/external/subpack/utils/rpcd-mod-lxc/files/CMakeLists.txt
new file mode 100644
index 0000000..4a728a0
--- /dev/null
+++ b/external/subpack/utils/rpcd-mod-lxc/files/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.6)
+PROJECT(rpcd-mod-lxc)
+ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -Wmissing-declarations)
+
+INCLUDE_DIRECTORIES(include)
+FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
+
+SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)
+
+SET(SOURCES lxc.c)
+
+ADD_LIBRARY(rpcd-mod-lxc SHARED ${SOURCES})
+
+FIND_LIBRARY(lxc NAMES lxc liblxc)
+TARGET_LINK_LIBRARIES(rpcd-mod-lxc ${lxc})
+
+SET_TARGET_PROPERTIES(rpcd-mod-lxc PROPERTIES OUTPUT_NAME lxc PREFIX "")
+INSTALL(TARGETS rpcd-mod-lxc LIBRARY DESTINATION lib)
diff --git a/external/subpack/utils/rpcd-mod-lxc/files/lxc.c b/external/subpack/utils/rpcd-mod-lxc/files/lxc.c
new file mode 100644
index 0000000..a98fcfc
--- /dev/null
+++ b/external/subpack/utils/rpcd-mod-lxc/files/lxc.c
@@ -0,0 +1,552 @@
+/*
+ * rpcd-lxc-plugin
+ *
+ * Copyright (C) 2014 Cisco Systems, Inc.
+ * Author: Luka Perkov <luka@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <libubus.h>
+
+#include <lxc/lxccontainer.h>
+
+#include <rpcd/plugin.h>
+
+static struct blob_buf buf;
+
+struct rpc_lxc {
+ /* ubus options */
+ char *name;
+ char *config;
+ /* lxc container */
+ struct lxc_container *container;
+};
+
+enum {
+ RPC_LXC_NAME,
+ RPC_LXC_CONFIG,
+ __RPC_LXC_MAX,
+};
+
+enum {
+ RPC_LXC_SHUTDOWN_NAME,
+ RPC_LXC_SHUTDOWN_CONFIG,
+ RPC_LXC_SHUTDOWN_TIMEOUT,
+ __RPC_LXC_SHUTDOWN_MAX,
+};
+
+enum {
+ RPC_LXC_RENAME_NAME,
+ RPC_LXC_RENAME_CONFIG,
+ RPC_LXC_RENAME_NEWNAME,
+ __RPC_LXC_RENAME_MAX,
+};
+
+enum {
+ RPC_LXC_CREATE_NAME,
+ RPC_LXC_CREATE_CONFIG,
+ RPC_LXC_CREATE_TEMPLATE,
+ RPC_LXC_CREATE_FLAGS,
+ RPC_LXC_CREATE_ARGS,
+ __RPC_LXC_CREATE_MAX,
+};
+
+static const struct blobmsg_policy rpc_lxc_min_policy[__RPC_LXC_MAX] = {
+ [RPC_LXC_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
+ [RPC_LXC_CONFIG] = { .name = "config", .type = BLOBMSG_TYPE_STRING },
+};
+
+static const struct blobmsg_policy rpc_lxc_shutdown_policy[__RPC_LXC_SHUTDOWN_MAX] = {
+ [RPC_LXC_SHUTDOWN_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
+ [RPC_LXC_SHUTDOWN_CONFIG] = { .name = "config", .type = BLOBMSG_TYPE_STRING },
+ [RPC_LXC_SHUTDOWN_TIMEOUT] = { .name = "timeout", .type = BLOBMSG_TYPE_INT32 },
+};
+
+static const struct blobmsg_policy rpc_lxc_rename_policy[__RPC_LXC_RENAME_MAX] = {
+ [RPC_LXC_RENAME_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
+ [RPC_LXC_RENAME_CONFIG] = { .name = "config", .type = BLOBMSG_TYPE_STRING },
+ [RPC_LXC_RENAME_NEWNAME] = { .name = "newname", .type = BLOBMSG_TYPE_STRING },
+};
+
+static const struct blobmsg_policy rpc_lxc_create_policy[__RPC_LXC_CREATE_MAX] = {
+ [RPC_LXC_CREATE_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
+ [RPC_LXC_CREATE_CONFIG] = { .name = "config", .type = BLOBMSG_TYPE_STRING },
+ [RPC_LXC_CREATE_TEMPLATE] = { .name = "template", .type = BLOBMSG_TYPE_STRING },
+ [RPC_LXC_CREATE_FLAGS] = { .name = "flags", .type = BLOBMSG_TYPE_INT32 },
+ [RPC_LXC_CREATE_ARGS] = { .name = "args", .type = BLOBMSG_TYPE_ARRAY },
+};
+
+static struct rpc_lxc *
+rpc_lxc_init(struct blob_attr *tb[__RPC_LXC_MAX])
+{
+ struct rpc_lxc *l = NULL;
+
+ l = calloc(1, sizeof(struct rpc_lxc));
+ if (!l) return NULL;
+
+ if (tb[RPC_LXC_NAME]) {
+ l->name = blobmsg_data(tb[RPC_LXC_NAME]);
+ } else {
+ goto error;
+ }
+
+ if (tb[RPC_LXC_CONFIG]) {
+ l->config = blobmsg_data(tb[RPC_LXC_CONFIG]);
+ } else {
+ l->config = NULL;
+ }
+
+ l->container = lxc_container_new(l->name, l->config);
+ if (!l->container) {
+ goto error;
+ }
+
+ return l;
+error:
+ free(l);
+ return NULL;
+}
+
+static void
+rpc_lxc_done(struct rpc_lxc *l)
+{
+ if (l) {
+ lxc_container_put(l->container);
+ free(l);
+ }
+
+ return;
+}
+
+static int
+rpc_lxc_start(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__RPC_LXC_MAX];
+ struct rpc_lxc *l = NULL;
+ int rc;
+
+ blobmsg_parse(rpc_lxc_min_policy, __RPC_LXC_MAX, tb, blob_data(msg), blob_len(msg));
+
+ l = rpc_lxc_init(tb);
+ if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (l->container->is_running(l->container)) {
+ rc = UBUS_STATUS_UNKNOWN_ERROR;
+ goto out;
+ }
+
+ if (!l->container->start(l->container, 0, NULL)) {
+ rc = UBUS_STATUS_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ rc = UBUS_STATUS_OK;
+out:
+ rpc_lxc_done(l);
+ return rc;
+}
+
+
+static int
+rpc_lxc_reboot(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__RPC_LXC_MAX];
+ struct rpc_lxc *l = NULL;
+ int rc;
+
+ blobmsg_parse(rpc_lxc_min_policy, __RPC_LXC_MAX, tb, blob_data(msg), blob_len(msg));
+
+ l = rpc_lxc_init(tb);
+ if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (!l->container->is_running(l->container)) {
+ rc = UBUS_STATUS_UNKNOWN_ERROR;
+ goto out;
+ }
+
+ if (!l->container->reboot(l->container)) {
+ rc = UBUS_STATUS_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ rc = UBUS_STATUS_OK;
+out:
+ rpc_lxc_done(l);
+ return rc;
+}
+
+static int
+rpc_lxc_shutdown(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__RPC_LXC_SHUTDOWN_MAX];
+ struct rpc_lxc *l = NULL;
+ int rc;
+
+ blobmsg_parse(rpc_lxc_shutdown_policy, __RPC_LXC_SHUTDOWN_MAX, tb, blob_data(msg), blob_len(msg));
+
+ l = rpc_lxc_init(tb);
+ if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (!l->container->is_running(l->container)) {
+ rc = UBUS_STATUS_UNKNOWN_ERROR;
+ goto out;
+ }
+
+ /* define default timeout */
+ int timeout = 30;
+ if (tb[RPC_LXC_SHUTDOWN_TIMEOUT]) {
+ timeout = blobmsg_get_u32(tb[RPC_LXC_SHUTDOWN_TIMEOUT]);
+ }
+
+ if (!l->container->shutdown(l->container, timeout)) {
+ rc = UBUS_STATUS_UNKNOWN_ERROR;
+ goto out;
+ }
+
+ rc = UBUS_STATUS_OK;
+out:
+ rpc_lxc_done(l);
+ return rc;
+}
+
+static int
+rpc_lxc_stop(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__RPC_LXC_MAX];
+ struct rpc_lxc *l = NULL;
+ int rc;
+
+ blobmsg_parse(rpc_lxc_min_policy, __RPC_LXC_MAX, tb, blob_data(msg), blob_len(msg));
+
+ l = rpc_lxc_init(tb);
+ if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (!l->container->is_running(l->container)) {
+ rc = UBUS_STATUS_UNKNOWN_ERROR;
+ goto out;
+ }
+
+ if (!l->container->stop(l->container)) {
+ rc = UBUS_STATUS_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ rc = UBUS_STATUS_OK;
+out:
+ rpc_lxc_done(l);
+ return rc;
+}
+
+static int
+rpc_lxc_freeze(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__RPC_LXC_MAX];
+ struct rpc_lxc *l = NULL;
+ int rc;
+
+ blobmsg_parse(rpc_lxc_min_policy, __RPC_LXC_MAX, tb, blob_data(msg), blob_len(msg));
+
+ l = rpc_lxc_init(tb);
+ if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (!l->container->is_running(l->container)) {
+ rc = UBUS_STATUS_UNKNOWN_ERROR;
+ goto out;
+ }
+
+ if (!l->container->freeze(l->container)) {
+ rc = UBUS_STATUS_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ rc = UBUS_STATUS_OK;
+out:
+ rpc_lxc_done(l);
+ return rc;
+}
+
+static int
+rpc_lxc_unfreeze(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__RPC_LXC_MAX];
+ struct rpc_lxc *l = NULL;
+ int rc;
+
+ blobmsg_parse(rpc_lxc_min_policy, __RPC_LXC_MAX, tb, blob_data(msg), blob_len(msg));
+
+ l = rpc_lxc_init(tb);
+ if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (!l->container->is_running(l->container)) {
+ rc = UBUS_STATUS_UNKNOWN_ERROR;
+ goto out;
+ }
+
+ if (!l->container->unfreeze(l->container)) {
+ rc = UBUS_STATUS_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ rc = UBUS_STATUS_OK;
+out:
+ rpc_lxc_done(l);
+ return rc;
+}
+
+static int
+rpc_lxc_info(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__RPC_LXC_RENAME_MAX];
+ struct rpc_lxc *l = NULL;
+ char **addresses;
+ void *k;
+ pid_t initpid;
+
+ blobmsg_parse(rpc_lxc_min_policy, __RPC_LXC_MAX, tb, blob_data(msg), blob_len(msg));
+
+ l = rpc_lxc_init(tb);
+ if (!l)
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (!l->container->is_running(l->container) &&
+ !l->container->is_defined(l->container))
+ return UBUS_STATUS_NOT_FOUND;
+
+ blob_buf_init(&buf, 0);
+
+ blobmsg_add_string(&buf, "name", l->container->name);
+
+ blobmsg_add_string(&buf, "state", l->container->state(l->container));
+
+ initpid = l->container->init_pid(l->container);
+ if (initpid >= 0)
+ blobmsg_add_u32(&buf, "pid", initpid);
+
+ k = blobmsg_open_array(&buf, "ips");
+ addresses = l->container->get_ips(l->container, NULL, NULL, 0);
+ if (addresses) {
+ int i;
+
+ for (i = 0; addresses[i]; i++)
+ blobmsg_add_string(&buf, "ip", addresses[i]);
+ }
+ blobmsg_close_array(&buf, k);
+
+ ubus_send_reply(ctx, req, buf.head);
+ rpc_lxc_done(l);
+
+ return UBUS_STATUS_OK;
+}
+
+static int
+rpc_lxc_rename(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__RPC_LXC_RENAME_MAX];
+ struct rpc_lxc *l = NULL;
+ int rc;
+
+ blobmsg_parse(rpc_lxc_rename_policy, __RPC_LXC_RENAME_MAX, tb, blob_data(msg), blob_len(msg));
+
+ l = rpc_lxc_init(tb);
+ if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (!tb[RPC_LXC_RENAME_NEWNAME]) {
+ rc = UBUS_STATUS_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ if (l->container->is_running(l->container)) {
+ rc = UBUS_STATUS_UNKNOWN_ERROR;
+ goto out;
+ }
+
+ char *newname = blobmsg_data(tb[RPC_LXC_RENAME_NEWNAME]);
+ if (!newname || !l->container->rename(l->container, newname)) {
+ rc = UBUS_STATUS_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ rc = UBUS_STATUS_OK;
+out:
+ rpc_lxc_done(l);
+ return rc;
+}
+
+static int
+rpc_lxc_create(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__RPC_LXC_CREATE_MAX];
+ struct rpc_lxc *l = NULL;
+ int rc;
+
+ char *template = "none";
+ int flags = 0;
+ char **args = NULL;
+
+ blobmsg_parse(rpc_lxc_create_policy, __RPC_LXC_CREATE_MAX, tb, blob_data(msg), blob_len(msg));
+
+ l = rpc_lxc_init(tb);
+ if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (tb[RPC_LXC_CREATE_TEMPLATE])
+ template = blobmsg_data(tb[RPC_LXC_CREATE_TEMPLATE]);
+
+ if (tb[RPC_LXC_CREATE_FLAGS])
+ flags = blobmsg_get_u32(tb[RPC_LXC_CREATE_FLAGS]);
+
+ if (tb[RPC_LXC_CREATE_ARGS]) {
+ struct blob_attr *cur;
+ int num, rem;
+
+ num = blobmsg_check_array(tb[RPC_LXC_CREATE_ARGS], BLOBMSG_TYPE_STRING);
+
+ // trailing NULL is needed
+ args = calloc(num + 1, sizeof(char *));
+ if (!args) {
+ rc = UBUS_STATUS_UNKNOWN_ERROR;
+ goto out;
+ }
+
+ num = 0;
+ blobmsg_for_each_attr(cur, tb[RPC_LXC_CREATE_ARGS], rem)
+ {
+ if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
+ continue;
+
+ args[num++] = (char *) blobmsg_data(cur);
+ }
+ }
+
+ if (!l->container->create(l->container, template, NULL, NULL, flags, args)) {
+ rc = UBUS_STATUS_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ rc = UBUS_STATUS_OK;
+out:
+ rpc_lxc_done(l);
+ free(args);
+ return rc;
+}
+
+static int
+rpc_lxc_destroy(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__RPC_LXC_MAX];
+ struct rpc_lxc *l = NULL;
+ int rc;
+
+ blobmsg_parse(rpc_lxc_min_policy, __RPC_LXC_MAX, tb, blob_data(msg), blob_len(msg));
+
+ l = rpc_lxc_init(tb);
+ if (!l) return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (l->container->is_running(l->container)) {
+ rc = UBUS_STATUS_UNKNOWN_ERROR;
+ goto out;
+ }
+
+ if (!l->container->destroy(l->container)) {
+ rc = UBUS_STATUS_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ rc = UBUS_STATUS_OK;
+out:
+ rpc_lxc_done(l);
+ return rc;
+}
+
+static int
+rpc_lxc_list(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+
+ blob_buf_init(&buf, 0);
+
+ int rc;
+ char **names;
+ struct lxc_container **cret;
+
+ rc = list_all_containers(NULL, &names, &cret);
+ if (rc == -1)
+ return UBUS_STATUS_UNKNOWN_ERROR;
+
+ for (int i = 0; i < rc; i++) {
+ struct lxc_container *c = cret[i];
+ blobmsg_add_string(&buf, names[i], c->state(c));
+
+ free(names[i]);
+ lxc_container_put(c);
+ }
+
+ ubus_send_reply(ctx, req, buf.head);
+
+ return UBUS_STATUS_OK;
+}
+
+static int
+rpc_lxc_api_init(const struct rpc_daemon_ops *o, struct ubus_context *ctx)
+{
+ static const struct ubus_method lxc_methods[] = {
+ UBUS_METHOD("start", rpc_lxc_start, rpc_lxc_min_policy),
+ UBUS_METHOD("reboot", rpc_lxc_reboot, rpc_lxc_min_policy),
+ UBUS_METHOD("shutdown", rpc_lxc_shutdown, rpc_lxc_shutdown_policy),
+ UBUS_METHOD("stop", rpc_lxc_stop, rpc_lxc_min_policy),
+ UBUS_METHOD("freeze", rpc_lxc_freeze, rpc_lxc_min_policy),
+ UBUS_METHOD("unfreeze", rpc_lxc_unfreeze, rpc_lxc_min_policy),
+ UBUS_METHOD("info", rpc_lxc_info, rpc_lxc_min_policy),
+ UBUS_METHOD("rename", rpc_lxc_rename, rpc_lxc_rename_policy),
+ UBUS_METHOD("create", rpc_lxc_create, rpc_lxc_create_policy),
+ UBUS_METHOD("destroy", rpc_lxc_destroy, rpc_lxc_min_policy),
+ UBUS_METHOD_NOARG("list", rpc_lxc_list),
+ };
+
+ static struct ubus_object_type lxc_type =
+ UBUS_OBJECT_TYPE("luci-rpc-lxc", lxc_methods);
+
+ static struct ubus_object obj = {
+ .name = "lxc",
+ .type = &lxc_type,
+ .methods = lxc_methods,
+ .n_methods = ARRAY_SIZE(lxc_methods),
+ };
+
+ return ubus_add_object(ctx, &obj);
+}
+
+struct rpc_plugin rpc_plugin = {
+ .init = rpc_lxc_api_init
+};
diff --git a/external/subpack/utils/rpcd-mod-wireguard/Makefile b/external/subpack/utils/rpcd-mod-wireguard/Makefile
new file mode 100644
index 0000000..9fb7d7e
--- /dev/null
+++ b/external/subpack/utils/rpcd-mod-wireguard/Makefile
@@ -0,0 +1,31 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=rpcd-mod-wireguard
+PKG_RELEASE=1
+
+PKG_LICENSE:=LGPL-2.1+
+PKG_BUILD_FLAGS:=gc-sections
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/rpcd-mod-wireguard
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=WireGuard rpcd module
+ DEPENDS:=+rpcd +kmod-wireguard
+ MAINTAINER:=Andre Heider <a.heider@gmail.com>
+endef
+
+define Package/rpcd-mod-wireguard/install
+ $(INSTALL_DIR) $(1)/usr/lib/rpcd
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/rpcd/wireguard.so \
+ $(1)/usr/lib/rpcd/
+endef
+
+define Package/rpcd-mod-wireguard/postinst
+#!/bin/sh
+[ -n "$$IPKG_INSTROOT" ] || /etc/init.d/rpcd reload
+endef
+
+$(eval $(call BuildPackage,rpcd-mod-wireguard))
diff --git a/external/subpack/utils/rpcd-mod-wireguard/src/CMakeLists.txt b/external/subpack/utils/rpcd-mod-wireguard/src/CMakeLists.txt
new file mode 100644
index 0000000..97e06aa
--- /dev/null
+++ b/external/subpack/utils/rpcd-mod-wireguard/src/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.8.12)
+PROJECT(rpcd-mod-wireguard)
+ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -g3 -Wmissing-declarations)
+
+SET(SOURCES wireguard.c api.c)
+
+ADD_LIBRARY(rpcd-mod-wireguard SHARED ${SOURCES})
+
+SET_TARGET_PROPERTIES(rpcd-mod-wireguard PROPERTIES OUTPUT_NAME wireguard PREFIX "")
+INSTALL(TARGETS rpcd-mod-wireguard LIBRARY DESTINATION lib/rpcd)
diff --git a/external/subpack/utils/rpcd-mod-wireguard/src/api.c b/external/subpack/utils/rpcd-mod-wireguard/src/api.c
new file mode 100644
index 0000000..e80ed53
--- /dev/null
+++ b/external/subpack/utils/rpcd-mod-wireguard/src/api.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: LGPL-2.1+
+// Copyright (C) 2023 Andre Heider <a.heider@gmail.com>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <libubox/blobmsg.h>
+#include <libubox/blobmsg_json.h>
+
+#include <libubus.h>
+
+#include <rpcd/plugin.h>
+
+#include "wireguard.h"
+
+static struct blob_buf buf;
+
+enum {
+ RPC_PK_DEVICE,
+ __RPC_PK_MAX,
+};
+
+static const struct blobmsg_policy rpc_privatekey_policy[__RPC_PK_MAX] = {
+ [RPC_PK_DEVICE] = { .name = "private", .type = BLOBMSG_TYPE_STRING },
+};
+
+static void rpc_wireguard_add_endpoint(const wg_endpoint *endpoint)
+{
+ char host[1025]; // NI_MAXHOST
+ char serv[32]; // NI_MAXSERV
+ char res[sizeof(host) + sizeof(serv) + 4];
+ socklen_t addr_len;
+
+ memset(res, 0, sizeof(res));
+ if (endpoint->addr.sa_family == AF_INET)
+ addr_len = sizeof(struct sockaddr_in);
+ else if (endpoint->addr.sa_family == AF_INET6)
+ addr_len = sizeof(struct sockaddr_in6);
+ else
+ return;
+
+ if (getnameinfo(&endpoint->addr, addr_len, host, sizeof(host), serv, sizeof(serv),
+ NI_DGRAM | NI_NUMERICHOST | NI_NUMERICSERV))
+ return;
+
+ if (endpoint->addr.sa_family == AF_INET6 && strchr(host, ':'))
+ snprintf(res, sizeof(res), "[%s]:%s", host, serv);
+ else
+ snprintf(res, sizeof(res), "%s:%s", host, serv);
+ res[sizeof(res) - 1] = 0;
+
+ blobmsg_add_string(&buf, "endpoint", res);
+}
+
+static void rpc_wireguard_add_allowedip(const wg_allowedip *allowedip)
+{
+ char res[INET6_ADDRSTRLEN + 4 + 1];
+
+ memset(res, 0, sizeof(res));
+ if (allowedip->family == AF_INET)
+ inet_ntop(AF_INET, &allowedip->ip4, res, INET6_ADDRSTRLEN);
+ else if (allowedip->family == AF_INET6)
+ inet_ntop(AF_INET6, &allowedip->ip6, res, INET6_ADDRSTRLEN);
+ else
+ return;
+
+ if (!res[0])
+ return;
+
+ sprintf(res + strlen(res), "/%u", allowedip->cidr);
+ res[sizeof(res) - 1] = 0;
+
+ blobmsg_add_string(&buf, NULL, res);
+}
+
+static void rpc_wireguard_add_peer(const wg_peer *peer)
+{
+ void *c;
+ struct wg_allowedip *allowedip;
+
+ rpc_wireguard_add_endpoint(&peer->endpoint);
+
+ c = blobmsg_open_array(&buf, "allowed_ips");
+ wg_for_each_allowedip(peer, allowedip)
+ rpc_wireguard_add_allowedip(allowedip);
+ blobmsg_close_array(&buf, c);
+
+ blobmsg_add_u64(&buf, "last_handshake", peer->last_handshake_time.tv_sec);
+ blobmsg_add_u64(&buf, "rx_bytes", peer->rx_bytes);
+ blobmsg_add_u64(&buf, "tx_bytes", peer->tx_bytes);
+ if (peer->persistent_keepalive_interval)
+ blobmsg_add_u16(&buf, "persistent_keepalive_interval", peer->persistent_keepalive_interval);
+}
+
+static void rpc_wireguard_add_device(const wg_device *device)
+{
+ void *c, *d;
+ wg_peer *peer;
+ wg_key_b64_string key;
+
+ blobmsg_add_u32(&buf, "ifindex", device->ifindex);
+
+ if (device->flags & WGDEVICE_HAS_PUBLIC_KEY) {
+ wg_key_to_base64(key, device->public_key);
+ blobmsg_add_string(&buf, "public_key", key);
+ }
+
+ if (device->listen_port)
+ blobmsg_add_u16(&buf, "listen_port", device->listen_port);
+
+ if (device->fwmark)
+ blobmsg_add_u32(&buf, "fwmark", device->fwmark);
+
+ c = blobmsg_open_table(&buf, "peers");
+ wg_for_each_peer(device, peer) {
+ wg_key_to_base64(key, peer->public_key);
+ d = blobmsg_open_table(&buf, key);
+ rpc_wireguard_add_peer(peer);
+ blobmsg_close_table(&buf, d);
+ }
+ blobmsg_close_table(&buf, c);
+}
+
+static int rpc_wireguard_status(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method, struct blob_attr *msg)
+{
+ void *c;
+ char *device_names, *device_name;
+ size_t len;
+
+ device_names = wg_list_device_names();
+ if (!device_names)
+ return UBUS_STATUS_NOT_FOUND;
+
+ blob_buf_init(&buf, 0);
+
+ wg_for_each_device_name(device_names, device_name, len) {
+ wg_device *device;
+
+ if (wg_get_device(&device, device_name) < 0)
+ continue;
+
+ c = blobmsg_open_table(&buf, device_name);
+ rpc_wireguard_add_device(device);
+ blobmsg_close_table(&buf, c);
+
+ wg_free_device(device);
+ }
+
+ free(device_names);
+
+ ubus_send_reply(ctx, req, buf.head);
+
+ return UBUS_STATUS_OK;
+}
+
+static int rpc_wireguard_genkey(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method, struct blob_attr *msg)
+{
+ wg_key private_key, public_key;
+ wg_key_b64_string key;
+
+ wg_generate_private_key(private_key);
+ wg_generate_public_key(public_key, private_key);
+
+ blob_buf_init(&buf, 0);
+ wg_key_to_base64(key, private_key);
+ blobmsg_add_string(&buf, "private", key);
+ wg_key_to_base64(key, public_key);
+ blobmsg_add_string(&buf, "public", key);
+ ubus_send_reply(ctx, req, buf.head);
+
+ return UBUS_STATUS_OK;
+}
+
+static int rpc_wireguard_genpsk(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method, struct blob_attr *msg)
+{
+ wg_key preshared_key;
+ wg_key_b64_string key;
+
+ wg_generate_preshared_key(preshared_key);
+
+ blob_buf_init(&buf, 0);
+ wg_key_to_base64(key, preshared_key);
+ blobmsg_add_string(&buf, "preshared", key);
+ ubus_send_reply(ctx, req, buf.head);
+
+ return UBUS_STATUS_OK;
+}
+
+static int rpc_wireguard_pubkey(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method, struct blob_attr *msg)
+{
+ static struct blob_attr *tb[__RPC_PK_MAX];
+ wg_key_b64_string key;
+ wg_key private_key, public_key;
+
+ blobmsg_parse(rpc_privatekey_policy, __RPC_PK_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[RPC_PK_DEVICE])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (wg_key_from_base64(private_key, blobmsg_get_string(tb[RPC_PK_DEVICE])))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ wg_generate_public_key(public_key, private_key);
+ blob_buf_init(&buf, 0);
+ wg_key_to_base64(key, public_key);
+ blobmsg_add_string(&buf, "public", key);
+ ubus_send_reply(ctx, req, buf.head);
+
+ return UBUS_STATUS_OK;
+}
+
+static int rpc_wireguard_api_init(const struct rpc_daemon_ops *ops, struct ubus_context *ctx)
+{
+ static const struct ubus_method wireguard_methods[] = {
+ UBUS_METHOD_NOARG("status", rpc_wireguard_status),
+ UBUS_METHOD_NOARG("genkey", rpc_wireguard_genkey),
+ UBUS_METHOD_NOARG("genpsk", rpc_wireguard_genpsk),
+ UBUS_METHOD("pubkey", rpc_wireguard_pubkey, rpc_privatekey_policy),
+ };
+
+ static struct ubus_object_type wireguard_type =
+ UBUS_OBJECT_TYPE("rpcd-plugin-wireguard", wireguard_methods);
+
+ static struct ubus_object obj = {
+ .name = "wireguard",
+ .type = &wireguard_type,
+ .methods = wireguard_methods,
+ .n_methods = ARRAY_SIZE(wireguard_methods),
+ };
+
+ return ubus_add_object(ctx, &obj);
+}
+
+struct rpc_plugin rpc_plugin = {
+ .init = rpc_wireguard_api_init
+};
diff --git a/external/subpack/utils/rpcd-mod-wireguard/src/wireguard.c b/external/subpack/utils/rpcd-mod-wireguard/src/wireguard.c
new file mode 100644
index 0000000..4941549
--- /dev/null
+++ b/external/subpack/utils/rpcd-mod-wireguard/src/wireguard.c
@@ -0,0 +1,1755 @@
+// SPDX-License-Identifier: LGPL-2.1+
+/*
+ * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ * Copyright (C) 2008-2012 Pablo Neira Ayuso <pablo@netfilter.org>.
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <linux/genetlink.h>
+#include <linux/if_link.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include "wireguard.h"
+
+/* wireguard.h netlink uapi: */
+
+#define WG_GENL_NAME "wireguard"
+#define WG_GENL_VERSION 1
+
+enum wg_cmd {
+ WG_CMD_GET_DEVICE,
+ WG_CMD_SET_DEVICE,
+ __WG_CMD_MAX
+};
+
+enum wgdevice_flag {
+ WGDEVICE_F_REPLACE_PEERS = 1U << 0
+};
+enum wgdevice_attribute {
+ WGDEVICE_A_UNSPEC,
+ WGDEVICE_A_IFINDEX,
+ WGDEVICE_A_IFNAME,
+ WGDEVICE_A_PRIVATE_KEY,
+ WGDEVICE_A_PUBLIC_KEY,
+ WGDEVICE_A_FLAGS,
+ WGDEVICE_A_LISTEN_PORT,
+ WGDEVICE_A_FWMARK,
+ WGDEVICE_A_PEERS,
+ __WGDEVICE_A_LAST
+};
+
+enum wgpeer_flag {
+ WGPEER_F_REMOVE_ME = 1U << 0,
+ WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1
+};
+enum wgpeer_attribute {
+ WGPEER_A_UNSPEC,
+ WGPEER_A_PUBLIC_KEY,
+ WGPEER_A_PRESHARED_KEY,
+ WGPEER_A_FLAGS,
+ WGPEER_A_ENDPOINT,
+ WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL,
+ WGPEER_A_LAST_HANDSHAKE_TIME,
+ WGPEER_A_RX_BYTES,
+ WGPEER_A_TX_BYTES,
+ WGPEER_A_ALLOWEDIPS,
+ WGPEER_A_PROTOCOL_VERSION,
+ __WGPEER_A_LAST
+};
+
+enum wgallowedip_attribute {
+ WGALLOWEDIP_A_UNSPEC,
+ WGALLOWEDIP_A_FAMILY,
+ WGALLOWEDIP_A_IPADDR,
+ WGALLOWEDIP_A_CIDR_MASK,
+ __WGALLOWEDIP_A_LAST
+};
+
+/* libmnl mini library: */
+
+#define MNL_SOCKET_AUTOPID 0
+#define MNL_ALIGNTO 4
+#define MNL_ALIGN(len) (((len)+MNL_ALIGNTO-1) & ~(MNL_ALIGNTO-1))
+#define MNL_NLMSG_HDRLEN MNL_ALIGN(sizeof(struct nlmsghdr))
+#define MNL_ATTR_HDRLEN MNL_ALIGN(sizeof(struct nlattr))
+
+enum mnl_attr_data_type {
+ MNL_TYPE_UNSPEC,
+ MNL_TYPE_U8,
+ MNL_TYPE_U16,
+ MNL_TYPE_U32,
+ MNL_TYPE_U64,
+ MNL_TYPE_STRING,
+ MNL_TYPE_FLAG,
+ MNL_TYPE_MSECS,
+ MNL_TYPE_NESTED,
+ MNL_TYPE_NESTED_COMPAT,
+ MNL_TYPE_NUL_STRING,
+ MNL_TYPE_BINARY,
+ MNL_TYPE_MAX,
+};
+
+#define mnl_attr_for_each(attr, nlh, offset) \
+ for ((attr) = mnl_nlmsg_get_payload_offset((nlh), (offset)); \
+ mnl_attr_ok((attr), (char *)mnl_nlmsg_get_payload_tail(nlh) - (char *)(attr)); \
+ (attr) = mnl_attr_next(attr))
+
+#define mnl_attr_for_each_nested(attr, nest) \
+ for ((attr) = mnl_attr_get_payload(nest); \
+ mnl_attr_ok((attr), (char *)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - (char *)(attr)); \
+ (attr) = mnl_attr_next(attr))
+
+#define mnl_attr_for_each_payload(payload, payload_size) \
+ for ((attr) = (payload); \
+ mnl_attr_ok((attr), (char *)(payload) + payload_size - (char *)(attr)); \
+ (attr) = mnl_attr_next(attr))
+
+#define MNL_CB_ERROR -1
+#define MNL_CB_STOP 0
+#define MNL_CB_OK 1
+
+typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data);
+typedef int (*mnl_cb_t)(const struct nlmsghdr *nlh, void *data);
+
+#ifndef MNL_ARRAY_SIZE
+#define MNL_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
+#endif
+
+static size_t mnl_ideal_socket_buffer_size(void)
+{
+ static size_t size = 0;
+
+ if (size)
+ return size;
+ size = (size_t)sysconf(_SC_PAGESIZE);
+ if (size > 8192)
+ size = 8192;
+ return size;
+}
+
+static size_t mnl_nlmsg_size(size_t len)
+{
+ return len + MNL_NLMSG_HDRLEN;
+}
+
+static struct nlmsghdr *mnl_nlmsg_put_header(void *buf)
+{
+ int len = MNL_ALIGN(sizeof(struct nlmsghdr));
+ struct nlmsghdr *nlh = buf;
+
+ memset(buf, 0, len);
+ nlh->nlmsg_len = len;
+ return nlh;
+}
+
+static void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size)
+{
+ char *ptr = (char *)nlh + nlh->nlmsg_len;
+ size_t len = MNL_ALIGN(size);
+ nlh->nlmsg_len += len;
+ memset(ptr, 0, len);
+ return ptr;
+}
+
+static void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh)
+{
+ return (void *)nlh + MNL_NLMSG_HDRLEN;
+}
+
+static void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset)
+{
+ return (void *)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset);
+}
+
+static bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len)
+{
+ return len >= (int)sizeof(struct nlmsghdr) &&
+ nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
+ (int)nlh->nlmsg_len <= len;
+}
+
+static struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len)
+{
+ *len -= MNL_ALIGN(nlh->nlmsg_len);
+ return (struct nlmsghdr *)((void *)nlh + MNL_ALIGN(nlh->nlmsg_len));
+}
+
+static void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
+{
+ return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len);
+}
+
+static bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq)
+{
+ return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true;
+}
+
+static bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid)
+{
+ return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true;
+}
+
+static uint16_t mnl_attr_get_type(const struct nlattr *attr)
+{
+ return attr->nla_type & NLA_TYPE_MASK;
+}
+
+static uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
+{
+ return attr->nla_len - MNL_ATTR_HDRLEN;
+}
+
+static void *mnl_attr_get_payload(const struct nlattr *attr)
+{
+ return (void *)attr + MNL_ATTR_HDRLEN;
+}
+
+static bool mnl_attr_ok(const struct nlattr *attr, int len)
+{
+ return len >= (int)sizeof(struct nlattr) &&
+ attr->nla_len >= sizeof(struct nlattr) &&
+ (int)attr->nla_len <= len;
+}
+
+static struct nlattr *mnl_attr_next(const struct nlattr *attr)
+{
+ return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len));
+}
+
+static int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
+{
+ if (mnl_attr_get_type(attr) > max) {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+ return 1;
+}
+
+static int __mnl_attr_validate(const struct nlattr *attr,
+ enum mnl_attr_data_type type, size_t exp_len)
+{
+ uint16_t attr_len = mnl_attr_get_payload_len(attr);
+ const char *attr_data = mnl_attr_get_payload(attr);
+
+ if (attr_len < exp_len) {
+ errno = ERANGE;
+ return -1;
+ }
+ switch(type) {
+ case MNL_TYPE_FLAG:
+ if (attr_len > 0) {
+ errno = ERANGE;
+ return -1;
+ }
+ break;
+ case MNL_TYPE_NUL_STRING:
+ if (attr_len == 0) {
+ errno = ERANGE;
+ return -1;
+ }
+ if (attr_data[attr_len-1] != '\0') {
+ errno = EINVAL;
+ return -1;
+ }
+ break;
+ case MNL_TYPE_STRING:
+ if (attr_len == 0) {
+ errno = ERANGE;
+ return -1;
+ }
+ break;
+ case MNL_TYPE_NESTED:
+
+ if (attr_len == 0)
+ break;
+
+ if (attr_len < MNL_ATTR_HDRLEN) {
+ errno = ERANGE;
+ return -1;
+ }
+ break;
+ default:
+
+ break;
+ }
+ if (exp_len && attr_len > exp_len) {
+ errno = ERANGE;
+ return -1;
+ }
+ return 0;
+}
+
+static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = {
+ [MNL_TYPE_U8] = sizeof(uint8_t),
+ [MNL_TYPE_U16] = sizeof(uint16_t),
+ [MNL_TYPE_U32] = sizeof(uint32_t),
+ [MNL_TYPE_U64] = sizeof(uint64_t),
+ [MNL_TYPE_MSECS] = sizeof(uint64_t),
+};
+
+static int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
+{
+ int exp_len;
+
+ if (type >= MNL_TYPE_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+ exp_len = mnl_attr_data_type_len[type];
+ return __mnl_attr_validate(attr, type, exp_len);
+}
+
+static int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset,
+ mnl_attr_cb_t cb, void *data)
+{
+ int ret = MNL_CB_OK;
+ const struct nlattr *attr;
+
+ mnl_attr_for_each(attr, nlh, offset)
+ if ((ret = cb(attr, data)) <= MNL_CB_STOP)
+ return ret;
+ return ret;
+}
+
+static int mnl_attr_parse_nested(const struct nlattr *nested, mnl_attr_cb_t cb,
+ void *data)
+{
+ int ret = MNL_CB_OK;
+ const struct nlattr *attr;
+
+ mnl_attr_for_each_nested(attr, nested)
+ if ((ret = cb(attr, data)) <= MNL_CB_STOP)
+ return ret;
+ return ret;
+}
+
+static uint8_t mnl_attr_get_u8(const struct nlattr *attr)
+{
+ return *((uint8_t *)mnl_attr_get_payload(attr));
+}
+
+static uint16_t mnl_attr_get_u16(const struct nlattr *attr)
+{
+ return *((uint16_t *)mnl_attr_get_payload(attr));
+}
+
+static uint32_t mnl_attr_get_u32(const struct nlattr *attr)
+{
+ return *((uint32_t *)mnl_attr_get_payload(attr));
+}
+
+static uint64_t mnl_attr_get_u64(const struct nlattr *attr)
+{
+ uint64_t tmp;
+ memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
+ return tmp;
+}
+
+static const char *mnl_attr_get_str(const struct nlattr *attr)
+{
+ return mnl_attr_get_payload(attr);
+}
+
+static void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len,
+ const void *data)
+{
+ struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
+ uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
+ int pad;
+
+ attr->nla_type = type;
+ attr->nla_len = payload_len;
+ memcpy(mnl_attr_get_payload(attr), data, len);
+ nlh->nlmsg_len += MNL_ALIGN(payload_len);
+ pad = MNL_ALIGN(len) - len;
+ if (pad > 0)
+ memset(mnl_attr_get_payload(attr) + len, 0, pad);
+}
+
+static void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data)
+{
+ mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
+}
+
+static void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data)
+{
+ mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
+}
+
+static void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data)
+{
+ mnl_attr_put(nlh, type, strlen(data)+1, data);
+}
+
+static struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type)
+{
+ struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
+
+ start->nla_type = NLA_F_NESTED | type;
+ nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
+ return start;
+}
+
+static bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
+ uint16_t type, size_t len, const void *data)
+{
+ if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
+ return false;
+ mnl_attr_put(nlh, type, len, data);
+ return true;
+}
+
+static bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
+ uint16_t type, uint8_t data)
+{
+ return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
+}
+
+static bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
+ uint16_t type, uint16_t data)
+{
+ return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
+}
+
+static bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
+ uint16_t type, uint32_t data)
+{
+ return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
+}
+
+static struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen,
+ uint16_t type)
+{
+ if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
+ return NULL;
+ return mnl_attr_nest_start(nlh, type);
+}
+
+static void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start)
+{
+ start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
+}
+
+static void mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start)
+{
+ nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
+}
+
+static int mnl_cb_noop(__attribute__((unused)) const struct nlmsghdr *nlh, __attribute__((unused)) void *data)
+{
+ return MNL_CB_OK;
+}
+
+static int mnl_cb_error(const struct nlmsghdr *nlh, __attribute__((unused)) void *data)
+{
+ const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
+
+ if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
+ errno = EBADMSG;
+ return MNL_CB_ERROR;
+ }
+
+ if (err->error < 0)
+ errno = -err->error;
+ else
+ errno = err->error;
+
+ return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
+}
+
+static int mnl_cb_stop(__attribute__((unused)) const struct nlmsghdr *nlh, __attribute__((unused)) void *data)
+{
+ return MNL_CB_STOP;
+}
+
+static const mnl_cb_t default_cb_array[NLMSG_MIN_TYPE] = {
+ [NLMSG_NOOP] = mnl_cb_noop,
+ [NLMSG_ERROR] = mnl_cb_error,
+ [NLMSG_DONE] = mnl_cb_stop,
+ [NLMSG_OVERRUN] = mnl_cb_noop,
+};
+
+static int __mnl_cb_run(const void *buf, size_t numbytes,
+ unsigned int seq, unsigned int portid,
+ mnl_cb_t cb_data, void *data,
+ const mnl_cb_t *cb_ctl_array,
+ unsigned int cb_ctl_array_len)
+{
+ int ret = MNL_CB_OK, len = numbytes;
+ const struct nlmsghdr *nlh = buf;
+
+ while (mnl_nlmsg_ok(nlh, len)) {
+
+ if (!mnl_nlmsg_portid_ok(nlh, portid)) {
+ errno = ESRCH;
+ return -1;
+ }
+
+ if (!mnl_nlmsg_seq_ok(nlh, seq)) {
+ errno = EPROTO;
+ return -1;
+ }
+
+ if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
+ errno = EINTR;
+ return -1;
+ }
+
+ if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) {
+ if (cb_data){
+ ret = cb_data(nlh, data);
+ if (ret <= MNL_CB_STOP)
+ goto out;
+ }
+ } else if (nlh->nlmsg_type < cb_ctl_array_len) {
+ if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) {
+ ret = cb_ctl_array[nlh->nlmsg_type](nlh, data);
+ if (ret <= MNL_CB_STOP)
+ goto out;
+ }
+ } else if (default_cb_array[nlh->nlmsg_type]) {
+ ret = default_cb_array[nlh->nlmsg_type](nlh, data);
+ if (ret <= MNL_CB_STOP)
+ goto out;
+ }
+ nlh = mnl_nlmsg_next(nlh, &len);
+ }
+out:
+ return ret;
+}
+
+static int mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq,
+ unsigned int portid, mnl_cb_t cb_data, void *data,
+ const mnl_cb_t *cb_ctl_array, unsigned int cb_ctl_array_len)
+{
+ return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data,
+ cb_ctl_array, cb_ctl_array_len);
+}
+
+static int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
+ unsigned int portid, mnl_cb_t cb_data, void *data)
+{
+ return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0);
+}
+
+struct mnl_socket {
+ int fd;
+ struct sockaddr_nl addr;
+};
+
+static unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
+{
+ return nl->addr.nl_pid;
+}
+
+static struct mnl_socket *__mnl_socket_open(int bus, int flags)
+{
+ struct mnl_socket *nl;
+
+ nl = calloc(1, sizeof(struct mnl_socket));
+ if (nl == NULL)
+ return NULL;
+
+ nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus);
+ if (nl->fd == -1) {
+ free(nl);
+ return NULL;
+ }
+
+ return nl;
+}
+
+static struct mnl_socket *mnl_socket_open(int bus)
+{
+ return __mnl_socket_open(bus, 0);
+}
+
+static int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid)
+{
+ int ret;
+ socklen_t addr_len;
+
+ nl->addr.nl_family = AF_NETLINK;
+ nl->addr.nl_groups = groups;
+ nl->addr.nl_pid = pid;
+
+ ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr));
+ if (ret < 0)
+ return ret;
+
+ addr_len = sizeof(nl->addr);
+ ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len);
+ if (ret < 0)
+ return ret;
+
+ if (addr_len != sizeof(nl->addr)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (nl->addr.nl_family != AF_NETLINK) {
+ errno = EINVAL;
+ return -1;
+ }
+ return 0;
+}
+
+static ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *buf,
+ size_t len)
+{
+ static const struct sockaddr_nl snl = {
+ .nl_family = AF_NETLINK
+ };
+ return sendto(nl->fd, buf, len, 0,
+ (struct sockaddr *) &snl, sizeof(snl));
+}
+
+static ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf,
+ size_t bufsiz)
+{
+ ssize_t ret;
+ struct sockaddr_nl addr;
+ struct iovec iov = {
+ .iov_base = buf,
+ .iov_len = bufsiz,
+ };
+ struct msghdr msg = {
+ .msg_name = &addr,
+ .msg_namelen = sizeof(struct sockaddr_nl),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = NULL,
+ .msg_controllen = 0,
+ .msg_flags = 0,
+ };
+ ret = recvmsg(nl->fd, &msg, 0);
+ if (ret == -1)
+ return ret;
+
+ if (msg.msg_flags & MSG_TRUNC) {
+ errno = ENOSPC;
+ return -1;
+ }
+ if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
+ errno = EINVAL;
+ return -1;
+ }
+ return ret;
+}
+
+static int mnl_socket_close(struct mnl_socket *nl)
+{
+ int ret = close(nl->fd);
+ free(nl);
+ return ret;
+}
+
+/* mnlg mini library: */
+
+struct mnlg_socket {
+ struct mnl_socket *nl;
+ char *buf;
+ uint16_t id;
+ uint8_t version;
+ unsigned int seq;
+ unsigned int portid;
+};
+
+static struct nlmsghdr *__mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
+ uint16_t flags, uint16_t id,
+ uint8_t version)
+{
+ struct nlmsghdr *nlh;
+ struct genlmsghdr *genl;
+
+ nlh = mnl_nlmsg_put_header(nlg->buf);
+ nlh->nlmsg_type = id;
+ nlh->nlmsg_flags = flags;
+ nlg->seq = time(NULL);
+ nlh->nlmsg_seq = nlg->seq;
+
+ genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr));
+ genl->cmd = cmd;
+ genl->version = version;
+
+ return nlh;
+}
+
+static struct nlmsghdr *mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
+ uint16_t flags)
+{
+ return __mnlg_msg_prepare(nlg, cmd, flags, nlg->id, nlg->version);
+}
+
+static int mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh)
+{
+ return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len);
+}
+
+static int mnlg_cb_noop(const struct nlmsghdr *nlh, void *data)
+{
+ (void)nlh;
+ (void)data;
+ return MNL_CB_OK;
+}
+
+static int mnlg_cb_error(const struct nlmsghdr *nlh, void *data)
+{
+ const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
+ (void)data;
+
+ if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
+ errno = EBADMSG;
+ return MNL_CB_ERROR;
+ }
+ /* Netlink subsystems returns the errno value with different signess */
+ if (err->error < 0)
+ errno = -err->error;
+ else
+ errno = err->error;
+
+ return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
+}
+
+static int mnlg_cb_stop(const struct nlmsghdr *nlh, void *data)
+{
+ (void)data;
+ if (nlh->nlmsg_flags & NLM_F_MULTI && nlh->nlmsg_len == mnl_nlmsg_size(sizeof(int))) {
+ int error = *(int *)mnl_nlmsg_get_payload(nlh);
+ /* Netlink subsystems returns the errno value with different signess */
+ if (error < 0)
+ errno = -error;
+ else
+ errno = error;
+
+ return error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
+ }
+ return MNL_CB_STOP;
+}
+
+static const mnl_cb_t mnlg_cb_array[] = {
+ [NLMSG_NOOP] = mnlg_cb_noop,
+ [NLMSG_ERROR] = mnlg_cb_error,
+ [NLMSG_DONE] = mnlg_cb_stop,
+ [NLMSG_OVERRUN] = mnlg_cb_noop,
+};
+
+static int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data)
+{
+ int err;
+
+ do {
+ err = mnl_socket_recvfrom(nlg->nl, nlg->buf,
+ mnl_ideal_socket_buffer_size());
+ if (err <= 0)
+ break;
+ err = mnl_cb_run2(nlg->buf, err, nlg->seq, nlg->portid,
+ data_cb, data, mnlg_cb_array, MNL_ARRAY_SIZE(mnlg_cb_array));
+ } while (err > 0);
+
+ return err;
+}
+
+static int get_family_id_attr_cb(const struct nlattr *attr, void *data)
+{
+ const struct nlattr **tb = data;
+ int type = mnl_attr_get_type(attr);
+
+ if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
+ return MNL_CB_ERROR;
+
+ if (type == CTRL_ATTR_FAMILY_ID &&
+ mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
+ return MNL_CB_ERROR;
+ tb[type] = attr;
+ return MNL_CB_OK;
+}
+
+static int get_family_id_cb(const struct nlmsghdr *nlh, void *data)
+{
+ uint16_t *p_id = data;
+ struct nlattr *tb[CTRL_ATTR_MAX + 1] = { 0 };
+
+ mnl_attr_parse(nlh, sizeof(struct genlmsghdr), get_family_id_attr_cb, tb);
+ if (!tb[CTRL_ATTR_FAMILY_ID])
+ return MNL_CB_ERROR;
+ *p_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]);
+ return MNL_CB_OK;
+}
+
+static struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t version)
+{
+ struct mnlg_socket *nlg;
+ struct nlmsghdr *nlh;
+ int err;
+
+ nlg = malloc(sizeof(*nlg));
+ if (!nlg)
+ return NULL;
+ nlg->id = 0;
+
+ err = -ENOMEM;
+ nlg->buf = malloc(mnl_ideal_socket_buffer_size());
+ if (!nlg->buf)
+ goto err_buf_alloc;
+
+ nlg->nl = mnl_socket_open(NETLINK_GENERIC);
+ if (!nlg->nl) {
+ err = -errno;
+ goto err_mnl_socket_open;
+ }
+
+ if (mnl_socket_bind(nlg->nl, 0, MNL_SOCKET_AUTOPID) < 0) {
+ err = -errno;
+ goto err_mnl_socket_bind;
+ }
+
+ nlg->portid = mnl_socket_get_portid(nlg->nl);
+
+ nlh = __mnlg_msg_prepare(nlg, CTRL_CMD_GETFAMILY,
+ NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1);
+ mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, family_name);
+
+ if (mnlg_socket_send(nlg, nlh) < 0) {
+ err = -errno;
+ goto err_mnlg_socket_send;
+ }
+
+ errno = 0;
+ if (mnlg_socket_recv_run(nlg, get_family_id_cb, &nlg->id) < 0) {
+ errno = errno == ENOENT ? EPROTONOSUPPORT : errno;
+ err = errno ? -errno : -ENOSYS;
+ goto err_mnlg_socket_recv_run;
+ }
+
+ nlg->version = version;
+ errno = 0;
+ return nlg;
+
+err_mnlg_socket_recv_run:
+err_mnlg_socket_send:
+err_mnl_socket_bind:
+ mnl_socket_close(nlg->nl);
+err_mnl_socket_open:
+ free(nlg->buf);
+err_buf_alloc:
+ free(nlg);
+ errno = -err;
+ return NULL;
+}
+
+static void mnlg_socket_close(struct mnlg_socket *nlg)
+{
+ mnl_socket_close(nlg->nl);
+ free(nlg->buf);
+ free(nlg);
+}
+
+/* wireguard-specific parts: */
+
+struct string_list {
+ char *buffer;
+ size_t len;
+ size_t cap;
+};
+
+static int string_list_add(struct string_list *list, const char *str)
+{
+ size_t len = strlen(str) + 1;
+
+ if (len == 1)
+ return 0;
+
+ if (len >= list->cap - list->len) {
+ char *new_buffer;
+ size_t new_cap = list->cap * 2;
+
+ if (new_cap < list->len +len + 1)
+ new_cap = list->len + len + 1;
+ new_buffer = realloc(list->buffer, new_cap);
+ if (!new_buffer)
+ return -errno;
+ list->buffer = new_buffer;
+ list->cap = new_cap;
+ }
+ memcpy(list->buffer + list->len, str, len);
+ list->len += len;
+ list->buffer[list->len] = '\0';
+ return 0;
+}
+
+struct interface {
+ const char *name;
+ bool is_wireguard;
+};
+
+static int parse_linkinfo(const struct nlattr *attr, void *data)
+{
+ struct interface *interface = data;
+
+ if (mnl_attr_get_type(attr) == IFLA_INFO_KIND && !strcmp(WG_GENL_NAME, mnl_attr_get_str(attr)))
+ interface->is_wireguard = true;
+ return MNL_CB_OK;
+}
+
+static int parse_infomsg(const struct nlattr *attr, void *data)
+{
+ struct interface *interface = data;
+
+ if (mnl_attr_get_type(attr) == IFLA_LINKINFO)
+ return mnl_attr_parse_nested(attr, parse_linkinfo, data);
+ else if (mnl_attr_get_type(attr) == IFLA_IFNAME)
+ interface->name = mnl_attr_get_str(attr);
+ return MNL_CB_OK;
+}
+
+static int read_devices_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct string_list *list = data;
+ struct interface interface = { 0 };
+ int ret;
+
+ ret = mnl_attr_parse(nlh, sizeof(struct ifinfomsg), parse_infomsg, &interface);
+ if (ret != MNL_CB_OK)
+ return ret;
+ if (interface.name && interface.is_wireguard)
+ ret = string_list_add(list, interface.name);
+ if (ret < 0)
+ return ret;
+ if (nlh->nlmsg_type != NLMSG_DONE)
+ return MNL_CB_OK + 1;
+ return MNL_CB_OK;
+}
+
+static int fetch_device_names(struct string_list *list)
+{
+ struct mnl_socket *nl = NULL;
+ char *rtnl_buffer = NULL;
+ size_t message_len;
+ unsigned int portid, seq;
+ ssize_t len;
+ int ret = 0;
+ struct nlmsghdr *nlh;
+ struct ifinfomsg *ifm;
+
+ ret = -ENOMEM;
+ rtnl_buffer = calloc(mnl_ideal_socket_buffer_size(), 1);
+ if (!rtnl_buffer)
+ goto cleanup;
+
+ nl = mnl_socket_open(NETLINK_ROUTE);
+ if (!nl) {
+ ret = -errno;
+ goto cleanup;
+ }
+
+ if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
+ ret = -errno;
+ goto cleanup;
+ }
+
+ seq = time(NULL);
+ portid = mnl_socket_get_portid(nl);
+ nlh = mnl_nlmsg_put_header(rtnl_buffer);
+ nlh->nlmsg_type = RTM_GETLINK;
+ nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP;
+ nlh->nlmsg_seq = seq;
+ ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
+ ifm->ifi_family = AF_UNSPEC;
+ message_len = nlh->nlmsg_len;
+
+ if (mnl_socket_sendto(nl, rtnl_buffer, message_len) < 0) {
+ ret = -errno;
+ goto cleanup;
+ }
+
+another:
+ if ((len = mnl_socket_recvfrom(nl, rtnl_buffer, mnl_ideal_socket_buffer_size())) < 0) {
+ ret = -errno;
+ goto cleanup;
+ }
+ if ((len = mnl_cb_run(rtnl_buffer, len, seq, portid, read_devices_cb, list)) < 0) {
+ /* Netlink returns NLM_F_DUMP_INTR if the set of all tunnels changed
+ * during the dump. That's unfortunate, but is pretty common on busy
+ * systems that are adding and removing tunnels all the time. Rather
+ * than retrying, potentially indefinitely, we just work with the
+ * partial results. */
+ if (errno != EINTR) {
+ ret = -errno;
+ goto cleanup;
+ }
+ }
+ if (len == MNL_CB_OK + 1)
+ goto another;
+ ret = 0;
+
+cleanup:
+ free(rtnl_buffer);
+ if (nl)
+ mnl_socket_close(nl);
+ return ret;
+}
+
+static int add_del_iface(const char *ifname, bool add)
+{
+ struct mnl_socket *nl = NULL;
+ char *rtnl_buffer;
+ ssize_t len;
+ int ret;
+ struct nlmsghdr *nlh;
+ struct ifinfomsg *ifm;
+ struct nlattr *nest;
+
+ rtnl_buffer = calloc(mnl_ideal_socket_buffer_size(), 1);
+ if (!rtnl_buffer) {
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ nl = mnl_socket_open(NETLINK_ROUTE);
+ if (!nl) {
+ ret = -errno;
+ goto cleanup;
+ }
+
+ if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
+ ret = -errno;
+ goto cleanup;
+ }
+
+ nlh = mnl_nlmsg_put_header(rtnl_buffer);
+ nlh->nlmsg_type = add ? RTM_NEWLINK : RTM_DELLINK;
+ nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (add ? NLM_F_CREATE | NLM_F_EXCL : 0);
+ nlh->nlmsg_seq = time(NULL);
+ ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
+ ifm->ifi_family = AF_UNSPEC;
+ mnl_attr_put_strz(nlh, IFLA_IFNAME, ifname);
+ nest = mnl_attr_nest_start(nlh, IFLA_LINKINFO);
+ mnl_attr_put_strz(nlh, IFLA_INFO_KIND, WG_GENL_NAME);
+ mnl_attr_nest_end(nlh, nest);
+
+ if (mnl_socket_sendto(nl, rtnl_buffer, nlh->nlmsg_len) < 0) {
+ ret = -errno;
+ goto cleanup;
+ }
+ if ((len = mnl_socket_recvfrom(nl, rtnl_buffer, mnl_ideal_socket_buffer_size())) < 0) {
+ ret = -errno;
+ goto cleanup;
+ }
+ if (mnl_cb_run(rtnl_buffer, len, nlh->nlmsg_seq, mnl_socket_get_portid(nl), NULL, NULL) < 0) {
+ ret = -errno;
+ goto cleanup;
+ }
+ ret = 0;
+
+cleanup:
+ free(rtnl_buffer);
+ if (nl)
+ mnl_socket_close(nl);
+ return ret;
+}
+
+int wg_set_device(wg_device *dev)
+{
+ int ret = 0;
+ wg_peer *peer = NULL;
+ wg_allowedip *allowedip = NULL;
+ struct nlattr *peers_nest, *peer_nest, *allowedips_nest, *allowedip_nest;
+ struct nlmsghdr *nlh;
+ struct mnlg_socket *nlg;
+
+ nlg = mnlg_socket_open(WG_GENL_NAME, WG_GENL_VERSION);
+ if (!nlg)
+ return -errno;
+
+again:
+ nlh = mnlg_msg_prepare(nlg, WG_CMD_SET_DEVICE, NLM_F_REQUEST | NLM_F_ACK);
+ mnl_attr_put_strz(nlh, WGDEVICE_A_IFNAME, dev->name);
+
+ if (!peer) {
+ uint32_t flags = 0;
+
+ if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
+ mnl_attr_put(nlh, WGDEVICE_A_PRIVATE_KEY, sizeof(dev->private_key), dev->private_key);
+ if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
+ mnl_attr_put_u16(nlh, WGDEVICE_A_LISTEN_PORT, dev->listen_port);
+ if (dev->flags & WGDEVICE_HAS_FWMARK)
+ mnl_attr_put_u32(nlh, WGDEVICE_A_FWMARK, dev->fwmark);
+ if (dev->flags & WGDEVICE_REPLACE_PEERS)
+ flags |= WGDEVICE_F_REPLACE_PEERS;
+ if (flags)
+ mnl_attr_put_u32(nlh, WGDEVICE_A_FLAGS, flags);
+ }
+ if (!dev->first_peer)
+ goto send;
+ peers_nest = peer_nest = allowedips_nest = allowedip_nest = NULL;
+ peers_nest = mnl_attr_nest_start(nlh, WGDEVICE_A_PEERS);
+ for (peer = peer ? peer : dev->first_peer; peer; peer = peer->next_peer) {
+ uint32_t flags = 0;
+
+ peer_nest = mnl_attr_nest_start_check(nlh, mnl_ideal_socket_buffer_size(), 0);
+ if (!peer_nest)
+ goto toobig_peers;
+ if (!mnl_attr_put_check(nlh, mnl_ideal_socket_buffer_size(), WGPEER_A_PUBLIC_KEY, sizeof(peer->public_key), peer->public_key))
+ goto toobig_peers;
+ if (peer->flags & WGPEER_REMOVE_ME)
+ flags |= WGPEER_F_REMOVE_ME;
+ if (!allowedip) {
+ if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
+ flags |= WGPEER_F_REPLACE_ALLOWEDIPS;
+ if (peer->flags & WGPEER_HAS_PRESHARED_KEY) {
+ if (!mnl_attr_put_check(nlh, mnl_ideal_socket_buffer_size(), WGPEER_A_PRESHARED_KEY, sizeof(peer->preshared_key), peer->preshared_key))
+ goto toobig_peers;
+ }
+ if (peer->endpoint.addr.sa_family == AF_INET) {
+ if (!mnl_attr_put_check(nlh, mnl_ideal_socket_buffer_size(), WGPEER_A_ENDPOINT, sizeof(peer->endpoint.addr4), &peer->endpoint.addr4))
+ goto toobig_peers;
+ } else if (peer->endpoint.addr.sa_family == AF_INET6) {
+ if (!mnl_attr_put_check(nlh, mnl_ideal_socket_buffer_size(), WGPEER_A_ENDPOINT, sizeof(peer->endpoint.addr6), &peer->endpoint.addr6))
+ goto toobig_peers;
+ }
+ if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) {
+ if (!mnl_attr_put_u16_check(nlh, mnl_ideal_socket_buffer_size(), WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, peer->persistent_keepalive_interval))
+ goto toobig_peers;
+ }
+ }
+ if (flags) {
+ if (!mnl_attr_put_u32_check(nlh, mnl_ideal_socket_buffer_size(), WGPEER_A_FLAGS, flags))
+ goto toobig_peers;
+ }
+ if (peer->first_allowedip) {
+ if (!allowedip)
+ allowedip = peer->first_allowedip;
+ allowedips_nest = mnl_attr_nest_start_check(nlh, mnl_ideal_socket_buffer_size(), WGPEER_A_ALLOWEDIPS);
+ if (!allowedips_nest)
+ goto toobig_allowedips;
+ for (; allowedip; allowedip = allowedip->next_allowedip) {
+ allowedip_nest = mnl_attr_nest_start_check(nlh, mnl_ideal_socket_buffer_size(), 0);
+ if (!allowedip_nest)
+ goto toobig_allowedips;
+ if (!mnl_attr_put_u16_check(nlh, mnl_ideal_socket_buffer_size(), WGALLOWEDIP_A_FAMILY, allowedip->family))
+ goto toobig_allowedips;
+ if (allowedip->family == AF_INET) {
+ if (!mnl_attr_put_check(nlh, mnl_ideal_socket_buffer_size(), WGALLOWEDIP_A_IPADDR, sizeof(allowedip->ip4), &allowedip->ip4))
+ goto toobig_allowedips;
+ } else if (allowedip->family == AF_INET6) {
+ if (!mnl_attr_put_check(nlh, mnl_ideal_socket_buffer_size(), WGALLOWEDIP_A_IPADDR, sizeof(allowedip->ip6), &allowedip->ip6))
+ goto toobig_allowedips;
+ }
+ if (!mnl_attr_put_u8_check(nlh, mnl_ideal_socket_buffer_size(), WGALLOWEDIP_A_CIDR_MASK, allowedip->cidr))
+ goto toobig_allowedips;
+ mnl_attr_nest_end(nlh, allowedip_nest);
+ allowedip_nest = NULL;
+ }
+ mnl_attr_nest_end(nlh, allowedips_nest);
+ allowedips_nest = NULL;
+ }
+
+ mnl_attr_nest_end(nlh, peer_nest);
+ peer_nest = NULL;
+ }
+ mnl_attr_nest_end(nlh, peers_nest);
+ peers_nest = NULL;
+ goto send;
+toobig_allowedips:
+ if (allowedip_nest)
+ mnl_attr_nest_cancel(nlh, allowedip_nest);
+ if (allowedips_nest)
+ mnl_attr_nest_end(nlh, allowedips_nest);
+ mnl_attr_nest_end(nlh, peer_nest);
+ mnl_attr_nest_end(nlh, peers_nest);
+ goto send;
+toobig_peers:
+ if (peer_nest)
+ mnl_attr_nest_cancel(nlh, peer_nest);
+ mnl_attr_nest_end(nlh, peers_nest);
+ goto send;
+send:
+ if (mnlg_socket_send(nlg, nlh) < 0) {
+ ret = -errno;
+ goto out;
+ }
+ errno = 0;
+ if (mnlg_socket_recv_run(nlg, NULL, NULL) < 0) {
+ ret = errno ? -errno : -EINVAL;
+ goto out;
+ }
+ if (peer)
+ goto again;
+
+out:
+ mnlg_socket_close(nlg);
+ errno = -ret;
+ return ret;
+}
+
+static int parse_allowedip(const struct nlattr *attr, void *data)
+{
+ wg_allowedip *allowedip = data;
+
+ switch (mnl_attr_get_type(attr)) {
+ case WGALLOWEDIP_A_UNSPEC:
+ break;
+ case WGALLOWEDIP_A_FAMILY:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U16))
+ allowedip->family = mnl_attr_get_u16(attr);
+ break;
+ case WGALLOWEDIP_A_IPADDR:
+ if (mnl_attr_get_payload_len(attr) == sizeof(allowedip->ip4))
+ memcpy(&allowedip->ip4, mnl_attr_get_payload(attr), sizeof(allowedip->ip4));
+ else if (mnl_attr_get_payload_len(attr) == sizeof(allowedip->ip6))
+ memcpy(&allowedip->ip6, mnl_attr_get_payload(attr), sizeof(allowedip->ip6));
+ break;
+ case WGALLOWEDIP_A_CIDR_MASK:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U8))
+ allowedip->cidr = mnl_attr_get_u8(attr);
+ break;
+ }
+
+ return MNL_CB_OK;
+}
+
+static int parse_allowedips(const struct nlattr *attr, void *data)
+{
+ wg_peer *peer = data;
+ wg_allowedip *new_allowedip = calloc(1, sizeof(wg_allowedip));
+ int ret;
+
+ if (!new_allowedip)
+ return MNL_CB_ERROR;
+ if (!peer->first_allowedip)
+ peer->first_allowedip = peer->last_allowedip = new_allowedip;
+ else {
+ peer->last_allowedip->next_allowedip = new_allowedip;
+ peer->last_allowedip = new_allowedip;
+ }
+ ret = mnl_attr_parse_nested(attr, parse_allowedip, new_allowedip);
+ if (!ret)
+ return ret;
+ if (!((new_allowedip->family == AF_INET && new_allowedip->cidr <= 32) || (new_allowedip->family == AF_INET6 && new_allowedip->cidr <= 128))) {
+ errno = EAFNOSUPPORT;
+ return MNL_CB_ERROR;
+ }
+ return MNL_CB_OK;
+}
+
+bool wg_key_is_zero(const wg_key key)
+{
+ volatile uint8_t acc = 0;
+ unsigned int i;
+
+ for (i = 0; i < sizeof(wg_key); ++i) {
+ acc |= key[i];
+ __asm__ ("" : "=r" (acc) : "0" (acc));
+ }
+ return 1 & ((acc - 1) >> 8);
+}
+
+static int parse_peer(const struct nlattr *attr, void *data)
+{
+ wg_peer *peer = data;
+
+ switch (mnl_attr_get_type(attr)) {
+ case WGPEER_A_UNSPEC:
+ break;
+ case WGPEER_A_PUBLIC_KEY:
+ if (mnl_attr_get_payload_len(attr) == sizeof(peer->public_key)) {
+ memcpy(peer->public_key, mnl_attr_get_payload(attr), sizeof(peer->public_key));
+ peer->flags |= WGPEER_HAS_PUBLIC_KEY;
+ }
+ break;
+ case WGPEER_A_PRESHARED_KEY:
+ if (mnl_attr_get_payload_len(attr) == sizeof(peer->preshared_key)) {
+ memcpy(peer->preshared_key, mnl_attr_get_payload(attr), sizeof(peer->preshared_key));
+ if (!wg_key_is_zero(peer->preshared_key))
+ peer->flags |= WGPEER_HAS_PRESHARED_KEY;
+ }
+ break;
+ case WGPEER_A_ENDPOINT: {
+ struct sockaddr *addr;
+
+ if (mnl_attr_get_payload_len(attr) < sizeof(*addr))
+ break;
+ addr = mnl_attr_get_payload(attr);
+ if (addr->sa_family == AF_INET && mnl_attr_get_payload_len(attr) == sizeof(peer->endpoint.addr4))
+ memcpy(&peer->endpoint.addr4, addr, sizeof(peer->endpoint.addr4));
+ else if (addr->sa_family == AF_INET6 && mnl_attr_get_payload_len(attr) == sizeof(peer->endpoint.addr6))
+ memcpy(&peer->endpoint.addr6, addr, sizeof(peer->endpoint.addr6));
+ break;
+ }
+ case WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U16))
+ peer->persistent_keepalive_interval = mnl_attr_get_u16(attr);
+ break;
+ case WGPEER_A_LAST_HANDSHAKE_TIME:
+ if (mnl_attr_get_payload_len(attr) == sizeof(peer->last_handshake_time))
+ memcpy(&peer->last_handshake_time, mnl_attr_get_payload(attr), sizeof(peer->last_handshake_time));
+ break;
+ case WGPEER_A_RX_BYTES:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U64))
+ peer->rx_bytes = mnl_attr_get_u64(attr);
+ break;
+ case WGPEER_A_TX_BYTES:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U64))
+ peer->tx_bytes = mnl_attr_get_u64(attr);
+ break;
+ case WGPEER_A_ALLOWEDIPS:
+ return mnl_attr_parse_nested(attr, parse_allowedips, peer);
+ }
+
+ return MNL_CB_OK;
+}
+
+static int parse_peers(const struct nlattr *attr, void *data)
+{
+ wg_device *device = data;
+ wg_peer *new_peer = calloc(1, sizeof(wg_peer));
+ int ret;
+
+ if (!new_peer)
+ return MNL_CB_ERROR;
+ if (!device->first_peer)
+ device->first_peer = device->last_peer = new_peer;
+ else {
+ device->last_peer->next_peer = new_peer;
+ device->last_peer = new_peer;
+ }
+ ret = mnl_attr_parse_nested(attr, parse_peer, new_peer);
+ if (!ret)
+ return ret;
+ if (!(new_peer->flags & WGPEER_HAS_PUBLIC_KEY)) {
+ errno = ENXIO;
+ return MNL_CB_ERROR;
+ }
+ return MNL_CB_OK;
+}
+
+static int parse_device(const struct nlattr *attr, void *data)
+{
+ wg_device *device = data;
+
+ switch (mnl_attr_get_type(attr)) {
+ case WGDEVICE_A_UNSPEC:
+ break;
+ case WGDEVICE_A_IFINDEX:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U32))
+ device->ifindex = mnl_attr_get_u32(attr);
+ break;
+ case WGDEVICE_A_IFNAME:
+ if (!mnl_attr_validate(attr, MNL_TYPE_STRING)) {
+ strncpy(device->name, mnl_attr_get_str(attr), sizeof(device->name) - 1);
+ device->name[sizeof(device->name) - 1] = '\0';
+ }
+ break;
+ case WGDEVICE_A_PRIVATE_KEY:
+ if (mnl_attr_get_payload_len(attr) == sizeof(device->private_key)) {
+ memcpy(device->private_key, mnl_attr_get_payload(attr), sizeof(device->private_key));
+ device->flags |= WGDEVICE_HAS_PRIVATE_KEY;
+ }
+ break;
+ case WGDEVICE_A_PUBLIC_KEY:
+ if (mnl_attr_get_payload_len(attr) == sizeof(device->public_key)) {
+ memcpy(device->public_key, mnl_attr_get_payload(attr), sizeof(device->public_key));
+ device->flags |= WGDEVICE_HAS_PUBLIC_KEY;
+ }
+ break;
+ case WGDEVICE_A_LISTEN_PORT:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U16))
+ device->listen_port = mnl_attr_get_u16(attr);
+ break;
+ case WGDEVICE_A_FWMARK:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U32))
+ device->fwmark = mnl_attr_get_u32(attr);
+ break;
+ case WGDEVICE_A_PEERS:
+ return mnl_attr_parse_nested(attr, parse_peers, device);
+ }
+
+ return MNL_CB_OK;
+}
+
+static int read_device_cb(const struct nlmsghdr *nlh, void *data)
+{
+ return mnl_attr_parse(nlh, sizeof(struct genlmsghdr), parse_device, data);
+}
+
+static void coalesce_peers(wg_device *device)
+{
+ wg_peer *old_next_peer, *peer = device->first_peer;
+
+ while (peer && peer->next_peer) {
+ if (memcmp(peer->public_key, peer->next_peer->public_key, sizeof(wg_key))) {
+ peer = peer->next_peer;
+ continue;
+ }
+ if (!peer->first_allowedip) {
+ peer->first_allowedip = peer->next_peer->first_allowedip;
+ peer->last_allowedip = peer->next_peer->last_allowedip;
+ } else {
+ peer->last_allowedip->next_allowedip = peer->next_peer->first_allowedip;
+ peer->last_allowedip = peer->next_peer->last_allowedip;
+ }
+ old_next_peer = peer->next_peer;
+ peer->next_peer = old_next_peer->next_peer;
+ free(old_next_peer);
+ }
+}
+
+int wg_get_device(wg_device **device, const char *device_name)
+{
+ int ret = 0;
+ struct nlmsghdr *nlh;
+ struct mnlg_socket *nlg;
+
+try_again:
+ *device = calloc(1, sizeof(wg_device));
+ if (!*device)
+ return -errno;
+
+ nlg = mnlg_socket_open(WG_GENL_NAME, WG_GENL_VERSION);
+ if (!nlg) {
+ wg_free_device(*device);
+ *device = NULL;
+ return -errno;
+ }
+
+ nlh = mnlg_msg_prepare(nlg, WG_CMD_GET_DEVICE, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
+ mnl_attr_put_strz(nlh, WGDEVICE_A_IFNAME, device_name);
+ if (mnlg_socket_send(nlg, nlh) < 0) {
+ ret = -errno;
+ goto out;
+ }
+ errno = 0;
+ if (mnlg_socket_recv_run(nlg, read_device_cb, *device) < 0) {
+ ret = errno ? -errno : -EINVAL;
+ goto out;
+ }
+ coalesce_peers(*device);
+
+out:
+ if (nlg)
+ mnlg_socket_close(nlg);
+ if (ret) {
+ wg_free_device(*device);
+ if (ret == -EINTR)
+ goto try_again;
+ *device = NULL;
+ }
+ errno = -ret;
+ return ret;
+}
+
+/* first\0second\0third\0forth\0last\0\0 */
+char *wg_list_device_names(void)
+{
+ struct string_list list = { 0 };
+ int ret = fetch_device_names(&list);
+
+ errno = -ret;
+ if (errno) {
+ free(list.buffer);
+ return NULL;
+ }
+ return list.buffer ?: strdup("\0");
+}
+
+int wg_add_device(const char *device_name)
+{
+ return add_del_iface(device_name, true);
+}
+
+int wg_del_device(const char *device_name)
+{
+ return add_del_iface(device_name, false);
+}
+
+void wg_free_device(wg_device *dev)
+{
+ wg_peer *peer, *np;
+ wg_allowedip *allowedip, *na;
+
+ if (!dev)
+ return;
+ for (peer = dev->first_peer, np = peer ? peer->next_peer : NULL; peer; peer = np, np = peer ? peer->next_peer : NULL) {
+ for (allowedip = peer->first_allowedip, na = allowedip ? allowedip->next_allowedip : NULL; allowedip; allowedip = na, na = allowedip ? allowedip->next_allowedip : NULL)
+ free(allowedip);
+ free(peer);
+ }
+ free(dev);
+}
+
+static void encode_base64(char dest[static 4], const uint8_t src[static 3])
+{
+ const uint8_t input[] = { (src[0] >> 2) & 63, ((src[0] << 4) | (src[1] >> 4)) & 63, ((src[1] << 2) | (src[2] >> 6)) & 63, src[2] & 63 };
+ unsigned int i;
+
+ for (i = 0; i < 4; ++i)
+ dest[i] = input[i] + 'A'
+ + (((25 - input[i]) >> 8) & 6)
+ - (((51 - input[i]) >> 8) & 75)
+ - (((61 - input[i]) >> 8) & 15)
+ + (((62 - input[i]) >> 8) & 3);
+
+}
+
+void wg_key_to_base64(wg_key_b64_string base64, const wg_key key)
+{
+ unsigned int i;
+
+ for (i = 0; i < 32 / 3; ++i)
+ encode_base64(&base64[i * 4], &key[i * 3]);
+ encode_base64(&base64[i * 4], (const uint8_t[]){ key[i * 3 + 0], key[i * 3 + 1], 0 });
+ base64[sizeof(wg_key_b64_string) - 2] = '=';
+ base64[sizeof(wg_key_b64_string) - 1] = '\0';
+}
+
+static int decode_base64(const char src[static 4])
+{
+ int val = 0;
+ unsigned int i;
+
+ for (i = 0; i < 4; ++i)
+ val |= (-1
+ + ((((('A' - 1) - src[i]) & (src[i] - ('Z' + 1))) >> 8) & (src[i] - 64))
+ + ((((('a' - 1) - src[i]) & (src[i] - ('z' + 1))) >> 8) & (src[i] - 70))
+ + ((((('0' - 1) - src[i]) & (src[i] - ('9' + 1))) >> 8) & (src[i] + 5))
+ + ((((('+' - 1) - src[i]) & (src[i] - ('+' + 1))) >> 8) & 63)
+ + ((((('/' - 1) - src[i]) & (src[i] - ('/' + 1))) >> 8) & 64)
+ ) << (18 - 6 * i);
+ return val;
+}
+
+int wg_key_from_base64(wg_key key, const wg_key_b64_string base64)
+{
+ unsigned int i;
+ int val;
+ volatile uint8_t ret = 0;
+
+ if (strlen(base64) != sizeof(wg_key_b64_string) - 1 || base64[sizeof(wg_key_b64_string) - 2] != '=') {
+ errno = EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < 32 / 3; ++i) {
+ val = decode_base64(&base64[i * 4]);
+ ret |= (uint32_t)val >> 31;
+ key[i * 3 + 0] = (val >> 16) & 0xff;
+ key[i * 3 + 1] = (val >> 8) & 0xff;
+ key[i * 3 + 2] = val & 0xff;
+ }
+ val = decode_base64((const char[]){ base64[i * 4 + 0], base64[i * 4 + 1], base64[i * 4 + 2], 'A' });
+ ret |= ((uint32_t)val >> 31) | (val & 0xff);
+ key[i * 3 + 0] = (val >> 16) & 0xff;
+ key[i * 3 + 1] = (val >> 8) & 0xff;
+ errno = EINVAL & ~((ret - 1) >> 8);
+out:
+ return -errno;
+}
+
+typedef int64_t fe[16];
+
+static __attribute__((noinline)) void memzero_explicit(void *s, size_t count)
+{
+ memset(s, 0, count);
+ __asm__ __volatile__("": :"r"(s) :"memory");
+}
+
+static void carry(fe o)
+{
+ int i;
+
+ for (i = 0; i < 16; ++i) {
+ o[(i + 1) % 16] += (i == 15 ? 38 : 1) * (o[i] >> 16);
+ o[i] &= 0xffff;
+ }
+}
+
+static void cswap(fe p, fe q, int b)
+{
+ int i;
+ int64_t t, c = ~(b - 1);
+
+ for (i = 0; i < 16; ++i) {
+ t = c & (p[i] ^ q[i]);
+ p[i] ^= t;
+ q[i] ^= t;
+ }
+
+ memzero_explicit(&t, sizeof(t));
+ memzero_explicit(&c, sizeof(c));
+ memzero_explicit(&b, sizeof(b));
+}
+
+static void pack(uint8_t *o, const fe n)
+{
+ int i, j, b;
+ fe m, t;
+
+ memcpy(t, n, sizeof(t));
+ carry(t);
+ carry(t);
+ carry(t);
+ for (j = 0; j < 2; ++j) {
+ m[0] = t[0] - 0xffed;
+ for (i = 1; i < 15; ++i) {
+ m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
+ m[i - 1] &= 0xffff;
+ }
+ m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
+ b = (m[15] >> 16) & 1;
+ m[14] &= 0xffff;
+ cswap(t, m, 1 - b);
+ }
+ for (i = 0; i < 16; ++i) {
+ o[2 * i] = t[i] & 0xff;
+ o[2 * i + 1] = t[i] >> 8;
+ }
+
+ memzero_explicit(m, sizeof(m));
+ memzero_explicit(t, sizeof(t));
+ memzero_explicit(&b, sizeof(b));
+}
+
+static void add(fe o, const fe a, const fe b)
+{
+ int i;
+
+ for (i = 0; i < 16; ++i)
+ o[i] = a[i] + b[i];
+}
+
+static void subtract(fe o, const fe a, const fe b)
+{
+ int i;
+
+ for (i = 0; i < 16; ++i)
+ o[i] = a[i] - b[i];
+}
+
+static void multmod(fe o, const fe a, const fe b)
+{
+ int i, j;
+ int64_t t[31] = { 0 };
+
+ for (i = 0; i < 16; ++i) {
+ for (j = 0; j < 16; ++j)
+ t[i + j] += a[i] * b[j];
+ }
+ for (i = 0; i < 15; ++i)
+ t[i] += 38 * t[i + 16];
+ memcpy(o, t, sizeof(fe));
+ carry(o);
+ carry(o);
+
+ memzero_explicit(t, sizeof(t));
+}
+
+static void invert(fe o, const fe i)
+{
+ fe c;
+ int a;
+
+ memcpy(c, i, sizeof(c));
+ for (a = 253; a >= 0; --a) {
+ multmod(c, c, c);
+ if (a != 2 && a != 4)
+ multmod(c, c, i);
+ }
+ memcpy(o, c, sizeof(fe));
+
+ memzero_explicit(c, sizeof(c));
+}
+
+static void clamp_key(uint8_t *z)
+{
+ z[31] = (z[31] & 127) | 64;
+ z[0] &= 248;
+}
+
+void wg_generate_public_key(wg_key public_key, const wg_key private_key)
+{
+ int i, r;
+ uint8_t z[32];
+ fe a = { 1 }, b = { 9 }, c = { 0 }, d = { 1 }, e, f;
+
+ memcpy(z, private_key, sizeof(z));
+ clamp_key(z);
+
+ for (i = 254; i >= 0; --i) {
+ r = (z[i >> 3] >> (i & 7)) & 1;
+ cswap(a, b, r);
+ cswap(c, d, r);
+ add(e, a, c);
+ subtract(a, a, c);
+ add(c, b, d);
+ subtract(b, b, d);
+ multmod(d, e, e);
+ multmod(f, a, a);
+ multmod(a, c, a);
+ multmod(c, b, e);
+ add(e, a, c);
+ subtract(a, a, c);
+ multmod(b, a, a);
+ subtract(c, d, f);
+ multmod(a, c, (const fe){ 0xdb41, 1 });
+ add(a, a, d);
+ multmod(c, c, a);
+ multmod(a, d, f);
+ multmod(d, b, (const fe){ 9 });
+ multmod(b, e, e);
+ cswap(a, b, r);
+ cswap(c, d, r);
+ }
+ invert(c, c);
+ multmod(a, a, c);
+ pack(public_key, a);
+
+ memzero_explicit(&r, sizeof(r));
+ memzero_explicit(z, sizeof(z));
+ memzero_explicit(a, sizeof(a));
+ memzero_explicit(b, sizeof(b));
+ memzero_explicit(c, sizeof(c));
+ memzero_explicit(d, sizeof(d));
+ memzero_explicit(e, sizeof(e));
+ memzero_explicit(f, sizeof(f));
+}
+
+void wg_generate_private_key(wg_key private_key)
+{
+ wg_generate_preshared_key(private_key);
+ clamp_key(private_key);
+}
+
+void wg_generate_preshared_key(wg_key preshared_key)
+{
+ ssize_t ret;
+ size_t i;
+ int fd;
+#if defined(__OpenBSD__) || (defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12) || (defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)))
+ if (!getentropy(preshared_key, sizeof(wg_key)))
+ return;
+#endif
+#if defined(__NR_getrandom) && defined(__linux__)
+ if (syscall(__NR_getrandom, preshared_key, sizeof(wg_key), 0) == sizeof(wg_key))
+ return;
+#endif
+ fd = open("/dev/urandom", O_RDONLY);
+ assert(fd >= 0);
+ for (i = 0; i < sizeof(wg_key); i += ret) {
+ ret = read(fd, preshared_key + i, sizeof(wg_key) - i);
+ assert(ret > 0);
+ }
+ close(fd);
+}
diff --git a/external/subpack/utils/rpcd-mod-wireguard/src/wireguard.h b/external/subpack/utils/rpcd-mod-wireguard/src/wireguard.h
new file mode 100644
index 0000000..328fcb4
--- /dev/null
+++ b/external/subpack/utils/rpcd-mod-wireguard/src/wireguard.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/*
+ * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ */
+
+#ifndef WIREGUARD_H
+#define WIREGUARD_H
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef uint8_t wg_key[32];
+typedef char wg_key_b64_string[((sizeof(wg_key) + 2) / 3) * 4 + 1];
+
+/* Cross platform __kernel_timespec */
+struct timespec64 {
+ int64_t tv_sec;
+ int64_t tv_nsec;
+};
+
+typedef struct wg_allowedip {
+ uint16_t family;
+ union {
+ struct in_addr ip4;
+ struct in6_addr ip6;
+ };
+ uint8_t cidr;
+ struct wg_allowedip *next_allowedip;
+} wg_allowedip;
+
+enum wg_peer_flags {
+ WGPEER_REMOVE_ME = 1U << 0,
+ WGPEER_REPLACE_ALLOWEDIPS = 1U << 1,
+ WGPEER_HAS_PUBLIC_KEY = 1U << 2,
+ WGPEER_HAS_PRESHARED_KEY = 1U << 3,
+ WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL = 1U << 4
+};
+
+typedef union wg_endpoint {
+ struct sockaddr addr;
+ struct sockaddr_in addr4;
+ struct sockaddr_in6 addr6;
+} wg_endpoint;
+
+typedef struct wg_peer {
+ enum wg_peer_flags flags;
+
+ wg_key public_key;
+ wg_key preshared_key;
+
+ wg_endpoint endpoint;
+
+ struct timespec64 last_handshake_time;
+ uint64_t rx_bytes, tx_bytes;
+ uint16_t persistent_keepalive_interval;
+
+ struct wg_allowedip *first_allowedip, *last_allowedip;
+ struct wg_peer *next_peer;
+} wg_peer;
+
+enum wg_device_flags {
+ WGDEVICE_REPLACE_PEERS = 1U << 0,
+ WGDEVICE_HAS_PRIVATE_KEY = 1U << 1,
+ WGDEVICE_HAS_PUBLIC_KEY = 1U << 2,
+ WGDEVICE_HAS_LISTEN_PORT = 1U << 3,
+ WGDEVICE_HAS_FWMARK = 1U << 4
+};
+
+typedef struct wg_device {
+ char name[IFNAMSIZ];
+ uint32_t ifindex;
+
+ enum wg_device_flags flags;
+
+ wg_key public_key;
+ wg_key private_key;
+
+ uint32_t fwmark;
+ uint16_t listen_port;
+
+ struct wg_peer *first_peer, *last_peer;
+} wg_device;
+
+#define wg_for_each_device_name(__names, __name, __len) for ((__name) = (__names), (__len) = 0; ((__len) = strlen(__name)); (__name) += (__len) + 1)
+#define wg_for_each_peer(__dev, __peer) for ((__peer) = (__dev)->first_peer; (__peer); (__peer) = (__peer)->next_peer)
+#define wg_for_each_allowedip(__peer, __allowedip) for ((__allowedip) = (__peer)->first_allowedip; (__allowedip); (__allowedip) = (__allowedip)->next_allowedip)
+
+int wg_set_device(wg_device *dev);
+int wg_get_device(wg_device **dev, const char *device_name);
+int wg_add_device(const char *device_name);
+int wg_del_device(const char *device_name);
+void wg_free_device(wg_device *dev);
+char *wg_list_device_names(void); /* first\0second\0third\0forth\0last\0\0 */
+void wg_key_to_base64(wg_key_b64_string base64, const wg_key key);
+int wg_key_from_base64(wg_key key, const wg_key_b64_string base64);
+bool wg_key_is_zero(const wg_key key);
+void wg_generate_public_key(wg_key public_key, const wg_key private_key);
+void wg_generate_private_key(wg_key private_key);
+void wg_generate_preshared_key(wg_key preshared_key);
+
+#endif
diff --git a/external/subpack/utils/rrdtool1/Makefile b/external/subpack/utils/rrdtool1/Makefile
new file mode 100644
index 0000000..a031c17
--- /dev/null
+++ b/external/subpack/utils/rrdtool1/Makefile
@@ -0,0 +1,135 @@
+#
+# Copyright (C) 2006-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=rrdtool1
+PKG_VERSION:=1.0.50
+PKG_RELEASE:=3
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/rrdtool-$(PKG_VERSION)
+PKG_SOURCE:=rrdtool-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:= \
+ http://oss.oetiker.ch/rrdtool/pub/rrdtool-1.0.x \
+ http://www.fastmirrors.org/rrdtool/rrdtool-1.0.x \
+ ftp://ftp.sunet.se/pub/network/monitoring/rrdtool/rrdtool-1.0.x
+PKG_HASH:=42aa7c213dedbd95d33ca84d92f4187880f7e96062c6a3fb05bfb16f77ba2a91
+PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+
+PKG_FIXUP:=autoreconf
+PKG_CHECK_FORMAT_SECURITY:=0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/rrdtool1/Default
+ TITLE:=Round Robin Database (RRD)
+ URL:=http://oss.oetiker.ch/rrdtool/
+endef
+
+define Package/rrdtool1/description/Default
+ RRD is the Acronym for Round Robin Database. RRD is a system to store and
+ display time-series data (i.e. network bandwidth, machine-room temperature,
+ server load average). It stores the data in a very compact way that will
+ not expand over time, and it presents useful graphs by processing the data
+ to enforce a certain data density. It can be used either via simple wrapper
+ scripts (from shell or Perl) or via frontends that poll network devices and
+ put friendly user interface on it.
+
+ This is version 1.0.x with cgilib-0.4, gd1.3 and libpng-1.0.9 linked into
+ librrd.so. The library is much smaller compared to the 1.2.x version with
+ separate dynamic linked libraries.
+endef
+
+define Package/librrd1
+$(call Package/rrdtool1/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ DEPENDS:=+zlib
+ TITLE+= management library
+endef
+
+define Package/librrd1/description
+$(call Package/rrdtool1/description/Default)
+ This package contains a shared library, used by other programs.
+endef
+
+define Package/rrdcgi1
+$(call Package/rrdtool1/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Database
+ DEPENDS:=+librrd1
+ TITLE+= CGI graphing tool
+endef
+
+define Package/rrdcgi1/description
+$(call Package/rrdtool1/description/Default)
+ This package contains the rrdcgi tool used to create web pages containing
+ RRD graphs based on templates.
+endef
+
+define Package/rrdtool1
+$(call Package/rrdtool1/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Database
+ DEPENDS:=+librrd1
+ TITLE+= management tools
+endef
+
+define Package/rrdtool1/description
+$(call Package/rrdtool1/description/Default)
+ This package contains command line tools used to manage RRDs.
+endef
+
+TARGET_CFLAGS += $(FPIC) --std=c99
+
+CONFIGURE_ARGS += \
+ $(DISABLE_NLS) \
+ --enable-shared=yes \
+ --enable-static=yes \
+ --disable-rpath \
+ --with-gnu-ld \
+ --enable-local-zlib
+
+CONFIGURE_VARS += \
+ ac_cv_path_PERL=no \
+ rd_cv_ieee_works=yes \
+ shrext_cmds=".so"
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ shrext_cmds=".so" \
+ all install
+endef
+
+define Package/rrdtool1/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/rrd{tool,update} $(1)/usr/bin/
+endef
+
+define Package/rrdcgi1/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/rrdcgi $(1)/usr/bin/
+endef
+
+define Package/librrd1/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/librrd.so.* $(1)/usr/lib/
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/lib/rrdtool-1.0/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/rrd.h $(1)/usr/lib/rrdtool-1.0/include/
+ $(INSTALL_DIR) $(1)/usr/lib/rrdtool-1.0/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/librrd.{a,so*} $(1)/usr/lib/rrdtool-1.0/lib/
+endef
+
+$(eval $(call BuildPackage,librrd1))
+$(eval $(call BuildPackage,rrdcgi1))
+$(eval $(call BuildPackage,rrdtool1))
diff --git a/external/subpack/utils/rrdtool1/patches/001-no_ordering_cd_joke.patch b/external/subpack/utils/rrdtool1/patches/001-no_ordering_cd_joke.patch
new file mode 100644
index 0000000..073c310
--- /dev/null
+++ b/external/subpack/utils/rrdtool1/patches/001-no_ordering_cd_joke.patch
@@ -0,0 +1,20 @@
+--- a/configure
++++ b/configure
+@@ -24873,17 +24873,12 @@ echo "$as_me:$LINENO: result: and out ag
+ echo "${ECHO_T}and out again" >&6
+
+ echo $ECHO_N "ordering CD from http://people.ee.ethz.ch/~oetiker/wish $ac_c" 1>&6
+-sleep 1
+ echo $ECHO_N ".$ac_c" 1>&6
+-sleep 2
+ echo $ECHO_N ".$ac_c" 1>&6
+-sleep 1
+ echo $ECHO_N ".$ac_c" 1>&6
+-sleep 3
+ echo $ECHO_N ".$ac_c" 1>&6
+ echo $ECHO_N ".$ac_c" 1>&6
+ echo $ECHO_N ".$ac_c" 1>&6
+-sleep 2
+ echo "$as_me:$LINENO: result: just kidding ;-)" >&5
+ echo "${ECHO_T} just kidding ;-)" >&6
+ echo
diff --git a/external/subpack/utils/rrdtool1/patches/002-no_timezone.patch b/external/subpack/utils/rrdtool1/patches/002-no_timezone.patch
new file mode 100644
index 0000000..67bc9b1
--- /dev/null
+++ b/external/subpack/utils/rrdtool1/patches/002-no_timezone.patch
@@ -0,0 +1,24 @@
+--- a/src/rrd_tool.c
++++ b/src/rrd_tool.c
+@@ -225,11 +225,8 @@ int main(int argc, char *argv[])
+ struct rusage myusage;
+ struct timeval starttime;
+ struct timeval currenttime;
+- struct timezone tz;
+
+- tz.tz_minuteswest =0;
+- tz.tz_dsttime=0;
+- gettimeofday(&starttime,&tz);
++ gettimeofday(&starttime,NULL);
+ #endif
+
+ while (fgets(aLine, sizeof(aLine)-1, stdin)){
+@@ -252,7 +249,7 @@ int main(int argc, char *argv[])
+
+ #if HAVE_GETRUSAGE
+ getrusage(RUSAGE_SELF,&myusage);
+- gettimeofday(¤ttime,&tz);
++ gettimeofday(¤ttime,NULL);
+ printf("OK u:%1.2f s:%1.2f r:%1.2f\n",
+ (double)myusage.ru_utime.tv_sec+
+ (double)myusage.ru_utime.tv_usec/1000000.0,
diff --git a/external/subpack/utils/rrdtool1/patches/020-x86-float-cast.patch b/external/subpack/utils/rrdtool1/patches/020-x86-float-cast.patch
new file mode 100644
index 0000000..1de2234
--- /dev/null
+++ b/external/subpack/utils/rrdtool1/patches/020-x86-float-cast.patch
@@ -0,0 +1,11 @@
+--- a/src/rrd_format.h
++++ b/src/rrd_format.h
+@@ -20,7 +20,7 @@
+
+ #define RRD_COOKIE "RRD"
+ #define RRD_VERSION "0001"
+-#define FLOAT_COOKIE 8.642135E130
++#define FLOAT_COOKIE ((double)8.642135E130)
+
+ #if defined(WIN32)
+ #define DNAN ((double)fmod(0.0,0.0))
diff --git a/external/subpack/utils/rrdtool1/patches/030-pod2man-stderr.patch b/external/subpack/utils/rrdtool1/patches/030-pod2man-stderr.patch
new file mode 100644
index 0000000..38deac7
--- /dev/null
+++ b/external/subpack/utils/rrdtool1/patches/030-pod2man-stderr.patch
@@ -0,0 +1,11 @@
+--- a/doc/Makefile.am
++++ b/doc/Makefile.am
+@@ -35,7 +35,7 @@ iman_DATA = $(MAN)
+ all-local: link txt man html
+
+ .pod.1 .pm.1 .pl.1:
+- pod2man --release=$(VERSION) --center=RRDtool $< > $@
++ pod2man --stderr --release=$(VERSION) --center=RRDtool $< > $@
+
+ .1.txt:
+ @NROFF@ -man -Tlp $< > $@ || echo @NROFF@ failed > $@
diff --git a/external/subpack/utils/rrdtool1/patches/040-no-e-notation-on-log-display.patch b/external/subpack/utils/rrdtool1/patches/040-no-e-notation-on-log-display.patch
new file mode 100644
index 0000000..4555167
--- /dev/null
+++ b/external/subpack/utils/rrdtool1/patches/040-no-e-notation-on-log-display.patch
@@ -0,0 +1,27 @@
+--- a/src/rrd_graph.c
++++ b/src/rrd_graph.c
+@@ -2049,7 +2049,7 @@ horizontal_log_grid(gdImagePtr gif, imag
+ char graph_label[100];
+ gdPoint polyPoints[4];
+ int styleMinor[2],styleMajor[2];
+- double value, pixperstep, minstep;
++ double value, pixperstep, minstep, yval;
+
+ /* find grid spaceing */
+ pixpex= (double)im->ysize / (log10(im->maxval) - log10(im->minval));
+@@ -2118,7 +2118,14 @@ horizontal_log_grid(gdImagePtr gif, imag
+
+ gdImageLine(gif, polyPoints[0].x,polyPoints[0].y,
+ polyPoints[1].x,polyPoints[0].y,gdStyled);
+- sprintf(graph_label,"%3.0e",value * yloglab[majoridx][i]);
++ yval = value * yloglab[majoridx][i];
++ if (yval >= 100000) {
++ sprintf(graph_label,"%3.0e", yval);
++ } else {
++ if (yval == 1) /* prints as 1e+00 */
++ yval = 0;
++ sprintf(graph_label,"%5.0f", yval);
++ }
+ gdImageString(gif, SmallFont,
+ (polyPoints[0].x - (strlen(graph_label) *
+ SmallFont->w)-7),
diff --git a/external/subpack/utils/rtklib/Makefile b/external/subpack/utils/rtklib/Makefile
new file mode 100644
index 0000000..5719852
--- /dev/null
+++ b/external/subpack/utils/rtklib/Makefile
@@ -0,0 +1,97 @@
+#
+# Copyright (C) 2014-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=rtklib
+PKG_VERSION:=2.4.3_b32
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/tomojitakasu/RTKLIB
+PKG_SOURCE_VERSION:=6e5ddadb737c54d4a43c43feeeb4e244c51b4286
+PKG_MIRROR_HASH:=b6ada49b6667a98e935055e718bf9a5712030cddc1694d1be7c0ab0e98bdc7b8
+
+PKG_MAINTAINER:=Nuno Goncalves <nunojpg@gmail.com>
+PKG_LICENSE:=BSD-2-Clause
+
+PKG_BUILD_PARALLEL:=0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/rtklib/default
+ SUBMENU:=RTKLIB Suite
+ SECTION:=utils
+ CATEGORY:=Utilities
+ URL:=http://www.rtklib.com/
+ DEPENDS:=+libpthread +librt
+endef
+
+define Package/convbin
+$(call Package/rtklib/default)
+ TITLE:=RINEX Converter
+endef
+
+define Package/pos2kml
+$(call Package/rtklib/default)
+ TITLE:=Solution to KML converter
+endef
+
+define Package/rnx2rtkp
+$(call Package/rtklib/default)
+ TITLE:=Post-Processing Analysis
+endef
+
+define Package/rtkrcv
+$(call Package/rtklib/default)
+ TITLE:=Real-Time Positioning
+endef
+
+define Package/str2str
+$(call Package/rtklib/default)
+ TITLE:=Communication Server
+endef
+
+define Build/Compile
+ rm -rf $(PKG_INSTALL_DIR)
+ mkdir -p $(PKG_INSTALL_DIR)
+ $(MAKE) -C $(PKG_BUILD_DIR)/app/convbin/gcc CC="$(TARGET_CC) $(TARGET_CFLAGS)"
+ $(MAKE) -C $(PKG_BUILD_DIR)/app/pos2kml/gcc CC="$(TARGET_CC) $(TARGET_CFLAGS)"
+ $(MAKE) -C $(PKG_BUILD_DIR)/app/rnx2rtkp/gcc CC="$(TARGET_CC) $(TARGET_CFLAGS)"
+ $(MAKE) -C $(PKG_BUILD_DIR)/app/rtkrcv/gcc CC="$(TARGET_CC) $(TARGET_CFLAGS)"
+ $(MAKE) -C $(PKG_BUILD_DIR)/app/str2str/gcc CC="$(TARGET_CC) $(TARGET_CFLAGS)"
+endef
+
+define Package/convbin/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/app/convbin/gcc/convbin $(1)/usr/bin/
+endef
+
+define Package/pos2kml/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/app/pos2kml/gcc/pos2kml $(1)/usr/bin/
+endef
+
+define Package/rnx2rtkp/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/app/rnx2rtkp/gcc/rnx2rtkp $(1)/usr/bin/
+endef
+
+define Package/rtkrcv/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/app/rtkrcv/gcc/rtkrcv $(1)/usr/bin/
+endef
+
+define Package/str2str/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/app/str2str/gcc/str2str $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,convbin))
+$(eval $(call BuildPackage,pos2kml))
+$(eval $(call BuildPackage,rnx2rtkp))
+$(eval $(call BuildPackage,rtkrcv))
+$(eval $(call BuildPackage,str2str))
diff --git a/external/subpack/utils/rtklib/patches/010-musl.patch b/external/subpack/utils/rtklib/patches/010-musl.patch
new file mode 100644
index 0000000..14a405f
--- /dev/null
+++ b/external/subpack/utils/rtklib/patches/010-musl.patch
@@ -0,0 +1,12 @@
+--- a/src/stream.c
++++ b/src/stream.c
+@@ -81,6 +81,9 @@
+ #include <netinet/in.h>
+ #include <netinet/tcp.h>
+ #include <arpa/inet.h>
++#ifndef _POSIX_SOURCE
++#define _POSIX_SOURCE
++#endif
+ #include <netdb.h>
+ #endif
+
diff --git a/external/subpack/utils/rtklib/patches/020-no-gfortran.patch b/external/subpack/utils/rtklib/patches/020-no-gfortran.patch
new file mode 100644
index 0000000..3bbd2fb
--- /dev/null
+++ b/external/subpack/utils/rtklib/patches/020-no-gfortran.patch
@@ -0,0 +1,21 @@
+--- a/app/rnx2rtkp/gcc/makefile
++++ b/app/rnx2rtkp/gcc/makefile
+@@ -2,14 +2,14 @@
+ BINDIR = /usr/local/bin
+ SRC = ../../../src
+
+-#OPTS = -DTRACE -DENAGLO -DENAQZS -DENAGAL -DENACMP -DENAIRN -DNFREQ=3
+-OPTS = -DTRACE -DENAGLO -DENAQZS -DENAGAL -DENACMP -DENAIRN -DNFREQ=3 -DIERS_MODEL
++OPTS = -DTRACE -DENAGLO -DENAQZS -DENAGAL -DENACMP -DENAIRN -DNFREQ=3
++#OPTS = -DTRACE -DENAGLO -DENAQZS -DENAGAL -DENACMP -DENAIRN -DNFREQ=3 -DIERS_MODEL
+ #OPTS = -DENAGLO -DENAQZS -DENAGAL -DENACMP -DNFREQ=2
+
+ # for no lapack
+ CFLAGS = -Wall -O3 -ansi -pedantic -Wno-unused-but-set-variable -I$(SRC) $(OPTS) -g
+-#LDLIBS = -lm -lrt
+-LDLIBS = ../../../lib/iers/gcc/iers.a -lgfortran -lm -lrt
++LDLIBS = -lm -lrt
++#LDLIBS = ../../../lib/iers/gcc/iers.a -lgfortran -lm -lrt
+
+ #CFLAGS = -Wall -O3 -ansi -pedantic -Wno-unused-but-set-variable -I$(SRC) -DLAPACK $(OPTS)
+ #LDLIBS = -lm -lrt -llapack -lblas
diff --git a/external/subpack/utils/rtl-ais/Makefile b/external/subpack/utils/rtl-ais/Makefile
new file mode 100644
index 0000000..3f234fc
--- /dev/null
+++ b/external/subpack/utils/rtl-ais/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=rtl-ais
+PKG_VERSION:=0.3
+PKG_RELEASE:=4
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/dgiardini/rtl-ais/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=01e2b675226ec403c409cec8b55999008f5c7aa9e82d6c0ba085ef13b200ceb1
+
+PKG_MAINTAINER:=Nuno Goncalves <nunojpg@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/rtl-ais
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=rtl-sdr AIS dual channel tuner
+ DEPENDS:=+libpthread +librtlsdr
+ URL:=https://github.com/dgiardini/rtl-ais
+endef
+
+define Package/rtl-ais/description
+ rtl_ais uses a rtl2832u dvb-t dongle to tune AIS (Automatic Identification
+ System) used on ships and by vessel traffic services
+endef
+
+define Package/rtl-ais/conffiles
+/etc/config/rtl_ais
+endef
+
+TARGET_CFLAGS += -std=gnu89
+
+define Package/rtl-ais/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/rtl_ais $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/rtl_ais.init $(1)/etc/init.d/rtl_ais
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/uci_rtl_ais $(1)/etc/config/rtl_ais
+endef
+
+$(eval $(call BuildPackage,rtl-ais))
diff --git a/external/subpack/utils/rtl-ais/files/rtl_ais.init b/external/subpack/utils/rtl-ais/files/rtl_ais.init
new file mode 100644
index 0000000..efcd99e
--- /dev/null
+++ b/external/subpack/utils/rtl-ais/files/rtl_ais.init
@@ -0,0 +1,37 @@
+#!/bin/sh /etc/rc.common
+
+START=99
+USE_PROCD=1
+
+PROG=/usr/bin/rtl_ais
+
+validate_rtl_ais_section() {
+ uci_load_validate "rtl_ais" "rtl_ais" "$1" "$2" \
+ 'enabled:bool' \
+ 'ppm:range(-100,100):0'
+}
+
+load_rtl_ais() {
+ local cfg="$1"
+
+ [ "$2" = 0 ] || { echo "validation failed"; return 1; }
+
+ [ "$enabled" = "1" ] || return 1
+
+ procd_open_instance
+ procd_set_param command "$PROG" -p "$ppm"
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_set_param respawn
+ procd_close_instance
+}
+
+start_service() {
+ config_load "rtl_ais"
+ config_foreach validate_rtl_ais_section "rtl_ais" load_rtl_ais
+}
+
+service_triggers() {
+ procd_add_reload_trigger "rtl_ais"
+ procd_add_validation validate_rtl_ais_section
+}
diff --git a/external/subpack/utils/rtl-ais/files/uci_rtl_ais b/external/subpack/utils/rtl-ais/files/uci_rtl_ais
new file mode 100644
index 0000000..1b5f1ec
--- /dev/null
+++ b/external/subpack/utils/rtl-ais/files/uci_rtl_ais
@@ -0,0 +1,3 @@
+config rtl_ais
+ option enabled 0
+ option ppm 0
diff --git a/external/subpack/utils/rtl-ais/patches/010-musl.patch b/external/subpack/utils/rtl-ais/patches/010-musl.patch
new file mode 100644
index 0000000..c2f0781
--- /dev/null
+++ b/external/subpack/utils/rtl-ais/patches/010-musl.patch
@@ -0,0 +1,10 @@
+--- a/tcp_listener/tcp_listener.c
++++ b/tcp_listener/tcp_listener.c
+@@ -6,6 +6,7 @@
+ #include <string.h>
+ #include <stdio.h>
+ #include <stdlib.h>
++#include <unistd.h>
+ #include <errno.h>
+ #include <stdio.h>
+ #include <pthread.h>
diff --git a/external/subpack/utils/rtl-sdr/Makefile b/external/subpack/utils/rtl-sdr/Makefile
new file mode 100644
index 0000000..1bd0ed0
--- /dev/null
+++ b/external/subpack/utils/rtl-sdr/Makefile
@@ -0,0 +1,96 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=rtl-sdr
+PKG_VERSION:=0.6.0
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://git.osmocom.org/rtl-sdr/snapshot
+PKG_HASH:=ee10a76fe0c6601102367d4cdf5c26271e9442d0491aa8df27e5a9bf639cff7c
+
+PKG_BUILD_PARALLEL:=1
+CMAKE_INSTALL:=1
+
+PKG_LICENSE:=GPLv2
+PKG_LICENSE_FILES:=COPYING
+
+PKG_MAINTAINER:=Vasilis Tsiligiannis <b_tsiligiannis@silverton.gr>
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/rtl-sdr/Default
+ TITLE:=Software Defined Radio with Realtek RTL2832U
+ URL:=http://sdr.osmocom.org/trac/wiki/rtl-sdr
+endef
+
+define Package/rtl-sdr/Default/description
+ rtl-sdr allows DVB-T dongles based on the Realtek RTL2832U to be used as
+ an inexpensive SDR.
+endef
+
+define Package/rtl-sdr
+ $(call Package/rtl-sdr/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+librt +libpthread +librtlsdr
+endef
+
+define Package/rtl-sdr/description
+ $(call Package/rtl-sdr/Default/description)
+
+ This package contains the utilities and daemons.
+endef
+
+define Package/librtlsdr
+ $(call Package/rtl-sdr/Default)
+ TITLE+= shared library
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+= library
+ DEPENDS:=+libusb-1.0
+endef
+
+define Package/librtlsdr/description
+ $(call Package/rtl-sdr/Default/description)
+
+ This package contains the librtlsdr shared library.
+endef
+
+TARGET_CFLAGS += $(FPIC)
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/*.h $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/librtlsdr.so* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/librtlsdr.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/rtl-sdr/conffiles
+/etc/config/rtl_tcp
+endef
+
+define Package/rtl-sdr/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/rtl_* $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) files/rtl_tcp.init $(1)/etc/init.d/rtl_tcp
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) files/rtl_tcp.config $(1)/etc/config/rtl_tcp
+endef
+
+define Package/librtlsdr/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/librtlsdr.so* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,rtl-sdr))
+$(eval $(call BuildPackage,librtlsdr))
diff --git a/external/subpack/utils/rtl-sdr/files/rtl_tcp.config b/external/subpack/utils/rtl-sdr/files/rtl_tcp.config
new file mode 100644
index 0000000..95998aa
--- /dev/null
+++ b/external/subpack/utils/rtl-sdr/files/rtl_tcp.config
@@ -0,0 +1,12 @@
+config rtl_tcp main
+ option disabled '1'
+ option respawn '1'
+ option device_index ''
+ option address '0.0.0.0'
+ option port ''
+ option frequency ''
+ option gain ''
+ option samplerate ''
+ option buffers '8'
+ option num_linked_lists '8'
+ option ppm_error ''
diff --git a/external/subpack/utils/rtl-sdr/files/rtl_tcp.init b/external/subpack/utils/rtl-sdr/files/rtl_tcp.init
new file mode 100755
index 0000000..4204787
--- /dev/null
+++ b/external/subpack/utils/rtl-sdr/files/rtl_tcp.init
@@ -0,0 +1,64 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2016 OpenWrt.org
+
+START=90
+STOP=10
+USE_PROCD=1
+
+append_arg() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get val "$cfg" "$var"
+ [ -n "$val" -o -n "$def" ] && procd_append_param command $opt "${val:-$def}"
+}
+
+append_bool() {
+ local cfg="$1"
+ local var="$2"
+ local opt="$3"
+ local def="$4"
+ local val
+
+ config_get_bool val "$cfg" "$var" "$def"
+ [ "$val" = 1 ] && procd_append_param command "$opt"
+}
+
+
+start_instance() {
+ local cfg="$1"
+ local aux
+
+ config_get_bool aux "$cfg" 'disabled' '0'
+ [ "$aux" = 1 ] && return 1
+
+ procd_open_instance
+
+ procd_set_param command /usr/bin/rtl_tcp
+ append_arg "$cfg" device_index "-d"
+ append_arg "$cfg" address "-a"
+ append_arg "$cfg" port "-p"
+ append_arg "$cfg" frequency "-f"
+ append_arg "$cfg" gain "-g"
+ append_arg "$cfg" samplerate "-s"
+ append_arg "$cfg" buffers "-b"
+ append_arg "$cfg" num_linked_lists "-n"
+ append_arg "$cfg" ppm_error "-P"
+
+ config_get_bool aux "$cfg" 'respawn' '0'
+ [ "$aux" = 1 ] && procd_set_param respawn
+
+ procd_close_instance
+}
+
+service_triggers() {
+ procd_add_reload_trigger "rtl_tcp"
+}
+
+start_service() {
+ config_load rtl_tcp
+ config_foreach start_instance rtl_tcp
+}
diff --git a/external/subpack/utils/rtl_433/Makefile b/external/subpack/utils/rtl_433/Makefile
new file mode 100644
index 0000000..410ed16
--- /dev/null
+++ b/external/subpack/utils/rtl_433/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=rtl_433
+PKG_VERSION:=20.11
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/merbanan/rtl_433/tar.gz/$(PKG_VERSION)?
+PKG_HASH:=12a5cb7a733ba352467522c704d5b685aa6137582dc18aaa444d4891c29ee839
+
+PKG_MAINTAINER:=Jasper Scholte <NightNL@outlook.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/rtl_433
+ TITLE:=Realtek RTL2832 based 433.92MHz generic data receiver
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+librtlsdr +rtl-sdr +libtool-bin
+ URL:=https://github.com/merbanan/rtl_433
+endef
+
+define Package/rtl-sdr/description
+ rtl_433 turns your Realtek RTL2832 based DVB dongle into a 433.92MHz generic data receiver.
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/rtl_433.h $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/rtl_433_devices.h $(1)/usr/include
+endef
+
+define Package/rtl_433/install
+ $(INSTALL_DIR) $(1)/etc/rtl_433
+ $(CP) $(PKG_INSTALL_DIR)/usr/etc/rtl_433/*.conf $(1)/etc/rtl_433
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/rtl_433 $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,rtl_433))
diff --git a/external/subpack/utils/rtty/Makefile b/external/subpack/utils/rtty/Makefile
new file mode 100644
index 0000000..f9d3a59
--- /dev/null
+++ b/external/subpack/utils/rtty/Makefile
@@ -0,0 +1,71 @@
+#
+# Copyright (C) 2018 Jianhui Zhao
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=rtty
+PKG_VERSION:=7.3.2
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL=https://github.com/zhaojh329/rtty/releases/download/v$(PKG_VERSION)
+PKG_HASH:=4c60eacd7a653988a1907284de2ecf360c74f55ef9e21c40b9ebd87af6570908
+CMAKE_INSTALL:=1
+
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_MAINTAINER:=Jianhui Zhao <zhaojh329@gmail.com>
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/rtty/Default
+ TITLE:=Access your terminals from anywhere via the web
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Terminal
+ URL:=https://github.com/zhaojh329/rtty
+ DEPENDS:=+libev $(2)
+ VARIANT:=$(1)
+ PROVIDES:=rtty
+endef
+
+Package/rtty-openssl=$(call Package/rtty/Default,openssl,+PACKAGE_rtty-openssl:libopenssl)
+Package/rtty-wolfssl=$(call Package/rtty/Default,wolfssl,+PACKAGE_rtty-wolfssl:libwolfssl)
+Package/rtty-mbedtls=$(call Package/rtty/Default,mbedtls,+PACKAGE_rtty-mbedtls:libmbedtls +PACKAGE_rtty-mbedtls:zlib)
+Package/rtty-nossl=$(call Package/rtty/Default,nossl)
+
+define Package/rtty-openssl/conffiles
+/etc/config/rtty
+endef
+
+Package/rtty-wolfssl/conffiles = $(Package/rtty-openssl/conffiles)
+Package/rtty-mbedtls/conffiles = $(Package/rtty-openssl/conffiles)
+Package/rtty-nossl/conffiles = $(Package/rtty-openssl/conffiles)
+
+ifeq ($(BUILD_VARIANT),openssl)
+ CMAKE_OPTIONS += -DRTTY_USE_OPENSSL=ON
+else ifeq ($(BUILD_VARIANT),wolfssl)
+ CMAKE_OPTIONS += -DRTTY_USE_WOLFSSL=ON
+else ifeq ($(BUILD_VARIANT),mbedtls)
+ CMAKE_OPTIONS += -DRTTY_USE_MBEDTLS=ON
+else
+ CMAKE_OPTIONS += -DRTTY_SSL_SUPPORT=OFF
+endif
+
+define Package/rtty-$(BUILD_VARIANT)/install
+ $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d $(1)/etc/config
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/rtty $(1)/usr/sbin
+ $(INSTALL_BIN) ./files/rtty.init $(1)/etc/init.d/rtty
+ $(INSTALL_CONF) ./files/rtty.config $(1)/etc/config/rtty
+endef
+
+$(eval $(call BuildPackage,rtty-openssl))
+$(eval $(call BuildPackage,rtty-wolfssl))
+$(eval $(call BuildPackage,rtty-mbedtls))
+$(eval $(call BuildPackage,rtty-nossl))
diff --git a/external/subpack/utils/rtty/files/rtty.config b/external/subpack/utils/rtty/files/rtty.config
new file mode 100644
index 0000000..b9952ce
--- /dev/null
+++ b/external/subpack/utils/rtty/files/rtty.config
@@ -0,0 +1,14 @@
+# You must specify an interface or id,
+# If the id is not specified, RTTY will uses the MAC address
+# of the interface you specify as its ID, otherwise the id
+# you specify is used as its ID
+
+#config rtty
+# option interface 'lan'
+# option id 'My-Device'
+# option description 'Description of my device'
+# option host 'your-server-host' # Server host
+# option port '5912' # Server Port
+# option ssl 1 # Whether to use ssl
+# option token 'your-token' # generated by rttys
+# option verbose '1' # verbose log
diff --git a/external/subpack/utils/rtty/files/rtty.init b/external/subpack/utils/rtty/files/rtty.init
new file mode 100644
index 0000000..94b4c36
--- /dev/null
+++ b/external/subpack/utils/rtty/files/rtty.init
@@ -0,0 +1,65 @@
+#!/bin/sh /etc/rc.common
+
+USE_PROCD=1
+START=99
+
+BIN=/usr/sbin/rtty
+
+validate_rtty_section() {
+ uci_load_validate rtty rtty "$1" "$2" \
+ 'interface:uci("network", "@interface"):lan' \
+ 'id:maxlength(63)' \
+ 'description:maxlength(126)' \
+ 'host:host' \
+ 'port:port' \
+ 'ssl:bool:0' \
+ 'token:maxlength(32)' \
+ 'verbose:bool:0'
+}
+
+start_rtty() {
+ . /lib/functions/network.sh
+
+ local ifname
+
+ [ "$2" = 0 ] || {
+ echo "validation failed" >&2
+ return 1
+ }
+
+ [ -n "$interface" ] && network_get_device ifname "$interface"
+
+ [ -z "$ifname" -a -z "$id" ] && {
+ echo "You must specify an interface or ID" >&2
+ return 1
+ }
+
+ [ -z "$host" ] && {
+ echo "host required" >&2
+ return 1
+ }
+
+ [ -z "$id" ] && {
+ id=$(sed 's/://g' /sys/class/net/$ifname/address | tr 'a-z' 'A-Z')
+ }
+
+ procd_open_instance
+ procd_set_param command $BIN -h $host -I "$id" -a
+ [ -n "$port" ] && procd_append_param command -p "$port"
+ [ -n "$description" ] && procd_append_param command -d "$description"
+ [ "$ssl" = "1" ] && procd_append_param command -s
+ [ -n "$token" ] && procd_append_param command -t "$token"
+ [ "$verbose" = "1" ] && procd_append_param command -v
+ procd_set_param respawn
+ procd_close_instance
+}
+
+start_service() {
+ config_load rtty
+ config_foreach validate_rtty_section rtty start_rtty
+}
+
+service_triggers() {
+ procd_add_reload_trigger "rtty"
+ procd_add_validation validate_rtty_section
+}
diff --git a/external/subpack/utils/runc/Makefile b/external/subpack/utils/runc/Makefile
new file mode 100644
index 0000000..ab37366
--- /dev/null
+++ b/external/subpack/utils/runc/Makefile
@@ -0,0 +1,63 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=runc
+PKG_VERSION:=1.1.2
+PKG_RELEASE:=1
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/opencontainers/runc/tar.gz/v${PKG_VERSION}?
+PKG_HASH:=0ccce82b1d9c058d8fd7443d261c96fd7a803f2775bcb1fec2bdb725bc7640f6
+
+PKG_MAINTAINER:=Gerard Ryan <G.M0N3Y.2503@gmail.com>
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/opencontainers/runc
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/runc
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=runc container runtime
+ URL:=https://www.opencontainers.org/
+ DEPENDS:=$(GO_ARCH_DEPENDS) +KERNEL_SECCOMP_FILTER:libseccomp
+endef
+
+define Package/runc/description
+runc is a CLI tool for spawning and running containers according to the OCI specification.
+endef
+
+GO_PKG_INSTALL_ALL:=1
+MAKE_PATH:=$(GO_PKG_WORK_DIR_NAME)/build/src/$(GO_PKG)
+MAKE_VARS += $(GO_PKG_VARS)
+MAKE_FLAGS += COMMIT=$(PKG_SOURCE_VERSION)
+
+ifeq ($(ARCH),mips)
+MAKE_FLAGS += EXTRA_FLAGS='-buildmode=default'
+endif
+
+BUILDTAGS:=
+ifeq ($(CONFIG_KERNEL_SECCOMP_FILTER),y)
+BUILDTAGS += seccomp
+endif
+ifeq ($(CONFIG_SELINUX),y)
+BUILDTAGS += selinux
+endif
+MAKE_FLAGS += BUILDTAGS='$(BUILDTAGS)'
+
+# Reset golang-package.mk overrides so we can use the Makefile
+Build/Compile=$(call Build/Compile/Default)
+
+define Package/runc/install
+ $(INSTALL_DIR) $(1)/usr/sbin/
+ $(INSTALL_BIN) $(GO_PKG_BUILD_DIR)/src/$(GO_PKG)/runc $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,runc))
diff --git a/external/subpack/utils/sane-backends/Makefile b/external/subpack/utils/sane-backends/Makefile
new file mode 100644
index 0000000..82acefc
--- /dev/null
+++ b/external/subpack/utils/sane-backends/Makefile
@@ -0,0 +1,395 @@
+#
+# Copyright (C) 2006-2016 OpenWrt.org
+# Copyright (C) 2017-2020 Luiz Angelo Daros de Luca <luizluca@gmail.com>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=sane-backends
+PKG_VERSION:=1.0.32
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://gitlab.com/sane-project/backends/uploads/104f09c07d35519cc8e72e604f11643f
+PKG_HASH:=3a28c237c0a72767086202379f6dc92dbb63ec08dfbab22312cba80e238bb114
+
+PKG_MAINTAINER:=Luiz Angelo Daros de Luca <luizluca@gmail.com>
+PKG_LICENSE:=GPL-2.0 GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING LICENSE
+PKG_CPE_ID:=cpe:/a:sane-backends_project:sane-backends
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+SANE_BACKENDS:=
+
+define Package/sane-backends/Default
+ TITLE:=Scanner Access Now Easy
+ URL:=http://www.sane-project.org/
+endef
+
+define Package/sane-backends/Default/description
+ SANE (Scanner Access Now Easy) is a universal scanner interface.
+endef
+
+define Package/sane-backends
+$(call Package/sane-backends/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE+= (drivers)
+ DEPENDS:=+ALL:sane-backends-all
+endef
+
+define Package/sane-backends/description
+$(call Package/sane-backends/Default/description)
+.
+This
+endef
+
+define Package/sane-backends/config
+ menu "Select SANE backends"
+ depends on PACKAGE_sane-backends
+
+
+ config PACKAGE_sane-backends-all
+ depends on PACKAGE_sane-backends
+ tristate "Include all SANE backends (sane-backends-all)"
+
+ comment "Backends"
+
+$(foreach backend,$(SANE_BACKENDS), \
+ $(eval \
+ $(call Package/Default)
+ $(call Package/sane-$(backend))
+ )\
+ config PACKAGE_sane-$(backend)
+ tristate "$(TITLE)"
+ $(foreach config_dep,\
+ $(filter @%,
+ $(foreach v, $(DEPENDS), $(if $(findstring :,$v),,$v))
+ ),\
+ depends on $(strip $(subst @,,$(config_dep)))
+ )
+)
+ endmenu
+
+endef
+
+# returns conditional dependency on sane backend
+# 1: backend name
+#
+# If there is no config deps on $(1), returns +sane-$(1).
+# Otherwise, +(CONFIG1&&CONFIG2&&..):sane-$(1)
+define SaneBackendDependency
+ $(eval \
+ $(call Package/Default)
+ $(call Package/sane-$(1))
+ FILTER_CONFIG:=$$(strip \
+ $$(foreach config_dep, \
+ $$(filter @%, \
+ $$(foreach v, \
+ $$(DEPENDS), \
+ $$(if $$(findstring :,$$v),,$$v) \
+ ) \
+ ), \
+ $$(subst @,,$$(config_dep)) \
+ ) \
+ )
+ ifneq (,$$(FILTER_CONFIG))
+ FILTER_CONFIG:=($$(subst $$(space),&&,$$(FILTER_CONFIG))):
+ endif
+ ) \
+ +$(FILTER_CONFIG)sane-$(1)
+endef
+
+define Package/sane-backends-all
+$(call Package/sane-backends/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE+= (all backends)
+ DEPENDS:=$(foreach backend,$(SANE_BACKENDS),$(strip $(call SaneBackendDependency,$(backend))))
+ HIDDEN:=1
+endef
+
+define Package/sane-backends-all/description
+$(call Package/sane-backends/Default/description)
+.
+Metapackage for selecting all SANE Backends
+endef
+
+define Package/sane-daemon
+$(call Package/sane-backends/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libsane
+ TITLE+= (network daemon)
+ USERID:=saned:scanner
+endef
+
+define Package/sane-daemon/description
+$(call Package/sane-backends/Default/description)
+This package contains the SANE daemon.
+endef
+
+# Run hotplug to grant access to existing scanners
+define Package/sane-daemon/postinst
+#!/bin/sh
+# We only need udevtrigger to have the magic work without
+# rebooting on a real system. In ImageBuilder or
+# the like, the boot process will call udevtrigger.
+if [ -z "$${IPKG_INSTROOT}" ]; then
+ udevtrigger
+fi
+endef
+
+define Package/libsane
+ $(call Package/sane-backends/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ DEPENDS+=+libusb-1.0
+ TITLE+= (libraries)
+endef
+
+define Package/libsane/description
+$(call Package/sane-backends/Default/description)
+This package contains the SANE shared libraries.
+endef
+
+define Package/sane-frontends
+ $(call Package/sane-backends/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libsane +libjpeg +libpng
+ TITLE+= (frontends)
+endef
+
+define Package/sane-frontends/description
+$(call Package/sane-backends/Default/description)
+This package contains the SANE frontends.
+endef
+
+CONFIGURE_ARGS += \
+ --enable-shared \
+ --enable-static \
+ --disable-preload \
+ --without-snmp \
+ --without-avahi \
+ --disable-locking \
+ --without-usb-record-replay \
+
+# ./configure does not even try to detect mmap if crosscompiling
+CONFIGURE_VARS += \
+ ac_cv_func_mmap_fixed_mapped="yes"
+
+define Build/Configure
+ $(INSTALL_DIR) $(PKG_BUILD_DIR)/backend/.libs
+ $(Build/Configure/Default)
+endef
+
+define Build/Install
+ $(call Build/Install/Default)
+ $(INSTALL_DIR) $(PKG_INSTALL_DIR)/usr/share/sane
+ cd $(PKG_BUILD_DIR)/doc/descriptions && for file in *.desc; do \
+ sed -rn -e '/^:usbid[[:blank:]]+"?0x(....)"?[[:blank:]]+"?0x(....)"?.*/{s//\1 \2/;p}' $$$$file | \
+ sort -u > $(PKG_INSTALL_DIR)/usr/share/sane/$$$${file/\.desc/}.usbid; \
+ awk -v path=$(PKG_INSTALL_DIR)/usr/share/sane -v file=$$$${file/\.desc/}.usbid '{ print $$$$2 > path"/"$$$$1"-"file }' \
+ $(PKG_INSTALL_DIR)/usr/share/sane/$$$${file/\.desc/}.usbid ; \
+ done
+endef
+
+define Package/libsane/install
+ $(INSTALL_DIR) $(1)/usr/lib/sane/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libsane.so.* $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/sane/libsane-dll.so.* $(1)/usr/lib/sane/
+ $(INSTALL_DIR) $(1)/etc/sane.d/dll.d
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/sane.d/dll.conf $(1)/etc/sane.d/
+endef
+
+define Package/libsane/conffiles
+/etc/sane.d/dll.conf
+endef
+
+define Package/sane-daemon/install
+ $(INSTALL_DIR) $(1)/etc/sane.d
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/sane.d/saned.conf $(1)/etc/sane.d/
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) ./files/saned.sbin $(1)/usr/sbin/saned
+ $(INSTALL_DIR) $(1)/usr/lib/sane/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/saned $(1)/usr/lib/sane/saned
+ $(INSTALL_DIR) $(1)/etc/xinetd.d
+ $(INSTALL_DATA) ./files/saned.xinetd $(1)/etc/xinetd.d/sane-port
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/usb/
+ $(INSTALL_BIN) ./files/saned.hotplug $(1)/etc/hotplug.d/usb/20-saned
+endef
+
+define Package/sane-daemon/conffiles
+/etc/sane.d/saned.conf
+/etc/xinetd.d/sane-port
+endef
+
+define Package/sane-frontends/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+endef
+
+define Package/sane-backends-all/install
+ /bin/true
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/sane $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libsane.{a,so*} $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_BUILD_DIR)/tools/sane-backends.pc $(1)/usr/lib/pkgconfig/
+endef
+
+# 1: short name
+# 2: description
+# 3: dependencies on other packages
+define SaneBackend
+ SANE_BACKENDS+= $(1)
+
+ define Package/sane-$(1)
+ $(call Package/sane-backends/Default)
+ TITLE:=SANE backend (sane-$(1)) for $(2)
+ DEPENDS+= +libsane $(3)
+ HIDDEN:=1
+ endef
+
+ define Package/sane-$(1)/description
+ $(call Package/sane-backends/Default/description)
+.
+This package contains the SANE backend for $(2).
+ endef
+
+ define Package/sane-$(1)/install
+ if [ -f "$(PKG_INSTALL_DIR)/etc/sane.d/$(1).conf" ]; then \
+ $(INSTALL_DIR) $$(1)/etc/sane.d ; \
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/sane.d/$(1).conf $$(1)/etc/sane.d/ ; \
+ fi ; \
+ $(INSTALL_DIR) $$(1)/usr/lib/sane ; \
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/sane/libsane-$(1).so.* $$(1)/usr/lib/sane/ ; \
+ if [ -d "$(PKG_INSTALL_DIR)/usr/share/sane/$(1)" ]; then \
+ $(INSTALL_DIR) $$(1)/usr/share/sane/ ; \
+ $(CP) -a $(PKG_INSTALL_DIR)/usr/share/sane/$(1) $$(1)/usr/share/sane/ ; \
+ fi ; \
+ if [ -s "$(PKG_INSTALL_DIR)/usr/share/sane/$(1).usbid" ]; then \
+ $(INSTALL_DIR) $$(1)/usr/share/sane/ ; \
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/sane/????-$(1).usbid $$(1)/usr/share/sane/ ; \
+ fi
+ endef
+
+ define Package/sane-$(1)/conffiles
+/etc/sane.d/$(1).conf
+ endef
+
+ $$(eval $$(call BuildPackage,sane-$(1)))
+endef
+
+$(eval $(call BuildPackage,libsane))
+$(eval $(call BuildPackage,sane-daemon))
+$(eval $(call SaneBackend,abaton,Abaton flatbed scanners))
+$(eval $(call SaneBackend,agfafocus,AGFA Focus flatbed scanners))
+$(eval $(call SaneBackend,apple,Apple flatbed scanners))
+$(eval $(call SaneBackend,artec,Artec flatbed scanners))
+$(eval $(call SaneBackend,artec_eplus48u,Artec E+ 48U and re-badged models,+libusb-1.0))
+$(eval $(call SaneBackend,as6e,Artec AS6E parallel port interface scanner))
+$(eval $(call SaneBackend,avision,Avision and Avision OEM scanners and possibly more flatbed and film scanners,+libusb-1.0))
+$(eval $(call SaneBackend,bh,Bell+Howell Copiscan II series document scanners))
+$(eval $(call SaneBackend,canon,Canon SCSI scanners,+libusb-1.0))
+$(eval $(call SaneBackend,canon630u,the Canon 630u USB flatbed scanner,+libusb-1.0))
+$(eval $(call SaneBackend,canon_dr,Canon DR-series scanners,+libusb-1.0))
+# Depends on libieee1284
+#$(eval $(call SaneBackend,canon_pp,Canon CanoScan Parallel Port flatbed scanners,+libieee1284))
+$(eval $(call SaneBackend,canon_lide70,Canon LiDE 70 USB flatbed scanner,))
+$(eval $(call SaneBackend,cardscan,Corex CardScan usb scanners,+libusb-1.0))
+$(eval $(call SaneBackend,coolscan,Nikon film-scanners,+libusb-1.0))
+$(eval $(call SaneBackend,coolscan2,Nikon Coolscan film scanners,+libusb-1.0))
+$(eval $(call SaneBackend,coolscan3,Nikon Coolscan film scanners,+libusb-1.0))
+$(eval $(call SaneBackend,dc210,Kodak DC210 Digital Camera,+libjpeg))
+$(eval $(call SaneBackend,dc240,Kodak DC240 Digital Camera,+libjpeg))
+$(eval $(call SaneBackend,dc25,Kodak DC20/DC25 Digital Cameras))
+$(eval $(call SaneBackend,dell1600n_net,Dell 1600n,+libtiff +libjpeg))
+$(eval $(call SaneBackend,dmc,Polaroid Digital Microscope Camera))
+$(eval $(call SaneBackend,epjitsu,Epson-based Fujitsu USB scanners,+libusb-1.0))
+$(eval $(call SaneBackend,epson,EPSON scanners,+libusb-1.0))
+$(eval $(call SaneBackend,epsonds,EPSON scanners,+libjpeg +libusb-1.0)) ####
+$(eval $(call SaneBackend,epson2,EPSON scanners,+libusb-1.0))
+#$(eval $(call SaneBackend,escl,AirScan/eSCL devices,+libcurl +libxml2 +libnetsnmp +libavahi))
+$(eval $(call SaneBackend,fujitsu,Fujitsu flatbed and ADF scanners,+libusb-1.0))
+$(eval $(call SaneBackend,genesys,GL646 GL841 GL843 GL847 and GL124 based USB flatbed scanners,+libstdcpp +libusb-1.0 +libtiff))
+$(eval $(call SaneBackend,gphoto2,digital cameras supported by gphoto2,+libjpeg +libgphoto2))
+$(eval $(call SaneBackend,gt68xx,GT-68XX based USB flatbed scanners,+libusb-1.0))
+$(eval $(call SaneBackend,hp,HP ScanJet scanners,+libusb-1.0))
+$(eval $(call SaneBackend,hp3500,Hewlett-Packard ScanJet 3500 series scanners,+libusb-1.0))
+$(eval $(call SaneBackend,hp3900,RTS8822 chipset based scanners,+libtiff +libusb-1.0))
+$(eval $(call SaneBackend,hp4200,Hewlett-Packard 4200 scanners,+libusb-1.0))
+$(eval $(call SaneBackend,hp5400,Hewlett-Packard 54XX scanners,+libusb-1.0))
+$(eval $(call SaneBackend,hp5590,Hewlett-Packard 4500C/4570C/5500C/5550C/5590/7650 Workgroup/Document scanners,+libusb-1.0))
+$(eval $(call SaneBackend,hpljm1005,Hewlett-Packard LaserJet M1005 MFP Scanner,+libusb-1.0))
+# Depends on libieee1284
+#$(eval $(call SaneBackend,hpsj5s,HP ScanJet 5S sheet-fed scanner,+libieee1284))
+$(eval $(call SaneBackend,hs2p,Ricoh SCSI flatbed/ADF scanners))
+$(eval $(call SaneBackend,ibm,IBM and Ricoh SCSI flatbed scanners))
+$(eval $(call SaneBackend,kodak,big Kodak flatbed and ADF scanners,+libusb-1.0))
+$(eval $(call SaneBackend,kodakaio,Kodak aio printer / scanners,+libusb-1.0))
+$(eval $(call SaneBackend,kvs1025,Panasonic KV-S102xC USB ADF scanners,+libusb-1.0))
+$(eval $(call SaneBackend,kvs20xx,Panasonic KV-S20xxC USB/SCSI ADF scanners,+libusb-1.0))
+$(eval $(call SaneBackend,kvs40xx,Panasonic KV-S40xxC USB/SCSI ADF scanners,+libpthread +libusb-1.0))
+$(eval $(call SaneBackend,leo,LEO Technologies scanners))
+$(eval $(call SaneBackend,lexmark,Lexmark X1100/X1200 Series scanners,+libusb-1.0))
+$(eval $(call SaneBackend,ma1509,Mustek BearPaw 1200F USB scanner,+libusb-1.0))
+$(eval $(call SaneBackend,magicolor,KONICA MINOLTA magicolor scanners,+libusb-1.0))
+$(eval $(call SaneBackend,matsushita,Panasonic KV-SS high speed scanners))
+$(eval $(call SaneBackend,microtek,Microtek scanners))
+$(eval $(call SaneBackend,microtek2,Microtek scanners with SCSI-2 command set))
+$(eval $(call SaneBackend,mustek,Mustek SCSI flatbed scanners and some other devices))
+# Depends on libieee1284
+#$(eval $(call SaneBackend,mustek_pp,Mustek parallel port flatbed scanners,+libieee1284))
+$(eval $(call SaneBackend,mustek_usb,Mustek USB flatbed scanners,+libusb-1.0))
+$(eval $(call SaneBackend,mustek_usb2,SQ113 based USB flatbed scanners,+libpthread +libusb-1.0))
+$(eval $(call SaneBackend,nec,NEC scanners))
+$(eval $(call SaneBackend,net,network backend))
+$(eval $(call SaneBackend,niash,scanners based on the NIASH chipset,+libusb-1.0))
+$(eval $(call SaneBackend,p5,the Primax PagePartner))
+$(eval $(call SaneBackend,pie,PIE Devcom and AdLib SCSI flatbed scanners))
+$(eval $(call SaneBackend,pieusb,PIE Devcom and AdLib SCSI flatbed scanners,+libusb-1.0))
+# requires sys/scanio.h
+#$(eval $(call SaneBackend,pint,))
+$(eval $(call SaneBackend,pixma,Canon Multi-Function Printers and CanoScan Scanners,+libusb-1.0 +libjpeg))
+$(eval $(call SaneBackend,plustek,LM983[1/2/3] based USB flatbed scanners,+libusb-1.0))
+$(eval $(call SaneBackend,plustek_pp,Plustek parallel port flatbed scanners))
+$(eval $(call SaneBackend,qcam,Connectix QuickCam cameras,@(TARGET_x86||TARGET_x86_64)))
+$(eval $(call SaneBackend,ricoh,Ricoh flatbed scanners))
+$(eval $(call SaneBackend,ricoh2,Ricoh2 flatbed scanners,+libusb-1.0))
+$(eval $(call SaneBackend,rts8891,rts8891 based scanners,+libusb-1.0))
+$(eval $(call SaneBackend,s9036,Siemens 9036 flatbed scanners))
+$(eval $(call SaneBackend,sceptre,SCEPTRE scanners))
+$(eval $(call SaneBackend,sharp,SHARP scanners))
+$(eval $(call SaneBackend,sm3600,Microtek scanners with M011 USB chip,+libusb-1.0))
+$(eval $(call SaneBackend,sm3840,Microtek scanners with SCAN08 USB chip,+libusb-1.0))
+$(eval $(call SaneBackend,snapscan,AGFA SnapScan flatbed scanners,+libusb-1.0))
+$(eval $(call SaneBackend,sp15c,Fujitsu ScanPartner 15C flatbed scanner))
+$(eval $(call SaneBackend,st400,Siemens ST/Highscan flatbed scanners))
+$(eval $(call SaneBackend,stv680,STV680 cameras,+libusb-1.0))
+$(eval $(call SaneBackend,tamarack,Tamarack flatbed scanners))
+$(eval $(call SaneBackend,teco1,TECO / RELISYS scanners))
+$(eval $(call SaneBackend,teco2,TECO / RELISYS scanners))
+$(eval $(call SaneBackend,teco3,TECO / RELISYS scanners))
+$(eval $(call SaneBackend,test,testing frontends))
+$(eval $(call SaneBackend,u12,Plustek USB flatbed scanners based on older parport designs,+libusb-1.0))
+$(eval $(call SaneBackend,umax,UMAX scanners,+libusb-1.0))
+$(eval $(call SaneBackend,umax1220u,the UMAX Astra 1220U and similar scanners,+libusb-1.0))
+$(eval $(call SaneBackend,umax_pp,Umax Astra parallel port flatbed scanners))
+$(eval $(call SaneBackend,v4l,Video for Linux API,+libv4l +libjpeg +libusb-1.0))
+$(eval $(call SaneBackend,xerox_mfp,Xerox Phaser 3200MFP device,+libjpeg +libusb-1.0))
+$(eval $(call BuildPackage,sane-backends))
+$(eval $(call BuildPackage,sane-backends-all))
+$(eval $(call BuildPackage,sane-frontends))
diff --git a/external/subpack/utils/sane-backends/files/saned.hotplug b/external/subpack/utils/sane-backends/files/saned.hotplug
new file mode 100755
index 0000000..470cf4f
--- /dev/null
+++ b/external/subpack/utils/sane-backends/files/saned.hotplug
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+[ "$ACTION" != "remove" ] || exit 0
+
+SANE_GROUP=scanner
+grep -q -E "^$SANE_GROUP:" /etc/group || exit 0
+
+grant() {
+ echo "hotplug(usb/20-saned): Granting $1 to '$2' for group '$SANE_GROUP'" >/dev/kmsg
+ chgrp "$SANE_GROUP" "$2"
+ chmod "$1" "$2"
+}
+
+usblp_bind="/sys/bus/usb/drivers/usblp/bind"
+if [ "$DEVTYPE" = "usb_device" ]; then
+ # Filter SANE known devices
+ vendor_product="${PRODUCT%/*}"
+ vendorid="$(printf '%04x' "0x0${vendor_product%/*}")"
+ productid="$(printf '%04x' "0x0${vendor_product#*/}")"
+ grep -s -x -F -q "$productid" "/usr/share/sane/$vendorid"-*.usbid || exit 0
+ grant g+rw "/dev/$DEVNAME"
+elif [ "$DEVTYPE" = "usb_interface" ] && [ "$DRIVER" = 'usblp' ]; then
+ # Needed by script /usr/bin/saned to rebind USB devices back to usblp after use
+ if [ -e "$usblp_bind" ]; then
+ grant g+w "$usblp_bind"
+ fi
+fi
+
diff --git a/external/subpack/utils/sane-backends/files/saned.sbin b/external/subpack/utils/sane-backends/files/saned.sbin
new file mode 100755
index 0000000..7114926
--- /dev/null
+++ b/external/subpack/utils/sane-backends/files/saned.sbin
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+usblp_driver="/sys/bus/usb/drivers/usblp"
+
+inuse=""
+if [ -e /sys/bus/usb/devices ]; then
+ for usbdev_driver in /sys/bus/usb/devices/*/driver; do
+ [ -e "$usbdev_driver" ] || continue
+ [ "$(readlink -f "$usbdev_driver")" = "$usblp_driver" ] || continue
+ usbdev="${usbdev_driver%/*}"
+ inuse="$inuse ${usbdev##*/}"
+ done
+fi
+
+/usr/lib/sane/saned "$@"
+err=$?
+
+for usbdev in $inuse; do
+ [ -e "/sys/bus/usb/devices/$usbdev/driver" ] && continue
+ logger -t saned "binding device $usbdev back to usblp..."
+ printf '%s' "$usbdev" > "$usblp_driver/bind"
+done
+
+exit $err
diff --git a/external/subpack/utils/sane-backends/files/saned.xinetd b/external/subpack/utils/sane-backends/files/saned.xinetd
new file mode 100644
index 0000000..1202d7f
--- /dev/null
+++ b/external/subpack/utils/sane-backends/files/saned.xinetd
@@ -0,0 +1,14 @@
+# default: off
+# description: The saned provides scanner service via the network. \
+# Applications like kooka, xsane or xscanimage can use the remote \
+# scanner.
+service sane-port
+{
+ socket_type = stream
+ port = 6566
+ wait = no
+ user = saned
+ group = scanner
+ server = /usr/sbin/saned
+ disable = yes
+}
diff --git a/external/subpack/utils/sane-backends/patches/002-remove-uneeded.patch b/external/subpack/utils/sane-backends/patches/002-remove-uneeded.patch
new file mode 100644
index 0000000..65d9cea
--- /dev/null
+++ b/external/subpack/utils/sane-backends/patches/002-remove-uneeded.patch
@@ -0,0 +1,11 @@
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -451,7 +451,7 @@ target_alias = @target_alias@
+ top_build_prefix = @top_build_prefix@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+-SUBDIRS = include lib sanei backend frontend tools doc po testsuite
++SUBDIRS = include lib sanei backend frontend
+ DIST_SUBDIRS = include lib sanei backend frontend tools doc po japi testsuite
+ dist_doc_DATA = AUTHORS COPYING LICENSE NEWS PROBLEMS PROJECTS README \
+ README.aix README.beos README.darwin README.djpeg \
diff --git a/external/subpack/utils/screen/Makefile b/external/subpack/utils/screen/Makefile
new file mode 100644
index 0000000..6b6d27f
--- /dev/null
+++ b/external/subpack/utils/screen/Makefile
@@ -0,0 +1,57 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=screen
+PKG_VERSION:=4.9.1
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@GNU/screen
+PKG_HASH:=26cef3e3c42571c0d484ad6faf110c5c15091fbf872b06fa7aa4766c7405ac69
+
+PKG_MAINTAINER:=Etienne CHAMPETIER <champetier.etienne@gmail.com>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:gnu:screen
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/screen
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Terminal
+ DEPENDS:=+libncurses
+ TITLE:=Full-screen terminal window manager
+ URL:=https://www.gnu.org/software/screen/
+endef
+
+define Package/screen/description
+ Screen is a full-screen window manager that multiplexes a physical
+ terminal between several processes, typically interactive shells.
+endef
+
+CONFIGURE_ARGS += \
+ --enable-colors256 \
+ --with-sys-screenrc=/etc/screenrc
+
+define Package/screen/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/screen $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_DATA) ./files/etc/screenrc $(1)/etc/screenrc
+endef
+
+define Package/screen/conffiles
+/etc/screenrc
+endef
+
+$(eval $(call BuildPackage,screen))
diff --git a/external/subpack/utils/screen/files/etc/screenrc b/external/subpack/utils/screen/files/etc/screenrc
new file mode 100644
index 0000000..3337674
--- /dev/null
+++ b/external/subpack/utils/screen/files/etc/screenrc
@@ -0,0 +1 @@
+startup_message off
diff --git a/external/subpack/utils/screen/patches/010-ptyh.patch b/external/subpack/utils/screen/patches/010-ptyh.patch
new file mode 100644
index 0000000..aad3580
--- /dev/null
+++ b/external/subpack/utils/screen/patches/010-ptyh.patch
@@ -0,0 +1,10 @@
+--- a/pty.c
++++ b/pty.c
+@@ -30,6 +30,7 @@
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <signal.h>
++#include <pty.h>
+
+ #if defined(__OpenBSD__)
+ #include <utils.h> /* for openpty() */
diff --git a/external/subpack/utils/sed/Makefile b/external/subpack/utils/sed/Makefile
new file mode 100644
index 0000000..895e0a8
--- /dev/null
+++ b/external/subpack/utils/sed/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2010-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=sed
+PKG_VERSION:=4.9
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/sed
+PKG_HASH:=6e226b732e1cd739464ad6862bd1a1aba42d7982922da7a53519631d24975181
+
+PKG_MAINTAINER:=Russell Senior <russell@personaltelco.net>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:gnu:sed
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/sed
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=sed stream editor utility - full version
+ URL:=https://www.gnu.org/software/sed/
+ ALTERNATIVES:=300:/bin/sed:/usr/libexec/sed-gnu
+endef
+
+define Package/sed/description
+sed (stream editor) is a non-interactive command-line text editor. sed is commonly
+used to filter text, i.e., it takes text input, performs some operation (or set of
+operations) on it, and outputs the modified text. sed is typically used for
+extracting part of a file using pattern matching or substituting multiple
+occurrences of a string within a file.
+endef
+
+CONFIGURE_ARGS += \
+ --disable-acl \
+ --without-selinux
+
+define Package/sed/install
+ $(INSTALL_DIR) $(1)/usr/libexec
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/sed $(1)/usr/libexec/sed-gnu
+endef
+
+$(eval $(call BuildPackage,sed))
diff --git a/external/subpack/utils/selinux-python/Makefile b/external/subpack/utils/selinux-python/Makefile
new file mode 100644
index 0000000..ababbae
--- /dev/null
+++ b/external/subpack/utils/selinux-python/Makefile
@@ -0,0 +1,289 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=selinux-python
+PKG_VERSION:=3.5
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/SELinuxProject/selinux/releases/download/$(PKG_VERSION)
+PKG_HASH:=8245bb4dae59333461f19ca0c79a829081f07972fa5e3ad4c2b2b917dd71d96b
+
+PKG_MAINTAINER:=Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+PYTHON3_PKG_BUILD:=0
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/python/python3-package.mk
+
+#
+# common definitions
+#
+
+define Package/selinux-python/Default
+ URL:=http://selinuxproject.org/page/Main_Page
+ DEPENDS:=+python3-light
+endef
+
+define Package/selinux-python/Default/python
+$(call Package/selinux-python/Default)
+ SUBMENU:=Python
+ SECTION:=lang
+ CATEGORY:=Languages
+endef
+
+define Package/selinux-python/Default/util
+$(call Package/selinux-python/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=SELinux management utility
+endef
+
+define Package/selinux-python/Default/description
+A set of SELinux tools written in Python that help with managing a
+system with SELinux enabled.
+endef
+
+MAKE_VARS = \
+ $(PYTHON3_VARS) \
+ $(HOST_PYTHON3_PIP_VARS) \
+ PYTHON_SETUP_ARGS=--no-compile
+
+define Build/Compile
+ $(call Build/Compile/Default,all)
+endef
+
+#
+# python3-seobject
+#
+
+define Package/python3-seobject
+$(call Package/selinux-python/Default/python)
+ TITLE:=SELinux seobject library
+ DEPENDS+= +python3-selinux +python3-semanage +python3-sepolicy +python3-setools
+endef
+
+define Package/python3-seobject/description
+$(call Package/selinux-python/Default/description)
+
+This package contains the seobject library.
+endef
+
+define Py3Package/python3-seobject/filespec
++|$(PYTHON3_PKG_DIR)/seobject.py
+endef
+
+Py3Package/python3-seobject/install:=:
+
+#
+# python3-sepolgen
+#
+
+define Package/python3-sepolgen
+$(call Package/selinux-python/Default/python)
+ TITLE:=SELinux policy generation library
+ DEPENDS+= +python3-selinux
+endef
+
+define Package/python3-sepolgen/description
+$(call Package/selinux-python/Default/description)
+
+This package contains the SELinux policy generation Python library.
+endef
+
+define Package/python3-sepolgen/conffiles
+/etc/sepolgen/
+endef
+
+define Py3Package/python3-sepolgen/filespec
++|$(PYTHON3_PKG_DIR)/sepolgen
+endef
+
+define Py3Package/python3-sepolgen/install
+ $(INSTALL_DIR) $(1)/etc/sepolgen
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/var/lib/sepolgen/perm_map $(1)/etc/sepolgen/
+endef
+
+#
+# python3-sepolicy
+#
+
+define Package/python3-sepolicy
+$(call Package/selinux-python/Default/python)
+ TITLE:=SELinux Policy Analyses binding
+ DEPENDS+= +python3-selinux +python3-sepolgen +python3-xml +python3-setools
+endef
+
+define Package/python3-sepolicy/description
+$(call Package/selinux-python/Default/description)
+
+This package contains a Python binding for SELinux Policy Analyses.
+endef
+
+define Py3Package/python3-sepolicy/filespec
++|$(PYTHON3_PKG_DIR)/sepolicy
+-|$(PYTHON3_PKG_DIR)/sepolicy/gui.py
+-|$(PYTHON3_PKG_DIR)/sepolicy/sedbus.py
++|$(PYTHON3_PKG_DIR)/sepolicy-$(PKG_VERSION).dist-info
+endef
+
+Py3Package/python3-sepolicy/install:=:
+
+#
+# selinux-audit2allow
+#
+
+define Package/selinux-audit2allow
+$(call Package/selinux-python/Default/util)
+ TITLE+= audit2allow
+ DEPENDS+= +python3-selinux +python3-sepolgen
+endef
+
+define Package/selinux-audit2allow/description
+$(call Package/selinux-python/Default/description)
+
+This package contains the audit2allow and audit2why tools.
+endef
+
+define Package/selinux-audit2allow/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/audit2allow $(1)/usr/bin/
+ $(LN) audit2allow $(1)/usr/bin/audit2why
+endef
+
+#
+# selinux-chchat
+#
+
+define Package/selinux-chcat
+$(call Package/selinux-python/Default/util)
+ TITLE+= chcat
+ DEPENDS+= +python3-selinux +python3-seobject +selinux-semanage
+endef
+
+define Package/selinux-chcat/description
+$(call Package/selinux-python/Default/description)
+
+This package contains the chcat tool.
+endef
+
+define Package/selinux-chcat/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/chcat $(1)/usr/bin/
+endef
+
+#
+# selinux-python
+#
+
+define Package/selinux-python
+$(call Package/selinux-python/Default/util)
+ TITLE+= meta-package
+ DEPENDS:= \
+ +selinux-audit2allow \
+ +selinux-chcat \
+ +selinux-semanage \
+ +selinux-sepolgen-ifgen \
+ +selinux-sepolicy
+endef
+
+define Package/selinux-python/description
+$(call Package/selinux-python/Default/description)
+
+This is a meta-package that installs all of the SELinux management
+utilities.
+endef
+
+Package/selinux-python/install:=:
+
+#
+# selinux-semanage
+#
+
+define Package/selinux-semanage
+$(call Package/selinux-python/Default/util)
+ TITLE+= semanage
+ DEPENDS+= +python3-seobject
+endef
+
+define Package/selinux-semanage/description
+$(call Package/selinux-python/Default/description)
+
+This package contains the semanage tool.
+endef
+
+define Package/selinux-semanage/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/semanage $(1)/usr/sbin/
+endef
+
+#
+# selinux-sepolgen-ifgen
+#
+
+define Package/selinux-sepolgen-ifgen
+$(call Package/selinux-python/Default/util)
+ TITLE+= sepolgen-ifgen
+ DEPENDS+= +python3-selinux +python3-sepolgen +libselinux
+endef
+
+define Package/selinux-sepolgen-iften/description
+$(call Package/selinux-python/Default/description)
+
+This package contains the sepolgen-ifgen tool.
+endef
+
+define Package/selinux-sepolgen-ifgen/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/sepolgen-ifgen $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/sepolgen-ifgen-attr-helper $(1)/usr/bin/
+endef
+
+#
+# selinux-sepolicy
+#
+
+define Package/selinux-sepolicy
+$(call Package/selinux-python/Default/util)
+ TITLE+= sepolicy
+ DEPENDS+= +python3-multiprocessing +python3-selinux +python3-sepolicy
+endef
+
+define Package/selinux-sepolicy/description
+$(call Package/selinux-python/Default/description)
+
+This package contains the sepolicy and sepolgen tools.
+endef
+
+define Package/selinux-sepolicy/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/sepolicy $(1)/usr/bin/
+ $(LN) sepolicy $(1)/usr/bin/sepolgen
+endef
+
+$(eval $(call Py3Package,python3-seobject))
+$(eval $(call Py3Package,python3-sepolgen))
+$(eval $(call Py3Package,python3-sepolicy))
+
+$(eval $(call BuildPackage,python3-seobject))
+$(eval $(call BuildPackage,python3-sepolgen))
+$(eval $(call BuildPackage,python3-sepolicy))
+
+$(eval $(call BuildPackage,python3-seobject-src))
+$(eval $(call BuildPackage,python3-sepolgen-src))
+$(eval $(call BuildPackage,python3-sepolicy-src))
+
+$(eval $(call BuildPackage,selinux-audit2allow))
+$(eval $(call BuildPackage,selinux-chcat))
+$(eval $(call BuildPackage,selinux-python))
+$(eval $(call BuildPackage,selinux-semanage))
+$(eval $(call BuildPackage,selinux-sepolgen-ifgen))
+$(eval $(call BuildPackage,selinux-sepolicy))
diff --git a/external/subpack/utils/selinux-python/patches/0001-sepolgen-adjust-data_dir.patch b/external/subpack/utils/selinux-python/patches/0001-sepolgen-adjust-data_dir.patch
new file mode 100644
index 0000000..5b866f1
--- /dev/null
+++ b/external/subpack/utils/selinux-python/patches/0001-sepolgen-adjust-data_dir.patch
@@ -0,0 +1,23 @@
+From 4dfa91b1377b6dc57e66443ea1a08c6d79a3a6e2 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Date: Wed, 2 Oct 2019 12:04:24 +0200
+Subject: [PATCH] sepolgen: adjust data_dir()
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+(changed data_dir prefix from /usr/share to /etc)
+Signed-off-by: Jeffery To <jeffery.to@gmail.com>
+---
+ sepolgen/src/sepolgen/defaults.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sepolgen/src/sepolgen/defaults.py
++++ b/sepolgen/src/sepolgen/defaults.py
+@@ -57,7 +57,7 @@ Various default settings, including file
+ """
+
+ def data_dir():
+- return "/var/lib/sepolgen"
++ return "/etc/sepolgen"
+
+ def perm_map():
+ return data_dir() + "/perm_map"
diff --git a/external/subpack/utils/selinux-python/patches/0002-sepolgen-don-t-hardcode-search-for-ausearch-in-sbin.patch b/external/subpack/utils/selinux-python/patches/0002-sepolgen-don-t-hardcode-search-for-ausearch-in-sbin.patch
new file mode 100644
index 0000000..426781b
--- /dev/null
+++ b/external/subpack/utils/selinux-python/patches/0002-sepolgen-don-t-hardcode-search-for-ausearch-in-sbin.patch
@@ -0,0 +1,33 @@
+From a8a7f8fb5cfe95f28cd5f7ff4b4679ca122fe410 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Date: Wed, 2 Oct 2019 13:38:18 +0200
+Subject: [PATCH] sepolgen: don't hardcode search for ausearch in /sbin
+
+ausearch may be installed in another location, just rely on PATH to
+find ausearch.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+---
+ sepolgen/src/sepolgen/audit.py | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sepolgen/src/sepolgen/audit.py
++++ b/sepolgen/src/sepolgen/audit.py
+@@ -41,7 +41,7 @@ def get_audit_boot_msgs():
+ s = time.localtime(time.time() - off)
+ bootdate = time.strftime("%x", s)
+ boottime = time.strftime("%X", s)
+- output = subprocess.Popen(["/sbin/ausearch", "-m", "AVC,USER_AVC,MAC_POLICY_LOAD,DAEMON_START,SELINUX_ERR", "-ts", bootdate, boottime],
++ output = subprocess.Popen(["ausearch", "-m", "AVC,USER_AVC,MAC_POLICY_LOAD,DAEMON_START,SELINUX_ERR", "-ts", bootdate, boottime],
+ stdout=subprocess.PIPE).communicate()[0]
+ if util.PY3:
+ output = util.decode_input(output)
+@@ -56,7 +56,7 @@ def get_audit_msgs():
+ string contain all of the audit messages returned by ausearch.
+ """
+ import subprocess
+- output = subprocess.Popen(["/sbin/ausearch", "-m", "AVC,USER_AVC,MAC_POLICY_LOAD,DAEMON_START,SELINUX_ERR"],
++ output = subprocess.Popen(["ausearch", "-m", "AVC,USER_AVC,MAC_POLICY_LOAD,DAEMON_START,SELINUX_ERR"],
+ stdout=subprocess.PIPE).communicate()[0]
+ if util.PY3:
+ output = util.decode_input(output)
diff --git a/external/subpack/utils/selinux-python/patches/0003-sepolicy-no-gui.patch b/external/subpack/utils/selinux-python/patches/0003-sepolicy-no-gui.patch
new file mode 100644
index 0000000..a822d4c
--- /dev/null
+++ b/external/subpack/utils/selinux-python/patches/0003-sepolicy-no-gui.patch
@@ -0,0 +1,23 @@
+--- a/sepolicy/sepolicy.py
++++ b/sepolicy/sepolicy.py
+@@ -685,7 +685,6 @@ if __name__ == '__main__':
+ gen_booleans_args(subparsers)
+ gen_communicate_args(subparsers)
+ gen_generate_args(subparsers)
+- gen_gui_args(subparsers)
+ gen_interface_args(subparsers)
+ gen_manpage_args(subparsers)
+ gen_network_args(subparsers)
+--- a/sepolicy/setup.py
++++ b/sepolicy/setup.py
+@@ -13,10 +13,5 @@ setup(
+ packages=[
+ "sepolicy",
+ "sepolicy.templates",
+- "sepolicy.help"
+ ],
+- package_data={
+- 'sepolicy': ['*.glade'],
+- 'sepolicy.help': ['*.txt', '*.png']
+- }
+ )
diff --git a/external/subpack/utils/selinux-python/patches/0004-sepolicy-fix-get_os_version-except.patch b/external/subpack/utils/selinux-python/patches/0004-sepolicy-fix-get_os_version-except.patch
new file mode 100644
index 0000000..f035846
--- /dev/null
+++ b/external/subpack/utils/selinux-python/patches/0004-sepolicy-fix-get_os_version-except.patch
@@ -0,0 +1,39 @@
+commit 80ba6c49dec9c2c48775e70a4d4564ba5e59eea1
+Author: Jeffery To <jeffery.to@gmail.com>
+Date: Mon Jun 19 14:15:45 2023 +0800
+
+ python/sepolicy: Fix get_os_version except clause
+
+ This adds more exceptions to be handled by the except clause in
+ `get_os_version()`:
+
+ * If the `distro` package is not installed, then `import distro` raises
+ a `ModuleNotFoundError` exception.
+
+ * The distro documentation[1] lists `OSError` and `UnicodeError` as
+ exceptions that can be raised.
+
+ * Older versions of distro (<= 1.6.0) may also raise
+ `subprocessCalledProcessError`[2].
+
+ [1]: https://github.com/python-distro/distro/blob/v1.8.0/src/distro/distro.py#L749-L753
+ [2]: https://github.com/python-distro/distro/blob/v1.6.0/distro.py#L726-L728
+
+ Signed-off-by: Jeffery To <jeffery.to@gmail.com>
+
+--- a/sepolicy/sepolicy/__init__.py
++++ b/sepolicy/sepolicy/__init__.py
+@@ -1240,11 +1240,12 @@ def boolean_desc(boolean):
+
+
+ def get_os_version():
++ import subprocess
+ system_release = ""
+ try:
+ import distro
+ system_release = distro.name(pretty=True)
+- except IOError:
++ except (ModuleNotFoundError, OSError, IOError, UnicodeError, subprocess.CalledProcessError):
+ system_release = "Misc"
+
+ return system_release
diff --git a/external/subpack/utils/selinux-python/patches/0005-no-translations.patch b/external/subpack/utils/selinux-python/patches/0005-no-translations.patch
new file mode 100644
index 0000000..9b1cb8c
--- /dev/null
+++ b/external/subpack/utils/selinux-python/patches/0005-no-translations.patch
@@ -0,0 +1,8 @@
+--- a/Makefile
++++ b/Makefile
+@@ -1,4 +1,4 @@
+-SUBDIRS = sepolicy audit2allow semanage sepolgen chcat po
++SUBDIRS = sepolicy audit2allow semanage sepolgen chcat
+
+ all install relabel clean indent test:
+ @for subdir in $(SUBDIRS); do \
diff --git a/external/subpack/utils/semodule-utils/Makefile b/external/subpack/utils/semodule-utils/Makefile
new file mode 100644
index 0000000..8250485
--- /dev/null
+++ b/external/subpack/utils/semodule-utils/Makefile
@@ -0,0 +1,51 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=semodule-utils
+PKG_VERSION:=3.1
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/SELinuxProject/selinux/releases/download/20200710
+PKG_HASH:=0cc37f9cec751d9c2abb5f2b228b060567e973cb47c19b53b8a4a7378baaa853
+
+PKG_MAINTAINER:=W. Michael Petullo <mike@flyn.org>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+HOST_BUILD_DEPENDS:=libsemanage/host
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/host-build.mk
+
+define Package/semodule-utils
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libsepol
+ TITLE:=SELinux policy utilities for dealing with modules
+ URL:=http://selinuxproject.org/page/Main_Page
+endef
+
+define Package/semodule-utils/description
+ Semodule-utils is a collection of utilities for dealing with
+ policy modules.
+endef
+
+HOST_MAKE_FLAGS += \
+ PREFIX=$(STAGING_DIR_HOSTPKG) \
+ SBINDIR=$(STAGING_DIR_HOSTPKG)/sbin \
+ ETCDIR=$(STAGING_DIR_HOSTPKG)/etc
+
+define Package/semodule-utils/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+endef
+
+$(eval $(call HostBuild))
+$(eval $(call BuildPackage,semodule-utils))
diff --git a/external/subpack/utils/serialconsole/Makefile b/external/subpack/utils/serialconsole/Makefile
new file mode 100644
index 0000000..86acf17
--- /dev/null
+++ b/external/subpack/utils/serialconsole/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=sc
+PKG_VERSION:=1.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/serialconsole/sc
+PKG_HASH:=2e7a27d588a51173dda3093381604e6f0a16bb04e95b00fd652f37c34c2c6d04
+
+PKG_MAINTAINER:=Stefan Bethke <stb@lassitu.de>
+PKG_LICENSE:=BSD-2-Clause
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/serialconsole
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Terminal
+ TITLE:=Serial Console - minimal terminal program
+ URL:=http://sourceforge.net/projects/serialconsole/
+endef
+
+define Package/serialconsole/description
+serialconsole (sc) is a minimal terminal program allowing to use one machine
+to access the serial console of another machine.
+endef
+
+define Package/serialconsole/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/local/bin/sc $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,serialconsole))
diff --git a/external/subpack/utils/setools/Makefile b/external/subpack/utils/setools/Makefile
new file mode 100644
index 0000000..e4cf10e
--- /dev/null
+++ b/external/subpack/utils/setools/Makefile
@@ -0,0 +1,114 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=setools
+PKG_VERSION:=4.4.4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://github.com/SELinuxProject/setools/releases/download/$(PKG_VERSION)
+PKG_HASH:=3c5fa76a674fe3f6890d900df59b9d142e4b63c9ffbde653904f90ed6e666ef9
+
+PKG_BUILD_DEPENDS:=python-cython/host # Cython>=0.27
+
+PKG_MAINTAINER:=W. Michael Petullo <mike@flyn.org>
+PKG_LICENSE:=GPL-2.0-only LGPL-2.1-only
+PKG_LICENSE_FILES:=COPYING COPYING.GPL COPYING.LGPL
+PKG_CPE_ID:=cpe:/a:selinuxproject:setools
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/python/python3-package.mk
+
+TAR_OPTIONS+= --strip-components 1
+TAR_CMD=$(HOST_TAR) -C $(1) $(TAR_OPTIONS)
+
+define Package/setools/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=SELinux policy analysis tool
+ URL:=http://selinuxproject.org/page/Main_Page
+ DEPENDS:=+python3-light +python3-logging +python3-setools
+endef
+
+define Package/setools/Default/description
+SETools is a collection of tools and libraries designed to facilitate
+SELinux policy analysis.
+endef
+
+define Package/python3-setools
+ SECTION:=lang
+ CATEGORY:=Languages
+ SUBMENU:=Python
+ TITLE:=SETools Python bindings
+ URL:=http://selinuxproject.org/page/Main_Page
+ DEPENDS:=+python3-light +python3-logging +python3-pkg-resources +libselinux +libsepol
+endef
+
+define Package/python3-setools/description
+$(call Package/setools/Default/description)
+
+This contains the SETools Python binding.
+endef
+
+Py3Package/python3-setools/install:=:
+
+define Package/setools
+$(call Package/setools/Default)
+ TITLE+= meta-package
+ DEPENDS:= \
+ setools-sechecker \
+ setools-sediff \
+ setools-sedta \
+ setools-seinfo \
+ setools-seinfoflow \
+ setools-sesearch
+endef
+
+define Package/setools/description
+$(call Package/setools/Default/description)
+
+This is a meta-package that installs all of the SETools tools.
+endef
+
+Package/setools/install:=:
+
+define BuildUtil
+ define Package/setools-$(1)
+ $(call Package/setools/Default)
+ TITLE+= $(1)
+ DEPENDS+= $(2)
+ endef
+
+ define Package/setools-$(1)/description
+$(call Package/setools/Default/description)
+
+This contains the $(1) tool.
+ endef
+
+ define Py3Package/setools-$(1)/install
+ $$(INSTALL_DIR) $$(1)/usr/bin
+ $$(INSTALL_BIN) $$(PKG_INSTALL_DIR)/usr/bin/$(1) $$(1)/usr/bin/
+ endef
+
+ Py3Package/setools-$(1)/filespec:=
+
+ $$(eval $$(call Py3Package,setools-$(1)))
+ $$(eval $$(call BuildPackage,setools-$(1)))
+endef
+
+$(eval $(call Py3Package,python3-setools))
+$(eval $(call BuildPackage,python3-setools))
+$(eval $(call BuildPackage,python3-setools-src))
+
+$(eval $(call BuildPackage,setools))
+
+$(eval $(call BuildUtil,sechecker))
+$(eval $(call BuildUtil,sediff))
+$(eval $(call BuildUtil,sedta,+python3-networkx))
+$(eval $(call BuildUtil,seinfo))
+$(eval $(call BuildUtil,seinfoflow,+python3-networkx))
+$(eval $(call BuildUtil,sesearch))
diff --git a/external/subpack/utils/setools/patches/010-no-gui.patch b/external/subpack/utils/setools/patches/010-no-gui.patch
new file mode 100644
index 0000000..54f03c3
--- /dev/null
+++ b/external/subpack/utils/setools/patches/010-no-gui.patch
@@ -0,0 +1,16 @@
+--- a/setup.py
++++ b/setup.py
+@@ -139,10 +139,10 @@ setup(name='setools',
+ author_email='pebenito@ieee.org',
+ url='https://github.com/SELinuxProject/setools',
+ cmdclass={'build_qhc': QtHelpCommand, 'clean': CleanCommand},
+- packages=['setools', 'setools.checker', 'setools.diff', 'setoolsgui', 'setoolsgui.apol'],
+- scripts=['apol', 'sediff', 'seinfo', 'seinfoflow', 'sesearch', 'sedta', 'sechecker'],
++ packages=['setools', 'setools.checker', 'setools.diff'],
++ scripts=['sediff', 'seinfo', 'seinfoflow', 'sesearch', 'sedta', 'sechecker'],
+ data_files=installed_data,
+- package_data={'': ['*.ui', '*.qhc', '*.qch'], 'setools': ['perm_map',
++ package_data={'setools': ['perm_map',
+ 'policyrep.pyi',
+ 'py.typed']},
+ ext_modules=cythonize(ext_py_mods, include_path=['setools/policyrep'],
diff --git a/external/subpack/utils/setools/patches/030-remove-host-paths.patch b/external/subpack/utils/setools/patches/030-remove-host-paths.patch
new file mode 100644
index 0000000..bec9be9
--- /dev/null
+++ b/external/subpack/utils/setools/patches/030-remove-host-paths.patch
@@ -0,0 +1,11 @@
+--- a/setup.py
++++ b/setup.py
+@@ -79,7 +79,7 @@ class QtHelpCommand(Command):
+
+
+ # Library linkage
+-lib_dirs = ['.', '/usr/lib64', '/usr/lib', '/usr/local/lib']
++lib_dirs = ['.', os.environ["STAGING_DIR"] + '/usr/lib']
+ include_dirs = []
+
+ with suppress(KeyError):
diff --git a/external/subpack/utils/setserial/Makefile b/external/subpack/utils/setserial/Makefile
new file mode 100644
index 0000000..e11adb2
--- /dev/null
+++ b/external/subpack/utils/setserial/Makefile
@@ -0,0 +1,34 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=setserial
+PKG_VERSION:=2.17
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/setserial
+PKG_HASH:=7e4487d320ac31558563424189435d396ddf77953bb23111a17a3d1487b5794a
+
+PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+PKG_LICENSE:=GPL-2.0-only
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/setserial
+ SECTION:=utils
+ CATEGORY:=Utilities
+ URL:=http://setserial.sourceforge.net/
+ TITLE:=Serial port attribute utility
+endef
+
+define Package/setserial/install
+ $(INSTALL_DIR) $(1)/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/setserial $(1)/bin/
+endef
+
+define Package/setserial/description
+ Setserial is a program which allows you to look at and change various
+ attributes of a serial device, including its port, its IRQ, and other
+ serial port options.
+endef
+
+$(eval $(call BuildPackage,setserial))
diff --git a/external/subpack/utils/setserial/patches/010-no-docs.patch b/external/subpack/utils/setserial/patches/010-no-docs.patch
new file mode 100644
index 0000000..8069c07
--- /dev/null
+++ b/external/subpack/utils/setserial/patches/010-no-docs.patch
@@ -0,0 +1,11 @@
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -17,7 +17,7 @@ DEFS = @DEFS@
+ INCS = -I.
+ TAR = tar
+
+-all: setserial setserial.cat
++all: setserial
+
+ setserial: setserial.c
+ $(CC) $(CFLAGS) $(DEFS) $(INCS) setserial.c -o setserial
diff --git a/external/subpack/utils/setserial/patches/020-musl.patch b/external/subpack/utils/setserial/patches/020-musl.patch
new file mode 100644
index 0000000..7b26594
--- /dev/null
+++ b/external/subpack/utils/setserial/patches/020-musl.patch
@@ -0,0 +1,19 @@
+--- a/setserial.c
++++ b/setserial.c
+@@ -11,6 +11,8 @@
+ */
+
+ #include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
+ #include <fcntl.h>
+ #include <termios.h>
+ #include <string.h>
+@@ -22,6 +24,7 @@
+ #ifdef HAVE_LINUX_HAYESESP_H
+ #include <linux/hayesesp.h>
+ #endif
++#include <sys/ioctl.h>
+ #include <linux/serial.h>
+
+ #include "version.h"
diff --git a/external/subpack/utils/shadow/Makefile b/external/subpack/utils/shadow/Makefile
new file mode 100644
index 0000000..ab2ba22
--- /dev/null
+++ b/external/subpack/utils/shadow/Makefile
@@ -0,0 +1,160 @@
+#
+# Copyright (C) 2008-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=shadow
+PKG_VERSION:=4.8.1
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://github.com/shadow-maint/shadow/releases/download/$(PKG_VERSION)
+PKG_HASH:=a3ad4630bdc41372f02a647278a8c3514844295d36eefe68ece6c3a641c1ae62
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:debian:shadow
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+PKG_BUILD_DEPENDS:=libxcrypt
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+SHADOW_APPLETS := \
+ chage chfn chgpasswd chpasswd chsh expiry faillog gpasswd \
+ groupadd groupdel groupmems groupmod groups grpck grpconv grpunconv \
+ lastlog login logoutd newgidmap newgrp newuidmap newusers nologin \
+ passwd pwck pwconv pwunconv su \
+ useradd userdel usermod vipw
+
+CONFIGURE_ARGS += \
+ --without-audit \
+ --without-libpam \
+ --without-selinux \
+ --without-acl \
+ --without-attr \
+ --without-tcb \
+ --without-nscd \
+ --with-bcrypt
+
+CONFIGURE_VARS += \
+ ac_cv_func_ruserok=no
+
+define Package/shadow/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=The PLD Linux shadow utilities
+ URL:=https://github.com/shadow-maint/shadow
+endef
+
+define Package/shadow
+ $(call Package/shadow/Default)
+ TITLE+= (all)
+ DEPENDS:=$(foreach u,$(SHADOW_APPLETS),+shadow-$(u))
+ HIDDEN:=1
+endef
+
+define Package/shadow/description
+ Full versions of standard shadow utilities. Normally, you would not
+ use this package, since the functionality in BusyBox is more than
+ sufficient and much smaller.
+endef
+
+define Package/shadow/install
+ true
+endef
+
+define Package/shadow-utils
+ $(call Package/shadow/Default)
+endef
+
+define Package/shadow-utils/config
+ menu "Select shadow utilities"
+ depends on PACKAGE_shadow-utils
+
+ config shadow-all
+ bool "Include all PLD shadow utilities"
+ select PACKAGE_shadow
+ default y
+
+ comment "Utilities"
+
+ $(foreach u,$(SHADOW_APPLETS), \
+ config PACKAGE_shadow-$(u)
+ prompt "Full PLD version of $(u) utility"
+
+ )
+
+ endmenu
+
+endef
+
+Package/shadow-utils/description = $(Package/shadow/description)
+
+define Package/shadow-common
+ $(call Package/shadow/Default)
+ TITLE:=Shared definitions for the PLD Linux shadow utilities
+ DEPENDS:=$(ICONV_DEPENDS) $(INTL_DEPENDS)
+ HIDDEN:=1
+endef
+
+define GenPlugin
+ define Package/shadow-$(1)
+ $(call Package/shadow/Default)
+ TITLE:=Utility $(1) from the PLD Linux shadow utilities
+ DEPENDS:=+shadow-common
+ HIDDEN:=1
+ endef
+
+ define Package/shadow-$(1)/description
+ Full version of standard $(1) utility. Normally, you would not use this
+ package, since the functionality in BusyBox is more than sufficient.
+ endef
+endef
+
+$(foreach u,$(SHADOW_APPLETS),$(eval $(call GenPlugin,$(u))))
+
+define Package/shadow-common/conffiles
+/etc/login.defs
+endef
+
+#hack to get libxcrypt working
+TARGET_LDFLAGS:=-L$(STAGING_DIR)/usr/lib/libxcrypt $(TARGET_LDFLAGS)
+
+define Package/shadow-common/install
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/login.defs $(1)/etc/
+ $(SED) 's,SU_NAME,#SU_NAME,g' $(1)/etc/login.defs
+ $(SED) 's,#ENCRYPT_METHOD DES,ENCRYPT_METHOD BCRYPT,g' $(1)/etc/login.defs
+endef
+
+define Package/shadow-utils/install
+ true
+endef
+
+define BuildPlugin
+ define Package/shadow-$(1)/install
+ [ -x "$(PKG_INSTALL_DIR)/usr/sbin/$(1)" ] && { \
+ $(INSTALL_DIR) $$(1)/usr/sbin; \
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/$(1) $$(1)/usr/sbin/; \
+ } || { \
+ $(INSTALL_DIR) $$(1)/usr/bin; \
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/$(1) $$(1)/usr/bin/; \
+ }
+ endef
+
+ $$(eval $$(call BuildPackage,shadow-$(1)))
+endef
+
+$(foreach u,$(SHADOW_APPLETS),$(eval $(call BuildPlugin,$(u))))
+
+$(eval $(call BuildPackage,shadow-utils))
+$(eval $(call BuildPackage,shadow-common))
+$(eval $(call BuildPackage,shadow))
diff --git a/external/subpack/utils/shadow/patches/004-fix-su-controoling-term.patch b/external/subpack/utils/shadow/patches/004-fix-su-controoling-term.patch
new file mode 100644
index 0000000..9644cf0
--- /dev/null
+++ b/external/subpack/utils/shadow/patches/004-fix-su-controoling-term.patch
@@ -0,0 +1,16 @@
+--- a/src/su.c
++++ b/src/su.c
+@@ -1122,8 +1122,12 @@ int main (int argc, char **argv)
+
+ if (fd >= 0) {
+ err = ioctl (fd, TIOCNOTTY, (char *) 0);
++ if (-1 == err && ENOTTY == errno) {
++ /* There are no controlling terminal already */
++ err = 0;
++ }
+ (void) close (fd);
+- } else if (ENXIO == errno) {
++ } else if (ENXIO == errno || EACCES == errno) {
+ /* There are no controlling terminal already */
+ err = 0;
+ }
diff --git a/external/subpack/utils/shadow/patches/008-internal-updwtmp.patch b/external/subpack/utils/shadow/patches/008-internal-updwtmp.patch
new file mode 100644
index 0000000..0cfb75c
--- /dev/null
+++ b/external/subpack/utils/shadow/patches/008-internal-updwtmp.patch
@@ -0,0 +1,71 @@
+ libmisc/utmp.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/libmisc/utmp.c b/libmisc/utmp.c
+index ba69cf6..a59939f 100644
+--- a/libmisc/utmp.c
++++ b/libmisc/utmp.c
+@@ -37,8 +37,8 @@
+
+ #ifdef USE_UTMPX
+ #include <utmpx.h>
+-#else
+-#include <utmp.h>
++//#else
++//#include <utmp.h>
+ #endif
+
+ #include <assert.h>
+@@ -46,6 +46,7 @@
+ #include <sys/socket.h>
+ #include <netdb.h>
+ #include <stdio.h>
++#include <fcntl.h>
+
+ #ident "$Id$"
+
+@@ -167,8 +168,8 @@ static bool is_my_tty (const char *tty)
+ * Some systems already have updwtmp() and possibly updwtmpx(). Others
+ * don't, so we re-implement these functions if necessary.
+ */
+-#ifndef HAVE_UPDWTMP
+-static void updwtmp (const char *filename, const struct utmp *ut)
++//#ifndef HAVE_UPDWTMP
++static void updwtmp1 (const char *filename, const struct utmp *ut)
+ {
+ int fd;
+
+@@ -178,10 +179,10 @@ static void updwtmp (const char *filename, const struct utmp *ut)
+ close (fd);
+ }
+ }
+-#endif /* ! HAVE_UPDWTMP */
++//#endif /* ! HAVE_UPDWTMP */
+
+ #ifdef USE_UTMPX
+-#ifndef HAVE_UPDWTMPX
++//#ifndef HAVE_UPDWTMPX
+ static void updwtmpx (const char *filename, const struct utmpx *utx)
+ {
+ int fd;
+@@ -192,7 +193,7 @@ static void updwtmpx (const char *filename, const struct utmpx *utx)
+ close (fd);
+ }
+ }
+-#endif /* ! HAVE_UPDWTMPX */
++//#endif /* ! HAVE_UPDWTMPX */
+ #endif /* ! USE_UTMPX */
+ #endif /* ! USE_PAM */
+
+@@ -351,7 +352,7 @@ int setutmp (struct utmp *ut)
+
+ #ifndef USE_PAM
+ /* This is done by pam_lastlog */
+- updwtmp (_WTMP_FILE, ut);
++ updwtmp1 (_WTMP_FILE, ut);
+ #endif /* ! USE_PAM */
+
+ return err;
+--
+2.17.1
+
diff --git a/external/subpack/utils/shared-mime-info/Makefile b/external/subpack/utils/shared-mime-info/Makefile
new file mode 100644
index 0000000..5e25608
--- /dev/null
+++ b/external/subpack/utils/shared-mime-info/Makefile
@@ -0,0 +1,56 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=shared-mime-info
+PKG_VERSION:=2.4
+PKG_RELEASE:=2
+
+PKG_MAINTAINER:=W. Michael Petullo <mike@flyn.org>
+
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_SOURCE:=shared-mime-info-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://gitlab.freedesktop.org/xdg/$(PKG_NAME)/-/archive/$(PKG_VERSION)
+PKG_HASH:=32dc32ae39ff1c1bf8434dd3b36770b48538a1772bc0298509d034f057005992
+
+PKG_BUILD_DEPENDS:=gettext-full/host
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+include $(INCLUDE_DIR)/meson.mk
+
+define Package/shared-mime-info
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+glib2 +libxml2 +libstdcpp
+ TITLE:=MIME-type information
+ URL:=https://freedesktop.org/wiki/Software/shared-mime-info/
+endef
+
+define Package/shared-mime-info/description
+ The shared-mime-info package contains a database of MIME types and their file extensions.
+endef
+
+define Package/shared-mime-info/install
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/bin/* \
+ $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/share/
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/share/* \
+ $(1)/usr/share/
+endef
+
+define Package/shared-mime-info/postinst
+#!/bin/sh
+
+update-mime-database /usr/share/mime/
+endef
+
+$(eval $(call BuildPackage,shared-mime-info))
diff --git a/external/subpack/utils/shared-mime-info/patches/001-no-xmllint.patch b/external/subpack/utils/shared-mime-info/patches/001-no-xmllint.patch
new file mode 100644
index 0000000..92588bc
--- /dev/null
+++ b/external/subpack/utils/shared-mime-info/patches/001-no-xmllint.patch
@@ -0,0 +1,11 @@
+--- a/meson.build
++++ b/meson.build
+@@ -21,7 +21,7 @@ config.set_quoted('VERSION', meson.proje
+ ###############################################################################
+ # Find tools
+
+-xmllint = find_program('xmllint')
++xmllint = find_program('xmllint', required: false)
+ xmlto = find_program('xmlto', required: false)
+
+ ###############################################################################
diff --git a/external/subpack/utils/sipcalc/Makefile b/external/subpack/utils/sipcalc/Makefile
new file mode 100644
index 0000000..323458e
--- /dev/null
+++ b/external/subpack/utils/sipcalc/Makefile
@@ -0,0 +1,41 @@
+#
+# This software is licensed under the Public Domain.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=sipcalc
+PKG_SOURCE_DATE:=2014-10-24
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/sii/sipcalc
+PKG_SOURCE_VERSION:=9b97dbca1a0ccaaeb322b8f0a4100dc234cfcc8c
+PKG_MIRROR_HASH:=fac4a3e967055bac734bda86c34d318c9bf8dc17b0feb24f556b1d5af57d2896
+
+PKG_MAINTAINER:=Nick Hainke <vincent@systemli.org>
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=COPYING
+
+PKG_BUILD_PARALLEL:=1
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/sipcalc
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=IPv4/IPv6 Calculator
+ URL:=https://github.com/sii/sipcalc
+endef
+
+define Package/sipcalc/description
+ Sipcalc is an advanced ip calculator supporting both IPv4 and IPv6.
+endef
+
+define Package/sipcalc/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/sipcalc $(1)/usr/sbin/sipcalc
+endef
+
+$(eval $(call BuildPackage,sipcalc))
diff --git a/external/subpack/utils/sispmctl/Makefile b/external/subpack/utils/sispmctl/Makefile
new file mode 100644
index 0000000..80da87a
--- /dev/null
+++ b/external/subpack/utils/sispmctl/Makefile
@@ -0,0 +1,69 @@
+#
+# Copyright (C) 2008-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=sispmctl
+PKG_VERSION:=4.8
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_HASH:=0f8391f7e95cbf1fb96a68686a1dcf1e16747b050ae1b8ff90653c99976068db
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libsispmctl
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=Silver Shield PM Control for Linux library
+ URL:=http://sispmctl.sourceforge.net
+ DEPENDS:=+libusb-compat
+endef
+
+define Package/sispmctl
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Silver Shield PM Control for Linux
+ URL:=http://sispmctl.sourceforge.net
+ DEPENDS:=+libsispmctl
+endef
+
+define Package/sispmctl/description
+ The sispmctl tool can control Gembird SIS-PM Silver Shield
+ programmable power outlet strips (also known under the name
+ Revolt Intelli-Plug) from the command line.
+ .
+ It can be used to switch on or off any of the programmable
+ power sockets of the SIS-PM via USB. It can also show the
+ current status of each power socket, and it can handle
+ multiple SIS-PM devices, too.
+endef
+
+CONFIGURE_ARGS += \
+ --enable-webless \
+ --disable-dependency-tracking
+
+define Package/libsispmctl/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libsispmctl.so* $(1)/usr/lib/
+endef
+
+define Package/sispmctl/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/sispmctl $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,libsispmctl))
+$(eval $(call BuildPackage,sispmctl))
diff --git a/external/subpack/utils/slide-switch/Makefile b/external/subpack/utils/slide-switch/Makefile
new file mode 100644
index 0000000..5520bfa
--- /dev/null
+++ b/external/subpack/utils/slide-switch/Makefile
@@ -0,0 +1,74 @@
+#
+# Copyright (C) 2016, 2018-2019, 2022 Jeffery To
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=slide-switch
+PKG_VERSION:=0.9.7
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/jefferyto/openwrt-slide-switch.git
+PKG_MIRROR_HASH:=a0bba3e952179d96667be293a230b2ad26b3bfdd7b01962116f2c99428696bc5
+PKG_SOURCE_VERSION:=$(PKG_VERSION)
+
+PKG_BUILD_PARALLEL:=1
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=Jeffery To <jeffery.to@gmail.com>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/slide-switch
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Translate switch position change to button press
+ URL:=https://github.com/jefferyto/openwrt-slide-switch
+ DEPENDS:=+jshn +jsonfilter
+ PKGARCH:=all
+endef
+
+define Package/slide-switch/description
+slide-switch translates slide switch position changes into normal button
+presses and releases for OpenWrt devices.
+endef
+
+define Package/slide-switch/install
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/button
+ $(INSTALL_DATA) \
+ $(PKG_INSTALL_DIR)/etc/hotplug.d/button/50-slide-switch \
+ $(1)/etc/hotplug.d/button
+
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) \
+ $(PKG_INSTALL_DIR)/etc/init.d/zzz-slide-switch \
+ $(1)/etc/init.d
+
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) \
+ $(PKG_INSTALL_DIR)/usr/sbin/slide-switch \
+ $(1)/usr/sbin
+
+ $(INSTALL_DIR) $(1)/usr/share/slide-switch
+ $(INSTALL_DATA) \
+ $(PKG_INSTALL_DIR)/usr/share/slide-switch/functions.sh \
+ $(PKG_INSTALL_DIR)/usr/share/slide-switch/switch-data.json \
+ $(1)/usr/share/slide-switch
+endef
+
+define Package/slide-switch/postinst
+[ -n "$$IPKG_INSTROOT" ] || /usr/sbin/slide-switch clean
+endef
+
+define Package/slide-switch/prerm
+[ -n "$$IPKG_INSTROOT" ] || /usr/sbin/slide-switch clean
+endef
+
+$(eval $(call BuildPackage,slide-switch))
diff --git a/external/subpack/utils/smartmontools/Makefile b/external/subpack/utils/smartmontools/Makefile
new file mode 100644
index 0000000..bd1b974
--- /dev/null
+++ b/external/subpack/utils/smartmontools/Makefile
@@ -0,0 +1,136 @@
+#
+# Copyright (C) 2006-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/uclibc++.mk
+
+PKG_NAME:=smartmontools
+PKG_VERSION:=7.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/smartmontools
+PKG_HASH:=5cd98a27e6393168bc6aaea070d9e1cd551b0f898c52f66b2ff2e5d274118cd6
+
+PKG_MAINTAINER:=Maxim Storchak <m.storchak@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/smartmontools/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=S.M.A.R.T Monitoring
+ URL:=https://www.smartmontools.org/
+endef
+
+define Package/smartmontools
+ $(call Package/smartmontools/Default)
+ DEPENDS:=$(CXX_DEPENDS)
+ TITLE+= Tool
+endef
+
+define Package/smartmontools/description
+ smartmontools contains utility programs (smartctl) to
+ control/monitor storage systems using the Self-Monitoring, Analysis
+ and Reporting Technology System (S.M.A.R.T.) built into most modern
+ ATA and SCSI disks. It is derived from smartsuite.
+endef
+
+define Package/smartd
+ $(call Package/smartmontools/Default)
+ DEPENDS:=$(CXX_DEPENDS)
+ TITLE+= Daemon
+endef
+
+define Package/smartd/description
+ smartmontools contains utility programs (smartd) to
+ control/monitor storage systems using the Self-Monitoring, Analysis
+ and Reporting Technology System (S.M.A.R.T.) built into most modern
+ ATA and SCSI disks. It is derived from smartsuite.
+endef
+
+define Package/smartmontools-drivedb
+ $(call Package/smartmontools/Default)
+ TITLE+= Drive database
+ PKGARCH=all
+endef
+
+define Package/smartmontools-drivedb/description
+ Database of known drives and USB bridges for smartctl and smartd.
+endef
+
+define Package/smartd-mail
+ $(call Package/smartmontools/Default)
+ TITLE+= Email notifications
+ PKGARCH=all
+ DEPENDS+= +smartd +nail +msmtp-mta
+endef
+
+define Package/smartd-mail/description
+ A script for mailing about SMART issues
+endef
+
+ifeq ($(CONFIG_USE_UCLIBCXX),y)
+TARGET_LDFLAGS +=-nodefaultlibs
+else
+CONFIGURE_VARS += with_cxx11_regex=yes
+endif
+TARGET_LDFLAGS += -flto
+
+TARGET_CXXFLAGS +=-fno-rtti -flto
+MAKE_FLAGS +=BUILD_INFO='"(localbuild)"'
+
+CONFIGURE_ARGS += \
+ --disable-fast-lebe \
+ --without-gnupg \
+ --without-libcap-ng \
+ --without-libsystemd
+
+#lower file size vs. CONFIGURE_ARGS
+CONFIGURE_VARS += \
+ with_smartdplugindir=no \
+ with_systemdenvfile=no \
+ with_systemdsystemunitdir=no \
+ with_update_smart_drivedb=no
+
+define Package/smartmontools/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/smartctl $(1)/usr/sbin/
+endef
+
+define Package/smartd/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/smartd $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_DATA) ./files/smartd.conf $(1)/etc/
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/smartd.init $(1)/etc/init.d/smartd
+endef
+
+define Package/smartmontools-drivedb/install
+ $(INSTALL_DIR) $(1)/usr/share/smartmontools/
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/smartmontools/drivedb.h $(1)/usr/share/smartmontools/
+endef
+
+define Package/smartd-mail/install
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/etc/smartd_warning.sh $(1)/etc
+endef
+
+define Package/smartd/conffiles
+/etc/smartd.conf
+endef
+
+$(eval $(call BuildPackage,smartmontools))
+$(eval $(call BuildPackage,smartd))
+$(eval $(call BuildPackage,smartmontools-drivedb))
+$(eval $(call BuildPackage,smartd-mail))
diff --git a/external/subpack/utils/smartmontools/files/smartd.conf b/external/subpack/utils/smartmontools/files/smartd.conf
new file mode 100644
index 0000000..0740fcf
--- /dev/null
+++ b/external/subpack/utils/smartmontools/files/smartd.conf
@@ -0,0 +1 @@
+/dev/hdb -H
diff --git a/external/subpack/utils/smartmontools/files/smartd.init b/external/subpack/utils/smartmontools/files/smartd.init
new file mode 100644
index 0000000..ae849ad
--- /dev/null
+++ b/external/subpack/utils/smartmontools/files/smartd.init
@@ -0,0 +1,18 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006-2011 OpenWrt.org
+
+START=95
+
+USE_PROCD=1
+PROG=/usr/sbin/smartd
+
+start_service() {
+ procd_open_instance
+ procd_set_param command "$PROG"
+ procd_append_param command -n -q never
+ procd_close_instance
+}
+
+reload_service() {
+ procd_send_signal smartd
+}
diff --git a/external/subpack/utils/smartmontools/patches/001-use-external-drivedb.patch b/external/subpack/utils/smartmontools/patches/001-use-external-drivedb.patch
new file mode 100644
index 0000000..1d3a7b6
--- /dev/null
+++ b/external/subpack/utils/smartmontools/patches/001-use-external-drivedb.patch
@@ -0,0 +1,90 @@
+--- a/knowndrives.cpp
++++ b/knowndrives.cpp
+@@ -40,11 +40,84 @@ const char * knowndrives_cpp_cvsid = "$I
+ // see read_default_drive_databases() below.
+ // The drive_settings structure is described in drivedb.h.
+ const drive_settings builtin_knowndrives[] = {
+-#include "drivedb.h"
++ { "DEFAULT",
++ "-", "-",
++ "Default settings",
++ "-v 1,raw48,Raw_Read_Error_Rate "
++ "-v 2,raw48,Throughput_Performance "
++ "-v 3,raw16(avg16),Spin_Up_Time "
++ "-v 4,raw48,Start_Stop_Count "
++ "-v 5,raw16(raw16),Reallocated_Sector_Ct "
++ "-v 6,raw48,Read_Channel_Margin,HDD "
++ "-v 7,raw48,Seek_Error_Rate,HDD "
++ "-v 8,raw48,Seek_Time_Performance,HDD "
++ "-v 9,raw24(raw8),Power_On_Hours "
++ "-v 10,raw48,Spin_Retry_Count,HDD "
++ "-v 11,raw48,Calibration_Retry_Count,HDD "
++ "-v 12,raw48,Power_Cycle_Count "
++ "-v 13,raw48,Read_Soft_Error_Rate "
++ // 14-174 Unknown_Attribute
++ "-v 175,raw48,Program_Fail_Count_Chip,SSD "
++ "-v 176,raw48,Erase_Fail_Count_Chip,SSD "
++ "-v 177,raw48,Wear_Leveling_Count,SSD "
++ "-v 178,raw48,Used_Rsvd_Blk_Cnt_Chip,SSD "
++ "-v 179,raw48,Used_Rsvd_Blk_Cnt_Tot,SSD "
++ "-v 180,raw48,Unused_Rsvd_Blk_Cnt_Tot,SSD "
++ "-v 181,raw48,Program_Fail_Cnt_Total "
++ "-v 182,raw48,Erase_Fail_Count_Total,SSD "
++ "-v 183,raw48,Runtime_Bad_Block "
++ "-v 184,raw48,End-to-End_Error "
++ // 185-186 Unknown_Attribute
++ "-v 187,raw48,Reported_Uncorrect "
++ "-v 188,raw48,Command_Timeout "
++ "-v 189,raw48,High_Fly_Writes,HDD "
++ "-v 190,tempminmax,Airflow_Temperature_Cel "
++ "-v 191,raw48,G-Sense_Error_Rate,HDD "
++ "-v 192,raw48,Power-Off_Retract_Count "
++ "-v 193,raw48,Load_Cycle_Count,HDD "
++ "-v 194,tempminmax,Temperature_Celsius "
++ "-v 195,raw48,Hardware_ECC_Recovered "
++ "-v 196,raw16(raw16),Reallocated_Event_Count "
++ "-v 197,raw48,Current_Pending_Sector "
++ "-v 198,raw48,Offline_Uncorrectable "
++ "-v 199,raw48,UDMA_CRC_Error_Count "
++ "-v 200,raw48,Multi_Zone_Error_Rate,HDD "
++ "-v 201,raw48,Soft_Read_Error_Rate,HDD "
++ "-v 202,raw48,Data_Address_Mark_Errs,HDD "
++ "-v 203,raw48,Run_Out_Cancel "
++ "-v 204,raw48,Soft_ECC_Correction "
++ "-v 205,raw48,Thermal_Asperity_Rate "
++ "-v 206,raw48,Flying_Height,HDD "
++ "-v 207,raw48,Spin_High_Current,HDD "
++ "-v 208,raw48,Spin_Buzz,HDD "
++ "-v 209,raw48,Offline_Seek_Performnce,HDD "
++ // 210-219 Unknown_Attribute
++ "-v 220,raw48,Disk_Shift,HDD "
++ "-v 221,raw48,G-Sense_Error_Rate,HDD "
++ "-v 222,raw48,Loaded_Hours,HDD "
++ "-v 223,raw48,Load_Retry_Count,HDD "
++ "-v 224,raw48,Load_Friction,HDD "
++ "-v 225,raw48,Load_Cycle_Count,HDD "
++ "-v 226,raw48,Load-in_Time,HDD "
++ "-v 227,raw48,Torq-amp_Count,HDD "
++ "-v 228,raw48,Power-off_Retract_Count "
++ // 229 Unknown_Attribute
++ "-v 230,raw48,Head_Amplitude,HDD "
++ "-v 231,raw48,Temperature_Celsius,HDD "
++ "-v 232,raw48,Available_Reservd_Space "
++ "-v 233,raw48,Media_Wearout_Indicator,SSD "
++ // 234-239 Unknown_Attribute
++ "-v 240,raw24(raw8),Head_Flying_Hours,HDD "
++ "-v 241,raw48,Total_LBAs_Written "
++ "-v 242,raw48,Total_LBAs_Read "
++ // 243-249 Unknown_Attribute
++ "-v 250,raw48,Read_Error_Retry_Rate "
++ // 251-253 Unknown_Attribute
++ "-v 254,raw48,Free_Fall_Sensor,HDD"
++ },
+ };
+
+-const unsigned builtin_knowndrives_size =
+- sizeof(builtin_knowndrives) / sizeof(builtin_knowndrives[0]);
++const unsigned builtin_knowndrives_size = 1;
+
+ /// Drive database class. Stores custom entries read from file.
+ /// Provides transparent access to concatenation of custom and
diff --git a/external/subpack/utils/smartmontools/patches/002-os_mailer-is-mailx.patch b/external/subpack/utils/smartmontools/patches/002-os_mailer-is-mailx.patch
new file mode 100644
index 0000000..b565f80
--- /dev/null
+++ b/external/subpack/utils/smartmontools/patches/002-os_mailer-is-mailx.patch
@@ -0,0 +1,11 @@
+--- a/configure
++++ b/configure
+@@ -6964,7 +6964,7 @@ releaseversion='${PACKAGE}-${VERSION}'
+ # Set platform-specific modules and symbols
+ os_libs=
+ os_dltools='curl wget lynx svn'
+-os_mailer=mail
++os_mailer=mailx
+ os_hostname="'hostname' 'uname -n'"
+ os_dnsdomainname=
+ os_nisdomainname="'domainname'"
diff --git a/external/subpack/utils/smartmontools/test.sh b/external/subpack/utils/smartmontools/test.sh
new file mode 100644
index 0000000..e4f6091
--- /dev/null
+++ b/external/subpack/utils/smartmontools/test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+case "$1" in
+ smartctl|smartd) "$1" -V | head -n 1 | grep "$2" ;;
+esac
diff --git a/external/subpack/utils/sms-tool/Makefile b/external/subpack/utils/sms-tool/Makefile
new file mode 100644
index 0000000..2b3bc92
--- /dev/null
+++ b/external/subpack/utils/sms-tool/Makefile
@@ -0,0 +1,39 @@
+# 2017 - 2021 Cezary Jackiewicz <cezary@eko.one.pl>
+# 2014 lovewilliam <ztong@vt.edu>
+# sms tool for various of 3g/4g modem
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=sms-tool
+PKG_RELEASE:=1
+
+PKG_SOURCE_URL:=https://github.com/obsy/sms_tool
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_DATE:=2023-09-21
+PKG_SOURCE_VERSION:=1b6ca03284fd65db8799dbf7c6224210093786b0
+PKG_MIRROR_HASH:=ea17426c945c29c1361f9e69ae1d980d8bd51a008876111ffb8f55146477bdba
+
+PKG_MAINTAINER:=Andrey Butirsky <butirsky@gmail.com>
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE-2.0.txt
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/sms-tool
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=SMS tool for 3G/4G modems
+ URL:=https://github.com/obsy/sms_tool
+endef
+
+define Package/sms-tool/description
+ SMS Tool for 3G/4G modem
+endef
+
+define Package/sms-tool/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/sms_tool $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,sms-tool))
diff --git a/external/subpack/utils/smstools3/Makefile b/external/subpack/utils/smstools3/Makefile
new file mode 100644
index 0000000..3a63323
--- /dev/null
+++ b/external/subpack/utils/smstools3/Makefile
@@ -0,0 +1,65 @@
+#
+# Copyright (C) 2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=smstools3
+PKG_VERSION:=3.1.21
+PKG_RELEASE:=4
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://smstools3.kekekasvi.com/packages/
+PKG_HASH:=a26ba4c02b16f6cf13177bffca6c9230dc5fefaeba8e3030cd4e4905f6a92084
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+PKG_MAINTAINER:=Harald Geyer <harald@ccbib.org>
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_PARALLEL:=0
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/smstools3
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=SMS Server Tools 3
+ DEPENDS:=$(ICONV_DEPENDS)
+ URL:=http://smstools3.kekekasvi.com/
+endef
+
+define Package/smstools3/description
+ The SMS Server Tools 3 is a SMS Gateway software which can send and receive
+ short messages through GSM modems and mobile phones.
+endef
+
+TARGET_CFLAGS += -D NUMBER_OF_MODEMS=1
+TARGET_CFLAGS += $(if $(ICONV_FULL),-D USE_ICONV)
+TARGET_CFLAGS += -D DISABLE_INET_SOCKET
+TARGET_CFLAGS += -W -Wall
+TARGET_CFLAGS += -D_FILE_OFFSET_BITS=64
+TARGET_CFLAGS += -fcommon
+
+MAKE_VARS += LFLAGS="$(TARGET_LDFLAGS) $(if $(ICONV_FULL),-liconv)"
+
+define Package/smstools3/configure
+endef
+
+define Package/smstools3/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) \
+ $(PKG_BUILD_DIR)/src/smsd \
+ $(PKG_BUILD_DIR)/scripts/sendsms \
+ $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/smstools3.init $(1)/etc/init.d/smstools3
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_CONF) ./files/smstools3.conf $(1)/etc/smsd.conf
+endef
+
+$(eval $(call BuildPackage,smstools3))
diff --git a/external/subpack/utils/smstools3/files/smstools3.conf b/external/subpack/utils/smstools3/files/smstools3.conf
new file mode 100644
index 0000000..da5a36a
--- /dev/null
+++ b/external/subpack/utils/smstools3/files/smstools3.conf
@@ -0,0 +1,24 @@
+#
+# Description: Main configuration file for the smsd
+#
+
+devices = GSM1
+incoming = /var/spool/sms/incoming
+outgoing = /var/spool/sms/outgoing
+checked = /var/spool/sms/checked
+failed = /var/spool/sms/failed
+sent = /var/spool/sms/sent
+receive_before_send = no
+autosplit = 3
+logfile = 1
+loglevel = 5
+
+# Uncomment (and edit) this section to allow smsd to start:
+#
+#[GSM1]
+#init = AT+CPMS="ME","ME","ME"
+#device = /dev/ttyUSB0
+#incoming = yes
+#pin = 0000
+#baudrate = 115200
+
diff --git a/external/subpack/utils/smstools3/files/smstools3.init b/external/subpack/utils/smstools3/files/smstools3.init
new file mode 100644
index 0000000..c036b8a
--- /dev/null
+++ b/external/subpack/utils/smstools3/files/smstools3.init
@@ -0,0 +1,37 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2014-2018 OpenWrt.org
+
+START=94
+
+USE_PROCD=1
+
+# If an unpriviledged user is selected, make sure that next two
+# files are writable by that user:
+PIDFILE="/var/run/smsd.pid"
+INFOFILE="/var/run/smsd.working"
+
+DAEMON=/usr/bin/smsd
+
+# Set/edit this before starting service !!!!!
+WRT_SPOOL=/var/spool
+
+start_service() {
+ echo "Creating minimum spool directories"
+ mkdir -p $WRT_SPOOL
+ mkdir -p $WRT_SPOOL/sms
+ mkdir -p $WRT_SPOOL/sms/incoming
+ mkdir -p $WRT_SPOOL/sms/outgoing
+ mkdir -p $WRT_SPOOL/sms/checked
+ mkdir -p $WRT_SPOOL/sms/failed
+ mkdir -p $WRT_SPOOL/sms/sent
+
+ procd_open_instance
+
+ procd_set_param command $DAEMON -t -n MAINPROCESS -p$PIDFILE -i$INFOFILE
+ procd_set_param respawn
+ procd_set_param stdout 1
+
+ procd_close_instance
+}
+
+
diff --git a/external/subpack/utils/smstools3/patches/002-Makefile.patch b/external/subpack/utils/smstools3/patches/002-Makefile.patch
new file mode 100644
index 0000000..a52aee4
--- /dev/null
+++ b/external/subpack/utils/smstools3/patches/002-Makefile.patch
@@ -0,0 +1,11 @@
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -1,7 +1,7 @@
+ # In case of windows, use os_cygwin=yes setting in the configuration file (smsd.conf).
+
+ # Select your setup size:
+-CFLAGS = -D NUMBER_OF_MODEMS=64
++CFLAGS ?= -D NUMBER_OF_MODEMS=64
+
+ # Uncomment for Solaris
+ # CFLAGS += -D SOLARIS
diff --git a/external/subpack/utils/smstools3/patches/003-bash-ash.patch b/external/subpack/utils/smstools3/patches/003-bash-ash.patch
new file mode 100644
index 0000000..4ad1663
--- /dev/null
+++ b/external/subpack/utils/smstools3/patches/003-bash-ash.patch
@@ -0,0 +1,8 @@
+--- a/scripts/sendsms
++++ b/scripts/sendsms
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/ash
+ # This script send a text sms at the command line by creating
+ # a sms file in the outgoing queue.
+
diff --git a/external/subpack/utils/smstools3/patches/004-modem-processes.patch b/external/subpack/utils/smstools3/patches/004-modem-processes.patch
new file mode 100644
index 0000000..8f0f446
--- /dev/null
+++ b/external/subpack/utils/smstools3/patches/004-modem-processes.patch
@@ -0,0 +1,24 @@
+commit 3790bd05ed86b1692719df22857ef76c1293b01c
+Author: Harald Geyer <harald@ccbib.org>
+Date: Sun Feb 18 19:24:48 2018 +0100
+
+ Make modem processes terminate when main process dies
+
+--- a/src/smsd.c
++++ b/src/smsd.c
+@@ -34,6 +34,7 @@ Either version 2 of the License, or (at
+ #ifndef DISABLE_INOTIFY
+ #include <sys/inotify.h>
+ #endif
++#include <sys/prctl.h>
+
+ #include "extras.h"
+ #include "locking.h"
+@@ -8100,6 +8101,7 @@ int main(int argc,char** argv)
+
+ if (pid == 0)
+ {
++ prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
+ process_id = i;
+ strcpy(process_title, DEVICE.name);
+ apply_process_name(argc, argv, process_title);
diff --git a/external/subpack/utils/sockread/Makefile b/external/subpack/utils/sockread/Makefile
new file mode 100644
index 0000000..d3c15d4
--- /dev/null
+++ b/external/subpack/utils/sockread/Makefile
@@ -0,0 +1,35 @@
+#
+# This software is licensed under the CC0-1.0 license.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=sockread
+PKG_VERSION:=1.0
+PKG_RELEASE:=1
+PKG_LICENSE:=CC0-1.0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/sockread
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=sockread
+ MAINTAINER:=Moritz Warning <moritzwarning@web.de>
+endef
+
+define Package/sockread/description
+ sockread writes and reads data from a Unix domain socket
+ represented as a special file on the file system.
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+endef
+
+define Package/sockread/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/sockread $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,sockread))
diff --git a/external/subpack/utils/sockread/src/Makefile b/external/subpack/utils/sockread/src/Makefile
new file mode 100644
index 0000000..fe4f8a7
--- /dev/null
+++ b/external/subpack/utils/sockread/src/Makefile
@@ -0,0 +1,11 @@
+CC ?= gcc
+CFLAGS ?= -O2 -Wall -pedantic
+CFLAGS += -std=gnu99
+
+.PHONY: clean
+
+sockread:
+ $(CC) $(CFLAGS) main.c -o sockread
+
+clean:
+ rm -f sockread
diff --git a/external/subpack/utils/sockread/src/main.c b/external/subpack/utils/sockread/src/main.c
new file mode 100644
index 0000000..06c21de
--- /dev/null
+++ b/external/subpack/utils/sockread/src/main.c
@@ -0,0 +1,63 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+int main(int argc, char *argv[]) {
+ char buf[1024];
+ ssize_t r;
+
+ if (argc != 2) {
+ fprintf(stderr, "Write to and read from a Unix domain socket.\n\nUsage: %s <socket>\n", argv[0]);
+ return 1;
+ }
+
+ size_t addrlen = strlen(argv[1]);
+
+ /* Allocate enough space for arbitrary-length paths */
+ char addrbuf[offsetof(struct sockaddr_un, sun_path) + addrlen + 1];
+ memset(addrbuf, 0, sizeof(addrbuf));
+
+ struct sockaddr_un *addr = (struct sockaddr_un *)addrbuf;
+ addr->sun_family = AF_UNIX;
+ memcpy(addr->sun_path, argv[1], addrlen+1);
+
+ int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to create socket: %s\n", strerror(errno));
+ return 1;
+ }
+
+ if (connect(fd, (struct sockaddr*)addr, sizeof(addrbuf)) < 0) {
+ fprintf(stderr, "Can't connect to `%s': %s\n", argv[1], strerror(errno));
+ return 1;
+ }
+
+ /* Check if stdin refers to a terminal */
+ if (!isatty(fileno(stdin))) {
+ /* Read from stdin and write to socket */
+ while (0 < (r = fread(buf, 1, sizeof(buf), stdin))) {
+ send(fd, buf, r, 0);
+ }
+ }
+
+ /* Read from socket and write to stdout */
+ while (1) {
+ r = recv(fd, buf, sizeof(buf), 0);
+ if (r < 0) {
+ fprintf(stderr, "read: %s\n", strerror(errno));
+ return 1;
+ }
+
+ if (r == 0)
+ return 0;
+
+ fwrite(buf, r, 1, stdout);
+ }
+
+ return 0;
+}
diff --git a/external/subpack/utils/spi-tools/Makefile b/external/subpack/utils/spi-tools/Makefile
new file mode 100644
index 0000000..804f44c
--- /dev/null
+++ b/external/subpack/utils/spi-tools/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2014-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=spi-tools
+PKG_VERSION:=0.8.6
+PKG_RELEASE:=1
+
+PKG_SOURCE_URL:=https://codeload.github.com/cpb-/spi-tools/tar.gz/$(PKG_VERSION)?
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_HASH:=319ad6ab296111109ea4a820e216cef392429295de7e10e76f7146677337cf09
+
+PKG_MAINTAINER:=John Crispin <blogic@openwrt.org>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+PKG_ASLR_PIE:=0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/spi-tools
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Command line SPI tools
+ URL:=https://github.com/cpb-/spi-tools
+endef
+
+define Package/spi-tools/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/spi-config $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/spi-pipe $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,spi-tools))
diff --git a/external/subpack/utils/squashfs-tools/Config.in b/external/subpack/utils/squashfs-tools/Config.in
new file mode 100644
index 0000000..6d55670
--- /dev/null
+++ b/external/subpack/utils/squashfs-tools/Config.in
@@ -0,0 +1,23 @@
+config SQUASHFS_TOOLS_LZO_SUPPORT
+ depends on PACKAGE_squashfs-tools-mksquashfs || PACKAGE_squashfs-tools-unsquashfs
+ bool "Enable LZO support"
+ select PACKAGE_liblzo
+ default n
+
+config SQUASHFS_TOOLS_LZ4_SUPPORT
+ depends on PACKAGE_squashfs-tools-mksquashfs || PACKAGE_squashfs-tools-unsquashfs
+ bool "Enable LZ4 support"
+ select PACKAGE_liblz4
+ default n
+
+config SQUASHFS_TOOLS_XZ_SUPPORT
+ depends on PACKAGE_squashfs-tools-mksquashfs || PACKAGE_squashfs-tools-unsquashfs
+ bool "Enable XZ support"
+ select PACKAGE_liblzma
+ default n
+
+config SQUASHFS_TOOLS_ZSTD_SUPPORT
+ depends on PACKAGE_squashfs-tools-mksquashfs || PACKAGE_squashfs-tools-unsquashfs
+ bool "Enable ZSTD support"
+ select PACKAGE_libzstd
+ default n
diff --git a/external/subpack/utils/squashfs-tools/Makefile b/external/subpack/utils/squashfs-tools/Makefile
new file mode 100644
index 0000000..e324e90
--- /dev/null
+++ b/external/subpack/utils/squashfs-tools/Makefile
@@ -0,0 +1,96 @@
+#
+# Copyright (C) 2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=squashfs-tools
+PKG_VERSION:=4.5
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=Alexandru Ardelean <ardeleanalex@gmail.com>
+PKG_CPE_ID:=cpe:/a:phillip_lougher:squashfs
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/plougher/squashfs-tools/tar.gz/${PKG_VERSION}?
+PKG_HASH:=b9e16188e6dc1857fe312633920f7d71cc36b0162eb50f3ecb1f0040f02edddd
+
+PKG_BUILD_PARALLEL:=1
+include $(INCLUDE_DIR)/package.mk
+
+define Package/squashfs-tools/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Filesystem
+ TITLE:=Tools to create and extract Squashfs filesystems
+ URL:=https://github.com/plougher/squashfs-tools
+ DEPENDS += +libpthread +zlib \
+ +SQUASHFS_TOOLS_LZO_SUPPORT:liblzo \
+ +SQUASHFS_TOOLS_LZ4_SUPPORT:liblz4 \
+ +SQUASHFS_TOOLS_XZ_SUPPORT:liblzma \
+ +SQUASHFS_TOOLS_ZSTD_SUPPORT:libzstd
+endef
+
+define Package/squashfs-tools-mksquashfs
+ $(call Package/squashfs-tools/Default)
+ TITLE+= mksquashfs
+endef
+
+define Package/squashfs-tools-unsquashfs
+ $(call Package/squashfs-tools/Default)
+ TITLE+= unsquashfs
+endef
+
+define Package/squashfs-tools-unsquashfs/config
+ source "$(SOURCE)/Config.in"
+endef
+
+Build/Configure:=
+
+MAKE_FLAGS += \
+ XATTR_SUPPORT=
+
+ifneq ($(CONFIG_SQUASHFS_TOOLS_XZ_SUPPORT),)
+MAKE_FLAGS += XZ_SUPPORT=1
+endif
+
+ifneq ($(CONFIG_SQUASHFS_TOOLS_LZO_SUPPORT),)
+MAKE_FLAGS += LZO_SUPPORT=1
+endif
+
+ifneq ($(CONFIG_SQUASHFS_TOOLS_LZ4_SUPPORT),)
+MAKE_FLAGS += LZ4_SUPPORT=1
+endif
+
+ifneq ($(CONFIG_SQUASHFS_TOOLS_ZSTD_SUPPORT),)
+MAKE_FLAGS += ZSTD_SUPPORT=1
+endif
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR)/squashfs-tools \
+ CC="$(TARGET_CC)" \
+ EXTRA_CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
+ EXTRA_LDFLAGS="$(TARGET_LDFLAGS)" \
+ $(MAKE_FLAGS) \
+ mksquashfs unsquashfs
+endef
+
+define Package/squashfs-tools-mksquashfs/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/squashfs-tools/mksquashfs $(1)/usr/sbin/mksquashfs
+ $(LN) mksquashfs $(1)/usr/sbin/sqfstar
+endef
+
+define Package/squashfs-tools-unsquashfs/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/squashfs-tools/unsquashfs $(1)/usr/sbin/unsquashfs
+ $(LN) unsquashfs $(1)/usr/sbin/sqfscat
+endef
+
+$(eval $(call BuildPackage,squashfs-tools-mksquashfs))
+$(eval $(call BuildPackage,squashfs-tools-unsquashfs))
diff --git a/external/subpack/utils/ssdeep/Makefile b/external/subpack/utils/ssdeep/Makefile
new file mode 100644
index 0000000..f089756
--- /dev/null
+++ b/external/subpack/utils/ssdeep/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2019 CZ.NIC, z. s. p. o. (https://www.nic.cz/)
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ssdeep
+PKG_VERSION:=2.14.1
+PKG_RELEASE=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/ssdeep-project/ssdeep/releases/download/release-$(PKG_VERSION)/
+PKG_HASH:=ff2eabc78106f009b4fb2def2d76fb0ca9e12acf624cbbfad9b3eb390d931313
+
+PKG_FIXUP:=autoreconf
+PKG_BUILD_PARALLEL:=1
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILES:=COPYING
+PKG_MAINTAINER:=Jan Pavlinec <jan.pavlinec@nic.cz>
+
+include $(INCLUDE_DIR)/uclibc++.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ssdeep
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=A program to compute and match fuzzy hashes
+ URL:=https://ssdeep-project.github.io/ssdeep
+ DEPENDS:=$(CXX_DEPENDS)
+endef
+
+define Package/ssdeep/description
+ ssdeep is a program for computing context triggered piecewise hashes (CTPH). Also called fuzzy hashes, CTPH can match inputs that have homologies.
+endef
+
+define Package/ssdeep/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ssdeep $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,ssdeep))
diff --git a/external/subpack/utils/sshpass/Makefile b/external/subpack/utils/sshpass/Makefile
new file mode 100644
index 0000000..0643314
--- /dev/null
+++ b/external/subpack/utils/sshpass/Makefile
@@ -0,0 +1,37 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=sshpass
+PKG_VERSION:=1.09
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/sshpass
+PKG_HASH:=71746e5e057ffe9b00b44ac40453bf47091930cba96bbea8dc48717dedc49fb7
+
+PKG_MAINTAINER:=Josef Schlehofer <josef.schlehofer@nic.cz>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/sshpass
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Non-interactive ssh password auth
+ URL:=https://sourceforge.net/projects/sshpass/
+endef
+
+define Package/sshpass/description
+ Sshpass is a tool for non-interactively performing password authentication
+ with SSH's so-called "interactive keyboard password authentication". Most user
+ should use SSH's more secure public-key authentication instead.
+endef
+
+define Package/sshpass/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/sshpass $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,sshpass))
diff --git a/external/subpack/utils/stm32flash/Makefile b/external/subpack/utils/stm32flash/Makefile
new file mode 100644
index 0000000..b6f73d9
--- /dev/null
+++ b/external/subpack/utils/stm32flash/Makefile
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2012-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=stm32flash
+PKG_VERSION:=0.5
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_HASH:=97aa9422ef02e82f7da9039329e21a437decf972cb3919ad817f70ac9a49e306
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+PKG_MAINTAINER:=Christian Pointner <equinox@spreadspace.org>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=gpl-2.0.txt
+include $(INCLUDE_DIR)/package.mk
+
+define Package/stm32flash
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Microcontroller programming
+ URL:=https://sourceforge.net/projects/stm32flash
+ TITLE:=Firmware flash tool for STM32's serial bootloader
+endef
+
+define Package/stm32flash/description
+ This tool can be used to burn firmware images to STM32 ARM processors
+ using the built-in serial bootloader.
+endef
+
+define Package/stm32flash/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/stm32flash $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,stm32flash))
diff --git a/external/subpack/utils/stm32flash/patches/100-add_support_for_stm32g4.patch b/external/subpack/utils/stm32flash/patches/100-add_support_for_stm32g4.patch
new file mode 100644
index 0000000..f4ec0db
--- /dev/null
+++ b/external/subpack/utils/stm32flash/patches/100-add_support_for_stm32g4.patch
@@ -0,0 +1,11 @@
+--- a/dev_table.c
++++ b/dev_table.c
+@@ -90,6 +90,8 @@ const stm32_dev_t devices[] = {
+ {0x434, "STM32F469xx" , 0x20003000, 0x20060000, 0x08000000, 0x08200000, 1, f4db , 0x1FFEC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF7800, 0},
+ /* F7 */
+ {0x449, "STM32F74xxx/75xxx" , 0x20004000, 0x20050000, 0x08000000, 0x08100000, 1, f7 , 0x1FFF0000, 0x1FFF001F, 0x1FF00000, 0x1FF0EDC0, 0},
++ /* G4 */
++ {0x468, "STM32G431xx/441xx" , 0x20000000, 0x20004000, 0x08000000, 0x08020000, 1, p_2k , 0x1FFF7800, 0x1FFF780F, 0x1FFF0000, 0x1FFF7000, 0},
+ /* L0 */
+ {0x425, "STM32L031xx/041xx" , 0x20001000, 0x20002000, 0x08000000, 0x08008000, 32, p_128 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF01000, 0},
+ {0x417, "STM32L05xxx/06xxx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 32, p_128 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF01000, 0},
diff --git a/external/subpack/utils/stoken/Makefile b/external/subpack/utils/stoken/Makefile
new file mode 100644
index 0000000..fef8a19
--- /dev/null
+++ b/external/subpack/utils/stoken/Makefile
@@ -0,0 +1,76 @@
+#
+# Copyright (C) 2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=stoken
+PKG_VERSION:=0.92
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/stoken
+PKG_HASH:=aa2b481b058e4caf068f7e747a2dcf5772bcbf278a4f89bc9efcbf82bcc9ef5a
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=LGPL-2.1
+PKG_INSTALL:=1
+
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/stoken/Default
+ TITLE:=tokencode generator compatible with RSA SecurID 128-bit (AES)
+ URL:=https://sourceforge.net/p/stoken/wiki/Home/
+ DEPENDS:= +libxml2 +libnettle
+endef
+
+define Package/stoken
+ $(call Package/stoken/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Encryption
+ DEPENDS:=+libstoken
+ MENU:=1
+endef
+
+define Package/stoken/description
+ stoken is a tokencode generator compatible with RSA SecurID 128-bit (AES). This package contains the cli
+endef
+
+define Package/libstoken
+ $(call Package/stoken/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+endef
+
+TARGET_LDFLAGS += -lz
+
+CONFIGURE_ARGS += \
+ --with-nettle
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libstoken*.{la,a,so*} $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/stoken.pc \
+ $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/stoken/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/stoken $(1)/usr/bin/
+endef
+
+define Package/libstoken/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libstoken*.so* $(1)/usr/lib
+endef
+
+$(eval $(call BuildPackage,stoken))
+$(eval $(call BuildPackage,libstoken))
diff --git a/external/subpack/utils/stress-ng/Makefile b/external/subpack/utils/stress-ng/Makefile
new file mode 100644
index 0000000..a41265a
--- /dev/null
+++ b/external/subpack/utils/stress-ng/Makefile
@@ -0,0 +1,47 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=stress-ng
+PKG_VERSION:=0.18.05
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/ColinIanKing/stress-ng/tar.gz/refs/tags/V$(PKG_VERSION)?
+PKG_HASH:=b0ac75b68bb804fd3276fcb235f1b0a9567090ebd887b2ed0f8a3203f9545e11
+
+PKG_MAINTAINER:=Alexandru Ardelean <ardeleanalex@gmail.com>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/stress-ng
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=stress-ng is a stress test utility
+ URL:=https://github.com/ColinIanKing/stress-ng
+ DEPENDS:=+zlib +libbsd +libaio +libsctp +libkmod +libatomic +libjpeg
+endef
+
+define Package/stress-ng/description
+stress-ng will stress test a computer system in various selectable ways. It
+was designed to exercise various physical subsystems of a computer as well as
+the various operating system kernel interfaces.
+endef
+
+MAKE_FLAGS += \
+ KERNEL=Linux
+
+define Package/stress-ng/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/stress-ng $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,stress-ng))
diff --git a/external/subpack/utils/stress-ng/patches/001-disable-extra-stressors.patch b/external/subpack/utils/stress-ng/patches/001-disable-extra-stressors.patch
new file mode 100644
index 0000000..2e4da9d
--- /dev/null
+++ b/external/subpack/utils/stress-ng/patches/001-disable-extra-stressors.patch
@@ -0,0 +1,17 @@
+--- a/Makefile.config
++++ b/Makefile.config
+@@ -362,10 +362,10 @@ clean:
+ .PHONY: libraries
+ libraries: \
+ configdir \
+- LIB_ACL LIB_AIO LIB_APPARMOR LIB_BSD LIB_CRYPT LIB_DL \
+- LIB_EGL LIB_GBM LIB_GLES2 LIB_GMP LIB_IPSEC_MB LIB_JPEG \
+- LIB_JUDY LIB_KMOD LIB_MD LIB_MPFR LIB_PTHREAD LIB_PTHREAD_SPINLOCK \
+- LIB_RT LIB_SCTP LIB_XXHASH LIB_Z
++ LIB_AIO LIB_APPARMOR LIB_BSD LIB_CRYPT LIB_DL \
++ LIB_IPSEC_MB LIB_JPEG \
++ LIB_JUDY LIB_KMOD LIB_MD LIB_PTHREAD LIB_PTHREAD_SPINLOCK \
++ LIB_RT LIB_SCTP LIB_Z
+
+ LIB_ACL:
+ $(call check,test-libacl,HAVE_LIB_ACL,$(LIB_ACL),$(LIB_ACL))
diff --git a/external/subpack/utils/stress-ng/test.sh b/external/subpack/utils/stress-ng/test.sh
new file mode 100644
index 0000000..0b70f7c
--- /dev/null
+++ b/external/subpack/utils/stress-ng/test.sh
@@ -0,0 +1,3 @@
+#!/bin/sh -e
+
+stress-ng --version | grep "$2"
diff --git a/external/subpack/utils/stress/Makefile b/external/subpack/utils/stress/Makefile
new file mode 100644
index 0000000..8e13158
--- /dev/null
+++ b/external/subpack/utils/stress/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=stress
+PKG_VERSION:=1.0.7
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://github.com/resurrecting-open-source-projects/stress/releases/download/${PKG_VERSION}/
+PKG_HASH:=e63adb57597e617c14ecb0d841b5d990460796d9e9ec69bd56fe645ef02eb239
+
+PKG_MAINTAINER:=Alexandru Ardelean <ardeleanalex@gmail.com>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/stress
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=stress is a simple stress utility
+ URL:=
+endef
+
+define Package/stress/description
+stress is a simple tool that imposes certain types of compute \ stress on
+UNIX-like operating systems.
+endef
+
+define Package/stress/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/stress $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,stress))
diff --git a/external/subpack/utils/stress/patches/010-usleep.patch b/external/subpack/utils/stress/patches/010-usleep.patch
new file mode 100644
index 0000000..02a2201
--- /dev/null
+++ b/external/subpack/utils/stress/patches/010-usleep.patch
@@ -0,0 +1,51 @@
+--- a/src/stress.c
++++ b/src/stress.c
+@@ -266,9 +266,12 @@ main (int argc, char **argv)
+ while ((forks = (do_cpu + do_io + do_vm + do_hdd)))
+ {
+ long long backoff, timeout = 0;
++ struct timespec b;
+
+ /* Calculate the backoff value so we get good fork throughput. */
+ backoff = do_backoff * forks;
++ b.tv_sec = backoff / 1000000;
++ b.tv_nsec = (backoff % 1000000) * 1000;
+ dbg (stdout, "using backoff sleep of %llius\n", backoff);
+
+ /* If we are supposed to respect a timeout, calculate it. */
+@@ -304,7 +307,7 @@ main (int argc, char **argv)
+ case 0: /* child */
+ worker_init();
+ alarm (timeout);
+- usleep (backoff);
++ nanosleep (&b, NULL);
+ if (do_dryrun)
+ exit (0);
+ exit (hogcpu ());
+@@ -326,7 +329,7 @@ main (int argc, char **argv)
+ case 0: /* child */
+ worker_init();
+ alarm (timeout);
+- usleep (backoff);
++ nanosleep (&b, NULL);
+ if (do_dryrun)
+ exit (0);
+ exit (hogio ());
+@@ -347,7 +350,7 @@ main (int argc, char **argv)
+ case 0: /* child */
+ worker_init();
+ alarm (timeout);
+- usleep (backoff);
++ nanosleep (&b, NULL);
+ if (do_dryrun)
+ exit (0);
+ exit (hogvm (do_vm_bytes, do_vm_stride, do_vm_hang, do_vm_keep));
+@@ -368,7 +371,7 @@ main (int argc, char **argv)
+ case 0: /* child */
+ worker_init();
+ alarm (timeout);
+- usleep (backoff);
++ nanosleep (&b, NULL);
+ if (do_dryrun)
+ exit (0);
+ exit (hoghdd (do_hdd_bytes));
diff --git a/external/subpack/utils/stressapptest/Makefile b/external/subpack/utils/stressapptest/Makefile
new file mode 100644
index 0000000..a0fe614
--- /dev/null
+++ b/external/subpack/utils/stressapptest/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2007-2018 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=stressapptest
+PKG_VERSION:=1
+PKG_RELEASE:=9
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/stressapptest
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=stressapptest tool for linux
+ DEPENDS:= +libpthread +libstdcpp
+ DEFAULT:=y
+endef
+
+define Package/stressapptest/description
+ This package contains the stressapptest for linux
+endef
+
+define Build/Prepare
+ mkdir -p $(PKG_BUILD_DIR)
+ cp -r ./src/* $(PKG_BUILD_DIR)/
+endef
+
+CONFIGURE_VARS += CC="$(TARGET_CROSS)gcc"
+CONFIGURE_VARS += CXX="$(TARGET_CROSS)g++"
+
+define Package/stressapptest/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/stressapptest $(1)/usr/sbin/stresstest
+endef
+
+$(eval $(call BuildPackage,stressapptest))
diff --git a/external/subpack/utils/stressapptest/src/COPYING b/external/subpack/utils/stressapptest/src/COPYING
new file mode 100644
index 0000000..8b9312d
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/COPYING
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2008 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/external/subpack/utils/stressapptest/src/MODULE_LICENSE_APACHE2 b/external/subpack/utils/stressapptest/src/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/MODULE_LICENSE_APACHE2
diff --git a/external/subpack/utils/stressapptest/src/Makefile.am b/external/subpack/utils/stressapptest/src/Makefile.am
new file mode 100644
index 0000000..5b1998f
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = src
+dist_man_MANS = stressapptest.1
+
diff --git a/external/subpack/utils/stressapptest/src/Makefile.in b/external/subpack/utils/stressapptest/src/Makefile.in
new file mode 100644
index 0000000..e0386c7
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/Makefile.in
@@ -0,0 +1,754 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = .
+DIST_COMMON = $(am__configure_deps) $(dist_man_MANS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/configure COPYING config.guess config.sub \
+ depcomp install-sh missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/stressapptest_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+man1dir = $(mandir)/man1
+am__installdirs = "$(DESTDIR)$(man1dir)"
+NROFF = nroff
+MANS = $(dist_man_MANS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir dist dist-all distcheck
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d "$(distdir)" \
+ || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr "$(distdir)"; }; }
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = src
+dist_man_MANS = stressapptest.1
+all: all-recursive
+
+.SUFFIXES:
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+install-man1: $(dist_man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
+ @list=''; test -n "$(man1dir)" || exit 0; \
+ { for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.1[a-z]*$$/p'; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man1dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.1[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ test -z "$$files" || { \
+ echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(man1dir)" && rm -f $$files; }
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @list='$(MANS)'; if test -n "$$list"; then \
+ list=`for p in $$list; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
+ if test -n "$$list" && \
+ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
+ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
+ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
+ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
+ echo " typically \`make maintainer-clean' will remove them" >&2; \
+ exit 1; \
+ else :; fi; \
+ else :; fi
+ $(am__remove_distdir)
+ test -d "$(distdir)" || mkdir "$(distdir)"
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ -test -n "$(am__skip_mode_fix)" \
+ || find "$(distdir)" -type d ! -perm -755 \
+ -exec chmod u+rwx,go+rx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-lzma: distdir
+ tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+ $(am__remove_distdir)
+
+dist-xz: distdir
+ tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lzma*) \
+ lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
+ *.tar.xz*) \
+ xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ test -d $(distdir)/_build || exit 0; \
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && am__cwd=`pwd` \
+ && $(am__cd) $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+ && cd "$$am__cwd" \
+ || exit 1
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @$(am__cd) '$(distuninstallcheck_dir)' \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(MANS)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(man1dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man: install-man1
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-man
+
+uninstall-man: uninstall-man1
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am am--refresh check check-am clean clean-generic \
+ ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
+ dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \
+ distclean distclean-generic distclean-tags distcleancheck \
+ distdir distuninstallcheck dvi dvi-am html html-am info \
+ info-am install install-am install-data install-data-am \
+ install-dvi install-dvi-am install-exec install-exec-am \
+ install-html install-html-am install-info install-info-am \
+ install-man install-man1 install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+ uninstall-man uninstall-man1
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/external/subpack/utils/stressapptest/src/README.md b/external/subpack/utils/stressapptest/src/README.md
new file mode 100644
index 0000000..d7b3f96
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/README.md
@@ -0,0 +1,104 @@
+# stressapptest
+Stressful Application Test (or stressapptest, its unix name) is a memory interface test.
+It tries to maximize randomized traffic to memory from processor and I/O, with the intent of creating a realistic high load situation in order to test the existing hardware devices in a computer. It has been used at Google for some time and now it is available under the apache 2.0 license.
+
+ (Exported from code.google.com/p/stressapptest)
+
+Discussion group: https://groups.google.com/d/forum/stressapptest-discuss
+
+
+## Usage
+
+To execute, a typical command would be:
+```
+./stressapptest -s 20 -M 256 -m 8 -W # Test 256MB, running 8 "warm copy" threads. Exit after 20 seconds.
+./stressapptest --help # list the available arguments.
+```
+Common arguments
+* -M mbytes : megabytes of ram to test (auto-detect all memory available)
+* -s seconds : number of seconds to run (20)
+* -m threads : number of memory copy threads to run (auto-detect to number of CPUs)
+* -W : Use more CPU-stressful memory copy (false)
+* -n ipaddr : add a network thread connecting to system at 'ipaddr'. (none)
+* --listen : run a thread to listen for and respond to network threads. (0)
+* -f filename : add a disk thread with tempfile 'filename' (none)
+* -F : don't result check each transaction, use libc memcpy instead. (false)
+
+Error handling
+* -l logfile : log output to file 'logfile' (none)
+* -v level : verbosity (0-20) (default: 8)
+
+```
+./stressapptest -s 20 -M 256 -m 8 -C 8 -W # Allocate 256MB of memory and run 8 "warm copy" threads, and 8 cpu load threads. Exit after 20 seconds.
+./stressapptest -f /tmp/file1 -f /tmp/file2 # Run 2 file IO threads, and autodetect memory size and core count to select allocated memory and memory copy threads.
+```
+
+
+## Installation
+
+stressapptest is often available on linux and can be installed as a distro package:
+```
+sudo apt-get install stressapptest
+sudo emerge stressaptest
+sudo yum install stressapptest
+sudo zypper install stressapptest
+```
+To build from source, the build/installation package follows the GNU guidelines. So, to download the latest package:
+```
+git clone https://github.com/stressapptest/stressapptest.git
+cd stressapptest
+./configure
+make
+sudo make install
+```
+And it should be installed. You can use the most common options on the configure script, it was generated by autoconf and automake, so they are accepted.
+
+
+## Objective
+
+Stressful Application Test (or stressapptest) tries to maximize randomized traffic to memory from processor and I/O, with the intent of creating a realistic high load situation.
+
+stressapptest may be used for various purposes:
+* Stress test: as described here.
+* Hardware qualification and debugging.
+* Memory interface test: see the Theory behind this.
+* Disk testing.
+
+
+**Background**
+
+Many hardware issues reproduce infrequently, or only under corner cases. The theory being used here is that by maximizing bus and memory traffic, the number of transactions is increased, and therefore the probability of failing a transaction is increased.
+
+
+**Overview**
+
+stressapptest is a userspace test, primarily composed of threads doing memory copies and directIO disk read/write. It allocates a large block of memory (typically 85% of the total memory on the machine), and each thread will choose randomized blocks of memory to copy, or to write to disk. Typically there are two threads per processor, and two threads for each disk. Result checking is done as the test proceeds by CRCing the data as it is copied.
+
+
+**Detailed Design**
+
+The code is structured fairly simply:
+
+A large amount of memory is allocated in a single block (default is 85% of physical memory size).
+Memory is divided into chunks, each filled with a potentially stressful data pattern.
+Worker threads are spawned, which draw pages from an "empty" queue and a "valid" queue, and copy the data from one block to the other.
+Some threads memory copy the data.
+Some threads invert the data in place.
+Some threads write the data to disk, and read it to the new location.
+After the specified time has elapsed, all "valid" pages have their data compared with the original fill pattern.
+
+
+**Caveats**
+
+This test works by stressing system interfaces. It is good at catching memory signal integrity or setup and hold problems, memory controller and bus interface issues, and disk controller issues. It is moderately good at catching bad memory cells and cache coherency issues. It is not good at catching bad processors, bad physical media on disks, or problems that require periods of inactivity to manifest themselves. It is not a thorough test of OS internals. The test may cause marginal systems to become bricks if disk or memory errors cause hard drive corruption, or if the physical components overheat.
+
+
+**Security Considerations**
+
+Someone running stressapptest on a live system could cause other applications to become extremely slow or unresponsive.
+
+
+**Logged information**
+
+stressapptest can output a logfile of miscompares detected during its execution. stressapptest cannot yet log reboot failures, or other failures not visible to user space.
+
diff --git a/external/subpack/utils/stressapptest/src/aclocal.m4 b/external/subpack/utils/stressapptest/src/aclocal.m4
new file mode 100644
index 0000000..e9b7b28
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/aclocal.m4
@@ -0,0 +1,951 @@
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.65],,
+[m4_warning([this file was generated for autoconf 2.65.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.11'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.11.1], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.11.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 10
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], UPC, [depcc="$UPC" am_compiler_list=],
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ am__universal=false
+ m4_case([$1], [CC],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac],
+ [CXX],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac])
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 5
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+ # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 16
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.62])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES(OBJC)],
+ [define([AC_PROG_OBJC],
+ defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
+dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+ [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+])
+
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+ [[\\/$]]* | ?:[[\\/]]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[[\\\"\#\$\&\'\`$am_lf]]*)
+ AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+ *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
+ AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
diff --git a/external/subpack/utils/stressapptest/src/compile b/external/subpack/utils/stressapptest/src/compile
new file mode 100755
index 0000000..49b3d05
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/compile
@@ -0,0 +1,351 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand '-c -o'.
+
+scriptversion=2024-06-19.01; # UTC
+
+# Copyright (C) 1999-2024 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+nl='
+'
+
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent tools from complaining about whitespace usage.
+IFS=" "" $nl"
+
+file_conv=
+
+# func_file_conv build_file lazy
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts. If the determined conversion
+# type is listed in (the comma separated) LAZY, no conversion will
+# take place.
+func_file_conv ()
+{
+ file=$1
+ case $file in
+ / | /[!/]*) # absolute file, and not a UNC file
+ if test -z "$file_conv"; then
+ # lazily determine how to convert abs files
+ case `uname -s` in
+ MINGW*)
+ file_conv=mingw
+ ;;
+ CYGWIN* | MSYS*)
+ file_conv=cygwin
+ ;;
+ *)
+ file_conv=wine
+ ;;
+ esac
+ fi
+ case $file_conv/,$2, in
+ *,$file_conv,*)
+ ;;
+ mingw/*)
+ file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+ ;;
+ cygwin/* | msys/*)
+ file=`cygpath -m "$file" || echo "$file"`
+ ;;
+ wine/*)
+ file=`winepath -w "$file" || echo "$file"`
+ ;;
+ esac
+ ;;
+ esac
+}
+
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+ func_file_conv "$1"
+ if test -z "$lib_path"; then
+ lib_path=$file
+ else
+ lib_path="$lib_path;$file"
+ fi
+ linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+ lib=$1
+ found=no
+ save_IFS=$IFS
+ IFS=';'
+ for dir in $lib_path $LIB
+ do
+ IFS=$save_IFS
+ if $shared && test -f "$dir/$lib.dll.lib"; then
+ found=yes
+ lib=$dir/$lib.dll.lib
+ break
+ fi
+ if test -f "$dir/$lib.lib"; then
+ found=yes
+ lib=$dir/$lib.lib
+ break
+ fi
+ if test -f "$dir/lib$lib.a"; then
+ found=yes
+ lib=$dir/lib$lib.a
+ break
+ fi
+ done
+ IFS=$save_IFS
+
+ if test "$found" != yes; then
+ lib=$lib.lib
+ fi
+}
+
+# func_cl_wrapper cl arg...
+# Adjust compile command to suit cl
+func_cl_wrapper ()
+{
+ # Assume a capable shell
+ lib_path=
+ shared=:
+ linker_opts=
+ for arg
+ do
+ if test -n "$eat"; then
+ eat=
+ else
+ case $1 in
+ -o)
+ # configure might choose to run compile as 'compile cc -o foo foo.c'.
+ eat=1
+ case $2 in
+ *.o | *.lo | *.[oO][bB][jJ])
+ func_file_conv "$2"
+ set x "$@" -Fo"$file"
+ shift
+ ;;
+ *)
+ func_file_conv "$2"
+ set x "$@" -Fe"$file"
+ shift
+ ;;
+ esac
+ ;;
+ -I)
+ eat=1
+ func_file_conv "$2" mingw
+ set x "$@" -I"$file"
+ shift
+ ;;
+ -I*)
+ func_file_conv "${1#-I}" mingw
+ set x "$@" -I"$file"
+ shift
+ ;;
+ -l)
+ eat=1
+ func_cl_dashl "$2"
+ set x "$@" "$lib"
+ shift
+ ;;
+ -l*)
+ func_cl_dashl "${1#-l}"
+ set x "$@" "$lib"
+ shift
+ ;;
+ -L)
+ eat=1
+ func_cl_dashL "$2"
+ ;;
+ -L*)
+ func_cl_dashL "${1#-L}"
+ ;;
+ -static)
+ shared=false
+ ;;
+ -Wl,*)
+ arg=${1#-Wl,}
+ save_ifs="$IFS"; IFS=','
+ for flag in $arg; do
+ IFS="$save_ifs"
+ linker_opts="$linker_opts $flag"
+ done
+ IFS="$save_ifs"
+ ;;
+ -Xlinker)
+ eat=1
+ linker_opts="$linker_opts $2"
+ ;;
+ -*)
+ set x "$@" "$1"
+ shift
+ ;;
+ *.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
+ func_file_conv "$1"
+ set x "$@" -Tp"$file"
+ shift
+ ;;
+ *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
+ func_file_conv "$1" mingw
+ set x "$@" "$file"
+ shift
+ ;;
+ *)
+ set x "$@" "$1"
+ shift
+ ;;
+ esac
+ fi
+ shift
+ done
+ if test -n "$linker_opts"; then
+ linker_opts="-link$linker_opts"
+ fi
+ exec "$@" $linker_opts
+ exit 1
+}
+
+eat=
+
+case $1 in
+ '')
+ echo "$0: No command. Try '$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand '-c -o'.
+Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file 'INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+GNU Automake home page: <https://www.gnu.org/software/automake/>.
+General help using GNU software: <https://www.gnu.org/gethelp/>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "compile (GNU Automake) $scriptversion"
+ exit $?
+ ;;
+ cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
+ clang-cl | *[/\\]clang-cl | clang-cl.exe | *[/\\]clang-cl.exe | \
+ icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
+ func_cl_wrapper "$@" # Doesn't return...
+ ;;
+esac
+
+ofile=
+cfile=
+
+for arg
+do
+ if test -n "$eat"; then
+ eat=
+ else
+ case $1 in
+ -o)
+ # configure might choose to run compile as 'compile cc -o foo foo.c'.
+ # So we strip '-o arg' only if arg is an object.
+ eat=1
+ case $2 in
+ *.o | *.obj)
+ ofile=$2
+ ;;
+ *)
+ set x "$@" -o "$2"
+ shift
+ ;;
+ esac
+ ;;
+ *.c)
+ cfile=$1
+ set x "$@" "$1"
+ shift
+ ;;
+ *)
+ set x "$@" "$1"
+ shift
+ ;;
+ esac
+ fi
+ shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+ # If no '-o' option was seen then we might have been invoked from a
+ # pattern rule where we don't need one. That is ok -- this is a
+ # normal compilation that the losing compiler can handle. If no
+ # '.c' file was seen then we are probably linking. That is also
+ # ok.
+ exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use '[/\\:.-]' here to ensure that we don't use the same name
+# that we are using for the .o file. Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
+while true; do
+ if mkdir "$lockdir" >/dev/null 2>&1; then
+ break
+ fi
+ sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+ test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+ test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/external/subpack/utils/stressapptest/src/config.guess b/external/subpack/utils/stressapptest/src/config.guess
new file mode 100755
index 0000000..b187213
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/config.guess
@@ -0,0 +1,1803 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright 1992-2023 Free Software Foundation, Inc.
+
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2023-07-20'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
+#
+# Please send patches to <config-patches@gnu.org>.
+
+
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX. However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system '$me' is run on.
+
+Options:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2023 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try '$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+# Just in case it came from the environment.
+GUESS=
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still
+# use 'HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+tmp=
+# shellcheck disable=SC2172
+trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
+
+set_cc_for_build() {
+ # prevent multiple calls if $tmp is already set
+ test "$tmp" && return 0
+ : "${TMPDIR=/tmp}"
+ # shellcheck disable=SC2039,SC3028
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
+ dummy=$tmp/dummy
+ case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
+ ,,) echo "int x;" > "$dummy.c"
+ for driver in cc gcc c89 c99 ; do
+ if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
+ CC_FOR_BUILD=$driver
+ break
+ fi
+ done
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+ esac
+}
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if test -f /.attbin/uname ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case $UNAME_SYSTEM in
+Linux|GNU|GNU/*)
+ LIBC=unknown
+
+ set_cc_for_build
+ cat <<-EOF > "$dummy.c"
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #elif defined(__GLIBC__)
+ LIBC=gnu
+ #else
+ #include <stdarg.h>
+ /* First heuristic to detect musl libc. */
+ #ifdef __DEFINED_va_list
+ LIBC=musl
+ #endif
+ #endif
+ EOF
+ cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ eval "$cc_set_libc"
+
+ # Second heuristic to detect musl libc.
+ if [ "$LIBC" = unknown ] &&
+ command -v ldd >/dev/null &&
+ ldd --version 2>&1 | grep -q ^musl; then
+ LIBC=musl
+ fi
+
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ if [ "$LIBC" = unknown ]; then
+ LIBC=gnu
+ fi
+ ;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+ echo unknown)`
+ case $UNAME_MACHINE_ARCH in
+ aarch64eb) machine=aarch64_be-unknown ;;
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ earmv*)
+ arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine=${arch}${endian}-unknown
+ ;;
+ *) machine=$UNAME_MACHINE_ARCH-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently (or will in the future) and ABI.
+ case $UNAME_MACHINE_ARCH in
+ earm*)
+ os=netbsdelf
+ ;;
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # Determine ABI tags.
+ case $UNAME_MACHINE_ARCH in
+ earm*)
+ expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+ abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case $UNAME_VERSION in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ GUESS=$machine-${os}${release}${abi-}
+ ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE
+ ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE
+ ;;
+ *:SecBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE
+ ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE
+ ;;
+ *:MidnightBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE
+ ;;
+ *:ekkoBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE
+ ;;
+ *:SolidBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE
+ ;;
+ *:OS108:*:*)
+ GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE
+ ;;
+ macppc:MirBSD:*:*)
+ GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE
+ ;;
+ *:MirBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE
+ ;;
+ *:Sortix:*:*)
+ GUESS=$UNAME_MACHINE-unknown-sortix
+ ;;
+ *:Twizzler:*:*)
+ GUESS=$UNAME_MACHINE-unknown-twizzler
+ ;;
+ *:Redox:*:*)
+ GUESS=$UNAME_MACHINE-unknown-redox
+ ;;
+ mips:OSF1:*.*)
+ GUESS=mips-dec-osf1
+ ;;
+ alpha:OSF1:*:*)
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ trap '' 0
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case $ALPHA_CPU_TYPE in
+ "EV4 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE=alpha ;;
+ "EV5 (21164)")
+ UNAME_MACHINE=alphaev5 ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE=alphaev56 ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE=alphapca56 ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE=alphapca57 ;;
+ "EV6 (21264)")
+ UNAME_MACHINE=alphaev6 ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE=alphaev67 ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE=alphaev69 ;;
+ "EV7 (21364)")
+ UNAME_MACHINE=alphaev7 ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE=alphaev79 ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ GUESS=$UNAME_MACHINE-dec-osf$OSF_REL
+ ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ GUESS=m68k-unknown-sysv4
+ ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ GUESS=$UNAME_MACHINE-unknown-amigaos
+ ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ GUESS=$UNAME_MACHINE-unknown-morphos
+ ;;
+ *:OS/390:*:*)
+ GUESS=i370-ibm-openedition
+ ;;
+ *:z/VM:*:*)
+ GUESS=s390-ibm-zvmoe
+ ;;
+ *:OS400:*:*)
+ GUESS=powerpc-ibm-os400
+ ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ GUESS=arm-acorn-riscix$UNAME_RELEASE
+ ;;
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
+ GUESS=arm-unknown-riscos
+ ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ GUESS=hppa1.1-hitachi-hiuxmpp
+ ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ case `(/bin/universe) 2>/dev/null` in
+ att) GUESS=pyramid-pyramid-sysv3 ;;
+ *) GUESS=pyramid-pyramid-bsd ;;
+ esac
+ ;;
+ NILE*:*:*:dcosx)
+ GUESS=pyramid-pyramid-svr4
+ ;;
+ DRS?6000:unix:4.0:6*)
+ GUESS=sparc-icl-nx6
+ ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) GUESS=sparc-icl-nx7 ;;
+ esac
+ ;;
+ s390x:SunOS:*:*)
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL
+ ;;
+ sun4H:SunOS:5.*:*)
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-hal-solaris2$SUN_REL
+ ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-sun-solaris2$SUN_REL
+ ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ GUESS=i386-pc-auroraux$UNAME_RELEASE
+ ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ set_cc_for_build
+ SUN_ARCH=i386
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH=x86_64
+ fi
+ fi
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=$SUN_ARCH-pc-solaris2$SUN_REL
+ ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-sun-solaris3$SUN_REL
+ ;;
+ sun4*:SunOS:*:*)
+ case `/usr/bin/arch -k` in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like '4.1.3-JL'.
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
+ GUESS=sparc-sun-sunos$SUN_REL
+ ;;
+ sun3*:SunOS:*:*)
+ GUESS=m68k-sun-sunos$UNAME_RELEASE
+ ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
+ case `/bin/arch` in
+ sun3)
+ GUESS=m68k-sun-sunos$UNAME_RELEASE
+ ;;
+ sun4)
+ GUESS=sparc-sun-sunos$UNAME_RELEASE
+ ;;
+ esac
+ ;;
+ aushp:SunOS:*:*)
+ GUESS=sparc-auspex-sunos$UNAME_RELEASE
+ ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ GUESS=m68k-milan-mint$UNAME_RELEASE
+ ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ GUESS=m68k-hades-mint$UNAME_RELEASE
+ ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ GUESS=m68k-unknown-mint$UNAME_RELEASE
+ ;;
+ m68k:machten:*:*)
+ GUESS=m68k-apple-machten$UNAME_RELEASE
+ ;;
+ powerpc:machten:*:*)
+ GUESS=powerpc-apple-machten$UNAME_RELEASE
+ ;;
+ RISC*:Mach:*:*)
+ GUESS=mips-dec-mach_bsd4.3
+ ;;
+ RISC*:ULTRIX:*:*)
+ GUESS=mips-dec-ultrix$UNAME_RELEASE
+ ;;
+ VAX*:ULTRIX*:*:*)
+ GUESS=vax-dec-ultrix$UNAME_RELEASE
+ ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ GUESS=clipper-intergraph-clix$UNAME_RELEASE
+ ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
+ dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ GUESS=mips-mips-riscos$UNAME_RELEASE
+ ;;
+ Motorola:PowerMAX_OS:*:*)
+ GUESS=powerpc-motorola-powermax
+ ;;
+ Motorola:*:4.3:PL8-*)
+ GUESS=powerpc-harris-powermax
+ ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ GUESS=powerpc-harris-powermax
+ ;;
+ Night_Hawk:Power_UNIX:*:*)
+ GUESS=powerpc-harris-powerunix
+ ;;
+ m88k:CX/UX:7*:*)
+ GUESS=m88k-harris-cxux7
+ ;;
+ m88k:*:4*:R4*)
+ GUESS=m88k-motorola-sysv4
+ ;;
+ m88k:*:3*:R3*)
+ GUESS=m88k-motorola-sysv3
+ ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
+ then
+ if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
+ test "$TARGET_BINARY_INTERFACE"x = x
+ then
+ GUESS=m88k-dg-dgux$UNAME_RELEASE
+ else
+ GUESS=m88k-dg-dguxbcs$UNAME_RELEASE
+ fi
+ else
+ GUESS=i586-dg-dgux$UNAME_RELEASE
+ fi
+ ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ GUESS=m88k-dolphin-sysv3
+ ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ GUESS=m88k-motorola-sysv3
+ ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ GUESS=m88k-tektronix-sysv3
+ ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ GUESS=m68k-tektronix-bsd
+ ;;
+ *:IRIX*:*:*)
+ IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'`
+ GUESS=mips-sgi-irix$IRIX_REL
+ ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ GUESS=i386-ibm-aix
+ ;;
+ ia64:AIX:*:*)
+ if test -x /usr/bin/oslevel ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
+ fi
+ GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV
+ ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
+ then
+ GUESS=$SYSTEM_NAME
+ else
+ GUESS=rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ GUESS=rs6000-ibm-aix3.2.4
+ else
+ GUESS=rs6000-ibm-aix3.2
+ fi
+ ;;
+ *:AIX:*:[4567])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if test -x /usr/bin/lslpp ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+ else
+ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
+ fi
+ GUESS=$IBM_ARCH-ibm-aix$IBM_REV
+ ;;
+ *:AIX:*:*)
+ GUESS=rs6000-ibm-aix
+ ;;
+ ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
+ GUESS=romp-ibm-bsd4.4
+ ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to
+ ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ GUESS=rs6000-bull-bosx
+ ;;
+ DPX/2?00:B.O.S.:*:*)
+ GUESS=m68k-bull-sysv3
+ ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ GUESS=m68k-hp-bsd
+ ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ GUESS=m68k-hp-bsd4.4
+ ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+ case $UNAME_MACHINE in
+ 9000/31?) HP_ARCH=m68000 ;;
+ 9000/[34]??) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if test -x /usr/bin/getconf; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case $sc_cpu_version in
+ 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case $sc_kernel_bits in
+ 32) HP_ARCH=hppa2.0n ;;
+ 64) HP_ARCH=hppa2.0w ;;
+ '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if test "$HP_ARCH" = ""; then
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if test "$HP_ARCH" = hppa2.0w
+ then
+ set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH=hppa2.0w
+ else
+ HP_ARCH=hppa64
+ fi
+ fi
+ GUESS=$HP_ARCH-hp-hpux$HPUX_REV
+ ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+ GUESS=ia64-hp-hpux$HPUX_REV
+ ;;
+ 3050*:HI-UX:*:*)
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ GUESS=unknown-hitachi-hiuxwe2
+ ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
+ GUESS=hppa1.1-hp-bsd
+ ;;
+ 9000/8??:4.3bsd:*:*)
+ GUESS=hppa1.0-hp-bsd
+ ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ GUESS=hppa1.0-hp-mpeix
+ ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
+ GUESS=hppa1.1-hp-osf
+ ;;
+ hp8??:OSF1:*:*)
+ GUESS=hppa1.0-hp-osf
+ ;;
+ i*86:OSF1:*:*)
+ if test -x /usr/sbin/sysversion ; then
+ GUESS=$UNAME_MACHINE-unknown-osf1mk
+ else
+ GUESS=$UNAME_MACHINE-unknown-osf1
+ fi
+ ;;
+ parisc*:Lites*:*:*)
+ GUESS=hppa1.1-hp-lites
+ ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ GUESS=c1-convex-bsd
+ ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ GUESS=c34-convex-bsd
+ ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ GUESS=c38-convex-bsd
+ ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ GUESS=c4-convex-bsd
+ ;;
+ CRAY*Y-MP:*:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=ymp-cray-unicos$CRAY_REL
+ ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=t90-cray-unicos$CRAY_REL
+ ;;
+ CRAY*T3E:*:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=alphaev5-cray-unicosmk$CRAY_REL
+ ;;
+ CRAY*SV1:*:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=sv1-cray-unicos$CRAY_REL
+ ;;
+ *:UNICOS/mp:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=craynv-cray-unicosmp$CRAY_REL
+ ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
+ GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+ ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+ ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE
+ ;;
+ sparc*:BSD/OS:*:*)
+ GUESS=sparc-unknown-bsdi$UNAME_RELEASE
+ ;;
+ *:BSD/OS:*:*)
+ GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE
+ ;;
+ arm:FreeBSD:*:*)
+ UNAME_PROCESSOR=`uname -p`
+ set_cc_for_build
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi
+ else
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf
+ fi
+ ;;
+ *:FreeBSD:*:*)
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case $UNAME_PROCESSOR in
+ amd64)
+ UNAME_PROCESSOR=x86_64 ;;
+ i386)
+ UNAME_PROCESSOR=i586 ;;
+ esac
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL
+ ;;
+ i*:CYGWIN*:*)
+ GUESS=$UNAME_MACHINE-pc-cygwin
+ ;;
+ *:MINGW64*:*)
+ GUESS=$UNAME_MACHINE-pc-mingw64
+ ;;
+ *:MINGW*:*)
+ GUESS=$UNAME_MACHINE-pc-mingw32
+ ;;
+ *:MSYS*:*)
+ GUESS=$UNAME_MACHINE-pc-msys
+ ;;
+ i*:PW*:*)
+ GUESS=$UNAME_MACHINE-pc-pw32
+ ;;
+ *:SerenityOS:*:*)
+ GUESS=$UNAME_MACHINE-pc-serenity
+ ;;
+ *:Interix*:*)
+ case $UNAME_MACHINE in
+ x86)
+ GUESS=i586-pc-interix$UNAME_RELEASE
+ ;;
+ authenticamd | genuineintel | EM64T)
+ GUESS=x86_64-unknown-interix$UNAME_RELEASE
+ ;;
+ IA64)
+ GUESS=ia64-unknown-interix$UNAME_RELEASE
+ ;;
+ esac ;;
+ i*:UWIN*:*)
+ GUESS=$UNAME_MACHINE-pc-uwin
+ ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ GUESS=x86_64-pc-cygwin
+ ;;
+ prep*:SunOS:5.*:*)
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=powerpcle-unknown-solaris2$SUN_REL
+ ;;
+ *:GNU:*:*)
+ # the GNU system
+ GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'`
+ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'`
+ GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL
+ ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"`
+ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
+ ;;
+ x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*)
+ GUESS="$UNAME_MACHINE-pc-managarm-mlibc"
+ ;;
+ *:[Mm]anagarm:*:*)
+ GUESS="$UNAME_MACHINE-unknown-managarm-mlibc"
+ ;;
+ *:Minix:*:*)
+ GUESS=$UNAME_MACHINE-unknown-minix
+ ;;
+ aarch64:Linux:*:*)
+ set_cc_for_build
+ CPU=$UNAME_MACHINE
+ LIBCABI=$LIBC
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ ABI=64
+ sed 's/^ //' << EOF > "$dummy.c"
+ #ifdef __ARM_EABI__
+ #ifdef __ARM_PCS_VFP
+ ABI=eabihf
+ #else
+ ABI=eabi
+ #endif
+ #endif
+EOF
+ cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
+ eval "$cc_set_abi"
+ case $ABI in
+ eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;;
+ esac
+ fi
+ GUESS=$CPU-unknown-linux-$LIBCABI
+ ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ arm*:Linux:*:*)
+ set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ else
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi
+ else
+ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf
+ fi
+ fi
+ ;;
+ avr32*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ cris:Linux:*:*)
+ GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+ ;;
+ crisv32:Linux:*:*)
+ GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+ ;;
+ e2k:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ frv:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ hexagon:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ i*86:Linux:*:*)
+ GUESS=$UNAME_MACHINE-pc-linux-$LIBC
+ ;;
+ ia64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ k1om:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ kvx:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ kvx:cos:*:*)
+ GUESS=$UNAME_MACHINE-unknown-cos
+ ;;
+ kvx:mbr:*:*)
+ GUESS=$UNAME_MACHINE-unknown-mbr
+ ;;
+ loongarch32:Linux:*:* | loongarch64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ m32r*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ m68*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ set_cc_for_build
+ IS_GLIBC=0
+ test x"${LIBC}" = xgnu && IS_GLIBC=1
+ sed 's/^ //' << EOF > "$dummy.c"
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #undef mips64
+ #undef mips64el
+ #if ${IS_GLIBC} && defined(_ABI64)
+ LIBCABI=gnuabi64
+ #else
+ #if ${IS_GLIBC} && defined(_ABIN32)
+ LIBCABI=gnuabin32
+ #else
+ LIBCABI=${LIBC}
+ #endif
+ #endif
+
+ #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa64r6
+ #else
+ #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa32r6
+ #else
+ #if defined(__mips64)
+ CPU=mips64
+ #else
+ CPU=mips
+ #endif
+ #endif
+ #endif
+
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ MIPS_ENDIAN=el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ MIPS_ENDIAN=
+ #else
+ MIPS_ENDIAN=
+ #endif
+ #endif
+EOF
+ cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`
+ eval "$cc_set_vars"
+ test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
+ ;;
+ mips64el:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ openrisc*:Linux:*:*)
+ GUESS=or1k-unknown-linux-$LIBC
+ ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ padre:Linux:*:*)
+ GUESS=sparc-unknown-linux-$LIBC
+ ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ GUESS=hppa64-unknown-linux-$LIBC
+ ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;;
+ PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;;
+ *) GUESS=hppa-unknown-linux-$LIBC ;;
+ esac
+ ;;
+ ppc64:Linux:*:*)
+ GUESS=powerpc64-unknown-linux-$LIBC
+ ;;
+ ppc:Linux:*:*)
+ GUESS=powerpc-unknown-linux-$LIBC
+ ;;
+ ppc64le:Linux:*:*)
+ GUESS=powerpc64le-unknown-linux-$LIBC
+ ;;
+ ppcle:Linux:*:*)
+ GUESS=powerpcle-unknown-linux-$LIBC
+ ;;
+ riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ GUESS=$UNAME_MACHINE-ibm-linux-$LIBC
+ ;;
+ sh64*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ sh*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ tile*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ vax:Linux:*:*)
+ GUESS=$UNAME_MACHINE-dec-linux-$LIBC
+ ;;
+ x86_64:Linux:*:*)
+ set_cc_for_build
+ CPU=$UNAME_MACHINE
+ LIBCABI=$LIBC
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ ABI=64
+ sed 's/^ //' << EOF > "$dummy.c"
+ #ifdef __i386__
+ ABI=x86
+ #else
+ #ifdef __ILP32__
+ ABI=x32
+ #endif
+ #endif
+EOF
+ cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
+ eval "$cc_set_abi"
+ case $ABI in
+ x86) CPU=i686 ;;
+ x32) LIBCABI=${LIBC}x32 ;;
+ esac
+ fi
+ GUESS=$CPU-pc-linux-$LIBCABI
+ ;;
+ xtensa*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ GUESS=i386-sequent-sysv4
+ ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
+ ;;
+ i*86:OS/2:*:*)
+ # If we were able to find 'uname', then EMX Unix compatibility
+ # is probably installed.
+ GUESS=$UNAME_MACHINE-pc-os2-emx
+ ;;
+ i*86:XTS-300:*:STOP)
+ GUESS=$UNAME_MACHINE-unknown-stop
+ ;;
+ i*86:atheos:*:*)
+ GUESS=$UNAME_MACHINE-unknown-atheos
+ ;;
+ i*86:syllable:*:*)
+ GUESS=$UNAME_MACHINE-pc-syllable
+ ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ GUESS=i386-unknown-lynxos$UNAME_RELEASE
+ ;;
+ i*86:*DOS:*:*)
+ GUESS=$UNAME_MACHINE-pc-msdosdjgpp
+ ;;
+ i*86:*:4.*:*)
+ UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL
+ else
+ GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL
+ fi
+ ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ GUESS=$UNAME_MACHINE-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL
+ else
+ GUESS=$UNAME_MACHINE-pc-sysv32
+ fi
+ ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configure will decide that
+ # this is a cross-build.
+ GUESS=i586-pc-msdosdjgpp
+ ;;
+ Intel:Mach:3*:*)
+ GUESS=i386-pc-mach3
+ ;;
+ paragon:*:*:*)
+ GUESS=i860-intel-osf1
+ ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4
+ fi
+ ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ GUESS=m68010-convergent-sysv
+ ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ GUESS=m68k-convergent-sysv
+ ;;
+ M680?0:D-NIX:5.3:*)
+ GUESS=m68k-diab-dnix
+ ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ GUESS=m68k-unknown-lynxos$UNAME_RELEASE
+ ;;
+ mc68030:UNIX_System_V:4.*:*)
+ GUESS=m68k-atari-sysv4
+ ;;
+ TSUNAMI:LynxOS:2.*:*)
+ GUESS=sparc-unknown-lynxos$UNAME_RELEASE
+ ;;
+ rs6000:LynxOS:2.*:*)
+ GUESS=rs6000-unknown-lynxos$UNAME_RELEASE
+ ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ GUESS=powerpc-unknown-lynxos$UNAME_RELEASE
+ ;;
+ SM[BE]S:UNIX_SV:*:*)
+ GUESS=mips-dde-sysv$UNAME_RELEASE
+ ;;
+ RM*:ReliantUNIX-*:*:*)
+ GUESS=mips-sni-sysv4
+ ;;
+ RM*:SINIX-*:*:*)
+ GUESS=mips-sni-sysv4
+ ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ GUESS=$UNAME_MACHINE-sni-sysv4
+ else
+ GUESS=ns32k-sni-sysv
+ fi
+ ;;
+ PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ GUESS=i586-unisys-sysv4
+ ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ GUESS=hppa1.1-stratus-sysv4
+ ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ GUESS=i860-stratus-sysv4
+ ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ GUESS=$UNAME_MACHINE-stratus-vos
+ ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ GUESS=hppa1.1-stratus-vos
+ ;;
+ mc68*:A/UX:*:*)
+ GUESS=m68k-apple-aux$UNAME_RELEASE
+ ;;
+ news*:NEWS-OS:6*:*)
+ GUESS=mips-sony-newsos6
+ ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if test -d /usr/nec; then
+ GUESS=mips-nec-sysv$UNAME_RELEASE
+ else
+ GUESS=mips-unknown-sysv$UNAME_RELEASE
+ fi
+ ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ GUESS=powerpc-be-beos
+ ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ GUESS=powerpc-apple-beos
+ ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ GUESS=i586-pc-beos
+ ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ GUESS=i586-pc-haiku
+ ;;
+ ppc:Haiku:*:*) # Haiku running on Apple PowerPC
+ GUESS=powerpc-apple-haiku
+ ;;
+ *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat)
+ GUESS=$UNAME_MACHINE-unknown-haiku
+ ;;
+ SX-4:SUPER-UX:*:*)
+ GUESS=sx4-nec-superux$UNAME_RELEASE
+ ;;
+ SX-5:SUPER-UX:*:*)
+ GUESS=sx5-nec-superux$UNAME_RELEASE
+ ;;
+ SX-6:SUPER-UX:*:*)
+ GUESS=sx6-nec-superux$UNAME_RELEASE
+ ;;
+ SX-7:SUPER-UX:*:*)
+ GUESS=sx7-nec-superux$UNAME_RELEASE
+ ;;
+ SX-8:SUPER-UX:*:*)
+ GUESS=sx8-nec-superux$UNAME_RELEASE
+ ;;
+ SX-8R:SUPER-UX:*:*)
+ GUESS=sx8r-nec-superux$UNAME_RELEASE
+ ;;
+ SX-ACE:SUPER-UX:*:*)
+ GUESS=sxace-nec-superux$UNAME_RELEASE
+ ;;
+ Power*:Rhapsody:*:*)
+ GUESS=powerpc-apple-rhapsody$UNAME_RELEASE
+ ;;
+ *:Rhapsody:*:*)
+ GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE
+ ;;
+ arm64:Darwin:*:*)
+ GUESS=aarch64-apple-darwin$UNAME_RELEASE
+ ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p`
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ if command -v xcode-select > /dev/null 2> /dev/null && \
+ ! xcode-select --print-path > /dev/null 2> /dev/null ; then
+ # Avoid executing cc if there is no toolchain installed as
+ # cc will be a stub that puts up a graphical alert
+ # prompting the user to install developer tools.
+ CC_FOR_BUILD=no_compiler_found
+ else
+ set_cc_for_build
+ fi
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+ if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_PPC >/dev/null
+ then
+ UNAME_PROCESSOR=powerpc
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # uname -m returns i386 or x86_64
+ UNAME_PROCESSOR=$UNAME_MACHINE
+ fi
+ GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE
+ ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = x86; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE
+ ;;
+ *:QNX:*:4*)
+ GUESS=i386-pc-qnx
+ ;;
+ NEO-*:NONSTOP_KERNEL:*:*)
+ GUESS=neo-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSE-*:NONSTOP_KERNEL:*:*)
+ GUESS=nse-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSR-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsr-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSV-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsv-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSX-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsx-tandem-nsk$UNAME_RELEASE
+ ;;
+ *:NonStop-UX:*:*)
+ GUESS=mips-compaq-nonstopux
+ ;;
+ BS2000:POSIX*:*:*)
+ GUESS=bs2000-siemens-sysv
+ ;;
+ DS/*:UNIX_System_V:*:*)
+ GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE
+ ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "${cputype-}" = 386; then
+ UNAME_MACHINE=i386
+ elif test "x${cputype-}" != x; then
+ UNAME_MACHINE=$cputype
+ fi
+ GUESS=$UNAME_MACHINE-unknown-plan9
+ ;;
+ *:TOPS-10:*:*)
+ GUESS=pdp10-unknown-tops10
+ ;;
+ *:TENEX:*:*)
+ GUESS=pdp10-unknown-tenex
+ ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ GUESS=pdp10-dec-tops20
+ ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ GUESS=pdp10-xkl-tops20
+ ;;
+ *:TOPS-20:*:*)
+ GUESS=pdp10-unknown-tops20
+ ;;
+ *:ITS:*:*)
+ GUESS=pdp10-unknown-its
+ ;;
+ SEI:*:*:SEIUX)
+ GUESS=mips-sei-seiux$UNAME_RELEASE
+ ;;
+ *:DragonFly:*:*)
+ DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL
+ ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case $UNAME_MACHINE in
+ A*) GUESS=alpha-dec-vms ;;
+ I*) GUESS=ia64-dec-vms ;;
+ V*) GUESS=vax-dec-vms ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ GUESS=i386-pc-xenix
+ ;;
+ i*86:skyos:*:*)
+ SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`
+ GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL
+ ;;
+ i*86:rdos:*:*)
+ GUESS=$UNAME_MACHINE-pc-rdos
+ ;;
+ i*86:Fiwix:*:*)
+ GUESS=$UNAME_MACHINE-pc-fiwix
+ ;;
+ *:AROS:*:*)
+ GUESS=$UNAME_MACHINE-unknown-aros
+ ;;
+ x86_64:VMkernel:*:*)
+ GUESS=$UNAME_MACHINE-unknown-esx
+ ;;
+ amd64:Isilon\ OneFS:*:*)
+ GUESS=x86_64-unknown-onefs
+ ;;
+ *:Unleashed:*:*)
+ GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
+ ;;
+esac
+
+# Do we have a guess based on uname results?
+if test "x$GUESS" != x; then
+ echo "$GUESS"
+ exit
+fi
+
+# No uname command or uname output not recognized.
+set_cc_for_build
+cat > "$dummy.c" <<EOF
+#ifdef _SEQUENT_
+#include <sys/types.h>
+#include <sys/utsname.h>
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#include <signal.h>
+#if defined(_SIZE_T_) || defined(SIGLOST)
+#include <sys/utsname.h>
+#endif
+#endif
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+#include <sys/param.h>
+#if defined (BSD)
+#if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+#else
+#if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#endif
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#else
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname un;
+ uname (&un);
+ printf ("vax-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname *un;
+ uname (&un);
+ printf ("mips-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("mips-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
+
+echo "$0: unable to guess system type" >&2
+
+case $UNAME_MACHINE:$UNAME_SYSTEM in
+ mips:Linux | mips64:Linux)
+ # If we got here on MIPS GNU/Linux, output extra information.
+ cat >&2 <<EOF
+
+NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+the system type. Please install a C compiler and try again.
+EOF
+ ;;
+esac
+
+cat >&2 <<EOF
+
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite *all*
+copies of config.guess and config.sub with the latest versions from:
+
+ https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
+and
+ https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
+EOF
+
+our_year=`echo $timestamp | sed 's,-.*,,'`
+thisyear=`date +%Y`
+# shellcheck disable=SC2003
+script_age=`expr "$thisyear" - "$our_year"`
+if test "$script_age" -lt 3 ; then
+ cat >&2 <<EOF
+
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = "$UNAME_MACHINE"
+UNAME_RELEASE = "$UNAME_RELEASE"
+UNAME_SYSTEM = "$UNAME_SYSTEM"
+UNAME_VERSION = "$UNAME_VERSION"
+EOF
+fi
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/external/subpack/utils/stressapptest/src/config.sub b/external/subpack/utils/stressapptest/src/config.sub
new file mode 100755
index 0000000..6ae2502
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/config.sub
@@ -0,0 +1,1895 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright 1992-2023 Free Software Foundation, Inc.
+
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2023-07-31'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX. However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
+
+Canonicalize a configuration name.
+
+Options:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2023 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try '$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo "$1"
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Split fields of configuration type
+# shellcheck disable=SC2162
+saved_IFS=$IFS
+IFS="-" read field1 field2 field3 field4 <<EOF
+$1
+EOF
+IFS=$saved_IFS
+
+# Separate into logical components for further validation
+case $1 in
+ *-*-*-*-*)
+ echo "Invalid configuration '$1': more than four components" >&2
+ exit 1
+ ;;
+ *-*-*-*)
+ basic_machine=$field1-$field2
+ basic_os=$field3-$field4
+ ;;
+ *-*-*)
+ # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
+ # parts
+ maybe_os=$field2-$field3
+ case $maybe_os in
+ nto-qnx* | linux-* | uclinux-uclibc* \
+ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
+ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
+ | storm-chaos* | os2-emx* | rtmk-nova* | managarm-* \
+ | windows-* )
+ basic_machine=$field1
+ basic_os=$maybe_os
+ ;;
+ android-linux)
+ basic_machine=$field1-unknown
+ basic_os=linux-android
+ ;;
+ *)
+ basic_machine=$field1-$field2
+ basic_os=$field3
+ ;;
+ esac
+ ;;
+ *-*)
+ # A lone config we happen to match not fitting any pattern
+ case $field1-$field2 in
+ decstation-3100)
+ basic_machine=mips-dec
+ basic_os=
+ ;;
+ *-*)
+ # Second component is usually, but not always the OS
+ case $field2 in
+ # Prevent following clause from handling this valid os
+ sun*os*)
+ basic_machine=$field1
+ basic_os=$field2
+ ;;
+ zephyr*)
+ basic_machine=$field1-unknown
+ basic_os=$field2
+ ;;
+ # Manufacturers
+ dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
+ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
+ | unicom* | ibm* | next | hp | isi* | apollo | altos* \
+ | convergent* | ncr* | news | 32* | 3600* | 3100* \
+ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
+ | ultra | tti* | harris | dolphin | highlevel | gould \
+ | cbm | ns | masscomp | apple | axis | knuth | cray \
+ | microblaze* | sim | cisco \
+ | oki | wec | wrs | winbond)
+ basic_machine=$field1-$field2
+ basic_os=
+ ;;
+ *)
+ basic_machine=$field1
+ basic_os=$field2
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *)
+ # Convert single-component short-hands not valid as part of
+ # multi-component configurations.
+ case $field1 in
+ 386bsd)
+ basic_machine=i386-pc
+ basic_os=bsd
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ basic_os=scout
+ ;;
+ alliant)
+ basic_machine=fx80-alliant
+ basic_os=
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ basic_os=
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ basic_os=bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ basic_os=sysv
+ ;;
+ amiga)
+ basic_machine=m68k-unknown
+ basic_os=
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ basic_os=amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ basic_os=sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ basic_os=sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ basic_os=bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ basic_os=aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ basic_os=aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ basic_os=dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ basic_os=linux
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ basic_os=cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ basic_os=bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ basic_os=bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ basic_os=bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ basic_os=bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ basic_os=bsd
+ ;;
+ cray)
+ basic_machine=j90-cray
+ basic_os=unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ basic_os=
+ ;;
+ da30)
+ basic_machine=m68k-da30
+ basic_os=
+ ;;
+ decstation | pmax | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ basic_os=
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ basic_os=sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ basic_os=dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ basic_os=msdosdjgpp
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ basic_os=ebmon
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ basic_os=ose
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ basic_os=sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ basic_os=go32
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ basic_os=hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ basic_os=xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ basic_os=hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ basic_os=sysv3
+ ;;
+ hp300 | hp300hpux)
+ basic_machine=m68k-hp
+ basic_os=hpux
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ basic_os=bsd
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ basic_os=osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ basic_os=proelf
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ basic_os=mach
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ basic_os=sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ basic_os=linux
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ basic_os=sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ basic_os=sysv
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ basic_os=mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ basic_os=mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ basic_os=mingw32ce
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ basic_os=coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ basic_os=morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ basic_os=moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ basic_os=msdos
+ ;;
+ msys)
+ basic_machine=i686-pc
+ basic_os=msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ basic_os=mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ basic_os=nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ basic_os=sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-pc
+ basic_os=netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ basic_os=linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ basic_os=newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ basic_os=newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ basic_os=sysv
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ basic_os=cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ basic_os=cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ basic_os=nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ basic_os=mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ basic_os=nonstopux
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ basic_os=os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ basic_os=ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ basic_os=os68k
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ basic_os=osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ basic_os=linux
+ ;;
+ psp)
+ basic_machine=mipsallegrexel-sony
+ basic_os=psp
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ basic_os=pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ basic_os=rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ basic_os=rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ basic_os=coff
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ sei)
+ basic_machine=mips-sei
+ basic_os=seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ basic_os=
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ basic_os=sysv2
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ basic_os=
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ basic_os=sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ basic_os=
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ basic_os=sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ basic_os=sunos4
+ ;;
+ sun3)
+ basic_machine=m68k-sun
+ basic_os=
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ basic_os=sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ basic_os=sunos4
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ basic_os=
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ basic_os=sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ basic_os=sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ basic_os=solaris2
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ basic_os=
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ basic_os=unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ basic_os=dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ basic_os=unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ basic_os=unicos
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ basic_os=tops20
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ basic_os=tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ basic_os=sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ basic_os=none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ basic_os=sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ basic_os=vms
+ ;;
+ vsta)
+ basic_machine=i386-pc
+ basic_os=vsta
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ basic_os=vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ basic_os=vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ basic_os=vxworks
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ basic_os=mingw32
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ basic_os=unicos
+ ;;
+ *)
+ basic_machine=$1
+ basic_os=
+ ;;
+ esac
+ ;;
+esac
+
+# Decode 1-component or ad-hoc basic machines
+case $basic_machine in
+ # Here we handle the default manufacturer of certain CPU types. It is in
+ # some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ cpu=hppa1.1
+ vendor=winbond
+ ;;
+ op50n)
+ cpu=hppa1.1
+ vendor=oki
+ ;;
+ op60c)
+ cpu=hppa1.1
+ vendor=oki
+ ;;
+ ibm*)
+ cpu=i370
+ vendor=ibm
+ ;;
+ orion105)
+ cpu=clipper
+ vendor=highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ cpu=m68k
+ vendor=apple
+ ;;
+ pmac | pmac-mpw)
+ cpu=powerpc
+ vendor=apple
+ ;;
+
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ cpu=m68000
+ vendor=att
+ ;;
+ 3b*)
+ cpu=we32k
+ vendor=att
+ ;;
+ bluegene*)
+ cpu=powerpc
+ vendor=ibm
+ basic_os=cnk
+ ;;
+ decsystem10* | dec10*)
+ cpu=pdp10
+ vendor=dec
+ basic_os=tops10
+ ;;
+ decsystem20* | dec20*)
+ cpu=pdp10
+ vendor=dec
+ basic_os=tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ cpu=m68k
+ vendor=motorola
+ ;;
+ dpx2*)
+ cpu=m68k
+ vendor=bull
+ basic_os=sysv3
+ ;;
+ encore | umax | mmax)
+ cpu=ns32k
+ vendor=encore
+ ;;
+ elxsi)
+ cpu=elxsi
+ vendor=elxsi
+ basic_os=${basic_os:-bsd}
+ ;;
+ fx2800)
+ cpu=i860
+ vendor=alliant
+ ;;
+ genix)
+ cpu=ns32k
+ vendor=ns
+ ;;
+ h3050r* | hiux*)
+ cpu=hppa1.1
+ vendor=hitachi
+ basic_os=hiuxwe2
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ cpu=hppa1.0
+ vendor=hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ cpu=m68000
+ vendor=hp
+ ;;
+ hp9k3[2-9][0-9])
+ cpu=m68k
+ vendor=hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ cpu=hppa1.0
+ vendor=hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ cpu=hppa1.0
+ vendor=hp
+ ;;
+ i*86v32)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv32
+ ;;
+ i*86v4*)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv4
+ ;;
+ i*86v)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv
+ ;;
+ i*86sol2)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=solaris2
+ ;;
+ j90 | j90-cray)
+ cpu=j90
+ vendor=cray
+ basic_os=${basic_os:-unicos}
+ ;;
+ iris | iris4d)
+ cpu=mips
+ vendor=sgi
+ case $basic_os in
+ irix*)
+ ;;
+ *)
+ basic_os=irix4
+ ;;
+ esac
+ ;;
+ miniframe)
+ cpu=m68000
+ vendor=convergent
+ ;;
+ *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ cpu=m68k
+ vendor=atari
+ basic_os=mint
+ ;;
+ news-3600 | risc-news)
+ cpu=mips
+ vendor=sony
+ basic_os=newsos
+ ;;
+ next | m*-next)
+ cpu=m68k
+ vendor=next
+ case $basic_os in
+ openstep*)
+ ;;
+ nextstep*)
+ ;;
+ ns2*)
+ basic_os=nextstep2
+ ;;
+ *)
+ basic_os=nextstep3
+ ;;
+ esac
+ ;;
+ np1)
+ cpu=np1
+ vendor=gould
+ ;;
+ op50n-* | op60c-*)
+ cpu=hppa1.1
+ vendor=oki
+ basic_os=proelf
+ ;;
+ pa-hitachi)
+ cpu=hppa1.1
+ vendor=hitachi
+ basic_os=hiuxwe2
+ ;;
+ pbd)
+ cpu=sparc
+ vendor=tti
+ ;;
+ pbb)
+ cpu=m68k
+ vendor=tti
+ ;;
+ pc532)
+ cpu=ns32k
+ vendor=pc532
+ ;;
+ pn)
+ cpu=pn
+ vendor=gould
+ ;;
+ power)
+ cpu=power
+ vendor=ibm
+ ;;
+ ps2)
+ cpu=i386
+ vendor=ibm
+ ;;
+ rm[46]00)
+ cpu=mips
+ vendor=siemens
+ ;;
+ rtpc | rtpc-*)
+ cpu=romp
+ vendor=ibm
+ ;;
+ sde)
+ cpu=mipsisa32
+ vendor=sde
+ basic_os=${basic_os:-elf}
+ ;;
+ simso-wrs)
+ cpu=sparclite
+ vendor=wrs
+ basic_os=vxworks
+ ;;
+ tower | tower-32)
+ cpu=m68k
+ vendor=ncr
+ ;;
+ vpp*|vx|vx-*)
+ cpu=f301
+ vendor=fujitsu
+ ;;
+ w65)
+ cpu=w65
+ vendor=wdc
+ ;;
+ w89k-*)
+ cpu=hppa1.1
+ vendor=winbond
+ basic_os=proelf
+ ;;
+ none)
+ cpu=none
+ vendor=none
+ ;;
+ leon|leon[3-9])
+ cpu=sparc
+ vendor=$basic_machine
+ ;;
+ leon-*|leon[3-9]-*)
+ cpu=sparc
+ vendor=`echo "$basic_machine" | sed 's/-.*//'`
+ ;;
+
+ *-*)
+ # shellcheck disable=SC2162
+ saved_IFS=$IFS
+ IFS="-" read cpu vendor <<EOF
+$basic_machine
+EOF
+ IFS=$saved_IFS
+ ;;
+ # We use 'pc' rather than 'unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ cpu=$basic_machine
+ vendor=pc
+ ;;
+ # These rules are duplicated from below for sake of the special case above;
+ # i.e. things that normalized to x86 arches should also default to "pc"
+ pc98)
+ cpu=i386
+ vendor=pc
+ ;;
+ x64 | amd64)
+ cpu=x86_64
+ vendor=pc
+ ;;
+ # Recognize the basic CPU types without company name.
+ *)
+ cpu=$basic_machine
+ vendor=unknown
+ ;;
+esac
+
+unset -v basic_machine
+
+# Decode basic machines in the full and proper CPU-Company form.
+case $cpu-$vendor in
+ # Here we handle the default manufacturer of certain CPU types in canonical form. It is in
+ # some cases the only manufacturer, in others, it is the most popular.
+ craynv-unknown)
+ vendor=cray
+ basic_os=${basic_os:-unicosmp}
+ ;;
+ c90-unknown | c90-cray)
+ vendor=cray
+ basic_os=${Basic_os:-unicos}
+ ;;
+ fx80-unknown)
+ vendor=alliant
+ ;;
+ romp-unknown)
+ vendor=ibm
+ ;;
+ mmix-unknown)
+ vendor=knuth
+ ;;
+ microblaze-unknown | microblazeel-unknown)
+ vendor=xilinx
+ ;;
+ rs6000-unknown)
+ vendor=ibm
+ ;;
+ vax-unknown)
+ vendor=dec
+ ;;
+ pdp11-unknown)
+ vendor=dec
+ ;;
+ we32k-unknown)
+ vendor=att
+ ;;
+ cydra-unknown)
+ vendor=cydrome
+ ;;
+ i370-ibm*)
+ vendor=ibm
+ ;;
+ orion-unknown)
+ vendor=highlevel
+ ;;
+ xps-unknown | xps100-unknown)
+ cpu=xps100
+ vendor=honeywell
+ ;;
+
+ # Here we normalize CPU types with a missing or matching vendor
+ armh-unknown | armh-alt)
+ cpu=armv7l
+ vendor=alt
+ basic_os=${basic_os:-linux-gnueabihf}
+ ;;
+ dpx20-unknown | dpx20-bull)
+ cpu=rs6000
+ vendor=bull
+ basic_os=${basic_os:-bosx}
+ ;;
+
+ # Here we normalize CPU types irrespective of the vendor
+ amd64-*)
+ cpu=x86_64
+ ;;
+ blackfin-*)
+ cpu=bfin
+ basic_os=linux
+ ;;
+ c54x-*)
+ cpu=tic54x
+ ;;
+ c55x-*)
+ cpu=tic55x
+ ;;
+ c6x-*)
+ cpu=tic6x
+ ;;
+ e500v[12]-*)
+ cpu=powerpc
+ basic_os=${basic_os}"spe"
+ ;;
+ mips3*-*)
+ cpu=mips64
+ ;;
+ ms1-*)
+ cpu=mt
+ ;;
+ m68knommu-*)
+ cpu=m68k
+ basic_os=linux
+ ;;
+ m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
+ cpu=s12z
+ ;;
+ openrisc-*)
+ cpu=or32
+ ;;
+ parisc-*)
+ cpu=hppa
+ basic_os=linux
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ cpu=i586
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*)
+ cpu=i686
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ cpu=i686
+ ;;
+ pentium4-*)
+ cpu=i786
+ ;;
+ pc98-*)
+ cpu=i386
+ ;;
+ ppc-* | ppcbe-*)
+ cpu=powerpc
+ ;;
+ ppcle-* | powerpclittle-*)
+ cpu=powerpcle
+ ;;
+ ppc64-*)
+ cpu=powerpc64
+ ;;
+ ppc64le-* | powerpc64little-*)
+ cpu=powerpc64le
+ ;;
+ sb1-*)
+ cpu=mipsisa64sb1
+ ;;
+ sb1el-*)
+ cpu=mipsisa64sb1el
+ ;;
+ sh5e[lb]-*)
+ cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
+ ;;
+ spur-*)
+ cpu=spur
+ ;;
+ strongarm-* | thumb-*)
+ cpu=arm
+ ;;
+ tx39-*)
+ cpu=mipstx39
+ ;;
+ tx39el-*)
+ cpu=mipstx39el
+ ;;
+ x64-*)
+ cpu=x86_64
+ ;;
+ xscale-* | xscalee[bl]-*)
+ cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
+ ;;
+ arm64-* | aarch64le-*)
+ cpu=aarch64
+ ;;
+
+ # Recognize the canonical CPU Types that limit and/or modify the
+ # company names they are paired with.
+ cr16-*)
+ basic_os=${basic_os:-elf}
+ ;;
+ crisv32-* | etraxfs*-*)
+ cpu=crisv32
+ vendor=axis
+ ;;
+ cris-* | etrax*-*)
+ cpu=cris
+ vendor=axis
+ ;;
+ crx-*)
+ basic_os=${basic_os:-elf}
+ ;;
+ neo-tandem)
+ cpu=neo
+ vendor=tandem
+ ;;
+ nse-tandem)
+ cpu=nse
+ vendor=tandem
+ ;;
+ nsr-tandem)
+ cpu=nsr
+ vendor=tandem
+ ;;
+ nsv-tandem)
+ cpu=nsv
+ vendor=tandem
+ ;;
+ nsx-tandem)
+ cpu=nsx
+ vendor=tandem
+ ;;
+ mipsallegrexel-sony)
+ cpu=mipsallegrexel
+ vendor=sony
+ ;;
+ tile*-*)
+ basic_os=${basic_os:-linux-gnu}
+ ;;
+
+ *)
+ # Recognize the canonical CPU types that are allowed with any
+ # company name.
+ case $cpu in
+ 1750a | 580 \
+ | a29k \
+ | aarch64 | aarch64_be \
+ | abacus \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
+ | alphapca5[67] | alpha64pca5[67] \
+ | am33_2.0 \
+ | amdgcn \
+ | arc | arceb | arc32 | arc64 \
+ | arm | arm[lb]e | arme[lb] | armv* \
+ | avr | avr32 \
+ | asmjs \
+ | ba \
+ | be32 | be64 \
+ | bfin | bpf | bs2000 \
+ | c[123]* | c30 | [cjt]90 | c4x \
+ | c8051 | clipper | craynv | csky | cydra \
+ | d10v | d30v | dlx | dsp16xx \
+ | e2k | elxsi | epiphany \
+ | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
+ | h8300 | h8500 \
+ | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i*86 | i860 | i960 | ia16 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | kvx \
+ | le32 | le64 \
+ | lm32 \
+ | loongarch32 | loongarch64 \
+ | m32c | m32r | m32rle \
+ | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
+ | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
+ | m88110 | m88k | maxq | mb | mcore | mep | metag \
+ | microblaze | microblazeel \
+ | mips* \
+ | mmix \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nfp \
+ | nios | nios2 | nios2eb | nios2el \
+ | none | np1 | ns16k | ns32k | nvptx \
+ | open8 \
+ | or1k* \
+ | or32 \
+ | orion \
+ | picochip \
+ | pdp10 | pdp11 | pj | pjl | pn | power \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
+ | pru \
+ | pyramid \
+ | riscv | riscv32 | riscv32be | riscv64 | riscv64be \
+ | rl78 | romp | rs6000 | rx \
+ | s390 | s390x \
+ | score \
+ | sh | shl \
+ | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
+ | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
+ | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
+ | spu \
+ | tahoe \
+ | thumbv7* \
+ | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
+ | tron \
+ | ubicom32 \
+ | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
+ | vax \
+ | visium \
+ | w65 \
+ | wasm32 | wasm64 \
+ | we32k \
+ | x86 | x86_64 | xc16x | xgate | xps100 \
+ | xstormy16 | xtensa* \
+ | ymp \
+ | z8k | z80)
+ ;;
+
+ *)
+ echo "Invalid configuration '$1': machine '$cpu-$vendor' not recognized" 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $vendor in
+ digital*)
+ vendor=dec
+ ;;
+ commodore*)
+ vendor=cbm
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if test x$basic_os != x
+then
+
+# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
+# set os.
+case $basic_os in
+ gnu/linux*)
+ kernel=linux
+ os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
+ ;;
+ os2-emx)
+ kernel=os2
+ os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
+ ;;
+ nto-qnx*)
+ kernel=nto
+ os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
+ ;;
+ *-*)
+ # shellcheck disable=SC2162
+ saved_IFS=$IFS
+ IFS="-" read kernel os <<EOF
+$basic_os
+EOF
+ IFS=$saved_IFS
+ ;;
+ # Default OS when just kernel was specified
+ nto*)
+ kernel=nto
+ os=`echo "$basic_os" | sed -e 's|nto|qnx|'`
+ ;;
+ linux*)
+ kernel=linux
+ os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
+ ;;
+ managarm*)
+ kernel=managarm
+ os=`echo "$basic_os" | sed -e 's|managarm|mlibc|'`
+ ;;
+ *)
+ kernel=
+ os=$basic_os
+ ;;
+esac
+
+# Now, normalize the OS (knowing we just have one component, it's not a kernel,
+# etc.)
+case $os in
+ # First match some system type aliases that might get confused
+ # with valid system types.
+ # solaris* is a basic system type, with this one exception.
+ auroraux)
+ os=auroraux
+ ;;
+ bluegene*)
+ os=cnk
+ ;;
+ solaris1 | solaris1.*)
+ os=`echo "$os" | sed -e 's|solaris1|sunos4|'`
+ ;;
+ solaris)
+ os=solaris2
+ ;;
+ unixware*)
+ os=sysv4.2uw
+ ;;
+ # es1800 is here to avoid being matched by es* (a different OS)
+ es1800*)
+ os=ose
+ ;;
+ # Some version numbers need modification
+ chorusos*)
+ os=chorusos
+ ;;
+ isc)
+ os=isc2.2
+ ;;
+ sco6)
+ os=sco5v6
+ ;;
+ sco5)
+ os=sco3.2v5
+ ;;
+ sco4)
+ os=sco3.2v4
+ ;;
+ sco3.2.[4-9]*)
+ os=`echo "$os" | sed -e 's/sco3.2./sco3.2v/'`
+ ;;
+ sco*v* | scout)
+ # Don't match below
+ ;;
+ sco*)
+ os=sco3.2v2
+ ;;
+ psos*)
+ os=psos
+ ;;
+ qnx*)
+ os=qnx
+ ;;
+ hiux*)
+ os=hiuxwe2
+ ;;
+ lynx*178)
+ os=lynxos178
+ ;;
+ lynx*5)
+ os=lynxos5
+ ;;
+ lynxos*)
+ # don't get caught up in next wildcard
+ ;;
+ lynx*)
+ os=lynxos
+ ;;
+ mac[0-9]*)
+ os=`echo "$os" | sed -e 's|mac|macos|'`
+ ;;
+ opened*)
+ os=openedition
+ ;;
+ os400*)
+ os=os400
+ ;;
+ sunos5*)
+ os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
+ ;;
+ sunos6*)
+ os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
+ ;;
+ wince*)
+ os=wince
+ ;;
+ utek*)
+ os=bsd
+ ;;
+ dynix*)
+ os=bsd
+ ;;
+ acis*)
+ os=aos
+ ;;
+ atheos*)
+ os=atheos
+ ;;
+ syllable*)
+ os=syllable
+ ;;
+ 386bsd)
+ os=bsd
+ ;;
+ ctix* | uts*)
+ os=sysv
+ ;;
+ nova*)
+ os=rtmk-nova
+ ;;
+ ns2)
+ os=nextstep2
+ ;;
+ # Preserve the version number of sinix5.
+ sinix5.*)
+ os=`echo "$os" | sed -e 's|sinix|sysv|'`
+ ;;
+ sinix*)
+ os=sysv4
+ ;;
+ tpf*)
+ os=tpf
+ ;;
+ triton*)
+ os=sysv3
+ ;;
+ oss*)
+ os=sysv3
+ ;;
+ svr4*)
+ os=sysv4
+ ;;
+ svr3)
+ os=sysv3
+ ;;
+ sysvr4)
+ os=sysv4
+ ;;
+ ose*)
+ os=ose
+ ;;
+ *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
+ os=mint
+ ;;
+ dicos*)
+ os=dicos
+ ;;
+ pikeos*)
+ # Until real need of OS specific support for
+ # particular features comes up, bare metal
+ # configurations are quite functional.
+ case $cpu in
+ arm*)
+ os=eabi
+ ;;
+ *)
+ os=elf
+ ;;
+ esac
+ ;;
+ *)
+ # No normalization, but not necessarily accepted, that comes below.
+ ;;
+esac
+
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+kernel=
+case $cpu-$vendor in
+ score-*)
+ os=elf
+ ;;
+ spu-*)
+ os=elf
+ ;;
+ *-acorn)
+ os=riscix1.2
+ ;;
+ arm*-rebel)
+ kernel=linux
+ os=gnu
+ ;;
+ arm*-semi)
+ os=aout
+ ;;
+ c4x-* | tic4x-*)
+ os=coff
+ ;;
+ c8051-*)
+ os=elf
+ ;;
+ clipper-intergraph)
+ os=clix
+ ;;
+ hexagon-*)
+ os=elf
+ ;;
+ tic54x-*)
+ os=coff
+ ;;
+ tic55x-*)
+ os=coff
+ ;;
+ tic6x-*)
+ os=coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=tops20
+ ;;
+ pdp11-*)
+ os=none
+ ;;
+ *-dec | vax-*)
+ os=ultrix4.2
+ ;;
+ m68*-apollo)
+ os=domain
+ ;;
+ i386-sun)
+ os=sunos4.0.2
+ ;;
+ m68000-sun)
+ os=sunos3
+ ;;
+ m68*-cisco)
+ os=aout
+ ;;
+ mep-*)
+ os=elf
+ ;;
+ mips*-cisco)
+ os=elf
+ ;;
+ mips*-*)
+ os=elf
+ ;;
+ or32-*)
+ os=coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=sysv3
+ ;;
+ sparc-* | *-sun)
+ os=sunos4.1.1
+ ;;
+ pru-*)
+ os=elf
+ ;;
+ *-be)
+ os=beos
+ ;;
+ *-ibm)
+ os=aix
+ ;;
+ *-knuth)
+ os=mmixware
+ ;;
+ *-wec)
+ os=proelf
+ ;;
+ *-winbond)
+ os=proelf
+ ;;
+ *-oki)
+ os=proelf
+ ;;
+ *-hp)
+ os=hpux
+ ;;
+ *-hitachi)
+ os=hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=sysv
+ ;;
+ *-cbm)
+ os=amigaos
+ ;;
+ *-dg)
+ os=dgux
+ ;;
+ *-dolphin)
+ os=sysv3
+ ;;
+ m68k-ccur)
+ os=rtu
+ ;;
+ m88k-omron*)
+ os=luna
+ ;;
+ *-next)
+ os=nextstep
+ ;;
+ *-sequent)
+ os=ptx
+ ;;
+ *-crds)
+ os=unos
+ ;;
+ *-ns)
+ os=genix
+ ;;
+ i370-*)
+ os=mvs
+ ;;
+ *-gould)
+ os=sysv
+ ;;
+ *-highlevel)
+ os=bsd
+ ;;
+ *-encore)
+ os=bsd
+ ;;
+ *-sgi)
+ os=irix
+ ;;
+ *-siemens)
+ os=sysv4
+ ;;
+ *-masscomp)
+ os=rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=uxpv
+ ;;
+ *-rom68k)
+ os=coff
+ ;;
+ *-*bug)
+ os=coff
+ ;;
+ *-apple)
+ os=macos
+ ;;
+ *-atari*)
+ os=mint
+ ;;
+ *-wrs)
+ os=vxworks
+ ;;
+ *)
+ os=none
+ ;;
+esac
+
+fi
+
+# Now, validate our (potentially fixed-up) OS.
+case $os in
+ # Sometimes we do "kernel-libc", so those need to count as OSes.
+ musl* | newlib* | relibc* | uclibc*)
+ ;;
+ # Likewise for "kernel-abi"
+ eabi* | gnueabi*)
+ ;;
+ # VxWorks passes extra cpu info in the 4th filed.
+ simlinux | simwindows | spe)
+ ;;
+ # Now accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST end in a * to match a version number.
+ gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
+ | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
+ | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
+ | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
+ | hiux* | abug | nacl* | netware* | windows* \
+ | os9* | macos* | osx* | ios* | tvos* | watchos* \
+ | mpw* | magic* | mmixware* | mon960* | lnews* \
+ | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
+ | aos* | aros* | cloudabi* | sortix* | twizzler* \
+ | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
+ | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
+ | mirbsd* | netbsd* | dicos* | openedition* | ose* \
+ | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
+ | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
+ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
+ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+ | udi* | lites* | ieee* | go32* | aux* | hcos* \
+ | chorusrdb* | cegcc* | glidix* | serenity* \
+ | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+ | midipix* | mingw32* | mingw64* | mint* \
+ | uxpv* | beos* | mpeix* | udk* | moxiebox* \
+ | interix* | uwin* | mks* | rhapsody* | darwin* \
+ | openstep* | oskit* | conix* | pw32* | nonstopux* \
+ | storm-chaos* | tops10* | tenex* | tops20* | its* \
+ | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
+ | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
+ | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
+ | skyos* | haiku* | rdos* | toppers* | drops* | es* \
+ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
+ | fiwix* | mlibc* | cos* | mbr* )
+ ;;
+ # This one is extra strict with allowed versions
+ sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ ;;
+ none)
+ ;;
+ kernel* | msvc* )
+ # Restricted further below
+ ;;
+ *)
+ echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2
+ exit 1
+ ;;
+esac
+
+# As a final step for OS-related things, validate the OS-kernel combination
+# (given a valid OS), if there is a kernel.
+case $kernel-$os in
+ linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
+ | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* )
+ ;;
+ uclinux-uclibc* )
+ ;;
+ managarm-mlibc* | managarm-kernel* )
+ ;;
+ windows*-gnu* | windows*-msvc*)
+ ;;
+ -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* )
+ # These are just libc implementations, not actual OSes, and thus
+ # require a kernel.
+ echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2
+ exit 1
+ ;;
+ -kernel* )
+ echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2
+ exit 1
+ ;;
+ *-kernel* )
+ echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2
+ exit 1
+ ;;
+ *-msvc* )
+ echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2
+ exit 1
+ ;;
+ kfreebsd*-gnu* | kopensolaris*-gnu*)
+ ;;
+ vxworks-simlinux | vxworks-simwindows | vxworks-spe)
+ ;;
+ nto-qnx*)
+ ;;
+ os2-emx)
+ ;;
+ *-eabi* | *-gnueabi*)
+ ;;
+ none-coff* | none-elf*)
+ # None (no kernel, i.e. freestanding / bare metal),
+ # can be paired with an output format "OS"
+ ;;
+ -*)
+ # Blank kernel with real OS is always fine.
+ ;;
+ *-*)
+ echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+case $vendor in
+ unknown)
+ case $cpu-$os in
+ *-riscix*)
+ vendor=acorn
+ ;;
+ *-sunos*)
+ vendor=sun
+ ;;
+ *-cnk* | *-aix*)
+ vendor=ibm
+ ;;
+ *-beos*)
+ vendor=be
+ ;;
+ *-hpux*)
+ vendor=hp
+ ;;
+ *-mpeix*)
+ vendor=hp
+ ;;
+ *-hiux*)
+ vendor=hitachi
+ ;;
+ *-unos*)
+ vendor=crds
+ ;;
+ *-dgux*)
+ vendor=dg
+ ;;
+ *-luna*)
+ vendor=omron
+ ;;
+ *-genix*)
+ vendor=ns
+ ;;
+ *-clix*)
+ vendor=intergraph
+ ;;
+ *-mvs* | *-opened*)
+ vendor=ibm
+ ;;
+ *-os400*)
+ vendor=ibm
+ ;;
+ s390-* | s390x-*)
+ vendor=ibm
+ ;;
+ *-ptx*)
+ vendor=sequent
+ ;;
+ *-tpf*)
+ vendor=ibm
+ ;;
+ *-vxsim* | *-vxworks* | *-windiss*)
+ vendor=wrs
+ ;;
+ *-aux*)
+ vendor=apple
+ ;;
+ *-hms*)
+ vendor=hitachi
+ ;;
+ *-mpw* | *-macos*)
+ vendor=apple
+ ;;
+ *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
+ vendor=atari
+ ;;
+ *-vos*)
+ vendor=stratus
+ ;;
+ esac
+ ;;
+esac
+
+echo "$cpu-$vendor-${kernel:+$kernel-}$os"
+exit
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/external/subpack/utils/stressapptest/src/configure b/external/subpack/utils/stressapptest/src/configure
new file mode 100755
index 0000000..eb0d11f
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/configure
@@ -0,0 +1,8588 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.71 for stressapptest 1.0.11_autoconf.
+#
+# Report bugs to <opensource@google.com>.
+#
+#
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else $as_nop
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
+as_nl='
+'
+export as_nl
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
+
+# The user is always right.
+if ${PATH_SEPARATOR+false} :; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else \$as_nop
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
+
+else \$as_nop
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null
+then :
+ as_have_required=yes
+else $as_nop
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
+
+else $as_nop
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi
+fi
+
+
+ if test "x$CONFIG_SHELL" != x
+then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and
+$0: opensource@google.com about your system, including any
+$0: error possibly output before this message. Then install
+$0: a modern shell, or manually run the script under such a
+$0: shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else $as_nop
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else $as_nop
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ printf "%s\n" "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='stressapptest'
+PACKAGE_TARNAME='stressapptest'
+PACKAGE_VERSION='1.0.11_autoconf'
+PACKAGE_STRING='stressapptest 1.0.11_autoconf'
+PACKAGE_BUGREPORT='opensource@google.com'
+PACKAGE_URL=''
+
+ac_unique_file="src/"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stddef.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
+#endif
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_header_c_list=
+ac_func_c_list=
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+CPP
+EGREP
+GREP
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+ac_ct_CC
+CFLAGS
+CC
+am__fastdepCXX_FALSE
+am__fastdepCXX_TRUE
+CXXDEPMODE
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CXX
+CPPFLAGS
+LDFLAGS
+CXXFLAGS
+CXX
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_static
+with_cpu
+enable_dependency_tracking
+enable_default_optimizations
+enable_largefile
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CXX
+CXXFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CCC
+CC
+CFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir runstatedir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures stressapptest 1.0.11_autoconf to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/stressapptest]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of stressapptest 1.0.11_autoconf:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --disable-default-optimizations
+ Disable default optimization flag overrides
+ --disable-largefile omit support for large files
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-static enable static linking
+ --with-cpu define host cpu
+
+Some influential environment variables:
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CC C compiler command
+ CFLAGS C compiler flags
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <opensource@google.com>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+stressapptest configure 1.0.11_autoconf
+generated by GNU Autoconf 2.71
+
+Copyright (C) 2021 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest.beam
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest.beam
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$3=yes"
+else $as_nop
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else $as_nop
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_find_uintX_t LINENO BITS VAR
+# ------------------------------------
+# Finds an unsigned integer type with width BITS, setting cache variable VAR
+# accordingly.
+ac_fn_c_find_uintX_t ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
+printf %s "checking for uint$2_t... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ eval "$3=no"
+ # Order is important - never check a type that is potentially smaller
+ # than half of the expected target width.
+ for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \
+ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main (void)
+{
+static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ case $ac_type in #(
+ uint$2_t) :
+ eval "$3=yes" ;; #(
+ *) :
+ eval "$3=\$ac_type" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ if eval test \"x\$"$3"\" = x"no"
+then :
+
+else $as_nop
+ break
+fi
+ done
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_find_uintX_t
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR
+# ------------------------------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR.
+ac_fn_check_decl ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+printf %s "checking whether $as_decl_name is declared... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ eval ac_save_FLAGS=\$$6
+ as_fn_append $6 " $5"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$3=yes"
+else $as_nop
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ eval $6=\$ac_save_FLAGS
+
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_check_decl
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below. */
+
+#include <limits.h>
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main (void)
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval "$3=yes"
+else $as_nop
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by stressapptest $as_me 1.0.11_autoconf, which was
+generated by GNU Autoconf 2.71. Invocation command line was
+
+ $ $0$ac_configure_args_raw
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ printf "%s\n" "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ printf "%s\n" "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ printf "%s\n" "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ printf "%s\n" "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+printf "%s\n" "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ ac_site_files="$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
+else
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+fi
+
+for ac_site_file in $ac_site_files
+do
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Test code for whether the C++ compiler supports C++98 (global declarations)
+ac_cxx_conftest_cxx98_globals='
+// Does the compiler advertise C++98 conformance?
+#if !defined __cplusplus || __cplusplus < 199711L
+# error "Compiler does not advertise C++98 conformance"
+#endif
+
+// These inclusions are to reject old compilers that
+// lack the unsuffixed header files.
+#include <cstdlib>
+#include <exception>
+
+// <cassert> and <cstring> are *not* freestanding headers in C++98.
+extern void assert (int);
+namespace std {
+ extern int strcmp (const char *, const char *);
+}
+
+// Namespaces, exceptions, and templates were all added after "C++ 2.0".
+using std::exception;
+using std::strcmp;
+
+namespace {
+
+void test_exception_syntax()
+{
+ try {
+ throw "test";
+ } catch (const char *s) {
+ // Extra parentheses suppress a warning when building autoconf itself,
+ // due to lint rules shared with more typical C programs.
+ assert (!(strcmp) (s, "test"));
+ }
+}
+
+template <typename T> struct test_template
+{
+ T const val;
+ explicit test_template(T t) : val(t) {}
+ template <typename U> T add(U u) { return static_cast<T>(u) + val; }
+};
+
+} // anonymous namespace
+'
+
+# Test code for whether the C++ compiler supports C++98 (body of main)
+ac_cxx_conftest_cxx98_main='
+ assert (argc);
+ assert (! argv[0]);
+{
+ test_exception_syntax ();
+ test_template<double> tt (2.0);
+ assert (tt.add (4) == 6.0);
+ assert (true && !false);
+}
+'
+
+# Test code for whether the C++ compiler supports C++11 (global declarations)
+ac_cxx_conftest_cxx11_globals='
+// Does the compiler advertise C++ 2011 conformance?
+#if !defined __cplusplus || __cplusplus < 201103L
+# error "Compiler does not advertise C++11 conformance"
+#endif
+
+namespace cxx11test
+{
+ constexpr int get_val() { return 20; }
+
+ struct testinit
+ {
+ int i;
+ double d;
+ };
+
+ class delegate
+ {
+ public:
+ delegate(int n) : n(n) {}
+ delegate(): delegate(2354) {}
+
+ virtual int getval() { return this->n; };
+ protected:
+ int n;
+ };
+
+ class overridden : public delegate
+ {
+ public:
+ overridden(int n): delegate(n) {}
+ virtual int getval() override final { return this->n * 2; }
+ };
+
+ class nocopy
+ {
+ public:
+ nocopy(int i): i(i) {}
+ nocopy() = default;
+ nocopy(const nocopy&) = delete;
+ nocopy & operator=(const nocopy&) = delete;
+ private:
+ int i;
+ };
+
+ // for testing lambda expressions
+ template <typename Ret, typename Fn> Ret eval(Fn f, Ret v)
+ {
+ return f(v);
+ }
+
+ // for testing variadic templates and trailing return types
+ template <typename V> auto sum(V first) -> V
+ {
+ return first;
+ }
+ template <typename V, typename... Args> auto sum(V first, Args... rest) -> V
+ {
+ return first + sum(rest...);
+ }
+}
+'
+
+# Test code for whether the C++ compiler supports C++11 (body of main)
+ac_cxx_conftest_cxx11_main='
+{
+ // Test auto and decltype
+ auto a1 = 6538;
+ auto a2 = 48573953.4;
+ auto a3 = "String literal";
+
+ int total = 0;
+ for (auto i = a3; *i; ++i) { total += *i; }
+
+ decltype(a2) a4 = 34895.034;
+}
+{
+ // Test constexpr
+ short sa[cxx11test::get_val()] = { 0 };
+}
+{
+ // Test initializer lists
+ cxx11test::testinit il = { 4323, 435234.23544 };
+}
+{
+ // Test range-based for
+ int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3,
+ 14, 19, 17, 8, 6, 20, 16, 2, 11, 1};
+ for (auto &x : array) { x += 23; }
+}
+{
+ // Test lambda expressions
+ using cxx11test::eval;
+ assert (eval ([](int x) { return x*2; }, 21) == 42);
+ double d = 2.0;
+ assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0);
+ assert (d == 5.0);
+ assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0);
+ assert (d == 5.0);
+}
+{
+ // Test use of variadic templates
+ using cxx11test::sum;
+ auto a = sum(1);
+ auto b = sum(1, 2);
+ auto c = sum(1.0, 2.0, 3.0);
+}
+{
+ // Test constructor delegation
+ cxx11test::delegate d1;
+ cxx11test::delegate d2();
+ cxx11test::delegate d3(45);
+}
+{
+ // Test override and final
+ cxx11test::overridden o1(55464);
+}
+{
+ // Test nullptr
+ char *c = nullptr;
+}
+{
+ // Test template brackets
+ test_template<::test_template<int>> v(test_template<int>(12));
+}
+{
+ // Unicode literals
+ char const *utf8 = u8"UTF-8 string \u2500";
+ char16_t const *utf16 = u"UTF-8 string \u2500";
+ char32_t const *utf32 = U"UTF-32 string \u2500";
+}
+'
+
+# Test code for whether the C compiler supports C++11 (complete).
+ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals}
+${ac_cxx_conftest_cxx11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_cxx_conftest_cxx98_main}
+ ${ac_cxx_conftest_cxx11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C++98 (complete).
+ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals}
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_cxx_conftest_cxx98_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (global declarations)
+ac_c_conftest_c89_globals='
+/* Does the compiler advertise C89 conformance?
+ Do not test the value of __STDC__, because some compilers set it to 0
+ while being otherwise adequately conformant. */
+#if !defined __STDC__
+# error "Compiler does not advertise C89 conformance"
+#endif
+
+#include <stddef.h>
+#include <stdarg.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
+struct buf { int x; };
+struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not \xHH hex character constants.
+ These do not provoke an error unfortunately, instead are silently treated
+ as an "x". The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously \x00 != x always comes out true, for an
+ array size at least. It is necessary to write \x00 == 0 to get something
+ that is true only with -std. */
+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) '\''x'\''
+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+ int, int);'
+
+# Test code for whether the C compiler supports C89 (body of main).
+ac_c_conftest_c89_main='
+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+'
+
+# Test code for whether the C compiler supports C99 (global declarations)
+ac_c_conftest_c99_globals='
+// Does the compiler advertise C99 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# error "Compiler does not advertise C99 conformance"
+#endif
+
+#include <stdbool.h>
+extern int puts (const char *);
+extern int printf (const char *, ...);
+extern int dprintf (int, const char *, ...);
+extern void *malloc (size_t);
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+// dprintf is used instead of fprintf to avoid needing to declare
+// FILE and stderr.
+#define debug(...) dprintf (2, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ #error "your preprocessor is broken"
+#endif
+#if BIG_OK
+#else
+ #error "your preprocessor is broken"
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static bool
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str = "";
+ int number = 0;
+ float fnumber = 0;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case '\''s'\'': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case '\''d'\'': // int
+ number = va_arg (args_copy, int);
+ break;
+ case '\''f'\'': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+
+ return *str && number && fnumber;
+}
+'
+
+# Test code for whether the C compiler supports C99 (body of main).
+ac_c_conftest_c99_main='
+ // Check bool.
+ _Bool success = false;
+ success |= (argc != 0);
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[0] = argv[0][0];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+ || dynamic_array[ni.number - 1] != 543);
+'
+
+# Test code for whether the C compiler supports C11 (global declarations)
+ac_c_conftest_c11_globals='
+// Does the compiler advertise C11 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
+
+// Check _Alignas.
+char _Alignas (double) aligned_as_double;
+char _Alignas (0) no_special_alignment;
+extern char aligned_as_int;
+char _Alignas (0) _Alignas (int) aligned_as_int;
+
+// Check _Alignof.
+enum
+{
+ int_alignment = _Alignof (int),
+ int_array_alignment = _Alignof (int[100]),
+ char_alignment = _Alignof (char)
+};
+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+
+// Check _Noreturn.
+int _Noreturn does_not_return (void) { for (;;) continue; }
+
+// Check _Static_assert.
+struct test_static_assert
+{
+ int x;
+ _Static_assert (sizeof (int) <= sizeof (long int),
+ "_Static_assert does not work in struct");
+ long int y;
+};
+
+// Check UTF-8 literals.
+#define u8 syntax error!
+char const utf8_literal[] = u8"happens to be ASCII" "another string";
+
+// Check duplicate typedefs.
+typedef long *long_ptr;
+typedef long int *long_ptr;
+typedef long_ptr long_ptr;
+
+// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+struct anonymous
+{
+ union {
+ struct { int i; int j; };
+ struct { int k; long int l; } w;
+ };
+ int m;
+} v1;
+'
+
+# Test code for whether the C compiler supports C11 (body of main).
+ac_c_conftest_c11_main='
+ _Static_assert ((offsetof (struct anonymous, i)
+ == offsetof (struct anonymous, w.k)),
+ "Anonymous union alignment botch");
+ v1.i = 2;
+ v1.w.k = 5;
+ ok |= v1.i != 5;
+'
+
+# Test code for whether the C compiler supports C11 (complete).
+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+${ac_c_conftest_c11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ ${ac_c_conftest_c11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C99 (complete).
+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (complete).
+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ return ok;
+}
+"
+
+as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+as_fn_append ac_header_c_list " sys/time.h sys_time_h HAVE_SYS_TIME_H"
+as_fn_append ac_header_c_list " sys/select.h sys_select_h HAVE_SYS_SELECT_H"
+as_fn_append ac_header_c_list " sys/socket.h sys_socket_h HAVE_SYS_SOCKET_H"
+as_fn_append ac_func_c_list " vprintf HAVE_VPRINTF"
+
+# Auxiliary files required by this configure script.
+ac_aux_files="missing install-sh config.guess config.sub"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.."
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+# Check whether --with-static was given.
+if test ${with_static+y}
+then :
+ withval=$with_static;
+fi
+
+
+if test "$with_static" = "yes"
+then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Compiling with staticaly linked libraries." >&5
+printf "%s\n" "$as_me: Compiling with staticaly linked libraries." >&6;}
+ LIBS="$LIBS -static"
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Compiling with dynamically linked libraries." >&5
+printf "%s\n" "$as_me: Compiling with dynamically linked libraries." >&6;}
+fi
+
+
+# Check whether --with-cpu was given.
+if test ${with_cpu+y}
+then :
+ withval=$with_cpu;
+fi
+
+
+if test -z "$with_cpu"
+then
+
+
+
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+else
+ host_cpu=$with_cpu
+fi
+# Checking for target cpu and setting custom configuration
+# for the different platforms
+case "$host_cpu" in #(
+ *x86_64*) :
+
+
+printf "%s\n" "#define STRESSAPPTEST_CPU_X86_64 /**/" >>confdefs.h
+
+ ;; #(
+ *i686*) :
+
+
+printf "%s\n" "#define STRESSAPPTEST_CPU_I686 /**/" >>confdefs.h
+
+ ;; #(
+ *mips*) :
+
+
+printf "%s\n" "#define STRESSAPPTEST_CPU_MIPS /**/" >>confdefs.h
+
+ ;; #(
+ *powerpc*) :
+
+
+printf "%s\n" "#define STRESSAPPTEST_CPU_PPC /**/" >>confdefs.h
+
+ ;; #(
+ *armv7a*) :
+
+
+printf "%s\n" "#define STRESSAPPTEST_CPU_ARMV7A /**/" >>confdefs.h
+
+ ;; #(
+ *aarch64*) :
+
+
+printf "%s\n" "#define STRESSAPPTEST_CPU_AARCH64 /**/" >>confdefs.h
+
+ ;; #(
+ *loongarch*) :
+
+
+printf "%s\n" "#define STRESSAPPTEST_CPU_LOONGARCH /**/" >>confdefs.h
+
+ ;; #(
+ *) :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Unsupported CPU: $host_cpu! Try x86_64, i686, mips, powerpc, armv7a, aarch64 or loongarch" >&5
+printf "%s\n" "$as_me: WARNING: Unsupported CPU: $host_cpu! Try x86_64, i686, mips, powerpc, armv7a, aarch64 or loongarch" >&2;}
+ ;;
+esac
+
+## The following allows like systems to share settings. This is not meant to
+## imply that these OS are the same thing. From OpenOffice dmake configure.in
+case "$host_os" in #(
+ *linux*) :
+
+ OS_VERSION=linux
+
+printf "%s\n" "#define STRESSAPPTEST_OS_LINUX /**/" >>confdefs.h
+
+ ;; #(
+ *darwin*) :
+
+ OS_VERSION=macosx
+
+printf "%s\n" "#define STRESSAPPTEST_OS_DARWIN /**/" >>confdefs.h
+
+ ;; #(
+ *freebsd*) :
+
+ OS_VERSION=bsd
+
+printf "%s\n" "#define STRESSAPPTEST_OS_BSD /**/" >>confdefs.h
+
+ ;; #(
+ *netbsd*) :
+
+ OS_VERSION=bsd
+
+printf "%s\n" "#define STRESSAPPTEST_OS_BSD /**/" >>confdefs.h
+
+ ;; #(
+ *) :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unsupported system: $host_os" >&5
+printf "%s\n" "$as_me: WARNING: unsupported system: $host_os" >&2;}
+ ;;
+esac
+
+am__api_version='1.11'
+
+
+ # Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+printf %s "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test ${ac_cv_path_install+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ # Account for fact that we put trailing slashes in our PATH walk.
+case $as_dir in #((
+ ./ | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test ${ac_cv_path_install+y}; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+printf "%s\n" "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+printf %s "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[\\\"\#\$\&\'\`$am_lf]*)
+ as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+ *[\\\"\#\$\&\'\`$am_lf\ \ ]*)
+ as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
+alias in your environment" "$LINENO" 5
+ fi
+
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+
+ if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
+printf "%s\n" "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_STRIP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+printf "%s\n" "$STRIP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_STRIP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+printf "%s\n" "$ac_ct_STRIP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5
+printf %s "checking for a race-free mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+ if test ${ac_cv_path_mkdir+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in mkdir gmkdir; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue
+ case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #(
+ 'mkdir ('*'coreutils) '* | \
+ 'BusyBox '* | \
+ 'mkdir (fileutils) '4.1*)
+ ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext
+ break 3;;
+ esac
+ done
+ done
+ done
+IFS=$as_save_IFS
+
+fi
+
+ test -d ./--version && rmdir ./--version
+ if test ${ac_cv_path_mkdir+y}; then
+ MKDIR_P="$ac_cv_path_mkdir -p"
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for MKDIR_P within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ MKDIR_P="$ac_install_sh -d"
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+printf "%s\n" "$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+ [\\/$]* | ?:[\\/]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AWK+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AWK="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+printf "%s\n" "$AWK" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval test \${ac_cv_prog_make_${ac_make}_set+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ SET_MAKE=
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ am__isrc=' -I$(srcdir)'
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='stressapptest'
+ VERSION='1.0.11_autoconf'
+
+
+printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
+
+
+printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+ac_config_headers="$ac_config_headers src/stressapptest_config.h"
+
+
+# Checks for programs.
+# Don't generate CXXFLAGS defaults: if CXXFLAGS are unset
+# AC_PROG_CXX will override them with unwanted defaults.
+CXXFLAGS="$CXXFLAGS"
+
+
+
+
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CXX+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+printf "%s\n" "$CXX" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CXX+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+printf "%s\n" "$ac_ct_CXX" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5
+printf %s "checking whether the C++ compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else $as_nop
+ ac_file=''
+fi
+if test -z "$ac_file"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C++ compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5
+printf %s "checking for C++ compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+printf "%s\n" "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main (void)
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+printf "%s\n" "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_objext+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+printf "%s\n" "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5
+printf %s "checking whether the compiler supports GNU C++... " >&6; }
+if test ${ac_cv_cxx_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_compiler_gnu=yes
+else $as_nop
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+if test $ac_compiler_gnu = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+y}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+printf %s "checking whether $CXX accepts -g... " >&6; }
+if test ${ac_cv_prog_cxx_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_g=yes
+else $as_nop
+ CXXFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+
+else $as_nop
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+printf "%s\n" "$ac_cv_prog_cxx_g" >&6; }
+if test $ac_test_CXXFLAGS; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_prog_cxx_stdcxx=no
+if test x$ac_prog_cxx_stdcxx = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5
+printf %s "checking for $CXX option to enable C++11 features... " >&6; }
+if test ${ac_cv_prog_cxx_cxx11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cxx_cxx11=no
+ac_save_CXX=$CXX
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_cxx_conftest_cxx11_program
+_ACEOF
+for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA
+do
+ CXX="$ac_save_CXX $ac_arg"
+ if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_cxx11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cxx_cxx11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CXX=$ac_save_CXX
+fi
+
+if test "x$ac_cv_prog_cxx_cxx11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cxx_cxx11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5
+printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; }
+ CXX="$CXX $ac_cv_prog_cxx_cxx11"
+fi
+ ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11
+ ac_prog_cxx_stdcxx=cxx11
+fi
+fi
+if test x$ac_prog_cxx_stdcxx = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5
+printf %s "checking for $CXX option to enable C++98 features... " >&6; }
+if test ${ac_cv_prog_cxx_cxx98+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cxx_cxx98=no
+ac_save_CXX=$CXX
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_cxx_conftest_cxx98_program
+_ACEOF
+for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA
+do
+ CXX="$ac_save_CXX $ac_arg"
+ if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_cxx98=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cxx_cxx98" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CXX=$ac_save_CXX
+fi
+
+if test "x$ac_cv_prog_cxx_cxx98" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cxx_cxx98" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5
+printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; }
+ CXX="$CXX $ac_cv_prog_cxx_cxx98"
+fi
+ ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98
+ ac_prog_cxx_stdcxx=cxx98
+fi
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+printf %s "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+printf "%s\n" "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test ${enable_dependency_tracking+y}
+then :
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+
+depcc="$CXX" am_compiler_list=
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+printf %s "checking dependency style of $depcc... " >&6; }
+if test ${am_cv_CXX_dependencies_compiler_type+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CXX_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CXX_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5
+printf "%s\n" "$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+ am__fastdepCXX_TRUE=
+ am__fastdepCXX_FALSE='#'
+else
+ am__fastdepCXX_TRUE='#'
+ am__fastdepCXX_FALSE=
+fi
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
+
+
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion -version; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_compiler_gnu=yes
+else $as_nop
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+y}
+ac_save_CFLAGS=$CFLAGS
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_g=yes
+else $as_nop
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else $as_nop
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c11=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
+
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+ CC="$CC $ac_cv_prog_cc_c11"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+ ac_prog_cc_stdc=c11
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
+
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+ CC="$CC $ac_cv_prog_cc_c99"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+ ac_prog_cc_stdc=c99
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c89_program
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
+
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+ CC="$CC $ac_cv_prog_cc_c89"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+ ac_prog_cc_stdc=c89
+fi
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CC" am_compiler_list=
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+printf %s "checking dependency style of $depcc... " >&6; }
+if test ${am_cv_CC_dependencies_compiler_type+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+
+#Getting user and host info
+username=$(whoami)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking user ID" >&5
+printf %s "checking user ID... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $username" >&5
+printf "%s\n" "$username" >&6; }
+
+hostname=$(uname -n)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host name" >&5
+printf %s "checking host name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hostname" >&5
+printf "%s\n" "$hostname" >&6; }
+
+timestamp=$(date)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking current timestamp" >&5
+printf %s "checking current timestamp... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $timestamp" >&5
+printf "%s\n" "$timestamp" >&6; }
+
+if test -n "$SOURCE_DATE_EPOCH"
+then
+ timestamp=$(date -u -d "@$SOURCE_DATE_EPOCH" 2>/dev/null || date -u -r "$SOURCE_DATE_EPOCH" 2>/dev/null || date -u)
+ username=reproducible
+ hostname=reproducible
+fi
+
+
+printf "%s\n" "#define STRESSAPPTEST_TIMESTAMP \"$username @ $hostname on $timestamp\"" >>confdefs.h
+
+
+# Check whether --enable-default-optimizations was given.
+if test ${enable_default_optimizations+y}
+then :
+ enableval=$enable_default_optimizations;
+fi
+
+if test x"$enable_default_optimizations" != xno
+then :
+
+ #Default cxxflags
+ CXXFLAGS="$CXXFLAGS -DCHECKOPTS"
+ CXXFLAGS="$CXXFLAGS -Wreturn-type -Wunused -Wuninitialized -Wall"
+ CXXFLAGS="$CXXFLAGS -O3 -funroll-all-loops -funroll-loops -DNDEBUG"
+
+fi
+
+
+# Check whether --enable-largefile was given.
+if test ${enable_largefile+y}
+then :
+ enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+printf %s "checking for special C compiler options needed for large files... " >&6; }
+if test ${ac_cv_sys_largefile_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_sys_largefile_CC=no
+ if test "$GCC" != yes; then
+ ac_save_CC=$CC
+ while :; do
+ # IRIX 6.2 and later do not support large files by default,
+ # so use the C compiler's -n32 option if that helps.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ CC="$CC -n32"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ break
+ done
+ CC=$ac_save_CC
+ rm -f conftest.$ac_ext
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+printf "%s\n" "$ac_cv_sys_largefile_CC" >&6; }
+ if test "$ac_cv_sys_largefile_CC" != no; then
+ CC=$CC$ac_cv_sys_largefile_CC
+ fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+printf %s "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if test ${ac_cv_sys_file_offset_bits+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_cv_sys_file_offset_bits=unknown
+ break
+done
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+printf "%s\n" "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+ no | unknown) ;;
+ *)
+printf "%s\n" "#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits" >>confdefs.h
+;;
+esac
+rm -rf conftest*
+ if test $ac_cv_sys_file_offset_bits = unknown; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+printf %s "checking for _LARGE_FILES value needed for large files... " >&6; }
+if test ${ac_cv_sys_large_files+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_cv_sys_large_files=unknown
+ break
+done
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+printf "%s\n" "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+ no | unknown) ;;
+ *)
+printf "%s\n" "#define _LARGE_FILES $ac_cv_sys_large_files" >>confdefs.h
+;;
+esac
+rm -rf conftest*
+ fi
+fi
+
+
+# Checks for header files.
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+ as_ac_Header=`printf "%s\n" "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5
+printf %s "checking for $ac_hdr that defines DIR... " >&6; }
+if eval test \${$as_ac_Header+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main (void)
+{
+if ((DIR *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$as_ac_Header=yes"
+else $as_nop
+ eval "$as_ac_Header=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+eval ac_res=\$$as_ac_Header
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+printf %s "checking for library containing opendir... " >&6; }
+if test ${ac_cv_search_opendir+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char opendir ();
+int
+main (void)
+{
+return opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' dir
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_opendir=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_opendir+y}
+then :
+ break
+fi
+done
+if test ${ac_cv_search_opendir+y}
+then :
+
+else $as_nop
+ ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+printf "%s\n" "$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+printf %s "checking for library containing opendir... " >&6; }
+if test ${ac_cv_search_opendir+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char opendir ();
+int
+main (void)
+{
+return opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' x
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_opendir=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_opendir+y}
+then :
+ break
+fi
+done
+if test ${ac_cv_search_opendir+y}
+then :
+
+else $as_nop
+ ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+printf "%s\n" "$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+fi
+
+ac_header= ac_cache=
+for ac_item in $ac_header_c_list
+do
+ if test $ac_cache; then
+ ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+ if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+ printf "%s\n" "#define $ac_item 1" >> confdefs.h
+ fi
+ ac_header= ac_cache=
+ elif test $ac_header; then
+ ac_cache=$ac_item
+ else
+ ac_header=$ac_item
+ fi
+done
+
+
+
+
+
+
+
+
+if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+then :
+
+printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+printf %s "checking for grep that handles long lines and -e... " >&6; }
+if test ${ac_cv_path_GREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in grep ggrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+printf "%s\n" "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+# Autoupdate added the next two lines to ensure that your configure
+# script's behavior did not change. They are probably safe to remove.
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+printf %s "checking for egrep... " >&6; }
+if test ${ac_cv_path_EGREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in egrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+printf "%s\n" "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+
+# Skip malloc.h to prevent redefinition of HAVE_MALLOC_H on some platforms
+ for ac_header in arpa/inet.h fcntl.h netdb.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h
+do :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Missing some header files.
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+done
+ac_fn_c_check_header_compile "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_PTHREAD_H 1" >>confdefs.h
+
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5
+printf %s "checking for library containing pthread_create... " >&6; }
+if test ${ac_cv_search_pthread_create+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char pthread_create ();
+int
+main (void)
+{
+return pthread_create ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' pthread
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_pthread_create=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_pthread_create+y}
+then :
+ break
+fi
+done
+if test ${ac_cv_search_pthread_create+y}
+then :
+
+else $as_nop
+ ac_cv_search_pthread_create=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create" >&5
+printf "%s\n" "$ac_cv_search_pthread_create" >&6; }
+ac_res=$ac_cv_search_pthread_create
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+ac_fn_c_check_type "$LINENO" "pthread_barrier_t" "ac_cv_type_pthread_barrier_t" "$ac_includes_default"
+if test "x$ac_cv_type_pthread_barrier_t" = xyes
+then :
+
+printf "%s\n" "#define HAVE_PTHREAD_BARRIERS 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_header_compile "$LINENO" "libaio.h" "ac_cv_header_libaio_h" "$ac_includes_default"
+if test "x$ac_cv_header_libaio_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBAIO_H 1" >>confdefs.h
+
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing io_setup" >&5
+printf %s "checking for library containing io_setup... " >&6; }
+if test ${ac_cv_search_io_setup+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char io_setup ();
+int
+main (void)
+{
+return io_setup ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' aio
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_io_setup=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_io_setup+y}
+then :
+ break
+fi
+done
+if test ${ac_cv_search_io_setup+y}
+then :
+
+else $as_nop
+ ac_cv_search_io_setup=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_io_setup" >&5
+printf "%s\n" "$ac_cv_search_io_setup" >&6; }
+ac_res=$ac_cv_search_io_setup
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+ac_fn_c_check_header_compile "$LINENO" "sys/shm.h" "ac_cv_header_sys_shm_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_shm_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_SHM_H 1" >>confdefs.h
+
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing shm_open" >&5
+printf %s "checking for library containing shm_open... " >&6; }
+if test ${ac_cv_search_shm_open+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char shm_open ();
+int
+main (void)
+{
+return shm_open ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' rt
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_shm_open=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_shm_open+y}
+then :
+ break
+fi
+done
+if test ${ac_cv_search_shm_open+y}
+then :
+
+else $as_nop
+ ac_cv_search_shm_open=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_shm_open" >&5
+printf "%s\n" "$ac_cv_search_shm_open" >&6; }
+ac_res=$ac_cv_search_shm_open
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
+if test "x$ac_cv_type__Bool" = xyes
+then :
+
+printf "%s\n" "#define HAVE__BOOL 1" >>confdefs.h
+
+
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
+printf %s "checking for stdbool.h that conforms to C99... " >&6; }
+if test ${ac_cv_header_stdbool_h+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdbool.h>
+
+ #ifndef __bool_true_false_are_defined
+ #error "__bool_true_false_are_defined is not defined"
+ #endif
+ char a[__bool_true_false_are_defined == 1 ? 1 : -1];
+
+ /* Regardless of whether this is C++ or "_Bool" is a
+ valid type name, "true" and "false" should be usable
+ in #if expressions and integer constant expressions,
+ and "bool" should be a valid type name. */
+
+ #if !true
+ #error "'true' is not true"
+ #endif
+ #if true != 1
+ #error "'true' is not equal to 1"
+ #endif
+ char b[true == 1 ? 1 : -1];
+ char c[true];
+
+ #if false
+ #error "'false' is not false"
+ #endif
+ #if false != 0
+ #error "'false' is not equal to 0"
+ #endif
+ char d[false == 0 ? 1 : -1];
+
+ enum { e = false, f = true, g = false * true, h = true * 256 };
+
+ char i[(bool) 0.5 == true ? 1 : -1];
+ char j[(bool) 0.0 == false ? 1 : -1];
+ char k[sizeof (bool) > 0 ? 1 : -1];
+
+ struct sb { bool s: 1; bool t; } s;
+ char l[sizeof s.t > 0 ? 1 : -1];
+
+ /* The following fails for
+ HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
+ bool m[h];
+ char n[sizeof m == h * sizeof m[0] ? 1 : -1];
+ char o[-1 - (bool) 0 < 0 ? 1 : -1];
+ /* Catch a bug in an HP-UX C compiler. See
+ https://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+ https://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
+ */
+ bool p = true;
+ bool *pp = &p;
+
+ /* C 1999 specifies that bool, true, and false are to be
+ macros, but C++ 2011 and later overrule this. */
+ #if __cplusplus < 201103
+ #ifndef bool
+ #error "bool is not defined"
+ #endif
+ #ifndef false
+ #error "false is not defined"
+ #endif
+ #ifndef true
+ #error "true is not defined"
+ #endif
+ #endif
+
+ /* If _Bool is available, repeat with it all the tests
+ above that used bool. */
+ #ifdef HAVE__BOOL
+ struct sB { _Bool s: 1; _Bool t; } t;
+
+ char q[(_Bool) 0.5 == true ? 1 : -1];
+ char r[(_Bool) 0.0 == false ? 1 : -1];
+ char u[sizeof (_Bool) > 0 ? 1 : -1];
+ char v[sizeof t.t > 0 ? 1 : -1];
+
+ _Bool w[h];
+ char x[sizeof m == h * sizeof m[0] ? 1 : -1];
+ char y[-1 - (_Bool) 0 < 0 ? 1 : -1];
+ _Bool z = true;
+ _Bool *pz = &p;
+ #endif
+
+int
+main (void)
+{
+
+ bool ps = &s;
+ *pp |= p;
+ *pp |= ! p;
+
+ #ifdef HAVE__BOOL
+ _Bool pt = &t;
+ *pz |= z;
+ *pz |= ! z;
+ #endif
+
+ /* Refer to every declared value, so they cannot be
+ discarded as unused. */
+ return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !j + !k
+ + !l + !m + !n + !o + !p + !pp + !ps
+ #ifdef HAVE__BOOL
+ + !q + !r + !u + !v + !w + !x + !y + !z + !pt
+ #endif
+ );
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_header_stdbool_h=yes
+else $as_nop
+ ac_cv_header_stdbool_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
+printf "%s\n" "$ac_cv_header_stdbool_h" >&6; }
+
+if test $ac_cv_header_stdbool_h = yes; then
+
+printf "%s\n" "#define HAVE_STDBOOL_H 1" >>confdefs.h
+
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
+printf %s "checking for an ANSI C-conforming const... " >&6; }
+if test ${ac_cv_c_const+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this sort of thing. */
+ typedef int charset[2];
+ const charset cs = { 0, 0 };
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *pcpcc;
+ char **ppc;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* IBM XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ pcpcc = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++pcpcc;
+ ppc = (char**) pcpcc;
+ pcpcc = (char const *const *) ppc;
+ { /* SCO 3.2v4 cc rejects this sort of thing. */
+ char tx;
+ char *t = &tx;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ if (s) return 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* IBM XL C 1.02.0.0 rejects this sort of thing, saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; } bx;
+ struct s *b = &bx; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ if (!foo) return 0;
+ }
+ return !cs[0] && !zero.x;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_c_const=yes
+else $as_nop
+ ac_cv_c_const=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
+printf "%s\n" "$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+printf "%s\n" "#define const /**/" >>confdefs.h
+
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+printf %s "checking for inline... " >&6; }
+if test ${ac_cv_c_inline+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo (void) {return 0; }
+$ac_kw foo_t foo (void) {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+printf "%s\n" "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+
+ ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default
+"
+if test "x$ac_cv_type_pid_t" = xyes
+then :
+
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #if defined _WIN64 && !defined __CYGWIN__
+ LLP64
+ #endif
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_pid_type='int'
+else $as_nop
+ ac_pid_type='__int64'
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+printf "%s\n" "#define pid_t $ac_pid_type" >>confdefs.h
+
+
+fi
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
+printf %s "checking for C/C++ restrict keyword... " >&6; }
+if test ${ac_cv_c_restrict+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_c_restrict=no
+ # Put '__restrict__' first, to avoid problems with glibc and non-GCC; see:
+ # https://lists.gnu.org/archive/html/bug-autoconf/2016-02/msg00006.html
+ # Put 'restrict' last, because C++ lacks it.
+ for ac_kw in __restrict__ __restrict _Restrict restrict; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+typedef int *int_ptr;
+ int foo (int_ptr $ac_kw ip) { return ip[0]; }
+ int bar (int [$ac_kw]); /* Catch GCC bug 14050. */
+ int bar (int ip[$ac_kw]) { return ip[0]; }
+
+int
+main (void)
+{
+int s[1];
+ int *$ac_kw t = s;
+ t[0] = 0;
+ return foo (t) + bar (t);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_c_restrict=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ test "$ac_cv_c_restrict" != no && break
+ done
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_restrict" >&5
+printf "%s\n" "$ac_cv_c_restrict" >&6; }
+
+ case $ac_cv_c_restrict in
+ restrict) ;;
+ no) printf "%s\n" "#define restrict /**/" >>confdefs.h
+ ;;
+ *) printf "%s\n" "#define restrict $ac_cv_c_restrict" >>confdefs.h
+ ;;
+ esac
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes
+then :
+
+else $as_nop
+
+printf "%s\n" "#define size_t unsigned int" >>confdefs.h
+
+fi
+
+ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default"
+if test "x$ac_cv_type_ssize_t" = xyes
+then :
+
+else $as_nop
+
+printf "%s\n" "#define ssize_t int" >>confdefs.h
+
+fi
+
+
+
+# Obsolete code to be removed.
+if test $ac_cv_header_sys_time_h = yes; then
+
+printf "%s\n" "#define TIME_WITH_SYS_TIME 1" >>confdefs.h
+
+fi
+# End of obsolete code.
+
+ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t"
+case $ac_cv_c_uint16_t in #(
+ no|yes) ;; #(
+ *)
+
+
+printf "%s\n" "#define uint16_t $ac_cv_c_uint16_t" >>confdefs.h
+;;
+ esac
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working volatile" >&5
+printf %s "checking for working volatile... " >&6; }
+if test ${ac_cv_c_volatile+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+volatile int x;
+int * volatile y = (int *) 0;
+return !x && !y;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_c_volatile=yes
+else $as_nop
+ ac_cv_c_volatile=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_volatile" >&5
+printf "%s\n" "$ac_cv_c_volatile" >&6; }
+if test $ac_cv_c_volatile = no; then
+
+printf "%s\n" "#define volatile /**/" >>confdefs.h
+
+fi
+
+
+
+# Checks for library functions.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether closedir returns void" >&5
+printf %s "checking whether closedir returns void... " >&6; }
+if test ${ac_cv_func_closedir_void+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <$ac_header_dirent>
+
+int
+main (void)
+{
+
+ return closedir(0);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_func_closedir_void=no
+else $as_nop
+ ac_cv_func_closedir_void=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_closedir_void" >&5
+printf "%s\n" "$ac_cv_func_closedir_void" >&6; }
+if test $ac_cv_func_closedir_void = yes; then
+
+printf "%s\n" "#define CLOSEDIR_VOID 1" >>confdefs.h
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+printf %s "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test ${ac_cv_prog_CPP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ # Double quotes because $CC needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else $as_nop
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else $as_nop
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+printf "%s\n" "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else $as_nop
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else $as_nop
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+if test $ac_cv_c_compiler_gnu = yes; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5
+printf %s "checking whether $CC needs -traditional... " >&6; }
+if test ${ac_cv_prog_gcc_traditional+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_pattern="Autoconf.*'x'"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1
+then :
+ ac_cv_prog_gcc_traditional=yes
+else $as_nop
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -rf conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1
+then :
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -rf conftest*
+
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5
+printf "%s\n" "$ac_cv_prog_gcc_traditional" >&6; }
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking types of arguments for select" >&5
+printf %s "checking types of arguments for select... " >&6; }
+if test ${ac_cv_func_select_args+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_func_select_args='int,int *,struct timeval *'
+for ac_arg234 in 'fd_set *' 'int *' 'void *'; do
+ for ac_arg1 in 'int' 'size_t' 'unsigned long int' 'unsigned int'; do
+ for ac_arg5 in 'struct timeval *' 'const struct timeval *'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+int
+main (void)
+{
+extern int select ($ac_arg1,
+ $ac_arg234, $ac_arg234, $ac_arg234,
+ $ac_arg5);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_func_select_args="$ac_arg1,$ac_arg234,$ac_arg5"; break 3
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ done
+ done
+done
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_select_args" >&5
+printf "%s\n" "$ac_cv_func_select_args" >&6; }
+ac_save_IFS=$IFS; IFS=','
+set dummy `echo "$ac_cv_func_select_args" | sed 's/\*/\*/g'`
+IFS=$ac_save_IFS
+shift
+
+printf "%s\n" "#define SELECT_TYPE_ARG1 $1" >>confdefs.h
+
+
+printf "%s\n" "#define SELECT_TYPE_ARG234 ($2)" >>confdefs.h
+
+
+printf "%s\n" "#define SELECT_TYPE_ARG5 ($3)" >>confdefs.h
+
+rm -rf conftest*
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5
+printf %s "checking return type of signal handlers... " >&6; }
+if test ${ac_cv_type_signal+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <signal.h>
+
+int
+main (void)
+{
+return *(signal (0, 0)) (0) == 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_type_signal=int
+else $as_nop
+ ac_cv_type_signal=void
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5
+printf "%s\n" "$ac_cv_type_signal" >&6; }
+
+printf "%s\n" "#define RETSIGTYPE $ac_cv_type_signal" >>confdefs.h
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5
+printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; }
+if test ${ac_cv_c_undeclared_builtin_options+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_save_CFLAGS=$CFLAGS
+ ac_cv_c_undeclared_builtin_options='cannot detect'
+ for ac_arg in '' -fno-builtin; do
+ CFLAGS="$ac_save_CFLAGS $ac_arg"
+ # This test program should *not* compile successfully.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+(void) strchr;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else $as_nop
+ # This test program should compile successfully.
+ # No library function is consistently available on
+ # freestanding implementations, so test against a dummy
+ # declaration. Include always-available headers on the
+ # off chance that they somehow elicit warnings.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <float.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+extern void ac_decl (int, char *);
+
+int
+main (void)
+{
+(void) ac_decl (0, (char *) 0);
+ (void) ac_decl;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ if test x"$ac_arg" = x
+then :
+ ac_cv_c_undeclared_builtin_options='none needed'
+else $as_nop
+ ac_cv_c_undeclared_builtin_options=$ac_arg
+fi
+ break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ done
+ CFLAGS=$ac_save_CFLAGS
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5
+printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; }
+ case $ac_cv_c_undeclared_builtin_options in #(
+ 'cannot detect') :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot make $CC report undeclared builtins
+See \`config.log' for more details" "$LINENO" 5; } ;; #(
+ 'none needed') :
+ ac_c_undeclared_builtin_options='' ;; #(
+ *) :
+ ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;;
+esac
+
+ac_fn_check_decl "$LINENO" "strerror_r" "ac_cv_have_decl_strerror_r" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_strerror_r" = xyes
+then :
+ ac_have_decl=1
+else $as_nop
+ ac_have_decl=0
+fi
+printf "%s\n" "#define HAVE_DECL_STRERROR_R $ac_have_decl" >>confdefs.h
+
+
+if test $ac_cv_have_decl_strerror_r = yes; then
+ # For backward compatibility's sake, define HAVE_STRERROR_R.
+ # (We used to run AC_CHECK_FUNCS_ONCE for strerror_r, as well
+ # as AC_CHECK_DECLS_ONCE.)
+
+printf "%s\n" "#define HAVE_STRERROR_R 1" >>confdefs.h
+
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether strerror_r returns char *" >&5
+printf %s "checking whether strerror_r returns char *... " >&6; }
+if test ${ac_cv_func_strerror_r_char_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ ac_cv_func_strerror_r_char_p=no
+ if test $ac_cv_have_decl_strerror_r = yes; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+int
+main (void)
+{
+
+ char buf[100];
+ char x = *strerror_r (0, buf, sizeof buf);
+ char *p = strerror_r (0, buf, sizeof buf);
+ return !p || x;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_func_strerror_r_char_p=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+ fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strerror_r_char_p" >&5
+printf "%s\n" "$ac_cv_func_strerror_r_char_p" >&6; }
+if test $ac_cv_func_strerror_r_char_p = yes; then
+
+printf "%s\n" "#define STRERROR_R_CHAR_P 1" >>confdefs.h
+
+fi
+
+ac_func=
+for ac_item in $ac_func_c_list
+do
+ if test $ac_func; then
+ ac_fn_c_check_func "$LINENO" $ac_func ac_cv_func_$ac_func
+ if eval test \"x\$ac_cv_func_$ac_func\" = xyes; then
+ echo "#define $ac_item 1" >> confdefs.h
+ fi
+ ac_func=
+ else
+ ac_func=$ac_item
+ fi
+done
+
+if test "x$ac_cv_func_vprintf" = xno
+then :
+ ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt"
+if test "x$ac_cv_func__doprnt" = xyes
+then :
+
+printf "%s\n" "#define HAVE_DOPRNT 1" >>confdefs.h
+
+fi
+
+fi
+ac_fn_c_check_func "$LINENO" "ftruncate" "ac_cv_func_ftruncate"
+if test "x$ac_cv_func_ftruncate" = xyes
+then :
+ printf "%s\n" "#define HAVE_FTRUNCATE 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday"
+if test "x$ac_cv_func_gettimeofday" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "memset" "ac_cv_func_memset"
+if test "x$ac_cv_func_memset" = xyes
+then :
+ printf "%s\n" "#define HAVE_MEMSET 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "munmap" "ac_cv_func_munmap"
+if test "x$ac_cv_func_munmap" = xyes
+then :
+ printf "%s\n" "#define HAVE_MUNMAP 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "select" "ac_cv_func_select"
+if test "x$ac_cv_func_select" = xyes
+then :
+ printf "%s\n" "#define HAVE_SELECT 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket"
+if test "x$ac_cv_func_socket" = xyes
+then :
+ printf "%s\n" "#define HAVE_SOCKET 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "strtol" "ac_cv_func_strtol"
+if test "x$ac_cv_func_strtol" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRTOL 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "strtoull" "ac_cv_func_strtoull"
+if test "x$ac_cv_func_strtoull" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRTOULL 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_func "$LINENO" "mmap64" "ac_cv_func_mmap64"
+if test "x$ac_cv_func_mmap64" = xyes
+then :
+ printf "%s\n" "#define HAVE_MMAP64 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "posix_memalign" "ac_cv_func_posix_memalign"
+if test "x$ac_cv_func_posix_memalign" = xyes
+then :
+ printf "%s\n" "#define HAVE_POSIX_MEMALIGN 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "rand_r" "ac_cv_func_rand_r"
+if test "x$ac_cv_func_rand_r" = xyes
+then :
+ printf "%s\n" "#define HAVE_RAND_R 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "sched_getaffinity" "ac_cv_func_sched_getaffinity"
+if test "x$ac_cv_func_sched_getaffinity" = xyes
+then :
+ printf "%s\n" "#define HAVE_SCHED_GETAFFINITY 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_func "$LINENO" "pthread_rwlockattr_setkind_np" "ac_cv_func_pthread_rwlockattr_setkind_np"
+if test "x$ac_cv_func_pthread_rwlockattr_setkind_np" = xyes
+then :
+ printf "%s\n" "#define HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP 1" >>confdefs.h
+
+fi
+
+
+ac_config_files="$ac_config_files Makefile src/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+ if test -n "$EXEEXT"; then
+ am__EXEEXT_TRUE=
+ am__EXEEXT_FALSE='#'
+else
+ am__EXEEXT_TRUE='#'
+ am__EXEEXT_FALSE=
+fi
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else $as_nop
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
+as_nl='
+'
+export as_nl
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
+
+# The user is always right.
+if ${PATH_SEPARATOR+false} :; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ printf "%s\n" "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else $as_nop
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else $as_nop
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by stressapptest $as_me 1.0.11_autoconf, which was
+generated by GNU Autoconf 2.71. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <opensource@google.com>."
+
+_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config='$ac_cs_config_escaped'
+ac_cs_version="\\
+stressapptest config.status 1.0.11_autoconf
+configured by $0, generated by GNU Autoconf 2.71,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2021 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ printf "%s\n" "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ printf "%s\n" "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ printf "%s\n" "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ printf "%s\n" "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "src/stressapptest_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/stressapptest_config.h" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
+ test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers
+ test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ printf "%s\n" "/* $configure_input */" >&1 \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+printf "%s\n" "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ printf "%s\n" "/* $configure_input */" >&1 \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$_am_arg" : 'X\(//\)[^/]' \| \
+ X"$_am_arg" : 'X\(//\)$' \| \
+ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$_am_arg" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+ :C) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+printf "%s\n" "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+ # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir=$dirpart/$fdir; as_fn_mkdir_p
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+ ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
diff --git a/external/subpack/utils/stressapptest/src/configure.ac b/external/subpack/utils/stressapptest/src/configure.ac
new file mode 100644
index 0000000..d6fd01a
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/configure.ac
@@ -0,0 +1,167 @@
+AC_PREREQ(2.61)
+AC_INIT([stressapptest], [1.0.11_autoconf], [opensource@google.com])
+
+AC_ARG_WITH(static, [ --with-static enable static linking])
+
+if test "$with_static" = "yes"
+then
+ AC_MSG_NOTICE([Compiling with staticaly linked libraries.])
+ LIBS="$LIBS -static"
+else
+ AC_MSG_NOTICE([Compiling with dynamically linked libraries.])
+fi
+
+AC_ARG_WITH(cpu, [ --with-cpu define host cpu])
+
+AC_CANONICAL_HOST
+
+if test -n "$with_cpu"
+then
+ host_cpu=$with_cpu
+fi
+# Checking for target cpu and setting custom configuration
+# for the different platforms
+AS_CASE(["$host_cpu"],
+ [*x86_64*], [
+ AC_DEFINE([STRESSAPPTEST_CPU_X86_64],[],
+ [Defined if the target CPU is x86_64])
+ ],
+ [*i686*], [
+ AC_DEFINE([STRESSAPPTEST_CPU_I686],[],
+ [Defined if the target CPU is i686])
+ ],
+ [*mips*], [
+ AC_DEFINE([STRESSAPPTEST_CPU_MIPS],[],
+ [Defined if the target CPU is MIPS])
+ ],
+ [*powerpc*], [
+ AC_DEFINE([STRESSAPPTEST_CPU_PPC],[],
+ [Defined if the target CPU is PowerPC])
+ ],
+ [*armv7a*], [
+ AC_DEFINE([STRESSAPPTEST_CPU_ARMV7A],[],
+ [Defined if the target CPU is armv7a])
+ ],
+ [*aarch64*], [
+ AC_DEFINE([STRESSAPPTEST_CPU_AARCH64],[],
+ [Defined if the target CPU is aarch64])
+ ],
+ [*loongarch*], [
+ AC_DEFINE([STRESSAPPTEST_CPU_LOONGARCH],[],
+ [Defined if the target CPU is LOONGARCH])
+ ],
+[AC_MSG_WARN([Unsupported CPU: $host_cpu! Try x86_64, i686, mips, powerpc, armv7a, aarch64 or loongarch])]
+)
+
+## The following allows like systems to share settings. This is not meant to
+## imply that these OS are the same thing. From OpenOffice dmake configure.in
+AS_CASE(["$host_os"],
+ [*linux*], [
+ OS_VERSION=linux
+ AC_DEFINE([STRESSAPPTEST_OS_LINUX],[],
+ [Defined if the target OS is Linux])
+ ],
+ [*darwin*], [
+ OS_VERSION=macosx
+ AC_DEFINE([STRESSAPPTEST_OS_DARWIN],[],
+ [Defined if the target OS is OSX])
+ ],
+ [*freebsd*], [
+ OS_VERSION=bsd
+ AC_DEFINE([STRESSAPPTEST_OS_BSD],[],
+ [Defined if the target OS is BSD based])
+ ],
+ [*netbsd*], [
+ OS_VERSION=bsd
+ AC_DEFINE([STRESSAPPTEST_OS_BSD],[],
+ [Defined if the target OS is BSD based])
+ ],
+ [AC_MSG_WARN([unsupported system: $host_os])]
+)
+
+AM_INIT_AUTOMAKE([-Wall -Werror foreign])
+AC_CONFIG_SRCDIR([src/])
+AC_CONFIG_HEADER([src/stressapptest_config.h])
+
+# Checks for programs.
+# Don't generate CXXFLAGS defaults: if CXXFLAGS are unset
+# AC_PROG_CXX will override them with unwanted defaults.
+CXXFLAGS="$CXXFLAGS"
+AC_PROG_CXX
+AC_PROG_CC
+
+#Getting user and host info
+username=$(whoami)
+AC_MSG_CHECKING([user ID])
+AC_MSG_RESULT([$username])
+
+hostname=$(uname -n)
+AC_MSG_CHECKING([host name])
+AC_MSG_RESULT([$hostname])
+
+timestamp=$(date)
+AC_MSG_CHECKING([current timestamp])
+AC_MSG_RESULT([$timestamp])
+
+if test -n "$SOURCE_DATE_EPOCH"
+then
+ timestamp=$(date -u -d "@$SOURCE_DATE_EPOCH" 2>/dev/null || date -u -r "$SOURCE_DATE_EPOCH" 2>/dev/null || date -u)
+ username=reproducible
+ hostname=reproducible
+fi
+
+AC_DEFINE_UNQUOTED([STRESSAPPTEST_TIMESTAMP],
+ "$username @ $hostname on $timestamp",
+ [Timestamp when ./configure was executed])
+
+AC_ARG_ENABLE([default-optimizations],
+ [AS_HELP_STRING([--disable-default-optimizations], [Disable default optimization flag overrides])])
+AS_IF([test x"$enable_default_optimizations" != xno], [
+ #Default cxxflags
+ CXXFLAGS="$CXXFLAGS -DCHECKOPTS"
+ CXXFLAGS="$CXXFLAGS -Wreturn-type -Wunused -Wuninitialized -Wall"
+ CXXFLAGS="$CXXFLAGS -O3 -funroll-all-loops -funroll-loops -DNDEBUG"
+])
+
+AC_SYS_LARGEFILE
+
+# Checks for header files.
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+# Skip malloc.h to prevent redefinition of HAVE_MALLOC_H on some platforms
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h], [], [AC_MSG_FAILURE([Missing some header files.])])
+AC_CHECK_HEADERS([pthread.h])
+AC_SEARCH_LIBS([pthread_create], [pthread])
+AC_CHECK_TYPE([pthread_barrier_t], AC_DEFINE(HAVE_PTHREAD_BARRIERS, [1], [Define to 1 if the system has `pthread_barrier'.]))
+AC_CHECK_HEADERS([libaio.h])
+AC_SEARCH_LIBS([io_setup], [aio])
+AC_CHECK_HEADERS([sys/shm.h])
+AC_SEARCH_LIBS([shm_open], [rt])
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_HEADER_STDBOOL
+AC_C_CONST
+AC_C_INLINE
+AC_TYPE_PID_T
+AC_C_RESTRICT
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_HEADER_TIME
+AC_TYPE_UINT16_T
+AC_C_VOLATILE
+
+
+# Checks for library functions.
+AC_FUNC_CLOSEDIR_VOID
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_SELECT_ARGTYPES
+AC_TYPE_SIGNAL
+AC_FUNC_STRERROR_R
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS([ftruncate gettimeofday memset munmap select socket strtol strtoull])
+AC_CHECK_FUNCS([mmap64 posix_memalign rand_r sched_getaffinity])
+AC_CHECK_FUNCS([pthread_rwlockattr_setkind_np])
+
+AC_CONFIG_FILES([Makefile src/Makefile])
+AC_OUTPUT
diff --git a/external/subpack/utils/stressapptest/src/depcomp b/external/subpack/utils/stressapptest/src/depcomp
new file mode 100755
index 0000000..e5f9736
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/depcomp
@@ -0,0 +1,589 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2007-03-29.01
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software
+# Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+ '')
+ echo "$0: No command. Try \`$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+ depmode Dependency tracking mode.
+ source Source file read by `PROGRAMS ARGS'.
+ object Object file output by `PROGRAMS ARGS'.
+ DEPDIR directory where to store dependencies.
+ depfile Dependency file to output.
+ tmpdepfile Temporary file to use when outputing dependencies.
+ libtool Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "depcomp $scriptversion"
+ exit $?
+ ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+ sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay! Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff. Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am. Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+ for arg
+ do
+ case $arg in
+ -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+ *) set fnord "$@" "$arg" ;;
+ esac
+ shift # fnord
+ shift # $arg
+ done
+ "$@"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+ tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'. On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like `#:fec' to the end of the
+ # dependency line.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+ tr '
+' ' ' >> $depfile
+ echo >> $depfile
+
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> $depfile
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. In older versions, this file always lives in the
+ # current directory. Also, the AIX compiler puts `$object:' at the
+ # start of each line; $object doesn't have directory information.
+ # Version 6 uses the directory in both cases.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$base.u
+ tmpdepfile3=$dir.libs/$base.u
+ "$@" -Wc,-M
+ else
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$dir$base.u
+ tmpdepfile3=$dir$base.u
+ "$@" -M
+ fi
+ stat=$?
+
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form `foo.o: dependent.h'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+icc)
+ # Intel's C compiler understands `-MD -MF file'. However on
+ # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+ # ICC 7.0 will fill foo.d with something like
+ # foo.o: sub/foo.c
+ # foo.o: sub/foo.h
+ # which is wrong. We want:
+ # sub/foo.o: sub/foo.c
+ # sub/foo.o: sub/foo.h
+ # sub/foo.c:
+ # sub/foo.h:
+ # ICC 7.1 will output
+ # foo.o: sub/foo.c sub/foo.h
+ # and will wrap long lines using \ :
+ # foo.o: sub/foo.c ... \
+ # sub/foo.h ... \
+ # ...
+
+ "$@" -MD -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ # Each line is of the form `foo.o: dependent.h',
+ # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process this invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+ sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp2)
+ # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+ # compilers, which have integrated preprocessors. The correct option
+ # to use with these is +Maked; it writes dependencies to a file named
+ # 'foo.d', which lands next to the object file, wherever that
+ # happens to be.
+ # Much of this is similar to the tru64 case; see comments there.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir.libs/$base.d
+ "$@" -Wc,+Maked
+ else
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir$base.d
+ "$@" +Maked
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+ # Add `dependent.h:' lines.
+ sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile" "$tmpdepfile2"
+ ;;
+
+tru64)
+ # The Tru64 compiler uses -MD to generate dependencies as a side
+ # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in `foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+ if test "$libtool" = yes; then
+ # With Tru64 cc, shared objects can also be used to make a
+ # static library. This mechanism is used in libtool 1.4 series to
+ # handle both shared and static libraries in a single compilation.
+ # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+ #
+ # With libtool 1.5 this exception was removed, and libtool now
+ # generates 2 separate objects for the 2 libraries. These two
+ # compilations output dependencies in $dir.libs/$base.o.d and
+ # in $dir$base.o.d. We have to check for both files, because
+ # one of the two compilations can be disabled. We should prefer
+ # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+ # automatically cleaned when .libs/ is deleted, while ignoring
+ # the former would cause a distcleancheck panic.
+ tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
+ tmpdepfile2=$dir$base.o.d # libtool 1.5
+ tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
+ tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
+ "$@" -Wc,-MD
+ else
+ tmpdepfile1=$dir$base.o.d
+ tmpdepfile2=$dir$base.d
+ tmpdepfile3=$dir$base.d
+ tmpdepfile4=$dir$base.d
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ test -z "$dashmflag" && dashmflag=-M
+ # Require at least two characters before searching for `:'
+ # in the target name. This is to cope with DOS-style filenames:
+ # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+ "$@" $dashmflag |
+ sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ "$@" || exit $?
+ # Remove any Libtool call
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+ # X makedepend
+ shift
+ cleared=no
+ for arg in "$@"; do
+ case $cleared in
+ no)
+ set ""; shift
+ cleared=yes ;;
+ esac
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift ;;
+ # Strip any option that makedepend may not understand. Remove
+ # the object too, otherwise makedepend will parse it as a source file.
+ -*|$object)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift ;;
+ esac
+ done
+ obj_suffix="`echo $object | sed 's/^.*\././'`"
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ "$@" -E |
+ sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+ sed '$ s: \\$::' > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ "$@" || exit $?
+ IFS=" "
+ for arg
+ do
+ case "$arg" in
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+ set fnord "$@"
+ shift
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
+ esac
+ done
+ "$@" -E |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
+ echo " " >> "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/external/subpack/utils/stressapptest/src/install-sh b/external/subpack/utils/stressapptest/src/install-sh
new file mode 100755
index 0000000..a5897de
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/install-sh
@@ -0,0 +1,519 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2006-12-25.00
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t) dst_arg=$2
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ trap '(exit $?); exit' 1 2 13 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dst_arg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ -*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test -z "$d" && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/external/subpack/utils/stressapptest/src/missing b/external/subpack/utils/stressapptest/src/missing
new file mode 100755
index 0000000..1c8ff70
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/missing
@@ -0,0 +1,367 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2006-05-10.23
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ # Exit code 63 means version mismatch. This often happens
+ # when the user try to use an ancient version of a tool on
+ # a file that requires a minimum version. In this case we
+ # we should proceed has if the program had been absent, or
+ # if --run hadn't been passed.
+ if test $? = 63; then
+ run=:
+ msg="probably too old"
+ fi
+ ;;
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ autom4te touch the output file, or create a stub one
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Send bug reports to <bug-automake@gnu.org>."
+ exit $?
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing $scriptversion (GNU Automake)"
+ exit $?
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+esac
+
+# Now exit if we have it, but it failed. Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).
+case $1 in
+ lex|yacc)
+ # Not GNU programs, they don't have --version.
+ ;;
+
+ tar)
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ exit 1
+ fi
+ ;;
+
+ *)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ # Could not run --version or --help. This is probably someone
+ # running `$TOOL --version' or `$TOOL --help' to check whether
+ # $TOOL exists and not knowing $TOOL uses missing.
+ exit 1
+ fi
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $1 in
+ aclocal*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case $f in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ autom4te)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them.
+ You can get \`$1' as part of \`Autoconf' from any GNU
+ archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo "#! /bin/sh"
+ echo "# Created by GNU Automake missing as a replacement of"
+ echo "# $ $@"
+ echo "exit 0"
+ chmod +x $file
+ exit 1
+ fi
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' $msg. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f y.tab.h; then
+ echo >y.tab.h
+ fi
+ if test ! -f y.tab.c; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f lex.yy.c; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit 1
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ # The file to touch is that specified with -o ...
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -z "$file"; then
+ # ... or it is the one specified with @setfilename ...
+ infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '
+ /^@setfilename/{
+ s/.* \([^ ]*\) *$/\1/
+ p
+ q
+ }' $infile`
+ # ... or it is derived from the source name (dir/f.texi becomes f.info)
+ test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+ fi
+ # If the file does not exist, the user really needs makeinfo;
+ # let's fail without touching anything.
+ test -f $file || exit 1
+ touch $file
+ ;;
+
+ tar)
+ shift
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar "$@" && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar "$@" && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case $firstarg in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ case $firstarg in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequisites for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/external/subpack/utils/stressapptest/src/src/Makefile.am b/external/subpack/utils/stressapptest/src/src/Makefile.am
new file mode 100644
index 0000000..16f539d
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/Makefile.am
@@ -0,0 +1,34 @@
+bin_PROGRAMS = stressapptest
+noinst_PROGRAMS = findmask
+
+AM_DEFAULT_SOURCE_EXT=.cc
+
+MAINFILES = main.cc
+CFILES = os.cc
+CFILES += os_factory.cc
+CFILES += pattern.cc
+CFILES += queue.cc
+CFILES += sat.cc
+CFILES += sat_factory.cc
+CFILES += worker.cc
+CFILES += finelock_queue.cc
+CFILES += error_diag.cc
+CFILES += disk_blocks.cc
+CFILES += adler32memcpy.cc
+CFILES += logger.cc
+
+HFILES = os.h
+HFILES += pattern.h
+HFILES += queue.h
+HFILES += sat.h
+HFILES += worker.h
+HFILES += sattypes.h
+HFILES += finelock_queue.h
+HFILES += error_diag.h
+HFILES += disk_blocks.h
+HFILES += adler32memcpy.h
+HFILES += logger.h
+HFILES += clock.h
+
+stressapptest_SOURCES = $(MAINFILES) $(CFILES) $(HFILES)
+findmask_SOURCES = findmask.c findmask.inc
diff --git a/external/subpack/utils/stressapptest/src/src/Makefile.in b/external/subpack/utils/stressapptest/src/src/Makefile.in
new file mode 100644
index 0000000..ff320f3
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/Makefile.in
@@ -0,0 +1,542 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = stressapptest$(EXEEXT)
+noinst_PROGRAMS = findmask$(EXEEXT)
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/stressapptest_config.h.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = stressapptest_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+am_findmask_OBJECTS = findmask.$(OBJEXT)
+findmask_OBJECTS = $(am_findmask_OBJECTS)
+findmask_LDADD = $(LDADD)
+am__objects_1 = main.$(OBJEXT)
+am__objects_2 = os.$(OBJEXT) os_factory.$(OBJEXT) pattern.$(OBJEXT) \
+ queue.$(OBJEXT) sat.$(OBJEXT) sat_factory.$(OBJEXT) \
+ worker.$(OBJEXT) finelock_queue.$(OBJEXT) error_diag.$(OBJEXT) \
+ disk_blocks.$(OBJEXT) adler32memcpy.$(OBJEXT) logger.$(OBJEXT)
+am__objects_3 =
+am_stressapptest_OBJECTS = $(am__objects_1) $(am__objects_2) \
+ $(am__objects_3)
+stressapptest_OBJECTS = $(am_stressapptest_OBJECTS)
+stressapptest_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+SOURCES = $(findmask_SOURCES) $(stressapptest_SOURCES)
+DIST_SOURCES = $(findmask_SOURCES) $(stressapptest_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_DEFAULT_SOURCE_EXT = .cc
+MAINFILES = main.cc
+CFILES = os.cc os_factory.cc pattern.cc queue.cc sat.cc sat_factory.cc \
+ worker.cc finelock_queue.cc error_diag.cc disk_blocks.cc \
+ adler32memcpy.cc logger.cc
+HFILES = os.h pattern.h queue.h sat.h worker.h sattypes.h \
+ finelock_queue.h error_diag.h disk_blocks.h adler32memcpy.h \
+ logger.h clock.h
+stressapptest_SOURCES = $(MAINFILES) $(CFILES) $(HFILES)
+findmask_SOURCES = findmask.c findmask.inc
+all: stressapptest_config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cc .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+stressapptest_config.h: stamp-h1
+ @if test ! -f $@; then \
+ rm -f stamp-h1; \
+ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+ else :; fi
+
+stamp-h1: $(srcdir)/stressapptest_config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status src/stressapptest_config.h
+$(srcdir)/stressapptest_config.h.in: $(am__configure_deps)
+ ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f stressapptest_config.h stamp-h1
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+findmask$(EXEEXT): $(findmask_OBJECTS) $(findmask_DEPENDENCIES)
+ @rm -f findmask$(EXEEXT)
+ $(LINK) $(findmask_OBJECTS) $(findmask_LDADD) $(LIBS)
+stressapptest$(EXEEXT): $(stressapptest_OBJECTS) $(stressapptest_DEPENDENCIES)
+ @rm -f stressapptest$(EXEEXT)
+ $(CXXLINK) $(stressapptest_OBJECTS) $(stressapptest_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adler32memcpy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disk_blocks.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error_diag.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findmask.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/finelock_queue.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_factory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pattern.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/queue.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sat_factory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/worker.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.cc.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) stressapptest_config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) stressapptest_config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) stressapptest_config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) stressapptest_config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) stressapptest_config.h
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: all install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic clean-noinstPROGRAMS ctags distclean \
+ distclean-compile distclean-generic distclean-hdr \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-binPROGRAMS install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-binPROGRAMS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/external/subpack/utils/stressapptest/src/src/adler32memcpy.cc b/external/subpack/utils/stressapptest/src/src/adler32memcpy.cc
new file mode 100644
index 0000000..d67a362
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/adler32memcpy.cc
@@ -0,0 +1,627 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "adler32memcpy.h"
+
+// We are using (a modified form of) adler-32 checksum algorithm instead
+// of CRC since adler-32 is faster than CRC.
+// (Comparison: http://guru.multimedia.cx/crc32-vs-adler32/)
+// This form of adler is bit modified, instead of treating the data in
+// units of bytes, 32-bit data is taken as a unit and two 64-bit
+// checksums are done (we could have one checksum but two checksums
+// make the code run faster).
+
+// Adler-32 implementation:
+// Data is treated as 1-byte numbers and,
+// there are two 16-bit numbers a and b
+// Initialize a with 1 and b with 0.
+// for each data unit 'd'
+// a += d
+// b += a
+// checksum = a<<16 + b
+// This sum should never overflow.
+//
+// Adler-64+64 implementation:
+// (applied in this code)
+// Data is treated as 32-bit numbers and whole data is separated into two
+// streams, and hence the two checksums a1, a2, b1 and b2.
+// Initialize a1 and a2 with 1, b1 and b2 with 0
+// add first dataunit to a1
+// add a1 to b1
+// add second dataunit to a1
+// add a1 to b1
+// add third dataunit to a2
+// add a2 to b2
+// add fourth dataunit to a2
+// add a2 to b2
+// ...
+// repeat the sequence back for next 4 dataunits
+//
+// variable A = XMM6 and variable B = XMM7.
+// (a1 = lower 8 bytes of XMM6 and b1 = lower 8 bytes of XMM7)
+
+// Assumptions
+// 1. size_in_bytes is a multiple of 16.
+// 2. srcmem and dstmem are 16 byte aligned.
+// 3. size_in_bytes is less than 2^19 bytes.
+
+// Assumption 3 ensures that there is no overflow when numbers are being
+// added (we can remove this assumption by doing modulus with a prime
+// number when it is just about to overflow but that would be a very costly
+// exercise)
+
+// Returns true if the checksums are equal.
+bool AdlerChecksum::Equals(const AdlerChecksum &other) const {
+ return ( (a1_ == other.a1_) && (a2_ == other.a2_) &&
+ (b1_ == other.b1_) && (b2_ == other.b2_) );
+}
+
+// Returns string representation of the Adler checksum.
+string AdlerChecksum::ToHexString() const {
+ char buffer[128];
+ snprintf(buffer, sizeof(buffer), "%016llx %016llx %016llx %016llx", a1_, a2_, b1_, b2_);
+ return string(buffer);
+}
+
+// Sets components of the Adler checksum.
+void AdlerChecksum::Set(uint64 a1, uint64 a2, uint64 b1, uint64 b2) {
+ a1_ = a1;
+ a2_ = a2;
+ b1_ = b1;
+ b2_ = b2;
+}
+
+// Calculates Adler checksum for supplied data.
+bool CalculateAdlerChecksum(uint64 *data64, unsigned int size_in_bytes,
+ AdlerChecksum *checksum) {
+ // Use this data wrapper to access memory with 64bit read/write.
+ datacast_t data;
+ unsigned int count = size_in_bytes / sizeof(data);
+
+ if (count > (1U) << 19) {
+ // Size is too large, must be strictly less than 512 KB.
+ return false;
+ }
+
+ uint64 a1 = 1;
+ uint64 a2 = 1;
+ uint64 b1 = 0;
+ uint64 b2 = 0;
+
+ unsigned int i = 0;
+ while (i < count) {
+ // Process 64 bits at a time.
+ data.l64 = data64[i];
+ a1 = a1 + data.l32.l;
+ b1 = b1 + a1;
+ a1 = a1 + data.l32.h;
+ b1 = b1 + a1;
+ i++;
+
+ data.l64 = data64[i];
+ a2 = a2 + data.l32.l;
+ b2 = b2 + a2;
+ a2 = a2 + data.l32.h;
+ b2 = b2 + a2;
+ i++;
+ }
+ checksum->Set(a1, a2, b1, b2);
+ return true;
+}
+
+// C implementation of Adler memory copy.
+bool AdlerMemcpyC(uint64 *dstmem64, uint64 *srcmem64,
+ unsigned int size_in_bytes, AdlerChecksum *checksum) {
+ // Use this data wrapper to access memory with 64bit read/write.
+ datacast_t data;
+ unsigned int count = size_in_bytes / sizeof(data);
+
+ if (count > ((1U) << 19)) {
+ // Size is too large, must be strictly less than 512 KB.
+ return false;
+ }
+
+ uint64 a1 = 1;
+ uint64 a2 = 1;
+ uint64 b1 = 0;
+ uint64 b2 = 0;
+
+ unsigned int i = 0;
+ while (i < count) {
+ // Process 64 bits at a time.
+ data.l64 = srcmem64[i];
+ a1 = a1 + data.l32.l;
+ b1 = b1 + a1;
+ a1 = a1 + data.l32.h;
+ b1 = b1 + a1;
+ dstmem64[i] = data.l64;
+ i++;
+
+ data.l64 = srcmem64[i];
+ a2 = a2 + data.l32.l;
+ b2 = b2 + a2;
+ a2 = a2 + data.l32.h;
+ b2 = b2 + a2;
+ dstmem64[i] = data.l64;
+ i++;
+ }
+ checksum->Set(a1, a2, b1, b2);
+ return true;
+}
+
+// C implementation of Adler memory copy with some float point ops,
+// attempting to warm up the CPU.
+bool AdlerMemcpyWarmC(uint64 *dstmem64, uint64 *srcmem64,
+ unsigned int size_in_bytes, AdlerChecksum *checksum) {
+ // Use this data wrapper to access memory with 64bit read/write.
+ datacast_t data;
+ unsigned int count = size_in_bytes / sizeof(data);
+
+ if (count > ((1U) << 19)) {
+ // Size is too large, must be strictly less than 512 KB.
+ return false;
+ }
+
+ uint64 a1 = 1;
+ uint64 a2 = 1;
+ uint64 b1 = 0;
+ uint64 b2 = 0;
+
+ double a = 2.0 * static_cast<double>(srcmem64[0]);
+ double b = 5.0 * static_cast<double>(srcmem64[0]);
+ double c = 7.0 * static_cast<double>(srcmem64[0]);
+ double d = 9.0 * static_cast<double>(srcmem64[0]);
+
+ unsigned int i = 0;
+ while (i < count) {
+ // Process 64 bits at a time.
+ data.l64 = srcmem64[i];
+ a1 = a1 + data.l32.l;
+ b1 = b1 + a1;
+ a1 = a1 + data.l32.h;
+ b1 = b1 + a1;
+ dstmem64[i] = data.l64;
+ i++;
+
+ // Warm cpu up.
+ a = a * b;
+ b = b + c;
+
+ data.l64 = srcmem64[i];
+ a2 = a2 + data.l32.l;
+ b2 = b2 + a2;
+ a2 = a2 + data.l32.h;
+ b2 = b2 + a2;
+ dstmem64[i] = data.l64;
+ i++;
+
+ // Warm cpu up.
+ c = c * d;
+ d = d + d;
+ }
+
+ // Warm cpu up.
+ d = a + b + c + d;
+ if (d == 1.0) {
+ // Reference the result so that it can't be discarded by the compiler.
+ printf("Log: This will probably never happen.\n");
+ }
+
+ checksum->Set(a1, a2, b1, b2);
+ return true;
+}
+
+// x86_64 SSE2 assembly implementation of fast and stressful Adler memory copy.
+bool AdlerMemcpyAsm(uint64 *dstmem64, uint64 *srcmem64,
+ unsigned int size_in_bytes, AdlerChecksum *checksum) {
+// Use assembly implementation where supported.
+#if defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
+
+// Pull a bit of tricky preprocessing to make the inline asm both
+// 32 bit and 64 bit.
+#ifdef STRESSAPPTEST_CPU_I686 // Instead of coding both, x86...
+#define rAX "%%eax"
+#define rCX "%%ecx"
+#define rDX "%%edx"
+#define rBX "%%ebx"
+#define rSP "%%esp"
+#define rBP "%%ebp"
+#define rSI "%%esi"
+#define rDI "%%edi"
+#endif
+
+#ifdef STRESSAPPTEST_CPU_X86_64 // ...and x64, we use rXX macros.
+#define rAX "%%rax"
+#define rCX "%%rcx"
+#define rDX "%%rdx"
+#define rBX "%%rbx"
+#define rSP "%%rsp"
+#define rBP "%%rbp"
+#define rSI "%%rsi"
+#define rDI "%%rdi"
+#endif
+
+ // Elements 0 to 3 are used for holding checksum terms a1, a2,
+ // b1, b2 respectively. These elements are filled by asm code.
+ // Elements 4 and 5 are used by asm code to for ANDing MMX data and removing
+ // 2 words from each MMX register (A MMX reg has 4 words, by ANDing we are
+ // setting word index 0 and word index 2 to zero).
+ // Element 6 and 7 are used for setting a1 and a2 to 1.
+ volatile uint64 checksum_arr[] __attribute__ ((aligned(16))) =
+ {0, 0, 0, 0, 0x00000000ffffffffUL, 0x00000000ffffffffUL, 1, 1};
+
+ if ((size_in_bytes >> 19) > 0) {
+ // Size is too large. Must be less than 2^19 bytes = 512 KB.
+ return false;
+ }
+
+ // Number of 32-bit words which are not added to a1/a2 in the main loop.
+ uint32 remaining_words = (size_in_bytes % 48) / 4;
+
+ // Since we are moving 48 bytes at a time number of iterations = total size/48
+ // is value of counter.
+ uint32 num_of_48_byte_units = size_in_bytes / 48;
+
+ asm volatile (
+ // Source address is in ESI (extended source index)
+ // destination is in EDI (extended destination index)
+ // and counter is already in ECX (extended counter
+ // index).
+ "cmp $0, " rCX ";" // Compare counter to zero.
+ "jz END;"
+
+ // XMM6 is initialized with 1 and XMM7 with 0.
+ "prefetchnta 0(" rSI ");"
+ "prefetchnta 64(" rSI ");"
+ "movdqu 48(" rAX "), %%xmm6;"
+ "xorps %%xmm7, %%xmm7;"
+
+ // Start of the loop which copies 48 bytes from source to dst each time.
+ "TOP:\n"
+
+ // Make 6 moves each of 16 bytes from srcmem to XMM registers.
+ // We are using 2 words out of 4 words in each XMM register,
+ // word index 0 and word index 2
+ "movdqa 0(" rSI "), %%xmm0;"
+ "movdqu 4(" rSI "), %%xmm1;" // Be careful to use unaligned move here.
+ "movdqa 16(" rSI "), %%xmm2;"
+ "movdqu 20(" rSI "), %%xmm3;"
+ "movdqa 32(" rSI "), %%xmm4;"
+ "movdqu 36(" rSI "), %%xmm5;"
+
+ // Move 3 * 16 bytes from XMM registers to dstmem.
+ // Note: this copy must be performed before pinsrw instructions since
+ // they will modify the XMM registers.
+ "movntdq %%xmm0, 0(" rDI ");"
+ "movntdq %%xmm2, 16(" rDI ");"
+ "movntdq %%xmm4, 32(" rDI ");"
+
+ // Sets the word[1] and word[3] of XMM0 to XMM5 to zero.
+ "andps 32(" rAX "), %%xmm0;"
+ "andps 32(" rAX "), %%xmm1;"
+ "andps 32(" rAX "), %%xmm2;"
+ "andps 32(" rAX "), %%xmm3;"
+ "andps 32(" rAX "), %%xmm4;"
+ "andps 32(" rAX "), %%xmm5;"
+
+ // Add XMM0 to XMM6 and then add XMM6 to XMM7.
+ // Repeat this for XMM1, ..., XMM5.
+ // Overflow(for XMM7) can occur only if there are more
+ // than 2^16 additions => more than 2^17 words => more than 2^19 bytes so
+ // if size_in_bytes > 2^19 than overflow occurs.
+ "paddq %%xmm0, %%xmm6;"
+ "paddq %%xmm6, %%xmm7;"
+ "paddq %%xmm1, %%xmm6;"
+ "paddq %%xmm6, %%xmm7;"
+ "paddq %%xmm2, %%xmm6;"
+ "paddq %%xmm6, %%xmm7;"
+ "paddq %%xmm3, %%xmm6;"
+ "paddq %%xmm6, %%xmm7;"
+ "paddq %%xmm4, %%xmm6;"
+ "paddq %%xmm6, %%xmm7;"
+ "paddq %%xmm5, %%xmm6;"
+ "paddq %%xmm6, %%xmm7;"
+
+ // Increment ESI and EDI by 48 bytes and decrement counter by 1.
+ "add $48, " rSI ";"
+ "add $48, " rDI ";"
+ "prefetchnta 0(" rSI ");"
+ "prefetchnta 64(" rSI ");"
+ "dec " rCX ";"
+ "jnz TOP;"
+
+ // Now only remaining_words 32-bit words are left.
+ // make a loop, add first two words to a1 and next two to a2 (just like
+ // above loop, the only extra thing we are doing is rechecking
+ // rDX (=remaining_words) everytime we add a number to a1/a2.
+ "REM_IS_STILL_NOT_ZERO:\n"
+ // Unless remaining_words becomes less than 4 words(16 bytes)
+ // there is not much issue and remaining_words will always
+ // be a multiple of four by assumption.
+ "cmp $4, " rDX ";"
+ // In case for some weird reasons if remaining_words becomes
+ // less than 4 but not zero then also break the code and go off to END.
+ "jl END;"
+ // Otherwise just go on and copy data in chunks of 4-words at a time till
+ // whole data (<48 bytes) is copied.
+ "movdqa 0(" rSI "), %%xmm0;" // Copy next 4-words to XMM0 and to XMM1.
+
+ "movdqa 0(" rSI "), %%xmm5;" // Accomplish movdqu 4(%rSI) without
+ "pshufd $0x39, %%xmm5, %%xmm1;" // indexing off memory boundary.
+
+ "movntdq %%xmm0, 0(" rDI ");" // Copy 4-words to destination.
+ "andps 32(" rAX "), %%xmm0;"
+ "andps 32(" rAX "), %%xmm1;"
+ "paddq %%xmm0, %%xmm6;"
+ "paddq %%xmm6, %%xmm7;"
+ "paddq %%xmm1, %%xmm6;"
+ "paddq %%xmm6, %%xmm7;"
+ "add $16, " rSI ";"
+ "add $16, " rDI ";"
+ "sub $4, " rDX ";"
+ // Decrement %rDX by 4 since %rDX is number of 32-bit
+ // words left after considering all 48-byte units.
+ "jmp REM_IS_STILL_NOT_ZERO;"
+
+ "END:\n"
+ // Report checksum values A and B (both right now are two concatenated
+ // 64 bit numbers and have to be converted to 64 bit numbers)
+ // seems like Adler128 (since size of each part is 4 byte rather than
+ // 1 byte).
+ "movdqa %%xmm6, 0(" rAX ");"
+ "movdqa %%xmm7, 16(" rAX ");"
+ "sfence;"
+
+ // No output registers.
+ :
+ // Input registers.
+ : "S" (srcmem64), "D" (dstmem64), "a" (checksum_arr),
+ "c" (num_of_48_byte_units), "d" (remaining_words)
+ ); // asm.
+
+ if (checksum != NULL) {
+ checksum->Set(checksum_arr[0], checksum_arr[1],
+ checksum_arr[2], checksum_arr[3]);
+ }
+
+ // Everything went fine, so return true (this does not mean
+ // that there is no problem with memory this just mean that data was copied
+ // from src to dst and checksum was calculated successfully).
+ return true;
+#elif defined(STRESSAPPTEST_CPU_AARCH64) || defined(STRESSAPPTEST_CPU_ARMV7A) && defined(__ARM_NEON__)
+#if defined(STRESSAPPTEST_CPU_AARCH64)
+#define src_r "x3"
+#define dst_r "x4"
+#define blocks_r "w5"
+#define crc_r "x6"
+#else
+#define src_r "r3"
+#define dst_r "r4"
+#define blocks_r "r5"
+#define crc_r "r6"
+#endif
+ // Elements 0 to 3 are used for holding checksum terms a1, a2,
+ // b1, b2 respectively. These elements are filled by asm code.
+ // Checksum is seeded with the null checksum.
+ volatile uint64 checksum_arr[] __attribute__ ((aligned(16))) =
+ {1, 1, 0, 0};
+
+ if ((size_in_bytes >> 19) > 0) {
+ // Size is too large. Must be less than 2^19 bytes = 512 KB.
+ return false;
+ }
+
+ // Since we are moving 64 bytes at a time number of iterations = total size/64
+ uint32 blocks = size_in_bytes / 64;
+
+ uint64 *dst = dstmem64;
+ uint64 *src = srcmem64;
+
+#if defined(STRESSAPPTEST_CPU_AARCH64)
+ asm volatile (
+ "mov " src_r ", %[src];\n"
+ "mov " dst_r ", %[dst];\n"
+ "mov " crc_r ", %[crc];\n"
+ "mov " blocks_r ", %w[blocks];\n"
+
+ // Loop over block count.
+ "cmp " blocks_r ", #0;\n" // Compare counter to zero.
+ "ble END;\n"
+
+
+ // Preload upcoming cacheline.
+ "prfm pldl1strm, [" src_r ", #0 ];\n"
+ "prfm pldl1strm, [" src_r ", #64 ];\n"
+ "prfm pldl1strm, [" src_r ", #128 ];\n"
+ "prfm pldl1strm, [" src_r ", #192];\n"
+ "prfm pldl1strm, [" src_r ", #256];\n"
+
+ // Init checksum
+ "ld1 {v0.2d}, [" crc_r "];\n"
+ "dup v1.2d, xzr;\n"
+
+ // Start of the loop which copies 64 bytes from source to dst each time.
+ "TOP:\n"
+
+ // Preload some stuff.
+ "prfm pldl1strm, [" src_r ", #320];\n"
+ "prfm pldl1strm, [" src_r ", #384];\n"
+
+ // Make 3 moves each of 16 bytes from srcmem to qX registers.
+ // We are using 2 words out of 4 words in each qX register,
+ // word index 0 and word index 2. We'll swizzle them in a bit.
+ // Copy it.
+ "ld1 {v8.2d, v9.2d, v10.2d, v11.2d}, [" src_r "], #64;\n"
+ "st1 {v8.2d, v9.2d, v10.2d, v11.2d}, [" dst_r "], #64;\n"
+
+ // Arrange it.
+ "dup v12.4s, wzr; \n"
+ "dup v13.4s, wzr; \n"
+ "dup v14.4s, wzr; \n"
+ "dup v15.4s, wzr; \n"
+ "dup v16.4s, wzr; \n"
+ // This exchenges words 1,3 in the filled registers with
+ // words 0,2 in the empty registers.
+ "trn1 v12.4s, v8.4s, v12.4s; \n"
+ "trn2 v8.4s, v8.4s, v16.4s; \n"
+ "trn1 v13.4s, v9.4s, v13.4s; \n"
+ "trn2 v9.4s, v9.4s, v16.4s; \n"
+ "trn1 v14.4s, v10.4s, v14.4s; \n"
+ "trn2 v10.4s, v10.4s, v16.4s; \n"
+ "trn1 v15.4s, v11.4s, v15.4s; \n"
+ "trn2 v11.4s, v11.4s, v16.4s; \n"
+
+ // Sum into v0, then into v1.
+ // Repeat this for v8 - v11 and their counterparts.
+ // Overflow can occur only if there are more
+ // than 2^16 additions => more than 2^17 words => more than 2^19 bytes so
+ // if size_in_bytes > 2^19 than overflow occurs.
+ "add v0.2d, v0.2d, v12.2d;\n"
+ "add v1.2d, v1.2d, v0.2d;\n"
+ "add v0.2d, v0.2d, v8.2d;\n"
+ "add v1.2d, v1.2d, v0.2d;\n"
+ "add v0.2d, v0.2d, v13.2d;\n"
+ "add v1.2d, v1.2d, v0.2d;\n"
+ "add v0.2d, v0.2d, v9.2d;\n"
+ "add v1.2d, v1.2d, v0.2d;\n"
+
+ "add v0.2d, v0.2d, v14.2d;\n"
+ "add v1.2d, v1.2d, v0.2d;\n"
+ "add v0.2d, v0.2d, v10.2d;\n"
+ "add v1.2d, v1.2d, v0.2d;\n"
+ "add v0.2d, v0.2d, v15.2d;\n"
+ "add v1.2d, v1.2d, v0.2d;\n"
+ "add v0.2d, v0.2d, v11.2d;\n"
+ "add v1.2d, v1.2d, v0.2d;\n"
+
+ // Increment counter and loop.
+ "sub " blocks_r ", " blocks_r ", #1;\n"
+ "cmp " blocks_r ", #0;\n" // Compare counter to zero.
+ "bgt TOP;\n"
+
+
+ "END:\n"
+ // Report checksum values A and B (both right now are two concatenated
+ // 64 bit numbers and have to be converted to 64 bit numbers)
+ // seems like Adler128 (since size of each part is 4 byte rather than
+ // 1 byte).
+ "st1 {v0.2d, v1.2d}, [" crc_r "]; \n"
+
+ // Output registers.
+ :
+ // Input registers.
+ : [src] "r"(src), [dst] "r"(dst), [blocks] "r"(blocks) , [crc] "r"(checksum_arr)
+ : "memory", "cc", src_r, dst_r, blocks_r, crc_r, "v0","v1","v8","v9","v10","v11","v12","v13","v14","v15","v16"
+ ); // asm.
+#else
+ asm volatile (
+ "mov " src_r ", %[src]; \n"
+ "mov " dst_r ", %[dst]; \n"
+ "mov " crc_r ", %[crc]; \n"
+ "mov " blocks_r ", %[blocks]; \n"
+
+ // Loop over block count.
+ "cmp " blocks_r ", #0; \n" // Compare counter to zero.
+ "ble END; \n"
+
+
+ // Preload upcoming cacheline.
+ "pld [" src_r ", #0x0]; \n"
+ "pld [" src_r ", #0x20]; \n"
+
+ // Init checksum
+ "vldm " crc_r ", {q0}; \n"
+ "vmov.i32 q1, #0; \n"
+
+ // Start of the loop which copies 48 bytes from source to dst each time.
+ "TOP: \n"
+
+ // Make 3 moves each of 16 bytes from srcmem to qX registers.
+ // We are using 2 words out of 4 words in each qX register,
+ // word index 0 and word index 2. We'll swizzle them in a bit.
+ // Copy it.
+ "vldm " src_r "!, {q8, q9, q10, q11}; \n"
+ "vstm " dst_r "!, {q8, q9, q10, q11}; \n"
+
+ // Arrange it.
+ "vmov.i64 q12, #0; \n"
+ "vmov.i64 q13, #0; \n"
+ "vmov.i64 q14, #0; \n"
+ "vmov.i64 q15, #0; \n"
+ // This exchenges words 1,3 in the filled registers with
+ // words 0,2 in the empty registers.
+ "vtrn.32 q8, q12; \n"
+ "vtrn.32 q9, q13; \n"
+ "vtrn.32 q10, q14; \n"
+ "vtrn.32 q11, q15; \n"
+
+ // Sum into q0, then into q1.
+ // Repeat this for q8 - q13.
+ // Overflow can occur only if there are more
+ // than 2^16 additions => more than 2^17 words => more than 2^19 bytes so
+ // if size_in_bytes > 2^19 than overflow occurs.
+ "vadd.i64 q0, q0, q8; \n"
+ "vadd.i64 q1, q1, q0; \n"
+ "vadd.i64 q0, q0, q12; \n"
+ "vadd.i64 q1, q1, q0; \n"
+ "vadd.i64 q0, q0, q9; \n"
+ "vadd.i64 q1, q1, q0; \n"
+ "vadd.i64 q0, q0, q13; \n"
+ "vadd.i64 q1, q1, q0; \n"
+
+ "vadd.i64 q0, q0, q10; \n"
+ "vadd.i64 q1, q1, q0; \n"
+ "vadd.i64 q0, q0, q14; \n"
+ "vadd.i64 q1, q1, q0; \n"
+ "vadd.i64 q0, q0, q11; \n"
+ "vadd.i64 q1, q1, q0; \n"
+ "vadd.i64 q0, q0, q15; \n"
+ "vadd.i64 q1, q1, q0; \n"
+
+ // Increment counter and loop.
+ "sub " blocks_r ", " blocks_r ", #1; \n"
+ "cmp " blocks_r ", #0; \n" // Compare counter to zero.
+ "bgt TOP; \n"
+
+
+ "END:\n"
+ // Report checksum values A and B (both right now are two concatenated
+ // 64 bit numbers and have to be converted to 64 bit numbers)
+ // seems like Adler128 (since size of each part is 4 byte rather than
+ // 1 byte).
+ "vstm " crc_r ", {q0, q1}; \n"
+
+ // Output registers.
+ :
+ // Input registers.
+ : [src] "r"(src), [dst] "r"(dst), [blocks] "r"(blocks) , [crc] "r"(checksum_arr)
+ : "memory", "cc", "r3", "r4", "r5", "r6", "q0", "q1", "q8","q9","q10", "q11", "q12","q13","q14","q15"
+ ); // asm.
+#endif
+
+ if (checksum != NULL) {
+ checksum->Set(checksum_arr[0], checksum_arr[1],
+ checksum_arr[2], checksum_arr[3]);
+ }
+
+ // Everything went fine, so return true (this does not mean
+ // that there is no problem with memory this just mean that data was copied
+ // from src to dst and checksum was calculated successfully).
+ return true;
+#else
+ #warning "No vector copy defined for this architecture."
+ // Fall back to C implementation for anything else.
+ return AdlerMemcpyWarmC(dstmem64, srcmem64, size_in_bytes, checksum);
+#endif
+}
diff --git a/external/subpack/utils/stressapptest/src/src/adler32memcpy.h b/external/subpack/utils/stressapptest/src/src/adler32memcpy.h
new file mode 100644
index 0000000..d053340
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/adler32memcpy.h
@@ -0,0 +1,59 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STRESSAPPTEST_ADLER32MEMCPY_H_
+#define STRESSAPPTEST_ADLER32MEMCPY_H_
+
+#include <string>
+#include "sattypes.h"
+
+// Encapsulation for Adler checksum. Please see adler32memcpy.cc for more
+// detail on the adler checksum algorithm.
+class AdlerChecksum {
+ public:
+ AdlerChecksum() {}
+ ~AdlerChecksum() {}
+ // Returns true if the checksums are equal.
+ bool Equals(const AdlerChecksum &other) const;
+ // Returns string representation of the Adler checksum
+ string ToHexString() const;
+ // Sets components of the Adler checksum.
+ void Set(uint64 a1, uint64 a2, uint64 b1, uint64 b2);
+
+ private:
+ // Components of Adler checksum.
+ uint64 a1_, a2_, b1_, b2_;
+
+ DISALLOW_COPY_AND_ASSIGN(AdlerChecksum);
+};
+
+// Calculates Adler checksum for supplied data.
+bool CalculateAdlerChecksum(uint64 *data64, unsigned int size_in_bytes,
+ AdlerChecksum *checksum);
+
+// C implementation of Adler memory copy.
+bool AdlerMemcpyC(uint64 *dstmem64, uint64 *srcmem64,
+ unsigned int size_in_bytes, AdlerChecksum *checksum);
+
+// C implementation of Adler memory copy with some float point ops,
+// attempting to warm up the CPU.
+bool AdlerMemcpyWarmC(uint64 *dstmem64, uint64 *srcmem64,
+ unsigned int size_in_bytes, AdlerChecksum *checksum);
+
+// x86_64 SSE2 assembly implementation of fast and stressful Adler memory copy.
+bool AdlerMemcpyAsm(uint64 *dstmem64, uint64 *srcmem64,
+ unsigned int size_in_bytes, AdlerChecksum *checksum);
+
+
+#endif // STRESSAPPTEST_ADLER32MEMCPY_H_
diff --git a/external/subpack/utils/stressapptest/src/src/clock.h b/external/subpack/utils/stressapptest/src/src/clock.h
new file mode 100644
index 0000000..4204188
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/clock.h
@@ -0,0 +1,29 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+// Author: cferris
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STRESSAPPTEST_CLOCK_H_ // NOLINT
+#define STRESSAPPTEST_CLOCK_H_
+
+#include <time.h>
+
+// This class implements a clock that can be overriden for unit tests.
+class Clock {
+ public:
+ virtual ~Clock() {}
+
+ virtual time_t Now() { return time(NULL); }
+};
+
+#endif // STRESSAPPTEST_CLOCK_H_ NOLINT
diff --git a/external/subpack/utils/stressapptest/src/src/disk_blocks.cc b/external/subpack/utils/stressapptest/src/src/disk_blocks.cc
new file mode 100644
index 0000000..60018f9
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/disk_blocks.cc
@@ -0,0 +1,256 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Thread-safe container of disk blocks
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "disk_blocks.h"
+
+#include <utility>
+
+// BlockData
+BlockData::BlockData() : address_(0), size_(0),
+ references_(0), initialized_(false),
+ pattern_(NULL) {
+ pthread_mutex_init(&data_mutex_, NULL);
+}
+
+BlockData::~BlockData() {
+ pthread_mutex_destroy(&data_mutex_);
+}
+
+void BlockData::set_initialized() {
+ pthread_mutex_lock(&data_mutex_);
+ initialized_ = true;
+ pthread_mutex_unlock(&data_mutex_);
+}
+
+bool BlockData::initialized() const {
+ pthread_mutex_lock(&data_mutex_);
+ bool initialized = initialized_;
+ pthread_mutex_unlock(&data_mutex_);
+ return initialized;
+}
+
+// DiskBlockTable
+DiskBlockTable::DiskBlockTable() : sector_size_(0), write_block_size_(0),
+ device_name_(""), device_sectors_(0),
+ segment_size_(0), size_(0) {
+ pthread_mutex_init(&data_mutex_, NULL);
+ pthread_mutex_init(¶meter_mutex_, NULL);
+ pthread_cond_init(&data_condition_, NULL);
+}
+
+DiskBlockTable::~DiskBlockTable() {
+ pthread_mutex_destroy(&data_mutex_);
+ pthread_mutex_destroy(¶meter_mutex_);
+ pthread_cond_destroy(&data_condition_);
+}
+
+// 64-bit non-negative random number generator. Stolen from
+// depot/google3/base/tracecontext_unittest.cc.
+int64 DiskBlockTable::Random64() {
+ int64 x = random();
+ x = (x << 30) ^ random();
+ x = (x << 30) ^ random();
+ if (x >= 0)
+ return x;
+ else
+ return -x;
+}
+
+uint64 DiskBlockTable::Size() {
+ pthread_mutex_lock(&data_mutex_);
+ uint64 size = size_;
+ pthread_mutex_unlock(&data_mutex_);
+ return size;
+}
+
+void DiskBlockTable::InsertOnStructure(BlockData *block) {
+ int64 address = block->address();
+ StorageData *sd = new StorageData();
+ sd->block = block;
+ sd->pos = size_;
+ // Creating new block ...
+ pthread_mutex_lock(&data_mutex_);
+ if (pos_to_addr_.size() <= size_) {
+ pos_to_addr_.insert(pos_to_addr_.end(), address);
+ } else {
+ pos_to_addr_[size_] = address;
+ }
+ addr_to_block_[address] = sd;
+ size_++;
+ pthread_cond_broadcast(&data_condition_);
+ pthread_mutex_unlock(&data_mutex_);
+}
+
+int DiskBlockTable::RemoveBlock(BlockData *block) {
+ // For write threads, check the reference counter and remove
+ // it from the structure.
+ int64 address = block->address();
+ AddrToBlockMap::iterator it = addr_to_block_.find(address);
+ int ret = 1;
+ if (it != addr_to_block_.end()) {
+ int curr_pos = it->second->pos;
+ int last_pos = size_ - 1;
+ AddrToBlockMap::iterator last_it = addr_to_block_.find(
+ pos_to_addr_[last_pos]);
+ sat_assert(size_ > 0);
+ sat_assert(last_it != addr_to_block_.end());
+ // Everything is fine, removing block from table.
+ pthread_mutex_lock(&data_mutex_);
+ pos_to_addr_[curr_pos] = pos_to_addr_[last_pos];
+ last_it->second->pos = curr_pos;
+ delete it->second;
+ addr_to_block_.erase(it);
+ size_--;
+ block->DecreaseReferenceCounter();
+ if (block->GetReferenceCounter() == 0)
+ delete block;
+ else if (block->GetReferenceCounter() < 0)
+ ret = 0;
+ pthread_cond_broadcast(&data_condition_);
+ pthread_mutex_unlock(&data_mutex_);
+ } else {
+ ret = 0;
+ }
+ return ret;
+}
+
+int DiskBlockTable::ReleaseBlock(BlockData *block) {
+ // If caller is a random thread, just check the reference counter.
+ int ret = 1;
+ pthread_mutex_lock(&data_mutex_);
+ int references = block->GetReferenceCounter();
+ if (references == 1)
+ delete block;
+ else if (references > 0)
+ block->DecreaseReferenceCounter();
+ else
+ ret = 0;
+ pthread_mutex_unlock(&data_mutex_);
+ return ret;
+}
+
+BlockData *DiskBlockTable::GetRandomBlock() {
+ struct timespec ts;
+ struct timeval tp;
+ gettimeofday(&tp, NULL);
+ ts.tv_sec = tp.tv_sec;
+ ts.tv_nsec = tp.tv_usec * 1000;
+ ts.tv_sec += 2; // Wait for 2 seconds.
+ int result = 0;
+ pthread_mutex_lock(&data_mutex_);
+ while (!size_ && result != ETIMEDOUT) {
+ result = pthread_cond_timedwait(&data_condition_, &data_mutex_, &ts);
+ }
+ if (result == ETIMEDOUT) {
+ pthread_mutex_unlock(&data_mutex_);
+ return NULL;
+ } else {
+ int64 random_number = Random64();
+ int64 random_pos = random_number % size_;
+ int64 address = pos_to_addr_[random_pos];
+ AddrToBlockMap::const_iterator it = addr_to_block_.find(address);
+ sat_assert(it != addr_to_block_.end());
+ BlockData *b = it->second->block;
+ // A block is returned only if its content is written on disk.
+ if (b->initialized()) {
+ b->IncreaseReferenceCounter();
+ } else {
+ b = NULL;
+ }
+ pthread_mutex_unlock(&data_mutex_);
+ return b;
+ }
+}
+
+void DiskBlockTable::SetParameters(int sector_size,
+ int write_block_size,
+ int64 device_sectors,
+ int64 segment_size,
+ const string& device_name) {
+ sat_assert(size_ == 0);
+ pthread_mutex_lock(¶meter_mutex_);
+ sector_size_ = sector_size;
+ write_block_size_ = write_block_size;
+ device_sectors_ = device_sectors;
+ segment_size_ = segment_size;
+ device_name_ = device_name;
+ pthread_mutex_unlock(¶meter_mutex_);
+}
+
+BlockData *DiskBlockTable::GetUnusedBlock(int64 segment) {
+ int64 sector = 0;
+ BlockData *block = new BlockData();
+ bool good_sequence = false;
+ if (block == NULL) {
+ logprintf(0, "Process Error: Unable to allocate memory "
+ "for sector data for disk %s.\n", device_name_.c_str());
+ return NULL;
+ }
+ pthread_mutex_lock(¶meter_mutex_);
+ sat_assert(device_sectors_ != 0);
+ // Align the first sector with the beginning of a write block
+ int num_sectors = write_block_size_ / sector_size_;
+ for (int i = 0; i < kBlockRetry && !good_sequence; i++) {
+ good_sequence = true;
+ // Use the entire disk or a small segment of the disk to allocate the first
+ // sector in the block from.
+ if (segment_size_ == -1) {
+ sector = (Random64() & 0x7FFFFFFFFFFFFFFFLL) % (
+ device_sectors_ / num_sectors);
+ sector *= num_sectors;
+ } else {
+ sector = (Random64() & 0x7FFFFFFFFFFFFFFFLL) % (
+ segment_size_ / num_sectors);
+ sector *= num_sectors;
+ sector += segment * segment_size_;
+ // Make sure the block is within the segment.
+ if (sector + num_sectors > (segment + 1) * segment_size_) {
+ good_sequence = false;
+ continue;
+ }
+ }
+ // Make sure the entire block is in range.
+ if (sector + num_sectors > device_sectors_) {
+ good_sequence = false;
+ continue;
+ }
+ // Check to see if the block is free. Since the blocks are
+ // now aligned to the write_block_size, it is not necessary
+ // to check each sector, just the first block (a sector
+ // overlap will never occur).
+ pthread_mutex_lock(&data_mutex_);
+ if (addr_to_block_.find(sector) != addr_to_block_.end()) {
+ good_sequence = false;
+ }
+ pthread_mutex_unlock(&data_mutex_);
+ }
+
+ if (good_sequence) {
+ block->set_address(sector);
+ block->set_size(write_block_size_);
+ block->IncreaseReferenceCounter();
+ InsertOnStructure(block);
+ } else {
+ // No contiguous sequence of num_sectors sectors was found within
+ // kBlockRetry iterations so return an error value.
+ delete block;
+ block = NULL;
+ }
+ pthread_mutex_unlock(¶meter_mutex_);
+ return block;
+}
diff --git a/external/subpack/utils/stressapptest/src/src/disk_blocks.h b/external/subpack/utils/stressapptest/src/src/disk_blocks.h
new file mode 100644
index 0000000..638ee9f
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/disk_blocks.h
@@ -0,0 +1,174 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Interface for a thread-safe container of disk blocks
+
+#ifndef STRESSAPPTEST_DISK_BLOCKS_H_
+#define STRESSAPPTEST_DISK_BLOCKS_H_
+
+#include <sys/types.h>
+#include <pthread.h>
+#include <time.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <map>
+#include <vector>
+#include <string>
+
+#include "sattypes.h"
+
+class Pattern;
+
+// Data about a block written to disk so that it can be verified later.
+// Thread-unsafe, must be used with locks on non-const methods,
+// except for initialized accessor/mutator, which are thread-safe
+// (and in fact, is the only method supposed to be accessed from
+// someone which is not the thread-safe DiskBlockTable).
+class BlockData {
+ public:
+ BlockData();
+ ~BlockData();
+
+ // These are reference counters used to control how many
+ // threads currently have a copy of this particular block.
+ void IncreaseReferenceCounter() { references_++; }
+ void DecreaseReferenceCounter() { references_--; }
+ int GetReferenceCounter() const { return references_; }
+
+ // Controls whether the block was written on disk or not.
+ // Once written, you cannot "un-written" then without destroying
+ // this object.
+ void set_initialized();
+ bool initialized() const;
+
+ // Accessor methods for some data related to blocks.
+ void set_address(uint64 address) { address_ = address; }
+ uint64 address() const { return address_; }
+ void set_size(uint64 size) { size_ = size; }
+ uint64 size() const { return size_; }
+ void set_pattern(Pattern *p) { pattern_ = p; }
+ Pattern *pattern() { return pattern_; }
+ private:
+ uint64 address_; // Address of first sector in block
+ uint64 size_; // Size of block
+ int references_; // Reference counter
+ bool initialized_; // Flag indicating the block was written on disk
+ Pattern *pattern_;
+ mutable pthread_mutex_t data_mutex_;
+ DISALLOW_COPY_AND_ASSIGN(BlockData);
+};
+
+// A thread-safe table used to store block data and control access
+// to these blocks, letting several threads read and write blocks on
+// disk.
+class DiskBlockTable {
+ public:
+ DiskBlockTable();
+ virtual ~DiskBlockTable();
+
+ // Returns number of elements stored on table.
+ uint64 Size();
+
+ // Sets all initial parameters. Assumes all existent data is
+ // invalid and, therefore, must be removed.
+ void SetParameters(int sector_size, int write_block_size,
+ int64 device_sectors,
+ int64 segment_size,
+ const string& device_name);
+
+ // During the regular execution, there will be 2 types of threads:
+ // - Write thread: gets a large number of blocks using GetUnusedBlock,
+ // writes them on disk (if on destructive mode),
+ // reads block content ONCE from disk and them removes
+ // the block from queue with RemoveBlock. After a removal a
+ // block is not available for read threads, but it is
+ // only removed from memory if there is no reference for
+ // this block. Note that a write thread also counts as
+ // a reference.
+ // - Read threads: get one block at a time (if available) with
+ // GetRandomBlock, reads its content from disk,
+ // checking whether it is correct or not, and releases
+ // (Using ReleaseBlock) the block to be erased by the
+ // write threads. Since several read threads are allowed
+ // to read the same block, a reference counter is used to
+ // control when the block can be REALLY erased from
+ // memory, and all memory management is made by a
+ // DiskBlockTable instance.
+
+ // Returns a new block in a unused address. Does not
+ // grant ownership of the pointer to the caller
+ // (use RemoveBlock to delete the block from memory instead).
+ BlockData *GetUnusedBlock(int64 segment);
+
+ // Removes block from structure (called by write threads). Returns
+ // 1 if successful, 0 otherwise.
+ int RemoveBlock(BlockData *block);
+
+ // Gets a random block from the list. Only returns if an element
+ // is available (a write thread has got this block, written it on disk,
+ // and set this block as initialized). Does not grant ownership of the
+ // pointer to the caller (use RemoveBlock to delete the block from
+ // memory instead).
+ BlockData *GetRandomBlock();
+
+ // Releases block to be erased (called by random threads). Returns
+ // 1 if successful, 0 otherwise.
+ int ReleaseBlock(BlockData *block);
+
+ protected:
+ struct StorageData {
+ BlockData *block;
+ int pos;
+ };
+ typedef map<int64, StorageData*> AddrToBlockMap;
+ typedef vector<int64> PosToAddrVector;
+
+ // Inserts block in structure, used in tests and by other methods.
+ void InsertOnStructure(BlockData *block);
+
+ // Generates a random 64-bit integer.
+ // Virtual method so it can be overridden by the tests.
+ virtual int64 Random64();
+
+ // Accessor methods for testing.
+ const PosToAddrVector& pos_to_addr() const { return pos_to_addr_; }
+ const AddrToBlockMap& addr_to_block() const { return addr_to_block_; }
+
+ int sector_size() const { return sector_size_; }
+ int write_block_size() const { return write_block_size_; }
+ const string& device_name() const { return device_name_; }
+ int64 device_sectors() const { return device_sectors_; }
+ int64 segment_size() const { return segment_size_; }
+
+ private:
+ // Number of retries to allocate sectors.
+ static const int kBlockRetry = 100;
+ // Actual tables.
+ PosToAddrVector pos_to_addr_;
+ AddrToBlockMap addr_to_block_;
+
+ // Configuration parameters for block selection
+ int sector_size_; // Sector size, in bytes
+ int write_block_size_; // Block size, in bytes
+ string device_name_; // Device name
+ int64 device_sectors_; // Number of sectors in device
+ int64 segment_size_; // Segment size in bytes
+ uint64 size_; // Number of elements on table
+ pthread_mutex_t data_mutex_;
+ pthread_cond_t data_condition_;
+ pthread_mutex_t parameter_mutex_;
+ DISALLOW_COPY_AND_ASSIGN(DiskBlockTable);
+};
+
+#endif // STRESSAPPTEST_BLOCKS_H_
diff --git a/external/subpack/utils/stressapptest/src/src/error_diag.cc b/external/subpack/utils/stressapptest/src/src/error_diag.cc
new file mode 100644
index 0000000..53f056f
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/error_diag.cc
@@ -0,0 +1,317 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// error_diag.cc: Collects device errors for analysis to more accurately
+// pin-point failed component.
+
+#include <set>
+#include <list>
+#include <map>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "error_diag.h"
+#include "sattypes.h"
+
+
+// DeviceTree constructor.
+DeviceTree::DeviceTree(string name)
+ : parent_(0), name_(name) {
+ pthread_mutex_init(&device_tree_mutex_, NULL);
+}
+
+// DeviceTree destructor.
+DeviceTree::~DeviceTree() {
+ // Deallocate subtree devices.
+ for (std::map<string, DeviceTree*>::iterator itr = subdevices_.begin();
+ itr != subdevices_.end();
+ ++itr) {
+ delete itr->second;
+ }
+ // Deallocate device errors.
+ for (std::list<ErrorInstance*>::iterator itr = errors_.begin();
+ itr != errors_.end();
+ ++itr) {
+ delete (*itr);
+ }
+ pthread_mutex_destroy(&device_tree_mutex_);
+}
+
+// Atomically find named device in sub device tree.
+// Returns 0 if not found
+DeviceTree *DeviceTree::FindInSubTree(string name) {
+ DeviceTree *ret;
+ pthread_mutex_lock(&device_tree_mutex_);
+ ret = UnlockedFindInSubTree(name);
+ pthread_mutex_unlock(&device_tree_mutex_);
+ return ret;
+}
+
+// Find named device in sub device tree (Non-atomic).
+// Returns 0 if not found
+DeviceTree *DeviceTree::UnlockedFindInSubTree(string name) {
+ std::map<string, DeviceTree*>::iterator itr = subdevices_.find(name);
+ if (itr != subdevices_.end()) {
+ return itr->second;
+ } else {
+ // Search sub-tree.
+ for (std::map<string, DeviceTree*>::iterator itr = subdevices_.begin();
+ itr != subdevices_.end();
+ ++itr) {
+ DeviceTree *result = itr->second->UnlockedFindInSubTree(name);
+ if (result != 0)
+ return result;
+ }
+ return 0;
+ }
+}
+
+// Atomically add error instance to device.
+void DeviceTree::AddErrorInstance(ErrorInstance *error_instance) {
+ pthread_mutex_lock(&device_tree_mutex_);
+ errors_.push_back(error_instance);
+ pthread_mutex_unlock(&device_tree_mutex_);
+}
+
+// Find or add queried device as necessary.
+DeviceTree *DeviceTree::FindOrAddDevice(string name) {
+ // Assume named device does not exist and try to insert the device anyway.
+ // No-op if named device already exists.
+ InsertSubDevice(name);
+ // Find and return sub device pointer.
+ return FindInSubTree(name);
+}
+
+// Pretty prints device tree.
+void DeviceTree::PrettyPrint(string spacer) {
+ for (std::map<string, DeviceTree*>::iterator itr = subdevices_.begin();
+ itr != subdevices_.end();
+ ++itr) {
+ printf("%s%s\n", spacer.c_str(), itr->first.c_str());
+ itr->second->PrettyPrint(spacer+spacer);
+ }
+}
+
+// Atomically add sub device.
+// No-op if named device already exists.
+void DeviceTree::InsertSubDevice(string name) {
+ pthread_mutex_lock(&device_tree_mutex_);
+ if (UnlockedFindInSubTree(name) != 0) {
+ pthread_mutex_unlock(&device_tree_mutex_);
+ return;
+ }
+ subdevices_[name] = new DeviceTree(name);
+ subdevices_[name]->parent_ = this;
+ pthread_mutex_unlock(&device_tree_mutex_);
+}
+
+
+// Returns true of any error associated with this device is fatal.
+bool DeviceTree::KnownBad() {
+ pthread_mutex_lock(&device_tree_mutex_);
+ for (std::list<ErrorInstance*>::iterator itr = errors_.begin();
+ itr != errors_.end();
+ ++itr) {
+ if ((*itr)->severity_ == SAT_ERROR_FATAL) {
+ pthread_mutex_unlock(&device_tree_mutex_);
+ return true;
+ }
+ }
+ pthread_mutex_unlock(&device_tree_mutex_);
+ return false;
+}
+
+
+// ErrorDiag constructor.
+ErrorDiag::ErrorDiag() {
+ os_ = 0;
+ system_tree_root_ = 0;
+}
+
+// ErrorDiag destructor.
+ErrorDiag::~ErrorDiag() {
+ if (system_tree_root_)
+ delete system_tree_root_;
+}
+
+// Set platform specific handle and initialize device tree.
+// Returns false on error. true otherwise.
+bool ErrorDiag::set_os(OsLayer *os) {
+ os_ = os;
+ return(InitializeDeviceTree());
+}
+
+// Create and initialize system device tree.
+// Returns false on error. true otherwise.
+bool ErrorDiag::InitializeDeviceTree() {
+ system_tree_root_ = new DeviceTree("system_root");
+ if (!system_tree_root_)
+ return false;
+ return true;
+}
+
+// Logs info about a CECC.
+// Returns -1 on error, 1 if diagnoser reports error externally; 0 otherwise.
+int ErrorDiag::AddCeccError(string dimm_string) {
+ DeviceTree *dimm_device = system_tree_root_->FindOrAddDevice(dimm_string);
+ ECCErrorInstance *error = new ECCErrorInstance;
+ if (!error)
+ return -1;
+ error->severity_ = SAT_ERROR_CORRECTABLE;
+ dimm_device->AddErrorInstance(error);
+ return 0;
+}
+
+// Logs info about a UECC.
+// Returns -1 on error, 1 if diagnoser reports error externally; 0 otherwise.
+int ErrorDiag::AddUeccError(string dimm_string) {
+ DeviceTree *dimm_device = system_tree_root_->FindOrAddDevice(dimm_string);
+ ECCErrorInstance *error = new ECCErrorInstance;
+ if (!error)
+ return -1;
+ error->severity_ = SAT_ERROR_FATAL;
+ dimm_device->AddErrorInstance(error);
+ return 0;
+}
+
+// Logs info about a miscompare.
+// Returns -1 on error, 1 if diagnoser reports error externally; 0 otherwise.
+int ErrorDiag::AddMiscompareError(string dimm_string, uint64 addr, int count) {
+ DeviceTree *dimm_device = system_tree_root_->FindOrAddDevice(dimm_string);
+ MiscompareErrorInstance *error = new MiscompareErrorInstance;
+ if (!error)
+ return -1;
+ error->severity_ = SAT_ERROR_FATAL;
+ error->addr_ = addr;
+ dimm_device->AddErrorInstance(error);
+ os_->ErrorReport(dimm_string.c_str(), "miscompare", count);
+ return 1;
+}
+
+// Utility Function to translate a virtual address to DIMM number.
+// Returns -1 on error, 1 if diagnoser reports error externally; 0 otherwise.
+string ErrorDiag::AddressToDimmString(OsLayer *os, void *addr, int offset) {
+ char dimm_string[256] = "";
+ char *vbyteaddr = reinterpret_cast<char*>(addr) + offset;
+ uint64 paddr = os->VirtualToPhysical(vbyteaddr);
+ os->FindDimm(paddr, dimm_string, sizeof(dimm_string));
+ return string(dimm_string);
+}
+
+// Info about a miscompare from a drive.
+// Returns -1 on error, 1 if diagnoser reports error externally; 0 otherwise.
+int ErrorDiag::AddHDDMiscompareError(string devicename, int block, int offset,
+ void *src_addr, void *dst_addr) {
+ bool mask_hdd_error = false;
+
+ HDDMiscompareErrorInstance *error = new HDDMiscompareErrorInstance;
+ if (!error)
+ return -1;
+
+ error->addr_ = reinterpret_cast<uint64>(src_addr);
+ error->addr2_ = reinterpret_cast<uint64>(dst_addr);
+ error->offset_ = offset;
+ error->block_ = block;
+
+ string src_dimm = AddressToDimmString(os_, src_addr, offset);
+ string dst_dimm = AddressToDimmString(os_, dst_addr, offset);
+
+ // DIMM name look up success
+ if (src_dimm.compare("DIMM Unknown")) {
+ // Add src DIMM as possible miscompare cause.
+ DeviceTree *src_dimm_dev = system_tree_root_->FindOrAddDevice(src_dimm);
+ error->causes_.insert(src_dimm_dev);
+ if (src_dimm_dev->KnownBad()) {
+ mask_hdd_error = true;
+ logprintf(5, "Log: supressed %s miscompare report: "
+ "known bad source: %s\n", devicename.c_str(), src_dimm.c_str());
+ }
+ }
+ if (dst_dimm.compare("DIMM Unknown")) {
+ // Add dst DIMM as possible miscompare cause.
+ DeviceTree *dst_dimm_dev = system_tree_root_->FindOrAddDevice(dst_dimm);
+ error->causes_.insert(dst_dimm_dev);
+ if (dst_dimm_dev->KnownBad()) {
+ mask_hdd_error = true;
+ logprintf(5, "Log: supressed %s miscompare report: "
+ "known bad destination: %s\n", devicename.c_str(),
+ dst_dimm.c_str());
+ }
+ }
+
+ DeviceTree *hdd_dev = system_tree_root_->FindOrAddDevice(devicename);
+ hdd_dev->AddErrorInstance(error);
+
+ // HDD error was not masked by bad DIMMs: report bad HDD.
+ if (!mask_hdd_error) {
+ os_->ErrorReport(devicename.c_str(), "miscompare", 1);
+ error->severity_ = SAT_ERROR_FATAL;
+ return 1;
+ }
+ return 0;
+}
+
+// Info about a sector tag miscompare from a drive.
+// Returns -1 on error, 1 if diagnoser reports error externally; 0 otherwise.
+int ErrorDiag::AddHDDSectorTagError(string devicename, int block, int offset,
+ int sector, void *src_addr,
+ void *dst_addr) {
+ bool mask_hdd_error = false;
+
+ HDDSectorTagErrorInstance *error = new HDDSectorTagErrorInstance;
+ if (!error)
+ return -1;
+
+ error->addr_ = reinterpret_cast<uint64>(src_addr);
+ error->addr2_ = reinterpret_cast<uint64>(dst_addr);
+ error->sector_ = sector;
+ error->block_ = block;
+
+ string src_dimm = AddressToDimmString(os_, src_addr, offset);
+ string dst_dimm = AddressToDimmString(os_, dst_addr, offset);
+
+ // DIMM name look up success
+ if (src_dimm.compare("DIMM Unknown")) {
+ // Add src DIMM as possible miscompare cause.
+ DeviceTree *src_dimm_dev = system_tree_root_->FindOrAddDevice(src_dimm);
+ error->causes_.insert(src_dimm_dev);
+ if (src_dimm_dev->KnownBad()) {
+ mask_hdd_error = true;
+ logprintf(5, "Log: supressed %s sector tag error report: "
+ "known bad source: %s\n", devicename.c_str(), src_dimm.c_str());
+ }
+ }
+ if (dst_dimm.compare("DIMM Unknown")) {
+ // Add dst DIMM as possible miscompare cause.
+ DeviceTree *dst_dimm_dev = system_tree_root_->FindOrAddDevice(dst_dimm);
+ error->causes_.insert(dst_dimm_dev);
+ if (dst_dimm_dev->KnownBad()) {
+ mask_hdd_error = true;
+ logprintf(5, "Log: supressed %s sector tag error report: "
+ "known bad destination: %s\n", devicename.c_str(),
+ dst_dimm.c_str());
+ }
+ }
+
+ DeviceTree *hdd_dev = system_tree_root_->FindOrAddDevice(devicename);
+ hdd_dev->AddErrorInstance(error);
+
+ // HDD error was not masked by bad DIMMs: report bad HDD.
+ if (!mask_hdd_error) {
+ os_->ErrorReport(devicename.c_str(), "sector", 1);
+ error->severity_ = SAT_ERROR_FATAL;
+ return 1;
+ }
+ return 0;
+}
diff --git a/external/subpack/utils/stressapptest/src/src/error_diag.h b/external/subpack/utils/stressapptest/src/src/error_diag.h
new file mode 100644
index 0000000..7faedb8
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/error_diag.h
@@ -0,0 +1,167 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// error_diag.h: Ambiguous error diagnosis class
+
+#ifndef STRESSAPPTEST_ERROR_DIAG_H_
+#define STRESSAPPTEST_ERROR_DIAG_H_
+
+#include <pthread.h>
+#include <list>
+#include <map>
+#include <set>
+#include <string>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "sattypes.h"
+#include "os.h"
+
+class ErrorInstance;
+
+// This describes the components of the system.
+class DeviceTree {
+ public:
+ explicit DeviceTree(string name);
+ ~DeviceTree();
+
+ // Atomically find arbitrary device in subtree.
+ DeviceTree *FindInSubTree(string name);
+ // Find or add named device.
+ DeviceTree *FindOrAddDevice(string name);
+ // Atomically add sub device.
+ void InsertSubDevice(string name);
+ // Returns parent device.
+ DeviceTree *GetParent() { return parent_; }
+ // Pretty prints device tree.
+ void PrettyPrint(string spacer = " ");
+ // Atomically add error instance to device.
+ void AddErrorInstance(ErrorInstance *error_instance);
+ // Returns true of device is known to be bad.
+ bool KnownBad();
+ // Returns number of direct sub devices.
+ int NumDirectSubDevices() { return subdevices_.size(); }
+
+ private:
+ // Unlocked version of FindInSubTree.
+ DeviceTree *UnlockedFindInSubTree(string name);
+
+ std::map<string, DeviceTree*> subdevices_; // Map of sub-devices.
+ std::list<ErrorInstance*> errors_; // Log of errors.
+ DeviceTree *parent_; // Pointer to parent device.
+ string name_; // Device name.
+ pthread_mutex_t device_tree_mutex_; // Mutex protecting device tree.
+};
+
+
+// enum type for collected errors.
+enum SATErrorType {
+ SAT_ERROR_NONE = 0,
+ SAT_ERROR_ECC,
+ SAT_ERROR_MISCOMPARE,
+ SAT_ERROR_SECTOR_TAG,
+};
+
+// enum type for error severity.
+enum SATErrorSeverity {
+ SAT_ERROR_CORRECTABLE = 0,
+ SAT_ERROR_FATAL,
+};
+
+// This describes an error and it's likely causes.
+class ErrorInstance {
+ public:
+ ErrorInstance(): type_(SAT_ERROR_NONE), severity_(SAT_ERROR_CORRECTABLE) {}
+
+ SATErrorType type_; // Type of error: ECC, miscompare, sector.
+ SATErrorSeverity severity_; // Correctable, or fatal.
+ std::set<DeviceTree*> causes_; // Devices that can cause this type of error.
+};
+
+// This describes ECC errors.
+class ECCErrorInstance: public ErrorInstance {
+ public:
+ ECCErrorInstance() { type_ = SAT_ERROR_ECC; }
+
+ uint64 addr_; // Address where error occured.
+};
+
+// This describes miscompare errors.
+class MiscompareErrorInstance: public ErrorInstance {
+ public:
+ MiscompareErrorInstance() { type_ = SAT_ERROR_MISCOMPARE; }
+
+ uint64 addr_; // Address where miscompare occured.
+};
+
+// This describes HDD miscompare errors.
+class HDDMiscompareErrorInstance: public MiscompareErrorInstance {
+ public:
+ uint64 addr2_; // addr_ and addr2_ are src and dst memory addr.
+ int offset_; // offset.
+ int block_; // error block.
+};
+
+// This describes HDD miscompare errors.
+class HDDSectorTagErrorInstance: public ErrorInstance {
+ public:
+ HDDSectorTagErrorInstance() { type_ = SAT_ERROR_SECTOR_TAG; }
+
+ uint64 addr_;
+ uint64 addr2_; // addr_ and addr2_ are src and dst memory addr.
+ int sector_; // error sector.
+ int block_; // error block.
+};
+
+// Generic error storage and sorting class.
+class ErrorDiag {
+ public:
+ ErrorDiag();
+ virtual ~ErrorDiag();
+
+ // Add info about a CECC.
+ virtual int AddCeccError(string dimm_string);
+
+ // Add info about a UECC.
+ virtual int AddUeccError(string dimm_string);
+
+ // Add info about a miscompare.
+ virtual int AddMiscompareError(string dimm_string, uint64 addr, int count);
+
+ // Add info about a miscompare from a drive.
+ virtual int AddHDDMiscompareError(string devicename, int block, int offset,
+ void *src_addr, void *dst_addr);
+
+ // Add info about a sector tag miscompare from a drive.
+ virtual int AddHDDSectorTagError(string devicename, int block, int offset,
+ int sector, void *src_addr, void *dst_addr);
+
+ // Set platform specific handle and initialize device tree.
+ bool set_os(OsLayer *os);
+
+ protected:
+ // Create and initialize system device tree.
+ virtual bool InitializeDeviceTree();
+
+ // Utility Function to translate a virtual address to DIMM number.
+ string AddressToDimmString(OsLayer *os, void *addr, int offset);
+
+ DeviceTree *system_tree_root_; // System device tree.
+ OsLayer *os_; // Platform handle.
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ErrorDiag);
+};
+
+#endif // STRESSAPPTEST_ERROR_DIAG_H_
diff --git a/external/subpack/utils/stressapptest/src/src/findmask.c b/external/subpack/utils/stressapptest/src/src/findmask.c
new file mode 100644
index 0000000..1b10988
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/findmask.c
@@ -0,0 +1,140 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/*
+ * This "tool" can be used to brute force the XOR bitmask that a memory
+ * controller uses to interleave addresses onto its two channels. To use it,
+ * you need to have a bunch of addresses that are known to go to only one
+ * of the memory channels... easiest way to get these is to run stressapptest on
+ * a machine while holding a soldering iron close to the chips of one channel.
+ * Generate about a thousand failures and extract their physical addresses
+ * from the output. Write them to findmask.inc in a way that forms a valid
+ * definition for the addrs array. Make and run on a big machine.
+ *
+ * The program iterates over all possible bitmasks within the first NUM_BITS,
+ * parallelizing execution over NUM_THREADS. Every integer is masked
+ * onto all supplied addresses, counting the amount of times this results in
+ * an odd or even amount of bits. If all but NOISE addresses fall on one side,
+ * it will print that mask to stdout. Note that the script will always "find"
+ * the mask 0x0, and may also report masks such as 0x100000000 depending on
+ * your test machines memory size... you will need to use your own judgement to
+ * interpret the results.
+ *
+ * As the program might run for a long time, you can send SIGUSR1 to it to
+ * output the last mask that was processed and get a rough idea of the
+ * current progress.
+ */
+
+#include <inttypes.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define NOISE 20
+#define NUM_BITS 32
+#define NUM_THREADS 128 // keep this a power of two
+
+static uint64_t addrs[] = {
+#include "findmask.inc"
+};
+static uint64_t lastmask;
+
+__attribute__((optimize(3, "unroll-loops")))
+void* thread_func(void* arg) {
+ register uint64_t mask;
+ register uintptr_t num = (uintptr_t)arg;
+
+ for (mask = num; mask < (1ULL << (NUM_BITS + 1)); mask += NUM_THREADS) {
+ register const uint64_t* cur;
+ register int a = 0;
+ register int b = 0;
+
+ for (cur = addrs; (char*)cur < (char*)addrs + sizeof(addrs); cur++) {
+#ifdef __x86_64__
+ register uint64_t addr asm("rdx") = *cur & mask;
+ register uint32_t tmp asm("ebx");
+
+ // Behold: the dark bit counting magic!
+ asm (
+ // Fold high and low 32 bits onto each other
+ "MOVl %%edx, %%ebx\n\t"
+ "SHRq $32, %%rdx\n\t"
+ "XORl %%ebx, %%edx\n\t"
+ // Fold high and low 16 bits onto each other
+ "MOVl %%edx, %%ebx\n\t"
+ "SHRl $16, %%edx\n\t"
+ "XORw %%bx, %%dx\n\t"
+ // Fold high and low 8 bits onto each other
+ "XORb %%dh, %%dl\n\t"
+ // Invoke ancient 8086 parity flag (only counts lowest byte)
+ "SETnp %%bl\n\t"
+ "SETp %%dl\n\t"
+ // Stupid SET instruction can only affect the lowest byte...
+ "ANDl $1, %%ebx\n\t"
+ "ANDl $1, %%edx\n\t"
+ // Increment either 'a' or 'b' without needing another branch
+ "ADDl %%ebx, %2\n\t"
+ "ADDl %%edx, %1\n\t"
+ : "=b" (tmp), "+r"(a), "+r"(b) : "d"(addr) : "cc");
+
+#else // generic processor
+ register uint64_t addr = *cur & mask;
+ register uint32_t low = (uint32_t)addr;
+ register uint32_t high = (uint32_t)(addr >> 32);
+
+ // Takes about twice as long as the version above... take that GCC!
+ __builtin_parity(low) ^ __builtin_parity(high) ? a++ : b++;
+#endif
+
+ // Early abort: probably still the most valuable optimization in here
+ if (a >= NOISE && b >= NOISE) break;
+ }
+
+ if (a < NOISE) b = a;
+ if (b < NOISE) {
+ printf("Found mask with just %d deviations: 0x%" PRIx64 "\n", b, mask);
+ fflush(stdout);
+ }
+
+ // I'm a little paranoid about performance: don't write to memory too often
+ if (!(mask & 0x7ff)) lastmask = mask;
+ }
+
+ return 0;
+}
+
+void signal_handler(int signum) {
+ printf("Received signal... currently evaluating mask 0x%" PRIx64 "!\n",
+ lastmask);
+ fflush(stdout);
+}
+
+int main(int argc, char** argv) {
+ uintptr_t i;
+ pthread_t threads[NUM_THREADS];
+
+ signal(SIGUSR1, signal_handler);
+
+ for (i = 0; i < NUM_THREADS; i++)
+ pthread_create(&threads[i], 0, thread_func, (void*)i);
+
+ for (i = 0; i < NUM_THREADS; i++)
+ pthread_join(threads[i], 0);
+
+ return 0;
+}
diff --git a/external/subpack/utils/stressapptest/src/src/findmask.inc b/external/subpack/utils/stressapptest/src/src/findmask.inc
new file mode 100644
index 0000000..e76f72f
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/findmask.inc
@@ -0,0 +1,4 @@
+// This is the body of a uintptr_t array definition. Fill in your own addresses.
+0x116bb312c, // example values (can be >32 bit)
+0x38d3c5ad, // replace with your own
+0x77c1e96d // don't forget: no comma after the last one
diff --git a/external/subpack/utils/stressapptest/src/src/finelock_queue.cc b/external/subpack/utils/stressapptest/src/src/finelock_queue.cc
new file mode 100644
index 0000000..8d914b8
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/finelock_queue.cc
@@ -0,0 +1,448 @@
+// Copyright 2007 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This is an interface to a simple thread safe container with fine-grain locks,
+// used to hold data blocks and patterns.
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "finelock_queue.h"
+#include "os.h"
+
+// Page entry queue implementation follows.
+// Push and Get functions are analogous to lock and unlock operations on a given
+// page entry, while preserving queue semantics.
+//
+// The actual 'queue' implementation is actually just an array. The entries are
+// never shuffled or re-ordered like that of a real queue. Instead, Get
+// functions return a random page entry of a given type and lock that particular
+// page entry until it is unlocked by corresponding Put functions.
+//
+// In this implementation, a free page is those page entries where pattern is
+// null (pe->pattern == 0)
+
+
+// Constructor: Allocates memory and initialize locks.
+FineLockPEQueue::FineLockPEQueue(
+ uint64 queuesize, int64 pagesize) {
+ q_size_ = queuesize;
+ pages_ = new struct page_entry[q_size_];
+ pagelocks_ = new pthread_mutex_t[q_size_];
+ page_size_ = pagesize;
+
+ // What metric should we measure this run.
+ queue_metric_ = kTouch;
+
+ { // Init all the page locks.
+ for (uint64 i = 0; i < q_size_; i++) {
+ pthread_mutex_init(&(pagelocks_[i]), NULL);
+ // Pages start out owned (locked) by Sat::InitializePages.
+ // A locked state indicates that the page state is unknown,
+ // and the lock should not be aquired. As InitializePages creates
+ // the page records, they will be inserted and unlocked, at which point
+ // they are ready to be aquired and filled by worker threads.
+ sat_assert(pthread_mutex_lock(&(pagelocks_[i])) == 0);
+ }
+ }
+
+ { // Init the random number generator.
+ for (int i = 0; i < 4; i++) {
+ rand_seed_[i] = i + 0xbeef;
+ pthread_mutex_init(&(randlocks_[i]), NULL);
+ }
+ }
+
+ // Try to make a linear congruential generator with our queue size.
+ // We need this to deterministically search all the queue (being able to find
+ // a single available element is a design requirement), but we don't want to
+ // cause any page to be more likley chosen than another. The previous
+ // sequential retry heavily biased pages at the beginning of a bunch, or
+ // isolated pages surrounded by unqualified ones.
+ int64 length = queuesize;
+ int64 modlength = length;
+ int64 a;
+ int64 c;
+
+ if (length < 3) {
+ a = 1;
+ c = 1;
+ } else {
+ // Search for a nontrivial generator.
+ a = getA(length) % length;
+ // If this queue size doesn't have a nontrivial generator (where the
+ // multiplier is greater then one) we'll check increasing queue sizes,
+ // and discard out of bounds results.
+ while (a == 1) {
+ modlength++;
+ a = getA(modlength) % modlength;
+ }
+ c = getC(modlength);
+ }
+
+ // This is our final generator.
+ a_ = a;
+ c_ = c;
+ modlength_ = modlength;
+}
+
+// Part of building a linear congruential generator n1 = (a * n0 + c) % m
+// Get 'a', where a - 1 must be divisible by all prime
+// factors of 'm', our queue size.
+int64 FineLockPEQueue::getA(int64 m) {
+ int64 remaining = m;
+ int64 a = 1;
+ if ((((remaining / 4) * 4) == remaining)) {
+ a = 2;
+ }
+ // For each number, let's see if it's divisible,
+ // then divide it out.
+ for (int64 i = 2; i <= m; i++) {
+ if (((remaining / i) * i) == remaining) {
+ remaining /= i;
+ // Keep dividing it out until there's no more.
+ while (((remaining / i) * i) == remaining)
+ remaining /= i;
+ a *= i;
+ }
+ }
+
+ // Return 'a' as specified.
+ return (a + 1) % m;
+}
+
+
+// Part of building a linear congruential generator n1 = (a * n0 + c) % m
+// Get a prime number approx 3/4 the size of our queue.
+int64 FineLockPEQueue::getC(int64 m) {
+ // Start here at 3/4.
+ int64 start = (3 * m) / 4 + 1;
+ int64 possible_prime = start;
+ // Keep trying until we find a prime.
+ for (possible_prime = start; possible_prime > 1; possible_prime--) {
+ bool failed = false;
+ for (int64 i = 2; i < possible_prime; i++) {
+ if (((possible_prime / i) * i) == possible_prime) {
+ failed = true;
+ break;
+ }
+ }
+ if (!failed) {
+ return possible_prime;
+ }
+ }
+ // One is prime enough.
+ return 1;
+}
+
+// Destructor: Clean-up allocated memory and destroy pthread locks.
+FineLockPEQueue::~FineLockPEQueue() {
+ uint64 i;
+ for (i = 0; i < q_size_; i++)
+ pthread_mutex_destroy(&(pagelocks_[i]));
+ delete[] pagelocks_;
+ delete[] pages_;
+ for (i = 0; i < 4; i++) {
+ pthread_mutex_destroy(&(randlocks_[i]));
+ }
+}
+
+
+bool FineLockPEQueue::QueueAnalysis() {
+ const char *measurement = "Error";
+ uint64 buckets[32];
+
+ if (queue_metric_ == kTries)
+ measurement = "Failed retrievals";
+ else if (queue_metric_ == kTouch)
+ measurement = "Reads per page";
+
+ // Buckets for each log2 access counts.
+ for (int b = 0; b < 32; b++) {
+ buckets[b] = 0;
+ }
+
+ // Bucketize the page counts by highest bit set.
+ for (uint64 i = 0; i < q_size_; i++) {
+ uint32 readcount = pages_[i].touch;
+ int b = 0;
+ for (b = 0; b < 31; b++) {
+ if (readcount < (1u << b))
+ break;
+ }
+
+ buckets[b]++;
+ }
+
+ logprintf(12, "Log: %s histogram\n", measurement);
+ for (int b = 0; b < 32; b++) {
+ if (buckets[b])
+ logprintf(12, "Log: %12d - %12d: %12d\n",
+ ((1 << b) >> 1), 1 << b, buckets[b]);
+ }
+
+ return true;
+}
+
+namespace {
+// Callback mechanism for exporting last action.
+OsLayer *g_os;
+FineLockPEQueue *g_fpqueue = 0;
+
+// Global callback to hook into Os object.
+bool err_log_callback(uint64 paddr, string *buf) {
+ if (g_fpqueue) {
+ return g_fpqueue->ErrorLogCallback(paddr, buf);
+ }
+ return false;
+}
+}
+
+// Setup global state for exporting callback.
+void FineLockPEQueue::set_os(OsLayer *os) {
+ g_os = os;
+ g_fpqueue = this;
+}
+
+OsLayer::ErrCallback FineLockPEQueue::get_err_log_callback() {
+ return err_log_callback;
+}
+
+// This call is used to export last transaction info on a particular physical
+// address.
+bool FineLockPEQueue::ErrorLogCallback(uint64 paddr, string *message) {
+ struct page_entry pe;
+ OsLayer *os = g_os;
+ sat_assert(g_os);
+ char buf[256];
+
+ // Find the page of this paddr.
+ int gotpage = GetPageFromPhysical(paddr, &pe);
+ if (!gotpage) {
+ return false;
+ }
+
+ // Find offset into the page.
+ uint64 addr_diff = paddr - pe.paddr;
+
+ // Find vaddr of this paddr. Make sure it matches,
+ // as sometimes virtual memory is not contiguous.
+ char *vaddr =
+ reinterpret_cast<char*>(os->PrepareTestMem(pe.offset, page_size_));
+ uint64 new_paddr = os->VirtualToPhysical(vaddr + addr_diff);
+ os->ReleaseTestMem(vaddr, pe.offset, page_size_);
+
+ // Is the physical address at this page offset the same as
+ // the physical address we were given?
+ if (new_paddr != paddr) {
+ return false;
+ }
+
+ // Print all the info associated with this page.
+ message->assign(" (Last Transaction:");
+
+ if (pe.lastpattern) {
+ int offset = addr_diff / 8;
+ datacast_t data;
+
+ data.l32.l = pe.lastpattern->pattern(offset << 1);
+ data.l32.h = pe.lastpattern->pattern((offset << 1) + 1);
+
+ snprintf(buf, sizeof(buf), " %s data=%#016llx",
+ pe.lastpattern->name(), data.l64);
+ message->append(buf);
+ }
+ snprintf(buf, sizeof(buf), " tsc=%#llx)", pe.ts);
+ message->append(buf);
+ return true;
+}
+
+bool FineLockPEQueue::GetPageFromPhysical(uint64 paddr,
+ struct page_entry *pe) {
+ // Traverse through array until finding a page
+ // that contains the address we want..
+ for (uint64 i = 0; i < q_size_; i++) {
+ uint64 page_addr = pages_[i].paddr;
+ // This assumes linear vaddr.
+ if ((page_addr <= paddr) && (page_addr + page_size_ > paddr)) {
+ *pe = pages_[i];
+ return true;
+ }
+ }
+ return false;
+}
+
+
+// Get a random number from the slot we locked.
+uint64 FineLockPEQueue::GetRandom64FromSlot(int slot) {
+ // 64 bit LCG numbers suggested on the internets by
+ // http://nuclear.llnl.gov/CNP/rng/rngman/node4.html and others.
+ uint64 result = 2862933555777941757ULL * rand_seed_[slot] + 3037000493ULL;
+ rand_seed_[slot] = result;
+ return result;
+}
+
+// Get a random number, we have 4 generators to choose from so hopefully we
+// won't be blocking on this.
+uint64 FineLockPEQueue::GetRandom64() {
+ // Try each available slot.
+ for (int i = 0; i < 4; i++) {
+ if (pthread_mutex_trylock(&(randlocks_[i])) == 0) {
+ uint64 result = GetRandom64FromSlot(i);
+ pthread_mutex_unlock(&(randlocks_[i]));
+ return result;
+ }
+ }
+ // Forget it, just wait.
+ int i = 0;
+ if (pthread_mutex_lock(&(randlocks_[i])) == 0) {
+ uint64 result = GetRandom64FromSlot(i);
+ pthread_mutex_unlock(&(randlocks_[i]));
+ return result;
+ }
+
+ logprintf(0, "Process Error: Could not acquire random lock.\n");
+ sat_assert(0);
+ return 0;
+}
+
+
+// Helper function to get a random page entry with given predicate,
+// ie, page_is_valid() or page_is_empty() as defined in finelock_queue.h.
+//
+// Setting tag to a value other than kDontCareTag (-1)
+// indicates that we need a tag match, otherwise any tag will do.
+//
+// Returns true on success, false on failure.
+bool FineLockPEQueue::GetRandomWithPredicateTag(struct page_entry *pe,
+ bool (*pred_func)(struct page_entry*),
+ int32 tag) {
+ if (!pe || !q_size_)
+ return false;
+
+ // Randomly index into page entry array.
+ uint64 first_try = GetRandom64() % q_size_;
+ uint64 next_try = 1;
+
+ // Traverse through array until finding a page meeting given predicate.
+ for (uint64 i = 0; i < q_size_; i++) {
+ uint64 index = (next_try + first_try) % q_size_;
+ // Go through the loop linear conguentially. We are offsetting by
+ // 'first_try' so this path will be a different sequence for every
+ // initioal value chosen.
+ next_try = (a_ * next_try + c_) % (modlength_);
+ while (next_try >= q_size_) {
+ // If we have chosen a modlength greater than the queue size,
+ // discard out of bounds results.
+ next_try = (a_ * next_try + c_) % (modlength_);
+ }
+
+ // If page does not meet predicate, don't trylock (expensive).
+ if (!(pred_func)(&pages_[index]))
+ continue;
+
+ // If page does not meet tag predicate, don't trylock (expensive).
+ if ((tag != kDontCareTag) && !(pages_[index].tag & tag))
+ continue;
+
+ if (pthread_mutex_trylock(&(pagelocks_[index])) == 0) {
+ // If page property (valid/empty) changes before successfully locking,
+ // release page and move on.
+ if (!(pred_func)(&pages_[index])) {
+ pthread_mutex_unlock(&(pagelocks_[index]));
+ continue;
+ } else {
+ // A page entry with given predicate is locked, returns success.
+ *pe = pages_[index];
+
+ // Add metrics as necessary.
+ if (pred_func == page_is_valid) {
+ // Measure time to fetch valid page.
+ if (queue_metric_ == kTries)
+ pe->touch = i;
+ // Measure number of times each page is read.
+ if (queue_metric_ == kTouch)
+ pe->touch++;
+ }
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// Without tag hint.
+bool FineLockPEQueue::GetRandomWithPredicate(struct page_entry *pe,
+ bool (*pred_func)(struct page_entry*)) {
+ return GetRandomWithPredicateTag(pe, pred_func, kDontCareTag);
+}
+
+
+// GetValid() randomly finds a valid page, locks it and returns page entry by
+// pointer.
+//
+// Returns true on success, false on failure.
+bool FineLockPEQueue::GetValid(struct page_entry *pe) {
+ return GetRandomWithPredicate(pe, page_is_valid);
+}
+
+bool FineLockPEQueue::GetValid(struct page_entry *pe, int32 mask) {
+ return GetRandomWithPredicateTag(pe, page_is_valid, mask);
+}
+
+// GetEmpty() randomly finds an empty page, locks it and returns page entry by
+// pointer.
+//
+// Returns true on success, false on failure.
+bool FineLockPEQueue::GetEmpty(struct page_entry *pe, int32 mask) {
+ return GetRandomWithPredicateTag(pe, page_is_empty, mask);
+}
+bool FineLockPEQueue::GetEmpty(struct page_entry *pe) {
+ return GetRandomWithPredicate(pe, page_is_empty);
+}
+
+// PutEmpty puts an empty page back into the queue, making it available by
+// releasing the per-page-entry lock.
+//
+// Returns true on success, false on failure.
+bool FineLockPEQueue::PutEmpty(struct page_entry *pe) {
+ if (!pe || !q_size_)
+ return false;
+
+ int64 index = pe->offset / page_size_;
+ if (!valid_index(index))
+ return false;
+
+ pages_[index] = *pe;
+ // Enforce that page entry is indeed empty.
+ pages_[index].pattern = 0;
+ return (pthread_mutex_unlock(&(pagelocks_[index])) == 0);
+}
+
+// PutValid puts a valid page back into the queue, making it available by
+// releasing the per-page-entry lock.
+//
+// Returns true on success, false on failure.
+bool FineLockPEQueue::PutValid(struct page_entry *pe) {
+ if (!pe || !page_is_valid(pe) || !q_size_)
+ return false;
+
+ int64 index = pe->offset / page_size_;
+ if (!valid_index(index))
+ return false;
+
+ pages_[index] = *pe;
+ return (pthread_mutex_unlock(&(pagelocks_[index])) == 0);
+}
diff --git a/external/subpack/utils/stressapptest/src/src/finelock_queue.h b/external/subpack/utils/stressapptest/src/src/finelock_queue.h
new file mode 100644
index 0000000..2de5a46
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/finelock_queue.h
@@ -0,0 +1,118 @@
+// Copyright 2007 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This page entry queue implementation with fine grain locks aim to ease
+// lock contention over previous queue implementation (with one lock protecting
+// the entire queue).
+
+#ifndef STRESSAPPTEST_FINELOCK_QUEUE_H_
+#define STRESSAPPTEST_FINELOCK_QUEUE_H_
+
+#include <string>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "sattypes.h"
+#include "pattern.h"
+#include "queue.h" // Using page_entry struct.
+#include "os.h"
+
+// This is a threadsafe randomized queue of pages with per-page entry lock
+// for worker threads to use.
+class FineLockPEQueue {
+ public:
+ FineLockPEQueue(uint64 queuesize, int64 pagesize);
+ ~FineLockPEQueue();
+
+ // Put and get functions for page entries.
+ bool GetEmpty(struct page_entry *pe);
+ bool GetValid(struct page_entry *pe);
+ bool PutEmpty(struct page_entry *pe);
+ bool PutValid(struct page_entry *pe);
+
+ // Put and get functions for page entries, selecting on tags.
+ bool GetEmpty(struct page_entry *pe, int32 tag);
+ bool GetValid(struct page_entry *pe, int32 tag);
+
+ bool QueueAnalysis();
+ bool GetPageFromPhysical(uint64 paddr, struct page_entry *pe);
+ void set_os(OsLayer *os);
+ OsLayer::ErrCallback get_err_log_callback();
+ bool ErrorLogCallback(uint64 paddr, string *buf);
+
+ private:
+ // Not that much blocking random number generator.
+ uint64 GetRandom64();
+ uint64 GetRandom64FromSlot(int slot);
+
+ // Helper function to check index range, returns true if index is valid.
+ bool valid_index(int64 index) {
+ return index >= 0 && static_cast<uint64>(index) < q_size_;
+ }
+
+ // Returns true if page entry is valid, false otherwise.
+ static bool page_is_valid(struct page_entry *pe) {
+ return pe->pattern != NULL;
+ }
+ // Returns true if page entry is empty, false otherwise.
+ static bool page_is_empty(struct page_entry *pe) {
+ return pe->pattern == NULL;
+ }
+
+ // Helper function to get a random page entry with given predicate,
+ // ie, page_is_valid() or page_is_empty() as defined above.
+ bool GetRandomWithPredicate(struct page_entry *pe,
+ bool (*pred_func)(struct page_entry*));
+
+ // Helper function to get a random page entry with given predicate,
+ // ie, page_is_valid() or page_is_empty() as defined above.
+ bool GetRandomWithPredicateTag(struct page_entry *pe,
+ bool (*pred_func)(struct page_entry*),
+ int32 tag);
+
+ // Used to make a linear congruential path through the queue.
+ int64 getA(int64 m);
+ int64 getC(int64 m);
+
+ pthread_mutex_t *pagelocks_; // Per-page-entry locks.
+ struct page_entry *pages_; // Where page entries are held.
+ uint64 q_size_; // Size of the queue.
+ int64 page_size_; // For calculating array index from offset.
+
+ enum {
+ kTries = 1, // Measure the number of attempts in the queue
+ // before getting a matching page.
+ kTouch = 2 } // Measure the number of touches on each page.
+ queue_metric_; // What to measure in the 'tries' field.
+
+ // Progress pseudorandomly through the queue. It's required that we can find
+ // every value in the list, but progressing through the same order each time
+ // causes bunching of pages, leading to long seach times for the correct
+ // type of pages.
+ int64 a_; // 'a' multiplicative value for progressing
+ // linear congruentially through the list.
+ int64 c_; // 'c' additive value for prgressing randomly
+ // through the list.
+ int64 modlength_; // 'm' mod value for linear congruential
+ // generator. Used when q_size_ doesn't
+ // generate a good progression through the
+ // list.
+
+ uint64 rand_seed_[4]; // Random number state for 4 generators.
+ pthread_mutex_t randlocks_[4]; // Per-random-generator locks.
+
+ DISALLOW_COPY_AND_ASSIGN(FineLockPEQueue);
+};
+
+#endif // STRESSAPPTEST_FINELOCK_QUEUE_H_
diff --git a/external/subpack/utils/stressapptest/src/src/logger.cc b/external/subpack/utils/stressapptest/src/src/logger.cc
new file mode 100644
index 0000000..f13e003
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/logger.cc
@@ -0,0 +1,170 @@
+// Copyright 2009 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "logger.h"
+
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "sattypes.h"
+
+
+Logger *Logger::GlobalLogger() {
+ static Logger logger;
+ return &logger;
+}
+
+void Logger::VLogF(int priority, const char *format, va_list args) {
+ if (priority > verbosity_) {
+ return;
+ }
+ char buffer[4096];
+ size_t length = 0;
+ if (log_timestamps_) {
+ time_t raw_time;
+ time(&raw_time);
+ struct tm time_struct;
+ localtime_r(&raw_time, &time_struct);
+ length = strftime(buffer, sizeof(buffer), "%Y/%m/%d-%H:%M:%S(%Z) ",
+ &time_struct);
+ LOGGER_ASSERT(length); // Catch if the buffer is set too small.
+ }
+ length += vsnprintf(buffer + length, sizeof(buffer) - length, format, args);
+ if (length >= sizeof(buffer)) {
+ length = sizeof(buffer);
+ buffer[sizeof(buffer) - 1] = '\n';
+ }
+ QueueLogLine(new string(buffer, length));
+}
+
+void Logger::StartThread() {
+ LOGGER_ASSERT(!thread_running_);
+ thread_running_ = true;
+ LOGGER_ASSERT(0 == pthread_create(&thread_, NULL, &StartRoutine, this));
+}
+
+void Logger::StopThread() {
+ // Allow this to be called before the thread has started.
+ if (!thread_running_) {
+ return;
+ }
+ thread_running_ = false;
+ int retval = pthread_mutex_lock(&queued_lines_mutex_);
+ LOGGER_ASSERT(0 == retval);
+ bool need_cond_signal = queued_lines_.empty();
+ queued_lines_.push_back(NULL);
+ retval = pthread_mutex_unlock(&queued_lines_mutex_);
+ LOGGER_ASSERT(0 == retval);
+ if (need_cond_signal) {
+ retval = pthread_cond_signal(&queued_lines_cond_);
+ LOGGER_ASSERT(0 == retval);
+ }
+ retval = pthread_join(thread_, NULL);
+ LOGGER_ASSERT(0 == retval);
+}
+
+Logger::Logger()
+ : verbosity_(20),
+ log_fd_(-1),
+ thread_running_(false),
+ log_timestamps_(true) {
+ LOGGER_ASSERT(0 == pthread_mutex_init(&queued_lines_mutex_, NULL));
+ LOGGER_ASSERT(0 == pthread_cond_init(&queued_lines_cond_, NULL));
+ LOGGER_ASSERT(0 == pthread_cond_init(&full_queue_cond_, NULL));
+}
+
+Logger::~Logger() {
+ LOGGER_ASSERT(0 == pthread_mutex_destroy(&queued_lines_mutex_));
+ LOGGER_ASSERT(0 == pthread_cond_destroy(&queued_lines_cond_));
+ LOGGER_ASSERT(0 == pthread_cond_destroy(&full_queue_cond_));
+}
+
+void Logger::QueueLogLine(string *line) {
+ LOGGER_ASSERT(line != NULL);
+ LOGGER_ASSERT(0 == pthread_mutex_lock(&queued_lines_mutex_));
+ if (thread_running_) {
+ if (queued_lines_.size() >= kMaxQueueSize) {
+ LOGGER_ASSERT(0 == pthread_cond_wait(&full_queue_cond_,
+ &queued_lines_mutex_));
+ }
+ if (queued_lines_.empty()) {
+ LOGGER_ASSERT(0 == pthread_cond_signal(&queued_lines_cond_));
+ }
+ queued_lines_.push_back(line);
+ } else {
+ WriteAndDeleteLogLine(line);
+ }
+ LOGGER_ASSERT(0 == pthread_mutex_unlock(&queued_lines_mutex_));
+}
+
+void Logger::WriteAndDeleteLogLine(string *line) {
+ LOGGER_ASSERT(line != NULL);
+ ssize_t bytes_written;
+ if (log_fd_ >= 0) {
+ bytes_written = write(log_fd_, line->data(), line->size());
+ LOGGER_ASSERT(bytes_written == static_cast<ssize_t>(line->size()));
+ }
+ bytes_written = write(STDOUT_FILENO, line->data(), line->size());
+ LOGGER_ASSERT(bytes_written == static_cast<ssize_t>(line->size()));
+ delete line;
+}
+
+void *Logger::StartRoutine(void *ptr) {
+ Logger *self = static_cast<Logger*>(ptr);
+ self->ThreadMain();
+ return NULL;
+}
+
+void Logger::ThreadMain() {
+ vector<string*> local_queue;
+ LOGGER_ASSERT(0 == pthread_mutex_lock(&queued_lines_mutex_));
+
+ for (;;) {
+ if (queued_lines_.empty()) {
+ LOGGER_ASSERT(0 == pthread_cond_wait(&queued_lines_cond_,
+ &queued_lines_mutex_));
+ continue;
+ }
+
+ // We move the log lines into a local queue so we can release the lock
+ // while writing them to disk, preventing other threads from blocking on
+ // our writes.
+ local_queue.swap(queued_lines_);
+ if (local_queue.size() >= kMaxQueueSize) {
+ LOGGER_ASSERT(0 == pthread_cond_broadcast(&full_queue_cond_));
+ }
+
+ // Unlock while we process our local queue.
+ LOGGER_ASSERT(0 == pthread_mutex_unlock(&queued_lines_mutex_));
+ for (vector<string*>::const_iterator it = local_queue.begin();
+ it != local_queue.end(); ++it) {
+ if (*it == NULL) {
+ // NULL is guaranteed to be at the end.
+ return;
+ }
+ WriteAndDeleteLogLine(*it);
+ }
+ local_queue.clear();
+ // We must hold the lock at the start of each iteration of this for loop.
+ LOGGER_ASSERT(0 == pthread_mutex_lock(&queued_lines_mutex_));
+ }
+}
diff --git a/external/subpack/utils/stressapptest/src/src/logger.h b/external/subpack/utils/stressapptest/src/src/logger.h
new file mode 100644
index 0000000..21b3c6b
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/logger.h
@@ -0,0 +1,149 @@
+// Copyright 2009 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STRESSAPPTEST_LOGGER_H_
+#define STRESSAPPTEST_LOGGER_H_
+
+#include <pthread.h>
+#include <stdarg.h>
+
+#include <string>
+#include <vector>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "sattypes.h"
+
+// Attempts to log additional lines will block when the queue reaches this size.
+// Due to how the logging thread works, up to twice this many log lines may be
+// outstanding at any point.
+static const size_t kMaxQueueSize = 250;
+
+
+// This is only for use by the Logger class, do not use it elsewhere!
+//
+// All Logger assertions should use this macro instead of sat_assert().
+//
+// This is like sat_assert() from sattypes.h, but whereas sat_assert() tries to
+// log the assertion after printing it to stderr, this only prints it to stderr.
+// Logging from within the wrong part of the logger would trigger a deadlock,
+// and even in places where it wouldn't there's a very good chance that the
+// logger is in no condition to handle new log lines.
+#define LOGGER_ASSERT(x) \
+{\
+ if (!(x)) {\
+ fprintf(stderr, "Assertion failed at %s:%d\n", __FILE__, __LINE__);\
+ exit(1);\
+ }\
+}
+
+
+// This class handles logging in SAT. It is a singleton accessed via
+// GlobalLogger().
+//
+// By default log lines are written in the calling thread. Call StartThread()
+// to launch a dedicated thread for the writes.
+class Logger {
+ public:
+ // Returns a pointer to the single global Logger instance. Will not return
+ // NULL.
+ static Logger *GlobalLogger();
+
+ // Lines with a priority numerically greater than this will not be logged.
+ // May not be called while multiple threads are running.
+ virtual void SetVerbosity(int verbosity) {
+ verbosity_ = verbosity;
+ }
+
+ // Sets a file to log to, in addition to stdout. May not be called while
+ // multiple threads are running.
+ //
+ // Args:
+ // log_fd: The file descriptor to write to. Will not be closed by this
+ // object.
+ virtual void SetLogFd(int log_fd) {
+ LOGGER_ASSERT(log_fd >= 0);
+ log_fd_ = log_fd;
+ }
+
+ // Set output to be written to stdout only. This is the default mode. May
+ // not be called while multiple threads are running.
+ virtual void SetStdoutOnly() {
+ log_fd_ = -1;
+ }
+
+ // Enable or disable logging of timestamps.
+ void SetTimestampLogging(bool log_ts_enabled) {
+ log_timestamps_ = log_ts_enabled;
+ }
+
+ // Logs a line, with a vprintf(3)-like interface. This will block on writing
+ // the line to stdout/disk iff the dedicated logging thread is not running.
+ // This will block on adding the line to the queue if doing so would exceed
+ // kMaxQueueSize.
+ //
+ // Args:
+ // priority: If this is numerically greater than the verbosity, the line
+ // will not be logged.
+ // format: see vprintf(3)
+ // args: see vprintf(3)
+ void VLogF(int priority, const char *format, va_list args);
+
+ // Starts the dedicated logging thread. May not be called while multiple
+ // threads are already running.
+ void StartThread();
+
+ // Stops the dedicated logging thread. May only be called when the logging
+ // thread is the only other thread running. Any queued lines will be logged
+ // before this returns. Waits for the thread to finish before returning.
+ void StopThread();
+
+ protected:
+ Logger();
+
+ virtual ~Logger();
+
+ private:
+ // Args:
+ // line: Must be non-NULL. This function takes ownership of it.
+ void QueueLogLine(string *line);
+
+ // Args:
+ // line: Must be non-NULL. This function takes ownership of it.
+ void WriteAndDeleteLogLine(string *line);
+
+ // Callback for pthread_create(3).
+ static void *StartRoutine(void *ptr);
+
+ // Processes the log queue.
+ void ThreadMain();
+
+ pthread_t thread_;
+ int verbosity_;
+ int log_fd_;
+ bool thread_running_;
+ bool log_timestamps_;
+ vector<string*> queued_lines_;
+ // This doubles as a mutex for log_fd_ when the logging thread is not running.
+ pthread_mutex_t queued_lines_mutex_;
+ // Lets the logging thread know that the queue is no longer empty.
+ pthread_cond_t queued_lines_cond_;
+ // Lets the threads blocked on the queue having reached kMaxQueueSize know
+ // that the queue has been emptied.
+ pthread_cond_t full_queue_cond_;
+
+ DISALLOW_COPY_AND_ASSIGN(Logger);
+};
+
+#endif // STRESSAPPTEST_LOGGER_H_
diff --git a/external/subpack/utils/stressapptest/src/src/main.cc b/external/subpack/utils/stressapptest/src/src/main.cc
new file mode 100644
index 0000000..04cd536
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/main.cc
@@ -0,0 +1,56 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// sat.cc : a stress test for stressful testing
+
+#include "sattypes.h"
+#include "sat.h"
+
+int main(int argc, char **argv) {
+ Sat *sat = SatFactory();
+ if (sat == NULL) {
+ logprintf(0, "Process Error: failed to allocate Sat object\n");
+ return 255;
+ }
+
+ if (!sat->ParseArgs(argc, argv)) {
+ logprintf(0, "Process Error: Sat::ParseArgs() failed\n");
+ sat->bad_status();
+ } else if (!sat->Initialize()) {
+ logprintf(0, "Process Error: Sat::Initialize() failed\n");
+ sat->bad_status();
+ } else if (!sat->Run()) {
+ logprintf(0, "Process Error: Sat::Run() failed\n");
+ sat->bad_status();
+ }
+ sat->PrintResults();
+ if (!sat->Cleanup()) {
+ logprintf(0, "Process Error: Sat::Cleanup() failed\n");
+ sat->bad_status();
+ }
+
+ int retval;
+ if (sat->status() != 0) {
+ logprintf(0, "Process Error: Fatal issue encountered. See above logs for "
+ "details.\n");
+ retval = 1;
+ } else if (sat->errors() != 0) {
+ retval = 1;
+ } else {
+ retval = 0;
+ }
+
+ delete sat;
+ return retval;
+}
diff --git a/external/subpack/utils/stressapptest/src/src/os.cc b/external/subpack/utils/stressapptest/src/src/os.cc
new file mode 100644
index 0000000..578e24f
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/os.cc
@@ -0,0 +1,939 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+// Author: nsanders, menderico
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// os.cc : os and machine specific implementation
+// This file includes an abstracted interface
+// for linux-distro specific and HW specific
+// interfaces.
+
+#include "os.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/types.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#ifdef HAVE_SYS_SHM_H
+#include <sys/shm.h>
+#endif
+#include <unistd.h>
+
+#ifndef SHM_HUGETLB
+#define SHM_HUGETLB 04000 // remove when glibc defines it
+#endif
+
+#include <string>
+#include <list>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "sattypes.h"
+#include "error_diag.h"
+#include "clock.h"
+
+// OsLayer initialization.
+OsLayer::OsLayer() {
+ testmem_ = 0;
+ testmemsize_ = 0;
+ totalmemsize_ = 0;
+ min_hugepages_bytes_ = 0;
+ reserve_mb_ = 0;
+ normal_mem_ = true;
+ use_hugepages_ = false;
+ use_posix_shm_ = false;
+ dynamic_mapped_shmem_ = false;
+ mmapped_allocation_ = false;
+ shmid_ = 0;
+ channels_ = NULL;
+
+ time_initialized_ = 0;
+
+ regionsize_ = 0;
+ regioncount_ = 1;
+ num_cpus_ = 0;
+ num_nodes_ = 0;
+ num_cpus_per_node_ = 0;
+ error_diagnoser_ = 0;
+ err_log_callback_ = 0;
+ error_injection_ = false;
+
+ void *pvoid = 0;
+ address_mode_ = sizeof(pvoid) * 8;
+
+ has_clflush_ = false;
+ has_vector_ = false;
+
+ use_flush_page_cache_ = false;
+
+ clock_ = NULL;
+}
+
+// OsLayer cleanup.
+OsLayer::~OsLayer() {
+ if (error_diagnoser_)
+ delete error_diagnoser_;
+ if (clock_)
+ delete clock_;
+}
+
+// OsLayer initialization.
+bool OsLayer::Initialize() {
+ if (!clock_) {
+ clock_ = new Clock();
+ }
+
+ time_initialized_ = clock_->Now();
+ // Detect asm support.
+ GetFeatures();
+
+ if (num_cpus_ == 0) {
+ num_nodes_ = 1;
+ num_cpus_ = sysconf(_SC_NPROCESSORS_ONLN);
+ num_cpus_per_node_ = num_cpus_ / num_nodes_;
+ }
+ logprintf(5, "Log: %d nodes, %d cpus.\n", num_nodes_, num_cpus_);
+ cpu_sets_.resize(num_nodes_);
+ cpu_sets_valid_.resize(num_nodes_);
+ // Create error diagnoser.
+ error_diagnoser_ = new ErrorDiag();
+ if (!error_diagnoser_->set_os(this))
+ return false;
+ return true;
+}
+
+// Machine type detected. Can we implement all these functions correctly?
+bool OsLayer::IsSupported() {
+ if (kOpenSource) {
+ // There are no explicitly supported systems in open source version.
+ return true;
+ }
+
+ // This is the default empty implementation.
+ // SAT won't report full error information.
+ return false;
+}
+
+int OsLayer::AddressMode() {
+ // Detect 32/64 bit binary.
+ void *pvoid = 0;
+ return sizeof(pvoid) * 8;
+}
+
+// Translates user virtual to physical address.
+uint64 OsLayer::VirtualToPhysical(void *vaddr) {
+ uint64 frame, paddr, pfnmask, pagemask;
+ int pagesize = sysconf(_SC_PAGESIZE);
+ off_t off = ((uintptr_t)vaddr) / pagesize * 8;
+ int fd = open(kPagemapPath, O_RDONLY);
+
+ /*
+ * https://www.kernel.org/doc/Documentation/vm/pagemap.txt
+ * API change (July 2015)
+ * https://patchwork.kernel.org/patch/6787991/
+ */
+
+ if (fd < 0)
+ return 0;
+
+ if (lseek(fd, off, SEEK_SET) != off || read(fd, &frame, 8) != 8) {
+ int err = errno;
+ string errtxt = ErrorString(err);
+ logprintf(0, "Process Error: failed to access %s with errno %d (%s)\n",
+ kPagemapPath, err, errtxt.c_str());
+ if (fd >= 0)
+ close(fd);
+ return 0;
+ }
+ close(fd);
+
+ /* Check if page is present and not swapped. */
+ if (!(frame & (1ULL << 63)) || (frame & (1ULL << 62)))
+ return 0;
+
+ /* pfn is bits 0-54. */
+ pfnmask = ((1ULL << 55) - 1);
+ /* Pagesize had better be a power of 2. */
+ pagemask = pagesize - 1;
+
+ paddr = ((frame & pfnmask) * pagesize) | ((uintptr_t)vaddr & pagemask);
+ return paddr;
+}
+
+// Returns the HD device that contains this file.
+string OsLayer::FindFileDevice(string filename) {
+ return "hdUnknown";
+}
+
+// Returns a list of locations corresponding to HD devices.
+list<string> OsLayer::FindFileDevices() {
+ // No autodetection on unknown systems.
+ list<string> locations;
+ return locations;
+}
+
+
+// Get HW core features from cpuid instruction.
+void OsLayer::GetFeatures() {
+#if defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
+ unsigned int eax = 1, ebx, ecx, edx;
+ cpuid(&eax, &ebx, &ecx, &edx);
+ has_clflush_ = (edx >> 19) & 1;
+ has_vector_ = (edx >> 26) & 1; // SSE2 caps bit.
+
+ logprintf(9, "Log: has clflush: %s, has sse2: %s\n",
+ has_clflush_ ? "true" : "false",
+ has_vector_ ? "true" : "false");
+#elif defined(STRESSAPPTEST_CPU_PPC)
+ // All PPC implementations have cache flush instructions.
+ has_clflush_ = true;
+#elif defined(STRESSAPPTEST_CPU_MIPS)
+ // All MIPS implementations have cache flush instructions.
+ has_clflush_ = true;
+#elif defined(STRESSAPPTEST_CPU_ARMV7A) || defined(STRESSAPPTEST_CPU_AARCH64)
+ // TODO(nsanders): add detect from /proc/cpuinfo or /proc/self/auxv.
+ // For now assume neon and don't run -W if you don't have it.
+ has_vector_ = true; // NEON.
+#elif defined(STRESSAPPTEST_CPU_LOONGARCH)
+ has_clflush_ = true;
+#else
+#warning "Unsupported CPU type: unable to determine feature set."
+#endif
+}
+
+
+// Enable FlushPageCache to be functional instead of a NOP.
+void OsLayer::ActivateFlushPageCache(void) {
+ logprintf(9, "Log: page cache will be flushed as needed\n");
+ use_flush_page_cache_ = true;
+}
+
+// Flush the page cache to ensure reads come from the disk.
+bool OsLayer::FlushPageCache(void) {
+ if (!use_flush_page_cache_)
+ return true;
+
+ // First, ask the kernel to write the cache to the disk.
+ sync();
+
+ // Second, ask the kernel to empty the cache by writing "1" to
+ // "/proc/sys/vm/drop_caches".
+ static const char *drop_caches_file = "/proc/sys/vm/drop_caches";
+ int dcfile = open(drop_caches_file, O_WRONLY);
+ if (dcfile < 0) {
+ int err = errno;
+ string errtxt = ErrorString(err);
+ logprintf(3, "Log: failed to open %s - err %d (%s)\n",
+ drop_caches_file, err, errtxt.c_str());
+ return false;
+ }
+
+ ssize_t bytes_written = write(dcfile, "1", 1);
+ close(dcfile);
+
+ if (bytes_written != 1) {
+ int err = errno;
+ string errtxt = ErrorString(err);
+ logprintf(3, "Log: failed to write %s - err %d (%s)\n",
+ drop_caches_file, err, errtxt.c_str());
+ return false;
+ }
+ return true;
+}
+
+
+// We need to flush the cacheline here.
+void OsLayer::Flush(void *vaddr) {
+ // Use the generic flush. This function is just so we can override
+ // this if we are so inclined.
+ if (has_clflush_) {
+ OsLayer::FastFlush(vaddr);
+ }
+}
+
+
+// Run C or ASM copy as appropriate..
+bool OsLayer::AdlerMemcpyWarm(uint64 *dstmem, uint64 *srcmem,
+ unsigned int size_in_bytes,
+ AdlerChecksum *checksum) {
+ if (has_vector_) {
+ return AdlerMemcpyAsm(dstmem, srcmem, size_in_bytes, checksum);
+ } else {
+ return AdlerMemcpyWarmC(dstmem, srcmem, size_in_bytes, checksum);
+ }
+}
+
+
+// Translate physical address to memory module/chip name.
+// Assumes interleaving between two memory channels based on the XOR of
+// all address bits in the 'channel_hash' mask, with repeated 'channel_width_'
+// blocks with bits distributed from each chip in that channel.
+int OsLayer::FindDimm(uint64 addr, char *buf, int len) {
+ if (!channels_) {
+ snprintf(buf, len, "DIMM Unknown");
+ return -1;
+ }
+
+ // Find channel by XORing address bits in channel_hash mask.
+ uint32 low = static_cast<uint32>(addr & channel_hash_);
+ uint32 high = static_cast<uint32>((addr & channel_hash_) >> 32);
+ vector<string>& channel = (*channels_)[
+ __builtin_parity(high) ^ __builtin_parity(low)];
+
+ // Find dram chip by finding which byte within the channel
+ // by address mod channel width, then divide the channel
+ // evenly among the listed dram chips. Note, this will not work
+ // with x4 dram.
+ int chip = (addr % (channel_width_ / 8)) /
+ ((channel_width_ / 8) / channel.size());
+ string name = channel[chip];
+ snprintf(buf, len, "%s", name.c_str());
+ return 1;
+}
+
+
+// Classifies addresses according to "regions"
+// This isn't really implemented meaningfully here..
+int32 OsLayer::FindRegion(uint64 addr) {
+ static bool warned = false;
+
+ if (regionsize_ == 0) {
+ regionsize_ = totalmemsize_ / 8;
+ if (regionsize_ < 512 * kMegabyte)
+ regionsize_ = 512 * kMegabyte;
+ regioncount_ = totalmemsize_ / regionsize_;
+ if (regioncount_ < 1) regioncount_ = 1;
+ }
+
+ int32 region_num = addr / regionsize_;
+ if (region_num >= regioncount_) {
+ if (!warned) {
+ logprintf(0, "Log: region number %d exceeds region count %d\n",
+ region_num, regioncount_);
+ warned = true;
+ }
+ region_num = region_num % regioncount_;
+ }
+ return region_num;
+}
+
+// Report which cores are associated with a given region.
+cpu_set_t *OsLayer::FindCoreMask(int32 region) {
+ sat_assert(region >= 0);
+ region %= num_nodes_;
+ if (!cpu_sets_valid_[region]) {
+ CPU_ZERO(&cpu_sets_[region]);
+ for (int i = 0; i < num_cpus_per_node_; ++i) {
+ CPU_SET(i + region * num_cpus_per_node_, &cpu_sets_[region]);
+ }
+ cpu_sets_valid_[region] = true;
+ logprintf(5, "Log: Region %d mask 0x%s\n",
+ region, FindCoreMaskFormat(region).c_str());
+ }
+ return &cpu_sets_[region];
+}
+
+// Return cores associated with a given region in hex string.
+string OsLayer::FindCoreMaskFormat(int32 region) {
+ cpu_set_t* mask = FindCoreMask(region);
+ string format = cpuset_format(mask);
+ if (format.size() < 8)
+ format = string(8 - format.size(), '0') + format;
+ return format;
+}
+
+// Report an error in an easily parseable way.
+bool OsLayer::ErrorReport(const char *part, const char *symptom, int count) {
+ time_t now = clock_->Now();
+ int ttf = now - time_initialized_;
+ if (strlen(symptom) && strlen(part)) {
+ logprintf(0, "Report Error: %s : %s : %d : %ds\n",
+ symptom, part, count, ttf);
+ } else {
+ // Log something so the error still shows up, but this won't break the
+ // parser.
+ logprintf(0, "Warning: Invalid Report Error: "
+ "%s : %s : %d : %ds\n", symptom, part, count, ttf);
+ }
+ return true;
+}
+
+// Read the number of hugepages out of the kernel interface in proc.
+int64 OsLayer::FindHugePages() {
+ char buf[65] = "0";
+
+ // This is a kernel interface to query the numebr of hugepages
+ // available in the system.
+ static const char *hugepages_info_file = "/proc/sys/vm/nr_hugepages";
+ int hpfile = open(hugepages_info_file, O_RDONLY);
+
+ ssize_t bytes_read = read(hpfile, buf, 64);
+ close(hpfile);
+
+ if (bytes_read <= 0) {
+ logprintf(12, "Log: /proc/sys/vm/nr_hugepages "
+ "read did not provide data\n");
+ return 0;
+ }
+
+ if (bytes_read == 64) {
+ logprintf(0, "Process Error: /proc/sys/vm/nr_hugepages "
+ "is surprisingly large\n");
+ return 0;
+ }
+
+ // Add a null termintation to be string safe.
+ buf[bytes_read] = '\0';
+ // Read the page count.
+ int64 pages = strtoull(buf, NULL, 10); // NOLINT
+
+ return pages;
+}
+
+int64 OsLayer::FindFreeMemSize() {
+ int64 size = 0;
+ int64 minsize = 0;
+ if (totalmemsize_ > 0)
+ return totalmemsize_;
+
+ int64 pages = sysconf(_SC_PHYS_PAGES);
+ int64 avpages = sysconf(_SC_AVPHYS_PAGES);
+ int64 pagesize = sysconf(_SC_PAGESIZE);
+ int64 physsize = pages * pagesize;
+ int64 avphyssize = avpages * pagesize;
+
+ // Assume 2MB hugepages.
+ int64 hugepagesize = FindHugePages() * 2 * kMegabyte;
+
+ if ((pages == -1) || (pagesize == -1)) {
+ logprintf(0, "Process Error: sysconf could not determine memory size.\n");
+ return 0;
+ }
+
+ // We want to leave enough stuff for things to run.
+ // If the user specified a minimum amount of memory to expect, require that.
+ // Otherwise, if more than 2GB is present, leave 192M + 5% for other stuff.
+ // If less than 2GB is present use 85% of what's available.
+ // These are fairly arbitrary numbers that seem to work OK.
+ //
+ // TODO(nsanders): is there a more correct way to determine target
+ // memory size?
+ if (hugepagesize > 0) {
+ if (min_hugepages_bytes_ > 0) {
+ minsize = min_hugepages_bytes_;
+ } else {
+ minsize = hugepagesize;
+ }
+ } else {
+ if (physsize < 2048LL * kMegabyte) {
+ minsize = ((pages * 85) / 100) * pagesize;
+ } else {
+ minsize = ((pages * 95) / 100) * pagesize - (192 * kMegabyte);
+ }
+ // Make sure that at least reserve_mb_ is left for the system.
+ if (reserve_mb_ > 0) {
+ int64 totalsize = pages * pagesize;
+ int64 reserve_kb = reserve_mb_ * kMegabyte;
+ if (reserve_kb > totalsize) {
+ logprintf(0, "Procedural Error: %lld is bigger than the total memory "
+ "available %lld\n", reserve_kb, totalsize);
+ } else if (reserve_kb > totalsize - minsize) {
+ logprintf(5, "Warning: Overriding memory to use: original %lld, "
+ "current %lld\n", minsize, totalsize - reserve_kb);
+ minsize = totalsize - reserve_kb;
+ }
+ }
+ }
+
+ // Use hugepage sizing if available.
+ if (hugepagesize > 0) {
+ if (hugepagesize < minsize) {
+ logprintf(0, "Procedural Error: Not enough hugepages. "
+ "%lldMB available < %lldMB required.\n",
+ hugepagesize / kMegabyte,
+ minsize / kMegabyte);
+ // Require the calculated minimum amount of memory.
+ size = minsize;
+ } else {
+ // Require that we get all hugepages.
+ size = hugepagesize;
+ }
+ } else {
+ // Require the calculated minimum amount of memory.
+ size = minsize;
+ }
+
+ logprintf(5, "Log: Total %lld MB. Free %lld MB. Hugepages %lld MB. "
+ "Targeting %lld MB (%lld%%)\n",
+ physsize / kMegabyte,
+ avphyssize / kMegabyte,
+ hugepagesize / kMegabyte,
+ size / kMegabyte,
+ size * 100 / physsize);
+
+ totalmemsize_ = size;
+ return size;
+}
+
+// Allocates all memory available.
+int64 OsLayer::AllocateAllMem() {
+ int64 length = FindFreeMemSize();
+ bool retval = AllocateTestMem(length, 0);
+ if (retval)
+ return length;
+ else
+ return 0;
+}
+
+// Allocate the target memory. This may be from malloc, hugepage pool
+// or other platform specific sources.
+bool OsLayer::AllocateTestMem(int64 length, uint64 paddr_base) {
+ // Try hugepages first.
+ void *buf = 0;
+
+ sat_assert(length >= 0);
+
+ if (paddr_base)
+ logprintf(0, "Process Error: non zero paddr_base %#llx is not supported,"
+ " ignore.\n", paddr_base);
+
+ // Determine optimal memory allocation path.
+ bool prefer_hugepages = false;
+ bool prefer_posix_shm = false;
+ bool prefer_dynamic_mapping = false;
+
+ // Are there enough hugepages?
+ int64 hugepagesize = FindHugePages() * 2 * kMegabyte;
+ // TODO(nsanders): Is there enough /dev/shm? Is there enough free memeory?
+ if ((length >= 1400LL * kMegabyte) && (address_mode_ == 32)) {
+ prefer_dynamic_mapping = true;
+ prefer_posix_shm = true;
+ logprintf(3, "Log: Prefer POSIX shared memory allocation.\n");
+ logprintf(3, "Log: You may need to run "
+ "'sudo mount -o remount,size=100\% /dev/shm.'\n");
+ } else if (hugepagesize >= length) {
+ prefer_hugepages = true;
+ logprintf(3, "Log: Prefer using hugepage allocation.\n");
+ } else {
+ logprintf(3, "Log: Prefer plain malloc memory allocation.\n");
+ }
+
+#ifdef HAVE_SYS_SHM_H
+ // Allocate hugepage mapped memory.
+ if (prefer_hugepages) {
+ do { // Allow break statement.
+ int shmid;
+ void *shmaddr;
+
+ if ((shmid = shmget(2, length,
+ SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) {
+ int err = errno;
+ string errtxt = ErrorString(err);
+ logprintf(3, "Log: failed to allocate shared hugepage "
+ "object - err %d (%s)\n",
+ err, errtxt.c_str());
+ logprintf(3, "Log: sysctl -w vm.nr_hugepages=XXX allows hugepages.\n");
+ break;
+ }
+
+ shmaddr = shmat(shmid, NULL, 0);
+ if (shmaddr == reinterpret_cast<void*>(-1)) {
+ int err = errno;
+ string errtxt = ErrorString(err);
+ logprintf(0, "Log: failed to attach shared "
+ "hugepage object - err %d (%s).\n",
+ err, errtxt.c_str());
+ if (shmctl(shmid, IPC_RMID, NULL) < 0) {
+ int err = errno;
+ string errtxt = ErrorString(err);
+ logprintf(0, "Log: failed to remove shared "
+ "hugepage object - err %d (%s).\n",
+ err, errtxt.c_str());
+ }
+ break;
+ }
+ use_hugepages_ = true;
+ shmid_ = shmid;
+ buf = shmaddr;
+ logprintf(0, "Log: Using shared hugepage object 0x%x at %p.\n",
+ shmid, shmaddr);
+ } while (0);
+ }
+
+ if ((!use_hugepages_) && prefer_posix_shm) {
+ do {
+ int shm_object;
+ void *shmaddr = NULL;
+
+ shm_object = shm_open("/stressapptest", O_CREAT | O_RDWR, S_IRWXU);
+ if (shm_object < 0) {
+ int err = errno;
+ string errtxt = ErrorString(err);
+ logprintf(3, "Log: failed to allocate shared "
+ "smallpage object - err %d (%s)\n",
+ err, errtxt.c_str());
+ break;
+ }
+
+ if (0 > ftruncate(shm_object, length)) {
+ int err = errno;
+ string errtxt = ErrorString(err);
+ logprintf(3, "Log: failed to ftruncate shared "
+ "smallpage object - err %d (%s)\n",
+ err, errtxt.c_str());
+ break;
+ }
+
+ // 32 bit linux apps can only use ~1.4G of address space.
+ // Use dynamic mapping for allocations larger than that.
+ // Currently perf hit is ~10% for this.
+ if (prefer_dynamic_mapping) {
+ dynamic_mapped_shmem_ = true;
+ } else {
+ // Do a full mapping here otherwise.
+ shmaddr = mmap(NULL, length, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_NORESERVE | MAP_LOCKED | MAP_POPULATE,
+ shm_object, 0);
+ if (shmaddr == reinterpret_cast<void*>(-1)) {
+ int err = errno;
+ string errtxt = ErrorString(err);
+ logprintf(0, "Log: failed to map shared "
+ "smallpage object - err %d (%s).\n",
+ err, errtxt.c_str());
+ break;
+ }
+ }
+
+ use_posix_shm_ = true;
+ shmid_ = shm_object;
+ buf = shmaddr;
+ char location_message[256] = "";
+ if (dynamic_mapped_shmem_) {
+ sprintf(location_message, "mapped as needed");
+ } else {
+ sprintf(location_message, "at %p", shmaddr);
+ }
+ logprintf(0, "Log: Using posix shared memory object 0x%x %s.\n",
+ shm_object, location_message);
+ } while (0);
+ shm_unlink("/stressapptest");
+ }
+#endif // HAVE_SYS_SHM_H
+
+ if (!use_hugepages_ && !use_posix_shm_) {
+ // If the page size is what SAT is expecting explicitly perform mmap()
+ // allocation.
+ if (sysconf(_SC_PAGESIZE) >= 4096) {
+ void *map_buf = mmap(NULL, length, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (map_buf != MAP_FAILED) {
+ buf = map_buf;
+ mmapped_allocation_ = true;
+ logprintf(0, "Log: Using mmap() allocation at %p.\n", buf);
+ }
+ }
+ if (!mmapped_allocation_) {
+ // Use memalign to ensure that blocks are aligned enough for disk direct
+ // IO.
+ buf = static_cast<char*>(memalign(4096, length));
+ if (buf) {
+ logprintf(0, "Log: Using memaligned allocation at %p.\n", buf);
+ } else {
+ logprintf(0, "Process Error: memalign returned 0\n");
+ if ((length >= 1499LL * kMegabyte) && (address_mode_ == 32)) {
+ logprintf(0, "Log: You are trying to allocate > 1.4G on a 32 "
+ "bit process. Please setup shared memory.\n");
+ }
+ }
+ }
+ }
+
+ testmem_ = buf;
+ if (buf || dynamic_mapped_shmem_) {
+ testmemsize_ = length;
+ } else {
+ testmemsize_ = 0;
+ }
+
+ return (buf != 0) || dynamic_mapped_shmem_;
+}
+
+// Free the test memory.
+void OsLayer::FreeTestMem() {
+ if (testmem_) {
+ if (use_hugepages_) {
+#ifdef HAVE_SYS_SHM_H
+ shmdt(testmem_);
+ shmctl(shmid_, IPC_RMID, NULL);
+#endif
+ } else if (use_posix_shm_) {
+ if (!dynamic_mapped_shmem_) {
+ munmap(testmem_, testmemsize_);
+ }
+ close(shmid_);
+ } else if (mmapped_allocation_) {
+ munmap(testmem_, testmemsize_);
+ } else {
+ free(testmem_);
+ }
+ testmem_ = 0;
+ testmemsize_ = 0;
+ }
+}
+
+
+// Prepare the target memory. It may requre mapping in, or this may be a noop.
+void *OsLayer::PrepareTestMem(uint64 offset, uint64 length) {
+ sat_assert((offset + length) <= testmemsize_);
+ if (dynamic_mapped_shmem_) {
+ // TODO(nsanders): Check if we can support MAP_NONBLOCK,
+ // and evaluate performance hit from not using it.
+ void * mapping = mmap(NULL, length, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_NORESERVE | MAP_LOCKED | MAP_POPULATE,
+ shmid_, offset);
+ if (mapping == MAP_FAILED) {
+ string errtxt = ErrorString(errno);
+ logprintf(0, "Process Error: PrepareTestMem mmap(%llx, %llx) failed. "
+ "error: %s.\n",
+ offset, length, errtxt.c_str());
+ sat_assert(0);
+ }
+ return mapping;
+ }
+
+ return reinterpret_cast<void*>(reinterpret_cast<char*>(testmem_) + offset);
+}
+
+// Release the test memory resources, if any.
+void OsLayer::ReleaseTestMem(void *addr, uint64 offset, uint64 length) {
+ if (dynamic_mapped_shmem_) {
+ int retval = munmap(addr, length);
+ if (retval == -1) {
+ string errtxt = ErrorString(errno);
+ logprintf(0, "Process Error: ReleaseTestMem munmap(%p, %llx) failed. "
+ "error: %s.\n",
+ addr, length, errtxt.c_str());
+ sat_assert(0);
+ }
+ }
+}
+
+// No error polling on unknown systems.
+int OsLayer::ErrorPoll() {
+ return 0;
+}
+
+// Generally, poll for errors once per second.
+void OsLayer::ErrorWait() {
+ sat_sleep(1);
+ return;
+}
+
+// Open a PCI bus-dev-func as a file and return its file descriptor.
+// Error is indicated by return value less than zero.
+int OsLayer::PciOpen(int bus, int device, int function) {
+ char dev_file[256];
+
+ snprintf(dev_file, sizeof(dev_file), "/proc/bus/pci/%02x/%02x.%x",
+ bus, device, function);
+
+ int fd = open(dev_file, O_RDWR);
+ if (fd == -1) {
+ logprintf(0, "Process Error: Unable to open PCI bus %d, device %d, "
+ "function %d (errno %d).\n",
+ bus, device, function, errno);
+ return -1;
+ }
+
+ return fd;
+}
+
+
+// Read and write functions to access PCI config.
+uint32 OsLayer::PciRead(int fd, uint32 offset, int width) {
+ // Strict aliasing rules lawyers will cause data corruption
+ // on cast pointers in some gccs.
+ union {
+ uint32 l32;
+ uint16 l16;
+ uint8 l8;
+ } datacast;
+ datacast.l32 = 0;
+ uint32 size = width / 8;
+
+ sat_assert((width == 32) || (width == 16) || (width == 8));
+ sat_assert(offset <= (256 - size));
+
+ if (lseek(fd, offset, SEEK_SET) < 0) {
+ logprintf(0, "Process Error: Can't seek %x\n", offset);
+ return 0;
+ }
+ if (read(fd, &datacast, size) != static_cast<ssize_t>(size)) {
+ logprintf(0, "Process Error: Can't read %x\n", offset);
+ return 0;
+ }
+
+ // Extract the data.
+ switch (width) {
+ case 8:
+ sat_assert(&(datacast.l8) == reinterpret_cast<uint8*>(&datacast));
+ return datacast.l8;
+ case 16:
+ sat_assert(&(datacast.l16) == reinterpret_cast<uint16*>(&datacast));
+ return datacast.l16;
+ case 32:
+ return datacast.l32;
+ }
+ return 0;
+}
+
+void OsLayer::PciWrite(int fd, uint32 offset, uint32 value, int width) {
+ // Strict aliasing rules lawyers will cause data corruption
+ // on cast pointers in some gccs.
+ union {
+ uint32 l32;
+ uint16 l16;
+ uint8 l8;
+ } datacast;
+ datacast.l32 = 0;
+ uint32 size = width / 8;
+
+ sat_assert((width == 32) || (width == 16) || (width == 8));
+ sat_assert(offset <= (256 - size));
+
+ // Cram the data into the right alignment.
+ switch (width) {
+ case 8:
+ sat_assert(&(datacast.l8) == reinterpret_cast<uint8*>(&datacast));
+ datacast.l8 = value;
+ case 16:
+ sat_assert(&(datacast.l16) == reinterpret_cast<uint16*>(&datacast));
+ datacast.l16 = value;
+ case 32:
+ datacast.l32 = value;
+ }
+
+ if (lseek(fd, offset, SEEK_SET) < 0) {
+ logprintf(0, "Process Error: Can't seek %x\n", offset);
+ return;
+ }
+ if (write(fd, &datacast, size) != static_cast<ssize_t>(size)) {
+ logprintf(0, "Process Error: Can't write %x to %x\n", datacast.l32, offset);
+ return;
+ }
+
+ return;
+}
+
+
+
+// Open dev msr.
+int OsLayer::OpenMSR(uint32 core, uint32 address) {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "/dev/cpu/%d/msr", core);
+ int fd = open(buf, O_RDWR);
+ if (fd < 0)
+ return fd;
+
+ uint32 pos = lseek(fd, address, SEEK_SET);
+ if (pos != address) {
+ close(fd);
+ logprintf(5, "Log: can't seek to msr %x, cpu %d\n", address, core);
+ return -1;
+ }
+
+ return fd;
+}
+
+bool OsLayer::ReadMSR(uint32 core, uint32 address, uint64 *data) {
+ int fd = OpenMSR(core, address);
+ if (fd < 0)
+ return false;
+
+ // Read from the msr.
+ bool res = (sizeof(*data) == read(fd, data, sizeof(*data)));
+
+ if (!res)
+ logprintf(5, "Log: Failed to read msr %x core %d\n", address, core);
+
+ close(fd);
+
+ return res;
+}
+
+bool OsLayer::WriteMSR(uint32 core, uint32 address, uint64 *data) {
+ int fd = OpenMSR(core, address);
+ if (fd < 0)
+ return false;
+
+ // Write to the msr
+ bool res = (sizeof(*data) == write(fd, data, sizeof(*data)));
+
+ if (!res)
+ logprintf(5, "Log: Failed to write msr %x core %d\n", address, core);
+
+ close(fd);
+
+ return res;
+}
+
+// Extract bits [n+len-1, n] from a 32 bit word.
+// so GetBitField(0x0f00, 8, 4) == 0xf.
+uint32 OsLayer::GetBitField(uint32 val, uint32 n, uint32 len) {
+ return (val >> n) & ((1<<len) - 1);
+}
+
+// Generic CPU stress workload that would work on any CPU/Platform.
+// Float-point array moving average calculation.
+bool OsLayer::CpuStressWorkload() {
+ double float_arr[100];
+ double sum = 0;
+#ifdef HAVE_RAND_R
+ unsigned int seed = 12345;
+#endif
+
+ // Initialize array with random numbers.
+ for (int i = 0; i < 100; i++) {
+#ifdef HAVE_RAND_R
+ float_arr[i] = rand_r(&seed);
+ if (rand_r(&seed) % 2)
+ float_arr[i] *= -1.0;
+#else
+ srand(time(NULL));
+ float_arr[i] = rand(); // NOLINT
+ if (rand() % 2) // NOLINT
+ float_arr[i] *= -1.0;
+#endif
+ }
+
+ // Calculate moving average.
+ for (int i = 0; i < 10000000; i++) {
+ float_arr[i % 100] =
+ (float_arr[i % 100] + float_arr[(i + 1) % 100] +
+ float_arr[(i + 99) % 100]) / 3;
+ sum += float_arr[i % 100];
+ }
+
+ // Artificial printf so the loops do not get optimized away.
+ if (sum == 0.0)
+ logprintf(12, "Log: I'm Feeling Lucky!\n");
+ return true;
+}
diff --git a/external/subpack/utils/stressapptest/src/src/os.h b/external/subpack/utils/stressapptest/src/src/os.h
new file mode 100644
index 0000000..440d79c
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/os.h
@@ -0,0 +1,450 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+// Author: nsanders, menderico
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STRESSAPPTEST_OS_H_ // NOLINT
+#define STRESSAPPTEST_OS_H_
+
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <stdint.h>
+
+#include <cstdint>
+#include <string>
+#include <list>
+#include <map>
+#include <vector>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "adler32memcpy.h" // NOLINT
+#include "sattypes.h" // NOLINT
+#include "clock.h" // NOLINT
+
+#if defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
+#include <immintrin.h>
+#include <x86intrin.h>
+#if defined(_MSC_VER)
+#include <intrin.h>
+#endif
+#endif
+
+const char kPagemapPath[] = "/proc/self/pagemap";
+
+struct PCIDevice {
+ int32 domain;
+ uint16 bus;
+ uint8 dev;
+ uint8 func;
+ uint16 vendor_id;
+ uint16 device_id;
+ uint64 base_addr[6];
+ uint64 size[6];
+};
+
+typedef vector<PCIDevice*> PCIDevices;
+
+class ErrorDiag;
+
+class Clock;
+
+// This class implements OS/Platform specific funtions.
+class OsLayer {
+ public:
+ OsLayer();
+ virtual ~OsLayer();
+
+ // Set the minimum amount of hugepages that should be available for testing.
+ // Must be set before Initialize().
+ void SetMinimumHugepagesSize(int64 min_bytes) {
+ min_hugepages_bytes_ = min_bytes;
+ }
+
+ // Set the minium amount of memory that should not be allocated. This only
+ // has any affect if hugepages are not used.
+ // Must be set before Initialize().
+ void SetReserveSize(int64 reserve_mb) {
+ reserve_mb_ = reserve_mb;
+ }
+
+ // Set parameters needed to translate physical address to memory module.
+ void SetDramMappingParams(uintptr_t channel_hash, int channel_width,
+ vector< vector<string> > *channels) {
+ channel_hash_ = channel_hash;
+ channel_width_ = channel_width;
+ channels_ = channels;
+ }
+
+ // Initializes data strctures and open files.
+ // Returns false on error.
+ virtual bool Initialize();
+
+ // Virtual to physical. This implementation is optional for
+ // subclasses to implement.
+ // Takes a pointer, and returns the corresponding bus address.
+ virtual uint64 VirtualToPhysical(void *vaddr);
+
+ // Prints failed dimm. This implementation is optional for
+ // subclasses to implement.
+ // Takes a bus address and string, and prints the DIMM name
+ // into the string. Returns the DIMM number that corresponds to the
+ // address given, or -1 if unable to identify the DIMM number.
+ // Note that subclass implementations of FindDimm() MUST fill
+ // buf with at LEAST one non-whitespace character (provided len > 0).
+ virtual int FindDimm(uint64 addr, char *buf, int len);
+
+ // Classifies addresses according to "regions"
+ // This may mean different things on different platforms.
+ virtual int32 FindRegion(uint64 paddr);
+ // Find cpu cores associated with a region. Either NUMA or arbitrary.
+ virtual cpu_set_t *FindCoreMask(int32 region);
+ // Return cpu cores associated with a region in a hex string.
+ virtual string FindCoreMaskFormat(int32 region);
+
+ // Returns the HD device that contains this file.
+ virtual string FindFileDevice(string filename);
+
+ // Returns a list of paths coresponding to HD devices found on this machine.
+ virtual list<string> FindFileDevices();
+
+ // Polls for errors. This implementation is optional.
+ // This will poll once for errors and return zero iff no errors were found.
+ virtual int ErrorPoll();
+
+ // Delay an appropriate amount of time between polling.
+ virtual void ErrorWait();
+
+ // Report errors. This implementation is mandatory.
+ // This will output a machine readable line regarding the error.
+ virtual bool ErrorReport(const char *part, const char *symptom, int count);
+
+ // Flushes page cache. Used to circumvent the page cache when doing disk
+ // I/O. This will be a NOP until ActivateFlushPageCache() is called, which
+ // is typically done when opening a file with O_DIRECT fails.
+ // Returns false on error, true on success or NOP.
+ // Subclasses may implement this in machine specific ways..
+ virtual bool FlushPageCache(void);
+ // Enable FlushPageCache() to actually do the flush instead of being a NOP.
+ virtual void ActivateFlushPageCache(void);
+
+ // Flushes cacheline. Used to distinguish read or write errors.
+ // Subclasses may implement this in machine specific ways..
+ // Takes a pointer, and flushed the cacheline containing that pointer.
+ virtual void Flush(void *vaddr);
+
+ // Fast flush, for use in performance critical code.
+ // This is bound at compile time, and will not pick up
+ // any runtime machine configuration info.
+ inline static void FastFlush(void *vaddr) {
+#ifdef STRESSAPPTEST_CPU_PPC
+ asm volatile("dcbf 0,%0; sync" : : "r" (vaddr));
+#elif defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
+ // Put mfence before and after clflush to make sure:
+ // 1. The write before the clflush is committed to memory bus;
+ // 2. The read after the clflush is hitting the memory bus.
+ //
+ // From Intel manual:
+ // CLFLUSH is only ordered by the MFENCE instruction. It is not guaranteed
+ // to be ordered by any other fencing, serializing or other CLFLUSH
+ // instruction. For example, software can use an MFENCE instruction to
+ // insure that previous stores are included in the write-back.
+ _mm_mfence();
+ _mm_clflush(vaddr);
+ _mm_mfence();
+#elif defined(STRESSAPPTEST_CPU_MIPS)
+ syscall(__NR_cacheflush, vaddr, 32, 0);
+#elif defined(STRESSAPPTEST_CPU_ARMV7A)
+ // ARMv7a cachelines are 8 words (32 bytes).
+ syscall(__ARM_NR_cacheflush, vaddr, reinterpret_cast<char*>(vaddr) + 32, 0);
+#elif defined(STRESSAPPTEST_CPU_AARCH64)
+ asm volatile("dc cvau, %0" : : "r" (vaddr));
+ asm volatile("dsb ish");
+ asm volatile("ic ivau, %0" : : "r" (vaddr));
+ asm volatile("dsb ish");
+ asm volatile("isb");
+#elif defined(STRESSAPPTEST_CPU_LOONGARCH)
+ // Reference linux kernel: arch/loongarch/mm/cache.c
+ asm volatile("ibar 0");
+#else
+ #warning "Unsupported CPU type: Unable to force cache flushes."
+#endif
+ }
+
+ // Fast flush, for use in performance critical code.
+ // This is bound at compile time, and will not pick up
+ // any runtime machine configuration info. Takes a NULL-terminated
+ // array of addresses to flush.
+ inline static void FastFlushList(void **vaddrs) {
+#ifdef STRESSAPPTEST_CPU_PPC
+ while (*vaddrs) {
+ asm volatile("dcbf 0,%0" : : "r" (*vaddrs++));
+ }
+ asm volatile("sync");
+#elif defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
+ // Put mfence before and after clflush to make sure:
+ // 1. The write before the clflush is committed to memory bus;
+ // 2. The read after the clflush is hitting the memory bus.
+ //
+ // From Intel manual:
+ // CLFLUSH is only ordered by the MFENCE instruction. It is not guaranteed
+ // to be ordered by any other fencing, serializing or other CLFLUSH
+ // instruction. For example, software can use an MFENCE instruction to
+ // insure that previous stores are included in the write-back.
+ _mm_mfence();
+ while (*vaddrs) {
+ _mm_clflush(*vaddrs++);
+ }
+ _mm_mfence();
+#elif defined(STRESSAPPTEST_CPU_MIPS) || defined(STRESSAPPTEST_CPU_ARMV7A) || \
+ defined(STRESSAPPTEST_CPU_AARCH64) || defined(STRESSAPPTEST_CPU_LOONGARCH)
+ while (*vaddrs) {
+ FastFlush(*vaddrs++);
+ }
+#else
+ #warning "Unsupported CPU type: Unable to force cache flushes."
+#endif
+ }
+
+ // Fast flush hint, for use in performance critical code.
+ // This is bound at compile time, and will not pick up
+ // any runtime machine configuration info. Note that this
+ // will not guarantee that a flush happens, but will at least
+ // hint that it should. This is useful for speeding up
+ // parallel march algorithms.
+ inline static void FastFlushHint(void *vaddr) {
+#ifdef STRESSAPPTEST_CPU_PPC
+ asm volatile("dcbf 0,%0" : : "r" (vaddr));
+#elif defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
+ // From Intel manual:
+ // CLFLUSH is only ordered by the MFENCE instruction. It is not guaranteed
+ // to be ordered by any other fencing, serializing or other CLFLUSH
+ // instruction. For example, software can use an MFENCE instruction to
+ // insure that previous stores are included in the write-back.
+ _mm_clflush(vaddr);
+#elif defined(STRESSAPPTEST_CPU_MIPS) || defined(STRESSAPPTEST_CPU_ARMV7A) || \
+ defined(STRESSAPPTEST_CPU_AARCH64) || defined(STRESSAPPTEST_CPU_LOONGARCH)
+ FastFlush(vaddr);
+#else
+ #warning "Unsupported CPU type: Unable to force cache flushes."
+#endif
+ }
+
+ // Fast flush, for use in performance critical code.
+ // This is bound at compile time, and will not pick up
+ // any runtime machine configuration info. Sync's any
+ // transactions for ordering FastFlushHints.
+ inline static void FastFlushSync() {
+#ifdef STRESSAPPTEST_CPU_PPC
+ asm volatile("sync");
+#elif defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
+ // Put mfence before and after clflush to make sure:
+ // 1. The write before the clflush is committed to memory bus;
+ // 2. The read after the clflush is hitting the memory bus.
+ //
+ // From Intel manual:
+ // CLFLUSH is only ordered by the MFENCE instruction. It is not guaranteed
+ // to be ordered by any other fencing, serializing or other CLFLUSH
+ // instruction. For example, software can use an MFENCE instruction to
+ // insure that previous stores are included in the write-back.
+ _mm_mfence();
+#elif defined(STRESSAPPTEST_CPU_MIPS) || defined(STRESSAPPTEST_CPU_ARMV7A) || \
+ defined(STRESSAPPTEST_CPU_AARCH64) || defined(STRESSAPPTEST_CPU_LOONGARCH)
+ // This is a NOP, FastFlushHint() always does a full flush, so there's
+ // nothing to do for FastFlushSync().
+#else
+ #warning "Unsupported CPU type: Unable to force cache flushes."
+#endif
+ }
+
+ // Get time in cpu timer ticks. Useful for matching MCEs with software
+ // actions.
+ inline static uint64 GetTimestamp(void) {
+ uint64 tsc;
+#ifdef STRESSAPPTEST_CPU_PPC
+ uint32 tbl, tbu, temp;
+ __asm __volatile(
+ "1:\n"
+ "mftbu %2\n"
+ "mftb %0\n"
+ "mftbu %1\n"
+ "cmpw %2,%1\n"
+ "bne 1b\n"
+ : "=r"(tbl), "=r"(tbu), "=r"(temp)
+ :
+ : "cc");
+
+ tsc = (static_cast<uint64>(tbu) << 32) | static_cast<uint64>(tbl);
+#elif defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
+ tsc = __rdtsc();
+#elif defined(STRESSAPPTEST_CPU_MIPS)
+ __asm __volatile("rdhwr %0, $2\n" : "=r" (tsc));
+#elif defined(STRESSAPPTEST_CPU_ARMV7A)
+ #warning "Unsupported CPU type ARMV7A: your timer may not function correctly"
+ tsc = 0;
+#elif defined(STRESSAPPTEST_CPU_AARCH64)
+ __asm __volatile("mrs %0, CNTVCT_EL0" : "=r" (tsc) : : );
+#elif defined(STRESSAPPTEST_CPU_LOONGARCH)
+#if defined(__loongarch64)
+ __asm __volatile("rdtime.d %0, $r0\n" : "=r" (tsc));
+#else
+ uint64 ltsc, htsc;
+ __asm __volatile("rdtimel.w %0, $r0\n" : "=r" (ltsc));
+ __asm __volatile("rdtimeh.w %0, $r0\n" : "=r" (htsc));
+ tsc = ltsc | (htsc << 32);
+#endif
+#else
+ #warning "Unsupported CPU type: your timer may not function correctly"
+ tsc = 0;
+#endif
+ return (tsc);
+ }
+
+ // Find the free memory on the machine.
+ virtual int64 FindFreeMemSize();
+
+ // Allocates test memory of length bytes.
+ // Subclasses must implement this.
+ // Call PepareTestMem to get a pointer.
+ virtual int64 AllocateAllMem(); // Returns length.
+ // Returns success.
+ virtual bool AllocateTestMem(int64 length, uint64 paddr_base);
+ virtual void FreeTestMem();
+
+ // Prepares the memory for use. You must call this
+ // before using test memory, and after you are done.
+ virtual void *PrepareTestMem(uint64 offset, uint64 length);
+ virtual void ReleaseTestMem(void *addr, uint64 offset, uint64 length);
+
+ // Machine type detected. Can we implement all these functions correctly?
+ // Returns true if machine type is detected and implemented.
+ virtual bool IsSupported();
+
+ // Returns 32 for 32-bit, 64 for 64-bit.
+ virtual int AddressMode();
+ // Update OsLayer state regarding cpu support for various features.
+ virtual void GetFeatures();
+
+ // Open, read, write pci cfg through /proc/bus/pci. fd is /proc/pci file.
+ virtual int PciOpen(int bus, int device, int function);
+ virtual void PciWrite(int fd, uint32 offset, uint32 value, int width);
+ virtual uint32 PciRead(int fd, uint32 offset, int width);
+
+ // Read MSRs
+ virtual bool ReadMSR(uint32 core, uint32 address, uint64 *data);
+ virtual bool WriteMSR(uint32 core, uint32 address, uint64 *data);
+
+ // Extract bits [n+len-1, n] from a 32 bit word.
+ // so GetBitField(0x0f00, 8, 4) == 0xf.
+ virtual uint32 GetBitField(uint32 val, uint32 n, uint32 len);
+
+ // Platform and CPU specific CPU-stressing function.
+ // Returns true on success, false otherwise.
+ virtual bool CpuStressWorkload();
+
+ // Causes false errors for unittesting.
+ // Setting to "true" causes errors to be injected.
+ void set_error_injection(bool errors) { error_injection_ = errors; }
+ bool error_injection() const { return error_injection_; }
+
+ // Is SAT using normal malloc'd memory, or exotic mmap'd memory.
+ bool normal_mem() const { return normal_mem_; }
+
+ // Get numa config, if available..
+ int num_nodes() const { return num_nodes_; }
+ int num_cpus() const { return num_cpus_; }
+
+ // Handle to platform-specific error diagnoser.
+ ErrorDiag *error_diagnoser_;
+
+ // Disambiguate between different "warm" memcopies.
+ virtual bool AdlerMemcpyWarm(uint64 *dstmem, uint64 *srcmem,
+ unsigned int size_in_bytes,
+ AdlerChecksum *checksum);
+ bool has_vector() const { return has_vector_; }
+
+ // Store a callback to use to print
+ // app-specific info about the last error location.
+ // This call back is called with a physical address, and the app can fill in
+ // the most recent transaction that occurred at that address.
+ typedef bool (*ErrCallback)(uint64 paddr, string *buf);
+ void set_err_log_callback(
+ ErrCallback err_log_callback) {
+ err_log_callback_ = err_log_callback;
+ }
+ ErrCallback get_err_log_callback() { return err_log_callback_; }
+
+ // Set a clock object that can be overridden for use with unit tests.
+ void SetClock(Clock *clock) {
+ if (clock_) {
+ delete clock_;
+ }
+ clock_ = clock;
+ time_initialized_ = clock_->Now();
+ }
+
+ protected:
+ void *testmem_; // Location of test memory.
+ uint64 testmemsize_; // Size of test memory.
+ int64 totalmemsize_; // Size of available memory.
+ int64 min_hugepages_bytes_; // Minimum hugepages size.
+ int64 reserve_mb_; // Minimum amount of memory to reserve in MB.
+ bool error_injection_; // Do error injection?
+ bool normal_mem_; // Memory DMA capable?
+ bool use_hugepages_; // Use hugepage shmem?
+ bool use_posix_shm_; // Use 4k page shmem?
+ bool dynamic_mapped_shmem_; // Conserve virtual address space.
+ bool mmapped_allocation_; // Was memory allocated using mmap()?
+ int shmid_; // Handle to shmem
+ vector< vector<string> > *channels_; // Memory module names per channel.
+ uint64 channel_hash_; // Mask of address bits XORed for channel.
+ int channel_width_; // Channel width in bits.
+
+ int64 regionsize_; // Size of memory "regions"
+ int regioncount_; // Number of memory "regions"
+ int num_cpus_; // Number of cpus in the system.
+ int num_nodes_; // Number of nodes in the system.
+ int num_cpus_per_node_; // Number of cpus per node in the system.
+ int address_mode_; // Are we running 32 or 64 bit?
+ bool has_vector_; // Do we have sse2/neon instructions?
+ bool has_clflush_; // Do we have clflush instructions?
+ bool use_flush_page_cache_; // Do we need to flush the page cache?
+
+
+ time_t time_initialized_; // Start time of test.
+
+ vector<cpu_set_t> cpu_sets_; // Cache for cpu masks.
+ vector<bool> cpu_sets_valid_; // If the cpu mask cache is valid.
+
+ // Get file descriptor for dev msr.
+ virtual int OpenMSR(uint32 core, uint32 address);
+
+ // Look up how many hugepages there are.
+ virtual int64 FindHugePages();
+
+ // Link to find last transaction at an error location.
+ ErrCallback err_log_callback_;
+
+ // Object to wrap the time function.
+ Clock *clock_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OsLayer);
+};
+
+// Selects and returns the proper OS and hardware interface. Does not call
+// OsLayer::Initialize() on the new object.
+OsLayer *OsLayerFactory(const std::map<std::string, std::string> &options);
+
+#endif // STRESSAPPTEST_OS_H_ NOLINT
diff --git a/external/subpack/utils/stressapptest/src/src/os_factory.cc b/external/subpack/utils/stressapptest/src/src/os_factory.cc
new file mode 100644
index 0000000..359f7ee
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/os_factory.cc
@@ -0,0 +1,40 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file generates an OS interface class consistant with the
+// current machine type. No machine type detection is currently done.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <string.h>
+
+#include <map>
+#include <string>
+
+#include "os.h"
+
+
+// Select the proper OS and hardware interface.
+OsLayer *OsLayerFactory(const std::map<std::string, std::string> &options) {
+ OsLayer *os = 0;
+ os = new OsLayer();
+
+ // Check for memory allocation failure.
+ if (!os) {
+ logprintf(0, "Process Error: Can't allocate memory\n");
+ return 0;
+ }
+ return os;
+}
diff --git a/external/subpack/utils/stressapptest/src/src/pattern.cc b/external/subpack/utils/stressapptest/src/src/pattern.cc
new file mode 100644
index 0000000..ba8f4d4
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/pattern.cc
@@ -0,0 +1,423 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// pattern.cc : library of stressful data patterns
+
+#include <sys/types.h>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "pattern.h"
+#include "sattypes.h"
+
+// Static data patterns.
+
+static unsigned int walkingOnes_data[] = {
+ 0x00000001, 0x00000002, 0x00000004, 0x00000008,
+ 0x00000010, 0x00000020, 0x00000040, 0x00000080,
+ 0x00000100, 0x00000200, 0x00000400, 0x00000800,
+ 0x00001000, 0x00002000, 0x00004000, 0x00008000,
+ 0x00010000, 0x00020000, 0x00040000, 0x00080000,
+ 0x00100000, 0x00200000, 0x00400000, 0x00800000,
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x40000000, 0x20000000, 0x10000000, 0x08000000,
+ 0x04000000, 0x02000000, 0x01000000, 0x00800000,
+ 0x00400000, 0x00200000, 0x00100000, 0x00080000,
+ 0x00040000, 0x00020000, 0x00010000, 0x00008000,
+ 0x00004000, 0x00002000, 0x00001000, 0x00000800,
+ 0x00000400, 0x00000200, 0x00000100, 0x00000080,
+ 0x00000040, 0x00000020, 0x00000010, 0x00000008,
+ 0x00000004, 0x00000002, 0x00000001, 0x00000000
+};
+static const struct PatternData walkingOnes = {
+ "walkingOnes",
+ walkingOnes_data,
+ (sizeof walkingOnes_data / sizeof walkingOnes_data[0]) - 1,
+ {1, 1, 2, 1} // Weight for choosing 32/64/128/256 bit wide of this pattern
+};
+
+static unsigned int walkingInvOnes_data[] = {
+ 0x00000001, 0xfffffffe, 0x00000002, 0xfffffffd,
+ 0x00000004, 0xfffffffb, 0x00000008, 0xfffffff7,
+ 0x00000010, 0xffffffef, 0x00000020, 0xffffffdf,
+ 0x00000040, 0xffffffbf, 0x00000080, 0xffffff7f,
+ 0x00000100, 0xfffffeff, 0x00000200, 0xfffffdff,
+ 0x00000400, 0xfffffbff, 0x00000800, 0xfffff7ff,
+ 0x00001000, 0xffffefff, 0x00002000, 0xffffdfff,
+ 0x00004000, 0xffffbfff, 0x00008000, 0xffff7fff,
+ 0x00010000, 0xfffeffff, 0x00020000, 0xfffdffff,
+ 0x00040000, 0xfffbffff, 0x00080000, 0xfff7ffff,
+ 0x00100000, 0xffefffff, 0x00200000, 0xffdfffff,
+ 0x00400000, 0xffbfffff, 0x00800000, 0xff7fffff,
+ 0x01000000, 0xfeffffff, 0x02000000, 0xfdffffff,
+ 0x04000000, 0xfbffffff, 0x08000000, 0xf7ffffff,
+ 0x10000000, 0xefffffff, 0x20000000, 0xdfffffff,
+ 0x40000000, 0xbfffffff, 0x80000000, 0x7fffffff,
+ 0x40000000, 0xbfffffff, 0x20000000, 0xdfffffff,
+ 0x10000000, 0xefffffff, 0x08000000, 0xf7ffffff,
+ 0x04000000, 0xfbffffff, 0x02000000, 0xfdffffff,
+ 0x01000000, 0xfeffffff, 0x00800000, 0xff7fffff,
+ 0x00400000, 0xffbfffff, 0x00200000, 0xffdfffff,
+ 0x00100000, 0xffefffff, 0x00080000, 0xfff7ffff,
+ 0x00040000, 0xfffbffff, 0x00020000, 0xfffdffff,
+ 0x00010000, 0xfffeffff, 0x00008000, 0xffff7fff,
+ 0x00004000, 0xffffbfff, 0x00002000, 0xffffdfff,
+ 0x00001000, 0xffffefff, 0x00000800, 0xfffff7ff,
+ 0x00000400, 0xfffffbff, 0x00000200, 0xfffffdff,
+ 0x00000100, 0xfffffeff, 0x00000080, 0xffffff7f,
+ 0x00000040, 0xffffffbf, 0x00000020, 0xffffffdf,
+ 0x00000010, 0xffffffef, 0x00000008, 0xfffffff7,
+ 0x00000004, 0xfffffffb, 0x00000002, 0xfffffffd,
+ 0x00000001, 0xfffffffe, 0x00000000, 0xffffffff
+};
+static const struct PatternData walkingInvOnes = {
+ "walkingInvOnes",
+ walkingInvOnes_data,
+ (sizeof walkingInvOnes_data / sizeof walkingInvOnes_data[0]) - 1,
+ {2, 2, 5, 5}
+};
+
+static unsigned int walkingZeros_data[] = {
+ 0xfffffffe, 0xfffffffd, 0xfffffffb, 0xfffffff7,
+ 0xffffffef, 0xffffffdf, 0xffffffbf, 0xffffff7f,
+ 0xfffffeff, 0xfffffdff, 0xfffffbff, 0xfffff7ff,
+ 0xffffefff, 0xffffdfff, 0xffffbfff, 0xffff7fff,
+ 0xfffeffff, 0xfffdffff, 0xfffbffff, 0xfff7ffff,
+ 0xffefffff, 0xffdfffff, 0xffbfffff, 0xff7fffff,
+ 0xfeffffff, 0xfdffffff, 0xfbffffff, 0xf7ffffff,
+ 0xefffffff, 0xdfffffff, 0xbfffffff, 0x7fffffff,
+ 0xbfffffff, 0xdfffffff, 0xefffffff, 0xf7ffffff,
+ 0xfbffffff, 0xfdffffff, 0xfeffffff, 0xff7fffff,
+ 0xffbfffff, 0xffdfffff, 0xffefffff, 0xfff7ffff,
+ 0xfffbffff, 0xfffdffff, 0xfffeffff, 0xffff7fff,
+ 0xffffbfff, 0xffffdfff, 0xffffefff, 0xfffff7ff,
+ 0xfffffbff, 0xfffffdff, 0xfffffeff, 0xffffff7f,
+ 0xffffffbf, 0xffffffdf, 0xffffffef, 0xfffffff7,
+ 0xfffffffb, 0xfffffffd, 0xfffffffe, 0xffffffff
+};
+static const struct PatternData walkingZeros = {
+ "walkingZeros",
+ walkingZeros_data,
+ (sizeof walkingZeros_data / sizeof walkingZeros_data[0]) - 1,
+ {1, 1, 2, 1}
+};
+
+static unsigned int OneZero_data[] = { 0x00000000, 0xffffffff};
+static const struct PatternData OneZero = {
+ "OneZero",
+ OneZero_data,
+ (sizeof OneZero_data / sizeof OneZero_data[0]) - 1,
+ {5, 5, 15, 5}
+};
+
+static unsigned int JustZero_data[] = { 0x00000000, 0x00000000};
+static const struct PatternData JustZero = {
+ "JustZero",
+ JustZero_data,
+ (sizeof JustZero_data / sizeof JustZero_data[0]) - 1,
+ {2, 0, 0, 0}
+};
+
+static unsigned int JustOne_data[] = { 0xffffffff, 0xffffffff};
+static const struct PatternData JustOne = {
+ "JustOne",
+ JustOne_data,
+ (sizeof JustOne_data / sizeof JustOne_data[0]) - 1,
+ {2, 0, 0, 0}
+};
+
+static unsigned int JustFive_data[] = { 0x55555555, 0x55555555};
+static const struct PatternData JustFive = {
+ "JustFive",
+ JustFive_data,
+ (sizeof JustFive_data / sizeof JustFive_data[0]) - 1,
+ {2, 0, 0, 0}
+};
+
+static unsigned int JustA_data[] = { 0xaaaaaaaa, 0xaaaaaaaa};
+static const struct PatternData JustA = {
+ "JustA",
+ JustA_data,
+ (sizeof JustA_data / sizeof JustA_data[0]) - 1,
+ {2, 0, 0, 0}
+};
+
+static unsigned int FiveA_data[] = { 0x55555555, 0xaaaaaaaa};
+static const struct PatternData FiveA = {
+ "FiveA",
+ FiveA_data,
+ (sizeof FiveA_data / sizeof FiveA_data[0]) - 1,
+ {1, 1, 1, 1}
+};
+
+static unsigned int FiveA8_data[] = {
+ 0x5aa5a55a, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a
+};
+static const struct PatternData FiveA8 = {
+ "FiveA8",
+ FiveA8_data,
+ (sizeof FiveA8_data / sizeof FiveA8_data[0]) - 1,
+ {1, 1, 1, 1}
+};
+
+static unsigned int Long8b10b_data[] = { 0x16161616, 0x16161616 };
+static const struct PatternData Long8b10b = {
+ "Long8b10b",
+ Long8b10b_data,
+ (sizeof Long8b10b_data / sizeof Long8b10b_data[0]) - 1,
+ {2, 0, 0, 0}
+};
+
+static unsigned int Short8b10b_data[] = { 0xb5b5b5b5, 0xb5b5b5b5 };
+static const struct PatternData Short8b10b = {
+ "Short8b10b",
+ Short8b10b_data,
+ (sizeof Short8b10b_data / sizeof Short8b10b_data[0]) - 1,
+ {2, 0, 0, 0}
+};
+
+static unsigned int Checker8b10b_data[] = { 0xb5b5b5b5, 0x4a4a4a4a };
+static const struct PatternData Checker8b10b = {
+ "Checker8b10b",
+ Checker8b10b_data,
+ (sizeof Checker8b10b_data / sizeof Checker8b10b_data[0]) - 1,
+ {1, 0, 0, 1}
+};
+
+static unsigned int Five7_data[] = { 0x55555557, 0x55575555 };
+static const struct PatternData Five7 = {
+ "Five7",
+ Five7_data,
+ (sizeof Five7_data / sizeof Five7_data[0]) - 1,
+ {0, 2, 0, 0}
+};
+
+static unsigned int Zero2fd_data[] = { 0x00020002, 0xfffdfffd };
+static const struct PatternData Zero2fd = {
+ "Zero2fd",
+ Zero2fd_data,
+ (sizeof Zero2fd_data / sizeof Zero2fd_data[0]) - 1,
+ {0, 2, 0, 0}
+};
+
+// Extern array of useable patterns.
+static const struct PatternData pattern_array[] = {
+ walkingOnes,
+ walkingInvOnes,
+ walkingZeros,
+ OneZero,
+ JustZero,
+ JustOne,
+ JustFive,
+ JustA,
+ FiveA,
+ FiveA8,
+ Long8b10b,
+ Short8b10b,
+ Checker8b10b,
+ Five7,
+ Zero2fd,
+};
+static const int pattern_array_size =
+ sizeof pattern_array / sizeof pattern_array[0];
+
+Pattern::Pattern() {
+ crc_ = NULL;
+}
+
+Pattern::~Pattern() {
+ if (crc_ != NULL) {
+ delete crc_;
+ }
+}
+
+// Calculate CRC for this pattern. This must match
+// the CRC calculation in worker.cc.
+int Pattern::CalculateCrc() {
+ // TODO(johnhuang):
+ // Consider refactoring to the form:
+ // while (i < count) AdlerInc(uint64, uint64, AdlerChecksum*)
+ uint64 a1 = 1;
+ uint64 a2 = 1;
+ uint64 b1 = 0;
+ uint64 b2 = 0;
+
+ // checksum is calculated using only the first 4096 bytes of data.
+ int i = 0;
+ int blocksize = 4096;
+ int count = blocksize / sizeof i;
+ while (i < count) {
+ a1 += pattern(i);
+ b1 += a1;
+ i++;
+ a1 += pattern(i);
+ b1 += a1;
+ i++;
+
+ a2 += pattern(i);
+ b2 += a2;
+ i++;
+ a2 += pattern(i);
+ b2 += a2;
+ i++;
+ }
+ if (crc_ != NULL) {
+ delete crc_;
+ }
+ crc_ = new AdlerChecksum();
+ crc_->Set(a1, a2, b1, b2);
+ return 0;
+}
+
+// Initialize pattern's CRC.
+int Pattern::Initialize(const struct PatternData &pattern_init,
+ int buswidth,
+ bool invert,
+ int weight) {
+ int result = 1;
+
+ pattern_ = &pattern_init;
+ busshift_ = 2;
+ inverse_ = invert;
+ weight_ = weight;
+
+ name_.clear();
+ name_.append(pattern_->name);
+
+ if (invert)
+ name_.append("~");
+
+ if (buswidth == 32) {
+ name_.append("32");
+ busshift_ = 0;
+ } else if (buswidth == 64) {
+ name_.append("64");
+ busshift_ = 1;
+ } else if (buswidth == 128) {
+ name_.append("128");
+ busshift_ = 2;
+ } else if (buswidth == 256) {
+ name_.append("256");
+ busshift_ = 3;
+ } else {
+ logprintf(0, "Process Error: Confused by bus width %d\n",
+ buswidth);
+ name_.append("Broken");
+ result = 0;
+ }
+
+ CalculateCrc();
+
+ return result;
+}
+
+
+PatternList::PatternList() {
+ size_= 0;
+ initialized_ = 0;
+}
+
+PatternList::~PatternList() {
+ if (initialized_) {
+ Destroy();
+ }
+}
+
+// Fill in the class with references to the static data patterns
+int PatternList::Initialize() {
+ int patterncount = 0;
+ int weightcount = 0;
+
+ patterns_.resize(pattern_array_size * 8);
+ for (int i = 0; i < pattern_array_size; i++) {
+ // Non inverted.
+ weightcount += pattern_array[i].weight[0];
+ patterns_[patterncount++].Initialize(pattern_array[i], 32, false,
+ pattern_array[i].weight[0]);
+ weightcount += pattern_array[i].weight[1];
+ patterns_[patterncount++].Initialize(pattern_array[i], 64, false,
+ pattern_array[i].weight[1]);
+ weightcount += pattern_array[i].weight[2];
+ patterns_[patterncount++].Initialize(pattern_array[i], 128, false,
+ pattern_array[i].weight[2]);
+ weightcount += pattern_array[i].weight[3];
+ patterns_[patterncount++].Initialize(pattern_array[i], 256, false,
+ pattern_array[i].weight[3]);
+
+ // Inverted.
+ weightcount += pattern_array[i].weight[0];
+ patterns_[patterncount++].Initialize(pattern_array[i], 32, true,
+ pattern_array[i].weight[0]);
+ weightcount += pattern_array[i].weight[1];
+ patterns_[patterncount++].Initialize(pattern_array[i], 64, true,
+ pattern_array[i].weight[1]);
+ weightcount += pattern_array[i].weight[2];
+ patterns_[patterncount++].Initialize(pattern_array[i], 128, true,
+ pattern_array[i].weight[2]);
+ weightcount += pattern_array[i].weight[3];
+ patterns_[patterncount++].Initialize(pattern_array[i], 256, true,
+ pattern_array[i].weight[3]);
+ }
+ size_ = patterncount;
+ weightcount_ = weightcount;
+ initialized_ = 1;
+
+ logprintf(12, "Log: initialized %d data patterns\n", size_);
+
+ return 1;
+}
+
+// Free the stuff.
+int PatternList::Destroy() {
+ if (!initialized_)
+ return 0;
+
+ patterns_.clear();
+ size_ = 0;
+ initialized_ = 0;
+
+ return 1;
+}
+
+// Return pattern numbered "i"
+Pattern *PatternList::GetPattern(int i) {
+ if (static_cast<unsigned int>(i) < size_) {
+ return &patterns_[i];
+ }
+
+ logprintf(0, "Process Error: Out of bounds pattern access\n");
+ return 0;
+}
+
+// Return a randomly selected pattern.
+Pattern *PatternList::GetRandomPattern() {
+ int target = random();
+ unsigned int i = 0;
+ target = (target % weightcount_) + 1;
+
+ do {
+ target -= patterns_[i].weight();
+ if (target <= 0)
+ break;
+ i++;
+ } while (i < size_);
+
+ if (i < size_) {
+ return &patterns_[i];
+ }
+
+ logprintf(0, "Process Error: Out of bounds pattern access\n");
+ return 0;
+}
diff --git a/external/subpack/utils/stressapptest/src/src/pattern.h b/external/subpack/utils/stressapptest/src/src/pattern.h
new file mode 100644
index 0000000..181f839
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/pattern.h
@@ -0,0 +1,124 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// pattern.h : global pattern references and initialization
+
+// This file implements easy access to statically declared
+// data patterns.
+
+#ifndef STRESSAPPTEST_PATTERN_H_
+#define STRESSAPPTEST_PATTERN_H_
+
+#include <vector>
+#include <string>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "adler32memcpy.h"
+#include "sattypes.h"
+
+// 2 = 128 bit bus, 1 = 64 bit bus, 0 = 32 bit bus
+const int kBusShift = 2;
+
+// Pattern and CRC data structure
+struct PatternData {
+ const char *name; // Name of this pattern.
+ unsigned int *pat; // Data array.
+ unsigned int mask; // Size - 1. data[index & mask] is always valid.
+ unsigned char weight[4]; // Weighted frequency of this pattern.
+ // Each pattern has 32,64,128,256 width versions.
+ // All weights are added up, a random number is
+ // chosen between 0-sum(weights), and the
+ // appropriate pattern is chosen. Thus a weight of
+ // 1 is rare, a weight of 10 is 2x as likely to be
+ // chosen as a weight of 5.
+};
+
+// Data structure to access data patterns.
+class Pattern {
+ public:
+ Pattern();
+ ~Pattern();
+ // Fill pattern data and calculate CRC.
+ int Initialize(const struct PatternData &pattern_init,
+ int buswidth,
+ bool invert,
+ int weight);
+
+ // Access data members.
+ // "busshift_" allows for repeating each pattern word 1, 2, 4, etc. times.
+ // in order to create patterns of different width.
+ unsigned int pattern(unsigned int offset) {
+ unsigned int data = pattern_->pat[(offset >> busshift_) & pattern_->mask];
+ if (inverse_)
+ data = ~data;
+ return data;
+ }
+ const AdlerChecksum *crc() {return crc_;}
+ unsigned int mask() {return pattern_->mask;}
+ unsigned int weight() {return weight_;}
+ const char *name() {return name_.c_str();}
+
+ private:
+ int CalculateCrc();
+ const struct PatternData *pattern_;
+ int busshift_; // Target data bus width.
+ bool inverse_; // Invert the data from the original pattern.
+ AdlerChecksum *crc_; // CRC of this pattern.
+ string name_; // The human readable pattern name.
+ int weight_; // This is the likelihood that this
+ // pattern will be chosen.
+ // We want to copy this!
+ // DISALLOW_COPY_AND_ASSIGN(Pattern);
+};
+
+// Object used to access global pattern list.
+class PatternList {
+ public:
+ PatternList();
+ ~PatternList();
+ // Initialize pointers to global data patterns, and calculate CRC.
+ int Initialize();
+ int Destroy();
+
+ // Return the pattern designated by index i.
+ Pattern *GetPattern(int i);
+ // Return a random pattern according to the specified weighted probability.
+ Pattern *GetRandomPattern();
+ // Return the number of patterns available.
+ int Size() {return size_;}
+
+ private:
+ vector<class Pattern> patterns_;
+ int weightcount_; // Total count of pattern weights.
+ unsigned int size_;
+ int initialized_;
+ DISALLOW_COPY_AND_ASSIGN(PatternList);
+};
+
+// CrcIncrement allows an abstracted way to add a 32bit
+// value into a running CRC. This function should be fast, and
+// generate meaningful CRCs for the types of data patterns that
+// we are using here.
+// This CRC formula may not be optimal, but it does work.
+// It may be improved in the future.
+static inline uint32 CrcIncrement(uint32 crc, uint32 expected, int index) {
+ uint32 addition = (expected ^ index);
+ uint32 carry = (addition & crc) >> 31;
+
+ return crc + addition + carry;
+}
+
+
+#endif // STRESSAPPTEST_PATTERN_H_
diff --git a/external/subpack/utils/stressapptest/src/src/queue.cc b/external/subpack/utils/stressapptest/src/src/queue.cc
new file mode 100644
index 0000000..d735e68
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/queue.cc
@@ -0,0 +1,118 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// queue.cc : simple thread safe queue implementation
+
+#include <stdlib.h>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "queue.h"
+#include "sattypes.h"
+
+// Page entry queue implementation follows.
+// Push inserts pages, pop returns a random entry.
+
+
+PageEntryQueue::PageEntryQueue(uint64 queuesize) {
+ // There must always be one empty queue location,
+ // since in == out => empty.
+ q_size_ = queuesize + 1;
+ pages_ = new struct page_entry[q_size_];
+ nextin_ = 0;
+ nextout_ = 0;
+ popped_ = 0;
+ pushed_ = 0;
+ pthread_mutex_init(&q_mutex_, NULL);
+}
+PageEntryQueue::~PageEntryQueue() {
+ delete[] pages_;
+ pthread_mutex_destroy(&q_mutex_);
+}
+
+// Add a page into this queue.
+int PageEntryQueue::Push(struct page_entry *pe) {
+ int result = 0;
+ int64 nextnextin;
+
+ if (!pe)
+ return 0;
+
+ pthread_mutex_lock(&q_mutex_);
+ nextnextin = (nextin_ + 1) % q_size_;
+
+ if (nextnextin != nextout_) {
+ pages_[nextin_] = *pe;
+
+ nextin_ = nextnextin;
+ result = 1;
+
+ pushed_++;
+ }
+
+ pthread_mutex_unlock(&q_mutex_);
+
+ return result;
+}
+
+// Retrieve a random page from this queue.
+int PageEntryQueue::PopRandom(struct page_entry *pe) {
+ int result = 0;
+ int64 lastin;
+ int64 entries;
+ int64 newindex;
+ struct page_entry tmp;
+
+ if (!pe)
+ return 0;
+
+ // TODO(nsanders): we should improve random to get 64 bit randoms, and make
+ // it more thread friendly.
+ uint64 rand = random();
+
+ int retval = pthread_mutex_lock(&q_mutex_);
+ if (retval)
+ logprintf(0, "Process Error: pthreads mutex failure %d\n", retval);
+
+
+ if (nextin_ != nextout_) {
+ // Randomized fetch.
+ // Swap random entry with next out.
+ {
+ lastin = (nextin_ - 1 + q_size_) % q_size_;
+ entries = (lastin - nextout_ + q_size_) % q_size_;
+
+ newindex = nextout_;
+ if (entries)
+ newindex = ((rand % entries) + nextout_) % q_size_;
+
+ // Swap the pages.
+ tmp = pages_[nextout_];
+ pages_[nextout_] = pages_[newindex];
+ pages_[newindex] = tmp;
+ }
+
+ // Return next out page.
+ *pe = pages_[nextout_];
+
+ nextout_ = (nextout_ + 1) % q_size_;
+ result = 1;
+
+ popped_++;
+ }
+
+ pthread_mutex_unlock(&q_mutex_);
+
+ return result;
+}
diff --git a/external/subpack/utils/stressapptest/src/src/queue.h b/external/subpack/utils/stressapptest/src/src/queue.h
new file mode 100644
index 0000000..d1920a5
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/queue.h
@@ -0,0 +1,86 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// queue.h : simple queue api
+
+// This is an interface to a simple thread safe queue,
+// used to hold data blocks and patterns.
+// The order in which the blocks are returned is random.
+
+#ifndef STRESSAPPTEST_QUEUE_H_ // NOLINT
+#define STRESSAPPTEST_QUEUE_H_
+
+#include <sys/types.h>
+#include <pthread.h>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "sattypes.h" // NOLINT
+#include "pattern.h" // NOLINT
+
+// Tag indicating no preference.
+static const int kDontCareTag = -1;
+// Tag indicating no preference.
+static const int kInvalidTag = 0xf001;
+
+
+// This describes a block of memory, and the expected fill pattern.
+struct page_entry {
+ uint64 offset;
+ void *addr;
+ uint64 paddr;
+ class Pattern *pattern;
+ int32 tag; // These are tags for use in NUMA affinity or other uses.
+ uint32 touch; // Counter of the number of reads from this page.
+ uint64 ts; // Timestamp of the last read from this page.
+ uint32 lastcpu; // Last CPU to write this page.
+ class Pattern *lastpattern; // Expected Pattern at last read.
+};
+
+static inline void init_pe(struct page_entry *pe) {
+ pe->offset = 0;
+ pe->addr = NULL;
+ pe->pattern = NULL;
+ pe->tag = kInvalidTag;
+ pe->touch = 0;
+ pe->ts = 0;
+ pe->lastcpu = 0;
+}
+
+// This is a threadsafe randomized queue of pages for
+// worker threads to use.
+class PageEntryQueue {
+ public:
+ explicit PageEntryQueue(uint64 queuesize);
+ ~PageEntryQueue();
+
+ // Push a page onto the list.
+ int Push(struct page_entry *pe);
+ // Pop a random page off of the list.
+ int PopRandom(struct page_entry *pe);
+
+ private:
+ struct page_entry *pages_; // Where the pages are held.
+ int64 nextin_;
+ int64 nextout_;
+ int64 q_size_; // Size of the queue.
+ int64 pushed_; // Number of pages pushed, total.
+ int64 popped_; // Number of pages popped, total.
+ pthread_mutex_t q_mutex_;
+
+ DISALLOW_COPY_AND_ASSIGN(PageEntryQueue);
+};
+
+
+#endif // MILES_TESTS_SAT_QUEUE_H_ NOLINT
diff --git a/external/subpack/utils/stressapptest/src/src/sat.cc b/external/subpack/utils/stressapptest/src/src/sat.cc
new file mode 100644
index 0000000..d15de74
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/sat.cc
@@ -0,0 +1,2098 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// sat.cc : a stress test for stressful testing
+
+// stressapptest (or SAT, from Stressful Application Test) is a test
+// designed to stress the system, as well as provide a comprehensive
+// memory interface test.
+
+// stressapptest can be run using memory only, or using many system components.
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/stat.h>
+#include <sys/times.h>
+
+// #define __USE_GNU
+// #define __USE_LARGEFILE64
+#include <fcntl.h>
+
+#include <list>
+#include <string>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "disk_blocks.h"
+#include "logger.h"
+#include "os.h"
+#include "sat.h"
+#include "sattypes.h"
+#include "worker.h"
+
+// stressapptest versioning here.
+#ifndef PACKAGE_VERSION
+static const char* kVersion = "1.0.0";
+#else
+static const char* kVersion = PACKAGE_VERSION;
+#endif
+
+// Global stressapptest reference, for use by signal handler.
+// This makes Sat objects not safe for multiple instances.
+namespace {
+ Sat *g_sat = NULL;
+
+ // Signal handler for catching break or kill.
+ //
+ // This must be installed after g_sat is assigned and while there is a single
+ // thread.
+ //
+ // This must be uninstalled while there is only a single thread, and of course
+ // before g_sat is cleared or deleted.
+ void SatHandleBreak(int signal) {
+ g_sat->Break();
+ }
+}
+
+// Opens the logfile for writing if necessary
+bool Sat::InitializeLogfile() {
+ // Open logfile.
+ if (use_logfile_) {
+ logfile_ = open(logfilename_,
+#if defined(O_DSYNC)
+ O_DSYNC |
+#elif defined(O_SYNC)
+ O_SYNC |
+#elif defined(O_FSYNC)
+ O_FSYNC |
+#endif
+ O_WRONLY | O_CREAT,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (logfile_ < 0) {
+ printf("Fatal Error: cannot open file %s for logging\n",
+ logfilename_);
+ bad_status();
+ return false;
+ }
+ // We seek to the end once instead of opening in append mode because no
+ // other processes should be writing to it while this one exists.
+ if (lseek(logfile_, 0, SEEK_END) == -1) {
+ printf("Fatal Error: cannot seek to end of logfile (%s)\n",
+ logfilename_);
+ bad_status();
+ return false;
+ }
+ Logger::GlobalLogger()->SetLogFd(logfile_);
+ }
+ return true;
+}
+
+// Check that the environment is known and safe to run on.
+// Return 1 if good, 0 if unsuppported.
+bool Sat::CheckEnvironment() {
+ // Check that this is not a debug build. Debug builds lack
+ // enough performance to stress the system.
+#if !defined NDEBUG
+ if (run_on_anything_) {
+ logprintf(1, "Log: Running DEBUG version of SAT, "
+ "with significantly reduced coverage.\n");
+ } else {
+ logprintf(0, "Process Error: Running DEBUG version of SAT, "
+ "with significantly reduced coverage.\n");
+ logprintf(0, "Log: Command line option '-A' bypasses this error.\n");
+ bad_status();
+ return false;
+ }
+#elif !defined CHECKOPTS
+ #error Build system regression - COPTS disregarded.
+#endif
+
+ // Check if the cpu frequency test is enabled and able to run.
+ if (cpu_freq_test_) {
+ if (!CpuFreqThread::CanRun()) {
+ logprintf(0, "Process Error: This platform does not support this "
+ "test.\n");
+ bad_status();
+ return false;
+ } else if (cpu_freq_threshold_ <= 0) {
+ logprintf(0, "Process Error: The cpu frequency test requires "
+ "--cpu_freq_threshold set to a value > 0\n");
+ bad_status();
+ return false;
+ } else if (cpu_freq_round_ < 0) {
+ logprintf(0, "Process Error: The --cpu_freq_round option must be greater"
+ " than or equal to zero. A value of zero means no rounding.\n");
+ bad_status();
+ return false;
+ }
+ }
+
+ // Use all CPUs if nothing is specified.
+ if (memory_threads_ == -1) {
+ memory_threads_ = os_->num_cpus();
+ logprintf(7, "Log: Defaulting to %d copy threads\n", memory_threads_);
+ }
+
+ // Use all memory if no size is specified.
+ if (size_mb_ == 0)
+ size_mb_ = os_->FindFreeMemSize() / kMegabyte;
+ size_ = static_cast<int64>(size_mb_) * kMegabyte;
+
+ // Autodetect file locations.
+ if (findfiles_ && (file_threads_ == 0)) {
+ // Get a space separated sting of disk locations.
+ list<string> locations = os_->FindFileDevices();
+
+ // Extract each one.
+ while (!locations.empty()) {
+ // Copy and remove the disk name.
+ string disk = locations.back();
+ locations.pop_back();
+
+ logprintf(12, "Log: disk at %s\n", disk.c_str());
+ file_threads_++;
+ filename_.push_back(disk + "/sat_disk.a");
+ file_threads_++;
+ filename_.push_back(disk + "/sat_disk.b");
+ }
+ }
+
+ // We'd better have some memory by this point.
+ if (size_ < 1) {
+ logprintf(0, "Process Error: No memory found to test.\n");
+ bad_status();
+ return false;
+ }
+
+ if (tag_mode_ && ((file_threads_ > 0) ||
+ (disk_threads_ > 0) ||
+ (net_threads_ > 0))) {
+ logprintf(0, "Process Error: Memory tag mode incompatible "
+ "with disk/network DMA.\n");
+ bad_status();
+ return false;
+ }
+
+ // If platform is 32 bit Xeon, floor memory size to multiple of 4.
+ if (address_mode_ == 32) {
+ size_mb_ = (size_mb_ / 4) * 4;
+ size_ = size_mb_ * kMegabyte;
+ logprintf(1, "Log: Flooring memory allocation to multiple of 4: %lldMB\n",
+ size_mb_);
+ }
+
+ // Check if this system is on the whitelist for supported systems.
+ if (!os_->IsSupported()) {
+ if (run_on_anything_) {
+ logprintf(1, "Log: Unsupported system. Running with reduced coverage.\n");
+ // This is ok, continue on.
+ } else {
+ logprintf(0, "Process Error: Unsupported system, "
+ "no error reporting available\n");
+ logprintf(0, "Log: Command line option '-A' bypasses this error.\n");
+ bad_status();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Allocates memory to run the test on
+bool Sat::AllocateMemory() {
+ // Allocate our test memory.
+ bool result = os_->AllocateTestMem(size_, paddr_base_);
+ if (!result) {
+ logprintf(0, "Process Error: failed to allocate memory\n");
+ bad_status();
+ return false;
+ }
+ return true;
+}
+
+// Sets up access to data patterns
+bool Sat::InitializePatterns() {
+ // Initialize pattern data.
+ patternlist_ = new PatternList();
+ if (!patternlist_) {
+ logprintf(0, "Process Error: failed to allocate patterns\n");
+ bad_status();
+ return false;
+ }
+ if (!patternlist_->Initialize()) {
+ logprintf(0, "Process Error: failed to initialize patternlist\n");
+ bad_status();
+ return false;
+ }
+ return true;
+}
+
+// Get any valid page, no tag specified.
+bool Sat::GetValid(struct page_entry *pe) {
+ return GetValid(pe, kDontCareTag);
+}
+
+
+// Fetch and return empty and full pages into the empty and full pools.
+bool Sat::GetValid(struct page_entry *pe, int32 tag) {
+ bool result = false;
+ // Get valid page depending on implementation.
+ if (pe_q_implementation_ == SAT_FINELOCK)
+ result = finelock_q_->GetValid(pe, tag);
+ else if (pe_q_implementation_ == SAT_ONELOCK)
+ result = valid_->PopRandom(pe);
+
+ if (result) {
+ pe->addr = os_->PrepareTestMem(pe->offset, page_length_); // Map it.
+
+ // Tag this access and current pattern.
+ pe->ts = os_->GetTimestamp();
+ pe->lastpattern = pe->pattern;
+
+ return (pe->addr != 0); // Return success or failure.
+ }
+ return false;
+}
+
+bool Sat::PutValid(struct page_entry *pe) {
+ if (pe->addr != 0)
+ os_->ReleaseTestMem(pe->addr, pe->offset, page_length_); // Unmap the page.
+ pe->addr = 0;
+
+ // Put valid page depending on implementation.
+ if (pe_q_implementation_ == SAT_FINELOCK)
+ return finelock_q_->PutValid(pe);
+ else if (pe_q_implementation_ == SAT_ONELOCK)
+ return valid_->Push(pe);
+ else
+ return false;
+}
+
+// Get an empty page with any tag.
+bool Sat::GetEmpty(struct page_entry *pe) {
+ return GetEmpty(pe, kDontCareTag);
+}
+
+bool Sat::GetEmpty(struct page_entry *pe, int32 tag) {
+ bool result = false;
+ // Get empty page depending on implementation.
+ if (pe_q_implementation_ == SAT_FINELOCK)
+ result = finelock_q_->GetEmpty(pe, tag);
+ else if (pe_q_implementation_ == SAT_ONELOCK)
+ result = empty_->PopRandom(pe);
+
+ if (result) {
+ pe->addr = os_->PrepareTestMem(pe->offset, page_length_); // Map it.
+ return (pe->addr != 0); // Return success or failure.
+ }
+ return false;
+}
+
+bool Sat::PutEmpty(struct page_entry *pe) {
+ if (pe->addr != 0)
+ os_->ReleaseTestMem(pe->addr, pe->offset, page_length_); // Unmap the page.
+ pe->addr = 0;
+
+ // Put empty page depending on implementation.
+ if (pe_q_implementation_ == SAT_FINELOCK)
+ return finelock_q_->PutEmpty(pe);
+ else if (pe_q_implementation_ == SAT_ONELOCK)
+ return empty_->Push(pe);
+ else
+ return false;
+}
+
+// Set up the bitmap of physical pages in case we want to see which pages were
+// accessed under this run of SAT.
+void Sat::AddrMapInit() {
+ if (!do_page_map_)
+ return;
+ // Find about how much physical mem is in the system.
+ // TODO(nsanders): Find some way to get the max
+ // and min phys addr in the system.
+ uint64 maxsize = os_->FindFreeMemSize() * 4;
+ sat_assert(maxsize != 0);
+
+ // Make a bitmask of this many pages. Assume that the memory is relatively
+ // zero based. This is true on x86, typically.
+ // This is one bit per page.
+ uint64 arraysize = maxsize / 4096 / 8;
+ unsigned char *bitmap = new unsigned char[arraysize];
+ sat_assert(bitmap);
+
+ // Mark every page as 0, not seen.
+ memset(bitmap, 0, arraysize);
+
+ page_bitmap_size_ = maxsize;
+ page_bitmap_ = bitmap;
+}
+
+// Add the 4k pages in this block to the array of pages SAT has seen.
+void Sat::AddrMapUpdate(struct page_entry *pe) {
+ if (!do_page_map_)
+ return;
+
+ // Go through 4k page blocks.
+ uint64 arraysize = page_bitmap_size_ / 4096 / 8;
+
+ char *base = reinterpret_cast<char*>(pe->addr);
+ for (int i = 0; i < page_length_; i += 4096) {
+ uint64 paddr = os_->VirtualToPhysical(base + i);
+
+ uint32 offset = paddr / 4096 / 8;
+ unsigned char mask = 1 << ((paddr / 4096) % 8);
+
+ if (offset >= arraysize) {
+ logprintf(0, "Process Error: Physical address %#llx is "
+ "greater than expected %#llx.\n",
+ paddr, page_bitmap_size_);
+ sat_assert(0);
+ }
+ page_bitmap_[offset] |= mask;
+ }
+}
+
+// Print out the physical memory ranges that SAT has accessed.
+void Sat::AddrMapPrint() {
+ if (!do_page_map_)
+ return;
+
+ uint64 pages = page_bitmap_size_ / 4096;
+
+ uint64 last_page = 0;
+ bool valid_range = false;
+
+ logprintf(4, "Log: Printing tested physical ranges.\n");
+
+ for (uint64 i = 0; i < pages; i ++) {
+ int offset = i / 8;
+ unsigned char mask = 1 << (i % 8);
+
+ bool touched = page_bitmap_[offset] & mask;
+ if (touched && !valid_range) {
+ valid_range = true;
+ last_page = i * 4096;
+ } else if (!touched && valid_range) {
+ valid_range = false;
+ logprintf(4, "Log: %#016llx - %#016llx\n", last_page, (i * 4096) - 1);
+ }
+ }
+ logprintf(4, "Log: Done printing physical ranges.\n");
+}
+
+// Initializes page lists and fills pages with data patterns.
+bool Sat::InitializePages() {
+ int result = 1;
+ // Calculate needed page totals.
+ int64 neededpages = memory_threads_ +
+ invert_threads_ +
+ check_threads_ +
+ net_threads_ +
+ file_threads_;
+
+ // Empty-valid page ratio is adjusted depending on queue implementation.
+ // since fine-grain-locked queue keeps both valid and empty entries in the
+ // same queue and randomly traverse to find pages, the empty-valid ratio
+ // should be more even.
+ if (pe_q_implementation_ == SAT_FINELOCK)
+ freepages_ = pages_ / 5 * 2; // Mark roughly 2/5 of all pages as Empty.
+ else
+ freepages_ = (pages_ / 100) + (2 * neededpages);
+
+ if (freepages_ < neededpages) {
+ logprintf(0, "Process Error: freepages < neededpages.\n");
+ logprintf(1, "Stats: Total: %lld, Needed: %lld, Marked free: %lld\n",
+ static_cast<int64>(pages_),
+ static_cast<int64>(neededpages),
+ static_cast<int64>(freepages_));
+ bad_status();
+ return false;
+ }
+
+ if (freepages_ > pages_/2) {
+ logprintf(0, "Process Error: not enough pages for IO\n");
+ logprintf(1, "Stats: Total: %lld, Needed: %lld, Available: %lld\n",
+ static_cast<int64>(pages_),
+ static_cast<int64>(freepages_),
+ static_cast<int64>(pages_/2));
+ bad_status();
+ return false;
+ }
+ logprintf(12, "Log: Allocating pages, Total: %lld Free: %lld\n",
+ pages_,
+ freepages_);
+
+ // Initialize page locations.
+ for (int64 i = 0; i < pages_; i++) {
+ struct page_entry pe;
+ init_pe(&pe);
+ pe.offset = i * page_length_;
+ result &= PutEmpty(&pe);
+ }
+
+ if (!result) {
+ logprintf(0, "Process Error: while initializing empty_ list\n");
+ bad_status();
+ return false;
+ }
+
+ // Fill valid pages with test patterns.
+ // Use fill threads to do this.
+ WorkerStatus fill_status;
+ WorkerVector fill_vector;
+
+ logprintf(12, "Starting Fill threads: %d threads, %d pages\n",
+ fill_threads_, pages_);
+ // Initialize the fill threads.
+ for (int i = 0; i < fill_threads_; i++) {
+ FillThread *thread = new FillThread();
+ thread->InitThread(i, this, os_, patternlist_, &fill_status);
+ if (i != fill_threads_ - 1) {
+ logprintf(12, "Starting Fill Threads %d: %d pages\n",
+ i, pages_ / fill_threads_);
+ thread->SetFillPages(pages_ / fill_threads_);
+ // The last thread finishes up all the leftover pages.
+ } else {
+ logprintf(12, "Starting Fill Threads %d: %d pages\n",
+ i, pages_ - pages_ / fill_threads_ * i);
+ thread->SetFillPages(pages_ - pages_ / fill_threads_ * i);
+ }
+ fill_vector.push_back(thread);
+ }
+
+ // Spawn the fill threads.
+ fill_status.Initialize();
+ for (WorkerVector::const_iterator it = fill_vector.begin();
+ it != fill_vector.end(); ++it)
+ (*it)->SpawnThread();
+
+ // Reap the finished fill threads.
+ for (WorkerVector::const_iterator it = fill_vector.begin();
+ it != fill_vector.end(); ++it) {
+ (*it)->JoinThread();
+ if ((*it)->GetStatus() != 1) {
+ logprintf(0, "Thread %d failed with status %d at %.2f seconds\n",
+ (*it)->ThreadID(), (*it)->GetStatus(),
+ (*it)->GetRunDurationUSec() * 1.0/1000000);
+ bad_status();
+ return false;
+ }
+ delete (*it);
+ }
+ fill_vector.clear();
+ fill_status.Destroy();
+ logprintf(12, "Log: Done filling pages.\n");
+ logprintf(12, "Log: Allocating pages.\n");
+
+ AddrMapInit();
+
+ // Initialize page locations.
+ for (int64 i = 0; i < pages_; i++) {
+ struct page_entry pe;
+ // Only get valid pages with uninitialized tags here.
+ if (GetValid(&pe, kInvalidTag)) {
+ int64 paddr = os_->VirtualToPhysical(pe.addr);
+ int32 region = os_->FindRegion(paddr);
+ region_[region]++;
+ pe.paddr = paddr;
+ pe.tag = 1 << region;
+ region_mask_ |= pe.tag;
+
+ // Generate a physical region map
+ AddrMapUpdate(&pe);
+
+ // Note: this does not allocate free pages among all regions
+ // fairly. However, with large enough (thousands) random number
+ // of pages being marked free in each region, the free pages
+ // count in each region end up pretty balanced.
+ if (i < freepages_) {
+ result &= PutEmpty(&pe);
+ } else {
+ result &= PutValid(&pe);
+ }
+ } else {
+ logprintf(0, "Log: didn't tag all pages. %d - %d = %d\n",
+ pages_, i, pages_ - i);
+ return false;
+ }
+ }
+ logprintf(12, "Log: Done allocating pages.\n");
+
+ AddrMapPrint();
+
+ for (int i = 0; i < 32; i++) {
+ if (region_mask_ & (1 << i)) {
+ region_count_++;
+ logprintf(12, "Log: Region %d: %d.\n", i, region_[i]);
+ }
+ }
+ logprintf(5, "Log: Region mask: 0x%x\n", region_mask_);
+
+ return true;
+}
+
+// Print SAT version info.
+bool Sat::PrintVersion() {
+ logprintf(1, "Stats: SAT revision %s, %d bit binary\n",
+ kVersion, address_mode_);
+ logprintf(5, "Log: %s from %s\n", Timestamp(), BuildChangelist());
+
+ return true;
+}
+
+
+// Initializes the resources that SAT needs to run.
+// This needs to be called before Run(), and after ParseArgs().
+// Returns true on success, false on error, and will exit() on help message.
+bool Sat::Initialize() {
+ g_sat = this;
+
+ // Initializes sync'd log file to ensure output is saved.
+ if (!InitializeLogfile())
+ return false;
+ Logger::GlobalLogger()->SetTimestampLogging(log_timestamps_);
+ Logger::GlobalLogger()->StartThread();
+
+ logprintf(5, "Log: Commandline - %s\n", cmdline_.c_str());
+ PrintVersion();
+
+ std::map<std::string, std::string> options;
+
+ GoogleOsOptions(&options);
+
+ // Initialize OS/Hardware interface.
+ os_ = OsLayerFactory(options);
+ if (!os_) {
+ bad_status();
+ return false;
+ }
+
+ if (min_hugepages_mbytes_ > 0)
+ os_->SetMinimumHugepagesSize(min_hugepages_mbytes_ * kMegabyte);
+
+ if (reserve_mb_ > 0)
+ os_->SetReserveSize(reserve_mb_);
+
+ if (channels_.size() > 0) {
+ logprintf(6, "Log: Decoding memory: %dx%d bit channels,"
+ "%d modules per channel (x%d), decoding hash 0x%x\n",
+ channels_.size(), channel_width_, channels_[0].size(),
+ channel_width_/channels_[0].size(), channel_hash_);
+ os_->SetDramMappingParams(channel_hash_, channel_width_, &channels_);
+ }
+
+ if (!os_->Initialize()) {
+ logprintf(0, "Process Error: Failed to initialize OS layer\n");
+ bad_status();
+ delete os_;
+ return false;
+ }
+
+ // Checks that OS/Build/Platform is supported.
+ if (!CheckEnvironment())
+ return false;
+
+ if (error_injection_)
+ os_->set_error_injection(true);
+
+ // Run SAT in monitor only mode, do not continue to allocate resources.
+ if (monitor_mode_) {
+ logprintf(5, "Log: Running in monitor-only mode. "
+ "Will not allocate any memory nor run any stress test. "
+ "Only polling ECC errors.\n");
+ return true;
+ }
+
+ // Allocate the memory to test.
+ if (!AllocateMemory())
+ return false;
+
+ logprintf(5, "Stats: Starting SAT, %dM, %d seconds\n",
+ static_cast<int>(size_/kMegabyte),
+ runtime_seconds_);
+
+ if (!InitializePatterns())
+ return false;
+
+ // Initialize memory allocation.
+ pages_ = size_ / page_length_;
+
+ // Allocate page queue depending on queue implementation switch.
+ if (pe_q_implementation_ == SAT_FINELOCK) {
+ finelock_q_ = new FineLockPEQueue(pages_, page_length_);
+ if (finelock_q_ == NULL)
+ return false;
+ finelock_q_->set_os(os_);
+ os_->set_err_log_callback(finelock_q_->get_err_log_callback());
+ } else if (pe_q_implementation_ == SAT_ONELOCK) {
+ empty_ = new PageEntryQueue(pages_);
+ valid_ = new PageEntryQueue(pages_);
+ if ((empty_ == NULL) || (valid_ == NULL))
+ return false;
+ }
+
+ if (!InitializePages()) {
+ logprintf(0, "Process Error: Initialize Pages failed\n");
+ return false;
+ }
+
+ return true;
+}
+
+// Constructor and destructor.
+Sat::Sat() {
+ // Set defaults, command line might override these.
+ runtime_seconds_ = 20;
+ page_length_ = kSatPageSize;
+ disk_pages_ = kSatDiskPage;
+ pages_ = 0;
+ size_mb_ = 0;
+ size_ = size_mb_ * kMegabyte;
+ reserve_mb_ = 0;
+ min_hugepages_mbytes_ = 0;
+ freepages_ = 0;
+ paddr_base_ = 0;
+ channel_hash_ = kCacheLineSize;
+ channel_width_ = 64;
+
+ user_break_ = false;
+ verbosity_ = 8;
+ Logger::GlobalLogger()->SetVerbosity(verbosity_);
+ print_delay_ = 10;
+ strict_ = 1;
+ warm_ = 0;
+ run_on_anything_ = 0;
+ use_logfile_ = false;
+ logfile_ = 0;
+ log_timestamps_ = true;
+ // Detect 32/64 bit binary.
+ void *pvoid = 0;
+ address_mode_ = sizeof(pvoid) * 8;
+ error_injection_ = false;
+ crazy_error_injection_ = false;
+ max_errorcount_ = 0; // Zero means no early exit.
+ stop_on_error_ = false;
+ error_poll_ = true;
+ findfiles_ = false;
+
+ do_page_map_ = false;
+ page_bitmap_ = 0;
+ page_bitmap_size_ = 0;
+
+ // Cache coherency data initialization.
+ cc_test_ = false; // Flag to trigger cc threads.
+ cc_cacheline_count_ = 2; // Two datastructures of cache line size.
+ cc_cacheline_size_ = 0; // Size of a cacheline (0 for auto-detect).
+ cc_inc_count_ = 1000; // Number of times to increment the shared variable.
+ cc_cacheline_data_ = 0; // Cache Line size datastructure.
+
+ // Cpu frequency data initialization.
+ cpu_freq_test_ = false; // Flag to trigger cpu frequency thread.
+ cpu_freq_threshold_ = 0; // Threshold, in MHz, at which a cpu fails.
+ cpu_freq_round_ = 10; // Round the computed frequency to this value.
+
+ sat_assert(0 == pthread_mutex_init(&worker_lock_, NULL));
+ file_threads_ = 0;
+ net_threads_ = 0;
+ listen_threads_ = 0;
+ // Default to autodetect number of cpus, and run that many threads.
+ memory_threads_ = -1;
+ invert_threads_ = 0;
+ fill_threads_ = 8;
+ check_threads_ = 0;
+ cpu_stress_threads_ = 0;
+ disk_threads_ = 0;
+ total_threads_ = 0;
+
+ use_affinity_ = true;
+ region_mask_ = 0;
+ region_count_ = 0;
+ for (int i = 0; i < 32; i++) {
+ region_[i] = 0;
+ }
+ region_mode_ = 0;
+
+ errorcount_ = 0;
+ statuscount_ = 0;
+
+ valid_ = 0;
+ empty_ = 0;
+ finelock_q_ = 0;
+ // Default to use fine-grain lock for better performance.
+ pe_q_implementation_ = SAT_FINELOCK;
+
+ os_ = 0;
+ patternlist_ = 0;
+ logfilename_[0] = 0;
+
+ read_block_size_ = 512;
+ write_block_size_ = -1;
+ segment_size_ = -1;
+ cache_size_ = -1;
+ blocks_per_segment_ = -1;
+ read_threshold_ = -1;
+ write_threshold_ = -1;
+ non_destructive_ = 1;
+ monitor_mode_ = 0;
+ tag_mode_ = 0;
+ random_threads_ = 0;
+
+ pause_delay_ = 600;
+ pause_duration_ = 15;
+}
+
+// Destructor.
+Sat::~Sat() {
+ // We need to have called Cleanup() at this point.
+ // We should probably enforce this.
+}
+
+
+#define ARG_KVALUE(argument, variable, value) \
+ if (!strcmp(argv[i], argument)) { \
+ variable = value; \
+ continue; \
+ }
+
+#define ARG_IVALUE(argument, variable) \
+ if (!strcmp(argv[i], argument)) { \
+ i++; \
+ if (i < argc) \
+ variable = strtoull(argv[i], NULL, 0); \
+ continue; \
+ }
+
+#define ARG_SVALUE(argument, variable) \
+ if (!strcmp(argv[i], argument)) { \
+ i++; \
+ if (i < argc) \
+ snprintf(variable, sizeof(variable), "%s", argv[i]); \
+ continue; \
+ }
+
+// Configures SAT from command line arguments.
+// This will call exit() given a request for
+// self-documentation or unexpected args.
+bool Sat::ParseArgs(int argc, char **argv) {
+ int i;
+ uint64 filesize = page_length_ * disk_pages_;
+
+ // Parse each argument.
+ for (i = 1; i < argc; i++) {
+ // Switch to fall back to corase-grain-lock queue. (for benchmarking)
+ ARG_KVALUE("--coarse_grain_lock", pe_q_implementation_, SAT_ONELOCK);
+
+ // Set number of megabyte to use.
+ ARG_IVALUE("-M", size_mb_);
+
+ // Specify the amount of megabytes to be reserved for system.
+ ARG_IVALUE("--reserve_memory", reserve_mb_);
+
+ // Set minimum megabytes of hugepages to require.
+ ARG_IVALUE("-H", min_hugepages_mbytes_);
+
+ // Set number of seconds to run.
+ ARG_IVALUE("-s", runtime_seconds_);
+
+ // Set number of memory copy threads.
+ ARG_IVALUE("-m", memory_threads_);
+
+ // Set number of memory invert threads.
+ ARG_IVALUE("-i", invert_threads_);
+
+ // Set number of check-only threads.
+ ARG_IVALUE("-c", check_threads_);
+
+ // Set number of cache line size datastructures.
+ ARG_IVALUE("--cc_inc_count", cc_inc_count_);
+
+ // Set number of cache line size datastructures
+ ARG_IVALUE("--cc_line_count", cc_cacheline_count_);
+
+ // Override the detected or assumed cache line size.
+ ARG_IVALUE("--cc_line_size", cc_cacheline_size_);
+
+ // Flag set when cache coherency tests need to be run
+ ARG_KVALUE("--cc_test", cc_test_, true);
+
+ // Set when the cpu_frequency test needs to be run
+ ARG_KVALUE("--cpu_freq_test", cpu_freq_test_, true);
+
+ // Set the threshold in MHz at which the cpu frequency test will fail.
+ ARG_IVALUE("--cpu_freq_threshold", cpu_freq_threshold_);
+
+ // Set the rounding value for the cpu frequency test. The default is to
+ // round to the nearest 10s value.
+ ARG_IVALUE("--cpu_freq_round", cpu_freq_round_);
+
+ // Set number of CPU stress threads.
+ ARG_IVALUE("-C", cpu_stress_threads_);
+
+ // Set logfile name.
+ ARG_SVALUE("-l", logfilename_);
+
+ // Verbosity level.
+ ARG_IVALUE("-v", verbosity_);
+
+ // Chatty printout level.
+ ARG_IVALUE("--printsec", print_delay_);
+
+ // Turn off timestamps logging.
+ ARG_KVALUE("--no_timestamps", log_timestamps_, false);
+
+ // Set maximum number of errors to collect. Stop running after this many.
+ ARG_IVALUE("--max_errors", max_errorcount_);
+
+ // Set pattern block size.
+ ARG_IVALUE("-p", page_length_);
+
+ // Set pattern block size.
+ ARG_IVALUE("--filesize", filesize);
+
+ // NUMA options.
+ ARG_KVALUE("--no_affinity", use_affinity_, false);
+ ARG_KVALUE("--local_numa", region_mode_, kLocalNuma);
+ ARG_KVALUE("--remote_numa", region_mode_, kRemoteNuma);
+
+ // Autodetect tempfile locations.
+ ARG_KVALUE("--findfiles", findfiles_, 1);
+
+ // Inject errors to force miscompare code paths
+ ARG_KVALUE("--force_errors", error_injection_, true);
+ ARG_KVALUE("--force_errors_like_crazy", crazy_error_injection_, true);
+ if (crazy_error_injection_)
+ error_injection_ = true;
+
+ // Stop immediately on any arror, for debugging HW problems.
+ ARG_KVALUE("--stop_on_errors", stop_on_error_, 1);
+
+ // Don't use internal error polling, allow external detection.
+ ARG_KVALUE("--no_errors", error_poll_, 0);
+
+ // Never check data as you go.
+ ARG_KVALUE("-F", strict_, 0);
+
+ // Warm the cpu as you go.
+ ARG_KVALUE("-W", warm_, 1);
+
+ // Allow runnign on unknown systems with base unimplemented OsLayer
+ ARG_KVALUE("-A", run_on_anything_, 1);
+
+ // Size of read blocks for disk test.
+ ARG_IVALUE("--read-block-size", read_block_size_);
+
+ // Size of write blocks for disk test.
+ ARG_IVALUE("--write-block-size", write_block_size_);
+
+ // Size of segment for disk test.
+ ARG_IVALUE("--segment-size", segment_size_);
+
+ // Size of disk cache size for disk test.
+ ARG_IVALUE("--cache-size", cache_size_);
+
+ // Number of blocks to test per segment.
+ ARG_IVALUE("--blocks-per-segment", blocks_per_segment_);
+
+ // Maximum time a block read should take before warning.
+ ARG_IVALUE("--read-threshold", read_threshold_);
+
+ // Maximum time a block write should take before warning.
+ ARG_IVALUE("--write-threshold", write_threshold_);
+
+ // Do not write anything to disk in the disk test.
+ ARG_KVALUE("--destructive", non_destructive_, 0);
+
+ // Run SAT in monitor mode. No test load at all.
+ ARG_KVALUE("--monitor_mode", monitor_mode_, true);
+
+ // Run SAT in address mode. Tag all cachelines by virt addr.
+ ARG_KVALUE("--tag_mode", tag_mode_, true);
+
+ // Dump range map of tested pages..
+ ARG_KVALUE("--do_page_map", do_page_map_, true);
+
+ // Specify the physical address base to test.
+ ARG_IVALUE("--paddr_base", paddr_base_);
+
+ // Specify the frequency for power spikes.
+ ARG_IVALUE("--pause_delay", pause_delay_);
+
+ // Specify the duration of each pause (for power spikes).
+ ARG_IVALUE("--pause_duration", pause_duration_);
+
+ // Disk device names
+ if (!strcmp(argv[i], "-d")) {
+ i++;
+ if (i < argc) {
+ disk_threads_++;
+ diskfilename_.push_back(string(argv[i]));
+ blocktables_.push_back(new DiskBlockTable());
+ }
+ continue;
+ }
+
+ // Set number of disk random threads for each disk write thread.
+ ARG_IVALUE("--random-threads", random_threads_);
+
+ // Set a tempfile to use in a file thread.
+ if (!strcmp(argv[i], "-f")) {
+ i++;
+ if (i < argc) {
+ file_threads_++;
+ filename_.push_back(string(argv[i]));
+ }
+ continue;
+ }
+
+ // Set a hostname to use in a network thread.
+ if (!strcmp(argv[i], "-n")) {
+ i++;
+ if (i < argc) {
+ net_threads_++;
+ ipaddrs_.push_back(string(argv[i]));
+ }
+ continue;
+ }
+
+ // Run threads that listen for incoming SAT net connections.
+ ARG_KVALUE("--listen", listen_threads_, 1);
+
+ if (CheckGoogleSpecificArgs(argc, argv, &i)) {
+ continue;
+ }
+
+ ARG_IVALUE("--channel_hash", channel_hash_);
+ ARG_IVALUE("--channel_width", channel_width_);
+
+ if (!strcmp(argv[i], "--memory_channel")) {
+ i++;
+ if (i < argc) {
+ char *channel = argv[i];
+ channels_.push_back(vector<string>());
+ while (char* next = strchr(channel, ',')) {
+ channels_.back().push_back(string(channel, next - channel));
+ channel = next + 1;
+ }
+ channels_.back().push_back(string(channel));
+ }
+ continue;
+ }
+
+ // Default:
+ PrintVersion();
+ PrintHelp();
+ if (strcmp(argv[i], "-h") && strcmp(argv[i], "--help")) {
+ printf("\n Unknown argument %s\n", argv[i]);
+ bad_status();
+ exit(1);
+ }
+ // Forget it, we printed the help, just bail.
+ // We don't want to print test status, or any log parser stuff.
+ exit(0);
+ }
+
+ Logger::GlobalLogger()->SetVerbosity(verbosity_);
+
+ // Update relevant data members with parsed input.
+ // Translate MB into bytes.
+ size_ = static_cast<int64>(size_mb_) * kMegabyte;
+
+ // Set logfile flag.
+ if (strcmp(logfilename_, ""))
+ use_logfile_ = true;
+ // Checks valid page length.
+ if (page_length_ &&
+ !(page_length_ & (page_length_ - 1)) &&
+ (page_length_ > 1023)) {
+ // Prints if we have changed from default.
+ if (page_length_ != kSatPageSize)
+ logprintf(12, "Log: Updating page size to %d\n", page_length_);
+ } else {
+ // Revert to default page length.
+ logprintf(6, "Process Error: "
+ "Invalid page size %d\n", page_length_);
+ page_length_ = kSatPageSize;
+ return false;
+ }
+
+ // Set disk_pages_ if filesize or page size changed.
+ if (filesize != static_cast<uint64>(page_length_) *
+ static_cast<uint64>(disk_pages_)) {
+ disk_pages_ = filesize / page_length_;
+ if (disk_pages_ == 0)
+ disk_pages_ = 1;
+ }
+
+ // Validate memory channel parameters if supplied
+ if (channels_.size()) {
+ if (channels_.size() == 1) {
+ channel_hash_ = 0;
+ logprintf(7, "Log: "
+ "Only one memory channel...deactivating interleave decoding.\n");
+ } else if (channels_.size() > 2) {
+ logprintf(6, "Process Error: "
+ "Triple-channel mode not yet supported... sorry.\n");
+ bad_status();
+ return false;
+ }
+ for (uint i = 0; i < channels_.size(); i++)
+ if (channels_[i].size() != channels_[0].size()) {
+ logprintf(6, "Process Error: "
+ "Channels 0 and %d have a different count of dram modules.\n", i);
+ bad_status();
+ return false;
+ }
+ if (channels_[0].size() & (channels_[0].size() - 1)) {
+ logprintf(6, "Process Error: "
+ "Amount of modules per memory channel is not a power of 2.\n");
+ bad_status();
+ return false;
+ }
+ if (channel_width_ < 16
+ || channel_width_ & (channel_width_ - 1)) {
+ logprintf(6, "Process Error: "
+ "Channel width %d is invalid.\n", channel_width_);
+ bad_status();
+ return false;
+ }
+ if (channel_width_ / channels_[0].size() < 8) {
+ logprintf(6, "Process Error: Chip width x%d must be x8 or greater.\n",
+ channel_width_ / channels_[0].size());
+ bad_status();
+ return false;
+ }
+ }
+
+
+ // Print each argument.
+ for (int i = 0; i < argc; i++) {
+ if (i)
+ cmdline_ += " ";
+ cmdline_ += argv[i];
+ }
+
+ return true;
+}
+
+void Sat::PrintHelp() {
+ printf("Usage: ./sat(32|64) [options]\n"
+ " -M mbytes megabytes of ram to test\n"
+ " --reserve-memory If not using hugepages, the amount of memory to "
+ " reserve for the system\n"
+ " -H mbytes minimum megabytes of hugepages to require\n"
+ " -s seconds number of seconds to run\n"
+ " -m threads number of memory copy threads to run\n"
+ " -i threads number of memory invert threads to run\n"
+ " -C threads number of memory CPU stress threads to run\n"
+ " --findfiles find locations to do disk IO automatically\n"
+ " -d device add a direct write disk thread with block "
+ "device (or file) 'device'\n"
+ " -f filename add a disk thread with "
+ "tempfile 'filename'\n"
+ " -l logfile log output to file 'logfile'\n"
+ " --no_timestamps do not prefix timestamps to log messages\n"
+ " --max_errors n exit early after finding 'n' errors\n"
+ " -v level verbosity (0-20), default is 8\n"
+ " --printsec secs How often to print 'seconds remaining'\n"
+ " -W Use more CPU-stressful memory copy\n"
+ " -A run in degraded mode on incompatible systems\n"
+ " -p pagesize size in bytes of memory chunks\n"
+ " --filesize size size of disk IO tempfiles\n"
+ " -n ipaddr add a network thread connecting to "
+ "system at 'ipaddr'\n"
+ " --listen run a thread to listen for and respond "
+ "to network threads.\n"
+ " --no_errors run without checking for ECC or other errors\n"
+ " --force_errors inject false errors to test error handling\n"
+ " --force_errors_like_crazy inject a lot of false errors "
+ "to test error handling\n"
+ " -F don't result check each transaction\n"
+ " --stop_on_errors Stop after finding the first error.\n"
+ " --read-block-size size of block for reading (-d)\n"
+ " --write-block-size size of block for writing (-d). If not "
+ "defined, the size of block for writing will be defined as the "
+ "size of block for reading\n"
+ " --segment-size size of segments to split disk into (-d)\n"
+ " --cache-size size of disk cache (-d)\n"
+ " --blocks-per-segment number of blocks to read/write per "
+ "segment per iteration (-d)\n"
+ " --read-threshold maximum time (in us) a block read should "
+ "take (-d)\n"
+ " --write-threshold maximum time (in us) a block write "
+ "should take (-d)\n"
+ " --random-threads number of random threads for each disk "
+ "write thread (-d)\n"
+ " --destructive write/wipe disk partition (-d)\n"
+ " --monitor_mode only do ECC error polling, no stress load.\n"
+ " --cc_test do the cache coherency testing\n"
+ " --cc_inc_count number of times to increment the "
+ "cacheline's member\n"
+ " --cc_line_count number of cache line sized datastructures "
+ "to allocate for the cache coherency threads to operate\n"
+ " --cc_line_size override the auto-detected cache line size\n"
+ " --cpu_freq_test enable the cpu frequency test (requires the "
+ "--cpu_freq_threshold argument to be set)\n"
+ " --cpu_freq_threshold fail the cpu frequency test if the frequency "
+ "goes below this value (specified in MHz)\n"
+ " --cpu_freq_round round the computed frequency to this value, if set"
+ " to zero, only round to the nearest MHz\n"
+ " --paddr_base allocate memory starting from this address\n"
+ " --pause_delay delay (in seconds) between power spikes\n"
+ " --pause_duration duration (in seconds) of each pause\n"
+ " --no_affinity do not set any cpu affinity\n"
+ " --local_numa choose memory regions associated with "
+ "each CPU to be tested by that CPU\n"
+ " --remote_numa choose memory regions not associated with "
+ "each CPU to be tested by that CPU\n"
+ " --channel_hash mask of address bits XORed to determine channel. "
+ "Mask 0x40 interleaves cachelines between channels\n"
+ " --channel_width bits width in bits of each memory channel\n"
+ " --memory_channel u1,u2 defines a comma-separated list of names "
+ "for dram packages in a memory channel. Use multiple times to "
+ "define multiple channels.\n");
+}
+
+bool Sat::CheckGoogleSpecificArgs(int argc, char **argv, int *i) {
+ // Do nothing, no google-specific argument on public stressapptest
+ return false;
+}
+
+void Sat::GoogleOsOptions(std::map<std::string, std::string> *options) {
+ // Do nothing, no OS-specific argument on public stressapptest
+}
+
+// Launch the SAT task threads. Returns 0 on error.
+void Sat::InitializeThreads() {
+ // Memory copy threads.
+ AcquireWorkerLock();
+
+ logprintf(12, "Log: Starting worker threads\n");
+ WorkerVector *memory_vector = new WorkerVector();
+
+ // Error polling thread.
+ // This may detect ECC corrected errors, disk problems, or
+ // any other errors normally hidden from userspace.
+ WorkerVector *error_vector = new WorkerVector();
+ if (error_poll_) {
+ ErrorPollThread *thread = new ErrorPollThread();
+ thread->InitThread(total_threads_++, this, os_, patternlist_,
+ &continuous_status_);
+
+ error_vector->insert(error_vector->end(), thread);
+ } else {
+ logprintf(5, "Log: Skipping error poll thread due to --no_errors flag\n");
+ }
+ workers_map_.insert(make_pair(kErrorType, error_vector));
+
+ // Only start error poll threads for monitor-mode SAT,
+ // skip all other types of worker threads.
+ if (monitor_mode_) {
+ ReleaseWorkerLock();
+ return;
+ }
+
+ for (int i = 0; i < memory_threads_; i++) {
+ CopyThread *thread = new CopyThread();
+ thread->InitThread(total_threads_++, this, os_, patternlist_,
+ &power_spike_status_);
+
+ if ((region_count_ > 1) && (region_mode_)) {
+ int32 region = region_find(i % region_count_);
+ cpu_set_t *cpuset = os_->FindCoreMask(region);
+ sat_assert(cpuset);
+ if (region_mode_ == kLocalNuma) {
+ // Choose regions associated with this CPU.
+ thread->set_cpu_mask(cpuset);
+ thread->set_tag(1 << region);
+ } else if (region_mode_ == kRemoteNuma) {
+ // Choose regions not associated with this CPU..
+ thread->set_cpu_mask(cpuset);
+ thread->set_tag(region_mask_ & ~(1 << region));
+ }
+ } else {
+ cpu_set_t available_cpus;
+ thread->AvailableCpus(&available_cpus);
+ int cores = cpuset_count(&available_cpus);
+ // Don't restrict thread location if we have more than one
+ // thread per core. Not so good for performance.
+ if (cpu_stress_threads_ + memory_threads_ <= cores) {
+ // Place a thread on alternating cores first.
+ // This assures interleaved core use with no overlap.
+ int nthcore = i;
+ int nthbit = (((2 * nthcore) % cores) +
+ (((2 * nthcore) / cores) % 2)) % cores;
+ cpu_set_t all_cores;
+ cpuset_set_ab(&all_cores, 0, cores);
+ if (!cpuset_isequal(&available_cpus, &all_cores)) {
+ // We are assuming the bits are contiguous.
+ // Complain if this is not so.
+ logprintf(0, "Log: cores = %s, expected %s\n",
+ cpuset_format(&available_cpus).c_str(),
+ cpuset_format(&all_cores).c_str());
+ }
+
+ // Set thread affinity.
+ thread->set_cpu_mask_to_cpu(nthbit);
+ }
+ }
+ memory_vector->insert(memory_vector->end(), thread);
+ }
+ workers_map_.insert(make_pair(kMemoryType, memory_vector));
+
+ // File IO threads.
+ WorkerVector *fileio_vector = new WorkerVector();
+ for (int i = 0; i < file_threads_; i++) {
+ FileThread *thread = new FileThread();
+ thread->InitThread(total_threads_++, this, os_, patternlist_,
+ &power_spike_status_);
+ thread->SetFile(filename_[i].c_str());
+ // Set disk threads high priority. They don't take much processor time,
+ // but blocking them will delay disk IO.
+ thread->SetPriority(WorkerThread::High);
+
+ fileio_vector->insert(fileio_vector->end(), thread);
+ }
+ workers_map_.insert(make_pair(kFileIOType, fileio_vector));
+
+ // Net IO threads.
+ WorkerVector *netio_vector = new WorkerVector();
+ WorkerVector *netslave_vector = new WorkerVector();
+ if (listen_threads_ > 0) {
+ // Create a network slave thread. This listens for connections.
+ NetworkListenThread *thread = new NetworkListenThread();
+ thread->InitThread(total_threads_++, this, os_, patternlist_,
+ &continuous_status_);
+
+ netslave_vector->insert(netslave_vector->end(), thread);
+ }
+ for (int i = 0; i < net_threads_; i++) {
+ NetworkThread *thread = new NetworkThread();
+ thread->InitThread(total_threads_++, this, os_, patternlist_,
+ &continuous_status_);
+ thread->SetIP(ipaddrs_[i].c_str());
+
+ netio_vector->insert(netio_vector->end(), thread);
+ }
+ workers_map_.insert(make_pair(kNetIOType, netio_vector));
+ workers_map_.insert(make_pair(kNetSlaveType, netslave_vector));
+
+ // Result check threads.
+ WorkerVector *check_vector = new WorkerVector();
+ for (int i = 0; i < check_threads_; i++) {
+ CheckThread *thread = new CheckThread();
+ thread->InitThread(total_threads_++, this, os_, patternlist_,
+ &continuous_status_);
+
+ check_vector->insert(check_vector->end(), thread);
+ }
+ workers_map_.insert(make_pair(kCheckType, check_vector));
+
+ // Memory invert threads.
+ logprintf(12, "Log: Starting invert threads\n");
+ WorkerVector *invert_vector = new WorkerVector();
+ for (int i = 0; i < invert_threads_; i++) {
+ InvertThread *thread = new InvertThread();
+ thread->InitThread(total_threads_++, this, os_, patternlist_,
+ &continuous_status_);
+
+ invert_vector->insert(invert_vector->end(), thread);
+ }
+ workers_map_.insert(make_pair(kInvertType, invert_vector));
+
+ // Disk stress threads.
+ WorkerVector *disk_vector = new WorkerVector();
+ WorkerVector *random_vector = new WorkerVector();
+ logprintf(12, "Log: Starting disk stress threads\n");
+ for (int i = 0; i < disk_threads_; i++) {
+ // Creating write threads
+ DiskThread *thread = new DiskThread(blocktables_[i]);
+ thread->InitThread(total_threads_++, this, os_, patternlist_,
+ &power_spike_status_);
+ thread->SetDevice(diskfilename_[i].c_str());
+ if (thread->SetParameters(read_block_size_, write_block_size_,
+ segment_size_, cache_size_,
+ blocks_per_segment_,
+ read_threshold_, write_threshold_,
+ non_destructive_)) {
+ disk_vector->insert(disk_vector->end(), thread);
+ } else {
+ logprintf(12, "Log: DiskThread::SetParameters() failed\n");
+ delete thread;
+ }
+
+ for (int j = 0; j < random_threads_; j++) {
+ // Creating random threads
+ RandomDiskThread *rthread = new RandomDiskThread(blocktables_[i]);
+ rthread->InitThread(total_threads_++, this, os_, patternlist_,
+ &power_spike_status_);
+ rthread->SetDevice(diskfilename_[i].c_str());
+ if (rthread->SetParameters(read_block_size_, write_block_size_,
+ segment_size_, cache_size_,
+ blocks_per_segment_,
+ read_threshold_, write_threshold_,
+ non_destructive_)) {
+ random_vector->insert(random_vector->end(), rthread);
+ } else {
+ logprintf(12, "Log: RandomDiskThread::SetParameters() failed\n");
+ delete rthread;
+ }
+ }
+ }
+
+ workers_map_.insert(make_pair(kDiskType, disk_vector));
+ workers_map_.insert(make_pair(kRandomDiskType, random_vector));
+
+ // CPU stress threads.
+ WorkerVector *cpu_vector = new WorkerVector();
+ logprintf(12, "Log: Starting cpu stress threads\n");
+ for (int i = 0; i < cpu_stress_threads_; i++) {
+ CpuStressThread *thread = new CpuStressThread();
+ thread->InitThread(total_threads_++, this, os_, patternlist_,
+ &continuous_status_);
+
+ // Don't restrict thread location if we have more than one
+ // thread per core. Not so good for performance.
+ cpu_set_t available_cpus;
+ thread->AvailableCpus(&available_cpus);
+ int cores = cpuset_count(&available_cpus);
+ if (cpu_stress_threads_ + memory_threads_ <= cores) {
+ // Place a thread on alternating cores first.
+ // Go in reverse order for CPU stress threads. This assures interleaved
+ // core use with no overlap.
+ int nthcore = (cores - 1) - i;
+ int nthbit = (((2 * nthcore) % cores) +
+ (((2 * nthcore) / cores) % 2)) % cores;
+ cpu_set_t all_cores;
+ cpuset_set_ab(&all_cores, 0, cores);
+ if (!cpuset_isequal(&available_cpus, &all_cores)) {
+ logprintf(0, "Log: cores = %s, expected %s\n",
+ cpuset_format(&available_cpus).c_str(),
+ cpuset_format(&all_cores).c_str());
+ }
+
+ // Set thread affinity.
+ thread->set_cpu_mask_to_cpu(nthbit);
+ }
+
+ cpu_vector->insert(cpu_vector->end(), thread);
+ }
+ workers_map_.insert(make_pair(kCPUType, cpu_vector));
+
+ // CPU Cache Coherency Threads - one for each core available.
+ if (cc_test_) {
+ WorkerVector *cc_vector = new WorkerVector();
+ logprintf(12, "Log: Starting cpu cache coherency threads\n");
+
+ // Allocate the shared datastructure to be worked on by the threads.
+ cc_cacheline_data_ = reinterpret_cast<cc_cacheline_data*>(
+ malloc(sizeof(cc_cacheline_data) * cc_cacheline_count_));
+ sat_assert(cc_cacheline_data_ != NULL);
+
+ // Initialize the strucutre.
+ memset(cc_cacheline_data_, 0,
+ sizeof(cc_cacheline_data) * cc_cacheline_count_);
+
+ int num_cpus = CpuCount();
+ char *num;
+ // Calculate the number of cache lines needed just to give each core
+ // its own counter.
+ int line_size = cc_cacheline_size_;
+ if (line_size <= 0) {
+ line_size = CacheLineSize();
+ if (line_size < kCacheLineSize)
+ line_size = kCacheLineSize;
+ logprintf(12, "Log: Using %d as cache line size\n", line_size);
+ }
+ // The number of cache lines needed to hold an array of num_cpus.
+ // "num" must be the same type as cc_cacheline_data[X].num or the memory
+ // size calculations will fail.
+ int needed_lines = (sizeof(*num) * num_cpus + line_size - 1) / line_size;
+ // Allocate all the nums once so that we get a single chunk
+ // of contiguous memory.
+#ifdef HAVE_POSIX_MEMALIGN
+ int err_result = posix_memalign(
+ reinterpret_cast<void**>(&num),
+ line_size, line_size * needed_lines * cc_cacheline_count_);
+#else
+ num = reinterpret_cast<int*>(memalign(
+ line_size, line_size * needed_lines * cc_cacheline_count_));
+ int err_result = (num == 0);
+#endif
+ sat_assert(err_result == 0);
+
+ int cline;
+ for (cline = 0; cline < cc_cacheline_count_; cline++) {
+ memset(num, 0, sizeof(*num) * num_cpus);
+ cc_cacheline_data_[cline].num = num;
+ num += (line_size * needed_lines) / sizeof(*num);
+ }
+
+ int tnum;
+ for (tnum = 0; tnum < num_cpus; tnum++) {
+ CpuCacheCoherencyThread *thread =
+ new CpuCacheCoherencyThread(cc_cacheline_data_, cc_cacheline_count_,
+ tnum, num_cpus, cc_inc_count_);
+ thread->InitThread(total_threads_++, this, os_, patternlist_,
+ &continuous_status_);
+ // Pin the thread to a particular core.
+ thread->set_cpu_mask_to_cpu(tnum);
+
+ // Insert the thread into the vector.
+ cc_vector->insert(cc_vector->end(), thread);
+ }
+ workers_map_.insert(make_pair(kCCType, cc_vector));
+ }
+
+ if (cpu_freq_test_) {
+ // Create the frequency test thread.
+ logprintf(5, "Log: Running cpu frequency test: threshold set to %dMHz.\n",
+ cpu_freq_threshold_);
+ CpuFreqThread *thread = new CpuFreqThread(CpuCount(), cpu_freq_threshold_,
+ cpu_freq_round_);
+ // This thread should be paused when other threads are paused.
+ thread->InitThread(total_threads_++, this, os_, NULL,
+ &power_spike_status_);
+
+ WorkerVector *cpu_freq_vector = new WorkerVector();
+ cpu_freq_vector->insert(cpu_freq_vector->end(), thread);
+ workers_map_.insert(make_pair(kCPUFreqType, cpu_freq_vector));
+ }
+
+ ReleaseWorkerLock();
+}
+
+// Return the number of cpus actually present in the machine.
+int Sat::CpuCount() {
+ return sysconf(_SC_NPROCESSORS_CONF);
+}
+
+// Return the worst case (largest) cache line size of the various levels of
+// cache actually prsent in the machine.
+int Sat::CacheLineSize() {
+ int max_linesize=0, linesize=0;
+#ifdef _SC_LEVEL1_DCACHE_LINESIZE
+ max_linesize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
+#endif
+#ifdef _SC_LEVEL2_DCACHE_LINESIZE
+ linesize = sysconf(_SC_LEVEL2_DCACHE_LINESIZE);
+#endif
+ if (linesize > max_linesize) max_linesize = linesize;
+#ifdef _SC_LEVEL3_DCACHE_LINESIZE
+ linesize = sysconf(_SC_LEVEL3_DCACHE_LINESIZE);
+#endif
+ if (linesize > max_linesize) max_linesize = linesize;
+#ifdef _SC_LEVEL4_DCACHE_LINESIZE
+ linesize = sysconf(_SC_LEVEL4_DCACHE_LINESIZE);
+#endif
+ if (linesize > max_linesize) max_linesize = linesize;
+
+ /* return -1 as the old uclibc also returns -1 */
+ return (max_linesize ? max_linesize : -1);
+}
+
+// Notify and reap worker threads.
+void Sat::JoinThreads() {
+ logprintf(12, "Log: Joining worker threads\n");
+ power_spike_status_.StopWorkers();
+ continuous_status_.StopWorkers();
+
+ AcquireWorkerLock();
+ for (WorkerMap::const_iterator map_it = workers_map_.begin();
+ map_it != workers_map_.end(); ++map_it) {
+ for (WorkerVector::const_iterator it = map_it->second->begin();
+ it != map_it->second->end(); ++it) {
+ logprintf(12, "Log: Joining thread %d\n", (*it)->ThreadID());
+ (*it)->JoinThread();
+ }
+ }
+ ReleaseWorkerLock();
+
+ QueueStats();
+
+ // Finish up result checking.
+ // Spawn 4 check threads to minimize check time.
+ logprintf(12, "Log: Finished countdown, begin to result check\n");
+ WorkerStatus reap_check_status;
+ WorkerVector reap_check_vector;
+
+ // No need for check threads for monitor mode.
+ if (!monitor_mode_) {
+ // Initialize the check threads.
+ for (int i = 0; i < fill_threads_; i++) {
+ CheckThread *thread = new CheckThread();
+ thread->InitThread(total_threads_++, this, os_, patternlist_,
+ &reap_check_status);
+ logprintf(12, "Log: Finished countdown, begin to result check\n");
+ reap_check_vector.push_back(thread);
+ }
+ }
+
+ reap_check_status.Initialize();
+ // Check threads should be marked to stop ASAP.
+ reap_check_status.StopWorkers();
+
+ // Spawn the check threads.
+ for (WorkerVector::const_iterator it = reap_check_vector.begin();
+ it != reap_check_vector.end(); ++it) {
+ logprintf(12, "Log: Spawning thread %d\n", (*it)->ThreadID());
+ (*it)->SpawnThread();
+ }
+
+ // Join the check threads.
+ for (WorkerVector::const_iterator it = reap_check_vector.begin();
+ it != reap_check_vector.end(); ++it) {
+ logprintf(12, "Log: Joining thread %d\n", (*it)->ThreadID());
+ (*it)->JoinThread();
+ }
+
+ // Reap all children. Stopped threads should have already ended.
+ // Result checking threads will end when they have finished
+ // result checking.
+ logprintf(12, "Log: Join all outstanding threads\n");
+
+ // Find all errors.
+ errorcount_ = GetTotalErrorCount();
+
+ AcquireWorkerLock();
+ for (WorkerMap::const_iterator map_it = workers_map_.begin();
+ map_it != workers_map_.end(); ++map_it) {
+ for (WorkerVector::const_iterator it = map_it->second->begin();
+ it != map_it->second->end(); ++it) {
+ logprintf(12, "Log: Reaping thread status %d\n", (*it)->ThreadID());
+ if ((*it)->GetStatus() != 1) {
+ logprintf(0, "Process Error: Thread %d failed with status %d at "
+ "%.2f seconds\n",
+ (*it)->ThreadID(), (*it)->GetStatus(),
+ (*it)->GetRunDurationUSec()*1.0/1000000);
+ bad_status();
+ }
+ int priority = 12;
+ if ((*it)->GetErrorCount())
+ priority = 5;
+ logprintf(priority, "Log: Thread %d found %lld hardware incidents\n",
+ (*it)->ThreadID(), (*it)->GetErrorCount());
+ }
+ }
+ ReleaseWorkerLock();
+
+
+ // Add in any errors from check threads.
+ for (WorkerVector::const_iterator it = reap_check_vector.begin();
+ it != reap_check_vector.end(); ++it) {
+ logprintf(12, "Log: Reaping thread status %d\n", (*it)->ThreadID());
+ if ((*it)->GetStatus() != 1) {
+ logprintf(0, "Process Error: Thread %d failed with status %d at "
+ "%.2f seconds\n",
+ (*it)->ThreadID(), (*it)->GetStatus(),
+ (*it)->GetRunDurationUSec()*1.0/1000000);
+ bad_status();
+ }
+ errorcount_ += (*it)->GetErrorCount();
+ int priority = 12;
+ if ((*it)->GetErrorCount())
+ priority = 5;
+ logprintf(priority, "Log: Thread %d found %lld hardware incidents\n",
+ (*it)->ThreadID(), (*it)->GetErrorCount());
+ delete (*it);
+ }
+ reap_check_vector.clear();
+ reap_check_status.Destroy();
+}
+
+// Print queuing information.
+void Sat::QueueStats() {
+ finelock_q_->QueueAnalysis();
+}
+
+void Sat::AnalysisAllStats() {
+ float max_runtime_sec = 0.;
+ float total_data = 0.;
+ float total_bandwidth = 0.;
+ float thread_runtime_sec = 0.;
+
+ for (WorkerMap::const_iterator map_it = workers_map_.begin();
+ map_it != workers_map_.end(); ++map_it) {
+ for (WorkerVector::const_iterator it = map_it->second->begin();
+ it != map_it->second->end(); ++it) {
+ thread_runtime_sec = (*it)->GetRunDurationUSec()*1.0/1000000.;
+ total_data += (*it)->GetMemoryCopiedData();
+ total_data += (*it)->GetDeviceCopiedData();
+ if (thread_runtime_sec > max_runtime_sec) {
+ max_runtime_sec = thread_runtime_sec;
+ }
+ }
+ }
+
+ total_bandwidth = total_data / max_runtime_sec;
+
+ logprintf(0, "Stats: Completed: %.2fM in %.2fs %.2fMB/s, "
+ "with %d hardware incidents, %d errors\n",
+ total_data,
+ max_runtime_sec,
+ total_bandwidth,
+ errorcount_,
+ statuscount_);
+}
+
+void Sat::MemoryStats() {
+ float memcopy_data = 0.;
+ float memcopy_bandwidth = 0.;
+ WorkerMap::const_iterator mem_it = workers_map_.find(
+ static_cast<int>(kMemoryType));
+ WorkerMap::const_iterator file_it = workers_map_.find(
+ static_cast<int>(kFileIOType));
+ sat_assert(mem_it != workers_map_.end());
+ sat_assert(file_it != workers_map_.end());
+ for (WorkerVector::const_iterator it = mem_it->second->begin();
+ it != mem_it->second->end(); ++it) {
+ memcopy_data += (*it)->GetMemoryCopiedData();
+ memcopy_bandwidth += (*it)->GetMemoryBandwidth();
+ }
+ for (WorkerVector::const_iterator it = file_it->second->begin();
+ it != file_it->second->end(); ++it) {
+ memcopy_data += (*it)->GetMemoryCopiedData();
+ memcopy_bandwidth += (*it)->GetMemoryBandwidth();
+ }
+ GoogleMemoryStats(&memcopy_data, &memcopy_bandwidth);
+ logprintf(4, "Stats: Memory Copy: %.2fM at %.2fMB/s\n",
+ memcopy_data,
+ memcopy_bandwidth);
+}
+
+void Sat::GoogleMemoryStats(float *memcopy_data,
+ float *memcopy_bandwidth) {
+ // Do nothing, should be implemented by subclasses.
+}
+
+void Sat::FileStats() {
+ float file_data = 0.;
+ float file_bandwidth = 0.;
+ WorkerMap::const_iterator file_it = workers_map_.find(
+ static_cast<int>(kFileIOType));
+ sat_assert(file_it != workers_map_.end());
+ for (WorkerVector::const_iterator it = file_it->second->begin();
+ it != file_it->second->end(); ++it) {
+ file_data += (*it)->GetDeviceCopiedData();
+ file_bandwidth += (*it)->GetDeviceBandwidth();
+ }
+ logprintf(4, "Stats: File Copy: %.2fM at %.2fMB/s\n",
+ file_data,
+ file_bandwidth);
+}
+
+void Sat::CheckStats() {
+ float check_data = 0.;
+ float check_bandwidth = 0.;
+ WorkerMap::const_iterator check_it = workers_map_.find(
+ static_cast<int>(kCheckType));
+ sat_assert(check_it != workers_map_.end());
+ for (WorkerVector::const_iterator it = check_it->second->begin();
+ it != check_it->second->end(); ++it) {
+ check_data += (*it)->GetMemoryCopiedData();
+ check_bandwidth += (*it)->GetMemoryBandwidth();
+ }
+ logprintf(4, "Stats: Data Check: %.2fM at %.2fMB/s\n",
+ check_data,
+ check_bandwidth);
+}
+
+void Sat::NetStats() {
+ float net_data = 0.;
+ float net_bandwidth = 0.;
+ WorkerMap::const_iterator netio_it = workers_map_.find(
+ static_cast<int>(kNetIOType));
+ WorkerMap::const_iterator netslave_it = workers_map_.find(
+ static_cast<int>(kNetSlaveType));
+ sat_assert(netio_it != workers_map_.end());
+ sat_assert(netslave_it != workers_map_.end());
+ for (WorkerVector::const_iterator it = netio_it->second->begin();
+ it != netio_it->second->end(); ++it) {
+ net_data += (*it)->GetDeviceCopiedData();
+ net_bandwidth += (*it)->GetDeviceBandwidth();
+ }
+ for (WorkerVector::const_iterator it = netslave_it->second->begin();
+ it != netslave_it->second->end(); ++it) {
+ net_data += (*it)->GetDeviceCopiedData();
+ net_bandwidth += (*it)->GetDeviceBandwidth();
+ }
+ logprintf(4, "Stats: Net Copy: %.2fM at %.2fMB/s\n",
+ net_data,
+ net_bandwidth);
+}
+
+void Sat::InvertStats() {
+ float invert_data = 0.;
+ float invert_bandwidth = 0.;
+ WorkerMap::const_iterator invert_it = workers_map_.find(
+ static_cast<int>(kInvertType));
+ sat_assert(invert_it != workers_map_.end());
+ for (WorkerVector::const_iterator it = invert_it->second->begin();
+ it != invert_it->second->end(); ++it) {
+ invert_data += (*it)->GetMemoryCopiedData();
+ invert_bandwidth += (*it)->GetMemoryBandwidth();
+ }
+ logprintf(4, "Stats: Invert Data: %.2fM at %.2fMB/s\n",
+ invert_data,
+ invert_bandwidth);
+}
+
+void Sat::DiskStats() {
+ float disk_data = 0.;
+ float disk_bandwidth = 0.;
+ WorkerMap::const_iterator disk_it = workers_map_.find(
+ static_cast<int>(kDiskType));
+ WorkerMap::const_iterator random_it = workers_map_.find(
+ static_cast<int>(kRandomDiskType));
+ sat_assert(disk_it != workers_map_.end());
+ sat_assert(random_it != workers_map_.end());
+ for (WorkerVector::const_iterator it = disk_it->second->begin();
+ it != disk_it->second->end(); ++it) {
+ disk_data += (*it)->GetDeviceCopiedData();
+ disk_bandwidth += (*it)->GetDeviceBandwidth();
+ }
+ for (WorkerVector::const_iterator it = random_it->second->begin();
+ it != random_it->second->end(); ++it) {
+ disk_data += (*it)->GetDeviceCopiedData();
+ disk_bandwidth += (*it)->GetDeviceBandwidth();
+ }
+
+ logprintf(4, "Stats: Disk: %.2fM at %.2fMB/s\n",
+ disk_data,
+ disk_bandwidth);
+}
+
+// Process worker thread data for bandwidth information, and error results.
+// You can add more methods here just subclassing SAT.
+void Sat::RunAnalysis() {
+ AnalysisAllStats();
+ MemoryStats();
+ FileStats();
+ NetStats();
+ CheckStats();
+ InvertStats();
+ DiskStats();
+}
+
+// Get total error count, summing across all threads..
+int64 Sat::GetTotalErrorCount() {
+ int64 errors = 0;
+
+ AcquireWorkerLock();
+ for (WorkerMap::const_iterator map_it = workers_map_.begin();
+ map_it != workers_map_.end(); ++map_it) {
+ for (WorkerVector::const_iterator it = map_it->second->begin();
+ it != map_it->second->end(); ++it) {
+ errors += (*it)->GetErrorCount();
+ }
+ }
+ ReleaseWorkerLock();
+ return errors;
+}
+
+
+void Sat::SpawnThreads() {
+ logprintf(12, "Log: Initializing WorkerStatus objects\n");
+ power_spike_status_.Initialize();
+ continuous_status_.Initialize();
+ logprintf(12, "Log: Spawning worker threads\n");
+ for (WorkerMap::const_iterator map_it = workers_map_.begin();
+ map_it != workers_map_.end(); ++map_it) {
+ for (WorkerVector::const_iterator it = map_it->second->begin();
+ it != map_it->second->end(); ++it) {
+ logprintf(12, "Log: Spawning thread %d\n", (*it)->ThreadID());
+ (*it)->SpawnThread();
+ }
+ }
+}
+
+// Delete used worker thread objects.
+void Sat::DeleteThreads() {
+ logprintf(12, "Log: Deleting worker threads\n");
+ for (WorkerMap::const_iterator map_it = workers_map_.begin();
+ map_it != workers_map_.end(); ++map_it) {
+ for (WorkerVector::const_iterator it = map_it->second->begin();
+ it != map_it->second->end(); ++it) {
+ logprintf(12, "Log: Deleting thread %d\n", (*it)->ThreadID());
+ delete (*it);
+ }
+ delete map_it->second;
+ }
+ workers_map_.clear();
+ logprintf(12, "Log: Destroying WorkerStatus objects\n");
+ power_spike_status_.Destroy();
+ continuous_status_.Destroy();
+}
+
+namespace {
+// Calculates the next time an action in Sat::Run() should occur, based on a
+// schedule derived from a start point and a regular frequency.
+//
+// Using frequencies instead of intervals with their accompanying drift allows
+// users to better predict when the actions will occur throughout a run.
+//
+// Arguments:
+// frequency: seconds
+// start: unixtime
+// now: unixtime
+//
+// Returns: unixtime
+inline time_t NextOccurance(time_t frequency, time_t start, time_t now) {
+ return start + frequency + (((now - start) / frequency) * frequency);
+}
+}
+
+// Run the actual test.
+bool Sat::Run() {
+ // Install signal handlers to gracefully exit in the middle of a run.
+ //
+ // Why go through this whole rigmarole? It's the only standards-compliant
+ // (C++ and POSIX) way to handle signals in a multithreaded program.
+ // Specifically:
+ //
+ // 1) (C++) The value of a variable not of type "volatile sig_atomic_t" is
+ // unspecified upon entering a signal handler and, if modified by the
+ // handler, is unspecified after leaving the handler.
+ //
+ // 2) (POSIX) After the value of a variable is changed in one thread, another
+ // thread is only guaranteed to see the new value after both threads have
+ // acquired or released the same mutex or rwlock, synchronized to the
+ // same barrier, or similar.
+ //
+ // #1 prevents the use of #2 in a signal handler, so the signal handler must
+ // be called in the same thread that reads the "volatile sig_atomic_t"
+ // variable it sets. We enforce that by blocking the signals in question in
+ // the worker threads, forcing them to be handled by this thread.
+ logprintf(12, "Log: Installing signal handlers\n");
+ sigset_t new_blocked_signals;
+ sigemptyset(&new_blocked_signals);
+ sigaddset(&new_blocked_signals, SIGINT);
+ sigaddset(&new_blocked_signals, SIGTERM);
+ sigset_t prev_blocked_signals;
+ pthread_sigmask(SIG_BLOCK, &new_blocked_signals, &prev_blocked_signals);
+ sighandler_t prev_sigint_handler = signal(SIGINT, SatHandleBreak);
+ sighandler_t prev_sigterm_handler = signal(SIGTERM, SatHandleBreak);
+
+ // Kick off all the worker threads.
+ logprintf(12, "Log: Launching worker threads\n");
+ InitializeThreads();
+ SpawnThreads();
+ pthread_sigmask(SIG_SETMASK, &prev_blocked_signals, NULL);
+
+ logprintf(12, "Log: Starting countdown with %d seconds\n", runtime_seconds_);
+
+ // In seconds.
+ static const time_t kSleepFrequency = 1;
+ // All of these are in seconds. You probably want them to be >=
+ // kSleepFrequency and multiples of kSleepFrequency, but neither is necessary.
+ static const time_t kInjectionFrequency = 10;
+ // print_delay_ determines "seconds remaining" chatty update.
+
+ const time_t start = time(NULL);
+ const time_t end = start + runtime_seconds_;
+ time_t now = start;
+ time_t next_print = start + print_delay_;
+ time_t next_pause = start + pause_delay_;
+ time_t next_resume = 0;
+ time_t next_injection;
+ if (crazy_error_injection_) {
+ next_injection = start + kInjectionFrequency;
+ } else {
+ next_injection = 0;
+ }
+
+ while (now < end) {
+ // This is an int because it's for logprintf().
+ const int seconds_remaining = end - now;
+
+ if (user_break_) {
+ // Handle early exit.
+ logprintf(0, "Log: User exiting early (%d seconds remaining)\n",
+ seconds_remaining);
+ break;
+ }
+
+ // If we have an error limit, check it here and see if we should exit.
+ if (max_errorcount_ != 0) {
+ uint64 errors = GetTotalErrorCount();
+ if (errors > max_errorcount_) {
+ logprintf(0, "Log: Exiting early (%d seconds remaining) "
+ "due to excessive failures (%lld)\n",
+ seconds_remaining,
+ errors);
+ break;
+ }
+ }
+
+ if (now >= next_print) {
+ // Print a count down message.
+ logprintf(5, "Log: Seconds remaining: %d\n", seconds_remaining);
+ next_print = NextOccurance(print_delay_, start, now);
+ }
+
+ if (next_injection && now >= next_injection) {
+ // Inject an error.
+ logprintf(4, "Log: Injecting error (%d seconds remaining)\n",
+ seconds_remaining);
+ struct page_entry src;
+ GetValid(&src);
+ src.pattern = patternlist_->GetPattern(0);
+ PutValid(&src);
+ next_injection = NextOccurance(kInjectionFrequency, start, now);
+ }
+
+ if (next_pause && now >= next_pause) {
+ // Tell worker threads to pause in preparation for a power spike.
+ logprintf(4, "Log: Pausing worker threads in preparation for power spike "
+ "(%d seconds remaining)\n", seconds_remaining);
+ power_spike_status_.PauseWorkers();
+ logprintf(12, "Log: Worker threads paused\n");
+ next_pause = 0;
+ next_resume = now + pause_duration_;
+ }
+
+ if (next_resume && now >= next_resume) {
+ // Tell worker threads to resume in order to cause a power spike.
+ logprintf(4, "Log: Resuming worker threads to cause a power spike (%d "
+ "seconds remaining)\n", seconds_remaining);
+ power_spike_status_.ResumeWorkers();
+ logprintf(12, "Log: Worker threads resumed\n");
+ next_pause = NextOccurance(pause_delay_, start, now);
+ next_resume = 0;
+ }
+
+ sat_sleep(NextOccurance(kSleepFrequency, start, now) - now);
+ now = time(NULL);
+ }
+
+ JoinThreads();
+
+ logprintf(0, "Stats: Found %lld hardware incidents\n", errorcount_);
+
+ if (!monitor_mode_)
+ RunAnalysis();
+
+ DeleteThreads();
+
+ logprintf(12, "Log: Uninstalling signal handlers\n");
+ signal(SIGINT, prev_sigint_handler);
+ signal(SIGTERM, prev_sigterm_handler);
+
+ return true;
+}
+
+// Clean up all resources.
+bool Sat::Cleanup() {
+ g_sat = NULL;
+ Logger::GlobalLogger()->StopThread();
+ Logger::GlobalLogger()->SetStdoutOnly();
+ if (logfile_) {
+ close(logfile_);
+ logfile_ = 0;
+ }
+ if (patternlist_) {
+ patternlist_->Destroy();
+ delete patternlist_;
+ patternlist_ = 0;
+ }
+ if (os_) {
+ os_->FreeTestMem();
+ delete os_;
+ os_ = 0;
+ }
+ if (empty_) {
+ delete empty_;
+ empty_ = 0;
+ }
+ if (valid_) {
+ delete valid_;
+ valid_ = 0;
+ }
+ if (finelock_q_) {
+ delete finelock_q_;
+ finelock_q_ = 0;
+ }
+ if (page_bitmap_) {
+ delete[] page_bitmap_;
+ }
+
+ for (size_t i = 0; i < blocktables_.size(); i++) {
+ delete blocktables_[i];
+ }
+
+ if (cc_cacheline_data_) {
+ // The num integer arrays for all the cacheline structures are
+ // allocated as a single chunk. The pointers in the cacheline struct
+ // are populated accordingly. Hence calling free on the first
+ // cacheline's num's address is going to free the entire array.
+ // TODO(aganti): Refactor this to have a class for the cacheline
+ // structure (currently defined in worker.h) and clean this up
+ // in the destructor of that class.
+ if (cc_cacheline_data_[0].num) {
+ free(cc_cacheline_data_[0].num);
+ }
+ free(cc_cacheline_data_);
+ }
+
+ sat_assert(0 == pthread_mutex_destroy(&worker_lock_));
+
+ return true;
+}
+
+
+// Pretty print really obvious results.
+bool Sat::PrintResults() {
+ bool result = true;
+
+ logprintf(4, "\n");
+ if (statuscount_) {
+ logprintf(4, "Status: FAIL - test encountered procedural errors\n");
+ result = false;
+ } else if (errorcount_) {
+ logprintf(4, "Status: FAIL - test discovered HW problems\n");
+ result = false;
+ } else {
+ logprintf(4, "Status: PASS - please verify no corrected errors\n");
+ }
+ logprintf(4, "\n");
+
+ return result;
+}
+
+// Helper functions.
+void Sat::AcquireWorkerLock() {
+ sat_assert(0 == pthread_mutex_lock(&worker_lock_));
+}
+void Sat::ReleaseWorkerLock() {
+ sat_assert(0 == pthread_mutex_unlock(&worker_lock_));
+}
+
+void logprintf(int priority, const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ Logger::GlobalLogger()->VLogF(priority, format, args);
+ va_end(args);
+}
+
+// Stop the logging thread and verify any pending data is written to the log.
+void logstop() {
+ Logger::GlobalLogger()->StopThread();
+}
+
diff --git a/external/subpack/utils/stressapptest/src/src/sat.h b/external/subpack/utils/stressapptest/src/src/sat.h
new file mode 100644
index 0000000..6af90a2
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/sat.h
@@ -0,0 +1,331 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// sat.h : sat stress test object interface and data structures
+
+#ifndef STRESSAPPTEST_SAT_H_
+#define STRESSAPPTEST_SAT_H_
+
+#include <signal.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "finelock_queue.h"
+#include "queue.h"
+#include "sattypes.h"
+#include "worker.h"
+#include "os.h"
+
+// SAT stress test class.
+class Sat {
+ public:
+ // Enum for page queue implementation switch.
+ enum PageQueueType { SAT_ONELOCK, SAT_FINELOCK };
+
+ Sat();
+ virtual ~Sat();
+
+ // Read configuration from arguments. Called first.
+ bool ParseArgs(int argc, char **argv);
+ virtual bool CheckGoogleSpecificArgs(int argc, char **argv, int *i);
+ // Initialize data structures, subclasses, and resources,
+ // based on command line args.
+ // Called after ParseArgs().
+ bool Initialize();
+
+ // Execute the test. Initialize() and ParseArgs() must be called first.
+ // This must be called from a single-threaded program.
+ bool Run();
+
+ // Pretty print result summary.
+ // Called after Run().
+ // Return value is success or failure of the SAT run, *not* of this function!
+ bool PrintResults();
+
+ // Pretty print version info.
+ bool PrintVersion();
+
+ // Pretty print help.
+ virtual void PrintHelp();
+
+ // Clean up allocations and resources.
+ // Called last.
+ bool Cleanup();
+
+ // Abort Run(). Only for use by Run()-installed signal handlers.
+ void Break() { user_break_ = true; }
+
+ // Fetch and return empty and full pages into the empty and full pools.
+ bool GetValid(struct page_entry *pe);
+ bool PutValid(struct page_entry *pe);
+ bool GetEmpty(struct page_entry *pe);
+ bool PutEmpty(struct page_entry *pe);
+
+ bool GetValid(struct page_entry *pe, int32 tag);
+ bool GetEmpty(struct page_entry *pe, int32 tag);
+
+ // Accessor functions.
+ int verbosity() const { return verbosity_; }
+ int logfile() const { return logfile_; }
+ int page_length() const { return page_length_; }
+ int disk_pages() const { return disk_pages_; }
+ int strict() const { return strict_; }
+ int tag_mode() const { return tag_mode_; }
+ int status() const { return statuscount_; }
+ void bad_status() { statuscount_++; }
+ int errors() const { return errorcount_; }
+ int warm() const { return warm_; }
+ bool stop_on_error() const { return stop_on_error_; }
+ bool use_affinity() const { return use_affinity_; }
+ int32 region_mask() const { return region_mask_; }
+ // Semi-accessor to find the "nth" region to avoid replicated bit searching..
+ int32 region_find(int32 num) const {
+ for (int i = 0; i < 32; i++) {
+ if ((1 << i) & region_mask_) {
+ if (num == 0)
+ return i;
+ num--;
+ }
+ }
+ return 0;
+ }
+
+ // Causes false errors for unittesting.
+ // Setting to "true" causes errors to be injected.
+ void set_error_injection(bool errors) { error_injection_ = errors; }
+ bool error_injection() const { return error_injection_; }
+
+ protected:
+ // Opens log file for writing. Returns 0 on failure.
+ bool InitializeLogfile();
+ // Checks for supported environment. Returns 0 on failure.
+ bool CheckEnvironment();
+ // Allocates size_ bytes of test memory.
+ bool AllocateMemory();
+ // Initializes datapattern reference structures.
+ bool InitializePatterns();
+ // Initializes test memory with datapatterns.
+ bool InitializePages();
+
+ // Start up worker threads.
+ virtual void InitializeThreads();
+ // Spawn worker threads.
+ void SpawnThreads();
+ // Reap worker threads.
+ void JoinThreads();
+ // Run bandwidth and error analysis.
+ virtual void RunAnalysis();
+ // Delete worker threads.
+ void DeleteThreads();
+
+ // Return the number of cpus in the system.
+ int CpuCount();
+ // Return the worst-case (largest) cache line size of the system.
+ int CacheLineSize();
+
+ // Collect error counts from threads.
+ int64 GetTotalErrorCount();
+
+ // Command line arguments.
+ string cmdline_;
+
+ // Memory and test configuration.
+ int runtime_seconds_; // Seconds to run.
+ int page_length_; // Length of each memory block.
+ int64 pages_; // Number of memory blocks.
+ int64 size_; // Size of memory tested, in bytes.
+ int64 size_mb_; // Size of memory tested, in MB.
+ int64 reserve_mb_; // Reserve at least this amount of memory
+ // for the system, in MB.
+ int64 min_hugepages_mbytes_; // Minimum hugepages size.
+ int64 freepages_; // How many invalid pages we need.
+ int disk_pages_; // Number of pages per temp file.
+ uint64 paddr_base_; // Physical address base.
+ uint64 channel_hash_; // Mask of address bits XORed for channel.
+ int channel_width_; // Channel width in bits.
+ vector< vector<string> > channels_; // Memory module names per channel.
+
+ // Control flags.
+ volatile sig_atomic_t user_break_; // User has signalled early exit. Used as
+ // a boolean.
+ int verbosity_; // How much to print.
+ int print_delay_; // Chatty update frequency.
+ int strict_; // Check results per transaction.
+ int warm_; // FPU warms CPU while copying.
+ int address_mode_; // 32 or 64 bit binary.
+ bool stop_on_error_; // Exit immendiately on any error.
+ bool findfiles_; // Autodetect tempfile locations.
+
+ bool error_injection_; // Simulate errors, for unittests.
+ bool crazy_error_injection_; // Simulate lots of errors.
+ uint64 max_errorcount_; // Number of errors before forced exit.
+ int run_on_anything_; // Ignore unknown machine ereor.
+ bool use_logfile_; // Log to a file.
+ char logfilename_[255]; // Name of file to log to.
+ int logfile_; // File handle to log to.
+ bool log_timestamps_; // Whether to add timestamps to log lines.
+
+ // Disk thread options.
+ int read_block_size_; // Size of block to read from disk.
+ int write_block_size_; // Size of block to write to disk.
+ int64 segment_size_; // Size of segment to split disk into.
+ int cache_size_; // Size of disk cache.
+ int blocks_per_segment_; // Number of blocks to test per segment.
+ int read_threshold_; // Maximum time (in us) a read should take
+ // before warning of a slow read.
+ int write_threshold_; // Maximum time (in us) a write should
+ // take before warning of a slow write.
+ int non_destructive_; // Whether to use non-destructive mode for
+ // the disk test.
+
+ // Generic Options.
+ int monitor_mode_; // Switch for monitor-only mode SAT.
+ // This switch trumps most of the other
+ // argument, as SAT will only run error
+ // polling threads.
+ int tag_mode_; // Do tagging of memory and strict
+ // checking for misplaced cachelines.
+
+ bool do_page_map_; // Should we print a list of used pages?
+ unsigned char *page_bitmap_; // Store bitmap of physical pages seen.
+ uint64 page_bitmap_size_; // Length of physical memory represented.
+
+ // Cpu Cache Coherency Options.
+ bool cc_test_; // Flag to decide whether to start the
+ // cache coherency threads.
+ int cc_cacheline_count_; // Number of cache line size structures.
+ int cc_cacheline_size_; // Size of a cache line.
+ int cc_inc_count_; // Number of times to increment the shared
+ // cache lines structure members.
+
+ // Cpu Frequency Options.
+ bool cpu_freq_test_; // Flag to decide whether to start the
+ // cpu frequency thread.
+ int cpu_freq_threshold_; // The MHz threshold which will cause
+ // the test to fail.
+ int cpu_freq_round_; // Round the computed frequency to this
+ // value.
+
+ // Thread control.
+ int file_threads_; // Threads of file IO.
+ int net_threads_; // Threads of network IO.
+ int listen_threads_; // Threads for network IO to connect.
+ int memory_threads_; // Threads of memcpy.
+ int invert_threads_; // Threads of invert.
+ int fill_threads_; // Threads of memset.
+ int check_threads_; // Threads of strcmp.
+ int cpu_stress_threads_; // Threads of CPU stress workload.
+ int disk_threads_; // Threads of disk test.
+ int random_threads_; // Number of random disk threads.
+ int total_threads_; // Total threads used.
+ bool error_poll_; // Poll for system errors.
+
+ // Resources.
+ cc_cacheline_data *cc_cacheline_data_; // The cache line sized datastructure
+ // used by the ccache threads
+ // (in worker.h).
+ vector<string> filename_; // Filenames for file IO.
+ vector<string> ipaddrs_; // Addresses for network IO.
+ vector<string> diskfilename_; // Filename for disk IO device.
+ // Block table for IO device.
+ vector<DiskBlockTable*> blocktables_;
+
+ bool use_affinity_; // Should stressapptest set cpu affinity?
+ int32 region_mask_; // Bitmask of available NUMA regions.
+ int32 region_count_; // Count of available NUMA regions.
+ int32 region_[32]; // Pagecount per region.
+ int region_mode_; // What to do with NUMA hints?
+ static const int kLocalNuma = 1; // Target local memory.
+ static const int kRemoteNuma = 2; // Target remote memory.
+
+ // Results.
+ int64 errorcount_; // Total hardware incidents seen.
+ int statuscount_; // Total test errors seen.
+
+ // Thread type constants and types
+ enum ThreadType {
+ kMemoryType = 0,
+ kFileIOType = 1,
+ kNetIOType = 2,
+ kNetSlaveType = 3,
+ kCheckType = 4,
+ kInvertType = 5,
+ kDiskType = 6,
+ kRandomDiskType = 7,
+ kCPUType = 8,
+ kErrorType = 9,
+ kCCType = 10,
+ kCPUFreqType = 11,
+ };
+
+ // Helper functions.
+ virtual void AcquireWorkerLock();
+ virtual void ReleaseWorkerLock();
+ pthread_mutex_t worker_lock_; // Lock access to the worker thread structure.
+ typedef vector<WorkerThread*> WorkerVector;
+ typedef map<int, WorkerVector*> WorkerMap;
+ // Contains all worker threads.
+ WorkerMap workers_map_;
+ // Delay between power spikes.
+ time_t pause_delay_;
+ // The duration of each pause (for power spikes).
+ time_t pause_duration_;
+ // For the workers we pause and resume to create power spikes.
+ WorkerStatus power_spike_status_;
+ // For the workers we never pause.
+ WorkerStatus continuous_status_;
+
+ class OsLayer *os_; // Os abstraction: put hacks here.
+ class PatternList *patternlist_; // Access to global data patterns.
+
+ // RunAnalysis methods
+ void AnalysisAllStats(); // Summary of all runs.
+ void MemoryStats();
+ void FileStats();
+ void NetStats();
+ void CheckStats();
+ void InvertStats();
+ void DiskStats();
+
+ void QueueStats();
+
+ // Physical page use reporting.
+ void AddrMapInit();
+ void AddrMapUpdate(struct page_entry *pe);
+ void AddrMapPrint();
+
+ // additional memory data from google-specific tests.
+ virtual void GoogleMemoryStats(float *memcopy_data,
+ float *memcopy_bandwidth);
+
+ virtual void GoogleOsOptions(std::map<std::string, std::string> *options);
+
+ // Page queues, only one of (valid_+empty_) or (finelock_q_) will be used
+ // at a time. A commandline switch controls which queue implementation will
+ // be used.
+ class PageEntryQueue *valid_; // Page queue structure, valid pages.
+ class PageEntryQueue *empty_; // Page queue structure, free pages.
+ class FineLockPEQueue *finelock_q_; // Page queue with fine-grain locks
+ Sat::PageQueueType pe_q_implementation_; // Queue implementation switch
+
+ DISALLOW_COPY_AND_ASSIGN(Sat);
+};
+
+Sat *SatFactory();
+
+#endif // STRESSAPPTEST_SAT_H_
diff --git a/external/subpack/utils/stressapptest/src/src/sat_factory.cc b/external/subpack/utils/stressapptest/src/src/sat_factory.cc
new file mode 100644
index 0000000..5cf3e4c
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/sat_factory.cc
@@ -0,0 +1,21 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// sat_factory.h : factory for SAT
+
+#include "sat.h" // NOLINT
+
+Sat *SatFactory() {
+ return new Sat();
+}
diff --git a/external/subpack/utils/stressapptest/src/src/sattypes.h b/external/subpack/utils/stressapptest/src/src/sattypes.h
new file mode 100644
index 0000000..4e57cba
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/sattypes.h
@@ -0,0 +1,256 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STRESSAPPTEST_SATTYPES_H_
+#define STRESSAPPTEST_SATTYPES_H_
+
+#include <arpa/inet.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <time.h>
+#include <string.h>
+#include <algorithm>
+#include <string>
+
+#ifdef HAVE_CONFIG_H // Built using autoconf
+#include "stressapptest_config.h" // NOLINT
+#ifndef _LIBCPP_VERSION
+using namespace __gnu_cxx; //NOLINT
+#endif // _LIBCPP_VERSION
+using namespace std;
+
+typedef signed long long int64;
+typedef signed int int32;
+typedef signed short int int16;
+typedef signed char int8;
+
+typedef unsigned long long uint64;
+typedef unsigned int uint32;
+typedef unsigned short uint16;
+typedef unsigned char uint8;
+
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+
+inline const char* Timestamp() {
+ return STRESSAPPTEST_TIMESTAMP;
+}
+
+inline const char* BuildChangelist() {
+ return "open source release";
+}
+
+static const bool kOpenSource = true;
+#else // !HAVE_CONFIG_H
+static const bool kOpenSource = false;
+ #include "googlesattypes.h" // NOLINT
+#endif // HAVE_CONFIG_H
+// Workaround to allow 32/64 bit conversion
+// without running into strict aliasing problems.
+union datacast_t {
+ uint64 l64;
+ struct {
+ uint32 l;
+ uint32 h;
+ } l32;
+};
+
+
+// File sync'd print to console and log
+void logprintf(int priority, const char *format, ...);
+
+// Stop the log and dump any queued lines.
+void logstop();
+
+// We print to stderr ourselves first in case we're in such a bad state that the
+// logger can't work.
+#define sat_assert(x) \
+{\
+ if (!(x)) {\
+ logstop();\
+ fprintf(stderr, "Assertion failed at %s:%d\n", __FILE__, __LINE__);\
+ logprintf(0, "Assertion failed at %s:%d\n", __FILE__, __LINE__);\
+ exit(1);\
+ }\
+}
+
+#if !defined(CPU_SETSIZE)
+ // Define type and macros for cpu mask operations
+ // Note: this code is hacked together to deal with difference
+ // function signatures across versions of glibc, ie those that take
+ // cpu_set_t versus those that take unsigned long. -johnhuang
+ typedef uint64 cpu_set_t;
+ #define CPU_SETSIZE (sizeof(cpu_set_t) * 8)
+ #define CPU_ISSET(index, cpu_set_ptr) (*(cpu_set_ptr) & 1ull << (index))
+ #define CPU_SET(index, cpu_set_ptr) (*(cpu_set_ptr) |= 1ull << (index))
+ #define CPU_ZERO(cpu_set_ptr) (*(cpu_set_ptr) = 0)
+ #define CPU_CLR(index, cpu_set_ptr) (*(cpu_set_ptr) &= ~(1ull << (index)))
+#endif
+
+static inline bool cpuset_isequal(const cpu_set_t *c1, const cpu_set_t *c2) {
+ for (int i = 0; i < CPU_SETSIZE; ++i)
+ if ((CPU_ISSET(i, c1) != 0) != (CPU_ISSET(i, c2) != 0))
+ return false;
+ return true;
+}
+
+static inline bool cpuset_issubset(const cpu_set_t *c1, const cpu_set_t *c2) {
+ for (int i = 0; i < CPU_SETSIZE; ++i)
+ if (CPU_ISSET(i, c1) && !CPU_ISSET(i, c2))
+ return false;
+ return true;
+}
+
+static inline int cpuset_count(const cpu_set_t *cpuset) {
+ int count = 0;
+ for (int i = 0; i < CPU_SETSIZE; ++i)
+ if (CPU_ISSET(i, cpuset))
+ ++count;
+ return count;
+}
+
+static inline void cpuset_set_ab(cpu_set_t *cpuset, int a, int b) {
+ CPU_ZERO(cpuset);
+ for (int i = a; i < b; ++i)
+ CPU_SET(i, cpuset);
+}
+
+static inline string cpuset_format(const cpu_set_t *cpuset) {
+ string format;
+ int digit = 0, last_non_zero_size = 1;
+ for (int i = 0; i < CPU_SETSIZE; ++i) {
+ if (CPU_ISSET(i, cpuset)) {
+ digit |= 1 << (i & 3);
+ }
+ if ((i & 3) == 3) {
+ format += char(digit <= 9 ? '0' + digit: 'A' + digit - 10);
+ if (digit) {
+ last_non_zero_size = format.size();
+ digit = 0;
+ }
+ }
+ }
+ if (digit) {
+ format += char(digit <= 9 ? '0' + digit: 'A' + digit - 10);
+ last_non_zero_size = format.size();
+ }
+ format.erase(last_non_zero_size);
+ reverse(format.begin(), format.end());
+ return format;
+}
+
+static const int32 kUSleepOneSecond = 1000000;
+
+// This is guaranteed not to use signals.
+inline bool sat_usleep(int32 microseconds) {
+ timespec req;
+ req.tv_sec = microseconds / 1000000;
+ // Convert microseconds argument to nano seconds.
+ req.tv_nsec = (microseconds % 1000000) * 1000;
+ return nanosleep(&req, NULL) == 0;
+}
+
+// This is guaranteed not to use signals.
+inline bool sat_sleep(time_t seconds) {
+ timespec req;
+ req.tv_sec = seconds;
+ req.tv_nsec = 0;
+ return nanosleep(&req, NULL) == 0;
+}
+
+// Get an error code description for use in error messages.
+//
+// Args:
+// error_num: an errno error code
+inline string ErrorString(int error_num) {
+ char buf[256];
+#ifdef STRERROR_R_CHAR_P
+ return string(strerror_r(error_num, buf, sizeof buf));
+#else
+ if (strerror_r(error_num, buf, sizeof buf))
+ return "unknown failure";
+ else
+ return string(buf);
+#endif
+}
+
+// Execute the cpuid instruction and pass back the contents of the registers.
+// This only works on x86 based platforms.
+inline void cpuid(
+ unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) {
+ *ebx = 0;
+ *ecx = 0;
+ *edx = 0;
+ // CPUID features documented at:
+ // http://www.sandpile.org/ia32/cpuid.htm
+#if defined(STRESSAPPTEST_CPU_I686) || defined(STRESSAPPTEST_CPU_X86_64)
+#if defined(__PIC__) && defined(STRESSAPPTEST_CPU_I686)
+ // In PIC compilations using the i686 cpu type, ebx contains the address
+ // of the global offset table. The compiler can't properly handle constraints
+ // using the ebx register for this compile, so preserve the register
+ // ourselves.
+ asm(
+ "mov %%ebx, %%edi;"
+ "cpuid;"
+ "xchg %%edi, %%ebx;"
+ // Output registers.
+ : "=a" (*eax), "=D" (*ebx), "=c" (*ecx), "=d" (*edx)
+ // Input registers.
+ : "a" (*eax)
+ ); // Asm
+#else
+ asm(
+ "cpuid;"
+ // Output registers.
+ : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
+ // Input registers.
+ : "a" (*eax)
+ ); // Asm
+#endif // defined(__PIC__) && defined(STRESSAPPTEST_CPU_I686)
+#elif defined(STRESSAPPTEST_CPU_MIPS)
+ return;
+#elif defined(STRESSAPPTEST_CPU_PPC)
+ return;
+#elif defined(STRESSAPPTEST_CPU_ARMV7A)
+ return;
+#elif defined(STRESSAPPTEST_CPU_AARCH64)
+ return;
+#elif defined(STRESSAPPTEST_CPU_LOONGARCH)
+ return;
+#else
+#warning "Unsupported CPU type."
+#endif
+}
+
+inline int64 sat_get_time_us() {
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts.tv_sec * 1000000ULL + ts.tv_nsec/1000ULL;
+}
+
+// Define handy constants here
+static const int kTicksPerSec = 100;
+static const int kMegabyte = (1024LL*1024LL);
+static const int kSatDiskPageMax = 32;
+static const int kSatDiskPage = 8;
+//static const int kSatPageSize = (1024LL*1024LL);
+//reduce the size for test when free memory is small
+static const int kSatPageSize = (512LL*1024LL);
+static const int kCacheLineSize = 64;
+static const uint16_t kNetworkPort = 19996;
+
+#endif // STRESSAPPTEST_SATTYPES_H_
diff --git a/external/subpack/utils/stressapptest/src/src/stressapptest_config.h.in b/external/subpack/utils/stressapptest/src/src/stressapptest_config.h.in
new file mode 100644
index 0000000..f698507
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/stressapptest_config.h.in
@@ -0,0 +1,265 @@
+/* src/stressapptest_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if the `closedir' function returns void instead of int. */
+#undef CLOSEDIR_VOID
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
+ don't. */
+#undef HAVE_DECL_STRERROR_R
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `ftruncate' function. */
+#undef HAVE_FTRUNCATE
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <libaio.h> header file. */
+#undef HAVE_LIBAIO_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the `mmap64' function. */
+#undef HAVE_MMAP64
+
+/* Define to 1 if you have the `munmap' function. */
+#undef HAVE_MUNMAP
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the `posix_memalign' function. */
+#undef HAVE_POSIX_MEMALIGN
+
+/* Define to 1 if the system has `pthread_barrier'. */
+#undef HAVE_PTHREAD_BARRIERS
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
+
+/* Define to 1 if you have the `pthread_rwlockattr_setkind_np' function. */
+#undef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP
+
+/* Define to 1 if you have the `rand_r' function. */
+#undef HAVE_RAND_R
+
+/* Define to 1 if you have the `sched_getaffinity' function. */
+#undef HAVE_SCHED_GETAFFINITY
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define if you have `strerror_r'. */
+#undef HAVE_STRERROR_R
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the `strtoull' function. */
+#undef HAVE_STRTOULL
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/shm.h> header file. */
+#undef HAVE_SYS_SHM_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to the type of arg 1 for `select'. */
+#undef SELECT_TYPE_ARG1
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#undef SELECT_TYPE_ARG234
+
+/* Define to the type of arg 5 for `select'. */
+#undef SELECT_TYPE_ARG5
+
+/* Define to 1 if all of the C90 standard headers exist (not just the ones
+ required in a freestanding environment). This macro is provided for
+ backward compatibility; new code need not use it. */
+#undef STDC_HEADERS
+
+/* Define to 1 if strerror_r returns char *. */
+#undef STRERROR_R_CHAR_P
+
+/* Defined if the target CPU is aarch64 */
+#undef STRESSAPPTEST_CPU_AARCH64
+
+/* Defined if the target CPU is armv7a */
+#undef STRESSAPPTEST_CPU_ARMV7A
+
+/* Defined if the target CPU is i686 */
+#undef STRESSAPPTEST_CPU_I686
+
+/* Defined if the target CPU is LOONGARCH */
+#undef STRESSAPPTEST_CPU_LOONGARCH
+
+/* Defined if the target CPU is MIPS */
+#undef STRESSAPPTEST_CPU_MIPS
+
+/* Defined if the target CPU is PowerPC */
+#undef STRESSAPPTEST_CPU_PPC
+
+/* Defined if the target CPU is x86_64 */
+#undef STRESSAPPTEST_CPU_X86_64
+
+/* Defined if the target OS is BSD based */
+#undef STRESSAPPTEST_OS_BSD
+
+/* Defined if the target OS is OSX */
+#undef STRESSAPPTEST_OS_DARWIN
+
+/* Defined if the target OS is Linux */
+#undef STRESSAPPTEST_OS_LINUX
+
+/* Timestamp when ./configure was executed */
+#undef STRESSAPPTEST_TIMESTAMP
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. This
+ macro is obsolete. */
+#undef TIME_WITH_SYS_TIME
+
+/* Version number of package */
+#undef VERSION
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define as a signed integer type capable of holding a process identifier. */
+#undef pid_t
+
+/* Define to the equivalent of the C99 'restrict' keyword, or to
+ nothing if this is not supported. Do not define if restrict is
+ supported only directly. */
+#undef restrict
+/* Work around a bug in older versions of Sun C++, which did not
+ #define __restrict__ or support _Restrict or __restrict__
+ even though the corresponding Sun C compiler ended up with
+ "#define restrict _Restrict" or "#define restrict __restrict__"
+ in the previous line. This workaround can be removed once
+ we assume Oracle Developer Studio 12.5 (2016) or later. */
+#if defined __SUNPRO_CC && !defined __RESTRICT && !defined __restrict__
+# define _Restrict
+# define __restrict__
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef ssize_t
+
+/* Define to the type of an unsigned integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint16_t
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+ code using `volatile' can become incorrect without. Disable with care. */
+#undef volatile
diff --git a/external/subpack/utils/stressapptest/src/src/stressapptest_config_android.h b/external/subpack/utils/stressapptest/src/src/stressapptest_config_android.h
new file mode 100644
index 0000000..3a6fcc8
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/stressapptest_config_android.h
@@ -0,0 +1,172 @@
+/* src/stressapptest_config.h. Generated from stressapptest_config.h.in by configure. */
+/* src/stressapptest_config.h.in. Generated from configure.ac by autoheader. */
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+#define CLOSEDIR_VOID 1
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRERROR_R 1
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#define HAVE_DIRENT_H 1
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+/* Define to 1 if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE 1
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+/* Define to 1 if you have the <libaio.h> header file. */
+/* #undef HAVE_LIBAIO_H */
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+/* Define to 1 if you have the `mmap64' function. */
+/* #undef HAVE_MMAP64 */
+/* Define to 1 if you have the `munmap' function. */
+#define HAVE_MUNMAP 1
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+/* Define to 1 if you have the `posix_memalign' function. */
+#define HAVE_POSIX_MEMALIGN 1
+/* Define to 1 if the system has `pthread_barrier'. */
+#define HAVE_PTHREAD_BARRIERS 1
+/* Define to 1 if you have the <pthread.h> header file. */
+#define HAVE_PTHREAD_H 1
+/* Define to 1 if you have the `rand_r' function. */
+/* #undef HAVE_RAND_R */
+/* Define to 1 if you have the `sched_getaffinity' function. */
+#define HAVE_SCHED_GETAFFINITY 1
+/* Define to 1 if you have the `select' function. */
+#define HAVE_SELECT 1
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+/* Define to 1 if you have the `strerror_r' function. */
+#define HAVE_STRERROR_R 1
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+/* Define to 1 if you have the `strtoull' function. */
+#define HAVE_STRTOULL 1
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_DIR_H */
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_NDIR_H */
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+/* Define to 1 if you have the <sys/shm.h> header file. */
+/* #undef HAVE_SYS_SHM_H */
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+/* Define to 1 if the system has the type `_Bool'. */
+#define HAVE__BOOL 1
+/* Name of package */
+#define PACKAGE "stressapptest"
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "opensource@google.com"
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "stressapptest"
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "stressapptest 1.0.9_autoconf"
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "stressapptest"
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.0.9_autoconf"
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+/* Define to the type of arg 1 for `select'. */
+#define SELECT_TYPE_ARG1 int
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#define SELECT_TYPE_ARG234 (fd_set *)
+/* Define to the type of arg 5 for `select'. */
+#define SELECT_TYPE_ARG5 (struct timeval *)
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+/* Define to 1 if strerror_r returns char *. */
+/* #undef STRERROR_R_CHAR_P */
+/* Defined if the target CPU is armv7a */
+/* #define STRESSAPPTEST_CPU_ARMV7A */
+/* Defined if the target CPU is i686 */
+/* #undef STRESSAPPTEST_CPU_I686 */
+/* Defined if the target CPU is PowerPC */
+/* #undef STRESSAPPTEST_CPU_PPC */
+/* Defined if the target CPU is x86_64 */
+/* #undef STRESSAPPTEST_CPU_X86_64 */
+/* Defined if the target OS is BSD based */
+/* #undef STRESSAPPTEST_OS_BSD */
+/* Defined if the target OS is OSX */
+/* #undef STRESSAPPTEST_OS_DARWIN */
+/* Defined if the target OS is Linux */
+#define STRESSAPPTEST_OS_LINUX /**/
+/* Timestamp when ./configure was executed */
+#ifndef STRESSAPPTEST_TIMESTAMP
+#define STRESSAPPTEST_TIMESTAMP "Android version"
+#endif
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+/* Version number of package */
+#define VERSION "1.0.9_autoconf"
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+/* Define to the equivalent of the C99 'restrict' keyword, or to
+ nothing if this is not supported. Do not define if restrict is
+ supported directly. */
+#define restrict __restrict
+/* Work around a bug in Sun C++: it does not support _Restrict or
+ __restrict__, even though the corresponding Sun C compiler ends up with
+ "#define restrict _Restrict" or "#define restrict __restrict__" in the
+ previous line. Perhaps some future version of Sun C++ will work with
+ restrict; if so, hopefully it defines __RESTRICT like Sun C does. */
+#if defined __SUNPRO_CC && !defined __RESTRICT
+# define _Restrict
+# define __restrict__
+#endif
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef ssize_t */
+/* Define to the type of an unsigned integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint16_t */
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+ code using `volatile' can become incorrect without. Disable with care. */
+/* #undef volatile */
diff --git a/external/subpack/utils/stressapptest/src/src/worker.cc b/external/subpack/utils/stressapptest/src/src/worker.cc
new file mode 100644
index 0000000..c4abc87
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/worker.cc
@@ -0,0 +1,3704 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// worker.cc : individual tasks that can be run in combination to
+// stress the system
+
+#include <errno.h>
+#include <pthread.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sys/select.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/times.h>
+
+// These are necessary, but on by default
+// #define __USE_GNU
+// #define __USE_LARGEFILE64
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <linux/unistd.h> // for gettid
+
+// For size of block device
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+// For asynchronous I/O
+#ifdef HAVE_LIBAIO_H
+#include <libaio.h>
+#endif
+
+#include <sys/syscall.h>
+
+#include <set>
+#include <string>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "error_diag.h" // NOLINT
+#include "os.h" // NOLINT
+#include "pattern.h" // NOLINT
+#include "queue.h" // NOLINT
+#include "sat.h" // NOLINT
+#include "sattypes.h" // NOLINT
+#include "worker.h" // NOLINT
+
+// Syscalls
+// Why ubuntu, do you hate gettid so bad?
+#if !defined(__NR_gettid)
+ #define __NR_gettid 224
+#endif
+
+#define gettid() syscall(__NR_gettid)
+#if !defined(CPU_SETSIZE)
+_syscall3(int, sched_getaffinity, pid_t, pid,
+ unsigned int, len, cpu_set_t*, mask)
+_syscall3(int, sched_setaffinity, pid_t, pid,
+ unsigned int, len, cpu_set_t*, mask)
+#endif
+
+namespace {
+ // Work around the sad fact that there are two (gnu, xsi) incompatible
+ // versions of strerror_r floating around google. Awesome.
+ bool sat_strerror(int err, char *buf, int len) {
+ buf[0] = 0;
+ char *errmsg = reinterpret_cast<char*>(strerror_r(err, buf, len));
+ int retval = reinterpret_cast<int64>(errmsg);
+ if (retval == 0)
+ return true;
+ if (retval == -1)
+ return false;
+ if (errmsg != buf) {
+ strncpy(buf, errmsg, len - 1);
+ buf[len - 1] = 0;
+ }
+ return true;
+ }
+
+
+ inline uint64 addr_to_tag(void *address) {
+ return reinterpret_cast<uint64>(address);
+ }
+} // namespace
+
+#if !defined(O_DIRECT)
+// Sometimes this isn't available.
+// Disregard if it's not defined.
+ #define O_DIRECT 0
+#endif
+
+// A struct to hold captured errors, for later reporting.
+struct ErrorRecord {
+ uint64 actual; // This is the actual value read.
+ uint64 reread; // This is the actual value, reread.
+ uint64 expected; // This is what it should have been.
+ uint64 *vaddr; // This is where it was (or wasn't).
+ char *vbyteaddr; // This is byte specific where the data was (or wasn't).
+ uint64 paddr; // This is the bus address, if available.
+ uint64 *tagvaddr; // This holds the tag value if this data was tagged.
+ uint64 tagpaddr; // This holds the physical address corresponding to the tag.
+ uint32 lastcpu; // This holds the CPU recorded as probably writing this data.
+ const char *patternname; // This holds the pattern name of the expected data.
+};
+
+// This is a helper function to create new threads with pthreads.
+static void *ThreadSpawnerGeneric(void *ptr) {
+ WorkerThread *worker = static_cast<WorkerThread*>(ptr);
+ worker->StartRoutine();
+ return NULL;
+}
+
+void WorkerStatus::Initialize() {
+ sat_assert(0 == pthread_mutex_init(&num_workers_mutex_, NULL));
+
+ pthread_rwlockattr_t attrs;
+ sat_assert(0 == pthread_rwlockattr_init(&attrs));
+#ifdef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP
+ // Avoid writer lock starvation.
+ sat_assert(0 == pthread_rwlockattr_setkind_np(
+ &attrs, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP));
+#endif
+ sat_assert(0 == pthread_rwlock_init(&status_rwlock_, &attrs));
+
+#ifdef HAVE_PTHREAD_BARRIERS
+ sat_assert(0 == pthread_barrier_init(&pause_barrier_, NULL,
+ num_workers_ + 1));
+ sat_assert(0 == pthread_rwlock_init(&pause_rwlock_, &attrs));
+#endif
+
+ sat_assert(0 == pthread_rwlockattr_destroy(&attrs));
+}
+
+void WorkerStatus::Destroy() {
+ sat_assert(0 == pthread_mutex_destroy(&num_workers_mutex_));
+ sat_assert(0 == pthread_rwlock_destroy(&status_rwlock_));
+#ifdef HAVE_PTHREAD_BARRIERS
+ sat_assert(0 == pthread_barrier_destroy(&pause_barrier_));
+#endif
+}
+
+void WorkerStatus::PauseWorkers() {
+ if (SetStatus(PAUSE) != PAUSE)
+ WaitOnPauseBarrier();
+}
+
+void WorkerStatus::ResumeWorkers() {
+ if (SetStatus(RUN) == PAUSE)
+ WaitOnPauseBarrier();
+}
+
+void WorkerStatus::StopWorkers() {
+ if (SetStatus(STOP) == PAUSE)
+ WaitOnPauseBarrier();
+}
+
+bool WorkerStatus::ContinueRunning(bool *paused) {
+ // This loop is an optimization. We use it to immediately re-check the status
+ // after resuming from a pause, instead of returning and waiting for the next
+ // call to this function.
+ if (paused) {
+ *paused = false;
+ }
+ for (;;) {
+ switch (GetStatus()) {
+ case RUN:
+ return true;
+ case PAUSE:
+ // Wait for the other workers to call this function so that
+ // PauseWorkers() can return.
+ WaitOnPauseBarrier();
+ // Wait for ResumeWorkers() to be called.
+ WaitOnPauseBarrier();
+ // Indicate that a pause occurred.
+ if (paused) {
+ *paused = true;
+ }
+ break;
+ case STOP:
+ return false;
+ }
+ }
+}
+
+bool WorkerStatus::ContinueRunningNoPause() {
+ return (GetStatus() != STOP);
+}
+
+void WorkerStatus::RemoveSelf() {
+ // Acquire a read lock on status_rwlock_ while (status_ != PAUSE).
+ for (;;) {
+ AcquireStatusReadLock();
+ if (status_ != PAUSE)
+ break;
+ // We need to obey PauseWorkers() just like ContinueRunning() would, so that
+ // the other threads won't wait on pause_barrier_ forever.
+ ReleaseStatusLock();
+ // Wait for the other workers to call this function so that PauseWorkers()
+ // can return.
+ WaitOnPauseBarrier();
+ // Wait for ResumeWorkers() to be called.
+ WaitOnPauseBarrier();
+ }
+
+ // This lock would be unnecessary if we held a write lock instead of a read
+ // lock on status_rwlock_, but that would also force all threads calling
+ // ContinueRunning() to wait on this one. Using a separate lock avoids that.
+ AcquireNumWorkersLock();
+ // Decrement num_workers_ and reinitialize pause_barrier_, which we know isn't
+ // in use because (status != PAUSE).
+#ifdef HAVE_PTHREAD_BARRIERS
+ sat_assert(0 == pthread_barrier_destroy(&pause_barrier_));
+ sat_assert(0 == pthread_barrier_init(&pause_barrier_, NULL, num_workers_));
+#endif
+ --num_workers_;
+ ReleaseNumWorkersLock();
+
+ // Release status_rwlock_.
+ ReleaseStatusLock();
+}
+
+
+// Parent thread class.
+WorkerThread::WorkerThread() {
+ status_ = false;
+ pages_copied_ = 0;
+ errorcount_ = 0;
+ runduration_usec_ = 1;
+ priority_ = Normal;
+ worker_status_ = NULL;
+ thread_spawner_ = &ThreadSpawnerGeneric;
+ tag_mode_ = false;
+}
+
+WorkerThread::~WorkerThread() {}
+
+// Constructors. Just init some default values.
+FillThread::FillThread() {
+ num_pages_to_fill_ = 0;
+}
+
+// Initialize file name to empty.
+FileThread::FileThread() {
+ filename_ = "";
+ devicename_ = "";
+ pass_ = 0;
+ page_io_ = true;
+ crc_page_ = -1;
+ local_page_ = NULL;
+}
+
+// If file thread used bounce buffer in memory, account for the extra
+// copy for memory bandwidth calculation.
+float FileThread::GetMemoryCopiedData() {
+ if (!os_->normal_mem())
+ return GetCopiedData();
+ else
+ return 0;
+}
+
+// Initialize target hostname to be invalid.
+NetworkThread::NetworkThread() {
+ snprintf(ipaddr_, sizeof(ipaddr_), "Unknown");
+ sock_ = 0;
+}
+
+// Initialize?
+NetworkSlaveThread::NetworkSlaveThread() {
+}
+
+// Initialize?
+NetworkListenThread::NetworkListenThread() {
+}
+
+// Init member variables.
+void WorkerThread::InitThread(int thread_num_init,
+ class Sat *sat_init,
+ class OsLayer *os_init,
+ class PatternList *patternlist_init,
+ WorkerStatus *worker_status) {
+ sat_assert(worker_status);
+ worker_status->AddWorkers(1);
+
+ thread_num_ = thread_num_init;
+ sat_ = sat_init;
+ os_ = os_init;
+ patternlist_ = patternlist_init;
+ worker_status_ = worker_status;
+
+ AvailableCpus(&cpu_mask_);
+ tag_ = 0xffffffff;
+
+ tag_mode_ = sat_->tag_mode();
+}
+
+
+// Use pthreads to prioritize a system thread.
+bool WorkerThread::InitPriority() {
+ // This doesn't affect performance that much, and may not be too safe.
+
+ bool ret = BindToCpus(&cpu_mask_);
+ if (!ret)
+ logprintf(11, "Log: Bind to %s failed.\n",
+ cpuset_format(&cpu_mask_).c_str());
+
+ logprintf(11, "Log: Thread %d running on core ID %d mask %s (%s).\n",
+ thread_num_, sched_getcpu(),
+ CurrentCpusFormat().c_str(),
+ cpuset_format(&cpu_mask_).c_str());
+#if 0
+ if (priority_ == High) {
+ sched_param param;
+ param.sched_priority = 1;
+ // Set the priority; others are unchanged.
+ logprintf(0, "Log: Changing priority to SCHED_FIFO %d\n",
+ param.sched_priority);
+ if (sched_setscheduler(0, SCHED_FIFO, ¶m)) {
+ char buf[256];
+ sat_strerror(errno, buf, sizeof(buf));
+ logprintf(0, "Process Error: sched_setscheduler "
+ "failed - error %d %s\n",
+ errno, buf);
+ }
+ }
+#endif
+ return true;
+}
+
+// Use pthreads to create a system thread.
+int WorkerThread::SpawnThread() {
+ // Create the new thread.
+ int result = pthread_create(&thread_, NULL, thread_spawner_, this);
+ if (result) {
+ char buf[256];
+ sat_strerror(result, buf, sizeof(buf));
+ logprintf(0, "Process Error: pthread_create "
+ "failed - error %d %s\n", result,
+ buf);
+ status_ = false;
+ return false;
+ }
+
+ // 0 is pthreads success.
+ return true;
+}
+
+// Kill the worker thread with SIGINT.
+bool WorkerThread::KillThread() {
+ return (pthread_kill(thread_, SIGINT) == 0);
+}
+
+// Block until thread has exited.
+bool WorkerThread::JoinThread() {
+ int result = pthread_join(thread_, NULL);
+
+ if (result) {
+ logprintf(0, "Process Error: pthread_join failed - error %d\n", result);
+ status_ = false;
+ }
+
+ // 0 is pthreads success.
+ return (!result);
+}
+
+
+void WorkerThread::StartRoutine() {
+ InitPriority();
+ StartThreadTimer();
+ Work();
+ StopThreadTimer();
+ worker_status_->RemoveSelf();
+}
+
+
+// Thread work loop. Execute until marked finished.
+bool WorkerThread::Work() {
+ do {
+ logprintf(9, "Log: ...\n");
+ // Sleep for 1 second.
+ sat_sleep(1);
+ } while (IsReadyToRun());
+
+ return false;
+}
+
+
+// Returns CPU mask of CPUs available to this process,
+// Conceptually, each bit represents a logical CPU, ie:
+// mask = 3 (11b): cpu0, 1
+// mask = 13 (1101b): cpu0, 2, 3
+bool WorkerThread::AvailableCpus(cpu_set_t *cpuset) {
+ CPU_ZERO(cpuset);
+#ifdef HAVE_SCHED_GETAFFINITY
+ return sched_getaffinity(getppid(), sizeof(*cpuset), cpuset) == 0;
+#else
+ return 0;
+#endif
+}
+
+
+// Returns CPU mask of CPUs this thread is bound to,
+// Conceptually, each bit represents a logical CPU, ie:
+// mask = 3 (11b): cpu0, 1
+// mask = 13 (1101b): cpu0, 2, 3
+bool WorkerThread::CurrentCpus(cpu_set_t *cpuset) {
+ CPU_ZERO(cpuset);
+#ifdef HAVE_SCHED_GETAFFINITY
+ return sched_getaffinity(0, sizeof(*cpuset), cpuset) == 0;
+#else
+ return 0;
+#endif
+}
+
+
+// Bind worker thread to specified CPU(s)
+// Args:
+// thread_mask: cpu_set_t representing CPUs, ie
+// mask = 1 (01b): cpu0
+// mask = 3 (11b): cpu0, 1
+// mask = 13 (1101b): cpu0, 2, 3
+//
+// Returns true on success, false otherwise.
+bool WorkerThread::BindToCpus(const cpu_set_t *thread_mask) {
+ cpu_set_t process_mask;
+ AvailableCpus(&process_mask);
+ if (cpuset_isequal(thread_mask, &process_mask))
+ return true;
+
+ logprintf(11, "Log: available CPU mask - %s\n",
+ cpuset_format(&process_mask).c_str());
+ if (!cpuset_issubset(thread_mask, &process_mask)) {
+ // Invalid cpu_mask, ie cpu not allocated to this process or doesn't exist.
+ logprintf(0, "Log: requested CPUs %s not a subset of available %s\n",
+ cpuset_format(thread_mask).c_str(),
+ cpuset_format(&process_mask).c_str());
+ return false;
+ }
+#ifdef HAVE_SCHED_GETAFFINITY
+ if (sat_->use_affinity()) {
+ return (sched_setaffinity(gettid(), sizeof(*thread_mask), thread_mask) == 0);
+ } else {
+ logprintf(11, "Log: Skipping CPU affinity set.\n");
+ }
+#endif
+ return true;
+}
+
+
+// A worker thread can yield itself to give up CPU until it's scheduled again.
+// Returns true on success, false on error.
+bool WorkerThread::YieldSelf() {
+ return (sched_yield() == 0);
+}
+
+
+// Fill this page with its pattern.
+bool WorkerThread::FillPage(struct page_entry *pe) {
+ // Error check arguments.
+ if (pe == 0) {
+ logprintf(0, "Process Error: Fill Page entry null\n");
+ return 0;
+ }
+
+ // Tag this page as written from the current CPU.
+ pe->lastcpu = sched_getcpu();
+
+ // Mask is the bitmask of indexes used by the pattern.
+ // It is the pattern size -1. Size is always a power of 2.
+ uint64 *memwords = static_cast<uint64*>(pe->addr);
+ int length = sat_->page_length();
+
+ if (tag_mode_) {
+ // Select tag or data as appropriate.
+ for (int i = 0; i < length / wordsize_; i++) {
+ datacast_t data;
+
+ if ((i & 0x7) == 0) {
+ data.l64 = addr_to_tag(&memwords[i]);
+ } else {
+ data.l32.l = pe->pattern->pattern(i << 1);
+ data.l32.h = pe->pattern->pattern((i << 1) + 1);
+ }
+ memwords[i] = data.l64;
+ }
+ } else {
+ // Just fill in untagged data directly.
+ for (int i = 0; i < length / wordsize_; i++) {
+ datacast_t data;
+
+ data.l32.l = pe->pattern->pattern(i << 1);
+ data.l32.h = pe->pattern->pattern((i << 1) + 1);
+ memwords[i] = data.l64;
+ }
+ }
+
+ return 1;
+}
+
+
+// Tell the thread how many pages to fill.
+void FillThread::SetFillPages(int64 num_pages_to_fill_init) {
+ num_pages_to_fill_ = num_pages_to_fill_init;
+}
+
+// Fill this page with a random pattern.
+bool FillThread::FillPageRandom(struct page_entry *pe) {
+ // Error check arguments.
+ if (pe == 0) {
+ logprintf(0, "Process Error: Fill Page entry null\n");
+ return 0;
+ }
+ if ((patternlist_ == 0) || (patternlist_->Size() == 0)) {
+ logprintf(0, "Process Error: No data patterns available\n");
+ return 0;
+ }
+
+ // Choose a random pattern for this block.
+ pe->pattern = patternlist_->GetRandomPattern();
+ pe->lastcpu = sched_getcpu();
+
+ if (pe->pattern == 0) {
+ logprintf(0, "Process Error: Null data pattern\n");
+ return 0;
+ }
+
+ // Actually fill the page.
+ return FillPage(pe);
+}
+
+
+// Memory fill work loop. Execute until alloted pages filled.
+bool FillThread::Work() {
+ bool result = true;
+
+ logprintf(9, "Log: Starting fill thread %d\n", thread_num_);
+
+ // We want to fill num_pages_to_fill pages, and
+ // stop when we've filled that many.
+ // We also want to capture early break
+ struct page_entry pe;
+ int64 loops = 0;
+ while (IsReadyToRun() && (loops < num_pages_to_fill_)) {
+ result = result && sat_->GetEmpty(&pe);
+ if (!result) {
+ logprintf(0, "Process Error: fill_thread failed to pop pages, "
+ "bailing\n");
+ break;
+ }
+
+ // Fill the page with pattern
+ result = result && FillPageRandom(&pe);
+ if (!result) break;
+
+ // Put the page back on the queue.
+ result = result && sat_->PutValid(&pe);
+ if (!result) {
+ logprintf(0, "Process Error: fill_thread failed to push pages, "
+ "bailing\n");
+ break;
+ }
+ loops++;
+ }
+
+ // Fill in thread status.
+ pages_copied_ = loops;
+ status_ = result;
+ logprintf(9, "Log: Completed %d: Fill thread. Status %d, %d pages filled\n",
+ thread_num_, status_, pages_copied_);
+ return result;
+}
+
+
+// Print error information about a data miscompare.
+void WorkerThread::ProcessError(struct ErrorRecord *error,
+ int priority,
+ const char *message) {
+ char dimm_string[256] = "";
+
+ int core_id = sched_getcpu();
+
+ // Determine if this is a write or read error.
+ os_->Flush(error->vaddr);
+ error->reread = *(error->vaddr);
+
+ char *good = reinterpret_cast<char*>(&(error->expected));
+ char *bad = reinterpret_cast<char*>(&(error->actual));
+
+ sat_assert(error->expected != error->actual);
+ unsigned int offset = 0;
+ for (offset = 0; offset < (sizeof(error->expected) - 1); offset++) {
+ if (good[offset] != bad[offset])
+ break;
+ }
+
+ error->vbyteaddr = reinterpret_cast<char*>(error->vaddr) + offset;
+
+ // Find physical address if possible.
+ error->paddr = os_->VirtualToPhysical(error->vbyteaddr);
+
+ // Pretty print DIMM mapping if available.
+ os_->FindDimm(error->paddr, dimm_string, sizeof(dimm_string));
+
+ // Report parseable error.
+ if (priority < 5) {
+ // Run miscompare error through diagnoser for logging and reporting.
+ os_->error_diagnoser_->AddMiscompareError(dimm_string,
+ reinterpret_cast<uint64>
+ (error->vaddr), 1);
+
+ logprintf(priority,
+ "%s: miscompare on CPU %d(<-%d) at %p(0x%llx:%s): "
+ "read:0x%016llx, reread:0x%016llx expected:0x%016llx. '%s'%s.\n",
+ message,
+ core_id,
+ error->lastcpu,
+ error->vaddr,
+ error->paddr,
+ dimm_string,
+ error->actual,
+ error->reread,
+ error->expected,
+ (error->patternname) ? error->patternname : "None",
+ (error->reread == error->expected) ? " read error" : "");
+ }
+
+
+ // Overwrite incorrect data with correct data to prevent
+ // future miscompares when this data is reused.
+ *(error->vaddr) = error->expected;
+ os_->Flush(error->vaddr);
+}
+
+
+
+// Print error information about a data miscompare.
+void FileThread::ProcessError(struct ErrorRecord *error,
+ int priority,
+ const char *message) {
+ char dimm_string[256] = "";
+
+ // Determine if this is a write or read error.
+ os_->Flush(error->vaddr);
+ error->reread = *(error->vaddr);
+
+ char *good = reinterpret_cast<char*>(&(error->expected));
+ char *bad = reinterpret_cast<char*>(&(error->actual));
+
+ sat_assert(error->expected != error->actual);
+ unsigned int offset = 0;
+ for (offset = 0; offset < (sizeof(error->expected) - 1); offset++) {
+ if (good[offset] != bad[offset])
+ break;
+ }
+
+ error->vbyteaddr = reinterpret_cast<char*>(error->vaddr) + offset;
+
+ // Find physical address if possible.
+ error->paddr = os_->VirtualToPhysical(error->vbyteaddr);
+
+ // Pretty print DIMM mapping if available.
+ os_->FindDimm(error->paddr, dimm_string, sizeof(dimm_string));
+
+ // If crc_page_ is valid, ie checking content read back from file,
+ // track src/dst memory addresses. Otherwise catagorize as general
+ // mememory miscompare for CRC checking everywhere else.
+ if (crc_page_ != -1) {
+ int miscompare_byteoffset = static_cast<char*>(error->vbyteaddr) -
+ static_cast<char*>(page_recs_[crc_page_].dst);
+ os_->error_diagnoser_->AddHDDMiscompareError(devicename_,
+ crc_page_,
+ miscompare_byteoffset,
+ page_recs_[crc_page_].src,
+ page_recs_[crc_page_].dst);
+ } else {
+ os_->error_diagnoser_->AddMiscompareError(dimm_string,
+ reinterpret_cast<uint64>
+ (error->vaddr), 1);
+ }
+
+ logprintf(priority,
+ "%s: miscompare on %s at %p(0x%llx:%s): read:0x%016llx, "
+ "reread:0x%016llx expected:0x%016llx\n",
+ message,
+ devicename_.c_str(),
+ error->vaddr,
+ error->paddr,
+ dimm_string,
+ error->actual,
+ error->reread,
+ error->expected,
+ (error->patternname) ? error->patternname : "None");
+
+ // Overwrite incorrect data with correct data to prevent
+ // future miscompares when this data is reused.
+ *(error->vaddr) = error->expected;
+ os_->Flush(error->vaddr);
+}
+
+
+// Do a word by word result check of a region.
+// Print errors on mismatches.
+int WorkerThread::CheckRegion(void *addr,
+ class Pattern *pattern,
+ uint32 lastcpu,
+ int64 length,
+ int offset,
+ int64 pattern_offset) {
+ uint64 *memblock = static_cast<uint64*>(addr);
+ const int kErrorLimit = 128;
+ int errors = 0;
+ int overflowerrors = 0; // Count of overflowed errors.
+ bool page_error = false;
+ string errormessage("Hardware Error");
+ struct ErrorRecord
+ recorded[kErrorLimit]; // Queued errors for later printing.
+
+ // For each word in the data region.
+ for (int i = 0; i < length / wordsize_; i++) {
+ uint64 actual = memblock[i];
+ uint64 expected;
+
+ // Determine the value that should be there.
+ datacast_t data;
+ int index = 2 * i + pattern_offset;
+ data.l32.l = pattern->pattern(index);
+ data.l32.h = pattern->pattern(index + 1);
+ expected = data.l64;
+ // Check tags if necessary.
+ if (tag_mode_ && ((reinterpret_cast<uint64>(&memblock[i]) & 0x3f) == 0)) {
+ expected = addr_to_tag(&memblock[i]);
+ }
+
+
+ // If the value is incorrect, save an error record for later printing.
+ if (actual != expected) {
+ if (errors < kErrorLimit) {
+ recorded[errors].actual = actual;
+ recorded[errors].expected = expected;
+ recorded[errors].vaddr = &memblock[i];
+ recorded[errors].patternname = pattern->name();
+ recorded[errors].lastcpu = lastcpu;
+ errors++;
+ } else {
+ page_error = true;
+ // If we have overflowed the error queue, just print the errors now.
+ logprintf(10, "Log: Error record overflow, too many miscompares!\n");
+ errormessage = "Page Error";
+ break;
+ }
+ }
+ }
+
+ // Find if this is a whole block corruption.
+ if (page_error && !tag_mode_) {
+ int patsize = patternlist_->Size();
+ for (int pat = 0; pat < patsize; pat++) {
+ class Pattern *altpattern = patternlist_->GetPattern(pat);
+ const int kGood = 0;
+ const int kBad = 1;
+ const int kGoodAgain = 2;
+ const int kNoMatch = 3;
+ int state = kGood;
+ unsigned int badstart = 0;
+ unsigned int badend = 0;
+
+ // Don't match against ourself!
+ if (pattern == altpattern)
+ continue;
+
+ for (int i = 0; i < length / wordsize_; i++) {
+ uint64 actual = memblock[i];
+ datacast_t expected;
+ datacast_t possible;
+
+ // Determine the value that should be there.
+ int index = 2 * i + pattern_offset;
+
+ expected.l32.l = pattern->pattern(index);
+ expected.l32.h = pattern->pattern(index + 1);
+
+ possible.l32.l = pattern->pattern(index);
+ possible.l32.h = pattern->pattern(index + 1);
+
+ if (state == kGood) {
+ if (actual == expected.l64) {
+ continue;
+ } else if (actual == possible.l64) {
+ badstart = i;
+ badend = i;
+ state = kBad;
+ continue;
+ } else {
+ state = kNoMatch;
+ break;
+ }
+ } else if (state == kBad) {
+ if (actual == possible.l64) {
+ badend = i;
+ continue;
+ } else if (actual == expected.l64) {
+ state = kGoodAgain;
+ continue;
+ } else {
+ state = kNoMatch;
+ break;
+ }
+ } else if (state == kGoodAgain) {
+ if (actual == expected.l64) {
+ continue;
+ } else {
+ state = kNoMatch;
+ break;
+ }
+ }
+ }
+
+ if ((state == kGoodAgain) || (state == kBad)) {
+ unsigned int blockerrors = badend - badstart + 1;
+ errormessage = "Block Error";
+ // It's okay for the 1st entry to be corrected multiple times,
+ // it will simply be reported twice. Once here and once below
+ // when processing the error queue.
+ ProcessError(&recorded[0], 0, errormessage.c_str());
+ logprintf(0, "Block Error: (%p) pattern %s instead of %s, "
+ "%d bytes from offset 0x%x to 0x%x\n",
+ &memblock[badstart],
+ altpattern->name(), pattern->name(),
+ blockerrors * wordsize_,
+ offset + badstart * wordsize_,
+ offset + badend * wordsize_);
+ }
+ }
+ }
+
+
+ // Process error queue after all errors have been recorded.
+ for (int err = 0; err < errors; err++) {
+ int priority = 5;
+ if (errorcount_ + err < 30)
+ priority = 0; // Bump up the priority for the first few errors.
+ ProcessError(&recorded[err], priority, errormessage.c_str());
+ }
+
+ if (page_error) {
+ // For each word in the data region.
+ for (int i = 0; i < length / wordsize_; i++) {
+ uint64 actual = memblock[i];
+ uint64 expected;
+ datacast_t data;
+ // Determine the value that should be there.
+ int index = 2 * i + pattern_offset;
+
+ data.l32.l = pattern->pattern(index);
+ data.l32.h = pattern->pattern(index + 1);
+ expected = data.l64;
+
+ // Check tags if necessary.
+ if (tag_mode_ && ((reinterpret_cast<uint64>(&memblock[i]) & 0x3f) == 0)) {
+ expected = addr_to_tag(&memblock[i]);
+ }
+
+ // If the value is incorrect, save an error record for later printing.
+ if (actual != expected) {
+ // If we have overflowed the error queue, print the errors now.
+ struct ErrorRecord er;
+ er.actual = actual;
+ er.expected = expected;
+ er.vaddr = &memblock[i];
+
+ // Do the error printout. This will take a long time and
+ // likely change the machine state.
+ ProcessError(&er, 12, errormessage.c_str());
+ overflowerrors++;
+ }
+ }
+ }
+
+ // Keep track of observed errors.
+ errorcount_ += errors + overflowerrors;
+ return errors + overflowerrors;
+}
+
+float WorkerThread::GetCopiedData() {
+ return pages_copied_ * sat_->page_length() / kMegabyte;
+}
+
+// Calculate the CRC of a region.
+// Result check if the CRC mismatches.
+int WorkerThread::CrcCheckPage(struct page_entry *srcpe) {
+ const int blocksize = 4096;
+ const int blockwords = blocksize / wordsize_;
+ int errors = 0;
+
+ const AdlerChecksum *expectedcrc = srcpe->pattern->crc();
+ uint64 *memblock = static_cast<uint64*>(srcpe->addr);
+ int blocks = sat_->page_length() / blocksize;
+ for (int currentblock = 0; currentblock < blocks; currentblock++) {
+ uint64 *memslice = memblock + currentblock * blockwords;
+
+ AdlerChecksum crc;
+ if (tag_mode_) {
+ AdlerAddrCrcC(memslice, blocksize, &crc, srcpe);
+ } else {
+ CalculateAdlerChecksum(memslice, blocksize, &crc);
+ }
+
+ // If the CRC does not match, we'd better look closer.
+ if (!crc.Equals(*expectedcrc)) {
+ logprintf(11, "Log: CrcCheckPage Falling through to slow compare, "
+ "CRC mismatch %s != %s\n",
+ crc.ToHexString().c_str(),
+ expectedcrc->ToHexString().c_str());
+ int errorcount = CheckRegion(memslice,
+ srcpe->pattern,
+ srcpe->lastcpu,
+ blocksize,
+ currentblock * blocksize, 0);
+ if (errorcount == 0) {
+ logprintf(0, "Log: CrcCheckPage CRC mismatch %s != %s, "
+ "but no miscompares found.\n",
+ crc.ToHexString().c_str(),
+ expectedcrc->ToHexString().c_str());
+ }
+ errors += errorcount;
+ }
+ }
+
+ // For odd length transfers, we should never hit this.
+ int leftovers = sat_->page_length() % blocksize;
+ if (leftovers) {
+ uint64 *memslice = memblock + blocks * blockwords;
+ errors += CheckRegion(memslice,
+ srcpe->pattern,
+ srcpe->lastcpu,
+ leftovers,
+ blocks * blocksize, 0);
+ }
+ return errors;
+}
+
+
+// Print error information about a data miscompare.
+void WorkerThread::ProcessTagError(struct ErrorRecord *error,
+ int priority,
+ const char *message) {
+ char dimm_string[256] = "";
+ char tag_dimm_string[256] = "";
+ bool read_error = false;
+
+ int core_id = sched_getcpu();
+
+ // Determine if this is a write or read error.
+ os_->Flush(error->vaddr);
+ error->reread = *(error->vaddr);
+
+ // Distinguish read and write errors.
+ if (error->actual != error->reread) {
+ read_error = true;
+ }
+
+ sat_assert(error->expected != error->actual);
+
+ error->vbyteaddr = reinterpret_cast<char*>(error->vaddr);
+
+ // Find physical address if possible.
+ error->paddr = os_->VirtualToPhysical(error->vbyteaddr);
+ error->tagpaddr = os_->VirtualToPhysical(error->tagvaddr);
+
+ // Pretty print DIMM mapping if available.
+ os_->FindDimm(error->paddr, dimm_string, sizeof(dimm_string));
+ // Pretty print DIMM mapping if available.
+ os_->FindDimm(error->tagpaddr, tag_dimm_string, sizeof(tag_dimm_string));
+
+ // Report parseable error.
+ if (priority < 5) {
+ logprintf(priority,
+ "%s: Tag from %p(0x%llx:%s) (%s) "
+ "miscompare on CPU %d(0x%s) at %p(0x%llx:%s): "
+ "read:0x%016llx, reread:0x%016llx expected:0x%016llx\n",
+ message,
+ error->tagvaddr, error->tagpaddr,
+ tag_dimm_string,
+ read_error ? "read error" : "write error",
+ core_id,
+ CurrentCpusFormat().c_str(),
+ error->vaddr,
+ error->paddr,
+ dimm_string,
+ error->actual,
+ error->reread,
+ error->expected);
+ }
+
+ errorcount_ += 1;
+
+ // Overwrite incorrect data with correct data to prevent
+ // future miscompares when this data is reused.
+ *(error->vaddr) = error->expected;
+ os_->Flush(error->vaddr);
+}
+
+
+// Print out and log a tag error.
+bool WorkerThread::ReportTagError(
+ uint64 *mem64,
+ uint64 actual,
+ uint64 tag) {
+ struct ErrorRecord er;
+ er.actual = actual;
+
+ er.expected = tag;
+ er.vaddr = mem64;
+
+ // Generate vaddr from tag.
+ er.tagvaddr = reinterpret_cast<uint64*>(actual);
+
+ ProcessTagError(&er, 0, "Hardware Error");
+ return true;
+}
+
+// C implementation of Adler memory copy, with memory tagging.
+bool WorkerThread::AdlerAddrMemcpyC(uint64 *dstmem64,
+ uint64 *srcmem64,
+ unsigned int size_in_bytes,
+ AdlerChecksum *checksum,
+ struct page_entry *pe) {
+ // Use this data wrapper to access memory with 64bit read/write.
+ datacast_t data;
+ datacast_t dstdata;
+ unsigned int count = size_in_bytes / sizeof(data);
+
+ if (count > ((1U) << 19)) {
+ // Size is too large, must be strictly less than 512 KB.
+ return false;
+ }
+
+ uint64 a1 = 1;
+ uint64 a2 = 1;
+ uint64 b1 = 0;
+ uint64 b2 = 0;
+
+ class Pattern *pattern = pe->pattern;
+
+ unsigned int i = 0;
+ while (i < count) {
+ // Process 64 bits at a time.
+ if ((i & 0x7) == 0) {
+ data.l64 = srcmem64[i];
+ dstdata.l64 = dstmem64[i];
+ uint64 src_tag = addr_to_tag(&srcmem64[i]);
+ uint64 dst_tag = addr_to_tag(&dstmem64[i]);
+ // Detect if tags have been corrupted.
+ if (data.l64 != src_tag)
+ ReportTagError(&srcmem64[i], data.l64, src_tag);
+ if (dstdata.l64 != dst_tag)
+ ReportTagError(&dstmem64[i], dstdata.l64, dst_tag);
+
+ data.l32.l = pattern->pattern(i << 1);
+ data.l32.h = pattern->pattern((i << 1) + 1);
+ a1 = a1 + data.l32.l;
+ b1 = b1 + a1;
+ a1 = a1 + data.l32.h;
+ b1 = b1 + a1;
+
+ data.l64 = dst_tag;
+ dstmem64[i] = data.l64;
+
+ } else {
+ data.l64 = srcmem64[i];
+ a1 = a1 + data.l32.l;
+ b1 = b1 + a1;
+ a1 = a1 + data.l32.h;
+ b1 = b1 + a1;
+ dstmem64[i] = data.l64;
+ }
+ i++;
+
+ data.l64 = srcmem64[i];
+ a2 = a2 + data.l32.l;
+ b2 = b2 + a2;
+ a2 = a2 + data.l32.h;
+ b2 = b2 + a2;
+ dstmem64[i] = data.l64;
+ i++;
+ }
+ checksum->Set(a1, a2, b1, b2);
+ return true;
+}
+
+// x86_64 SSE2 assembly implementation of Adler memory copy, with address
+// tagging added as a second step. This is useful for debugging failures
+// that only occur when SSE / nontemporal writes are used.
+bool WorkerThread::AdlerAddrMemcpyWarm(uint64 *dstmem64,
+ uint64 *srcmem64,
+ unsigned int size_in_bytes,
+ AdlerChecksum *checksum,
+ struct page_entry *pe) {
+ // Do ASM copy, ignore checksum.
+ AdlerChecksum ignored_checksum;
+ os_->AdlerMemcpyWarm(dstmem64, srcmem64, size_in_bytes, &ignored_checksum);
+
+ // Force cache flush of both the source and destination addresses.
+ // length - length of block to flush in cachelines.
+ // mem_increment - number of dstmem/srcmem values per cacheline.
+ int length = size_in_bytes / kCacheLineSize;
+ int mem_increment = kCacheLineSize / sizeof(*dstmem64);
+ OsLayer::FastFlushSync();
+ for (int i = 0; i < length; ++i) {
+ OsLayer::FastFlushHint(dstmem64 + (i * mem_increment));
+ OsLayer::FastFlushHint(srcmem64 + (i * mem_increment));
+ }
+ OsLayer::FastFlushSync();
+
+ // Check results.
+ AdlerAddrCrcC(srcmem64, size_in_bytes, checksum, pe);
+ // Patch up address tags.
+ TagAddrC(dstmem64, size_in_bytes);
+ return true;
+}
+
+// Retag pages..
+bool WorkerThread::TagAddrC(uint64 *memwords,
+ unsigned int size_in_bytes) {
+ // Mask is the bitmask of indexes used by the pattern.
+ // It is the pattern size -1. Size is always a power of 2.
+
+ // Select tag or data as appropriate.
+ int length = size_in_bytes / wordsize_;
+ for (int i = 0; i < length; i += 8) {
+ datacast_t data;
+ data.l64 = addr_to_tag(&memwords[i]);
+ memwords[i] = data.l64;
+ }
+ return true;
+}
+
+// C implementation of Adler memory crc.
+bool WorkerThread::AdlerAddrCrcC(uint64 *srcmem64,
+ unsigned int size_in_bytes,
+ AdlerChecksum *checksum,
+ struct page_entry *pe) {
+ // Use this data wrapper to access memory with 64bit read/write.
+ datacast_t data;
+ unsigned int count = size_in_bytes / sizeof(data);
+
+ if (count > ((1U) << 19)) {
+ // Size is too large, must be strictly less than 512 KB.
+ return false;
+ }
+
+ uint64 a1 = 1;
+ uint64 a2 = 1;
+ uint64 b1 = 0;
+ uint64 b2 = 0;
+
+ class Pattern *pattern = pe->pattern;
+
+ unsigned int i = 0;
+ while (i < count) {
+ // Process 64 bits at a time.
+ if ((i & 0x7) == 0) {
+ data.l64 = srcmem64[i];
+ uint64 src_tag = addr_to_tag(&srcmem64[i]);
+ // Check that tags match expected.
+ if (data.l64 != src_tag)
+ ReportTagError(&srcmem64[i], data.l64, src_tag);
+
+ data.l32.l = pattern->pattern(i << 1);
+ data.l32.h = pattern->pattern((i << 1) + 1);
+ a1 = a1 + data.l32.l;
+ b1 = b1 + a1;
+ a1 = a1 + data.l32.h;
+ b1 = b1 + a1;
+ } else {
+ data.l64 = srcmem64[i];
+ a1 = a1 + data.l32.l;
+ b1 = b1 + a1;
+ a1 = a1 + data.l32.h;
+ b1 = b1 + a1;
+ }
+ i++;
+
+ data.l64 = srcmem64[i];
+ a2 = a2 + data.l32.l;
+ b2 = b2 + a2;
+ a2 = a2 + data.l32.h;
+ b2 = b2 + a2;
+ i++;
+ }
+ checksum->Set(a1, a2, b1, b2);
+ return true;
+}
+
+// Copy a block of memory quickly, while keeping a CRC of the data.
+// Result check if the CRC mismatches.
+int WorkerThread::CrcCopyPage(struct page_entry *dstpe,
+ struct page_entry *srcpe) {
+ int errors = 0;
+ const int blocksize = 4096;
+ const int blockwords = blocksize / wordsize_;
+ int blocks = sat_->page_length() / blocksize;
+
+ // Base addresses for memory copy
+ uint64 *targetmembase = static_cast<uint64*>(dstpe->addr);
+ uint64 *sourcemembase = static_cast<uint64*>(srcpe->addr);
+ // Remember the expected CRC
+ const AdlerChecksum *expectedcrc = srcpe->pattern->crc();
+
+ for (int currentblock = 0; currentblock < blocks; currentblock++) {
+ uint64 *targetmem = targetmembase + currentblock * blockwords;
+ uint64 *sourcemem = sourcemembase + currentblock * blockwords;
+
+ AdlerChecksum crc;
+ if (tag_mode_) {
+ AdlerAddrMemcpyC(targetmem, sourcemem, blocksize, &crc, srcpe);
+ } else {
+ AdlerMemcpyC(targetmem, sourcemem, blocksize, &crc);
+ }
+
+ // Investigate miscompares.
+ if (!crc.Equals(*expectedcrc)) {
+ logprintf(11, "Log: CrcCopyPage Falling through to slow compare, "
+ "CRC mismatch %s != %s\n", crc.ToHexString().c_str(),
+ expectedcrc->ToHexString().c_str());
+ int errorcount = CheckRegion(sourcemem,
+ srcpe->pattern,
+ srcpe->lastcpu,
+ blocksize,
+ currentblock * blocksize, 0);
+ if (errorcount == 0) {
+ logprintf(0, "Log: CrcCopyPage CRC mismatch %s != %s, "
+ "but no miscompares found. Retrying with fresh data.\n",
+ crc.ToHexString().c_str(),
+ expectedcrc->ToHexString().c_str());
+ if (!tag_mode_) {
+ // Copy the data originally read from this region back again.
+ // This data should have any corruption read originally while
+ // calculating the CRC.
+ memcpy(sourcemem, targetmem, blocksize);
+ errorcount = CheckRegion(sourcemem,
+ srcpe->pattern,
+ srcpe->lastcpu,
+ blocksize,
+ currentblock * blocksize, 0);
+ if (errorcount == 0) {
+ int core_id = sched_getcpu();
+ logprintf(0, "Process Error: CPU %d(0x%s) CrcCopyPage "
+ "CRC mismatch %s != %s, "
+ "but no miscompares found on second pass.\n",
+ core_id, CurrentCpusFormat().c_str(),
+ crc.ToHexString().c_str(),
+ expectedcrc->ToHexString().c_str());
+ struct ErrorRecord er;
+ er.actual = sourcemem[0];
+ er.expected = 0xbad00000ull << 32;
+ er.vaddr = sourcemem;
+ er.lastcpu = srcpe->lastcpu;
+ logprintf(0, "Process Error: lastCPU %d\n", srcpe->lastcpu);
+ er.patternname = srcpe->pattern->name();
+ ProcessError(&er, 0, "Hardware Error");
+ errors += 1;
+ errorcount_ ++;
+ }
+ }
+ }
+ errors += errorcount;
+ }
+ }
+
+ // For odd length transfers, we should never hit this.
+ int leftovers = sat_->page_length() % blocksize;
+ if (leftovers) {
+ uint64 *targetmem = targetmembase + blocks * blockwords;
+ uint64 *sourcemem = sourcemembase + blocks * blockwords;
+
+ errors += CheckRegion(sourcemem,
+ srcpe->pattern,
+ srcpe->lastcpu,
+ leftovers,
+ blocks * blocksize, 0);
+ int leftoverwords = leftovers / wordsize_;
+ for (int i = 0; i < leftoverwords; i++) {
+ targetmem[i] = sourcemem[i];
+ }
+ }
+
+ // Update pattern reference to reflect new contents.
+ dstpe->pattern = srcpe->pattern;
+ dstpe->lastcpu = sched_getcpu();
+
+ // Clean clean clean the errors away.
+ if (errors) {
+ // TODO(nsanders): Maybe we should patch rather than fill? Filling may
+ // cause bad data to be propogated across the page.
+ FillPage(dstpe);
+ }
+ return errors;
+}
+
+
+
+// Invert a block of memory quickly, traversing downwards.
+int InvertThread::InvertPageDown(struct page_entry *srcpe) {
+ const int invert_flush_interval = kCacheLineSize / sizeof(unsigned int);
+ const int blocksize = 4096;
+ const int blockwords = blocksize / wordsize_;
+ int blocks = sat_->page_length() / blocksize;
+
+ // Base addresses for memory copy
+ unsigned int* iter = static_cast<unsigned int *>(srcpe->addr) + (blocks * blockwords);
+ unsigned int* rend = static_cast<unsigned int *>(srcpe->addr);
+
+ OsLayer::FastFlushSync();
+ while(iter != rend) {
+ for(int i = 0; i < invert_flush_interval; ++i) {
+ --iter;
+ *iter = ~(*iter);
+ }
+ OsLayer::FastFlushHint(iter);
+ }
+ OsLayer::FastFlushSync();
+ srcpe->lastcpu = sched_getcpu();
+ return 0;
+}
+
+// Invert a block of memory, traversing upwards.
+int InvertThread::InvertPageUp(struct page_entry *srcpe) {
+ const int invert_flush_interval = kCacheLineSize / sizeof(unsigned int);
+ const int blocksize = 4096;
+ const int blockwords = blocksize / wordsize_;
+ int blocks = sat_->page_length() / blocksize;
+
+ // Base addresses for memory copy
+ unsigned int* iter = static_cast<unsigned int *>(srcpe->addr);
+ unsigned int* end = static_cast<unsigned int *>(srcpe->addr) + (blocks * blockwords);
+
+ OsLayer::FastFlushSync();
+ while(iter != end) {
+ for(int i = 0; i < invert_flush_interval; ++i) {
+ *iter = ~(*iter);
+ ++iter;
+ }
+ OsLayer::FastFlushHint(iter - invert_flush_interval);
+ }
+ OsLayer::FastFlushSync();
+
+ srcpe->lastcpu = sched_getcpu();
+ return 0;
+}
+
+// Copy a block of memory quickly, while keeping a CRC of the data.
+// Result check if the CRC mismatches. Warm the CPU while running
+int WorkerThread::CrcWarmCopyPage(struct page_entry *dstpe,
+ struct page_entry *srcpe) {
+ int errors = 0;
+ const int blocksize = 4096;
+ const int blockwords = blocksize / wordsize_;
+ int blocks = sat_->page_length() / blocksize;
+
+ // Base addresses for memory copy
+ uint64 *targetmembase = static_cast<uint64*>(dstpe->addr);
+ uint64 *sourcemembase = static_cast<uint64*>(srcpe->addr);
+ // Remember the expected CRC
+ const AdlerChecksum *expectedcrc = srcpe->pattern->crc();
+
+ for (int currentblock = 0; currentblock < blocks; currentblock++) {
+ uint64 *targetmem = targetmembase + currentblock * blockwords;
+ uint64 *sourcemem = sourcemembase + currentblock * blockwords;
+
+ AdlerChecksum crc;
+ if (tag_mode_) {
+ AdlerAddrMemcpyWarm(targetmem, sourcemem, blocksize, &crc, srcpe);
+ } else {
+ os_->AdlerMemcpyWarm(targetmem, sourcemem, blocksize, &crc);
+ }
+
+ // Investigate miscompares.
+ if (!crc.Equals(*expectedcrc)) {
+ logprintf(11, "Log: CrcWarmCopyPage Falling through to slow compare, "
+ "CRC mismatch %s != %s\n", crc.ToHexString().c_str(),
+ expectedcrc->ToHexString().c_str());
+ int errorcount = CheckRegion(sourcemem,
+ srcpe->pattern,
+ srcpe->lastcpu,
+ blocksize,
+ currentblock * blocksize, 0);
+ if (errorcount == 0) {
+ logprintf(0, "Log: CrcWarmCopyPage CRC mismatch expected: %s != actual: %s, "
+ "but no miscompares found. Retrying with fresh data.\n",
+ expectedcrc->ToHexString().c_str(),
+ crc.ToHexString().c_str() );
+ if (!tag_mode_) {
+ // Copy the data originally read from this region back again.
+ // This data should have any corruption read originally while
+ // calculating the CRC.
+ memcpy(sourcemem, targetmem, blocksize);
+ errorcount = CheckRegion(sourcemem,
+ srcpe->pattern,
+ srcpe->lastcpu,
+ blocksize,
+ currentblock * blocksize, 0);
+ if (errorcount == 0) {
+ int core_id = sched_getcpu();
+ logprintf(0, "Process Error: CPU %d(0x%s) CrciWarmCopyPage "
+ "CRC mismatch %s != %s, "
+ "but no miscompares found on second pass.\n",
+ core_id, CurrentCpusFormat().c_str(),
+ crc.ToHexString().c_str(),
+ expectedcrc->ToHexString().c_str());
+ struct ErrorRecord er;
+ er.actual = sourcemem[0];
+ er.expected = 0xbad;
+ er.vaddr = sourcemem;
+ er.lastcpu = srcpe->lastcpu;
+ er.patternname = srcpe->pattern->name();
+ ProcessError(&er, 0, "Hardware Error");
+ errors ++;
+ errorcount_ ++;
+ }
+ }
+ }
+ errors += errorcount;
+ }
+ }
+
+ // For odd length transfers, we should never hit this.
+ int leftovers = sat_->page_length() % blocksize;
+ if (leftovers) {
+ uint64 *targetmem = targetmembase + blocks * blockwords;
+ uint64 *sourcemem = sourcemembase + blocks * blockwords;
+
+ errors += CheckRegion(sourcemem,
+ srcpe->pattern,
+ srcpe->lastcpu,
+ leftovers,
+ blocks * blocksize, 0);
+ int leftoverwords = leftovers / wordsize_;
+ for (int i = 0; i < leftoverwords; i++) {
+ targetmem[i] = sourcemem[i];
+ }
+ }
+
+ // Update pattern reference to reflect new contents.
+ dstpe->pattern = srcpe->pattern;
+ dstpe->lastcpu = sched_getcpu();
+
+
+ // Clean clean clean the errors away.
+ if (errors) {
+ // TODO(nsanders): Maybe we should patch rather than fill? Filling may
+ // cause bad data to be propogated across the page.
+ FillPage(dstpe);
+ }
+ return errors;
+}
+
+
+
+// Memory check work loop. Execute until done, then exhaust pages.
+bool CheckThread::Work() {
+ struct page_entry pe;
+ bool result = true;
+ int64 loops = 0;
+
+ logprintf(9, "Log: Starting Check thread %d\n", thread_num_);
+
+ // We want to check all the pages, and
+ // stop when there aren't any left.
+ while (true) {
+ result = result && sat_->GetValid(&pe);
+ if (!result) {
+ if (IsReadyToRunNoPause())
+ logprintf(0, "Process Error: check_thread failed to pop pages, "
+ "bailing\n");
+ else
+ result = true;
+ break;
+ }
+
+ // Do the result check.
+ CrcCheckPage(&pe);
+
+ // Push pages back on the valid queue if we are still going,
+ // throw them out otherwise.
+ if (IsReadyToRunNoPause())
+ result = result && sat_->PutValid(&pe);
+ else
+ result = result && sat_->PutEmpty(&pe);
+ if (!result) {
+ logprintf(0, "Process Error: check_thread failed to push pages, "
+ "bailing\n");
+ break;
+ }
+ loops++;
+ }
+
+ pages_copied_ = loops;
+ status_ = result;
+ logprintf(9, "Log: Completed %d: Check thread. Status %d, %d pages checked\n",
+ thread_num_, status_, pages_copied_);
+ return result;
+}
+
+
+// Memory copy work loop. Execute until marked done.
+bool CopyThread::Work() {
+ struct page_entry src;
+ struct page_entry dst;
+ bool result = true;
+ int64 loops = 0;
+
+ logprintf(9, "Log: Starting copy thread %d: cpu %s, "
+ "mem %x, warm: %d, has_vector: %d\n",
+ thread_num_, cpuset_format(&cpu_mask_).c_str(), tag_,
+ sat_->warm(), os_->has_vector());
+
+ while (IsReadyToRun()) {
+ // Pop the needed pages.
+ result = result && sat_->GetValid(&src, tag_);
+ result = result && sat_->GetEmpty(&dst, tag_);
+ if (!result) {
+ logprintf(0, "Process Error: copy_thread failed to pop pages, "
+ "bailing\n");
+ break;
+ }
+
+ // Force errors for unittests.
+ if (sat_->error_injection()) {
+ if ((random() % 50000) == 8) {
+ char *addr = reinterpret_cast<char*>(src.addr);
+ int offset = random() % sat_->page_length();
+ addr[offset] = 0xba;
+ }
+ }
+
+ // We can use memcpy, or CRC check while we copy.
+ if (sat_->warm()) {
+ CrcWarmCopyPage(&dst, &src);
+ } else if (sat_->strict()) {
+ CrcCopyPage(&dst, &src);
+ } else {
+ memcpy(dst.addr, src.addr, sat_->page_length());
+ dst.pattern = src.pattern;
+ dst.lastcpu = sched_getcpu();
+ }
+
+ result = result && sat_->PutValid(&dst);
+ result = result && sat_->PutEmpty(&src);
+
+ // Copy worker-threads yield themselves at the end of each copy loop,
+ // to avoid threads from preempting each other in the middle of the inner
+ // copy-loop. Cooperations between Copy worker-threads results in less
+ // unnecessary cache thrashing (which happens when context-switching in the
+ // middle of the inner copy-loop).
+ YieldSelf();
+
+ if (!result) {
+ logprintf(0, "Process Error: copy_thread failed to push pages, "
+ "bailing\n");
+ break;
+ }
+ loops++;
+ }
+
+ pages_copied_ = loops;
+ status_ = result;
+ logprintf(9, "Log: Completed %d: Copy thread. Status %d, %d pages copied\n",
+ thread_num_, status_, pages_copied_);
+ return result;
+}
+
+// Memory invert work loop. Execute until marked done.
+bool InvertThread::Work() {
+ struct page_entry src;
+ bool result = true;
+ int64 loops = 0;
+
+ logprintf(9, "Log: Starting invert thread %d\n", thread_num_);
+
+ while (IsReadyToRun()) {
+ // Pop the needed pages.
+ result = result && sat_->GetValid(&src);
+ if (!result) {
+ logprintf(0, "Process Error: invert_thread failed to pop pages, "
+ "bailing\n");
+ break;
+ }
+
+ if (sat_->strict())
+ CrcCheckPage(&src);
+
+ // For the same reason CopyThread yields itself (see YieldSelf comment
+ // in CopyThread::Work(), InvertThread yields itself after each invert
+ // operation to improve cooperation between different worker threads
+ // stressing the memory/cache.
+ InvertPageUp(&src);
+ YieldSelf();
+ InvertPageDown(&src);
+ YieldSelf();
+ InvertPageDown(&src);
+ YieldSelf();
+ InvertPageUp(&src);
+ YieldSelf();
+
+ if (sat_->strict())
+ CrcCheckPage(&src);
+
+ result = result && sat_->PutValid(&src);
+ if (!result) {
+ logprintf(0, "Process Error: invert_thread failed to push pages, "
+ "bailing\n");
+ break;
+ }
+ loops++;
+ }
+
+ pages_copied_ = loops * 2;
+ status_ = result;
+ logprintf(9, "Log: Completed %d: Copy thread. Status %d, %d pages copied\n",
+ thread_num_, status_, pages_copied_);
+ return result;
+}
+
+
+// Set file name to use for File IO.
+void FileThread::SetFile(const char *filename_init) {
+ filename_ = filename_init;
+ devicename_ = os_->FindFileDevice(filename_);
+}
+
+// Open the file for access.
+bool FileThread::OpenFile(int *pfile) {
+ int flags = O_RDWR | O_CREAT | O_SYNC;
+ int fd = open(filename_.c_str(), flags | O_DIRECT, 0644);
+ if (O_DIRECT != 0 && fd < 0 && errno == EINVAL) {
+ fd = open(filename_.c_str(), flags, 0644); // Try without O_DIRECT
+ os_->ActivateFlushPageCache(); // Not using O_DIRECT fixed EINVAL
+ }
+ if (fd < 0) {
+ logprintf(0, "Process Error: Failed to create file %s!!\n",
+ filename_.c_str());
+ pages_copied_ = 0;
+ return false;
+ }
+ *pfile = fd;
+ return true;
+}
+
+// Close the file.
+bool FileThread::CloseFile(int fd) {
+ close(fd);
+ return true;
+}
+
+// Check sector tagging.
+bool FileThread::SectorTagPage(struct page_entry *src, int block) {
+ int page_length = sat_->page_length();
+ struct FileThread::SectorTag *tag =
+ (struct FileThread::SectorTag *)(src->addr);
+
+ // Tag each sector.
+ unsigned char magic = ((0xba + thread_num_) & 0xff);
+ for (int sec = 0; sec < page_length / 512; sec++) {
+ tag[sec].magic = magic;
+ tag[sec].block = block & 0xff;
+ tag[sec].sector = sec & 0xff;
+ tag[sec].pass = pass_ & 0xff;
+ }
+ return true;
+}
+
+bool FileThread::WritePageToFile(int fd, struct page_entry *src) {
+ int page_length = sat_->page_length();
+ // Fill the file with our data.
+ int64 size = write(fd, src->addr, page_length);
+
+ if (size != page_length) {
+ os_->ErrorReport(devicename_.c_str(), "write-error", 1);
+ errorcount_++;
+ logprintf(0, "Block Error: file_thread failed to write, "
+ "bailing\n");
+ return false;
+ }
+ return true;
+}
+
+// Write the data to the file.
+bool FileThread::WritePages(int fd) {
+ int strict = sat_->strict();
+
+ // Start fresh at beginning of file for each batch of pages.
+ lseek(fd, 0, SEEK_SET);
+ for (int i = 0; i < sat_->disk_pages(); i++) {
+ struct page_entry src;
+ if (!GetValidPage(&src))
+ return false;
+ // Save expected pattern.
+ page_recs_[i].pattern = src.pattern;
+ page_recs_[i].src = src.addr;
+
+ // Check data correctness.
+ if (strict)
+ CrcCheckPage(&src);
+
+ SectorTagPage(&src, i);
+
+ bool result = WritePageToFile(fd, &src);
+
+ if (!PutEmptyPage(&src))
+ return false;
+
+ if (!result)
+ return false;
+ }
+ return os_->FlushPageCache(); // If O_DIRECT worked, this will be a NOP.
+}
+
+// Copy data from file into memory block.
+bool FileThread::ReadPageFromFile(int fd, struct page_entry *dst) {
+ int page_length = sat_->page_length();
+
+ // Do the actual read.
+ int64 size = read(fd, dst->addr, page_length);
+ if (size != page_length) {
+ os_->ErrorReport(devicename_.c_str(), "read-error", 1);
+ logprintf(0, "Block Error: file_thread failed to read, "
+ "bailing\n");
+ errorcount_++;
+ return false;
+ }
+ return true;
+}
+
+// Check sector tagging.
+bool FileThread::SectorValidatePage(const struct PageRec &page,
+ struct page_entry *dst, int block) {
+ // Error injection.
+ static int calls = 0;
+ calls++;
+
+ // Do sector tag compare.
+ int firstsector = -1;
+ int lastsector = -1;
+ bool badsector = false;
+ int page_length = sat_->page_length();
+
+ // Cast data block into an array of tagged sectors.
+ struct FileThread::SectorTag *tag =
+ (struct FileThread::SectorTag *)(dst->addr);
+
+ sat_assert(sizeof(*tag) == 512);
+
+ // Error injection.
+ if (sat_->error_injection()) {
+ if (calls == 2) {
+ for (int badsec = 8; badsec < 17; badsec++)
+ tag[badsec].pass = 27;
+ }
+ if (calls == 18) {
+ (static_cast<int32*>(dst->addr))[27] = 0xbadda7a;
+ }
+ }
+
+ // Check each sector for the correct tag we added earlier,
+ // then revert the tag to the to normal data pattern.
+ unsigned char magic = ((0xba + thread_num_) & 0xff);
+ for (int sec = 0; sec < page_length / 512; sec++) {
+ // Check magic tag.
+ if ((tag[sec].magic != magic) ||
+ (tag[sec].block != (block & 0xff)) ||
+ (tag[sec].sector != (sec & 0xff)) ||
+ (tag[sec].pass != (pass_ & 0xff))) {
+ // Offset calculation for tag location.
+ int offset = sec * sizeof(SectorTag);
+ if (tag[sec].block != (block & 0xff))
+ offset += 1 * sizeof(uint8);
+ else if (tag[sec].sector != (sec & 0xff))
+ offset += 2 * sizeof(uint8);
+ else if (tag[sec].pass != (pass_ & 0xff))
+ offset += 3 * sizeof(uint8);
+
+ // Run sector tag error through diagnoser for logging and reporting.
+ errorcount_ += 1;
+ os_->error_diagnoser_->AddHDDSectorTagError(devicename_, tag[sec].block,
+ offset,
+ tag[sec].sector,
+ page.src, page.dst);
+
+ errorcount_ += 1;
+ logprintf(5, "Sector Error: Sector tag @ 0x%x, pass %d/%d. "
+ "sec %x/%x, block %d/%d, magic %x/%x, File: %s \n",
+ block * page_length + 512 * sec,
+ (pass_ & 0xff), (unsigned int)tag[sec].pass,
+ sec, (unsigned int)tag[sec].sector,
+ block, (unsigned int)tag[sec].block,
+ magic, (unsigned int)tag[sec].magic,
+ filename_.c_str());
+
+ // Keep track of first and last bad sector.
+ if (firstsector == -1)
+ firstsector = (block * page_length / 512) + sec;
+ lastsector = (block * page_length / 512) + sec;
+ badsector = true;
+ }
+ // Patch tag back to proper pattern.
+ unsigned int *addr = (unsigned int *)(&tag[sec]);
+ *addr = dst->pattern->pattern(512 * sec / sizeof(*addr));
+ }
+
+ // If we found sector errors:
+ if (badsector == true) {
+ logprintf(5, "Log: file sector miscompare at offset %x-%x. File: %s\n",
+ firstsector * 512,
+ ((lastsector + 1) * 512) - 1,
+ filename_.c_str());
+
+ // Either exit immediately, or patch the data up and continue.
+ if (sat_->stop_on_error()) {
+ exit(1);
+ } else {
+ // Patch up bad pages.
+ for (int block = (firstsector * 512) / page_length;
+ block <= (lastsector * 512) / page_length;
+ block++) {
+ unsigned int *memblock = static_cast<unsigned int *>(dst->addr);
+ int length = page_length / wordsize_;
+ for (int i = 0; i < length; i++) {
+ memblock[i] = dst->pattern->pattern(i);
+ }
+ }
+ }
+ }
+ return true;
+}
+
+// Get memory for an incoming data transfer..
+bool FileThread::PagePrepare() {
+ // We can only do direct IO to SAT pages if it is normal mem.
+ page_io_ = os_->normal_mem();
+
+ // Init a local buffer if we need it.
+ if (!page_io_) {
+#ifdef HAVE_POSIX_MEMALIGN
+ int result = posix_memalign(&local_page_, 512, sat_->page_length());
+#else
+ local_page_ = memalign(512, sat_->page_length());
+ int result = (local_page_ == 0);
+#endif
+ if (result) {
+ logprintf(0, "Process Error: disk thread posix_memalign "
+ "returned %d (fail)\n",
+ result);
+ status_ = false;
+ return false;
+ }
+ }
+ return true;
+}
+
+
+// Remove memory allocated for data transfer.
+bool FileThread::PageTeardown() {
+ // Free a local buffer if we need to.
+ if (!page_io_) {
+ free(local_page_);
+ }
+ return true;
+}
+
+
+
+// Get memory for an incoming data transfer..
+bool FileThread::GetEmptyPage(struct page_entry *dst) {
+ if (page_io_) {
+ if (!sat_->GetEmpty(dst))
+ return false;
+ } else {
+ dst->addr = local_page_;
+ dst->offset = 0;
+ dst->pattern = 0;
+ dst->lastcpu = 0;
+ }
+ return true;
+}
+
+// Get memory for an outgoing data transfer..
+bool FileThread::GetValidPage(struct page_entry *src) {
+ struct page_entry tmp;
+ if (!sat_->GetValid(&tmp))
+ return false;
+ if (page_io_) {
+ *src = tmp;
+ return true;
+ } else {
+ src->addr = local_page_;
+ src->offset = 0;
+ CrcCopyPage(src, &tmp);
+ if (!sat_->PutValid(&tmp))
+ return false;
+ }
+ return true;
+}
+
+
+// Throw out a used empty page.
+bool FileThread::PutEmptyPage(struct page_entry *src) {
+ if (page_io_) {
+ if (!sat_->PutEmpty(src))
+ return false;
+ }
+ return true;
+}
+
+// Throw out a used, filled page.
+bool FileThread::PutValidPage(struct page_entry *src) {
+ if (page_io_) {
+ if (!sat_->PutValid(src))
+ return false;
+ }
+ return true;
+}
+
+// Copy data from file into memory blocks.
+bool FileThread::ReadPages(int fd) {
+ int page_length = sat_->page_length();
+ int strict = sat_->strict();
+ bool result = true;
+
+ // Read our data back out of the file, into it's new location.
+ lseek(fd, 0, SEEK_SET);
+ for (int i = 0; i < sat_->disk_pages(); i++) {
+ struct page_entry dst;
+ if (!GetEmptyPage(&dst))
+ return false;
+ // Retrieve expected pattern.
+ dst.pattern = page_recs_[i].pattern;
+ dst.lastcpu = sched_getcpu();
+ // Update page recordpage record.
+ page_recs_[i].dst = dst.addr;
+
+ // Read from the file into destination page.
+ if (!ReadPageFromFile(fd, &dst)) {
+ PutEmptyPage(&dst);
+ return false;
+ }
+
+ SectorValidatePage(page_recs_[i], &dst, i);
+
+ // Ensure that the transfer ended up with correct data.
+ if (strict) {
+ // Record page index currently CRC checked.
+ crc_page_ = i;
+ int errors = CrcCheckPage(&dst);
+ if (errors) {
+ logprintf(5, "Log: file miscompare at block %d, "
+ "offset %x-%x. File: %s\n",
+ i, i * page_length, ((i + 1) * page_length) - 1,
+ filename_.c_str());
+ result = false;
+ }
+ crc_page_ = -1;
+ errorcount_ += errors;
+ }
+ if (!PutValidPage(&dst))
+ return false;
+ }
+ return result;
+}
+
+// File IO work loop. Execute until marked done.
+bool FileThread::Work() {
+ bool result = true;
+ int64 loops = 0;
+
+ logprintf(9, "Log: Starting file thread %d, file %s, device %s\n",
+ thread_num_,
+ filename_.c_str(),
+ devicename_.c_str());
+
+ if (!PagePrepare()) {
+ status_ = false;
+ return false;
+ }
+
+ // Open the data IO file.
+ int fd = 0;
+ if (!OpenFile(&fd)) {
+ status_ = false;
+ return false;
+ }
+
+ pass_ = 0;
+
+ // Load patterns into page records.
+ page_recs_ = new struct PageRec[sat_->disk_pages()];
+ for (int i = 0; i < sat_->disk_pages(); i++) {
+ page_recs_[i].pattern = new class Pattern();
+ }
+
+ // Loop until done.
+ while (IsReadyToRun()) {
+ // Do the file write.
+ if (!(result = result && WritePages(fd)))
+ break;
+
+ // Do the file read.
+ if (!(result = result && ReadPages(fd)))
+ break;
+
+ loops++;
+ pass_ = loops;
+ }
+
+ pages_copied_ = loops * sat_->disk_pages();
+
+ // Clean up.
+ CloseFile(fd);
+ PageTeardown();
+
+ logprintf(9, "Log: Completed %d: file thread status %d, %d pages copied\n",
+ thread_num_, status_, pages_copied_);
+ // Failure to read from device indicates hardware,
+ // rather than procedural SW error.
+ status_ = true;
+ return true;
+}
+
+bool NetworkThread::IsNetworkStopSet() {
+ return !IsReadyToRunNoPause();
+}
+
+bool NetworkSlaveThread::IsNetworkStopSet() {
+ // This thread has no completion status.
+ // It finishes whever there is no more data to be
+ // passed back.
+ return true;
+}
+
+// Set ip name to use for Network IO.
+void NetworkThread::SetIP(const char *ipaddr_init) {
+ strncpy(ipaddr_, ipaddr_init, 255);
+}
+
+// Create a socket.
+// Return 0 on error.
+bool NetworkThread::CreateSocket(int *psocket) {
+ int sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock == -1) {
+ logprintf(0, "Process Error: Cannot open socket\n");
+ pages_copied_ = 0;
+ status_ = false;
+ return false;
+ }
+ *psocket = sock;
+ return true;
+}
+
+// Close the socket.
+bool NetworkThread::CloseSocket(int sock) {
+ close(sock);
+ return true;
+}
+
+// Initiate the tcp connection.
+bool NetworkThread::Connect(int sock) {
+ struct sockaddr_in dest_addr;
+ dest_addr.sin_family = AF_INET;
+ dest_addr.sin_port = htons(kNetworkPort);
+ memset(&(dest_addr.sin_zero), '\0', sizeof(dest_addr.sin_zero));
+
+ // Translate dot notation to u32.
+ if (inet_aton(ipaddr_, &dest_addr.sin_addr) == 0) {
+ logprintf(0, "Process Error: Cannot resolve %s\n", ipaddr_);
+ pages_copied_ = 0;
+ status_ = false;
+ return false;
+ }
+
+ if (-1 == connect(sock, reinterpret_cast<struct sockaddr *>(&dest_addr),
+ sizeof(struct sockaddr))) {
+ logprintf(0, "Process Error: Cannot connect %s\n", ipaddr_);
+ pages_copied_ = 0;
+ status_ = false;
+ return false;
+ }
+ return true;
+}
+
+// Initiate the tcp connection.
+bool NetworkListenThread::Listen() {
+ struct sockaddr_in sa;
+
+ memset(&(sa.sin_zero), '\0', sizeof(sa.sin_zero));
+
+ sa.sin_family = AF_INET;
+ sa.sin_addr.s_addr = INADDR_ANY;
+ sa.sin_port = htons(kNetworkPort);
+
+ if (-1 == ::bind(sock_, (struct sockaddr*)&sa, sizeof(struct sockaddr))) {
+ char buf[256];
+ sat_strerror(errno, buf, sizeof(buf));
+ logprintf(0, "Process Error: Cannot bind socket: %s\n", buf);
+ pages_copied_ = 0;
+ status_ = false;
+ return false;
+ }
+ listen(sock_, 3);
+ return true;
+}
+
+// Wait for a connection from a network traffic generation thread.
+bool NetworkListenThread::Wait() {
+ fd_set rfds;
+ struct timeval tv;
+ int retval;
+
+ // Watch sock_ to see when it has input.
+ FD_ZERO(&rfds);
+ FD_SET(sock_, &rfds);
+ // Wait up to five seconds.
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+
+ retval = select(sock_ + 1, &rfds, NULL, NULL, &tv);
+
+ return (retval > 0);
+}
+
+// Wait for a connection from a network traffic generation thread.
+bool NetworkListenThread::GetConnection(int *pnewsock) {
+ struct sockaddr_in sa;
+ socklen_t size = sizeof(struct sockaddr_in);
+
+ int newsock = accept(sock_, reinterpret_cast<struct sockaddr *>(&sa), &size);
+ if (newsock < 0) {
+ logprintf(0, "Process Error: Did not receive connection\n");
+ pages_copied_ = 0;
+ status_ = false;
+ return false;
+ }
+ *pnewsock = newsock;
+ return true;
+}
+
+// Send a page, return false if a page was not sent.
+bool NetworkThread::SendPage(int sock, struct page_entry *src) {
+ int page_length = sat_->page_length();
+ char *address = static_cast<char*>(src->addr);
+
+ // Send our data over the network.
+ int size = page_length;
+ while (size) {
+ int transferred = send(sock, address + (page_length - size), size, 0);
+ if ((transferred == 0) || (transferred == -1)) {
+ if (!IsNetworkStopSet()) {
+ char buf[256] = "";
+ sat_strerror(errno, buf, sizeof(buf));
+ logprintf(0, "Process Error: Thread %d, "
+ "Network write failed, bailing. (%s)\n",
+ thread_num_, buf);
+ status_ = false;
+ }
+ return false;
+ }
+ size = size - transferred;
+ }
+ return true;
+}
+
+// Receive a page. Return false if a page was not received.
+bool NetworkThread::ReceivePage(int sock, struct page_entry *dst) {
+ int page_length = sat_->page_length();
+ char *address = static_cast<char*>(dst->addr);
+
+ // Maybe we will get our data back again, maybe not.
+ int size = page_length;
+ while (size) {
+ int transferred = recv(sock, address + (page_length - size), size, 0);
+ if ((transferred == 0) || (transferred == -1)) {
+ // Typically network slave thread should exit as network master
+ // thread stops sending data.
+ if (IsNetworkStopSet()) {
+ int err = errno;
+ if (transferred == 0 && err == 0) {
+ // Two system setups will not sync exactly,
+ // allow early exit, but log it.
+ logprintf(0, "Log: Net thread did not receive any data, exiting.\n");
+ } else {
+ char buf[256] = "";
+ sat_strerror(err, buf, sizeof(buf));
+ // Print why we failed.
+ logprintf(0, "Process Error: Thread %d, "
+ "Network read failed, bailing (%s).\n",
+ thread_num_, buf);
+ status_ = false;
+ // Print arguments and results.
+ logprintf(0, "Log: recv(%d, address %x, size %x, 0) == %x, err %d\n",
+ sock, address + (page_length - size),
+ size, transferred, err);
+ if ((transferred == 0) &&
+ (page_length - size < 512) &&
+ (page_length - size > 0)) {
+ // Print null terminated data received, to see who's been
+ // sending us supicious unwanted data.
+ address[page_length - size] = 0;
+ logprintf(0, "Log: received %d bytes: '%s'\n",
+ page_length - size, address);
+ }
+ }
+ }
+ return false;
+ }
+ size = size - transferred;
+ }
+ return true;
+}
+
+// Network IO work loop. Execute until marked done.
+// Return true if the thread ran as expected.
+bool NetworkThread::Work() {
+ logprintf(9, "Log: Starting network thread %d, ip %s\n",
+ thread_num_,
+ ipaddr_);
+
+ // Make a socket.
+ int sock = 0;
+ if (!CreateSocket(&sock))
+ return false;
+
+ // Network IO loop requires network slave thread to have already initialized.
+ // We will sleep here for awhile to ensure that the slave thread will be
+ // listening by the time we connect.
+ // Sleep for 15 seconds.
+ sat_sleep(15);
+ logprintf(9, "Log: Starting execution of network thread %d, ip %s\n",
+ thread_num_,
+ ipaddr_);
+
+
+ // Connect to a slave thread.
+ if (!Connect(sock))
+ return false;
+
+ // Loop until done.
+ bool result = true;
+ int strict = sat_->strict();
+ int64 loops = 0;
+ while (IsReadyToRun()) {
+ struct page_entry src;
+ struct page_entry dst;
+ result = result && sat_->GetValid(&src);
+ result = result && sat_->GetEmpty(&dst);
+ if (!result) {
+ logprintf(0, "Process Error: net_thread failed to pop pages, "
+ "bailing\n");
+ break;
+ }
+
+ // Check data correctness.
+ if (strict)
+ CrcCheckPage(&src);
+
+ // Do the network write.
+ if (!(result = result && SendPage(sock, &src)))
+ break;
+
+ // Update pattern reference to reflect new contents.
+ dst.pattern = src.pattern;
+ dst.lastcpu = sched_getcpu();
+
+ // Do the network read.
+ if (!(result = result && ReceivePage(sock, &dst)))
+ break;
+
+ // Ensure that the transfer ended up with correct data.
+ if (strict)
+ CrcCheckPage(&dst);
+
+ // Return all of our pages to the queue.
+ result = result && sat_->PutValid(&dst);
+ result = result && sat_->PutEmpty(&src);
+ if (!result) {
+ logprintf(0, "Process Error: net_thread failed to push pages, "
+ "bailing\n");
+ break;
+ }
+ loops++;
+ }
+
+ pages_copied_ = loops;
+ status_ = result;
+
+ // Clean up.
+ CloseSocket(sock);
+
+ logprintf(9, "Log: Completed %d: network thread status %d, "
+ "%d pages copied\n",
+ thread_num_, status_, pages_copied_);
+ return result;
+}
+
+// Spawn slave threads for incoming connections.
+bool NetworkListenThread::SpawnSlave(int newsock, int threadid) {
+ logprintf(12, "Log: Listen thread spawning slave\n");
+
+ // Spawn slave thread, to reflect network traffic back to sender.
+ ChildWorker *child_worker = new ChildWorker;
+ child_worker->thread.SetSock(newsock);
+ child_worker->thread.InitThread(threadid, sat_, os_, patternlist_,
+ &child_worker->status);
+ child_worker->status.Initialize();
+ child_worker->thread.SpawnThread();
+ child_workers_.push_back(child_worker);
+
+ return true;
+}
+
+// Reap slave threads.
+bool NetworkListenThread::ReapSlaves() {
+ bool result = true;
+ // Gather status and reap threads.
+ logprintf(12, "Log: Joining all outstanding threads\n");
+
+ for (size_t i = 0; i < child_workers_.size(); i++) {
+ NetworkSlaveThread& child_thread = child_workers_[i]->thread;
+ logprintf(12, "Log: Joining slave thread %d\n", i);
+ child_thread.JoinThread();
+ if (child_thread.GetStatus() != 1) {
+ logprintf(0, "Process Error: Slave Thread %d failed with status %d\n", i,
+ child_thread.GetStatus());
+ result = false;
+ }
+ errorcount_ += child_thread.GetErrorCount();
+ logprintf(9, "Log: Slave Thread %d found %lld miscompares\n", i,
+ child_thread.GetErrorCount());
+ pages_copied_ += child_thread.GetPageCount();
+ }
+
+ return result;
+}
+
+// Network listener IO work loop. Execute until marked done.
+// Return false on fatal software error.
+bool NetworkListenThread::Work() {
+ logprintf(9, "Log: Starting network listen thread %d\n",
+ thread_num_);
+
+ // Make a socket.
+ sock_ = 0;
+ if (!CreateSocket(&sock_)) {
+ status_ = false;
+ return false;
+ }
+ logprintf(9, "Log: Listen thread created sock\n");
+
+ // Allows incoming connections to be queued up by socket library.
+ int newsock = 0;
+ Listen();
+ logprintf(12, "Log: Listen thread waiting for incoming connections\n");
+
+ // Wait on incoming connections, and spawn worker threads for them.
+ int threadcount = 0;
+ while (IsReadyToRun()) {
+ // Poll for connections that we can accept().
+ if (Wait()) {
+ // Accept those connections.
+ logprintf(12, "Log: Listen thread found incoming connection\n");
+ if (GetConnection(&newsock)) {
+ SpawnSlave(newsock, threadcount);
+ threadcount++;
+ }
+ }
+ }
+
+ // Gather status and join spawned threads.
+ ReapSlaves();
+
+ // Delete the child workers.
+ for (ChildVector::iterator it = child_workers_.begin();
+ it != child_workers_.end(); ++it) {
+ (*it)->status.Destroy();
+ delete *it;
+ }
+ child_workers_.clear();
+
+ CloseSocket(sock_);
+
+ status_ = true;
+ logprintf(9,
+ "Log: Completed %d: network listen thread status %d, "
+ "%d pages copied\n",
+ thread_num_, status_, pages_copied_);
+ return true;
+}
+
+// Set network reflector socket struct.
+void NetworkSlaveThread::SetSock(int sock) {
+ sock_ = sock;
+}
+
+// Network reflector IO work loop. Execute until marked done.
+// Return false on fatal software error.
+bool NetworkSlaveThread::Work() {
+ logprintf(9, "Log: Starting network slave thread %d\n",
+ thread_num_);
+
+ // Verify that we have a socket.
+ int sock = sock_;
+ if (!sock) {
+ status_ = false;
+ return false;
+ }
+
+ // Loop until done.
+ int64 loops = 0;
+ // Init a local buffer for storing data.
+ void *local_page = NULL;
+#ifdef HAVE_POSIX_MEMALIGN
+ int result = posix_memalign(&local_page, 512, sat_->page_length());
+#else
+ local_page = memalign(512, sat_->page_length());
+ int result = (local_page == 0);
+#endif
+ if (result) {
+ logprintf(0, "Process Error: net slave posix_memalign "
+ "returned %d (fail)\n",
+ result);
+ status_ = false;
+ return false;
+ }
+
+ struct page_entry page;
+ page.addr = local_page;
+
+ // This thread will continue to run as long as the thread on the other end of
+ // the socket is still sending and receiving data.
+ while (1) {
+ // Do the network read.
+ if (!ReceivePage(sock, &page))
+ break;
+
+ // Do the network write.
+ if (!SendPage(sock, &page))
+ break;
+
+ loops++;
+ }
+
+ pages_copied_ = loops;
+ // No results provided from this type of thread.
+ status_ = true;
+
+ // Clean up.
+ CloseSocket(sock);
+
+ logprintf(9,
+ "Log: Completed %d: network slave thread status %d, "
+ "%d pages copied\n",
+ thread_num_, status_, pages_copied_);
+ return true;
+}
+
+// Thread work loop. Execute until marked finished.
+bool ErrorPollThread::Work() {
+ logprintf(9, "Log: Starting system error poll thread %d\n", thread_num_);
+
+ // This calls a generic error polling function in the Os abstraction layer.
+ do {
+ errorcount_ += os_->ErrorPoll();
+ os_->ErrorWait();
+ } while (IsReadyToRun());
+
+ logprintf(9, "Log: Finished system error poll thread %d: %d errors\n",
+ thread_num_, errorcount_);
+ status_ = true;
+ return true;
+}
+
+// Worker thread to heat up CPU.
+// This thread does not evaluate pass/fail or software error.
+bool CpuStressThread::Work() {
+ logprintf(9, "Log: Starting CPU stress thread %d\n", thread_num_);
+
+ do {
+ // Run ludloff's platform/CPU-specific assembly workload.
+ os_->CpuStressWorkload();
+ YieldSelf();
+ } while (IsReadyToRun());
+
+ logprintf(9, "Log: Finished CPU stress thread %d:\n",
+ thread_num_);
+ status_ = true;
+ return true;
+}
+
+CpuCacheCoherencyThread::CpuCacheCoherencyThread(cc_cacheline_data *data,
+ int cacheline_count,
+ int thread_num,
+ int thread_count,
+ int inc_count) {
+ cc_cacheline_data_ = data;
+ cc_cacheline_count_ = cacheline_count;
+ cc_thread_num_ = thread_num;
+ cc_thread_count_ = thread_count;
+ cc_inc_count_ = inc_count;
+}
+
+// A very simple psuedorandom generator. Since the random number is based
+// on only a few simple logic operations, it can be done quickly in registers
+// and the compiler can inline it.
+uint64 CpuCacheCoherencyThread::SimpleRandom(uint64 seed) {
+ return (seed >> 1) ^ (-(seed & 1) & kRandomPolynomial);
+}
+
+// Worked thread to test the cache coherency of the CPUs
+// Return false on fatal sw error.
+bool CpuCacheCoherencyThread::Work() {
+ logprintf(9, "Log: Starting the Cache Coherency thread %d\n",
+ cc_thread_num_);
+ int64 time_start, time_end;
+
+ // Use a slightly more robust random number for the initial
+ // value, so the random sequences from the simple generator will
+ // be more divergent.
+#ifdef HAVE_RAND_R
+ unsigned int seed = static_cast<unsigned int>(gettid());
+ uint64 r = static_cast<uint64>(rand_r(&seed));
+ r |= static_cast<uint64>(rand_r(&seed)) << 32;
+#else
+ srand(time(NULL));
+ uint64 r = static_cast<uint64>(rand()); // NOLINT
+ r |= static_cast<uint64>(rand()) << 32; // NOLINT
+#endif
+
+ time_start = sat_get_time_us();
+
+ uint64 total_inc = 0; // Total increments done by the thread.
+ while (IsReadyToRun()) {
+ for (int i = 0; i < cc_inc_count_; i++) {
+ // Choose a datastructure in random and increment the appropriate
+ // member in that according to the offset (which is the same as the
+ // thread number.
+ r = SimpleRandom(r);
+ int cline_num = r % cc_cacheline_count_;
+ int offset;
+ // Reverse the order for odd numbered threads in odd numbered cache
+ // lines. This is designed for massively multi-core systems where the
+ // number of cores exceeds the bytes in a cache line, so "distant" cores
+ // get a chance to exercize cache coherency between them.
+ if (cline_num & cc_thread_num_ & 1)
+ offset = (cc_thread_count_ & ~1) - cc_thread_num_;
+ else
+ offset = cc_thread_num_;
+ // Increment the member of the randomely selected structure.
+ (cc_cacheline_data_[cline_num].num[offset])++;
+ }
+
+ total_inc += cc_inc_count_;
+
+ // Calculate if the local counter matches with the global value
+ // in all the cache line structures for this particular thread.
+ int cc_global_num = 0;
+ for (int cline_num = 0; cline_num < cc_cacheline_count_; cline_num++) {
+ int offset;
+ // Perform the same offset calculation from above.
+ if (cline_num & cc_thread_num_ & 1)
+ offset = (cc_thread_count_ & ~1) - cc_thread_num_;
+ else
+ offset = cc_thread_num_;
+ cc_global_num += cc_cacheline_data_[cline_num].num[offset];
+ // Reset the cachline member's value for the next run.
+ cc_cacheline_data_[cline_num].num[offset] = 0;
+ }
+ if (sat_->error_injection())
+ cc_global_num = -1;
+
+ // Since the count is only stored in a byte, to squeeze more into a
+ // single cache line, only compare it as a byte. In the event that there
+ // is something detected, the chance that it would be missed by a single
+ // thread is 1 in 256. If it affects all cores, that makes the chance
+ // of it being missed terribly minute. It seems unlikely any failure
+ // case would be off by more than a small number.
+ if ((cc_global_num & 0xff) != (cc_inc_count_ & 0xff)) {
+ errorcount_++;
+ logprintf(0, "Hardware Error: global(%d) and local(%d) do not match\n",
+ cc_global_num, cc_inc_count_);
+ }
+ }
+ time_end = sat_get_time_us();
+
+ int64 us_elapsed = time_end - time_start;
+ // inc_rate is the no. of increments per second.
+ double inc_rate = total_inc * 1e6 / us_elapsed;
+
+ logprintf(4, "Stats: CC Thread(%d): Time=%llu us,"
+ " Increments=%llu, Increments/sec = %.6lf\n",
+ cc_thread_num_, us_elapsed, total_inc, inc_rate);
+ logprintf(9, "Log: Finished CPU Cache Coherency thread %d:\n",
+ cc_thread_num_);
+ status_ = true;
+ return true;
+}
+
+DiskThread::DiskThread(DiskBlockTable *block_table) {
+ read_block_size_ = kSectorSize; // default 1 sector (512 bytes)
+ write_block_size_ = kSectorSize; // this assumes read and write block size
+ // are the same
+ segment_size_ = -1; // use the entire disk as one segment
+ cache_size_ = 16 * 1024 * 1024; // assume 16MiB cache by default
+ // Use a queue such that 3/2 times as much data as the cache can hold
+ // is written before it is read so that there is little chance the read
+ // data is in the cache.
+ queue_size_ = ((cache_size_ / write_block_size_) * 3) / 2;
+ blocks_per_segment_ = 32;
+
+ read_threshold_ = 100000; // 100ms is a reasonable limit for
+ write_threshold_ = 100000; // reading/writing a sector
+
+ read_timeout_ = 5000000; // 5 seconds should be long enough for a
+ write_timeout_ = 5000000; // timout for reading/writing
+
+ device_sectors_ = 0;
+ non_destructive_ = 0;
+
+#ifdef HAVE_LIBAIO_H
+ aio_ctx_ = 0;
+#endif
+ block_table_ = block_table;
+ update_block_table_ = 1;
+
+ block_buffer_ = NULL;
+
+ blocks_written_ = 0;
+ blocks_read_ = 0;
+}
+
+DiskThread::~DiskThread() {
+ if (block_buffer_)
+ free(block_buffer_);
+}
+
+// Set filename for device file (in /dev).
+void DiskThread::SetDevice(const char *device_name) {
+ device_name_ = device_name;
+}
+
+// Set various parameters that control the behaviour of the test.
+// -1 is used as a sentinel value on each parameter (except non_destructive)
+// to indicate that the parameter not be set.
+bool DiskThread::SetParameters(int read_block_size,
+ int write_block_size,
+ int64 segment_size,
+ int64 cache_size,
+ int blocks_per_segment,
+ int64 read_threshold,
+ int64 write_threshold,
+ int non_destructive) {
+ if (read_block_size != -1) {
+ // Blocks must be aligned to the disk's sector size.
+ if (read_block_size % kSectorSize != 0) {
+ logprintf(0, "Process Error: Block size must be a multiple of %d "
+ "(thread %d).\n", kSectorSize, thread_num_);
+ return false;
+ }
+
+ read_block_size_ = read_block_size;
+ }
+
+ if (write_block_size != -1) {
+ // Write blocks must be aligned to the disk's sector size and to the
+ // block size.
+ if (write_block_size % kSectorSize != 0) {
+ logprintf(0, "Process Error: Write block size must be a multiple "
+ "of %d (thread %d).\n", kSectorSize, thread_num_);
+ return false;
+ }
+ if (write_block_size % read_block_size_ != 0) {
+ logprintf(0, "Process Error: Write block size must be a multiple "
+ "of the read block size, which is %d (thread %d).\n",
+ read_block_size_, thread_num_);
+ return false;
+ }
+
+ write_block_size_ = write_block_size;
+
+ } else {
+ // Make sure write_block_size_ is still valid.
+ if (read_block_size_ > write_block_size_) {
+ logprintf(5, "Log: Assuming write block size equal to read block size, "
+ "which is %d (thread %d).\n", read_block_size_,
+ thread_num_);
+ write_block_size_ = read_block_size_;
+ } else {
+ if (write_block_size_ % read_block_size_ != 0) {
+ logprintf(0, "Process Error: Write block size (defined as %d) must "
+ "be a multiple of the read block size, which is %d "
+ "(thread %d).\n", write_block_size_, read_block_size_,
+ thread_num_);
+ return false;
+ }
+ }
+ }
+
+ if (cache_size != -1) {
+ cache_size_ = cache_size;
+ }
+
+ if (blocks_per_segment != -1) {
+ if (blocks_per_segment <= 0) {
+ logprintf(0, "Process Error: Blocks per segment must be greater than "
+ "zero.\n (thread %d)", thread_num_);
+ return false;
+ }
+
+ blocks_per_segment_ = blocks_per_segment;
+ }
+
+ if (read_threshold != -1) {
+ if (read_threshold <= 0) {
+ logprintf(0, "Process Error: Read threshold must be greater than "
+ "zero (thread %d).\n", thread_num_);
+ return false;
+ }
+
+ read_threshold_ = read_threshold;
+ }
+
+ if (write_threshold != -1) {
+ if (write_threshold <= 0) {
+ logprintf(0, "Process Error: Write threshold must be greater than "
+ "zero (thread %d).\n", thread_num_);
+ return false;
+ }
+
+ write_threshold_ = write_threshold;
+ }
+
+ if (segment_size != -1) {
+ // Segments must be aligned to the disk's sector size.
+ if (segment_size % kSectorSize != 0) {
+ logprintf(0, "Process Error: Segment size must be a multiple of %d"
+ " (thread %d).\n", kSectorSize, thread_num_);
+ return false;
+ }
+
+ segment_size_ = segment_size / kSectorSize;
+ }
+
+ non_destructive_ = non_destructive;
+
+ // Having a queue of 150% of blocks that will fit in the disk's cache
+ // should be enough to force out the oldest block before it is read and hence,
+ // making sure the data comes form the disk and not the cache.
+ queue_size_ = ((cache_size_ / write_block_size_) * 3) / 2;
+ // Updating DiskBlockTable parameters
+ if (update_block_table_) {
+ block_table_->SetParameters(kSectorSize, write_block_size_,
+ device_sectors_, segment_size_,
+ device_name_);
+ }
+ return true;
+}
+
+// Open a device, return false on failure.
+bool DiskThread::OpenDevice(int *pfile) {
+ int flags = O_RDWR | O_SYNC | O_LARGEFILE;
+ int fd = open(device_name_.c_str(), flags | O_DIRECT, 0);
+ if (O_DIRECT != 0 && fd < 0 && errno == EINVAL) {
+ fd = open(device_name_.c_str(), flags, 0); // Try without O_DIRECT
+ os_->ActivateFlushPageCache();
+ }
+ if (fd < 0) {
+ logprintf(0, "Process Error: Failed to open device %s (thread %d)!!\n",
+ device_name_.c_str(), thread_num_);
+ return false;
+ }
+ *pfile = fd;
+
+ return GetDiskSize(fd);
+}
+
+// Retrieves the size (in bytes) of the disk/file.
+// Return false on failure.
+bool DiskThread::GetDiskSize(int fd) {
+ struct stat device_stat;
+ if (fstat(fd, &device_stat) == -1) {
+ logprintf(0, "Process Error: Unable to fstat disk %s (thread %d).\n",
+ device_name_.c_str(), thread_num_);
+ return false;
+ }
+
+ // For a block device, an ioctl is needed to get the size since the size
+ // of the device file (i.e. /dev/sdb) is 0.
+ if (S_ISBLK(device_stat.st_mode)) {
+ uint64 block_size = 0;
+
+ if (ioctl(fd, BLKGETSIZE64, &block_size) == -1) {
+ logprintf(0, "Process Error: Unable to ioctl disk %s (thread %d).\n",
+ device_name_.c_str(), thread_num_);
+ return false;
+ }
+
+ // Zero size indicates nonworking device..
+ if (block_size == 0) {
+ os_->ErrorReport(device_name_.c_str(), "device-size-zero", 1);
+ ++errorcount_;
+ status_ = true; // Avoid a procedural error.
+ return false;
+ }
+
+ device_sectors_ = block_size / kSectorSize;
+
+ } else if (S_ISREG(device_stat.st_mode)) {
+ device_sectors_ = device_stat.st_size / kSectorSize;
+
+ } else {
+ logprintf(0, "Process Error: %s is not a regular file or block "
+ "device (thread %d).\n", device_name_.c_str(),
+ thread_num_);
+ return false;
+ }
+
+ logprintf(12, "Log: Device sectors: %lld on disk %s (thread %d).\n",
+ device_sectors_, device_name_.c_str(), thread_num_);
+
+ if (update_block_table_) {
+ block_table_->SetParameters(kSectorSize, write_block_size_,
+ device_sectors_, segment_size_,
+ device_name_);
+ }
+
+ return true;
+}
+
+bool DiskThread::CloseDevice(int fd) {
+ close(fd);
+ return true;
+}
+
+// Return the time in microseconds.
+int64 DiskThread::GetTime() {
+ return sat_get_time_us();
+}
+
+// Do randomized reads and (possibly) writes on a device.
+// Return false on fatal SW error, true on SW success,
+// regardless of whether HW failed.
+bool DiskThread::DoWork(int fd) {
+ int64 block_num = 0;
+ int64 num_segments;
+
+ if (segment_size_ == -1) {
+ num_segments = 1;
+ } else {
+ num_segments = device_sectors_ / segment_size_;
+ if (device_sectors_ % segment_size_ != 0)
+ num_segments++;
+ }
+
+ // Disk size should be at least 3x cache size. See comment later for
+ // details.
+ sat_assert(device_sectors_ * kSectorSize > 3 * cache_size_);
+
+ // This disk test works by writing blocks with a certain pattern to
+ // disk, then reading them back and verifying it against the pattern
+ // at a later time. A failure happens when either the block cannot
+ // be written/read or when the read block is different than what was
+ // written. If a block takes too long to write/read, then a warning
+ // is given instead of an error since taking too long is not
+ // necessarily an error.
+ //
+ // To prevent the read blocks from coming from the disk cache,
+ // enough blocks are written before read such that a block would
+ // be ejected from the disk cache by the time it is read.
+ //
+ // TODO(amistry): Implement some sort of read/write throttling. The
+ // flood of asynchronous I/O requests when a drive is
+ // unplugged is causing the application and kernel to
+ // become unresponsive.
+
+ while (IsReadyToRun()) {
+ // Write blocks to disk.
+ logprintf(16, "Log: Write phase %sfor disk %s (thread %d).\n",
+ non_destructive_ ? "(disabled) " : "",
+ device_name_.c_str(), thread_num_);
+ while (IsReadyToRunNoPause() &&
+ in_flight_sectors_.size() <
+ static_cast<size_t>(queue_size_ + 1)) {
+ // Confine testing to a particular segment of the disk.
+ int64 segment = (block_num / blocks_per_segment_) % num_segments;
+ if (!non_destructive_ &&
+ (block_num % blocks_per_segment_ == 0)) {
+ logprintf(20, "Log: Starting to write segment %lld out of "
+ "%lld on disk %s (thread %d).\n",
+ segment, num_segments, device_name_.c_str(),
+ thread_num_);
+ }
+ block_num++;
+
+ BlockData *block = block_table_->GetUnusedBlock(segment);
+
+ // If an unused sequence of sectors could not be found, skip to the
+ // next block to process. Soon, a new segment will come and new
+ // sectors will be able to be allocated. This effectively puts a
+ // minumim on the disk size at 3x the stated cache size, or 48MiB
+ // if a cache size is not given (since the cache is set as 16MiB
+ // by default). Given that todays caches are at the low MiB range
+ // and drive sizes at the mid GB, this shouldn't pose a problem.
+ // The 3x minimum comes from the following:
+ // 1. In order to allocate 'y' blocks from a segment, the
+ // segment must contain at least 2y blocks or else an
+ // allocation may not succeed.
+ // 2. Assume the entire disk is one segment.
+ // 3. A full write phase consists of writing blocks corresponding to
+ // 3/2 cache size.
+ // 4. Therefore, the one segment must have 2 * 3/2 * cache
+ // size worth of blocks = 3 * cache size worth of blocks
+ // to complete.
+ // In non-destructive mode, don't write anything to disk.
+ if (!non_destructive_) {
+ if (!WriteBlockToDisk(fd, block)) {
+ block_table_->RemoveBlock(block);
+ return true;
+ }
+ blocks_written_++;
+ }
+
+ // Block is either initialized by writing, or in nondestructive case,
+ // initialized by being added into the datastructure for later reading.
+ block->initialized();
+
+ in_flight_sectors_.push(block);
+ }
+ if (!os_->FlushPageCache()) // If O_DIRECT worked, this will be a NOP.
+ return false;
+
+ // Verify blocks on disk.
+ logprintf(20, "Log: Read phase for disk %s (thread %d).\n",
+ device_name_.c_str(), thread_num_);
+ while (IsReadyToRunNoPause() && !in_flight_sectors_.empty()) {
+ BlockData *block = in_flight_sectors_.front();
+ in_flight_sectors_.pop();
+ if (!ValidateBlockOnDisk(fd, block))
+ return true;
+ block_table_->RemoveBlock(block);
+ blocks_read_++;
+ }
+ }
+
+ pages_copied_ = blocks_written_ + blocks_read_;
+ return true;
+}
+
+// Do an asynchronous disk I/O operation.
+// Return false if the IO is not set up.
+bool DiskThread::AsyncDiskIO(IoOp op, int fd, void *buf, int64 size,
+ int64 offset, int64 timeout) {
+#ifdef HAVE_LIBAIO_H
+ // Use the Linux native asynchronous I/O interface for reading/writing.
+ // A read/write consists of three basic steps:
+ // 1. create an io context.
+ // 2. prepare and submit an io request to the context
+ // 3. wait for an event on the context.
+
+ struct {
+ const int opcode;
+ const char *op_str;
+ const char *error_str;
+ } operations[2] = {
+ { IO_CMD_PREAD, "read", "disk-read-error" },
+ { IO_CMD_PWRITE, "write", "disk-write-error" }
+ };
+
+ struct iocb cb;
+ memset(&cb, 0, sizeof(cb));
+
+ cb.aio_fildes = fd;
+ cb.aio_lio_opcode = operations[op].opcode;
+ cb.u.c.buf = buf;
+ cb.u.c.nbytes = size;
+ cb.u.c.offset = offset;
+
+ struct iocb *cbs[] = { &cb };
+ if (io_submit(aio_ctx_, 1, cbs) != 1) {
+ int error = errno;
+ char buf[256];
+ sat_strerror(error, buf, sizeof(buf));
+ logprintf(0, "Process Error: Unable to submit async %s "
+ "on disk %s (thread %d). Error %d, %s\n",
+ operations[op].op_str, device_name_.c_str(),
+ thread_num_, error, buf);
+ return false;
+ }
+
+ struct io_event event;
+ memset(&event, 0, sizeof(event));
+ struct timespec tv;
+ tv.tv_sec = timeout / 1000000;
+ tv.tv_nsec = (timeout % 1000000) * 1000;
+ if (io_getevents(aio_ctx_, 1, 1, &event, &tv) != 1) {
+ // A ctrl-c from the keyboard will cause io_getevents to fail with an
+ // EINTR error code. This is not an error and so don't treat it as such,
+ // but still log it.
+ int error = errno;
+ if (error == EINTR) {
+ logprintf(5, "Log: %s interrupted on disk %s (thread %d).\n",
+ operations[op].op_str, device_name_.c_str(),
+ thread_num_);
+ } else {
+ os_->ErrorReport(device_name_.c_str(), operations[op].error_str, 1);
+ errorcount_ += 1;
+ logprintf(0, "Hardware Error: Timeout doing async %s to sectors "
+ "starting at %lld on disk %s (thread %d).\n",
+ operations[op].op_str, offset / kSectorSize,
+ device_name_.c_str(), thread_num_);
+ }
+
+ // Don't bother checking return codes since io_cancel seems to always fail.
+ // Since io_cancel is always failing, destroying and recreating an I/O
+ // context is a workaround for canceling an in-progress I/O operation.
+ // TODO(amistry): Find out why io_cancel isn't working and make it work.
+ io_cancel(aio_ctx_, &cb, &event);
+ io_destroy(aio_ctx_);
+ aio_ctx_ = 0;
+ if (io_setup(5, &aio_ctx_)) {
+ int error = errno;
+ char buf[256];
+ sat_strerror(error, buf, sizeof(buf));
+ logprintf(0, "Process Error: Unable to create aio context on disk %s"
+ " (thread %d) Error %d, %s\n",
+ device_name_.c_str(), thread_num_, error, buf);
+ }
+
+ return false;
+ }
+
+ // event.res contains the number of bytes written/read or
+ // error if < 0, I think.
+ if (event.res != static_cast<uint64>(size)) {
+ errorcount_++;
+ os_->ErrorReport(device_name_.c_str(), operations[op].error_str, 1);
+
+ int64 result = static_cast<int64>(event.res);
+ if (result < 0) {
+ switch (result) {
+ case -EIO:
+ logprintf(0, "Hardware Error: Low-level I/O error while doing %s to "
+ "sectors starting at %lld on disk %s (thread %d).\n",
+ operations[op].op_str, offset / kSectorSize,
+ device_name_.c_str(), thread_num_);
+ break;
+ default:
+ logprintf(0, "Hardware Error: Unknown error while doing %s to "
+ "sectors starting at %lld on disk %s (thread %d).\n",
+ operations[op].op_str, offset / kSectorSize,
+ device_name_.c_str(), thread_num_);
+ }
+ } else {
+ logprintf(0, "Hardware Error: Unable to %s to sectors starting at "
+ "%lld on disk %s (thread %d).\n",
+ operations[op].op_str, offset / kSectorSize,
+ device_name_.c_str(), thread_num_);
+ }
+ return false;
+ }
+
+ return true;
+#else // !HAVE_LIBAIO_H
+ return false;
+#endif
+}
+
+// Write a block to disk.
+// Return false if the block is not written.
+bool DiskThread::WriteBlockToDisk(int fd, BlockData *block) {
+ memset(block_buffer_, 0, block->size());
+
+ // Fill block buffer with a pattern
+ struct page_entry pe;
+ if (!sat_->GetValid(&pe)) {
+ // Even though a valid page could not be obatined, it is not an error
+ // since we can always fill in a pattern directly, albeit slower.
+ unsigned int *memblock = static_cast<unsigned int *>(block_buffer_);
+ block->set_pattern(patternlist_->GetRandomPattern());
+
+ logprintf(11, "Log: Warning, using pattern fill fallback in "
+ "DiskThread::WriteBlockToDisk on disk %s (thread %d).\n",
+ device_name_.c_str(), thread_num_);
+
+ for (unsigned int i = 0; i < block->size()/wordsize_; i++) {
+ memblock[i] = block->pattern()->pattern(i);
+ }
+ } else {
+ memcpy(block_buffer_, pe.addr, block->size());
+ block->set_pattern(pe.pattern);
+ sat_->PutValid(&pe);
+ }
+
+ logprintf(12, "Log: Writing %lld sectors starting at %lld on disk %s"
+ " (thread %d).\n",
+ block->size()/kSectorSize, block->address(),
+ device_name_.c_str(), thread_num_);
+
+ int64 start_time = GetTime();
+
+ if (!AsyncDiskIO(ASYNC_IO_WRITE, fd, block_buffer_, block->size(),
+ block->address() * kSectorSize, write_timeout_)) {
+ return false;
+ }
+
+ int64 end_time = GetTime();
+ logprintf(12, "Log: Writing time: %lld us (thread %d).\n",
+ end_time - start_time, thread_num_);
+ if (end_time - start_time > write_threshold_) {
+ logprintf(5, "Log: Write took %lld us which is longer than threshold "
+ "%lld us on disk %s (thread %d).\n",
+ end_time - start_time, write_threshold_, device_name_.c_str(),
+ thread_num_);
+ }
+
+ return true;
+}
+
+// Verify a block on disk.
+// Return true if the block was read, also increment errorcount
+// if the block had data errors or performance problems.
+bool DiskThread::ValidateBlockOnDisk(int fd, BlockData *block) {
+ int64 blocks = block->size() / read_block_size_;
+ int64 bytes_read = 0;
+ int64 current_blocks;
+ int64 current_bytes;
+ uint64 address = block->address();
+
+ logprintf(20, "Log: Reading sectors starting at %lld on disk %s "
+ "(thread %d).\n",
+ address, device_name_.c_str(), thread_num_);
+
+ // Read block from disk and time the read. If it takes longer than the
+ // threshold, complain.
+ if (lseek(fd, address * kSectorSize, SEEK_SET) == -1) {
+ logprintf(0, "Process Error: Unable to seek to sector %lld in "
+ "DiskThread::ValidateSectorsOnDisk on disk %s "
+ "(thread %d).\n", address, device_name_.c_str(), thread_num_);
+ return false;
+ }
+ int64 start_time = GetTime();
+
+ // Split a large write-sized block into small read-sized blocks and
+ // read them in groups of randomly-sized multiples of read block size.
+ // This assures all data written on disk by this particular block
+ // will be tested using a random reading pattern.
+ while (blocks != 0) {
+ // Test all read blocks in a written block.
+ current_blocks = (random() % blocks) + 1;
+ current_bytes = current_blocks * read_block_size_;
+
+ memset(block_buffer_, 0, current_bytes);
+
+ logprintf(20, "Log: Reading %lld sectors starting at sector %lld on "
+ "disk %s (thread %d)\n",
+ current_bytes / kSectorSize,
+ (address * kSectorSize + bytes_read) / kSectorSize,
+ device_name_.c_str(), thread_num_);
+
+ if (!AsyncDiskIO(ASYNC_IO_READ, fd, block_buffer_, current_bytes,
+ address * kSectorSize + bytes_read,
+ write_timeout_)) {
+ return false;
+ }
+
+ int64 end_time = GetTime();
+ logprintf(20, "Log: Reading time: %lld us (thread %d).\n",
+ end_time - start_time, thread_num_);
+ if (end_time - start_time > read_threshold_) {
+ logprintf(5, "Log: Read took %lld us which is longer than threshold "
+ "%lld us on disk %s (thread %d).\n",
+ end_time - start_time, read_threshold_,
+ device_name_.c_str(), thread_num_);
+ }
+
+ // In non-destructive mode, don't compare the block to the pattern since
+ // the block was never written to disk in the first place.
+ if (!non_destructive_) {
+ if (CheckRegion(block_buffer_, block->pattern(), 0, current_bytes,
+ 0, bytes_read)) {
+ os_->ErrorReport(device_name_.c_str(), "disk-pattern-error", 1);
+ errorcount_ += 1;
+ logprintf(0, "Hardware Error: Pattern mismatch in block starting at "
+ "sector %lld in DiskThread::ValidateSectorsOnDisk on "
+ "disk %s (thread %d).\n",
+ address, device_name_.c_str(), thread_num_);
+ }
+ }
+
+ bytes_read += current_blocks * read_block_size_;
+ blocks -= current_blocks;
+ }
+
+ return true;
+}
+
+// Direct device access thread.
+// Return false on software error.
+bool DiskThread::Work() {
+ int fd;
+
+ logprintf(9, "Log: Starting disk thread %d, disk %s\n",
+ thread_num_, device_name_.c_str());
+
+ srandom(time(NULL));
+
+ if (!OpenDevice(&fd)) {
+ status_ = false;
+ return false;
+ }
+
+ // Allocate a block buffer aligned to 512 bytes since the kernel requires it
+ // when using direct IO.
+#ifdef HAVE_POSIX_MEMALIGN
+ int memalign_result = posix_memalign(&block_buffer_, kBufferAlignment,
+ sat_->page_length());
+#else
+ block_buffer_ = memalign(kBufferAlignment, sat_->page_length());
+ int memalign_result = (block_buffer_ == 0);
+#endif
+ if (memalign_result) {
+ CloseDevice(fd);
+ logprintf(0, "Process Error: Unable to allocate memory for buffers "
+ "for disk %s (thread %d) posix memalign returned %d.\n",
+ device_name_.c_str(), thread_num_, memalign_result);
+ status_ = false;
+ return false;
+ }
+
+#ifdef HAVE_LIBAIO_H
+ if (io_setup(5, &aio_ctx_)) {
+ CloseDevice(fd);
+ logprintf(0, "Process Error: Unable to create aio context for disk %s"
+ " (thread %d).\n",
+ device_name_.c_str(), thread_num_);
+ status_ = false;
+ return false;
+ }
+#endif
+
+ bool result = DoWork(fd);
+
+ status_ = result;
+
+#ifdef HAVE_LIBAIO_H
+ io_destroy(aio_ctx_);
+#endif
+ CloseDevice(fd);
+
+ logprintf(9, "Log: Completed %d (disk %s): disk thread status %d, "
+ "%d pages copied\n",
+ thread_num_, device_name_.c_str(), status_, pages_copied_);
+ return result;
+}
+
+RandomDiskThread::RandomDiskThread(DiskBlockTable *block_table)
+ : DiskThread(block_table) {
+ update_block_table_ = 0;
+}
+
+RandomDiskThread::~RandomDiskThread() {
+}
+
+// Workload for random disk thread.
+bool RandomDiskThread::DoWork(int fd) {
+ logprintf(11, "Log: Random phase for disk %s (thread %d).\n",
+ device_name_.c_str(), thread_num_);
+ while (IsReadyToRun()) {
+ BlockData *block = block_table_->GetRandomBlock();
+ if (block == NULL) {
+ logprintf(12, "Log: No block available for device %s (thread %d).\n",
+ device_name_.c_str(), thread_num_);
+ } else {
+ ValidateBlockOnDisk(fd, block);
+ block_table_->ReleaseBlock(block);
+ blocks_read_++;
+ }
+ }
+ pages_copied_ = blocks_read_;
+ return true;
+}
+
+MemoryRegionThread::MemoryRegionThread() {
+ error_injection_ = false;
+ pages_ = NULL;
+}
+
+MemoryRegionThread::~MemoryRegionThread() {
+ if (pages_ != NULL)
+ delete pages_;
+}
+
+// Set a region of memory or MMIO to be tested.
+// Return false if region could not be mapped.
+bool MemoryRegionThread::SetRegion(void *region, int64 size) {
+ int plength = sat_->page_length();
+ int npages = size / plength;
+ if (size % plength) {
+ logprintf(0, "Process Error: region size is not a multiple of SAT "
+ "page length\n");
+ return false;
+ } else {
+ if (pages_ != NULL)
+ delete pages_;
+ pages_ = new PageEntryQueue(npages);
+ char *base_addr = reinterpret_cast<char*>(region);
+ region_ = base_addr;
+ for (int i = 0; i < npages; i++) {
+ struct page_entry pe;
+ init_pe(&pe);
+ pe.addr = reinterpret_cast<void*>(base_addr + i * plength);
+ pe.offset = i * plength;
+
+ pages_->Push(&pe);
+ }
+ return true;
+ }
+}
+
+// More detailed error printout for hardware errors in memory or MMIO
+// regions.
+void MemoryRegionThread::ProcessError(struct ErrorRecord *error,
+ int priority,
+ const char *message) {
+ uint32 buffer_offset;
+ if (phase_ == kPhaseCopy) {
+ // If the error occurred on the Copy Phase, it means that
+ // the source data (i.e., the main memory) is wrong. so
+ // just pass it to the original ProcessError to call a
+ // bad-dimm error
+ WorkerThread::ProcessError(error, priority, message);
+ } else if (phase_ == kPhaseCheck) {
+ // A error on the Check Phase means that the memory region tested
+ // has an error. Gathering more information and then reporting
+ // the error.
+ // Determine if this is a write or read error.
+ os_->Flush(error->vaddr);
+ error->reread = *(error->vaddr);
+ char *good = reinterpret_cast<char*>(&(error->expected));
+ char *bad = reinterpret_cast<char*>(&(error->actual));
+ sat_assert(error->expected != error->actual);
+ unsigned int offset = 0;
+ for (offset = 0; offset < (sizeof(error->expected) - 1); offset++) {
+ if (good[offset] != bad[offset])
+ break;
+ }
+
+ error->vbyteaddr = reinterpret_cast<char*>(error->vaddr) + offset;
+
+ buffer_offset = error->vbyteaddr - region_;
+
+ // Find physical address if possible.
+ error->paddr = os_->VirtualToPhysical(error->vbyteaddr);
+ logprintf(priority,
+ "%s: miscompare on %s, CRC check at %p(0x%llx), "
+ "offset %llx: read:0x%016llx, reread:0x%016llx "
+ "expected:0x%016llx\n",
+ message,
+ identifier_.c_str(),
+ error->vaddr,
+ error->paddr,
+ buffer_offset,
+ error->actual,
+ error->reread,
+ error->expected);
+ } else {
+ logprintf(0, "Process Error: memory region thread raised an "
+ "unexpected error.");
+ }
+}
+
+// Workload for testion memory or MMIO regions.
+// Return false on software error.
+bool MemoryRegionThread::Work() {
+ struct page_entry source_pe;
+ struct page_entry memregion_pe;
+ bool result = true;
+ int64 loops = 0;
+ const uint64 error_constant = 0x00ba00000000ba00LL;
+
+ // For error injection.
+ int64 *addr = 0x0;
+ int offset = 0;
+ int64 data = 0;
+
+ logprintf(9, "Log: Starting Memory Region thread %d\n", thread_num_);
+
+ while (IsReadyToRun()) {
+ // Getting pages from SAT and queue.
+ phase_ = kPhaseNoPhase;
+ result = result && sat_->GetValid(&source_pe);
+ if (!result) {
+ logprintf(0, "Process Error: memory region thread failed to pop "
+ "pages from SAT, bailing\n");
+ break;
+ }
+
+ result = result && pages_->PopRandom(&memregion_pe);
+ if (!result) {
+ logprintf(0, "Process Error: memory region thread failed to pop "
+ "pages from queue, bailing\n");
+ break;
+ }
+
+ // Error injection for CRC copy.
+ if ((sat_->error_injection() || error_injection_) && loops == 1) {
+ addr = reinterpret_cast<int64*>(source_pe.addr);
+ offset = random() % (sat_->page_length() / wordsize_);
+ data = addr[offset];
+ addr[offset] = error_constant;
+ }
+
+ // Copying SAT page into memory region.
+ phase_ = kPhaseCopy;
+ CrcCopyPage(&memregion_pe, &source_pe);
+ memregion_pe.pattern = source_pe.pattern;
+ memregion_pe.lastcpu = sched_getcpu();
+
+ // Error injection for CRC Check.
+ if ((sat_->error_injection() || error_injection_) && loops == 2) {
+ addr = reinterpret_cast<int64*>(memregion_pe.addr);
+ offset = random() % (sat_->page_length() / wordsize_);
+ data = addr[offset];
+ addr[offset] = error_constant;
+ }
+
+ // Checking page content in memory region.
+ phase_ = kPhaseCheck;
+ CrcCheckPage(&memregion_pe);
+
+ phase_ = kPhaseNoPhase;
+ // Storing pages on their proper queues.
+ result = result && sat_->PutValid(&source_pe);
+ if (!result) {
+ logprintf(0, "Process Error: memory region thread failed to push "
+ "pages into SAT, bailing\n");
+ break;
+ }
+ result = result && pages_->Push(&memregion_pe);
+ if (!result) {
+ logprintf(0, "Process Error: memory region thread failed to push "
+ "pages into queue, bailing\n");
+ break;
+ }
+
+ if ((sat_->error_injection() || error_injection_) &&
+ loops >= 1 && loops <= 2) {
+ addr[offset] = data;
+ }
+
+ loops++;
+ YieldSelf();
+ }
+
+ pages_copied_ = loops;
+ status_ = result;
+ logprintf(9, "Log: Completed %d: Memory Region thread. Status %d, %d "
+ "pages checked\n", thread_num_, status_, pages_copied_);
+ return result;
+}
+
+// The list of MSRs to read from each cpu.
+const CpuFreqThread::CpuRegisterType CpuFreqThread::kCpuRegisters[] = {
+ { kMsrTscAddr, "TSC" },
+ { kMsrAperfAddr, "APERF" },
+ { kMsrMperfAddr, "MPERF" },
+};
+
+CpuFreqThread::CpuFreqThread(int num_cpus, int freq_threshold, int round)
+ : num_cpus_(num_cpus),
+ freq_threshold_(freq_threshold),
+ round_(round) {
+ sat_assert(round >= 0);
+ if (round == 0) {
+ // If rounding is off, force rounding to the nearest MHz.
+ round_ = 1;
+ round_value_ = 0.5;
+ } else {
+ round_value_ = round/2.0;
+ }
+}
+
+CpuFreqThread::~CpuFreqThread() {
+}
+
+// Compute the difference between the currently read MSR values and the
+// previously read values and store the results in delta. If any of the
+// values did not increase, or the TSC value is too small, returns false.
+// Otherwise, returns true.
+bool CpuFreqThread::ComputeDelta(CpuDataType *current, CpuDataType *previous,
+ CpuDataType *delta) {
+ // Loop through the msrs.
+ for (int msr = 0; msr < kMsrLast; msr++) {
+ if (previous->msrs[msr] > current->msrs[msr]) {
+ logprintf(0, "Log: Register %s went backwards 0x%llx to 0x%llx "
+ "skipping interval\n", kCpuRegisters[msr], previous->msrs[msr],
+ current->msrs[msr]);
+ return false;
+ } else {
+ delta->msrs[msr] = current->msrs[msr] - previous->msrs[msr];
+ }
+ }
+
+ // Check for TSC < 1 Mcycles over interval.
+ if (delta->msrs[kMsrTsc] < (1000 * 1000)) {
+ logprintf(0, "Log: Insanely slow TSC rate, TSC stops in idle?\n");
+ return false;
+ }
+ timersub(¤t->tv, &previous->tv, &delta->tv);
+
+ return true;
+}
+
+// Compute the change in values of the MSRs between current and previous,
+// set the frequency in MHz of the cpu. If there is an error computing
+// the delta, return false. Othewise, return true.
+bool CpuFreqThread::ComputeFrequency(CpuDataType *current,
+ CpuDataType *previous, int *freq) {
+ CpuDataType delta;
+ if (!ComputeDelta(current, previous, &delta)) {
+ return false;
+ }
+
+ double interval = delta.tv.tv_sec + delta.tv.tv_usec / 1000000.0;
+ double frequency = 1.0 * delta.msrs[kMsrTsc] / 1000000
+ * delta.msrs[kMsrAperf] / delta.msrs[kMsrMperf] / interval;
+
+ // Use the rounding value to round up properly.
+ int computed = static_cast<int>(frequency + round_value_);
+ *freq = computed - (computed % round_);
+ return true;
+}
+
+// This is the task function that the thread executes.
+bool CpuFreqThread::Work() {
+ cpu_set_t cpuset;
+ if (!AvailableCpus(&cpuset)) {
+ logprintf(0, "Process Error: Cannot get information about the cpus.\n");
+ return false;
+ }
+
+ // Start off indicating the test is passing.
+ status_ = true;
+
+ int curr = 0;
+ int prev = 1;
+ uint32 num_intervals = 0;
+ bool paused = false;
+ bool valid;
+ bool pass = true;
+
+ vector<CpuDataType> data[2];
+ data[0].resize(num_cpus_);
+ data[1].resize(num_cpus_);
+ while (IsReadyToRun(&paused)) {
+ if (paused) {
+ // Reset the intervals and restart logic after the pause.
+ num_intervals = 0;
+ }
+ if (num_intervals == 0) {
+ // If this is the first interval, then always wait a bit before
+ // starting to collect data.
+ sat_sleep(kStartupDelay);
+ }
+
+ // Get the per cpu counters.
+ valid = true;
+ for (int cpu = 0; cpu < num_cpus_; cpu++) {
+ if (CPU_ISSET(cpu, &cpuset)) {
+ if (!GetMsrs(cpu, &data[curr][cpu])) {
+ logprintf(0, "Failed to get msrs on cpu %d.\n", cpu);
+ valid = false;
+ break;
+ }
+ }
+ }
+ if (!valid) {
+ // Reset the number of collected intervals since something bad happened.
+ num_intervals = 0;
+ continue;
+ }
+
+ num_intervals++;
+
+ // Only compute a delta when we have at least two intervals worth of data.
+ if (num_intervals > 2) {
+ for (int cpu = 0; cpu < num_cpus_; cpu++) {
+ if (CPU_ISSET(cpu, &cpuset)) {
+ int freq;
+ if (!ComputeFrequency(&data[curr][cpu], &data[prev][cpu],
+ &freq)) {
+ // Reset the number of collected intervals since an unknown
+ // error occurred.
+ logprintf(0, "Log: Cannot get frequency of cpu %d.\n", cpu);
+ num_intervals = 0;
+ break;
+ }
+ logprintf(15, "Cpu %d Freq %d\n", cpu, freq);
+ if (freq < freq_threshold_) {
+ errorcount_++;
+ pass = false;
+ logprintf(0, "Log: Cpu %d frequency is too low, frequency %d MHz "
+ "threshold %d MHz.\n", cpu, freq, freq_threshold_);
+ }
+ }
+ }
+ }
+
+ sat_sleep(kIntervalPause);
+
+ // Swap the values in curr and prev (these values flip between 0 and 1).
+ curr ^= 1;
+ prev ^= 1;
+ }
+
+ return pass;
+}
+
+
+// Get the MSR values for this particular cpu and save them in data. If
+// any error is encountered, returns false. Otherwise, returns true.
+bool CpuFreqThread::GetMsrs(int cpu, CpuDataType *data) {
+ for (int msr = 0; msr < kMsrLast; msr++) {
+ if (!os_->ReadMSR(cpu, kCpuRegisters[msr].msr, &data->msrs[msr])) {
+ return false;
+ }
+ }
+ // Save the time at which we acquired these values.
+ gettimeofday(&data->tv, NULL);
+
+ return true;
+}
+
+// Returns true if this test can run on the current machine. Otherwise,
+// returns false.
+bool CpuFreqThread::CanRun() {
+#if defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
+ unsigned int eax, ebx, ecx, edx;
+
+ // Check that the TSC feature is supported.
+ // This check is valid for both Intel and AMD.
+ eax = 1;
+ cpuid(&eax, &ebx, &ecx, &edx);
+ if (!(edx & (1 << 5))) {
+ logprintf(0, "Process Error: No TSC support.\n");
+ return false;
+ }
+
+ // Check the highest extended function level supported.
+ // This check is valid for both Intel and AMD.
+ eax = 0x80000000;
+ cpuid(&eax, &ebx, &ecx, &edx);
+ if (eax < 0x80000007) {
+ logprintf(0, "Process Error: No invariant TSC support.\n");
+ return false;
+ }
+
+ // Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8
+ // This check is valid for both Intel and AMD.
+ eax = 0x80000007;
+ cpuid(&eax, &ebx, &ecx, &edx);
+ if ((edx & (1 << 8)) == 0) {
+ logprintf(0, "Process Error: No non-stop TSC support.\n");
+ return false;
+ }
+
+ // APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0
+ // This check is valid for both Intel and AMD.
+ eax = 0x6;
+ cpuid(&eax, &ebx, &ecx, &edx);
+ if ((ecx & 1) == 0) {
+ logprintf(0, "Process Error: No APERF MSR support.\n");
+ return false;
+ }
+ return true;
+#else
+ logprintf(0, "Process Error: "
+ "cpu_freq_test is only supported on X86 processors.\n");
+ return false;
+#endif
+}
diff --git a/external/subpack/utils/stressapptest/src/src/worker.h b/external/subpack/utils/stressapptest/src/src/worker.h
new file mode 100644
index 0000000..c96c04c
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/src/worker.h
@@ -0,0 +1,899 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// worker.h : worker thread interface
+
+// This file contains the Worker Thread class interface
+// for the SAT test. Worker Threads implement a repetative
+// task used to test or stress the system.
+
+#ifndef STRESSAPPTEST_WORKER_H_
+#define STRESSAPPTEST_WORKER_H_
+
+#include <pthread.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+
+#ifdef HAVE_LIBAIO_H
+#include <libaio.h>
+#endif
+
+#include <queue>
+#include <set>
+#include <string>
+#include <vector>
+
+// This file must work with autoconf on its public version,
+// so these includes are correct.
+#include "disk_blocks.h"
+#include "queue.h"
+#include "sattypes.h"
+
+
+// Global Datastruture shared by the Cache Coherency Worker Threads.
+struct cc_cacheline_data {
+ char *num;
+};
+
+// Typical usage:
+// (Other workflows may be possible, see function comments for details.)
+// - Control thread creates object.
+// - Control thread calls AddWorkers(1) for each worker thread.
+// - Control thread calls Initialize().
+// - Control thread launches worker threads.
+// - Every worker thread frequently calls ContinueRunning().
+// - Control thread periodically calls PauseWorkers(), effectively sleeps, and
+// then calls ResumeWorkers().
+// - Some worker threads may exit early, before StopWorkers() is called. They
+// call RemoveSelf() after their last call to ContinueRunning().
+// - Control thread eventually calls StopWorkers().
+// - Worker threads exit.
+// - Control thread joins worker threads.
+// - Control thread calls Destroy().
+// - Control thread destroys object.
+//
+// Threadsafety:
+// - ContinueRunning() may be called concurrently by different workers, but not
+// by a single worker.
+// - No other methods may ever be called concurrently, with themselves or
+// eachother.
+// - This object may be used by multiple threads only between Initialize() and
+// Destroy().
+//
+// TODO(matthewb): Move this class and its unittest to their own files.
+class WorkerStatus {
+ public:
+ //--------------------------------
+ // Methods for the control thread.
+ //--------------------------------
+
+ WorkerStatus() : num_workers_(0), status_(RUN) {}
+
+ // Called by the control thread to increase the worker count. Must be called
+ // before Initialize(). The worker count is 0 upon object initialization.
+ void AddWorkers(int num_new_workers) {
+ // No need to lock num_workers_mutex_ because this is before Initialize().
+ num_workers_ += num_new_workers;
+ }
+
+ // Called by the control thread. May not be called multiple times. If
+ // called, Destroy() must be called before destruction.
+ void Initialize();
+
+ // Called by the control thread after joining all worker threads. Must be
+ // called iff Initialize() was called. No methods may be called after calling
+ // this.
+ void Destroy();
+
+ // Called by the control thread to tell the workers to pause. Does not return
+ // until all workers have called ContinueRunning() or RemoveSelf(). May only
+ // be called between Initialize() and Stop(). Must not be called multiple
+ // times without ResumeWorkers() having been called inbetween.
+ void PauseWorkers();
+
+ // Called by the control thread to tell the workers to resume from a pause.
+ // May only be called between Initialize() and Stop(). May only be called
+ // directly after PauseWorkers().
+ void ResumeWorkers();
+
+ // Called by the control thread to tell the workers to stop. May only be
+ // called between Initialize() and Destroy(). May only be called once.
+ void StopWorkers();
+
+ //--------------------------------
+ // Methods for the worker threads.
+ //--------------------------------
+
+ // Called by worker threads to decrease the worker count by one. May only be
+ // called between Initialize() and Destroy(). May wait for ResumeWorkers()
+ // when called after PauseWorkers().
+ void RemoveSelf();
+
+ // Called by worker threads between Initialize() and Destroy(). May be called
+ // any number of times. Return value is whether or not the worker should
+ // continue running. When called after PauseWorkers(), does not return until
+ // ResumeWorkers() or StopWorkers() has been called. Number of distinct
+ // calling threads must match the worker count (see AddWorkers() and
+ // RemoveSelf()).
+ bool ContinueRunning(bool *paused);
+
+ // This is a hack! It's like ContinueRunning(), except it won't pause. If
+ // any worker threads use this exclusively in place of ContinueRunning() then
+ // PauseWorkers() should never be used!
+ bool ContinueRunningNoPause();
+
+ private:
+ enum Status { RUN, PAUSE, STOP };
+
+ void WaitOnPauseBarrier() {
+#ifdef HAVE_PTHREAD_BARRIERS
+ pthread_rwlock_rdlock(&pause_rwlock_);
+ int error = pthread_barrier_wait(&pause_barrier_);
+ if (error != PTHREAD_BARRIER_SERIAL_THREAD)
+ sat_assert(error == 0);
+ pthread_rwlock_unlock(&pause_rwlock_);
+#endif
+ }
+
+ void AcquireNumWorkersLock() {
+ sat_assert(0 == pthread_mutex_lock(&num_workers_mutex_));
+ }
+
+ void ReleaseNumWorkersLock() {
+ sat_assert(0 == pthread_mutex_unlock(&num_workers_mutex_));
+ }
+
+ void AcquireStatusReadLock() {
+ sat_assert(0 == pthread_rwlock_rdlock(&status_rwlock_));
+ }
+
+ void AcquireStatusWriteLock() {
+ sat_assert(0 == pthread_rwlock_wrlock(&status_rwlock_));
+ }
+
+ void ReleaseStatusLock() {
+ sat_assert(0 == pthread_rwlock_unlock(&status_rwlock_));
+ }
+
+ Status GetStatus() {
+ AcquireStatusReadLock();
+ Status status = status_;
+ ReleaseStatusLock();
+ return status;
+ }
+
+ // Returns the previous status.
+ Status SetStatus(Status status) {
+ AcquireStatusWriteLock();
+ Status prev_status = status_;
+ status_ = status;
+ ReleaseStatusLock();
+ return prev_status;
+ }
+
+ pthread_mutex_t num_workers_mutex_;
+ int num_workers_;
+
+ pthread_rwlock_t status_rwlock_;
+ Status status_;
+
+#ifdef HAVE_PTHREAD_BARRIERS
+ pthread_barrier_t pause_barrier_;
+ pthread_rwlock_t pause_rwlock_; // Guards pause_barrier_
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(WorkerStatus);
+};
+
+
+// This is a base class for worker threads.
+// Each thread repeats a specific
+// task on various blocks of memory.
+class WorkerThread {
+ public:
+ // Enum to mark a thread as low/med/high priority.
+ enum Priority {
+ Low,
+ Normal,
+ High,
+ };
+ WorkerThread();
+ virtual ~WorkerThread();
+
+ // Initialize values and thread ID number.
+ virtual void InitThread(int thread_num_init,
+ class Sat *sat_init,
+ class OsLayer *os_init,
+ class PatternList *patternlist_init,
+ WorkerStatus *worker_status);
+
+ // This function is DEPRECATED, it does nothing.
+ void SetPriority(Priority priority) { priority_ = priority; }
+ // Spawn the worker thread, by running Work().
+ int SpawnThread();
+ // Only for ThreadSpawnerGeneric().
+ void StartRoutine();
+ bool InitPriority();
+
+ // Wait for the thread to complete its cleanup.
+ virtual bool JoinThread();
+ // Kill worker thread with SIGINT.
+ virtual bool KillThread();
+
+ // This is the task function that the thread executes.
+ // This is implemented per subclass.
+ virtual bool Work();
+
+ // Starts per-WorkerThread timer.
+ void StartThreadTimer() {start_time_ = sat_get_time_us();}
+ // Reads current timer value and returns run duration without recording it.
+ int64 ReadThreadTimer() {
+ int64 end_time_ = sat_get_time_us();
+ return end_time_ - start_time_;
+ }
+ // Stops per-WorkerThread timer and records thread run duration.
+ // Start/Stop ThreadTimer repetitively has cumulative effect, ie the timer
+ // is effectively paused and restarted, so runduration_usec accumulates on.
+ void StopThreadTimer() {
+ runduration_usec_ += ReadThreadTimer();
+ }
+
+ // Acccess member variables.
+ bool GetStatus() {return status_;}
+ int64 GetErrorCount() {return errorcount_;}
+ int64 GetPageCount() {return pages_copied_;}
+ int64 GetRunDurationUSec() {return runduration_usec_;}
+
+ // Returns bandwidth defined as pages_copied / thread_run_durations.
+ virtual float GetCopiedData();
+ // Calculate worker thread specific copied data.
+ virtual float GetMemoryCopiedData() {return 0;}
+ virtual float GetDeviceCopiedData() {return 0;}
+ // Calculate worker thread specific bandwidth.
+ virtual float GetMemoryBandwidth()
+ {return GetMemoryCopiedData() / (
+ runduration_usec_ * 1.0 / 1000000.);}
+ virtual float GetDeviceBandwidth()
+ {return GetDeviceCopiedData() / (
+ runduration_usec_ * 1.0 / 1000000.);}
+
+ void set_cpu_mask(cpu_set_t *mask) {
+ memcpy(&cpu_mask_, mask, sizeof(*mask));
+ }
+
+ void set_cpu_mask_to_cpu(int cpu_num) {
+ cpuset_set_ab(&cpu_mask_, cpu_num, cpu_num + 1);
+ }
+
+ void set_tag(int32 tag) {tag_ = tag;}
+
+ // Returns CPU mask, where each bit represents a logical cpu.
+ bool AvailableCpus(cpu_set_t *cpuset);
+ // Returns CPU mask of CPUs this thread is bound to,
+ bool CurrentCpus(cpu_set_t *cpuset);
+ // Returns Current Cpus mask as string.
+ string CurrentCpusFormat() {
+ cpu_set_t current_cpus;
+ CurrentCpus(¤t_cpus);
+ return cpuset_format(¤t_cpus);
+ }
+
+ int ThreadID() {return thread_num_;}
+
+ // Bind worker thread to specified CPU(s)
+ bool BindToCpus(const cpu_set_t *cpuset);
+
+ protected:
+ // This function dictates whether the main work loop
+ // continues, waits, or terminates.
+ // All work loops should be of the form:
+ // do {
+ // // work.
+ // } while (IsReadyToRun());
+ virtual bool IsReadyToRun(bool *paused = NULL) {
+ return worker_status_->ContinueRunning(paused);
+ }
+
+ // Like IsReadyToRun(), except it won't pause.
+ virtual bool IsReadyToRunNoPause() {
+ return worker_status_->ContinueRunningNoPause();
+ }
+
+ // These are functions used by the various work loops.
+ // Pretty print and log a data miscompare.
+ virtual void ProcessError(struct ErrorRecord *er,
+ int priority,
+ const char *message);
+
+ // Compare a region of memory with a known data patter, and report errors.
+ virtual int CheckRegion(void *addr,
+ class Pattern *pat,
+ uint32 lastcpu,
+ int64 length,
+ int offset,
+ int64 patternoffset);
+
+ // Fast compare a block of memory.
+ virtual int CrcCheckPage(struct page_entry *srcpe);
+
+ // Fast copy a block of memory, while verifying correctness.
+ virtual int CrcCopyPage(struct page_entry *dstpe,
+ struct page_entry *srcpe);
+
+ // Fast copy a block of memory, while verifying correctness, and heating CPU.
+ virtual int CrcWarmCopyPage(struct page_entry *dstpe,
+ struct page_entry *srcpe);
+
+ // Fill a page with its specified pattern.
+ virtual bool FillPage(struct page_entry *pe);
+
+ // Copy with address tagging.
+ virtual bool AdlerAddrMemcpyC(uint64 *dstmem64,
+ uint64 *srcmem64,
+ unsigned int size_in_bytes,
+ AdlerChecksum *checksum,
+ struct page_entry *pe);
+ // SSE copy with address tagging.
+ virtual bool AdlerAddrMemcpyWarm(uint64 *dstmem64,
+ uint64 *srcmem64,
+ unsigned int size_in_bytes,
+ AdlerChecksum *checksum,
+ struct page_entry *pe);
+ // Crc data with address tagging.
+ virtual bool AdlerAddrCrcC(uint64 *srcmem64,
+ unsigned int size_in_bytes,
+ AdlerChecksum *checksum,
+ struct page_entry *pe);
+ // Setup tagging on an existing page.
+ virtual bool TagAddrC(uint64 *memwords,
+ unsigned int size_in_bytes);
+ // Report a mistagged cacheline.
+ virtual bool ReportTagError(uint64 *mem64,
+ uint64 actual,
+ uint64 tag);
+ // Print out the error record of the tag mismatch.
+ virtual void ProcessTagError(struct ErrorRecord *error,
+ int priority,
+ const char *message);
+
+ // A worker thread can yield itself to give up CPU until it's scheduled again
+ bool YieldSelf();
+
+ protected:
+ // General state variables that all subclasses need.
+ int thread_num_; // Thread ID.
+ volatile bool status_; // Error status.
+ volatile int64 pages_copied_; // Recorded for memory bandwidth calc.
+ volatile int64 errorcount_; // Miscompares seen by this thread.
+
+ cpu_set_t cpu_mask_; // Cores this thread is allowed to run on.
+ volatile uint32 tag_; // Tag hint for memory this thread can use.
+
+ bool tag_mode_; // Tag cachelines with vaddr.
+
+ // Thread timing variables.
+ int64 start_time_; // Worker thread start time.
+ volatile int64 runduration_usec_; // Worker run duration in u-seconds.
+
+ // Function passed to pthread_create.
+ void *(*thread_spawner_)(void *args);
+ pthread_t thread_; // Pthread thread ID.
+ Priority priority_; // Worker thread priority.
+ class Sat *sat_; // Reference to parent stest object.
+ class OsLayer *os_; // Os abstraction: put hacks here.
+ class PatternList *patternlist_; // Reference to data patterns.
+
+ // Work around style guide ban on sizeof(int).
+ static const uint64 iamint_ = 0;
+ static const int wordsize_ = sizeof(iamint_);
+
+ private:
+ WorkerStatus *worker_status_;
+
+ DISALLOW_COPY_AND_ASSIGN(WorkerThread);
+};
+
+// Worker thread to perform File IO.
+class FileThread : public WorkerThread {
+ public:
+ FileThread();
+ // Set filename to use for file IO.
+ virtual void SetFile(const char *filename_init);
+ virtual bool Work();
+
+ // Calculate worker thread specific bandwidth.
+ virtual float GetDeviceCopiedData()
+ {return GetCopiedData()*2;}
+ virtual float GetMemoryCopiedData();
+
+ protected:
+ // Record of where these pages were sourced from, and what
+ // potentially broken components they passed through.
+ struct PageRec {
+ class Pattern *pattern; // This is the data it should contain.
+ void *src; // This is the memory location the data was sourced from.
+ void *dst; // This is where it ended up.
+ };
+
+ // These are functions used by the various work loops.
+ // Pretty print and log a data miscompare. Disks require
+ // slightly different error handling.
+ virtual void ProcessError(struct ErrorRecord *er,
+ int priority,
+ const char *message);
+
+ virtual bool OpenFile(int *pfile);
+ virtual bool CloseFile(int fd);
+
+ // Read and write whole file to disk.
+ virtual bool WritePages(int fd);
+ virtual bool ReadPages(int fd);
+
+ // Read and write pages to disk.
+ virtual bool WritePageToFile(int fd, struct page_entry *src);
+ virtual bool ReadPageFromFile(int fd, struct page_entry *dst);
+
+ // Sector tagging support.
+ virtual bool SectorTagPage(struct page_entry *src, int block);
+ virtual bool SectorValidatePage(const struct PageRec &page,
+ struct page_entry *dst,
+ int block);
+
+ // Get memory for an incoming data transfer..
+ virtual bool PagePrepare();
+ // Remove memory allocated for data transfer.
+ virtual bool PageTeardown();
+
+ // Get memory for an incoming data transfer..
+ virtual bool GetEmptyPage(struct page_entry *dst);
+ // Get memory for an outgoing data transfer..
+ virtual bool GetValidPage(struct page_entry *dst);
+ // Throw out a used empty page.
+ virtual bool PutEmptyPage(struct page_entry *src);
+ // Throw out a used, filled page.
+ virtual bool PutValidPage(struct page_entry *src);
+
+
+ struct PageRec *page_recs_; // Array of page records.
+ int crc_page_; // Page currently being CRC checked.
+ string filename_; // Name of file to access.
+ string devicename_; // Name of device file is on.
+
+ bool page_io_; // Use page pool for IO.
+ void *local_page_; // malloc'd page fon non-pool IO.
+ int pass_; // Number of writes to the file so far.
+
+ // Tag to detect file corruption.
+ struct SectorTag {
+ volatile uint8 magic;
+ volatile uint8 block;
+ volatile uint8 sector;
+ volatile uint8 pass;
+ char pad[512-4];
+ };
+
+ DISALLOW_COPY_AND_ASSIGN(FileThread);
+};
+
+
+// Worker thread to perform Network IO.
+class NetworkThread : public WorkerThread {
+ public:
+ NetworkThread();
+ // Set hostname to use for net IO.
+ virtual void SetIP(const char *ipaddr_init);
+ virtual bool Work();
+
+ // Calculate worker thread specific bandwidth.
+ virtual float GetDeviceCopiedData()
+ {return GetCopiedData()*2;}
+
+ protected:
+ // IsReadyToRunNoPause() wrapper, for NetworkSlaveThread to override.
+ virtual bool IsNetworkStopSet();
+ virtual bool CreateSocket(int *psocket);
+ virtual bool CloseSocket(int sock);
+ virtual bool Connect(int sock);
+ virtual bool SendPage(int sock, struct page_entry *src);
+ virtual bool ReceivePage(int sock, struct page_entry *dst);
+ char ipaddr_[256];
+ int sock_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NetworkThread);
+};
+
+// Worker thread to reflect Network IO.
+class NetworkSlaveThread : public NetworkThread {
+ public:
+ NetworkSlaveThread();
+ // Set socket for IO.
+ virtual void SetSock(int sock);
+ virtual bool Work();
+
+ protected:
+ virtual bool IsNetworkStopSet();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NetworkSlaveThread);
+};
+
+// Worker thread to detect incoming Network IO.
+class NetworkListenThread : public NetworkThread {
+ public:
+ NetworkListenThread();
+ virtual bool Work();
+
+ private:
+ virtual bool Listen();
+ virtual bool Wait();
+ virtual bool GetConnection(int *pnewsock);
+ virtual bool SpawnSlave(int newsock, int threadid);
+ virtual bool ReapSlaves();
+
+ // For serviced incoming connections.
+ struct ChildWorker {
+ WorkerStatus status;
+ NetworkSlaveThread thread;
+ };
+ typedef vector<ChildWorker*> ChildVector;
+ ChildVector child_workers_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkListenThread);
+};
+
+// Worker thread to perform Memory Copy.
+class CopyThread : public WorkerThread {
+ public:
+ CopyThread() {}
+ virtual bool Work();
+ // Calculate worker thread specific bandwidth.
+ virtual float GetMemoryCopiedData()
+ {return GetCopiedData()*2;}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CopyThread);
+};
+
+// Worker thread to perform Memory Invert.
+class InvertThread : public WorkerThread {
+ public:
+ InvertThread() {}
+ virtual bool Work();
+ // Calculate worker thread specific bandwidth.
+ virtual float GetMemoryCopiedData()
+ {return GetCopiedData()*4;}
+
+ private:
+ virtual int InvertPageUp(struct page_entry *srcpe);
+ virtual int InvertPageDown(struct page_entry *srcpe);
+ DISALLOW_COPY_AND_ASSIGN(InvertThread);
+};
+
+// Worker thread to fill blank pages on startup.
+class FillThread : public WorkerThread {
+ public:
+ FillThread();
+ // Set how many pages this thread should fill before exiting.
+ virtual void SetFillPages(int64 num_pages_to_fill_init);
+ virtual bool Work();
+
+ private:
+ // Fill a page with the data pattern in pe->pattern.
+ virtual bool FillPageRandom(struct page_entry *pe);
+ int64 num_pages_to_fill_;
+ DISALLOW_COPY_AND_ASSIGN(FillThread);
+};
+
+// Worker thread to verify page data matches pattern data.
+// Thread will check and replace pages until "done" flag is set,
+// then it will check and discard pages until no more remain.
+class CheckThread : public WorkerThread {
+ public:
+ CheckThread() {}
+ virtual bool Work();
+ // Calculate worker thread specific bandwidth.
+ virtual float GetMemoryCopiedData()
+ {return GetCopiedData();}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CheckThread);
+};
+
+
+// Worker thread to poll for system error messages.
+// Thread will check for messages until "done" flag is set.
+class ErrorPollThread : public WorkerThread {
+ public:
+ ErrorPollThread() {}
+ virtual bool Work();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ErrorPollThread);
+};
+
+// Computation intensive worker thread to stress CPU.
+class CpuStressThread : public WorkerThread {
+ public:
+ CpuStressThread() {}
+ virtual bool Work();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CpuStressThread);
+};
+
+// Worker thread that tests the correctness of the
+// CPU Cache Coherency Protocol.
+class CpuCacheCoherencyThread : public WorkerThread {
+ public:
+ CpuCacheCoherencyThread(cc_cacheline_data *cc_data,
+ int cc_cacheline_count_,
+ int cc_thread_num_,
+ int cc_thread_count_,
+ int cc_inc_count_);
+ virtual bool Work();
+
+ protected:
+ // Used by the simple random number generator as a shift feedback;
+ // this polynomial (x^64 + x^63 + x^61 + x^60 + 1) will produce a
+ // psuedorandom cycle of period 2^64-1.
+ static const uint64 kRandomPolynomial = 0xD800000000000000ULL;
+ // A very simple psuedorandom generator that can be inlined and use
+ // registers, to keep the CC test loop tight and focused.
+ static uint64 SimpleRandom(uint64 seed);
+
+ cc_cacheline_data *cc_cacheline_data_; // Datstructure for each cacheline.
+ int cc_local_num_; // Local counter for each thread.
+ int cc_cacheline_count_; // Number of cache lines to operate on.
+ int cc_thread_num_; // The integer id of the thread which is
+ // used as an index into the integer array
+ // of the cacheline datastructure.
+ int cc_thread_count_; // Total number of threads being run, for
+ // calculations mixing up cache line access.
+ int cc_inc_count_; // Number of times to increment the counter.
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CpuCacheCoherencyThread);
+};
+
+// Worker thread to perform disk test.
+class DiskThread : public WorkerThread {
+ public:
+ explicit DiskThread(DiskBlockTable *block_table);
+ virtual ~DiskThread();
+ // Calculate disk thread specific bandwidth.
+ virtual float GetDeviceCopiedData() {
+ return (blocks_written_ * write_block_size_ +
+ blocks_read_ * read_block_size_) / kMegabyte;}
+
+ // Set filename for device file (in /dev).
+ virtual void SetDevice(const char *device_name);
+ // Set various parameters that control the behaviour of the test.
+ virtual bool SetParameters(int read_block_size,
+ int write_block_size,
+ int64 segment_size,
+ int64 cache_size,
+ int blocks_per_segment,
+ int64 read_threshold,
+ int64 write_threshold,
+ int non_destructive);
+
+ virtual bool Work();
+
+ virtual float GetMemoryCopiedData() {return 0;}
+
+ protected:
+ static const int kSectorSize = 512; // Size of sector on disk.
+ static const int kBufferAlignment = 512; // Buffer alignment required by the
+ // kernel.
+ static const int kBlockRetry = 100; // Number of retries to allocate
+ // sectors.
+
+ enum IoOp {
+ ASYNC_IO_READ = 0,
+ ASYNC_IO_WRITE = 1
+ };
+
+ virtual bool OpenDevice(int *pfile);
+ virtual bool CloseDevice(int fd);
+
+ // Retrieves the size (in bytes) of the disk/file.
+ virtual bool GetDiskSize(int fd);
+
+ // Retrieves the current time in microseconds.
+ virtual int64 GetTime();
+
+ // Do an asynchronous disk I/O operation.
+ virtual bool AsyncDiskIO(IoOp op, int fd, void *buf, int64 size,
+ int64 offset, int64 timeout);
+
+ // Write a block to disk.
+ virtual bool WriteBlockToDisk(int fd, BlockData *block);
+
+ // Verify a block on disk.
+ virtual bool ValidateBlockOnDisk(int fd, BlockData *block);
+
+ // Main work loop.
+ virtual bool DoWork(int fd);
+
+ int read_block_size_; // Size of blocks read from disk, in bytes.
+ int write_block_size_; // Size of blocks written to disk, in bytes.
+ int64 blocks_read_; // Number of blocks read in work loop.
+ int64 blocks_written_; // Number of blocks written in work loop.
+ int64 segment_size_; // Size of disk segments (in bytes) that the disk
+ // will be split into where testing can be
+ // confined to a particular segment.
+ // Allows for control of how evenly the disk will
+ // be tested. Smaller segments imply more even
+ // testing (less random).
+ int blocks_per_segment_; // Number of blocks that will be tested per
+ // segment.
+ int cache_size_; // Size of disk cache, in bytes.
+ int queue_size_; // Length of in-flight-blocks queue, in blocks.
+ int non_destructive_; // Use non-destructive mode or not.
+ int update_block_table_; // If true, assume this is the thread
+ // responsible for writing the data in the disk
+ // for this block device and, therefore,
+ // update the block table. If false, just use
+ // the block table to get data.
+
+ // read/write times threshold for reporting a problem
+ int64 read_threshold_; // Maximum time a read should take (in us) before
+ // a warning is given.
+ int64 write_threshold_; // Maximum time a write should take (in us) before
+ // a warning is given.
+ int64 read_timeout_; // Maximum time a read can take before a timeout
+ // and the aborting of the read operation.
+ int64 write_timeout_; // Maximum time a write can take before a timeout
+ // and the aborting of the write operation.
+
+ string device_name_; // Name of device file to access.
+ int64 device_sectors_; // Number of sectors on the device.
+
+ std::queue<BlockData*> in_flight_sectors_; // Queue of sectors written but
+ // not verified.
+ void *block_buffer_; // Pointer to aligned block buffer.
+
+#ifdef HAVE_LIBAIO_H
+ io_context_t aio_ctx_; // Asynchronous I/O context for Linux native AIO.
+#endif
+
+ DiskBlockTable *block_table_; // Disk Block Table, shared by all disk
+ // threads that read / write at the same
+ // device
+
+ DISALLOW_COPY_AND_ASSIGN(DiskThread);
+};
+
+class RandomDiskThread : public DiskThread {
+ public:
+ explicit RandomDiskThread(DiskBlockTable *block_table);
+ virtual ~RandomDiskThread();
+ // Main work loop.
+ virtual bool DoWork(int fd);
+ protected:
+ DISALLOW_COPY_AND_ASSIGN(RandomDiskThread);
+};
+
+// Worker thread to perform checks in a specific memory region.
+class MemoryRegionThread : public WorkerThread {
+ public:
+ MemoryRegionThread();
+ ~MemoryRegionThread();
+ virtual bool Work();
+ void ProcessError(struct ErrorRecord *error, int priority,
+ const char *message);
+ bool SetRegion(void *region, int64 size);
+ // Calculate worker thread specific bandwidth.
+ virtual float GetMemoryCopiedData()
+ {return GetCopiedData();}
+ virtual float GetDeviceCopiedData()
+ {return GetCopiedData() * 2;}
+ void SetIdentifier(string identifier) {
+ identifier_ = identifier;
+ }
+
+ protected:
+ // Page queue for this particular memory region.
+ char *region_;
+ PageEntryQueue *pages_;
+ bool error_injection_;
+ int phase_;
+ string identifier_;
+ static const int kPhaseNoPhase = 0;
+ static const int kPhaseCopy = 1;
+ static const int kPhaseCheck = 2;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MemoryRegionThread);
+};
+
+// Worker thread to check that the frequency of every cpu does not go below a
+// certain threshold.
+class CpuFreqThread : public WorkerThread {
+ public:
+ CpuFreqThread(int num_cpus, int freq_threshold, int round);
+ ~CpuFreqThread();
+
+ // This is the task function that the thread executes.
+ virtual bool Work();
+
+ // Returns true if this test can run on the current machine. Otherwise,
+ // returns false.
+ static bool CanRun();
+
+ private:
+ static const int kIntervalPause = 10; // The number of seconds to pause
+ // between acquiring the MSR data.
+ static const int kStartupDelay = 5; // The number of seconds to wait
+ // before acquiring MSR data.
+ static const int kMsrTscAddr = 0x10; // The address of the TSC MSR.
+ static const int kMsrAperfAddr = 0xE8; // The address of the APERF MSR.
+ static const int kMsrMperfAddr = 0xE7; // The address of the MPERF MSR.
+
+ // The index values into the CpuDataType.msr[] array.
+ enum MsrValues {
+ kMsrTsc = 0, // MSR index 0 = TSC.
+ kMsrAperf = 1, // MSR index 1 = APERF.
+ kMsrMperf = 2, // MSR index 2 = MPERF.
+ kMsrLast, // Last MSR index.
+ };
+
+ typedef struct {
+ uint32 msr; // The address of the MSR.
+ const char *name; // A human readable string for the MSR.
+ } CpuRegisterType;
+
+ typedef struct {
+ uint64 msrs[kMsrLast]; // The values of the MSRs.
+ struct timeval tv; // The time at which the MSRs were read.
+ } CpuDataType;
+
+ // The set of MSR addresses and register names.
+ static const CpuRegisterType kCpuRegisters[kMsrLast];
+
+ // Compute the change in values of the MSRs between current and previous,
+ // set the frequency in MHz of the cpu. If there is an error computing
+ // the delta, return false. Othewise, return true.
+ bool ComputeFrequency(CpuDataType *current, CpuDataType *previous,
+ int *frequency);
+
+ // Get the MSR values for this particular cpu and save them in data. If
+ // any error is encountered, returns false. Otherwise, returns true.
+ bool GetMsrs(int cpu, CpuDataType *data);
+
+ // Compute the difference between the currently read MSR values and the
+ // previously read values and store the results in delta. If any of the
+ // values did not increase, or the TSC value is too small, returns false.
+ // Otherwise, returns true.
+ bool ComputeDelta(CpuDataType *current, CpuDataType *previous,
+ CpuDataType *delta);
+
+ // The total number of cpus on the system.
+ int num_cpus_;
+
+ // The minimum frequency that each cpu must operate at (in MHz).
+ int freq_threshold_;
+
+ // The value to round the computed frequency to.
+ int round_;
+
+ // Precomputed value to add to the frequency to do the rounding.
+ double round_value_;
+
+ DISALLOW_COPY_AND_ASSIGN(CpuFreqThread);
+};
+
+#endif // STRESSAPPTEST_WORKER_H_
diff --git a/external/subpack/utils/stressapptest/src/stressapptest.1 b/external/subpack/utils/stressapptest/src/stressapptest.1
new file mode 100644
index 0000000..2c91478
--- /dev/null
+++ b/external/subpack/utils/stressapptest/src/stressapptest.1
@@ -0,0 +1,192 @@
+.TH STRESSAPPTEST 1 2009-10-20
+.SH NAME
+stressapptest \- stress test application for simulating high load situations
+.SH SYNOPSIS
+.B stressapptest
+.RI [ options ]
+.SH DESCRIPTION
+This manual page documents briefly the
+.B stressapptest
+command.
+.PP
+\fBstressapptest\fP (unix name for Stressful Application Test) is a program that
+tries to maximize randomized traffic to memory from processor and I/O, with the
+intent of creating a realistic high load situation in order to test the existing
+hardware devices in a computer.
+.SH OPTIONS
+This program supports the following options:
+
+.TP
+.B \-A
+Run in degraded mode on incompatible systems.
+
+.TP
+.B \-C <threads>
+Number of memory CPU stress threads to run.
+
+.TP
+.B \-d <device>
+Add a direct write disk thread with block device (or file) 'device'.
+
+.TP
+.B \-f <filename>
+Add a disk thread with tempfile 'filename'.
+
+.TP
+.B \-F
+Don't result check each transaction.
+
+.TP
+.B \-i <threads>
+Number of memory invert threads to run.
+
+.TP
+.B \-l <logfile>
+Log output to file 'logfile'.
+
+.TP
+.B \-m <threads>
+Number of memory copy threads to run.
+
+.TP
+.B \-M <mbytes>
+Megabytes of RAM to test.
+
+.TP
+.B \-n <ipaddr>
+Add a network thread connecting to system at 'ipaddr'.
+
+.TP
+.B \-p <pagesize>
+Size in bytes of memory chunks.
+
+.TP
+.B \-s <seconds>
+Number of seconds to run.
+
+.TP
+.B \-v <level>
+Verbosity (0-20), default is 8.
+
+.TP
+.B \-W
+Use more CPU-stressful memory copy.
+
+.TP
+.B \-\-blocks\-per\-segment <number>
+Number of blocks to read/write per segment per iteration (\-d).
+
+.TP
+.B \-\-cache\-size <size>
+Size of disk cache (\-d).
+
+.TP
+.B \-\-cc_inc_count <number>
+Number of times to increment the cacheline's member.
+
+.TP
+.B \-\-cc_line_count <number>
+Number of cache line sized datastructures to allocate for the cache coherency
+threads to operate.
+
+.TP
+.B \-\-cc_line_size <number>
+Size of cache line to use as the basis for cache coherency test data
+structures.
+
+.TP
+.B \-\-cc_test
+Do the cache coherency testing.
+
+.TP
+.B \-\-destructive
+Write/wipe disk partition (\-d).
+
+.TP
+.B \-\-filesize <size>
+Size of disk IO tempfiles.
+
+.TP
+.B \-\-findfiles
+Find locations to do disk IO automatically.
+
+.TP
+.B \-\-force_errors
+Inject false errors to test error handling.
+
+.TP
+.B \-\-force_errors_like_crazy
+Inject a lot of false errors to test error handling.
+
+.TP
+.B \-\-listen
+Run threads that listen for incoming net connections.
+
+.TP
+.B \-\-local_numa
+Choose memory regions associated with each CPU to be tested by that CPU.
+
+.TP
+.B \-\-max_errors <number>
+Exit early after finding specified number of errors.
+
+.TP
+.B \-\-monitor_mode
+Only do ECC error polling, no stress load.
+
+.TP
+.B \-\-no_errors
+Run without checking for ECC or other errors.
+
+.TP
+.B \-\-paddr_base <address>
+Allocate memory starting from this address.
+
+.TP
+.B \-\-pause_delay <seconds>
+Delay (in seconds) between power spikes.
+
+.TP
+.B \-\-pause_duration <seconds>
+Duration (in seconds) of each pause.
+
+.TP
+.B \-\-random-threads <number>
+Number of random threads for each disk write thread (\-d).
+
+.TP
+.B \-\-read-block-size <size>
+Size of block for reading (\-d).
+
+.TP
+.B \-\-read-threshold <time>
+Maximum time (in us) a block read should take (\-d).
+
+.TP
+.B \-\-remote_numa <time>
+Choose memory regions not associated with each CPU to be tested by that CPU.
+
+.TP
+.B \-\-segment-size <size>
+Size of segments to split disk into (\-d).
+
+.TP
+.B \-\-stop_on_errors
+Stop after finding the first error.
+
+.TP
+.B \-\-write-block-size <size>
+Size of block for writing (\-d). If not defined, the size of block for writing
+will be defined as the size of block for reading.
+
+.TP
+.B \-\-write-threshold <time>
+Maximum time (in us) a block write should take (\-d).
+
+.SH SEE ALSO
+.BR http://code.google.com/p/stressapptest/
+.SH AUTHOR
+stressapptest was written by Nick Sanders and Rapahel Menderico (Google Inc).
+.PP
+This manual page was written by Michael Prokop <mika@debian.org>
+for the Debian project (and may be used by others).
diff --git a/external/subpack/utils/sumo/Makefile b/external/subpack/utils/sumo/Makefile
new file mode 100644
index 0000000..5a26c96
--- /dev/null
+++ b/external/subpack/utils/sumo/Makefile
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2015-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=sumo
+PKG_VERSION:=1.8.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-src-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/sumo
+PKG_HASH:=fb0636152085153155ddb41841f0175c5f1e7989907b883f6c7453c63af49edb
+
+PKG_MAINTAINER:=Álvaro Fernández Rojas <noltari@gmail.com>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/sumo
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=SUMO - Simulation of Urban MObility
+ URL:=https://sumo.dlr.de/
+ DEPENDS:=+libxerces-c +zlib
+endef
+
+define Package/sumo/description
+ SUMO is a free and open traffic simulation suite which is available since 2001.
+ SUMO allows modelling of intermodal traffic systems including road vehicles,
+ public transport and pedestrians. Included with SUMO is a wealth of supporting
+ tools which handle tasks such as route finding, visualization, network import
+ and emission calculation. SUMO can be enhanced with custom models and provides
+ various APIs to remotely control the simulation.
+endef
+
+CMAKE_OPTIONS += \
+ -DCCACHE_SUPPORT=OFF
+
+define Package/sumo/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/{activitygen,dfrouter,duarouter,emissionsDrivingCycle,emissionsMap,jtrrouter,marouter,netconvert,netgenerate,od2trips,polyconvert} $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/sumo $(1)/usr/bin/sumo-bin
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) files/sumo.sh $(1)/usr/sbin/sumo
+ $(INSTALL_DIR) $(1)/usr/share/sumo
+ $(CP) $(PKG_BUILD_DIR)/data $(1)/usr/share/sumo/
+endef
+
+$(eval $(call BuildPackage,sumo))
diff --git a/external/subpack/utils/sumo/files/sumo.sh b/external/subpack/utils/sumo/files/sumo.sh
new file mode 100644
index 0000000..0f0af4d
--- /dev/null
+++ b/external/subpack/utils/sumo/files/sumo.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+# Copyright (C) 2015 OpenWrt.org
+
+SUMO_HOME=/usr/share/sumo sumo-bin $@
+
+exit $?
diff --git a/external/subpack/utils/swig/Makefile b/external/subpack/utils/swig/Makefile
new file mode 100644
index 0000000..2a3c16c
--- /dev/null
+++ b/external/subpack/utils/swig/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2006-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=swig
+PKG_VERSION:=4.0.2
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_HASH:=d53be9730d8d58a16bf0cbd1f8ac0c0c3e1090573168bfa151b01eb47fa906fc
+
+PKG_MAINTAINER:=John Crispin <blogic@openwrt.org>, Hirokazu MORIKAWA <morikw2@gmail.com>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_HOST_ONLY:=1
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/swig
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=swig binding generator
+ URL:=http://swig.org/
+ BUILDONLY:=1
+endef
+
+HOST_CONFIGURE_ARGS += \
+ --without-pcre
+
+define Package/swig/description
+ tool that generates bindings for various languages
+endef
+
+$(eval $(call HostBuild))
+$(eval $(call BuildPackage,swig))
diff --git a/external/subpack/utils/swig/patches/000-support_v12.patch b/external/subpack/utils/swig/patches/000-support_v12.patch
new file mode 100644
index 0000000..6ac90a8
--- /dev/null
+++ b/external/subpack/utils/swig/patches/000-support_v12.patch
@@ -0,0 +1,1854 @@
+diff --git a/.travis.yml b/.travis.yml
+index 32c6656dd2..6530d2cb5f 100644
+--- a/.travis.yml
++++ b/.travis.yml
+@@ -89,27 +89,17 @@ matrix:
+ dist: xenial
+ - compiler: gcc
+ os: linux
+- env: SWIGLANG=javascript ENGINE=node VER=0.10
+- sudo: required
+- dist: xenial
+- - compiler: gcc
+- os: linux
+- env: SWIGLANG=javascript ENGINE=node VER=4 CPP11=1
+- sudo: required
+- dist: xenial
+- - compiler: gcc
+- os: linux
+- env: SWIGLANG=javascript ENGINE=node VER=6 CPP11=1
++ env: SWIGLANG=javascript ENGINE=node VER=10 CPP11=1
+ sudo: required
+ dist: xenial
+ - compiler: gcc
+ os: linux
+- env: SWIGLANG=javascript ENGINE=node VER=8 CPP11=1
++ env: SWIGLANG=javascript ENGINE=node VER=12 CPP11=1
+ sudo: required
+ dist: xenial
+ - compiler: gcc
+ os: linux
+- env: SWIGLANG=javascript ENGINE=node VER=10 CPP11=1
++ env: SWIGLANG=javascript ENGINE=node VER=13 CPP11=1
+ sudo: required
+ dist: xenial
+ - compiler: gcc
+@@ -117,11 +107,6 @@ matrix:
+ env: SWIGLANG=javascript ENGINE=jsc
+ sudo: required
+ dist: xenial
+- - compiler: gcc
+- os: linux
+- env: SWIGLANG=javascript ENGINE=v8
+- sudo: required
+- dist: xenial
+ - compiler: gcc
+ os: linux
+ env: SWIGLANG=lua
+diff --git a/Examples/Makefile.in b/Examples/Makefile.in
+index 6fbca29db5..dadb012bf9 100644
+--- a/Examples/Makefile.in
++++ b/Examples/Makefile.in
+@@ -674,8 +674,8 @@ java_clean:
+ # create a configuration for a new example.
+
+ ROOT_DIR = @ROOT_DIR@
+-JSINCLUDES = @JSCOREINC@ @JSV8INC@
+-JSDYNAMICLINKING = @JSCOREDYNAMICLINKING@ @JSV8DYNAMICLINKING@
++JSINCLUDES = @JSCOREINC@
++JSDYNAMICLINKING = @JSCOREDYNAMICLINKING@
+ NODEJS = @NODEJS@
+ NODEGYP = @NODEGYP@
+
+@@ -710,7 +710,7 @@ javascript: $(SRCDIR_SRCS) javascript_custom_interpreter
+ ifeq (jsc, $(ENGINE))
+ $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(SRCDIR_SRCS) $(INCLUDES) $(JSINCLUDES)
+ $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO)
+-else # (v8 | node) # v8 and node must be compiled as c++
++else # (node) # node must be compiled as c++
+ $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ISRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) $(JSINCLUDES)
+ $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO)
+ endif
+@@ -759,9 +759,6 @@ ifeq (jsc, $(ENGINE))
+ echo "Unknown JavascriptCore version."; \
+ fi
+ endif
+-ifeq (v8, $(ENGINE))
+- echo "Unknown v8 version."
+-endif
+
+ # -----------------------------------------------------------------
+ # Cleaning the Javascript examples
+diff --git a/Examples/javascript/example.mk b/Examples/javascript/example.mk
+index 3ef012aa82..beafd6f3fb 100644
+--- a/Examples/javascript/example.mk
++++ b/Examples/javascript/example.mk
+@@ -7,19 +7,13 @@ else
+ JSENGINE=node
+ endif
+
+-ifneq (, $(V8_VERSION))
+- JSV8_VERSION=$(V8_VERSION)
+-else
+- JSV8_VERSION=0x031110
+-endif
+-
+ EXAMPLES_TOP = ../..
+ SWIG_TOP = ../../..
+ SWIGEXE = $(SWIG_TOP)/swig
+ SWIG_LIB_DIR = $(SWIG_TOP)/$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
+ TARGET = example
+ INTERFACE = example.i
+-SWIGOPT = -$(JSENGINE) -DV8_VERSION=$(JSV8_VERSION)
++SWIGOPT = -$(JSENGINE)
+
+ check: build
+ $(MAKE) -f $(EXAMPLES_TOP)/Makefile SRCDIR='$(SRCDIR)' JSENGINE='$(JSENGINE)' TARGET='$(TARGET)' javascript_run
+diff --git a/Examples/javascript/native/example.i b/Examples/javascript/native/example.i
+index 8c61600606..e94f18118b 100644
+--- a/Examples/javascript/native/example.i
++++ b/Examples/javascript/native/example.i
+@@ -15,7 +15,7 @@ int placeholder() { return 0; }
+ static SwigV8ReturnValue JavaScript_do_work(const SwigV8Arguments &args) {
+ SWIGV8_HANDLESCOPE();
+ const int MY_MAGIC_NUMBER = 5;
+- v8::Handle<v8::Value> jsresult =
++ v8::Local<v8::Value> jsresult =
+ SWIG_From_int(static_cast< int >(MY_MAGIC_NUMBER));
+ if (args.Length() != 0)
+ SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments.");
+diff --git a/Examples/test-suite/javascript/Makefile.in b/Examples/test-suite/javascript/Makefile.in
+index 8127415f12..ce16f2ec0d 100644
+--- a/Examples/test-suite/javascript/Makefile.in
++++ b/Examples/test-suite/javascript/Makefile.in
+@@ -22,16 +22,8 @@ else
+ JSENGINE=node
+ endif
+
+-ifneq (, $(V8_VERSION))
+- JSV8_VERSION=$(V8_VERSION)
+-else
+- JSV8_VERSION=0x031110
+-endif
+-
+ include $(srcdir)/../common.mk
+
+-SWIGOPT += -DV8_VERSION=$(JSV8_VERSION)
+-
+ _setup = \
+ if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \
+ echo "$(ACTION)ing $(LANGUAGE) ($(JSENGINE)) testcase $* (with run test)" ; \
+diff --git a/Examples/test-suite/native_directive.i b/Examples/test-suite/native_directive.i
+index 9ae76e0b7f..99089af507 100644
+--- a/Examples/test-suite/native_directive.i
++++ b/Examples/test-suite/native_directive.i
+@@ -53,7 +53,7 @@ extern "C" JNIEXPORT jint JNICALL Java_native_1directive_native_1directiveJNI_Co
+
+ static SwigV8ReturnValue JavaScript_alpha_count(const SwigV8Arguments &args) {
+ SWIGV8_HANDLESCOPE();
+- v8::Handle<v8::Value> jsresult;
++ v8::Local<v8::Value> jsresult;
+ char *arg1 = (char *)0;
+ int res1;
+ char *buf1 = 0;
+diff --git a/Lib/javascript/v8/javascriptcode.swg b/Lib/javascript/v8/javascriptcode.swg
+index c4aaf3db0c..b470e2aeeb 100644
+--- a/Lib/javascript/v8/javascriptcode.swg
++++ b/Lib/javascript/v8/javascriptcode.swg
+@@ -11,7 +11,7 @@
+ static SwigV8ReturnValue $jswrapper(const SwigV8Arguments &args) {
+ SWIGV8_HANDLESCOPE();
+
+- v8::Handle<v8::Object> self = args.Holder();
++ v8::Local<v8::Object> self = args.Holder();
+ $jslocals
+ if(args.Length() != $jsargcount) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for $jswrapper.");
+ $jscode
+@@ -53,7 +53,7 @@ static SwigV8ReturnValue $jswrapper(const SwigV8Arguments &args) {
+ SWIGV8_HANDLESCOPE();
+
+ OverloadErrorHandler errorHandler;
+- v8::Handle<v8::Value> self;
++ v8::Local<v8::Value> self;
+
+ // switch all cases by means of series of if-returns.
+ $jsdispatchcases
+@@ -78,7 +78,7 @@ fail:
+ static SwigV8ReturnValue $jswrapper(const SwigV8Arguments &args, V8ErrorHandler &SWIGV8_ErrorHandler) {
+ SWIGV8_HANDLESCOPE();
+
+- v8::Handle<v8::Object> self = args.Holder();
++ v8::Local<v8::Object> self = args.Holder();
+ $jslocals
+ if(args.Length() != $jsargcount) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for $jswrapper.");
+ $jscode
+@@ -103,17 +103,10 @@ fail:
+ %{
+ if(args.Length() == $jsargcount) {
+ errorHandler.err.Clear();
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903)
+- self = $jswrapper(args, errorHandler);
+- if(errorHandler.err.IsEmpty()) {
+- SWIGV8_ESCAPE(self);
+- }
+-#else
+ $jswrapper(args, errorHandler);
+ if(errorHandler.err.IsEmpty()) {
+ return;
+ }
+-#endif
+ }
+ %}
+
+@@ -124,23 +117,8 @@ fail:
+ * ----------------------------------------------------------------------------- */
+ %fragment ("js_dtor", "templates")
+ %{
+-
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+-static void $jswrapper(v8::Persistent< v8::Value > object, void *parameter) {
+- SWIGV8_Proxy *proxy = static_cast<SWIGV8_Proxy *>(parameter);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+-static void $jswrapper(v8::Isolate *isolate, v8::Persistent<v8::Value> object, void *parameter) {
+- SWIGV8_Proxy *proxy = static_cast<SWIGV8_Proxy *>(parameter);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION)
+-static void $jswrapper(v8::Isolate *isolate, v8::Persistent<v8::Object> *object, SWIGV8_Proxy *proxy) {
+-#elif (V8_MAJOR_VERSION-0) < 5
+-static void $jswrapper(const v8::WeakCallbackData<v8::Object, SWIGV8_Proxy> &data) {
+- v8::Local<v8::Object> object = data.GetValue();
+- SWIGV8_Proxy *proxy = data.GetParameter();
+-#else
+ static void $jswrapper(const v8::WeakCallbackInfo<SWIGV8_Proxy> &data) {
+ SWIGV8_Proxy *proxy = data.GetParameter();
+-#endif
+
+ if(proxy->swigCMemOwn && proxy->swigCObject) {
+ #ifdef SWIGRUNTIME_DEBUG
+@@ -149,20 +127,6 @@ static void $jswrapper(const v8::WeakCallbackData<v8::Object, SWIGV8_Proxy> &dat
+ $jsfree proxy->swigCObject;
+ }
+ delete proxy;
+-
+-#if (V8_MAJOR_VERSION-0) < 5
+- object.Clear();
+-#endif
+-
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+- object.Dispose();
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+- object.Dispose(isolate);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100)
+- object->Dispose(isolate);
+-#elif (V8_MAJOR_VERSION-0) < 5
+- object->Dispose();
+-#endif
+ }
+ %}
+
+@@ -174,40 +138,14 @@ static void $jswrapper(const v8::WeakCallbackData<v8::Object, SWIGV8_Proxy> &dat
+ * ----------------------------------------------------------------------------- */
+ %fragment ("js_dtoroverride", "templates")
+ %{
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+-static void $jswrapper(v8::Persistent<v8::Value> object, void *parameter) {
+- SWIGV8_Proxy *proxy = static_cast<SWIGV8_Proxy *>(parameter);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+-static void $jswrapper(v8::Isolate *isolate, v8::Persistent<v8::Value> object, void *parameter) {
+- SWIGV8_Proxy *proxy = static_cast<SWIGV8_Proxy *>(parameter);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION)
+-static void $jswrapper(v8::Isolate *isolate, v8::Persistent< v8::Object> *object, SWIGV8_Proxy *proxy) {
+-#elif (V8_MAJOR_VERSION-0) < 5
+-static void $jswrapper(const v8::WeakCallbackData<v8::Object, SWIGV8_Proxy> &data) {
+- v8::Local<v8::Object> object = data.GetValue();
+- SWIGV8_Proxy *proxy = data.GetParameter();
+-#else
+ static void $jswrapper(const v8::WeakCallbackInfo<SWIGV8_Proxy> &data) {
+ SWIGV8_Proxy *proxy = data.GetParameter();
+-#endif
+
+ if(proxy->swigCMemOwn && proxy->swigCObject) {
+ $jstype arg1 = ($jstype)proxy->swigCObject;
+ ${destructor_action}
+ }
+ delete proxy;
+-
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+- object.Dispose();
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+- object.Dispose(isolate);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100)
+- object->Dispose(isolate);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION)
+- object->Dispose();
+-#elif (V8_MAJOR_VERSION-0) < 5
+- object.Clear();
+-#endif
+ }
+ %}
+
+@@ -219,14 +157,10 @@ static void $jswrapper(const v8::WeakCallbackInfo<SWIGV8_Proxy> &data) {
+ * ----------------------------------------------------------------------------- */
+ %fragment("js_getter", "templates")
+ %{
+-#if (V8_MAJOR_VERSION-0) < 5
+-static SwigV8ReturnValue $jswrapper(v8::Local<v8::String> property, const SwigV8PropertyCallbackInfo &info) {
+-#else
+ static SwigV8ReturnValue $jswrapper(v8::Local<v8::Name> property, const SwigV8PropertyCallbackInfo &info) {
+-#endif
+ SWIGV8_HANDLESCOPE();
+
+- v8::Handle<v8::Value> jsresult;
++ v8::Local<v8::Value> jsresult;
+ $jslocals
+ $jscode
+ SWIGV8_RETURN_INFO(jsresult, info);
+@@ -245,11 +179,7 @@ fail:
+ * ----------------------------------------------------------------------------- */
+ %fragment("js_setter", "templates")
+ %{
+-#if (V8_MAJOR_VERSION-0) < 5
+-static void $jswrapper(v8::Local<v8::String> property, v8::Local<v8::Value> value, const SwigV8PropertyCallbackInfoVoid &info) {
+-#else
+ static void $jswrapper(v8::Local<v8::Name> property, v8::Local<v8::Value> value, const SwigV8PropertyCallbackInfoVoid &info) {
+-#endif
+ SWIGV8_HANDLESCOPE();
+
+ $jslocals
+@@ -271,7 +201,7 @@ fail:
+ static SwigV8ReturnValue $jswrapper(const SwigV8Arguments &args) {
+ SWIGV8_HANDLESCOPE();
+
+- v8::Handle<v8::Value> jsresult;
++ v8::Local<v8::Value> jsresult;
+ $jslocals
+ if(args.Length() != $jsargcount) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for $jswrapper.");
+
+@@ -296,7 +226,7 @@ fail:
+ static SwigV8ReturnValue $jswrapper(const SwigV8Arguments &args) {
+ SWIGV8_HANDLESCOPE();
+
+- v8::Handle<v8::Value> jsresult;
++ v8::Local<v8::Value> jsresult;
+ OverloadErrorHandler errorHandler;
+ $jscode
+
+@@ -320,7 +250,7 @@ static SwigV8ReturnValue $jswrapper(const SwigV8Arguments &args, V8ErrorHandler
+ {
+ SWIGV8_HANDLESCOPE();
+
+- v8::Handle<v8::Value> jsresult;
++ v8::Local<v8::Value> jsresult;
+ $jslocals
+ $jscode
+ SWIGV8_RETURN(jsresult);
+@@ -342,17 +272,10 @@ fail:
+
+ if(args.Length() == $jsargcount) {
+ errorHandler.err.Clear();
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903)
+- jsresult = $jswrapper(args, errorHandler);
+- if(errorHandler.err.IsEmpty()) {
+- SWIGV8_ESCAPE(jsresult);
+- }
+-#else
+ $jswrapper(args, errorHandler);
+ if(errorHandler.err.IsEmpty()) {
+ return;
+ }
+-#endif
+ }
+ %}
+
+@@ -374,7 +297,7 @@ fail:
+ %fragment("jsv8_define_class_template", "templates")
+ %{
+ /* Name: $jsmangledname, Type: $jsmangledtype, Dtor: $jsdtor */
+- v8::Handle<v8::FunctionTemplate> $jsmangledname_class = SWIGV8_CreateClassTemplate("$jsmangledname");
++ v8::Local<v8::FunctionTemplate> $jsmangledname_class = SWIGV8_CreateClassTemplate("$jsmangledname");
+ SWIGV8_SET_CLASS_TEMPL($jsmangledname_clientData.class_templ, $jsmangledname_class);
+ $jsmangledname_clientData.dtor = $jsdtor;
+ if (SWIGTYPE_$jsmangledtype->clientdata == 0) {
+@@ -392,15 +315,11 @@ fail:
+ %{
+ if (SWIGTYPE_p$jsbaseclass->clientdata && !(static_cast<SWIGV8_ClientData *>(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ.IsEmpty()))
+ {
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903)
+- $jsmangledname_class->Inherit(static_cast<SWIGV8_ClientData *>(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ);
+-#else
+ $jsmangledname_class->Inherit(
+ v8::Local<v8::FunctionTemplate>::New(
+ v8::Isolate::GetCurrent(),
+ static_cast<SWIGV8_ClientData *>(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ)
+ );
+-#endif
+
+ #ifdef SWIGRUNTIME_DEBUG
+ printf("Inheritance successful $jsmangledname $jsbaseclass\n");
+@@ -420,11 +339,10 @@ fail:
+ %fragment("jsv8_create_class_instance", "templates")
+ %{
+ /* Class: $jsname ($jsmangledname) */
+- v8::Handle<v8::FunctionTemplate> $jsmangledname_class_0 = SWIGV8_CreateClassTemplate("$jsname");
++ v8::Local<v8::FunctionTemplate> $jsmangledname_class_0 = SWIGV8_CreateClassTemplate("$jsname");
+ $jsmangledname_class_0->SetCallHandler($jsctor);
+ $jsmangledname_class_0->Inherit($jsmangledname_class);
+- $jsmangledname_class_0->SetHiddenPrototype(true);
+- v8::Handle<v8::Object> $jsmangledname_obj = $jsmangledname_class_0->GetFunction();
++ v8::Local<v8::Object> $jsmangledname_obj = $jsmangledname_class_0->GetFunction(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked();
+ %}
+
+ /* -----------------------------------------------------------------------------
+@@ -435,7 +353,7 @@ fail:
+ * ----------------------------------------------------------------------------- */
+ %fragment("jsv8_register_class", "templates")
+ %{
+- $jsparent_obj->Set(SWIGV8_SYMBOL_NEW("$jsname"), $jsmangledname_obj);
++ $jsparent_obj->Set(SWIGV8_CURRENT_CONTEXT(), SWIGV8_SYMBOL_NEW("$jsname"), $jsmangledname_obj);
+ %}
+
+ /* -----------------------------------------------------------------------------
+@@ -444,7 +362,7 @@ fail:
+ * ----------------------------------------------------------------------------- */
+ %fragment("jsv8_create_namespace", "templates")
+ %{
+- v8::Handle<v8::Object> $jsmangledname_obj = SWIGV8_OBJECT_NEW();
++ v8::Local<v8::Object> $jsmangledname_obj = SWIGV8_OBJECT_NEW();
+ %}
+
+ /* -----------------------------------------------------------------------------
+@@ -455,7 +373,7 @@ fail:
+ * ----------------------------------------------------------------------------- */
+ %fragment("jsv8_register_namespace", "templates")
+ %{
+- $jsparent_obj->Set(SWIGV8_SYMBOL_NEW("$jsname"), $jsmangledname_obj);
++ $jsparent_obj->Set(SWIGV8_CURRENT_CONTEXT(), SWIGV8_SYMBOL_NEW("$jsname"), $jsmangledname_obj);
+ %}
+
+ /* -----------------------------------------------------------------------------
+diff --git a/Lib/javascript/v8/javascriptcomplex.swg b/Lib/javascript/v8/javascriptcomplex.swg
+index d3b4aaffa6..533e548131 100644
+--- a/Lib/javascript/v8/javascriptcomplex.swg
++++ b/Lib/javascript/v8/javascriptcomplex.swg
+@@ -12,7 +12,7 @@
+ %fragment(SWIG_From_frag(Type),"header",
+ fragment=SWIG_From_frag(double))
+ {
+-SWIGINTERNINLINE v8::Handle<v8::Value>
++SWIGINTERNINLINE v8::Local<v8::Value>
+ SWIG_From_dec(Type)(%ifcplusplus(const Type&, Type) c)
+ {
+ SWIGV8_HANDLESCOPE_ESC();
+@@ -32,12 +32,12 @@ SWIG_From_dec(Type)(%ifcplusplus(const Type&, Type) c)
+ fragment=SWIG_AsVal_frag(double))
+ {
+ SWIGINTERN int
+-SWIG_AsVal_dec(Type) (v8::Handle<v8::Value> o, Type* val)
++SWIG_AsVal_dec(Type) (v8::Local<v8::Value> o, Type* val)
+ {
+ SWIGV8_HANDLESCOPE();
+
+ if (o->IsArray()) {
+- v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(o);
++ v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(o);
+
+ if(array->Length() != 2) SWIG_Error(SWIG_TypeError, "Illegal argument for complex: must be array[2].");
+ double re, im;
+@@ -74,12 +74,12 @@ SWIG_AsVal_dec(Type) (v8::Handle<v8::Value> o, Type* val)
+ %fragment(SWIG_AsVal_frag(Type),"header",
+ fragment=SWIG_AsVal_frag(float)) {
+ SWIGINTERN int
+-SWIG_AsVal_dec(Type) (v8::Handle<v8::Value> o, Type* val)
++SWIG_AsVal_dec(Type) (v8::Local<v8::Value> o, Type* val)
+ {
+ SWIGV8_HANDLESCOPE();
+
+ if (o->IsArray()) {
+- v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(o);
++ v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(o);
+
+ if(array->Length() != 2) SWIG_Error(SWIG_TypeError, "Illegal argument for complex: must be array[2].");
+ double re, im;
+diff --git a/Lib/javascript/v8/javascripthelpers.swg b/Lib/javascript/v8/javascripthelpers.swg
+index 80fbd7aa1a..d722581552 100644
+--- a/Lib/javascript/v8/javascripthelpers.swg
++++ b/Lib/javascript/v8/javascripthelpers.swg
+@@ -1,39 +1,26 @@
+ %insert(runtime) %{
+
+-// Note: since 3.19 there are new CallBack types, since 03.21.9 the old ones have been removed
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903)
+-typedef v8::InvocationCallback SwigV8FunctionCallback;
+-typedef v8::AccessorGetter SwigV8AccessorGetterCallback;
+-typedef v8::AccessorSetter SwigV8AccessorSetterCallback;
+-typedef v8::AccessorInfo SwigV8PropertyCallbackInfoVoid;
+-#elif (V8_MAJOR_VERSION-0) < 5
+-typedef v8::FunctionCallback SwigV8FunctionCallback;
+-typedef v8::AccessorGetterCallback SwigV8AccessorGetterCallback;
+-typedef v8::AccessorSetterCallback SwigV8AccessorSetterCallback;
+-typedef v8::PropertyCallbackInfo<void> SwigV8PropertyCallbackInfoVoid;
+-#else
+ typedef v8::FunctionCallback SwigV8FunctionCallback;
+ typedef v8::AccessorNameGetterCallback SwigV8AccessorGetterCallback;
+ typedef v8::AccessorNameSetterCallback SwigV8AccessorSetterCallback;
+ typedef v8::PropertyCallbackInfo<void> SwigV8PropertyCallbackInfoVoid;
+-#endif
+
+ /**
+ * Creates a class template for a class with specified initialization function.
+ */
+-SWIGRUNTIME v8::Handle<v8::FunctionTemplate> SWIGV8_CreateClassTemplate(const char* symbol) {
++SWIGRUNTIME v8::Local<v8::FunctionTemplate> SWIGV8_CreateClassTemplate(const char* symbol) {
+ SWIGV8_HANDLESCOPE_ESC();
+
+ v8::Local<v8::FunctionTemplate> class_templ = SWIGV8_FUNCTEMPLATE_NEW_VOID();
+ class_templ->SetClassName(SWIGV8_SYMBOL_NEW(symbol));
+
+- v8::Handle<v8::ObjectTemplate> inst_templ = class_templ->InstanceTemplate();
++ v8::Local<v8::ObjectTemplate> inst_templ = class_templ->InstanceTemplate();
+ inst_templ->SetInternalFieldCount(1);
+
+- v8::Handle<v8::ObjectTemplate> equals_templ = class_templ->PrototypeTemplate();
++ v8::Local<v8::ObjectTemplate> equals_templ = class_templ->PrototypeTemplate();
+ equals_templ->Set(SWIGV8_SYMBOL_NEW("equals"), SWIGV8_FUNCTEMPLATE_NEW(_SWIGV8_wrap_equals));
+
+- v8::Handle<v8::ObjectTemplate> cptr_templ = class_templ->PrototypeTemplate();
++ v8::Local<v8::ObjectTemplate> cptr_templ = class_templ->PrototypeTemplate();
+ cptr_templ->Set(SWIGV8_SYMBOL_NEW("getCPtr"), SWIGV8_FUNCTEMPLATE_NEW(_wrap_getCPtr));
+
+ SWIGV8_ESCAPE(class_templ);
+@@ -42,55 +29,47 @@ SWIGRUNTIME v8::Handle<v8::FunctionTemplate> SWIGV8_CreateClassTemplate(const ch
+ /**
+ * Registers a class method with given name for a given class template.
+ */
+-SWIGRUNTIME void SWIGV8_AddMemberFunction(v8::Handle<v8::FunctionTemplate> class_templ, const char* symbol,
++SWIGRUNTIME void SWIGV8_AddMemberFunction(v8::Local<v8::FunctionTemplate> class_templ, const char* symbol,
+ SwigV8FunctionCallback _func) {
+- v8::Handle<v8::ObjectTemplate> proto_templ = class_templ->PrototypeTemplate();
++ v8::Local<v8::ObjectTemplate> proto_templ = class_templ->PrototypeTemplate();
+ proto_templ->Set(SWIGV8_SYMBOL_NEW(symbol), SWIGV8_FUNCTEMPLATE_NEW(_func));
+ }
+
+ /**
+ * Registers a class property with given name for a given class template.
+ */
+-SWIGRUNTIME void SWIGV8_AddMemberVariable(v8::Handle<v8::FunctionTemplate> class_templ, const char* symbol,
++SWIGRUNTIME void SWIGV8_AddMemberVariable(v8::Local<v8::FunctionTemplate> class_templ, const char* symbol,
+ SwigV8AccessorGetterCallback getter, SwigV8AccessorSetterCallback setter) {
+- v8::Handle<v8::ObjectTemplate> proto_templ = class_templ->InstanceTemplate();
++ v8::Local<v8::ObjectTemplate> proto_templ = class_templ->InstanceTemplate();
+ proto_templ->SetAccessor(SWIGV8_SYMBOL_NEW(symbol), getter, setter);
+ }
+
+ /**
+ * Registers a class method with given name for a given object.
+ */
+-SWIGRUNTIME void SWIGV8_AddStaticFunction(v8::Handle<v8::Object> obj, const char* symbol,
++SWIGRUNTIME void SWIGV8_AddStaticFunction(v8::Local<v8::Object> obj, const char* symbol,
+ const SwigV8FunctionCallback& _func) {
+- obj->Set(SWIGV8_SYMBOL_NEW(symbol), SWIGV8_FUNCTEMPLATE_NEW(_func)->GetFunction());
++#if (NODE_MODULE_VERSION < 72)
++ obj->Set(SWIGV8_SYMBOL_NEW(symbol), SWIGV8_FUNCTEMPLATE_NEW(_func)->GetFunction(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked());
++#else
++ obj->Set(SWIGV8_CURRENT_CONTEXT(), SWIGV8_SYMBOL_NEW(symbol), SWIGV8_FUNCTEMPLATE_NEW(_func)->GetFunction(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked());
++#endif
+ }
+
+ /**
+ * Registers a class method with given name for a given object.
+ */
+-SWIGRUNTIME void SWIGV8_AddStaticVariable(v8::Handle<v8::Object> obj, const char* symbol,
++SWIGRUNTIME void SWIGV8_AddStaticVariable(v8::Local<v8::Object> obj, const char* symbol,
+ SwigV8AccessorGetterCallback getter, SwigV8AccessorSetterCallback setter) {
+-#if (V8_MAJOR_VERSION-0) < 5
+- obj->SetAccessor(SWIGV8_SYMBOL_NEW(symbol), getter, setter);
+-#else
+ obj->SetAccessor(SWIGV8_CURRENT_CONTEXT(), SWIGV8_SYMBOL_NEW(symbol), getter, setter);
+-#endif
+ }
+
+-#if (V8_MAJOR_VERSION-0) < 5
+-SWIGRUNTIME void JS_veto_set_variable(v8::Local<v8::String> property, v8::Local<v8::Value> value, const SwigV8PropertyCallbackInfoVoid& info)
+-#else
+ SWIGRUNTIME void JS_veto_set_variable(v8::Local<v8::Name> property, v8::Local<v8::Value> value, const SwigV8PropertyCallbackInfoVoid& info)
+-#endif
+ {
+ char buffer[256];
+ char msg[512];
+ int res;
+
+-#if (V8_MAJOR_VERSION-0) < 5
+- property->WriteUtf8(buffer, 256);
+- res = sprintf(msg, "Tried to write read-only variable: %s.", buffer);
+-#else
+ v8::Local<v8::String> sproperty;
+ if (property->ToString(SWIGV8_CURRENT_CONTEXT()).ToLocal(&sproperty)) {
+ SWIGV8_WRITE_UTF8(sproperty, buffer, 256);
+@@ -99,7 +78,6 @@ SWIGRUNTIME void JS_veto_set_variable(v8::Local<v8::Name> property, v8::Local<v8
+ else {
+ res = -1;
+ }
+-#endif
+
+ if(res<0) {
+ SWIG_exception(SWIG_ERROR, "Tried to write read-only variable.");
+diff --git a/Lib/javascript/v8/javascriptinit.swg b/Lib/javascript/v8/javascriptinit.swg
+index 8faf2dd8e1..5f6c219dcc 100644
+--- a/Lib/javascript/v8/javascriptinit.swg
++++ b/Lib/javascript/v8/javascriptinit.swg
+@@ -68,16 +68,16 @@ SWIG_V8_GetModule(void *) {
+ // TODO: is it ok to do that?
+ extern "C"
+ #if (NODE_MODULE_VERSION < 0x000C)
+-void SWIGV8_INIT (v8::Handle<v8::Object> exports)
++void SWIGV8_INIT (v8::Local<v8::Object> exports)
+ #else
+-void SWIGV8_INIT (v8::Handle<v8::Object> exports, v8::Handle<v8::Object> /*module*/)
++void SWIGV8_INIT (v8::Local<v8::Object> exports, v8::Local<v8::Object> /*module*/)
+ #endif
+ {
+ SWIG_InitializeModule(static_cast<void *>(&exports));
+
+ SWIGV8_HANDLESCOPE();
+
+- v8::Handle<v8::Object> exports_obj = exports;
++ v8::Local<v8::Object> exports_obj = exports;
+ %}
+
+
+diff --git a/Lib/javascript/v8/javascriptprimtypes.swg b/Lib/javascript/v8/javascriptprimtypes.swg
+index f76be983b1..41635e9d2d 100644
+--- a/Lib/javascript/v8/javascriptprimtypes.swg
++++ b/Lib/javascript/v8/javascriptprimtypes.swg
+@@ -6,7 +6,7 @@
+
+ %fragment(SWIG_From_frag(bool),"header") {
+ SWIGINTERNINLINE
+-v8::Handle<v8::Value>
++v8::Local<v8::Value>
+ SWIG_From_dec(bool)(bool value)
+ {
+ return SWIGV8_BOOLEAN_NEW(value);
+@@ -16,7 +16,7 @@ SWIG_From_dec(bool)(bool value)
+ %fragment(SWIG_AsVal_frag(bool),"header",
+ fragment=SWIG_AsVal_frag(long)) {
+ SWIGINTERN
+-int SWIG_AsVal_dec(bool)(v8::Handle<v8::Value> obj, bool *val)
++int SWIG_AsVal_dec(bool)(v8::Local<v8::Value> obj, bool *val)
+ {
+ if(!obj->IsBoolean()) {
+ return SWIG_ERROR;
+@@ -31,7 +31,7 @@ int SWIG_AsVal_dec(bool)(v8::Handle<v8::Value> obj, bool *val)
+
+ %fragment(SWIG_From_frag(int),"header") {
+ SWIGINTERNINLINE
+-v8::Handle<v8::Value> SWIG_From_dec(int)(int value)
++v8::Local<v8::Value> SWIG_From_dec(int)(int value)
+ {
+ return SWIGV8_INT32_NEW(value);
+ }
+@@ -39,7 +39,7 @@ v8::Handle<v8::Value> SWIG_From_dec(int)(int value)
+
+ %fragment(SWIG_AsVal_frag(int),"header") {
+ SWIGINTERN
+-int SWIG_AsVal_dec(int)(v8::Handle<v8::Value> valRef, int* val)
++int SWIG_AsVal_dec(int)(v8::Local<v8::Value> valRef, int* val)
+ {
+ if (!valRef->IsNumber()) {
+ return SWIG_TypeError;
+@@ -54,7 +54,7 @@ int SWIG_AsVal_dec(int)(v8::Handle<v8::Value> valRef, int* val)
+
+ %fragment(SWIG_From_frag(long),"header") {
+ SWIGINTERNINLINE
+-v8::Handle<v8::Value> SWIG_From_dec(long)(long value)
++v8::Local<v8::Value> SWIG_From_dec(long)(long value)
+ {
+ return SWIGV8_NUMBER_NEW(value);
+ }
+@@ -63,7 +63,7 @@ v8::Handle<v8::Value> SWIG_From_dec(long)(long value)
+ %fragment(SWIG_AsVal_frag(long),"header",
+ fragment="SWIG_CanCastAsInteger") {
+ SWIGINTERN
+-int SWIG_AsVal_dec(long)(v8::Handle<v8::Value> obj, long* val)
++int SWIG_AsVal_dec(long)(v8::Local<v8::Value> obj, long* val)
+ {
+ if (!obj->IsNumber()) {
+ return SWIG_TypeError;
+@@ -79,7 +79,7 @@ int SWIG_AsVal_dec(long)(v8::Handle<v8::Value> obj, long* val)
+ %fragment(SWIG_From_frag(unsigned long),"header",
+ fragment=SWIG_From_frag(long)) {
+ SWIGINTERNINLINE
+-v8::Handle<v8::Value> SWIG_From_dec(unsigned long)(unsigned long value)
++v8::Local<v8::Value> SWIG_From_dec(unsigned long)(unsigned long value)
+ {
+ return (value > LONG_MAX) ?
+ SWIGV8_INTEGER_NEW_UNS(value) : SWIGV8_INTEGER_NEW(%numeric_cast(value,long));
+@@ -89,7 +89,7 @@ v8::Handle<v8::Value> SWIG_From_dec(unsigned long)(unsigned long value)
+ %fragment(SWIG_AsVal_frag(unsigned long),"header",
+ fragment="SWIG_CanCastAsInteger") {
+ SWIGINTERN
+-int SWIG_AsVal_dec(unsigned long)(v8::Handle<v8::Value> obj, unsigned long *val)
++int SWIG_AsVal_dec(unsigned long)(v8::Local<v8::Value> obj, unsigned long *val)
+ {
+ if(!obj->IsNumber()) {
+ return SWIG_TypeError;
+@@ -115,7 +115,7 @@ int SWIG_AsVal_dec(unsigned long)(v8::Handle<v8::Value> obj, unsigned long *val)
+ fragment="SWIG_LongLongAvailable") {
+ %#ifdef SWIG_LONG_LONG_AVAILABLE
+ SWIGINTERNINLINE
+-v8::Handle<v8::Value> SWIG_From_dec(long long)(long long value)
++v8::Local<v8::Value> SWIG_From_dec(long long)(long long value)
+ {
+ return SWIGV8_NUMBER_NEW(value);
+ }
+@@ -128,7 +128,7 @@ v8::Handle<v8::Value> SWIG_From_dec(long long)(long long value)
+ fragment="SWIG_LongLongAvailable") {
+ %#ifdef SWIG_LONG_LONG_AVAILABLE
+ SWIGINTERN
+-int SWIG_AsVal_dec(long long)(v8::Handle<v8::Value> obj, long long* val)
++int SWIG_AsVal_dec(long long)(v8::Local<v8::Value> obj, long long* val)
+ {
+ if (!obj->IsNumber()) {
+ return SWIG_TypeError;
+@@ -148,7 +148,7 @@ int SWIG_AsVal_dec(long long)(v8::Handle<v8::Value> obj, long long* val)
+ fragment="SWIG_LongLongAvailable") {
+ %#ifdef SWIG_LONG_LONG_AVAILABLE
+ SWIGINTERNINLINE
+-v8::Handle<v8::Value> SWIG_From_dec(unsigned long long)(unsigned long long value)
++v8::Local<v8::Value> SWIG_From_dec(unsigned long long)(unsigned long long value)
+ {
+ return (value > LONG_MAX) ?
+ SWIGV8_INTEGER_NEW_UNS(value) : SWIGV8_INTEGER_NEW(%numeric_cast(value,long));
+@@ -162,7 +162,7 @@ v8::Handle<v8::Value> SWIG_From_dec(unsigned long long)(unsigned long long value
+ fragment="SWIG_LongLongAvailable") {
+ %#ifdef SWIG_LONG_LONG_AVAILABLE
+ SWIGINTERN
+-int SWIG_AsVal_dec(unsigned long long)(v8::Handle<v8::Value> obj, unsigned long long *val)
++int SWIG_AsVal_dec(unsigned long long)(v8::Local<v8::Value> obj, unsigned long long *val)
+ {
+ if(!obj->IsNumber()) {
+ return SWIG_TypeError;
+@@ -185,7 +185,7 @@ int SWIG_AsVal_dec(unsigned long long)(v8::Handle<v8::Value> obj, unsigned long
+
+ %fragment(SWIG_From_frag(double),"header") {
+ SWIGINTERN
+-v8::Handle<v8::Value> SWIG_From_dec(double) (double val)
++v8::Local<v8::Value> SWIG_From_dec(double) (double val)
+ {
+ return SWIGV8_NUMBER_NEW(val);
+ }
+@@ -193,7 +193,7 @@ v8::Handle<v8::Value> SWIG_From_dec(double) (double val)
+
+ %fragment(SWIG_AsVal_frag(double),"header") {
+ SWIGINTERN
+-int SWIG_AsVal_dec(double)(v8::Handle<v8::Value> obj, double *val)
++int SWIG_AsVal_dec(double)(v8::Local<v8::Value> obj, double *val)
+ {
+ if(!obj->IsNumber()) {
+ return SWIG_TypeError;
+@@ -203,4 +203,3 @@ int SWIG_AsVal_dec(double)(v8::Handle<v8::Value> obj, double *val)
+ return SWIG_OK;
+ }
+ }
+-
+diff --git a/Lib/javascript/v8/javascriptrun.swg b/Lib/javascript/v8/javascriptrun.swg
+index 2452f4040d..2023d023da 100644
+--- a/Lib/javascript/v8/javascriptrun.swg
++++ b/Lib/javascript/v8/javascriptrun.swg
+@@ -5,70 +5,37 @@
+
+ // First v8 version that uses "SetWeak" and not "MakeWeak"
+
+-#define SWIGV8_SETWEAK_VERSION 0x032224
+-
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031803)
+-#define SWIGV8_STRING_NEW2(cstr, len) v8::String::New(cstr, len)
+-#else
++#if (NODE_MODULE_VERSION < 72)
+ #define SWIGV8_STRING_NEW2(cstr, len) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), cstr, v8::String::kNormalString, len)
++#else
++#define SWIGV8_STRING_NEW2(cstr, len) (v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), cstr, v8::NewStringType::kNormal, len)).ToLocalChecked()
+ #endif
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903)
+-typedef v8::Handle<v8::Value> SwigV8ReturnValue;
+-typedef v8::Arguments SwigV8Arguments;
+-typedef v8::AccessorInfo SwigV8PropertyCallbackInfo;
+-#define SWIGV8_RETURN(val) return scope.Close(val)
+-#define SWIGV8_RETURN_INFO(val, info) return scope.Close(val)
+-#else
+ typedef void SwigV8ReturnValue;
+ typedef v8::FunctionCallbackInfo<v8::Value> SwigV8Arguments;
+ typedef v8::PropertyCallbackInfo<v8::Value> SwigV8PropertyCallbackInfo;
+ #define SWIGV8_RETURN(val) args.GetReturnValue().Set(val); return
+ #define SWIGV8_RETURN_INFO(val, info) info.GetReturnValue().Set(val); return
+-#endif
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032117)
+-#define SWIGV8_HANDLESCOPE() v8::HandleScope scope
+-#define SWIGV8_HANDLESCOPE_ESC() v8::HandleScope scope
+-#define SWIGV8_ESCAPE(val) return scope.Close(val)
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032224)
+-#define SWIGV8_HANDLESCOPE() v8::HandleScope scope(v8::Isolate::GetCurrent());
+-#define SWIGV8_HANDLESCOPE_ESC() v8::HandleScope scope(v8::Isolate::GetCurrent());
+-#define SWIGV8_ESCAPE(val) return scope.Close(val)
+-#else
+ #define SWIGV8_HANDLESCOPE() v8::HandleScope scope(v8::Isolate::GetCurrent());
+ #define SWIGV8_HANDLESCOPE_ESC() v8::EscapableHandleScope scope(v8::Isolate::GetCurrent());
+ #define SWIGV8_ESCAPE(val) return scope.Escape(val)
+-#endif
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032224)
+-#define SWIGV8_ADJUST_MEMORY(size) v8::V8::AdjustAmountOfExternalAllocatedMemory(size)
+-#define SWIGV8_CURRENT_CONTEXT() v8::Context::GetCurrent()
+-#define SWIGV8_THROW_EXCEPTION(err) v8::ThrowException(err)
+-#define SWIGV8_STRING_NEW(str) v8::String::New(str)
+-#define SWIGV8_SYMBOL_NEW(sym) v8::String::NewSymbol(sym)
++#if (NODE_MODULE_VERSION < 72)
++#define SWIGV8_ADJUST_MEMORY(size) v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(size)
++#define SWIGV8_CURRENT_CONTEXT() v8::Isolate::GetCurrent()->GetCurrentContext()
++#define SWIGV8_THROW_EXCEPTION(err) v8::Isolate::GetCurrent()->ThrowException(err)
++#define SWIGV8_STRING_NEW(str) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), str, v8::String::kNormalString)
++#define SWIGV8_SYMBOL_NEW(sym) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), sym, v8::String::kNormalString)
+ #else
+ #define SWIGV8_ADJUST_MEMORY(size) v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(size)
+ #define SWIGV8_CURRENT_CONTEXT() v8::Isolate::GetCurrent()->GetCurrentContext()
+ #define SWIGV8_THROW_EXCEPTION(err) v8::Isolate::GetCurrent()->ThrowException(err)
+-#define SWIGV8_STRING_NEW(str) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), str)
+-#define SWIGV8_SYMBOL_NEW(sym) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), sym)
++#define SWIGV8_STRING_NEW(str) (v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), str, v8::NewStringType::kNormal)).ToLocalChecked()
++#define SWIGV8_SYMBOL_NEW(sym) (v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), sym, v8::NewStringType::kNormal)).ToLocalChecked()
+ #endif
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032318)
+-#define SWIGV8_ARRAY_NEW() v8::Array::New()
+-#define SWIGV8_BOOLEAN_NEW(bool) v8::Boolean::New(bool)
+-#define SWIGV8_EXTERNAL_NEW(val) v8::External::New(val)
+-#define SWIGV8_FUNCTEMPLATE_NEW(func) v8::FunctionTemplate::New(func)
+-#define SWIGV8_FUNCTEMPLATE_NEW_VOID() v8::FunctionTemplate::New()
+-#define SWIGV8_INT32_NEW(num) v8::Int32::New(num)
+-#define SWIGV8_INTEGER_NEW(num) v8::Integer::New(num)
+-#define SWIGV8_INTEGER_NEW_UNS(num) v8::Integer::NewFromUnsigned(num)
+-#define SWIGV8_NUMBER_NEW(num) v8::Number::New(num)
+-#define SWIGV8_OBJECT_NEW() v8::Object::New()
+-#define SWIGV8_UNDEFINED() v8::Undefined()
+-#define SWIGV8_NULL() v8::Null()
+-#else
++
+ #define SWIGV8_ARRAY_NEW() v8::Array::New(v8::Isolate::GetCurrent())
+ #define SWIGV8_BOOLEAN_NEW(bool) v8::Boolean::New(v8::Isolate::GetCurrent(), bool)
+ #define SWIGV8_EXTERNAL_NEW(val) v8::External::New(v8::Isolate::GetCurrent(), val)
+@@ -81,15 +48,8 @@ typedef v8::PropertyCallbackInfo<v8::Value> SwigV8PropertyCallbackInfo;
+ #define SWIGV8_OBJECT_NEW() v8::Object::New(v8::Isolate::GetCurrent())
+ #define SWIGV8_UNDEFINED() v8::Undefined(v8::Isolate::GetCurrent())
+ #define SWIGV8_NULL() v8::Null(v8::Isolate::GetCurrent())
+-#endif
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+-#define SWIGV8_SET_CLASS_TEMPL(class_templ, class) class_templ = v8::Persistent<v8::FunctionTemplate>::New(class);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+-#define SWIGV8_SET_CLASS_TEMPL(class_templ, class) class_templ = v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::GetCurrent(), class);
+-#else
+ #define SWIGV8_SET_CLASS_TEMPL(class_templ, class) class_templ.Reset(v8::Isolate::GetCurrent(), class);
+-#endif
+
+ #ifdef NODE_VERSION
+ #if NODE_VERSION_AT_LEAST(10, 12, 0)
+@@ -98,23 +58,17 @@ typedef v8::PropertyCallbackInfo<v8::Value> SwigV8PropertyCallbackInfo;
+ #endif
+
+ //Necessary to check Node.js version because V8 API changes are backported in Node.js
+-#if (defined(NODE_VERSION) && !defined(SWIG_NODE_AT_LEAST_1012)) || \
+- (!defined(NODE_VERSION) && (V8_MAJOR_VERSION-0) < 7)
+-#define SWIGV8_TO_OBJECT(handle) (handle)->ToObject()
+-#define SWIGV8_TO_STRING(handle) (handle)->ToString()
+-#define SWIGV8_NUMBER_VALUE(handle) (handle)->NumberValue()
+-#define SWIGV8_INTEGER_VALUE(handle) (handle)->IntegerValue()
+-#define SWIGV8_BOOLEAN_VALUE(handle) (handle)->BooleanValue()
+-#define SWIGV8_WRITE_UTF8(handle, buffer, len) (handle)->WriteUtf8(buffer, len)
+-#define SWIGV8_UTF8_LENGTH(handle) (handle)->Utf8Length()
+-#else
+ #define SWIGV8_TO_OBJECT(handle) (handle)->ToObject(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked()
+ #define SWIGV8_TO_STRING(handle) (handle)->ToString(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked()
+ #define SWIGV8_NUMBER_VALUE(handle) (handle)->NumberValue(SWIGV8_CURRENT_CONTEXT()).ToChecked()
+ #define SWIGV8_INTEGER_VALUE(handle) (handle)->IntegerValue(SWIGV8_CURRENT_CONTEXT()).ToChecked()
+-#define SWIGV8_BOOLEAN_VALUE(handle) (handle)->BooleanValue(SWIGV8_CURRENT_CONTEXT()).ToChecked()
+ #define SWIGV8_WRITE_UTF8(handle, buffer, len) (handle)->WriteUtf8(v8::Isolate::GetCurrent(), buffer, len)
+ #define SWIGV8_UTF8_LENGTH(handle) (handle)->Utf8Length(v8::Isolate::GetCurrent())
++
++#if (NODE_MODULE_VERSION < 72)
++#define SWIGV8_BOOLEAN_VALUE(handle) (handle)->BooleanValue(SWIGV8_CURRENT_CONTEXT()).ToChecked()
++#else
++#define SWIGV8_BOOLEAN_VALUE(handle) (handle)->BooleanValue(v8::Isolate::GetCurrent())
+ #endif
+
+ /* ---------------------------------------------------------------------------
+@@ -163,7 +117,7 @@ public:
+ SWIGV8_THROW_EXCEPTION(err);
+ }
+ }
+- v8::Handle<v8::Value> err;
++ v8::Local<v8::Value> err;
+ };
+
+ /* ---------------------------------------------------------------------------
+@@ -182,23 +136,8 @@ public:
+ };
+
+ ~SWIGV8_Proxy() {
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+- handle.ClearWeak();
+- handle.Dispose();
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100)
+- handle.ClearWeak(v8::Isolate::GetCurrent());
+- handle.Dispose(v8::Isolate::GetCurrent());
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION)
+- handle.ClearWeak();
+- handle.Dispose();
+-#else
+ handle.ClearWeak();
+ handle.Reset();
+-#endif
+-
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION)
+- handle.Clear();
+-#endif
+
+ SWIGV8_ADJUST_MEMORY(-SWIGV8_AVG_OBJ_SIZE);
+ }
+@@ -213,32 +152,17 @@ class SWIGV8_ClientData {
+ public:
+ v8::Persistent<v8::FunctionTemplate> class_templ;
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+- void (*dtor) (v8::Persistent< v8::Value> object, void *parameter);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+- void (*dtor) (v8::Isolate *isolate, v8::Persistent< v8::Value> object, void *parameter);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION)
+- void (*dtor) (v8::Isolate *isolate, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy);
+-#elif (V8_MAJOR_VERSION-0) < 5
+- void (*dtor) (const v8::WeakCallbackData<v8::Object, SWIGV8_Proxy> &data);
+-#else
+ void (*dtor) (const v8::WeakCallbackInfo<SWIGV8_Proxy> &data);
+-#endif
+ };
+
+ SWIGRUNTIME v8::Persistent<v8::FunctionTemplate> SWIGV8_SWIGTYPE_Proxy_class_templ;
+
+-SWIGRUNTIME int SWIG_V8_ConvertInstancePtr(v8::Handle<v8::Object> objRef, void **ptr, swig_type_info *info, int flags) {
++SWIGRUNTIME int SWIG_V8_ConvertInstancePtr(v8::Local<v8::Object> objRef, void **ptr, swig_type_info *info, int flags) {
+ SWIGV8_HANDLESCOPE();
+
+ if(objRef->InternalFieldCount() < 1) return SWIG_ERROR;
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511)
+- v8::Handle<v8::Value> cdataRef = objRef->GetInternalField(0);
+- SWIGV8_Proxy *cdata = static_cast<SWIGV8_Proxy *>(v8::External::Unwrap(cdataRef));
+-#else
+ SWIGV8_Proxy *cdata = static_cast<SWIGV8_Proxy *>(objRef->GetAlignedPointerFromInternalField(0));
+-#endif
+
+ if(cdata == NULL) {
+ return SWIG_ERROR;
+@@ -261,39 +185,21 @@ SWIGRUNTIME int SWIG_V8_ConvertInstancePtr(v8::Handle<v8::Object> objRef, void *
+ }
+
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+-SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(v8::Persistent< v8::Value > object, void *parameter) {
+- SWIGV8_Proxy *proxy = static_cast<SWIGV8_Proxy *>(parameter);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+-SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(v8::Isolate *, v8::Persistent< v8::Value > object, void *parameter) {
+- SWIGV8_Proxy *proxy = static_cast<SWIGV8_Proxy *>(parameter);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION)
+-SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(v8::Isolate *, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy) {
+-#elif (V8_MAJOR_VERSION-0) < 5
+-SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(const v8::WeakCallbackData<v8::Object, SWIGV8_Proxy> &data) {
+- SWIGV8_Proxy *proxy = data.GetParameter();
+-#else
+ SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(const v8::WeakCallbackInfo<SWIGV8_Proxy> &data) {
+ SWIGV8_Proxy *proxy = data.GetParameter();
+-#endif
+
+ delete proxy;
+ }
+
+-SWIGRUNTIME int SWIG_V8_GetInstancePtr(v8::Handle<v8::Value> valRef, void **ptr) {
++SWIGRUNTIME int SWIG_V8_GetInstancePtr(v8::Local<v8::Value> valRef, void **ptr) {
+ if(!valRef->IsObject()) {
+ return SWIG_TypeError;
+ }
+- v8::Handle<v8::Object> objRef = SWIGV8_TO_OBJECT(valRef);
++ v8::Local<v8::Object> objRef = SWIGV8_TO_OBJECT(valRef);
+
+ if(objRef->InternalFieldCount() < 1) return SWIG_ERROR;
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511)
+- v8::Handle<v8::Value> cdataRef = objRef->GetInternalField(0);
+- SWIGV8_Proxy *cdata = static_cast<SWIGV8_Proxy *>(v8::External::Unwrap(cdataRef));
+-#else
+ SWIGV8_Proxy *cdata = static_cast<SWIGV8_Proxy *>(objRef->GetAlignedPointerFromInternalField(0));
+-#endif
+
+ if(cdata == NULL) {
+ return SWIG_ERROR;
+@@ -304,70 +210,31 @@ SWIGRUNTIME int SWIG_V8_GetInstancePtr(v8::Handle<v8::Value> valRef, void **ptr)
+ return SWIG_OK;
+ }
+
+-SWIGRUNTIME void SWIGV8_SetPrivateData(v8::Handle<v8::Object> obj, void *ptr, swig_type_info *info, int flags) {
++SWIGRUNTIME void SWIGV8_SetPrivateData(v8::Local<v8::Object> obj, void *ptr, swig_type_info *info, int flags) {
+ SWIGV8_Proxy *cdata = new SWIGV8_Proxy();
+ cdata->swigCObject = ptr;
+ cdata->swigCMemOwn = (flags & SWIG_POINTER_OWN) ? 1 : 0;
+ cdata->info = info;
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511)
+- obj->SetPointerInInternalField(0, cdata);
+-#else
+ obj->SetAlignedPointerInInternalField(0, cdata);
+-#endif
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+- cdata->handle = v8::Persistent<v8::Object>::New(obj);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+- cdata->handle = v8::Persistent<v8::Object>::New(v8::Isolate::GetCurrent(), obj);
+-#else
+ cdata->handle.Reset(v8::Isolate::GetCurrent(), obj);
+-#endif
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+- // clientdata must be set for owned data as we need to register the dtor
+- if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) {
+- cdata->handle.MakeWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor);
+- } else {
+- cdata->handle.MakeWeak(cdata, SWIGV8_Proxy_DefaultDtor);
+- }
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031918)
+- if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) {
+- cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor);
+- } else {
+- cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, SWIGV8_Proxy_DefaultDtor);
+- }
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION)
+- if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) {
+- cdata->handle.MakeWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor);
+- } else {
+- cdata->handle.MakeWeak(cdata, SWIGV8_Proxy_DefaultDtor);
+- }
+-#elif (V8_MAJOR_VERSION-0) < 5
+- if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) {
+- cdata->handle.SetWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor);
+- } else {
+- cdata->handle.SetWeak(cdata, SWIGV8_Proxy_DefaultDtor);
+- }
+-#else
+ if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) {
+ cdata->handle.SetWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor, v8::WeakCallbackType::kParameter);
+ } else {
+ cdata->handle.SetWeak(cdata, SWIGV8_Proxy_DefaultDtor, v8::WeakCallbackType::kParameter);
+ }
+-#endif
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+- cdata->handle.MarkIndependent();
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100)
+- cdata->handle.MarkIndependent(v8::Isolate::GetCurrent());
+-#else
++#if (NODE_MODULE_VERSION < 72)
+ cdata->handle.MarkIndependent();
++// Looks like future versions do not require that anymore:
++// https://monorail-prod.appspot.com/p/chromium/issues/detail?id=923361#c11
+ #endif
+
+ }
+
+-SWIGRUNTIME int SWIG_V8_ConvertPtr(v8::Handle<v8::Value> valRef, void **ptr, swig_type_info *info, int flags) {
++SWIGRUNTIME int SWIG_V8_ConvertPtr(v8::Local<v8::Value> valRef, void **ptr, swig_type_info *info, int flags) {
+ SWIGV8_HANDLESCOPE();
+
+ /* special case: JavaScript null => C NULL pointer */
+@@ -378,31 +245,20 @@ SWIGRUNTIME int SWIG_V8_ConvertPtr(v8::Handle<v8::Value> valRef, void **ptr, swi
+ if(!valRef->IsObject()) {
+ return SWIG_TypeError;
+ }
+- v8::Handle<v8::Object> objRef = SWIGV8_TO_OBJECT(valRef);
++ v8::Local<v8::Object> objRef = SWIGV8_TO_OBJECT(valRef);
+ return SWIG_V8_ConvertInstancePtr(objRef, ptr, info, flags);
+ }
+
+-SWIGRUNTIME v8::Handle<v8::Value> SWIG_V8_NewPointerObj(void *ptr, swig_type_info *info, int flags) {
++SWIGRUNTIME v8::Local<v8::Value> SWIG_V8_NewPointerObj(void *ptr, swig_type_info *info, int flags) {
+ SWIGV8_HANDLESCOPE_ESC();
+
+- v8::Handle<v8::FunctionTemplate> class_templ;
++ v8::Local<v8::FunctionTemplate> class_templ;
+
+ if (ptr == NULL) {
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903)
+- SWIGV8_ESCAPE(SWIGV8_NULL());
+-#else
+ v8::Local<v8::Primitive> result = SWIGV8_NULL();
+ SWIGV8_ESCAPE(result);
+-#endif
+ }
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903)
+- if(info->clientdata != 0) {
+- class_templ = ((SWIGV8_ClientData*) info->clientdata)->class_templ;
+- } else {
+- class_templ = SWIGV8_SWIGTYPE_Proxy_class_templ;
+- }
+-#else
+ v8::Isolate *isolate = v8::Isolate::GetCurrent();
+
+ if(info->clientdata != 0) {
+@@ -410,10 +266,13 @@ SWIGRUNTIME v8::Handle<v8::Value> SWIG_V8_NewPointerObj(void *ptr, swig_type_inf
+ } else {
+ class_templ = v8::Local<v8::FunctionTemplate>::New(isolate, SWIGV8_SWIGTYPE_Proxy_class_templ);
+ }
+-#endif
+
+-// v8::Handle<v8::Object> result = class_templ->InstanceTemplate()->NewInstance();
++#if (NODE_MODULE_VERSION < 72)
+ v8::Local<v8::Object> result = class_templ->InstanceTemplate()->NewInstance();
++#else
++ v8::Local<v8::Object> result = class_templ->InstanceTemplate()->NewInstance(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked();
++#endif
++
+ SWIGV8_SetPrivateData(result, ptr, info, flags);
+
+ SWIGV8_ESCAPE(result);
+@@ -433,7 +292,7 @@ SWIGRUNTIME v8::Handle<v8::Value> SWIG_V8_NewPointerObj(void *ptr, swig_type_inf
+ SWIGRUNTIME SwigV8ReturnValue _SWIGV8_wrap_equals(const SwigV8Arguments &args) {
+ SWIGV8_HANDLESCOPE();
+
+- v8::Handle<v8::Value> jsresult;
++ v8::Local<v8::Value> jsresult;
+ void *arg1 = (void *) 0 ;
+ void *arg2 = (void *) 0 ;
+ bool result;
+@@ -463,7 +322,7 @@ fail:
+ SWIGRUNTIME SwigV8ReturnValue _wrap_getCPtr(const SwigV8Arguments &args) {
+ SWIGV8_HANDLESCOPE();
+
+- v8::Handle<v8::Value> jsresult;
++ v8::Local<v8::Value> jsresult;
+ void *arg1 = (void *) 0 ;
+ long result;
+ int res1;
+@@ -502,37 +361,29 @@ public:
+ };
+
+ SWIGRUNTIMEINLINE
+-int SwigV8Packed_Check(v8::Handle<v8::Value> valRef) {
++int SwigV8Packed_Check(v8::Local<v8::Value> valRef) {
+ SWIGV8_HANDLESCOPE();
+
+- v8::Handle<v8::Object> objRef = SWIGV8_TO_OBJECT(valRef);
++ v8::Local<v8::Object> objRef = SWIGV8_TO_OBJECT(valRef);
+ if(objRef->InternalFieldCount() < 1) return false;
+-#if (V8_MAJOR_VERSION-0) < 5
+- v8::Handle<v8::Value> flag = objRef->GetHiddenValue(SWIGV8_STRING_NEW("__swig__packed_data__"));
+-#else
+ v8::Local<v8::Private> privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), SWIGV8_STRING_NEW("__swig__packed_data__"));
+ v8::Local<v8::Value> flag;
+ if (!objRef->GetPrivate(SWIGV8_CURRENT_CONTEXT(), privateKey).ToLocal(&flag))
+ return false;
+-#endif
++
+ return (flag->IsBoolean() && SWIGV8_BOOLEAN_VALUE(flag));
+ }
+
+ SWIGRUNTIME
+-swig_type_info *SwigV8Packed_UnpackData(v8::Handle<v8::Value> valRef, void *ptr, size_t size) {
++swig_type_info *SwigV8Packed_UnpackData(v8::Local<v8::Value> valRef, void *ptr, size_t size) {
+ if (SwigV8Packed_Check(valRef)) {
+ SWIGV8_HANDLESCOPE();
+
+ SwigV8PackedData *sobj;
+
+- v8::Handle<v8::Object> objRef = SWIGV8_TO_OBJECT(valRef);
++ v8::Local<v8::Object> objRef = SWIGV8_TO_OBJECT(valRef);
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511)
+- v8::Handle<v8::Value> cdataRef = objRef->GetInternalField(0);
+- sobj = static_cast<SwigV8PackedData*>(v8::External::Unwrap(cdataRef));
+-#else
+ sobj = static_cast<SwigV8PackedData*>(objRef->GetAlignedPointerFromInternalField(0));
+-#endif
+ if (sobj == NULL || sobj->size != size) return 0;
+ memcpy(ptr, sobj->data, size);
+ return sobj->type;
+@@ -542,7 +393,7 @@ swig_type_info *SwigV8Packed_UnpackData(v8::Handle<v8::Value> valRef, void *ptr,
+ }
+
+ SWIGRUNTIME
+-int SWIGV8_ConvertPacked(v8::Handle<v8::Value> valRef, void *ptr, size_t sz, swig_type_info *ty) {
++int SWIGV8_ConvertPacked(v8::Local<v8::Value> valRef, void *ptr, size_t sz, swig_type_info *ty) {
+ swig_type_info *to = SwigV8Packed_UnpackData(valRef, ptr, sz);
+ if (!to) return SWIG_ERROR;
+ if (ty) {
+@@ -555,89 +406,32 @@ int SWIGV8_ConvertPacked(v8::Handle<v8::Value> valRef, void *ptr, size_t sz, swi
+ return SWIG_OK;
+ }
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+-SWIGRUNTIME void _wrap_SwigV8PackedData_delete(v8::Persistent< v8::Value > object, void *parameter) {
+- SwigV8PackedData *cdata = static_cast<SwigV8PackedData *>(parameter);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+-SWIGRUNTIME void _wrap_SwigV8PackedData_delete(v8::Isolate *isolate, v8::Persistent<v8::Value> object, void *parameter) {
+- SwigV8PackedData *cdata = static_cast<SwigV8PackedData *>(parameter);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION)
+-SWIGRUNTIME void _wrap_SwigV8PackedData_delete(v8::Isolate *isolate, v8::Persistent<v8::Object> *object, SwigV8PackedData *cdata) {
+-#elif (V8_MAJOR_VERSION-0) < 5
+-SWIGRUNTIME void _wrap_SwigV8PackedData_delete(const v8::WeakCallbackData<v8::Object, SwigV8PackedData> &data) {
+- v8::Local<v8::Object> object = data.GetValue();
+- SwigV8PackedData *cdata = data.GetParameter();
+-#else
+ SWIGRUNTIME void _wrap_SwigV8PackedData_delete(const v8::WeakCallbackInfo<SwigV8PackedData> &data) {
+ SwigV8PackedData *cdata = data.GetParameter();
+-#endif
+
+ delete cdata;
+-
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+- object.Clear();
+- object.Dispose();
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+- object.Clear();
+- object.Dispose(isolate);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100)
+- object->Dispose(isolate);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION)
+- object->Dispose();
+-#elif (V8_MAJOR_VERSION-0) < 5
+- object.Clear();
+-#endif
+ }
+
+ SWIGRUNTIME
+-v8::Handle<v8::Value> SWIGV8_NewPackedObj(void *data, size_t size, swig_type_info *type) {
++v8::Local<v8::Value> SWIGV8_NewPackedObj(void *data, size_t size, swig_type_info *type) {
+ SWIGV8_HANDLESCOPE_ESC();
+
+ SwigV8PackedData *cdata = new SwigV8PackedData(data, size, type);
+-// v8::Handle<v8::Object> obj = SWIGV8_OBJECT_NEW();
+ v8::Local<v8::Object> obj = SWIGV8_OBJECT_NEW();
+
+-#if (V8_MAJOR_VERSION-0) < 5
+- obj->SetHiddenValue(SWIGV8_STRING_NEW("__swig__packed_data__"), SWIGV8_BOOLEAN_NEW(true));
+-#else
+ v8::Local<v8::Private> privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), SWIGV8_STRING_NEW("__swig__packed_data__"));
+ obj->SetPrivate(SWIGV8_CURRENT_CONTEXT(), privateKey, SWIGV8_BOOLEAN_NEW(true));
+-#endif
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511)
+- obj->SetPointerInInternalField(0, cdata);
+-#else
+ obj->SetAlignedPointerInInternalField(0, cdata);
+-#endif
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+- cdata->handle = v8::Persistent<v8::Object>::New(obj);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+- cdata->handle = v8::Persistent<v8::Object>::New(v8::Isolate::GetCurrent(), obj);
+-#else
+ cdata->handle.Reset(v8::Isolate::GetCurrent(), obj);
+-#endif
+-
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+- cdata->handle.MakeWeak(cdata, _wrap_SwigV8PackedData_delete);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031918)
+- cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, _wrap_SwigV8PackedData_delete);
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION)
+- cdata->handle.MakeWeak(cdata, _wrap_SwigV8PackedData_delete);
+-#elif (V8_MAJOR_VERSION-0) < 5
+- cdata->handle.SetWeak(cdata, _wrap_SwigV8PackedData_delete);
+-// v8::V8::SetWeak(&cdata->handle, cdata, _wrap_SwigV8PackedData_delete);
+-#else
+ cdata->handle.SetWeak(cdata, _wrap_SwigV8PackedData_delete, v8::WeakCallbackType::kParameter);
+-#endif
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+- cdata->handle.MarkIndependent();
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100)
+- cdata->handle.MarkIndependent(v8::Isolate::GetCurrent());
+-#else
++#if (NODE_MODULE_VERSION < 72)
+ cdata->handle.MarkIndependent();
++// Looks like future versions do not require that anymore:
++// https://monorail-prod.appspot.com/p/chromium/issues/detail?id=923361#c11
+ #endif
+
+ SWIGV8_ESCAPE(obj);
+@@ -654,22 +448,18 @@ v8::Handle<v8::Value> SWIGV8_NewPackedObj(void *data, size_t size, swig_type_inf
+
+ SWIGRUNTIME
+
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903)
+-v8::Handle<v8::Value> SWIGV8_AppendOutput(v8::Handle<v8::Value> result, v8::Handle<v8::Value> obj) {
+-#else
+-v8::Handle<v8::Value> SWIGV8_AppendOutput(v8::Local<v8::Value> result, v8::Handle<v8::Value> obj) {
+-#endif
++v8::Local<v8::Value> SWIGV8_AppendOutput(v8::Local<v8::Value> result, v8::Local<v8::Value> obj) {
+ SWIGV8_HANDLESCOPE_ESC();
+
+ if (result->IsUndefined()) {
+ result = SWIGV8_ARRAY_NEW();
+ }
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903)
+- v8::Handle<v8::Array> arr = v8::Handle<v8::Array>::Cast(result);
+-#else
+ v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(result);
+-#endif
++#if (NODE_MODULE_VERSION < 72)
+ arr->Set(arr->Length(), obj);
++#else
++ arr->Set(SWIGV8_CURRENT_CONTEXT(), arr->Length(), obj);
++#endif
+
+ SWIGV8_ESCAPE(arr);
+ }
+diff --git a/Lib/javascript/v8/javascriptstrings.swg b/Lib/javascript/v8/javascriptstrings.swg
+index e767a6d662..61a937fa52 100644
+--- a/Lib/javascript/v8/javascriptstrings.swg
++++ b/Lib/javascript/v8/javascriptstrings.swg
+@@ -4,10 +4,10 @@
+ * ------------------------------------------------------------ */
+ %fragment("SWIG_AsCharPtrAndSize", "header", fragment="SWIG_pchar_descriptor") {
+ SWIGINTERN int
+-SWIG_AsCharPtrAndSize(v8::Handle<v8::Value> valRef, char** cptr, size_t* psize, int *alloc)
++SWIG_AsCharPtrAndSize(v8::Local<v8::Value> valRef, char** cptr, size_t* psize, int *alloc)
+ {
+ if(valRef->IsString()) {
+- v8::Handle<v8::String> js_str = SWIGV8_TO_STRING(valRef);
++ v8::Local<v8::String> js_str = SWIGV8_TO_STRING(valRef);
+
+ size_t len = SWIGV8_UTF8_LENGTH(js_str) + 1;
+ char* cstr = new char[len];
+@@ -20,7 +20,7 @@ SWIG_AsCharPtrAndSize(v8::Handle<v8::Value> valRef, char** cptr, size_t* psize,
+ return SWIG_OK;
+ } else {
+ if(valRef->IsObject()) {
+- v8::Handle<v8::Object> obj = SWIGV8_TO_OBJECT(valRef);
++ v8::Local<v8::Object> obj = SWIGV8_TO_OBJECT(valRef);
+ // try if the object is a wrapped char[]
+ swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
+ if (pchar_descriptor) {
+@@ -41,7 +41,7 @@ SWIG_AsCharPtrAndSize(v8::Handle<v8::Value> valRef, char** cptr, size_t* psize,
+ }
+
+ %fragment("SWIG_FromCharPtrAndSize","header",fragment="SWIG_pchar_descriptor") {
+-SWIGINTERNINLINE v8::Handle<v8::Value>
++SWIGINTERNINLINE v8::Local<v8::Value>
+ SWIG_FromCharPtrAndSize(const char* carray, size_t size)
+ {
+ if (carray) {
+@@ -49,7 +49,7 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size)
+ // TODO: handle extra long strings
+ return SWIGV8_UNDEFINED();
+ } else {
+- v8::Handle<v8::String> js_str = SWIGV8_STRING_NEW2(carray, size);
++ v8::Local<v8::String> js_str = SWIGV8_STRING_NEW2(carray, size);
+ return js_str;
+ }
+ } else {
+diff --git a/Lib/javascript/v8/javascripttypemaps.swg b/Lib/javascript/v8/javascripttypemaps.swg
+index 4601698e03..fbe7849cd2 100644
+--- a/Lib/javascript/v8/javascripttypemaps.swg
++++ b/Lib/javascript/v8/javascripttypemaps.swg
+@@ -25,7 +25,7 @@
+
+ /* Javascript types */
+
+-#define SWIG_Object v8::Handle<v8::Value>
++#define SWIG_Object v8::Local<v8::Value>
+ #define VOID_Object SWIGV8_UNDEFINED()
+
+ /* Overload of the output/constant/exception/dirout handling */
+diff --git a/Tools/javascript/Makefile.in b/Tools/javascript/Makefile.in
+index 5eeec07857..21088a8fad 100644
+--- a/Tools/javascript/Makefile.in
++++ b/Tools/javascript/Makefile.in
+@@ -3,12 +3,9 @@
+ # ----------------------------------------------------------------
+ #
+ # Note:
+-# There is no common CLI Javascript interpreter.
+-# V8 comes with one 'd8' which however does not provide a means
+-# to load extensions. Therefore, by default we use nodejs as
+-# environment.
+-# For testing native v8 and jsc extensions we provide our own
+-# interpreter (see 'Tools/javascript').
++# There is no common CLI Javascript interpreter. By default we
++# use nodejs as environment. For testing jsc extensions we
++# provide our own interpreter (see 'Tools/javascript').
+ #
+ # ----------------------------------------------------------------
+ all: javascript
+@@ -24,37 +21,25 @@ LDFLAGS =
+ LINKFLAGS = @JSINTERPRETERLINKFLAGS@
+
+ ROOT_DIR = @ROOT_DIR@
+-JSINCLUDES = @JSCOREINC@ @JSV8INC@
+-JSDYNAMICLINKING = @JSCOREDYNAMICLINKING@ @JSV8DYNAMICLINKING@
+-JSV8ENABLED = @JSV8ENABLED@
++JSINCLUDES = @JSCOREINC@
++JSDYNAMICLINKING = @JSCOREDYNAMICLINKING@
+ JSCENABLED = @JSCENABLED@
+
+ srcdir = @srcdir@
+
+-
+-ifneq (, $(V8_VERSION))
+- JSV8_VERSION=$(V8_VERSION)
+-else
+- JSV8_VERSION=0x031110
+-endif
+-
+ # Regenerate Makefile if Makefile.in or config.status have changed.
+ Makefile: $(srcdir)/Makefile.in ../../config.status
+ cd ../.. && $(SHELL) ./config.status Tools/javascript/Makefile
+
+ # These settings are provided by 'configure' (see '/configure.in')
+-ifeq (1, $(JSV8ENABLED))
+-JS_INTERPRETER_SRC_V8 = v8_shell.cxx
+-JS_INTERPRETER_ENABLE_V8 = -DENABLE_V8 -DSWIG_V8_VERSION=$(JSV8_VERSION) -DV8_DEPRECATION_WARNINGS
+-endif
+
+ ifeq (1, $(JSCENABLED))
+ JS_INTERPRETER_SRC_JSC = jsc_shell.cxx
+ JS_INTERPRETER_ENABLE_JSC = -DENABLE_JSC
+ endif
+
+-JS_INTERPRETER_DEFINES = $(JS_INTERPRETER_ENABLE_JSC) $(JS_INTERPRETER_ENABLE_V8)
+-JS_INTERPRETER_SRC = javascript.cxx js_shell.cxx $(JS_INTERPRETER_SRC_JSC) $(JS_INTERPRETER_SRC_V8)
++JS_INTERPRETER_DEFINES = $(JS_INTERPRETER_ENABLE_JSC)
++JS_INTERPRETER_SRC = javascript.cxx js_shell.cxx $(JS_INTERPRETER_SRC_JSC)
+
+ JS_INTERPRETER_OBJS = $(JS_INTERPRETER_SRC:.cxx=.o)
+
+diff --git a/Tools/javascript/v8_shell.cxx b/Tools/javascript/v8_shell.cxx
+deleted file mode 100644
+index 5001bc25a6..0000000000
+--- a/Tools/javascript/v8_shell.cxx
++++ /dev/null
+@@ -1,388 +0,0 @@
+-#include <assert.h>
+-#include <fcntl.h>
+-#include <string.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-
+-#include <v8.h>
+-#include <vector>
+-
+-#include "js_shell.h"
+-
+-typedef int (*V8ExtensionInitializer) (v8::Handle<v8::Object> module);
+-
+-// Note: these typedefs and defines are used to deal with v8 API changes since version 3.19.00
+-
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903)
+-typedef v8::Handle<v8::Value> SwigV8ReturnValue;
+-typedef v8::Arguments SwigV8Arguments;
+-typedef v8::AccessorInfo SwigV8PropertyCallbackInfo;
+-#define SWIGV8_RETURN(val) return scope.Close(val)
+-#define SWIGV8_RETURN_INFO(val, info) return scope.Close(val)
+-#else
+-typedef void SwigV8ReturnValue;
+-typedef v8::FunctionCallbackInfo<v8::Value> SwigV8Arguments;
+-typedef v8::PropertyCallbackInfo<v8::Value> SwigV8PropertyCallbackInfo;
+-#define SWIGV8_RETURN(val) args.GetReturnValue().Set(val); return
+-#define SWIGV8_RETURN_INFO(val, info) info.GetReturnValue().Set(val); return
+-#endif
+-
+-
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032117)
+-#define SWIGV8_HANDLESCOPE() v8::HandleScope scope
+-#define SWIGV8_HANDLESCOPE_ESC() v8::HandleScope scope
+-#define SWIGV8_ESCAPE(val) return scope.Close(val)
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032318)
+-#define SWIGV8_HANDLESCOPE() v8::HandleScope scope(v8::Isolate::GetCurrent());
+-#define SWIGV8_HANDLESCOPE_ESC() v8::HandleScope scope(v8::Isolate::GetCurrent());
+-#define SWIGV8_ESCAPE(val) return scope.Close(val)
+-#else
+-#define SWIGV8_HANDLESCOPE() v8::HandleScope scope(v8::Isolate::GetCurrent());
+-#define SWIGV8_HANDLESCOPE_ESC() v8::EscapableHandleScope scope(v8::Isolate::GetCurrent());
+-#define SWIGV8_ESCAPE(val) return scope.Escape(val)
+-#endif
+-
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032318)
+-#define SWIGV8_CURRENT_CONTEXT() v8::Context::GetCurrent()
+-#define SWIGV8_STRING_NEW(str) v8::String::New(str)
+-#define SWIGV8_FUNCTEMPLATE_NEW(func) v8::FunctionTemplate::New(func)
+-#define SWIGV8_OBJECT_NEW() v8::Object::New()
+-#define SWIGV8_EXTERNAL_NEW(val) v8::External::New(val)
+-#define SWIGV8_UNDEFINED() v8::Undefined()
+-#else
+-#define SWIGV8_CURRENT_CONTEXT() v8::Isolate::GetCurrent()->GetCurrentContext()
+-#define SWIGV8_STRING_NEW(str) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), str)
+-#define SWIGV8_FUNCTEMPLATE_NEW(func) v8::FunctionTemplate::New(v8::Isolate::GetCurrent(), func)
+-#define SWIGV8_OBJECT_NEW() v8::Object::New(v8::Isolate::GetCurrent())
+-#define SWIGV8_EXTERNAL_NEW(val) v8::External::New(v8::Isolate::GetCurrent(), val)
+-#define SWIGV8_UNDEFINED() v8::Undefined(v8::Isolate::GetCurrent())
+-#endif
+-
+-
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+-typedef v8::Persistent<v8::Context> SwigV8Context;
+-#else
+-typedef v8::Local<v8::Context> SwigV8Context;
+-#endif
+-
+-class V8Shell: public JSShell {
+-
+-public:
+- V8Shell();
+-
+- virtual ~V8Shell();
+-
+- virtual bool RunScript(const std::string &scriptPath);
+-
+- virtual bool RunShell();
+-
+-
+-protected:
+-
+- virtual bool InitializeEngine();
+-
+- virtual bool ExecuteScript(const std::string &source, const std::string &scriptPath);
+-
+- virtual bool DisposeEngine();
+-
+-private:
+-
+- v8::Handle<v8::Value> Import(const std::string &moduleName);
+-
+- SwigV8Context CreateShellContext();
+-
+- void ReportException(v8::TryCatch *handler);
+-
+- static SwigV8ReturnValue Print(const SwigV8Arguments &args);
+-
+- static SwigV8ReturnValue Require(const SwigV8Arguments &args);
+-
+- static SwigV8ReturnValue Quit(const SwigV8Arguments &args);
+-
+- static SwigV8ReturnValue Version(const SwigV8Arguments &args);
+-
+- static const char* ToCString(const v8::String::Utf8Value &value);
+-
+-};
+-
+-#ifdef __GNUC__
+-#include <dlfcn.h>
+-#define LOAD_SYMBOL(handle, name) dlsym(handle, name)
+-#else
+-#error "implement dll loading"
+-#endif
+-
+-V8Shell::V8Shell() {}
+-
+-V8Shell::~V8Shell() {}
+-
+-bool V8Shell::RunScript(const std::string &scriptPath) {
+- std::string source = ReadFile(scriptPath);
+-
+- v8::Isolate *isolate = v8::Isolate::New();
+- v8::Isolate::Scope isolate_scope(isolate);
+-
+- SWIGV8_HANDLESCOPE();
+-
+- SwigV8Context context = CreateShellContext();
+-
+- if (context.IsEmpty()) {
+- printf("Could not create context.\n");
+- return false;
+- }
+-
+- context->Enter();
+-
+- // Store a pointer to this shell for later use
+-
+- v8::Handle<v8::Object> global = context->Global();
+- v8::Local<v8::External> __shell__ = SWIGV8_EXTERNAL_NEW((void*) (long) this);
+-
+- global->SetHiddenValue(SWIGV8_STRING_NEW("__shell__"), __shell__);
+-
+- // Node.js compatibility: make `print` available as `console.log()`
+- ExecuteScript("var console = {}; console.log = print;", "<console>");
+-
+- bool success = ExecuteScript(source, scriptPath);
+-
+- // Cleanup
+-
+- context->Exit();
+-
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+- context.Dispose();
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+- context.Dispose(v8::Isolate::GetCurrent());
+-#else
+-// context.Dispose();
+-#endif
+-
+-// v8::V8::Dispose();
+-
+- return success;
+-}
+-
+-bool V8Shell::RunShell() {
+- SWIGV8_HANDLESCOPE();
+-
+- SwigV8Context context = CreateShellContext();
+-
+- if (context.IsEmpty()) {
+- printf("Could not create context.\n");
+- return false;
+- }
+-
+- context->Enter();
+-
+- v8::Context::Scope context_scope(context);
+-
+- ExecuteScript("var console = {}; console.log = print;", "<console>");
+-
+- static const int kBufferSize = 1024;
+- while (true) {
+- char buffer[kBufferSize];
+- printf("> ");
+- char *str = fgets(buffer, kBufferSize, stdin);
+- if (str == NULL) break;
+- std::string source(str);
+- ExecuteScript(source, "(shell)");
+- }
+- printf("\n");
+-
+- // Cleanup
+-
+- context->Exit();
+-
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710)
+- context.Dispose();
+-#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+- context.Dispose(v8::Isolate::GetCurrent());
+-#else
+-// context.Dispose();
+-#endif
+-
+-// v8::V8::Dispose();
+-
+- return true;
+-}
+-
+-
+-bool V8Shell::InitializeEngine() {
+- return true;
+-}
+-
+-bool V8Shell::ExecuteScript(const std::string &source, const std::string &name) {
+- SWIGV8_HANDLESCOPE();
+-
+- v8::TryCatch try_catch;
+- v8::Handle<v8::Script> script = v8::Script::Compile(SWIGV8_STRING_NEW(source.c_str()), SWIGV8_STRING_NEW(name.c_str()));
+-
+- // Stop if script is empty
+- if (script.IsEmpty()) {
+- // Print errors that happened during compilation.
+- ReportException(&try_catch);
+- return false;
+- }
+-
+- v8::Handle<v8::Value> result = script->Run();
+-
+- // Print errors that happened during execution.
+- if (try_catch.HasCaught()) {
+- ReportException(&try_catch);
+- return false;
+- } else {
+- return true;
+- }
+-}
+-
+-bool V8Shell::DisposeEngine() {
+- return true;
+-}
+-
+-SwigV8Context V8Shell::CreateShellContext() {
+- // Create a template for the global object.
+- v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
+-
+- // Bind global functions
+- global->Set(SWIGV8_STRING_NEW("print"), SWIGV8_FUNCTEMPLATE_NEW(V8Shell::Print));
+- global->Set(SWIGV8_STRING_NEW("quit"), SWIGV8_FUNCTEMPLATE_NEW(V8Shell::Quit));
+- global->Set(SWIGV8_STRING_NEW("require"), SWIGV8_FUNCTEMPLATE_NEW(V8Shell::Require));
+- global->Set(SWIGV8_STRING_NEW("version"), SWIGV8_FUNCTEMPLATE_NEW(V8Shell::Version));
+-
+-#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900)
+- SwigV8Context context = v8::Context::New(NULL, global);
+- return context;
+-#else
+- SwigV8Context context = v8::Context::New(v8::Isolate::GetCurrent(), NULL, global);
+- return context;
+-#endif
+-}
+-
+-v8::Handle<v8::Value> V8Shell::Import(const std::string &module_path)
+-{
+- SWIGV8_HANDLESCOPE_ESC();
+-
+- HANDLE library;
+- std::string module_name = LoadModule(module_path, &library);
+-
+- std::string symname = std::string(module_name).append("_initialize");
+-
+- V8ExtensionInitializer init_function = reinterpret_cast<V8ExtensionInitializer>((long) LOAD_SYMBOL(library, symname.c_str()));
+-
+- if(init_function == 0) {
+- printf("Could not find initializer function.");
+-
+- return SWIGV8_UNDEFINED();
+- }
+-
+- v8::Local<v8::Object> module = SWIGV8_OBJECT_NEW();
+- init_function(module);
+-
+- SWIGV8_ESCAPE(module);
+-}
+-
+-SwigV8ReturnValue V8Shell::Print(const SwigV8Arguments &args) {
+- SWIGV8_HANDLESCOPE();
+-
+- bool first = true;
+- for (int i = 0; i < args.Length(); i++) {
+-
+- if (first) {
+- first = false;
+- } else {
+- printf(" ");
+- }
+- v8::String::Utf8Value str(args[i]);
+- const char *cstr = V8Shell::ToCString(str);
+- printf("%s", cstr);
+- }
+- printf("\n");
+- fflush(stdout);
+-
+- SWIGV8_RETURN(SWIGV8_UNDEFINED());
+-}
+-
+-SwigV8ReturnValue V8Shell::Require(const SwigV8Arguments &args) {
+- SWIGV8_HANDLESCOPE();
+-
+- if (args.Length() != 1) {
+- printf("Illegal arguments for `require`");
+- };
+-
+- v8::String::Utf8Value str(args[0]);
+- const char *cstr = V8Shell::ToCString(str);
+- std::string moduleName(cstr);
+-
+- v8::Local<v8::Object> global = SWIGV8_CURRENT_CONTEXT()->Global();
+-
+- v8::Local<v8::Value> hidden = global->GetHiddenValue(SWIGV8_STRING_NEW("__shell__"));
+- v8::Local<v8::External> __shell__ = v8::Local<v8::External>::Cast(hidden);
+- V8Shell *_this = (V8Shell *) (long) __shell__->Value();
+-
+- v8::Handle<v8::Value> module = _this->Import(moduleName);
+-
+- SWIGV8_RETURN(module);
+-}
+-
+-SwigV8ReturnValue V8Shell::Quit(const SwigV8Arguments &args) {
+- SWIGV8_HANDLESCOPE();
+-
+- int exit_code = args[0]->Int32Value();
+- fflush(stdout);
+- fflush(stderr);
+- exit(exit_code);
+-
+- SWIGV8_RETURN(SWIGV8_UNDEFINED());
+-}
+-
+-SwigV8ReturnValue V8Shell::Version(const SwigV8Arguments &args) {
+- SWIGV8_HANDLESCOPE();
+- SWIGV8_RETURN(SWIGV8_STRING_NEW(v8::V8::GetVersion()));
+-}
+-
+-void V8Shell::ReportException(v8::TryCatch *try_catch) {
+- SWIGV8_HANDLESCOPE();
+-
+- v8::String::Utf8Value exception(try_catch->Exception());
+- const char *exception_string = V8Shell::ToCString(exception);
+- v8::Handle<v8::Message> message = try_catch->Message();
+- if (message.IsEmpty()) {
+- // V8 didn't provide any extra information about this error; just
+- // print the exception.
+- printf("%s\n", exception_string);
+- } else {
+- // Print (filename):(line number): (message).
+- v8::String::Utf8Value filename(message->GetScriptResourceName());
+- const char *filename_string = V8Shell::ToCString(filename);
+- int linenum = message->GetLineNumber();
+- printf("%s:%i: %s\n", filename_string, linenum, exception_string);
+- // Print line of source code.
+- v8::String::Utf8Value sourceline(message->GetSourceLine());
+- const char *sourceline_string = V8Shell::ToCString(sourceline);
+- printf("%s\n", sourceline_string);
+- // Print wavy underline (GetUnderline is deprecated).
+- int start = message->GetStartColumn();
+- for (int i = 0; i < start; i++) {
+- printf(" ");
+- }
+- int end = message->GetEndColumn();
+- for (int i = start; i < end; i++) {
+- printf("^");
+- }
+- printf("\n");
+- v8::String::Utf8Value stack_trace(try_catch->StackTrace());
+- if (stack_trace.length() > 0) {
+- const char *stack_trace_string = V8Shell::ToCString(stack_trace);
+- printf("%s\n", stack_trace_string);
+- }
+- }
+-}
+-
+-// Extracts a C string from a V8 Utf8Value.
+-const char *V8Shell::ToCString(const v8::String::Utf8Value &value) {
+- return *value ? *value : "<string conversion failed>";
+-}
+-
+-JSShell *V8Shell_Create() {
+- return new V8Shell();
+-}
+diff --git a/Tools/travis-linux-install.sh b/Tools/travis-linux-install.sh
+index c8347d27a4..2427d08230 100755
+--- a/Tools/travis-linux-install.sh
++++ b/Tools/travis-linux-install.sh
+@@ -39,22 +39,12 @@
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
+ travis_retry nvm install ${VER}
+ nvm use ${VER}
+- if [ "$VER" == "0.10" ] || [ "$VER" == "0.12" ] || [ "$VER" == "4" ] || [ "$VER" == "6" ] ; then
+-# travis_retry sudo apt-get install -qq nodejs node-gyp
+- travis_retry npm install -g node-gyp@$VER
+- elif [ "$VER" == "8" ] ; then
+- travis_retry npm install -g node-gyp@6
+- else
+- travis_retry npm install -g node-gyp
+- fi
++ travis_retry npm install -g node-gyp
+ ;;
+ "jsc")
+ travis_retry sudo apt-get install -qq libwebkitgtk-dev
+ ;;
+- "v8")
+- travis_retry sudo apt-get install -qq libv8-dev
+- ;;
+- esac
++
+ ;;
+ "guile")
+ travis_retry sudo apt-get -qq install guile-2.0-dev
diff --git a/external/subpack/utils/syncthing/Makefile b/external/subpack/utils/syncthing/Makefile
new file mode 100644
index 0000000..f16c1f0
--- /dev/null
+++ b/external/subpack/utils/syncthing/Makefile
@@ -0,0 +1,65 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=syncthing
+PKG_VERSION:=1.18.2
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=syncthing-source-v$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/syncthing/syncthing/releases/download/v$(PKG_VERSION)
+PKG_HASH:=afe2ae979da3b4f1af8aeabd7e1704807242913b516e0b6585510821c9d6d4f2
+
+PKG_BUILD_DIR=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/$(PKG_NAME)
+
+PKG_MAINTAINER:=Paul Spooren <mail@aparcar.org>
+PKG_LICENSE:=MPL-2.0
+PKG_LICENSE_FILES:=LICENSE
+PKG_CPE_ID:=cpe:/a:syncthing:syncthing
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/syncthing/syncthing/
+GO_PKG_BUILD_PKG:=github.com/syncthing/syncthing/cmd/syncthing/
+GO_PKG_INSTALL_EXTRA:=^gui/
+
+GO_PKG_LDFLAGS_X:=\
+ github.com/syncthing/syncthing/lib/build.Version=v$(PKG_VERSION) \
+ github.com/syncthing/syncthing/lib/build.Stamp=$(SOURCE_DATE_EPOCH) \
+ github.com/syncthing/syncthing/lib/build.User=openwrt \
+ github.com/syncthing/syncthing/lib/build.Host=openwrt \
+ github.com/syncthing/syncthing/lib/build.Program=syncthing
+GO_PKG_TAGS:=noupgrade
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/syncthing
+ TITLE:=Continuous file synchronization program
+ URL:=https://syncthing.net
+ DEPENDS:=$(GO_ARCH_DEPENDS)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ USERID:=syncthing=499:syncthing=499
+endef
+
+define Package/syncthing/conffiles
+/etc/config/syncthing
+/etc/syncthing
+endef
+
+define Package/syncthing/description
+ Syncthing replaces proprietary sync and cloud services with something
+ open, trustworthy and decentralized. Your data is your data alone and
+ you deserve to choose where it is stored, if it is shared with some
+ third party and how it's transmitted over the Internet.
+endef
+
+define Package/syncthing/install
+ $(call GoPackage/Package/Install/Bin,$(1))
+
+ $(CP) ./files/* $(1)/
+endef
+
+$(eval $(call GoBinPackage,syncthing))
+$(eval $(call BuildPackage,syncthing))
diff --git a/external/subpack/utils/syncthing/files/etc/config/syncthing b/external/subpack/utils/syncthing/files/etc/config/syncthing
new file mode 100644
index 0000000..291675d
--- /dev/null
+++ b/external/subpack/utils/syncthing/files/etc/config/syncthing
@@ -0,0 +1,26 @@
+
+config syncthing 'syncthing'
+ option enabled '0'
+
+ option gui_address 'http://127.0.0.1:8384'
+
+ # Use internal flash for evaluation purpouses. Use external storage
+ # for production.
+ # This filesystem must either support ownership/attributes or
+ # be readable/writable by the user specified in
+ # 'option user'.
+ # Consult syslog if things go wrong.
+ option home '/etc/syncthing'
+
+ # Changes to "niceness"/macprocs are not picked up by "reload_config"
+ # nor by "restart": the service has to be stopped/started
+ # for those to take effect
+ option nice '19'
+
+ # 0 to match the number of CPUs (default)
+ # >0 to explicitly specify concurrency
+ option macprocs '0'
+
+ # Running as 'root' is possible, but not recommended
+ option user 'syncthing'
+
diff --git a/external/subpack/utils/syncthing/files/etc/init.d/syncthing b/external/subpack/utils/syncthing/files/etc/init.d/syncthing
new file mode 100755
index 0000000..f77aad8
--- /dev/null
+++ b/external/subpack/utils/syncthing/files/etc/init.d/syncthing
@@ -0,0 +1,69 @@
+#!/bin/sh /etc/rc.common
+
+START=90
+STOP=10
+
+USE_PROCD=1
+
+PROG=/usr/bin/syncthing
+
+service_triggers()
+{
+ procd_add_reload_trigger "syncthing"
+}
+
+start_service() {
+ local gui_address home enabled nice macprocs user
+ config_load "syncthing"
+
+ # Some of the default values below might not match the defaults
+ # in /etc/config/syncthing: the reason is to remain backwards
+ # compatible with the older versions of this service as it
+ # evolves.
+
+ config_get_bool enabled syncthing enabled 1
+ [ "$enabled" -gt 0 ] || return 0
+
+ config_get user syncthing user 'root'
+ config_get gui_address syncthing gui_address "http://127.0.0.1:8384"
+ config_get home syncthing home "/etc/syncthing"
+
+ # For backwards compatibility
+ IDX_DB=$(readlink -n "$home"/index-v0.14.0.db)
+ if [ ! -z "$IDX_DB" ]; then
+ [ -d "$IDX_DB" ] || mkdir -p "$IDX_DB"
+
+ # A separate step to handle an upgrade use case
+ [ -d "$IDX_DB" ] && chown -R $user:$user "$IDX_DB"
+ fi
+
+ [ -d "$home" ] || mkdir -p "$home"
+ # A separate step to handle an upgrade use case
+ [ -d "$home" ] && chown -R $user:$user "$home"
+
+ # Changes to "niceness"/macprocs are not picked up by "reload_config"
+ # nor by "restart": the service has to be stopped/started
+ # for it to take effect
+ config_get nice syncthing nice "0"
+
+ config_get macprocs syncthing macprocs 0
+ if [ $macprocs -le 0 ]; then
+ # Default to the number of cores in this case
+ macprocs=$(grep -c ^processor /proc/cpuinfo)
+ fi
+
+ procd_open_instance
+ procd_set_param command "$PROG"
+ procd_set_param file /etc/config/syncthing
+ procd_set_param env GOMAXPROCS="$macprocs" STNOUPGRADE=1
+ procd_append_param command -gui-address="$gui_address"
+ procd_append_param command -home="$home"
+ procd_append_param command -no-browser
+ procd_set_param nice "$nice"
+ procd_set_param term_timeout 15
+ procd_set_param user "$user"
+ procd_set_param respawn
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_close_instance
+}
diff --git a/external/subpack/utils/syncthing/files/etc/sysctl.d/90-syncthing-inotify.conf b/external/subpack/utils/syncthing/files/etc/sysctl.d/90-syncthing-inotify.conf
new file mode 100644
index 0000000..1e65bf9
--- /dev/null
+++ b/external/subpack/utils/syncthing/files/etc/sysctl.d/90-syncthing-inotify.conf
@@ -0,0 +1 @@
+fs.inotify.max_user_watches=204800
diff --git a/external/subpack/utils/syncthing/test.sh b/external/subpack/utils/syncthing/test.sh
new file mode 100644
index 0000000..f582111
--- /dev/null
+++ b/external/subpack/utils/syncthing/test.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+syncthing --version | grep "$2"
diff --git a/external/subpack/utils/sysstat/Makefile b/external/subpack/utils/sysstat/Makefile
new file mode 100644
index 0000000..ca6b0c3
--- /dev/null
+++ b/external/subpack/utils/sysstat/Makefile
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=sysstat
+PKG_VERSION:=12.4.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=http://pagesperso-orange.fr/sebastien.godard/
+PKG_HASH:=3701b2c1883d50eb384d7b95ce5b6df0a71fdcb3c23f96cb58098d1bcffa018f
+
+PKG_MAINTAINER:=Marko Ratkaj <marko.ratkaj@sartura.hr>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:sysstat_project:sysstat
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/sysstat
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Sysstat performance monitoring tools
+ URL:=http://pagesperso-orange.fr/sebastien.godard/index.html
+ DEPENDS:=$(INTL_DEPENDS)
+endef
+
+define Package/sysstat/description
+ The sysstat utilities are a collection of performance monitoring tools for
+ Linux. These include sar, sadf, mpstat, iostat, pidstat and sa tools.
+endef
+
+define Package/sysstat/conffiles
+/etc/config/sysstat
+/etc/sysstat/sysstat.ioconf
+/etc/sysstat/sysstat
+endef
+
+CONFIGURE_VARS+= \
+ sa_lib_dir="/usr/lib/sysstat" \
+ conf_dir="/etc/sysstat"
+
+CONFIGURE_ARGS+= \
+ --disable-documentation \
+ --disable-sensors
+
+define Package/sysstat/install
+ $(INSTALL_DIR) $(1)/usr/lib/sysstat
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/sysstat/{sadc,sa1,sa2} $(1)/usr/lib/sysstat/
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/{sar,sadf,iostat,mpstat,pidstat} $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/sysstat
+ $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/sysstat/sysstat.ioconf $(1)/etc/sysstat/
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) ./files/sysstat.config $(1)/etc/config/sysstat
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/sysstat.init $(1)/etc/init.d/sysstat
+endef
+
+$(eval $(call BuildPackage,sysstat))
diff --git a/external/subpack/utils/sysstat/files/sysstat.config b/external/subpack/utils/sysstat/files/sysstat.config
new file mode 100644
index 0000000..638b379
--- /dev/null
+++ b/external/subpack/utils/sysstat/files/sysstat.config
@@ -0,0 +1,7 @@
+config sysstat 'sysstat'
+ option log_history '7'
+ option compressafter '10'
+ option sadc_options ''
+ option sa_dir '/var/log/sysstat'
+ option zip 'xz'
+ option enabled 'true'
diff --git a/external/subpack/utils/sysstat/files/sysstat.init b/external/subpack/utils/sysstat/files/sysstat.init
new file mode 100755
index 0000000..e7b75e2
--- /dev/null
+++ b/external/subpack/utils/sysstat/files/sysstat.init
@@ -0,0 +1,52 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2015 OpenWrt.org
+
+START=90
+STOP=10
+
+USE_PROCD=1
+PROG=/usr/lib/sysstat/sadc
+SYSSTAT_CFG="/etc/sysstat/sysstat"
+
+validate_sysstat_section() {
+ uci_load_validate sysstat sysstat "$1" "$2" \
+ 'log_history:uinteger' \
+ 'compressafter:uinteger' \
+ 'sadc_options:string' \
+ 'sa_dir:string' \
+ 'zip:string' \
+ 'enabled:string'
+}
+
+start_sysstat_instance() {
+ [ "$2" = 0 ] || {
+ echo "validation failed"
+ return 1
+ }
+
+ [ -d /var/log/sysstat ] || mkdir -p /var/log/sysstat
+
+ {
+ echo "HISTORY=$log_history"
+ echo "COMPRESSAFTER=$compressafter"
+ echo "SADC_OPTIONS=\"$sadc_options\""
+ echo "SA_DIR=\"$sa_dir\""
+ echo "ZIP=\"$zip\""
+ echo "ENABLED=\"$enabled\""
+ } > $SYSSTAT_CFG
+
+ procd_open_instance
+ procd_set_param command $PROG -S DISK -F -L -
+ procd_set_param file $SYSSTAT_CFG
+ procd_close_instance
+}
+
+start_service() {
+ validate_sysstat_section sysstat start_sysstat_instance
+}
+
+service_triggers()
+{
+ procd_add_reload_trigger "sysstat"
+ procd_add_validation validate_sysstat_section
+}
diff --git a/external/subpack/utils/sysstat/patches/010-ldflags.patch b/external/subpack/utils/sysstat/patches/010-ldflags.patch
new file mode 100644
index 0000000..8b024ff
--- /dev/null
+++ b/external/subpack/utils/sysstat/patches/010-ldflags.patch
@@ -0,0 +1,47 @@
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -80,7 +80,7 @@ SYSCONFIG_FILE = @SYSCONFIG_FILE@
+ # Compiler flags
+ CFLAGS = @CFLAGS@ -Wall -Wstrict-prototypes -pipe -O2
+ DFLAGS = @DFLAGS@
+-LFLAGS = @STRIP@
++LDFLAGS += @STRIP@
+ DFLAGS += -DSA_DIR=\"$(SA_DIR)\" -DSADC_PATH=\"$(SADC_PATH)\"
+ DFLAGS += $(DFSENSORS)
+ DFLAGS += $(DFPCP)
+@@ -117,7 +117,7 @@ ifeq ($(SYSPARAM),y)
+ DFLAGS += -DHAVE_SYS_PARAM_H
+ endif
+ NLS = @NLS@
+-LFLAGS += @LFINTL@
++LDFLAGS += @LFINTL@
+ ifeq ($(NLS),y)
+ REQUIRE_NLS = -DUSE_NLS -DPACKAGE=\"$(PACKAGE)\" -DLOCALEDIR=\"$(NLS_DIR)\"
+ endif
+@@ -195,7 +195,7 @@ NLSPOT= $(NLSPO:.po=.pot)
+ $(CC) -o $@ -c $(CFLAGS) $(DFLAGS) $<
+
+ % : %.o
+- $(CC) -o $@ $(CFLAGS) $^ $(LFLAGS)
++ $(CC) -o $@ $(CFLAGS) $^ $(LDFLAGS)
+
+ all: sadc sar sadf iostat tapestat mpstat pidstat cifsiostat locales
+
+@@ -283,7 +283,7 @@ librdsensors.a: rd_sensors.o
+
+ sadc.o: sadc.c sa.h version.h common.h rd_stats.h rd_sensors.h
+
+-sadc: LFLAGS += $(LFSENSORS)
++sadc: LDFLAGS += $(LFSENSORS)
+
+ sadc: sadc.o act_sadc.o sa_wrap.o sa_common_sadc.o common_sadc.o systest.o librdstats.a librdsensors.a
+
+@@ -293,7 +293,7 @@ sar: sar.o act_sar.o format_sar.o sa_com
+
+ sadf.o: sadf.c sadf.h version.h sa.h common.h rd_stats.h rd_sensors.h
+
+-sadf: LFLAGS += $(LFPCP)
++sadf: LDFLAGS += $(LFPCP)
+
+ sadf: sadf.o act_sadf.o format_sadf.o sadf_misc.o pcp_def_metrics.o sa_conv.o rndr_stats.o xml_stats.o json_stats.o svg_stats.o raw_stats.o pcp_stats.o sa_common.o librdstats_light.a libsyscom.a
+
diff --git a/external/subpack/utils/tang/Makefile b/external/subpack/utils/tang/Makefile
new file mode 100644
index 0000000..e159bd4
--- /dev/null
+++ b/external/subpack/utils/tang/Makefile
@@ -0,0 +1,73 @@
+#
+# Author: Tibor Dudlák
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tang
+PKG_VERSION:=7
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://github.com/latchset/$(PKG_NAME)/releases/download/v$(PKG_VERSION)/
+PKG_HASH:=fbe13e4e3103cd24cada7824b63e510cffd650832ecd075fd49b99475a4f9bfa
+
+PKG_MAINTAINER:=Tibor Dudlák <tibor.dudlak@gmail.com>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+# This avoids generating man pages
+CONFIGURE_VARS += ac_cv_prog_A2X=
+
+define Package/tang
+ SECTION:=utils
+ TITLE:=tang v$(PKG_VERSION) - daemon for binding data to the presence of a third party
+ DEPENDS:=+libhttp-parser +xinetd +jose +bash
+ URL:=https://github.com/latchset/tang
+endef
+
+define Package/tang/description
+ Tang is a small daemon for binding data to the presence of a third party.
+endef
+
+define Package/tang/conffiles
+/etc/xinetd.d/tangdx
+/usr/share/tang/db/
+endef
+
+define Package/tang/install
+ $(INSTALL_DIR) $(1)/usr/libexec
+ $(INSTALL_DIR) $(1)/etc/xinetd.d/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/tangd* $(1)/usr/libexec/
+ $(INSTALL_BIN) ./files/tangdw $(1)/usr/libexec/
+ $(CP) ./files/tangdx $(1)/etc/xinetd.d/
+endef
+
+define Package/tang/postinst
+#!/bin/sh
+if [ -z "$${IPKG_INSTROOT}" ]; then
+ mkdir -p /usr/share/tang/db && mkdir -p /usr/share/tang/cache
+ KEYS=$(find /usr/share/tang/db/ -name "*.jw*" -maxdepth 1 | wc -l)
+ if [ "${KEYS}" = "0" ]; then # if db is empty generate new key pair
+ /usr/libexec/tangd-keygen /usr/share/tang/db/
+ elif [ "${KEYS}" = "1" ]; then # having 1 key should not happen
+ (>&2 echo "Please check the Tang's keys in /usr/share/tang/db \
+and regenate cache using /usr/libexec/tangd-update script.")
+ else
+ /usr/libexec/tangd-update /usr/share/tang/db/ /usr/share/tang/cache/
+ fi
+ (cat /etc/services | grep -E "tangd.*8888\/tcp") > /dev/null \
+ || echo -e "tangd\t\t8888/tcp" >> /etc/services
+fi
+endef
+
+$(eval $(call BuildPackage,tang))
diff --git a/external/subpack/utils/tang/files/tangdw b/external/subpack/utils/tang/files/tangdw
new file mode 100755
index 0000000..91c8a89
--- /dev/null
+++ b/external/subpack/utils/tang/files/tangdw
@@ -0,0 +1,4 @@
+#!/bin/sh
+echo "==================================" >> /var/log/tangd.log
+echo `date`: >> /var/log/tangd.log
+/usr/libexec/tangd $1 2>> /var/log/tangd.log
diff --git a/external/subpack/utils/tang/files/tangdx b/external/subpack/utils/tang/files/tangdx
new file mode 100644
index 0000000..2b15eb0
--- /dev/null
+++ b/external/subpack/utils/tang/files/tangdx
@@ -0,0 +1,12 @@
+service tangd
+{
+ port = 8888
+ socket_type = stream
+ wait = no
+ user = root
+ server = /usr/libexec/tangdw
+ server_args = /usr/share/tang/cache
+ log_on_success += USERID
+ log_on_failure += USERID
+ disable = no
+}
diff --git a/external/subpack/utils/tang/patches/010-makefile.patch b/external/subpack/utils/tang/patches/010-makefile.patch
new file mode 100644
index 0000000..94b0738
--- /dev/null
+++ b/external/subpack/utils/tang/patches/010-makefile.patch
@@ -0,0 +1,31 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,4 +1,3 @@
+-DISTCHECK_CONFIGURE_FLAGS = --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
+ BUILT_SOURCES=
+ CLEANFILES=
+ man1_MANS=
+@@ -10,13 +9,6 @@ LDADD = @jose_LIBS@ @http_parser_LIBS@
+ cachedir = $(localstatedir)/cache/$(PACKAGE_NAME)
+ jwkdir = $(localstatedir)/db/$(PACKAGE_NAME)
+
+-nodist_systemdsystemunit_DATA = \
+- units/tangd@.service \
+- units/tangd.socket \
+- units/tangd-update.path \
+- units/tangd-update.service \
+- units/tangd-keygen.service
+-
+ dist_libexec_SCRIPTS = src/tangd-update src/tangd-keygen
+ dist_bin_SCRIPTS = src/tang-show-keys
+ libexec_PROGRAMS = src/tangd
+@@ -52,9 +44,7 @@ src_tangd_SOURCES = src/http.c src/http.
+ AM_TESTS_ENVIRONMENT = SD_ACTIVATE="@SD_ACTIVATE@" PATH=$(srcdir)/src:$(builddir)/src:$(PATH)
+ TESTS = tests/adv tests/rec
+
+-CLEANFILES += $(nodist_systemdsystemunit_DATA)
+ EXTRA_DIST = \
+- $(foreach unit,$(nodist_systemdsystemunit_DATA),$(unit).in) \
+ COPYING \
+ $(TESTS) \
+ $(man_ADOC_FILES)
diff --git a/external/subpack/utils/tang/patches/020-no-systemd.patch b/external/subpack/utils/tang/patches/020-no-systemd.patch
new file mode 100644
index 0000000..1969412
--- /dev/null
+++ b/external/subpack/utils/tang/patches/020-no-systemd.patch
@@ -0,0 +1,35 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -27,32 +27,6 @@ AC_CHECK_LIB([http_parser], [http_parser
+ [AC_MSG_ERROR([http-parser required!])])
+
+ PKG_CHECK_MODULES([jose], [jose >= 8])
+-PKG_CHECK_MODULES([systemd], [systemd])
+-
+-AC_ARG_WITH([systemdsystemunitdir],
+- [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],
+- [],
+- [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
+-
+-AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
+-
+-for ac_prog in systemd-socket-activate systemd-activate; do
+- AC_CHECK_PROG([SD_ACTIVATE], [$ac_prog], [$as_dir/$ac_prog], [],
+- [$PATH$PATH_SEPARATOR$($PKG_CONFIG --variable=systemdutildir systemd)])
+- test -n "$SD_ACTIVATE" && break
+-done
+-
+-test -n "$SD_ACTIVATE" || AC_MSG_ERROR([systemd-socket-activate required!])
+-
+-AC_MSG_CHECKING([systemd-socket-activate inetd flag])
+-if $SD_ACTIVATE --help | grep -q inetd; then
+- SD_ACTIVATE="$SD_ACTIVATE --inetd"
+- AC_MSG_RESULT([--inetd])
+-else
+- AC_MSG_RESULT([(default)])
+-fi
+-
+-AC_SUBST(SD_ACTIVATE)
+
+ TANG_CFLAGS="\
+ -Wall \
diff --git a/external/subpack/utils/tang/patches/030-readlink.patch b/external/subpack/utils/tang/patches/030-readlink.patch
new file mode 100644
index 0000000..1a3f897
--- /dev/null
+++ b/external/subpack/utils/tang/patches/030-readlink.patch
@@ -0,0 +1,13 @@
+--- a/src/tangd-update
++++ b/src/tangd-update
+@@ -33,8 +33,8 @@ fi
+
+ [ ! -d "$2" ] && mkdir -p -m 0700 "$2"
+
+-src=`realpath "$1"`
+-dst=`realpath "$2"`
++src=`readlink -f "$1"`
++dst=`readlink -f "$2"`
+
+ payl=()
+ sign=()
diff --git a/external/subpack/utils/tar/Makefile b/external/subpack/utils/tar/Makefile
new file mode 100644
index 0000000..f124f98
--- /dev/null
+++ b/external/subpack/utils/tar/Makefile
@@ -0,0 +1,100 @@
+#
+# Copyright (C) 2008-2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tar
+PKG_VERSION:=1.32
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/tar
+PKG_HASH:=d0d3ae07f103323be809bc3eac0dcc386d52c5262499fe05511ac4788af1fdd8
+
+PKG_MAINTAINER:=Álvaro Fernández Rojas <noltari@gmail.com>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:gnu:tar
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/tar
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+PACKAGE_TAR_POSIX_ACL:libacl +PACKAGE_TAR_XATTR:libattr +PACKAGE_TAR_BZIP2:bzip2
+ EXTRA_DEPENDS:=$(if $(CONFIG_PACKAGE_TAR_XZ),xz)
+ TITLE:=GNU tar
+ URL:=https://www.gnu.org/software/tar/
+ MENU:=1
+ ALTERNATIVES:=300:/bin/tar:/usr/libexec/tar-gnu
+endef
+
+define Package/tar/config
+ if PACKAGE_tar
+ config PACKAGE_TAR_POSIX_ACL
+ bool "tar: Enable POSIX ACL support"
+ default y if USE_FS_ACL_ATTR
+ default n
+
+ config PACKAGE_TAR_XATTR
+ bool "tar: Enable extended attribute (xattr) support"
+ default y if USE_FS_ACL_ATTR
+ default n
+
+ config PACKAGE_TAR_BZIP2
+ bool "tar: Enable seamless bzip2 support"
+ default y
+
+ config PACKAGE_TAR_GZIP
+ bool "tar: Enable seamless gzip support"
+ default y
+
+ config PACKAGE_TAR_XZ
+ bool "tar: Enable seamless xz support"
+ select PACKAGE_xz-utils
+ select PACKAGE_xz
+ default y
+
+ config PACKAGE_TAR_ZSTD
+ bool "tar: Enable seamless zstd support"
+ select PACKAGE_libzstd
+ default y
+ endif
+endef
+
+define Package/tar/description
+ Tar is a program for packaging a set of files as a
+ single archive in tar format.
+endef
+
+CONFIGURE_ARGS += \
+ $(if $(CONFIG_PACKAGE_TAR_POSIX_ACL),--with,--without)-posix-acls \
+ $(if $(CONFIG_PACKAGE_TAR_XATTR),--with,--without)-xattrs \
+ $(if $(CONFIG_PACKAGE_TAR_BZIP2),--with-bzip2=bzip2,--without-bzip2) \
+ $(if $(CONFIG_PACKAGE_TAR_GZIP),--with-gzip=gzip,--without-gzip) \
+ $(if $(CONFIG_PACKAGE_TAR_XZ),--with-xz=xz,--without-xz) \
+ $(if $(CONFIG_PACKAGE_TAR_ZSTD),--with-zstd=zstd,--without-zstd) \
+ --without-compress \
+ --without-lzip \
+ --without-lzma \
+ --without-lzop \
+ --without-selinux \
+ --disable-rpath
+
+MAKE_FLAGS += \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ LDFLAGS="$(TARGET_LDLAGS)"
+
+define Package/tar/install
+ $(INSTALL_DIR) $(1)/usr/libexec
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/tar $(1)/usr/libexec/tar-gnu
+endef
+
+$(eval $(call BuildPackage,tar))
diff --git a/external/subpack/utils/taskwarrior/Makefile b/external/subpack/utils/taskwarrior/Makefile
new file mode 100644
index 0000000..5ca7c70
--- /dev/null
+++ b/external/subpack/utils/taskwarrior/Makefile
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=taskwarrior
+PKG_VERSION:=2.5.1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=task-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://www.taskwarrior.org/download
+PKG_HASH:=d87bcee58106eb8a79b850e9abc153d98b79e00d50eade0d63917154984f2a15
+PKG_BUILD_DIR:=$(BUILD_DIR)/task-$(PKG_VERSION)
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/taskwarrior
+ TITLE:=taskwarrior
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libstdcpp +libuuid +libgnutls
+ URL:=https://taskwarrior.org/
+endef
+
+define Package/taskwarrior/description
+ taskwarrior is a command-line todo list manager
+endef
+
+define Package/taskwarrior/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/task $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,taskwarrior))
diff --git a/external/subpack/utils/tcsh/Makefile b/external/subpack/utils/tcsh/Makefile
new file mode 100644
index 0000000..f2a8ceb
--- /dev/null
+++ b/external/subpack/utils/tcsh/Makefile
@@ -0,0 +1,67 @@
+#
+# Copyright (C) 2011-2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tcsh
+PKG_VERSION:=6.22.03
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:= \
+ https://astron.com/pub/tcsh/ \
+ https://astron.com/pub/tcsh/old \
+ https://ftp.funet.fi/pub/mirrors/ftp.astron.com/pub/tcsh \
+ https://ftp.funet.fi/pub/mirrors/ftp.astron.com/pub/tcsh/old
+PKG_HASH:=be2cfd653d2a0c7f506d2dd14c12324ba749bd484037be6df44a3973f52262b7
+
+PKG_MAINTAINER:=Nuno Goncalves <nunojpg@gmail.com>
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=Copyright
+PKG_CPE_ID:=cpe:/a:tcsh:tcsh
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/tcsh
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Shells
+ TITLE:=Enhanced Berkeley UNIX C shell
+ DEPENDS:=+libncurses $(ICONV_DEPENDS)
+ URL:=https://www.tcsh.org/
+endef
+
+define Package/tcsh/description
+ Tcsh is an enhanced, but completely compatible
+ version of the Berkeley UNIX C shell (csh). It
+ is a command language interpreter usable both
+ as an interactive login shell and a shell
+ script command processor. It includes a
+ command-line editor, programmable word
+ completion, spelling correction, a history
+ mechanism, job control and a C-like syntax.
+endef
+
+define Package/tcsh/postinst
+#!/bin/sh
+grep tcsh $${IPKG_INSTROOT}/etc/shells || { \
+ echo "/bin/tcsh"
+ echo "/bin/csh"
+} >> $${IPKG_INSTROOT}/etc/shells
+endef
+
+define Package/tcsh/install
+ $(INSTALL_DIR) $(1)/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/tcsh $(1)/bin/
+ ln -sf tcsh $(1)/bin/csh
+endef
+
+$(eval $(call BuildPackage,tcsh))
diff --git a/external/subpack/utils/tcsh/patches/001-sysmalloc.patch b/external/subpack/utils/tcsh/patches/001-sysmalloc.patch
new file mode 100644
index 0000000..f46ce35
--- /dev/null
+++ b/external/subpack/utils/tcsh/patches/001-sysmalloc.patch
@@ -0,0 +1,15 @@
+--- a/config_f.h
++++ b/config_f.h
+@@ -138,11 +138,8 @@
+ * This can be much slower and no memory statistics will be
+ * provided.
+ */
+-#if defined(__MACHTEN__) || defined(PURIFY) || defined(MALLOC_TRACE) || defined(_OSD_POSIX) || defined(__MVS__) || defined (__CYGWIN__) || defined(__GLIBC__) || defined(__OpenBSD__) || defined(__APPLE__) || defined (__ANDROID__)
++
+ # define SYSMALLOC
+-#else
+-# undef SYSMALLOC
+-#endif
+
+ /*
+ * USE_ACCESS Use access(2) rather than stat(2) when POSIX is defined.
diff --git a/external/subpack/utils/tcsh/patches/010-wint.patch b/external/subpack/utils/tcsh/patches/010-wint.patch
new file mode 100644
index 0000000..2f6fc94
--- /dev/null
+++ b/external/subpack/utils/tcsh/patches/010-wint.patch
@@ -0,0 +1,14 @@
+--- a/ed.inputl.c
++++ b/ed.inputl.c
+@@ -668,9 +668,9 @@ int
+ GetCmdChar(Char ch)
+ {
+ #ifndef WINNT_NATIVE // We use more than 256 for various extended keys
+- wint_t c = ch & CHAR;
++ Char c = ch & CHAR;
+ #else
+- wint_t c = ch;
++ Char c = ch;
+ #endif
+ return c < NT_NUM_KEYS ? CurrentKeyMap[c] : F_INSERT;
+ }
diff --git a/external/subpack/utils/tcsh/patches/020-cross.patch b/external/subpack/utils/tcsh/patches/020-cross.patch
new file mode 100644
index 0000000..526b3c4
--- /dev/null
+++ b/external/subpack/utils/tcsh/patches/020-cross.patch
@@ -0,0 +1,11 @@
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -448,7 +448,7 @@ pure:$(P) ${OBJS}
+
+ gethost: gethost.c sh.err.h tc.const.h sh.h
+ rm -f gethost
+- ${CC_FOR_GETHOST} -o gethost ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} $(srcdir)/gethost.c
++ ${CC_FOR_GETHOST} -o gethost $(srcdir)/gethost.c
+
+ tc.defs.c: gethost host.defs
+ @rm -f $@.tmp
diff --git a/external/subpack/utils/telegraf/Makefile b/external/subpack/utils/telegraf/Makefile
new file mode 100644
index 0000000..c0a5676
--- /dev/null
+++ b/external/subpack/utils/telegraf/Makefile
@@ -0,0 +1,90 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=telegraf
+PKG_VERSION:=1.23.4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/influxdata/telegraf/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=05188b5f0c0dfa204dc6bd8429ebc5366b73e42c7bdd4f1a50fffa2a1e75616f
+
+PKG_MAINTAINER:=Jonathan Pagel <jonny_tischbein@systemli.org>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/influxdata/telegraf
+GO_PKG_BUILD_PKG:=github.com/influxdata/telegraf/cmd/telegraf
+GO_PKG_LDFLAGS_X:=main.version=$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/telegraf/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Telegraf
+ DEPENDS:=$(GO_ARCH_DEPENDS)
+endef
+
+define Package/telegraf-full
+ $(call Package/telegraf/Default)
+ TITLE+= (Full)
+ VARIANT:=full
+endef
+
+define Package/telegraf
+ $(call Package/telegraf/Default)
+ TITLE+= (Small)
+ VARIANT:=small
+endef
+
+define Package/telegraf/description/Default
+ Telegraf is a plugin-driven agent for collecting and sending metrics and events.
+ It supports various inputs (including prometheus endpoints) and is able to send data into InfluxDB.
+endef
+
+define Package/telegraf/description
+ $(call Package/telegraf/description/Default)
+ (Small build. Most plugins excluded)
+endef
+
+define Package/telegraf-full/description
+ $(call Package/telegraf/description/Default)
+ (Full build. including all plugins)
+endef
+
+define Package/telegraf/conffiles
+/etc/telegraf.conf
+endef
+
+Package/telegraf-full/conffiles = $(Package/telegraf/conffiles)
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ifeq ($(BUILD_VARIANT),small)
+ $(CP) ./variant-$(BUILD_VARIANT)/* $(PKG_BUILD_DIR)/
+endif
+endef
+
+define Package/telegraf/install
+ $(call GoPackage/Package/Install/Bin,$(1))
+ $(INSTALL_DIR) $(1)/etc/init.d $(1)/etc/config
+ $(INSTALL_BIN) ./files/etc/init.d/telegraf $(1)/etc/init.d/telegraf
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/etc/telegraf.conf $(1)/etc/telegraf.conf
+endef
+
+define Package/telegraf-full/install
+ $(call Package/telegraf/install,$(1))
+endef
+
+$(eval $(call GoBinPackage,telegraf))
+$(eval $(call BuildPackage,telegraf))
+
+$(eval $(call GoBinPackage,telegraf-full))
+$(eval $(call BuildPackage,telegraf-full))
diff --git a/external/subpack/utils/telegraf/files/etc/init.d/telegraf b/external/subpack/utils/telegraf/files/etc/init.d/telegraf
new file mode 100755
index 0000000..dd1c8a1
--- /dev/null
+++ b/external/subpack/utils/telegraf/files/etc/init.d/telegraf
@@ -0,0 +1,14 @@
+#!/bin/sh /etc/rc.common
+
+USE_PROCD=1
+
+START=95
+STOP=01
+
+start_service() {
+ procd_open_instance
+ procd_set_param command /usr/bin/telegraf --config /etc/telegraf.conf
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_close_instance
+}
diff --git a/external/subpack/utils/telegraf/variant-small/plugins/aggregators/all/all.go b/external/subpack/utils/telegraf/variant-small/plugins/aggregators/all/all.go
new file mode 100644
index 0000000..001f130
--- /dev/null
+++ b/external/subpack/utils/telegraf/variant-small/plugins/aggregators/all/all.go
@@ -0,0 +1,5 @@
+package all
+
+import (
+ //Blank imports for plugins to register themselves
+)
diff --git a/external/subpack/utils/telegraf/variant-small/plugins/inputs/all/all.go b/external/subpack/utils/telegraf/variant-small/plugins/inputs/all/all.go
new file mode 100644
index 0000000..1b30a03
--- /dev/null
+++ b/external/subpack/utils/telegraf/variant-small/plugins/inputs/all/all.go
@@ -0,0 +1,30 @@
+package all
+
+import (
+ //Blank imports for plugins to register themselves
+ _ "github.com/influxdata/telegraf/plugins/inputs/cpu"
+ _ "github.com/influxdata/telegraf/plugins/inputs/ethtool"
+ _ "github.com/influxdata/telegraf/plugins/inputs/internal"
+ _ "github.com/influxdata/telegraf/plugins/inputs/interrupts"
+ _ "github.com/influxdata/telegraf/plugins/inputs/ipset"
+ _ "github.com/influxdata/telegraf/plugins/inputs/iptables"
+ _ "github.com/influxdata/telegraf/plugins/inputs/kernel"
+ _ "github.com/influxdata/telegraf/plugins/inputs/mem"
+ _ "github.com/influxdata/telegraf/plugins/inputs/net"
+ _ "github.com/influxdata/telegraf/plugins/inputs/net_response"
+ _ "github.com/influxdata/telegraf/plugins/inputs/ping"
+ _ "github.com/influxdata/telegraf/plugins/inputs/processes"
+ _ "github.com/influxdata/telegraf/plugins/inputs/procstat"
+ _ "github.com/influxdata/telegraf/plugins/inputs/prometheus"
+ _ "github.com/influxdata/telegraf/plugins/inputs/sensors"
+ _ "github.com/influxdata/telegraf/plugins/inputs/snmp"
+ _ "github.com/influxdata/telegraf/plugins/inputs/socket_listener"
+ _ "github.com/influxdata/telegraf/plugins/inputs/swap"
+ _ "github.com/influxdata/telegraf/plugins/inputs/syslog"
+ _ "github.com/influxdata/telegraf/plugins/inputs/system"
+ _ "github.com/influxdata/telegraf/plugins/inputs/tail"
+ _ "github.com/influxdata/telegraf/plugins/inputs/tcp_listener"
+ _ "github.com/influxdata/telegraf/plugins/inputs/udp_listener"
+ _ "github.com/influxdata/telegraf/plugins/inputs/wireguard"
+ _ "github.com/influxdata/telegraf/plugins/inputs/wireless"
+)
diff --git a/external/subpack/utils/telegraf/variant-small/plugins/outputs/all/all.go b/external/subpack/utils/telegraf/variant-small/plugins/outputs/all/all.go
new file mode 100644
index 0000000..eefc73b
--- /dev/null
+++ b/external/subpack/utils/telegraf/variant-small/plugins/outputs/all/all.go
@@ -0,0 +1,13 @@
+package all
+
+import (
+ //Blank imports for plugins to register themselves
+ _ "github.com/influxdata/telegraf/plugins/outputs/exec"
+ _ "github.com/influxdata/telegraf/plugins/outputs/file"
+ _ "github.com/influxdata/telegraf/plugins/outputs/graphite"
+ _ "github.com/influxdata/telegraf/plugins/outputs/http"
+ _ "github.com/influxdata/telegraf/plugins/outputs/influxdb"
+ _ "github.com/influxdata/telegraf/plugins/outputs/influxdb_v2"
+ _ "github.com/influxdata/telegraf/plugins/outputs/prometheus_client"
+ _ "github.com/influxdata/telegraf/plugins/outputs/syslog"
+)
diff --git a/external/subpack/utils/telegraf/variant-small/plugins/processors/all/all.go b/external/subpack/utils/telegraf/variant-small/plugins/processors/all/all.go
new file mode 100644
index 0000000..001f130
--- /dev/null
+++ b/external/subpack/utils/telegraf/variant-small/plugins/processors/all/all.go
@@ -0,0 +1,5 @@
+package all
+
+import (
+ //Blank imports for plugins to register themselves
+)
diff --git a/external/subpack/utils/telldus-core/Makefile b/external/subpack/utils/telldus-core/Makefile
new file mode 100644
index 0000000..f7e46fc
--- /dev/null
+++ b/external/subpack/utils/telldus-core/Makefile
@@ -0,0 +1,63 @@
+#
+# Copyright (C) 2010 Telldus Technologies AB
+#
+# This is free software, licensed under the GNU General Public License v2.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=telldus-core
+PKG_VERSION:=2.1.2
+PKG_RELEASE:=6
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://download.telldus.com/TellStick/Software/telldus-core/
+PKG_HASH:=a20f6c74814afc23312d2c93ebbb37fdea9deaaee05ae7b6a6275e11e4662014
+
+PKG_MAINTAINER:=Peter Liedholm <PeterFromSwe884@gmail.com>
+PKG_LICENSE:=LGPL-2.1-or-later
+PKG_LICENSE_FILES:=LICENSE
+
+CMAKE_INSTALL:=1
+PKG_BUILD_PARALLEL:=0
+PKG_BUILD_DEPENDS:=!USE_GLIBC:argp-standalone
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/telldus-core
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Telldus TellStick USB interface
+ URL:=https://telldus.com
+ DEPENDS:=+confuse +libftdi +libstdcpp
+endef
+
+define Package/telldus-core/description
+ Telldus driver for USB-based 433 MHz RF transceiver for home automation.
+ MUST be built with full language support, (don't know how to DEPEND that)
+endef
+
+define Package/telldus-core/conffiles
+/etc/tellstick.conf
+endef
+
+CMAKE_OPTIONS += \
+ -DBUILD_LIBTELLDUS-CORE=1 \
+ -DBUILD_TDTOOL=1 \
+ -DGENERATE_MAN=0
+
+define Package/telldus-core/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/tdtool $(1)/usr/bin
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/telldusd $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/tdadmin $(1)/usr/sbin
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libtelldus* $(1)/usr/lib
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) ./files/tellstick.conf $(1)/etc
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/telldusd $(1)/etc/init.d
+endef
+
+$(eval $(call BuildPackage,telldus-core))
diff --git a/external/subpack/utils/telldus-core/files/telldusd b/external/subpack/utils/telldus-core/files/telldusd
new file mode 100644
index 0000000..1c75cb5
--- /dev/null
+++ b/external/subpack/utils/telldus-core/files/telldusd
@@ -0,0 +1,20 @@
+#!/bin/sh /etc/rc.common
+
+
+START=99
+
+USE_PROCD=1
+PROG=/usr/sbin/telldusd
+CONFFILE=/etc/tellstick.conf
+
+start_service() {
+ procd_open_instance
+ procd_set_param command $PROG
+ procd_append_param command --nodaemon # foreground required by procd
+ procd_set_param file $CONFFILE
+ procd_set_param term_timeout 10 # telldusd is slow to exit of some reason
+ procd_set_param respawn # respawn the service if it exits
+ procd_set_param stdout 1 # forward stdout of the command to logd
+ procd_set_param stderr 1 # same for stderr
+ procd_close_instance
+}
diff --git a/external/subpack/utils/telldus-core/files/tellstick.conf b/external/subpack/utils/telldus-core/files/tellstick.conf
new file mode 100644
index 0000000..ec76d01
--- /dev/null
+++ b/external/subpack/utils/telldus-core/files/tellstick.conf
@@ -0,0 +1,21 @@
+user = "root"
+group = "root"
+ignoreControllerConfirmation = "false"
+device {
+ id = 1
+ name = "Example device"
+ protocol = "arctech"
+ model = "codeswitch"
+ parameters {
+ house = "A"
+ unit = "1"
+ }
+}
+
+# Example controller (tellstick duo)
+#controller {
+ #id=1
+ # name=""
+ #type=2
+ #serial="A501IVK7"
+#}
diff --git a/external/subpack/utils/telldus-core/patches/100-add_includes.patch b/external/subpack/utils/telldus-core/patches/100-add_includes.patch
new file mode 100644
index 0000000..f4e8232
--- /dev/null
+++ b/external/subpack/utils/telldus-core/patches/100-add_includes.patch
@@ -0,0 +1,21 @@
+Added missing includes required by openwrt. Expected to be portable.
+--- a/common/Socket_unix.cpp
++++ b/common/Socket_unix.cpp
+@@ -8,6 +8,7 @@
+ #include <stdio.h>
+ #include <unistd.h>
+ #include <sys/socket.h>
++#include <sys/select.h> // POSIX.1-2001
+ #include <sys/un.h>
+ #include <fcntl.h>
+ #include <math.h>
+--- a/service/ConnectionListener_unix.cpp
++++ b/service/ConnectionListener_unix.cpp
+@@ -13,6 +13,7 @@
+ #include <fcntl.h>
+ #include <errno.h>
+ #include <string>
++#include <cstring> // strcpy
+
+ #include "service/ConnectionListener.h"
+ #include "common/Socket.h"
diff --git a/external/subpack/utils/telldus-core/patches/110-fix_warnings.patch b/external/subpack/utils/telldus-core/patches/110-fix_warnings.patch
new file mode 100644
index 0000000..f47327c
--- /dev/null
+++ b/external/subpack/utils/telldus-core/patches/110-fix_warnings.patch
@@ -0,0 +1,23 @@
+Added a typecast (signed/unsigned char problem). Should be portable.
+--- a/service/ProtocolIkea.cpp
++++ b/service/ProtocolIkea.cpp
+@@ -23,7 +23,7 @@ int ProtocolIkea::methods() const {
+
+ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Controller *) {
+ const char B1[] = {84, 84, 0};
+- const char B0[] = {170, 0};
++ const char B0[] = {(char)170, 0};
+
+ int intSystem = this->getIntParameter(L"system", 1, 16)-1;
+ int intFadeStyle = TelldusCore::comparei(this->getStringParameter(L"fade", L"true"), L"true");
+--- a/service/ProtocolX10.cpp
++++ b/service/ProtocolX10.cpp
+@@ -22,7 +22,7 @@ int ProtocolX10::methods() const {
+ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Controller *controller) {
+ const unsigned char S = 59, L = 169;
+ const char B0[] = {S, S, 0};
+- const char B1[] = {S, L, 0};
++ const char B1[] = {S, (char)L, 0};
+ const unsigned char START_CODE[] = {'S', 255, 1, 255, 1, 255, 1, 100, 255, 1, 180, 0};
+ const unsigned char STOP_CODE[] = {S, 0};
+
diff --git a/external/subpack/utils/telldus-core/patches/120-fix_missing_var_conf.patch b/external/subpack/utils/telldus-core/patches/120-fix_missing_var_conf.patch
new file mode 100644
index 0000000..d148423
--- /dev/null
+++ b/external/subpack/utils/telldus-core/patches/120-fix_missing_var_conf.patch
@@ -0,0 +1,11 @@
+Added a missing initialisation that under special circumstanses causes seg fault.
+--- a/service/SettingsConfuse.cpp
++++ b/service/SettingsConfuse.cpp
+@@ -435,6 +435,7 @@ bool readVarConfig(cfg_t **cfg) {
+
+ FILE *fp = fopen(VAR_CONFIG_FILE, "re"); // e for setting O_CLOEXEC on the file handle
+ if (!fp) {
++ (*cfg) = 0;
+ Log::warning("Unable to open var config file, %s", VAR_CONFIG_FILE);
+ return false;
+ }
diff --git a/external/subpack/utils/telldus-core/patches/200-no-iconv.patch b/external/subpack/utils/telldus-core/patches/200-no-iconv.patch
new file mode 100644
index 0000000..de9493b
--- /dev/null
+++ b/external/subpack/utils/telldus-core/patches/200-no-iconv.patch
@@ -0,0 +1,72 @@
+--- a/common/Strings.cpp
++++ b/common/Strings.cpp
+@@ -12,7 +12,8 @@
+ #ifdef _WINDOWS
+ #include <windows.h>
+ #else
+-#include <iconv.h>
++#include <locale>
++#include <codecvt>
+ #endif
+ #include <algorithm>
+ #include <sstream>
+@@ -50,35 +51,8 @@ std::wstring TelldusCore::charToWstring(
+ return retval;
+
+ #else
+- size_t utf8Length = strlen(value);
+- size_t outbytesLeft = utf8Length*sizeof(wchar_t);
+-
+- // Copy the instring
+- char *inString = new char[utf8Length+1];
+- snprintf(inString, utf8Length+1, "%s", value);
+-
+- // Create buffer for output
+- char *outString = reinterpret_cast<char*>(new wchar_t[utf8Length+1]);
+- memset(outString, 0, sizeof(wchar_t)*(utf8Length+1));
+-
+-#ifdef _FREEBSD
+- const char *inPointer = inString;
+-#else
+- char *inPointer = inString;
+-#endif
+- char *outPointer = outString;
+-
+- iconv_t convDesc = iconv_open(WCHAR_T_ENCODING, "UTF-8");
+- iconv(convDesc, &inPointer, &utf8Length, &outPointer, &outbytesLeft);
+- iconv_close(convDesc);
+-
+- std::wstring retval( reinterpret_cast<wchar_t *>(outString) );
+-
+- // Cleanup
+- delete[] inString;
+- delete[] outString;
+-
+- return retval;
++ std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
++ return converter.from_bytes(value);
+ #endif
+ }
+
+@@ -211,19 +185,8 @@ std::string TelldusCore::wideToString(co
+ #else
+ char *inPointer = inString;
+ #endif
+- char *outPointer = outString;
+-
+- iconv_t convDesc = iconv_open("UTF-8", WCHAR_T_ENCODING);
+- iconv(convDesc, &inPointer, &wideSize, &outPointer, &outbytesLeft);
+- iconv_close(convDesc);
+-
+- std::string retval(outString);
+-
+- // Cleanup
+- delete[] inString;
+- delete[] outString;
+-
+- return retval;
++ std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
++ return converter.to_bytes(input);
+ #endif
+ }
+
diff --git a/external/subpack/utils/telldus-core/patches/900-openwrt_fixes_cmake.patch b/external/subpack/utils/telldus-core/patches/900-openwrt_fixes_cmake.patch
new file mode 100644
index 0000000..d48e2b2
--- /dev/null
+++ b/external/subpack/utils/telldus-core/patches/900-openwrt_fixes_cmake.patch
@@ -0,0 +1,37 @@
+Adopted to OpenWrt target. Most likely these changes go elsewhere when done right.
+--- a/service/CMakeLists.txt
++++ b/service/CMakeLists.txt
+@@ -98,7 +98,7 @@ IF (UNIX AND NOT APPLE)
+ IF (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
+ SET(DEFAULT_STATE_INSTALL_DIR "/var/spool")
+ ELSE ()
+- SET(DEFAULT_STATE_INSTALL_DIR "/var/state")
++ SET(DEFAULT_STATE_INSTALL_DIR "/tmp/state") # OpenWrt has var as symlink to tmp
+ ENDIF ()
+ SET(STATE_INSTALL_DIR "${DEFAULT_STATE_INSTALL_DIR}" CACHE PATH "The directory to store state information of the devices")
+
+--- a/tdadmin/CMakeLists.txt
++++ b/tdadmin/CMakeLists.txt
+@@ -38,8 +38,11 @@ ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeB
+ ${ARGP_LIBRARY}
+ )
+ ELSE (WIN32)
++ # Linux, in this case openwrt that requires argp-standalone
++ FIND_LIBRARY(ARGP_LIBRARY argp)
+ TARGET_LINK_LIBRARIES(tdadmin
+ ${CMAKE_BINARY_DIR}/client/libtelldus-core.so
++ ${ARGP_LIBRARY}
+ )
+ ENDIF (WIN32)
+
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -62,7 +62,7 @@ IF(DOXYGEN_FOUND)
+ SET(DOXY_CONFIG ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
+
+ CONFIGURE_FILE(
+- "${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in"
++ "${CMAKE_CURRENT_SOURCE_DIR}/CMakeDoxyfile.in"
+ ${DOXY_CONFIG} @ONLY
+ )
+
diff --git a/external/subpack/utils/telldus-core/patches/920-openwrt_missing_var_conf.patch b/external/subpack/utils/telldus-core/patches/920-openwrt_missing_var_conf.patch
new file mode 100644
index 0000000..be87bf8
--- /dev/null
+++ b/external/subpack/utils/telldus-core/patches/920-openwrt_missing_var_conf.patch
@@ -0,0 +1,18 @@
+On OpenWrt targets the tmp filesystem is wiped upon power cycle, so files
+requires to be created.
+--- a/service/SettingsConfuse.cpp
++++ b/service/SettingsConfuse.cpp
+@@ -436,6 +436,13 @@ bool readVarConfig(cfg_t **cfg) {
+ FILE *fp = fopen(VAR_CONFIG_FILE, "re"); // e for setting O_CLOEXEC on the file handle
+ if (!fp) {
+ (*cfg) = 0;
++ fp = fopen(VAR_CONFIG_FILE, "we"); // If missing, create file if possible
++ if(fp) {
++ fclose(fp);
++ }
++ else {
++ Log::warning("Unable to create var config file, %s", VAR_CONFIG_FILE);
++ }
+ Log::warning("Unable to open var config file, %s", VAR_CONFIG_FILE);
+ return false;
+ }
diff --git a/external/subpack/utils/telldus-core/patches/930-usleep.patch b/external/subpack/utils/telldus-core/patches/930-usleep.patch
new file mode 100644
index 0000000..c716129
--- /dev/null
+++ b/external/subpack/utils/telldus-core/patches/930-usleep.patch
@@ -0,0 +1,40 @@
+--- a/common/common.h
++++ b/common/common.h
+@@ -25,15 +25,13 @@
+ #ifdef _WINDOWS
+ #include <fstream> // NOLINT(readability/streams)
+ #endif
++#include <chrono>
+ #include <string>
++#include <thread>
+ #include "common/Strings.h"
+
+ inline void msleep( const int msec) {
+-#ifdef _WINDOWS
+- Sleep(msec);
+-#else
+- usleep(msec*1000);
+-#endif
++ std::this_thread::sleep_for(std::chrono::milliseconds(msec));
+ }
+
+ inline void dlog(const char *fmt, ...) {
+--- a/service/TellStick_libftdi.cpp
++++ b/service/TellStick_libftdi.cpp
+@@ -8,7 +8,6 @@
+ #include <string.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+-#include <unistd.h>
+ #include <list>
+ #include <string>
+
+@@ -231,7 +230,7 @@ int TellStick::send( const std::string &
+ return TELLSTICK_SUCCESS;
+ }
+ } else if(ret == 0) { // No data available
+- usleep(100);
++ std::this_thread::sleep_for(std::chrono::microseconds(100));
+ } else { // Error
+ Log::debug("Broken pipe on read");
+ return TELLSTICK_ERROR_BROKEN_PIPE;
diff --git a/external/subpack/utils/telldus-core/patches/940-cxx11.patch b/external/subpack/utils/telldus-core/patches/940-cxx11.patch
new file mode 100644
index 0000000..bad984f
--- /dev/null
+++ b/external/subpack/utils/telldus-core/patches/940-cxx11.patch
@@ -0,0 +1,29 @@
+--- a/common/Event.h
++++ b/common/Event.h
+@@ -9,7 +9,7 @@
+
+
+ #ifndef _WINDOWS
+- #include <tr1/memory>
++ #include <memory>
+ typedef void* EVENT_T;
+ #else
+ #include <windows.h>
+@@ -32,7 +32,7 @@ namespace TelldusCore {
+ virtual bool isValid() const;
+ };
+
+- typedef std::tr1::shared_ptr<EventData> EventDataRef;
++ typedef std::shared_ptr<EventData> EventDataRef;
+
+ class EventBase {
+ public:
+@@ -74,7 +74,7 @@ namespace TelldusCore {
+ friend class EventHandler;
+ };
+
+- typedef std::tr1::shared_ptr<Event> EventRef;
++ typedef std::shared_ptr<Event> EventRef;
+ }
+
+ #endif // TELLDUS_CORE_COMMON_EVENT_H_
diff --git a/external/subpack/utils/telldus-core/patches/950-pthread.patch b/external/subpack/utils/telldus-core/patches/950-pthread.patch
new file mode 100644
index 0000000..89cb89f
--- /dev/null
+++ b/external/subpack/utils/telldus-core/patches/950-pthread.patch
@@ -0,0 +1,21 @@
+--- a/common/Thread.cpp
++++ b/common/Thread.cpp
+@@ -16,6 +16,8 @@
+ #endif
+ #include "common/EventHandler.h"
+
++#include <pthread.h>
++
+ namespace TelldusCore {
+
+ class ThreadPrivate {
+--- a/service/Timer.cpp
++++ b/service/Timer.cpp
+@@ -7,6 +7,7 @@
+ #include "service/Timer.h"
+ #ifdef _WINDOWS
+ #else
++#include <pthread.h>
+ #include <sys/time.h>
+ #include <errno.h>
+ #endif
diff --git a/external/subpack/utils/telldus-core/patches/960-time.patch b/external/subpack/utils/telldus-core/patches/960-time.patch
new file mode 100644
index 0000000..eb659de
--- /dev/null
+++ b/external/subpack/utils/telldus-core/patches/960-time.patch
@@ -0,0 +1,20 @@
+--- a/service/DeviceManager.h
++++ b/service/DeviceManager.h
+@@ -7,6 +7,7 @@
+ #ifndef TELLDUS_CORE_SERVICE_DEVICEMANAGER_H_
+ #define TELLDUS_CORE_SERVICE_DEVICEMANAGER_H_
+
++#include <ctime>
+ #include <set>
+ #include <string>
+ #include "service/Device.h"
+--- a/service/Sensor.h
++++ b/service/Sensor.h
+@@ -7,6 +7,7 @@
+ #ifndef TELLDUS_CORE_SERVICE_SENSOR_H_
+ #define TELLDUS_CORE_SERVICE_SENSOR_H_
+
++#include <ctime>
+ #include <string>
+ #include "common/Mutex.h"
+
diff --git a/external/subpack/utils/temperusb/Makefile b/external/subpack/utils/temperusb/Makefile
new file mode 100644
index 0000000..7bbea2b
--- /dev/null
+++ b/external/subpack/utils/temperusb/Makefile
@@ -0,0 +1,42 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=temperusb
+PKG_VERSION:=2.3
+PKG_RELEASE:=1
+PKG_CONFIG_DEPENDS:=libusb
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/temperv14-$(PKG_VERSION)
+PKG_SOURCE_URL:=https://codeload.github.com/Arduous/temperv14/tar.gz/v${PKG_VERSION}?
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_HASH:=3319026e0d5c42aebe9a75a23593f181c29d0ec9d544fac90b7ba886269ff246
+PKG_LICENSE:=BSD-2-Clause
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_MAINTAINER := Samuel Progin <samuel.progin@gmail.com>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/temperusb
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libusb-1.0
+ TITLE:=USB Thermometer RDing TEMPer v1.4 reader
+endef
+
+define Package/temperusb/description
+ RDing TEMPer v1.4 USB thermometer are cheap devices that can be sourced everywhere on
+ the Internet. This package allows to operate them from user space.
+endef
+
+define Package/temperusb/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/temperusb $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,temperusb))
+
diff --git a/external/subpack/utils/tessdata/Makefile b/external/subpack/utils/tessdata/Makefile
new file mode 100644
index 0000000..376d16c
--- /dev/null
+++ b/external/subpack/utils/tessdata/Makefile
@@ -0,0 +1,63 @@
+# Copyright (C) 2019 Valentín Kivachuk <vk18496@gmail.com>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tessdata
+PKG_VERSION:=4.1.0
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/tesseract-ocr/tessdata/tar.gz/$(PKG_VERSION)?
+PKG_HASH:=990fffb9b7a9b52dc9a2d053a9ef6852ca2b72bd8dfb22988b0b990a700fd3c7
+
+PKG_MAINTAINER:=Valentín Kivachuk <vk18496@gmail.com>
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=COPYING
+
+#No need to extract 1,5GB... We only extract what we need.
+PKG_UNPACK:=
+
+include $(INCLUDE_DIR)/package.mk
+
+ALLTESSERACTLANG:=afr amh ara asm aze aze_cyrl bel ben bod bos bre bul cat ceb ces chi_sim chi_sim_vert chi_tra chi_tra_vert chr cos cym dan dan_frak deu deu_frak div dzo ell eng enm epo equ est eus fao fas fil fin fra frk frm fry gla gle glg grc guj hat heb hin hrv hun hye iku ind isl ita ita_old jav jpn jpn_vert kan kat kat_old kaz khm kir kmr kor kor_vert lao lat lav lit ltz mal mar mkd mlt mon mri msa mya nep nld nor oci ori osd pan pol por pus que ron rus san sin slk slk_frak slv snd spa spa_old sqi srp srp_latn sun swa swe syr tam tat tel tgk tgl tha tir ton tur uig ukr urd uzb uzb_cyrl vie yid yor
+
+
+define Build/Prepare
+ $(Build/Prepare/Default)
+ $(TAR) --strip=1 -C $(PKG_BUILD_DIR) -xvf $(DL_DIR)/$(PKG_NAME)-$(PKG_VERSION).tar.gz --exclude 'script' --wildcards '*.traineddata'
+endef
+
+define Build/Compile
+endef
+
+define Build/Install
+endef
+
+
+define Package/tesseract-data-default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=tesseract
+ PKGARCH:=all
+endef
+
+define generate-tesseract-data-package
+ define Package/tesseract-data-$(1)
+ TITLE:=Training data for $(1) language
+ $(call Package/tesseract-data-default)
+ endef
+
+ define Package/tesseract-data-$(1)/install
+ $(INSTALL_DIR) $$(1)/usr/share/tessdata
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(1).traineddata $$(1)/usr/share/tessdata/
+ endef
+
+endef
+
+
+$(foreach LANG,$(ALLTESSERACTLANG),$(eval $(call generate-tesseract-data-package,$(LANG))))
+$(foreach LANG,$(ALLTESSERACTLANG),$(eval $(call BuildPackage,tesseract-data-$(LANG))))
diff --git a/external/subpack/utils/tesseract/Makefile b/external/subpack/utils/tesseract/Makefile
new file mode 100644
index 0000000..b3aebe5
--- /dev/null
+++ b/external/subpack/utils/tesseract/Makefile
@@ -0,0 +1,59 @@
+# Copyright (C) 2019 Valentin Kivachuk <vk18496@gmail.com>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tesseract
+PKG_VERSION:=4.0.0
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/tesseract-ocr/tesseract/tar.gz/$(PKG_VERSION)?
+PKG_HASH:=a1f5422ca49a32e5f35c54dee5112b11b99928fc9f4ee6695cdc6768d69f61dd
+
+PKG_MAINTAINER:=Valentin Kivachuk <vk18496@gmail.com>
+PKG_LICENSE:=Apache-2.0
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_PARALLEL:=1
+CMAKE_BINARY_SUBDIR:=openwrt-build
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/tesseract
+ MENU:=1
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Tesseract Open Source OCR Engine
+ URL:=https://github.com/tesseract-ocr/tesseract
+ DEPENDS:=+libleptonica +libpthread +libstdcpp
+endef
+
+TARGET_CFLAGS:=$(filter-out -O%,$(TARGET_CFLAGS)) -O3
+
+CMAKE_OPTIONS += \
+ -DBUILD_TRAINING_TOOLS=OFF
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/tesseract $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libtesseract.so* $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/cmake
+ $(CP) $(PKG_INSTALL_DIR)/usr/cmake/*.cmake $(1)/usr/lib/cmake/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/tesseract.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/tesseract/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib*.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,tesseract))
diff --git a/external/subpack/utils/tesseract/patches/010-cmake.patch b/external/subpack/utils/tesseract/patches/010-cmake.patch
new file mode 100644
index 0000000..5b77e57
--- /dev/null
+++ b/external/subpack/utils/tesseract/patches/010-cmake.patch
@@ -0,0 +1,44 @@
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -224,41 +224,6 @@ set(tesseract_src ${tesseract_src}
+ src/api/pdfrenderer.cpp
+ )
+
+-if (WIN32)
+- if (MSVC)
+- include_directories(src/vs2010/tesseract)
+- set(tesseract_hdr
+- ${tesseract_hdr}
+- ${CMAKE_CURRENT_SOURCE_DIR}/src/vs2010/tesseract/resource.h)
+- set(tesseract_rsc ${CMAKE_BINARY_DIR}/vs2010/tesseract/libtesseract.rc)
+- set_source_files_properties(
+- ${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductsse.cpp
+- PROPERTIES COMPILE_DEFINITIONS __SSE4_1__)
+- set_source_files_properties(
+- ${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixsse.cpp
+- PROPERTIES COMPILE_DEFINITIONS __SSE4_1__)
+- set_source_files_properties(
+- ${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductavx.cpp
+- PROPERTIES COMPILE_FLAGS "/arch:AVX")
+- set_source_files_properties(
+- ${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixavx2.cpp
+- PROPERTIES COMPILE_FLAGS "/arch:AVX2")
+- endif()
+-else()
+- set_source_files_properties(
+- ${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductsse.cpp
+- PROPERTIES COMPILE_FLAGS "-msse4.1")
+- set_source_files_properties(
+- ${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixsse.cpp
+- PROPERTIES COMPILE_FLAGS "-msse4.1")
+- set_source_files_properties(
+- ${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductavx.cpp
+- PROPERTIES COMPILE_FLAGS "-mavx")
+- set_source_files_properties(
+- ${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixavx2.cpp
+- PROPERTIES COMPILE_FLAGS "-mavx2")
+-endif()
+-
+ add_library (libtesseract ${LIBRARY_TYPE} ${tesseract_src} ${tesseract_hdr}
+ ${tesseract_rsc}
+ )
diff --git a/external/subpack/utils/tini/Makefile b/external/subpack/utils/tini/Makefile
new file mode 100644
index 0000000..c7ad5bc
--- /dev/null
+++ b/external/subpack/utils/tini/Makefile
@@ -0,0 +1,44 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tini
+PKG_VERSION:=0.19.0
+PKG_RELEASE:=2
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/krallin/tini/tar.gz/v${PKG_VERSION}?
+PKG_HASH:=0fd35a7030052acd9f58948d1d900fe1e432ee37103c5561554408bdac6bbf0d
+PKG_SOURCE_VERSION:=de40ad007797e0dcd8b7126f27bb87401d224240
+TINI_COMMIT:=de40ad0
+
+PKG_MAINTAINER:=Gerard Ryan <G.M0N3Y.2503@gmail.com>
+
+CMAKE_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/tini
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=simplest init utility
+ URL:=https://github.com/krallin/tini
+ DEPENDS:=
+endef
+
+define Package/tini/description
+A tiny but valid init process for containers.
+endef
+
+CMAKE_OPTIONS += -DTINI_VERSION_GIT='$(TINI_COMMIT)'
+TARGET_LDFLAGS += $(if $(CONFIG_USE_GLIBC),-lc -lgcc_eh)
+
+define Package/tini/install
+ $(INSTALL_DIR) $(1)/usr/bin
+
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/tini-static $(1)/usr/bin/docker-init
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/tini $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,tini))
diff --git a/external/subpack/utils/tini/patches/001-override-git-version.patch b/external/subpack/utils/tini/patches/001-override-git-version.patch
new file mode 100644
index 0000000..bd64849
--- /dev/null
+++ b/external/subpack/utils/tini/patches/001-override-git-version.patch
@@ -0,0 +1,67 @@
+commit 31b0908a5eff3926195670beecc8548c429ceff5
+Author: Gerard Ryan <G.M0N3Y.2503@gmail.com>
+Date: Sat Oct 31 16:53:39 2020 +1000
+
+ Added support for setting git version externally
+ * This to help when building from source snapshots
+ that don't have the .git file structure.
+
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -13,27 +13,37 @@ if(MINIMAL)
+ add_definitions(-DTINI_MINIMAL=1)
+ endif()
+
+-# Extract git version and dirty-ness
+-execute_process (
+- COMMAND git --git-dir "${PROJECT_SOURCE_DIR}/.git" --work-tree "${PROJECT_SOURCE_DIR}" log -n 1 --date=local --pretty=format:%h
+- WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
+- RESULT_VARIABLE git_version_check_ret
+- OUTPUT_VARIABLE tini_VERSION_GIT
+-)
++# Set the git version
++if (NOT "${TINI_VERSION_GIT}" STREQUAL "")
++ # Set by the user directly
++ set(tini_VERSION_GIT "${TINI_VERSION_GIT}")
++else()
++ # Extract git version
++ execute_process (
++ COMMAND git --git-dir "${PROJECT_SOURCE_DIR}/.git" --work-tree "${PROJECT_SOURCE_DIR}" log -n 1 --date=local --pretty=format:%h
++ WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
++ RESULT_VARIABLE git_version_check_ret
++ OUTPUT_VARIABLE tini_VERSION_GIT
++ )
+
+-execute_process(
+- COMMAND git --git-dir "${PROJECT_SOURCE_DIR}/.git" --work-tree "${PROJECT_SOURCE_DIR}" status --porcelain --untracked-files=no
+- WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
+- OUTPUT_VARIABLE git_dirty_check_out
+-)
++ if("${git_version_check_ret}" EQUAL 0)
++ # Extract git dirty-ness
++ execute_process(
++ COMMAND git --git-dir "${PROJECT_SOURCE_DIR}/.git" --work-tree "${PROJECT_SOURCE_DIR}" status --porcelain --untracked-files=no
++ WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
++ OUTPUT_VARIABLE git_dirty_check_out
++ )
+
+-if("${git_version_check_ret}" EQUAL 0)
+- set(tini_VERSION_GIT " - git.${tini_VERSION_GIT}")
+- if(NOT "${git_dirty_check_out}" STREQUAL "")
+- set(tini_VERSION_GIT "${tini_VERSION_GIT}-dirty")
+- endif()
+-else()
+- set(tini_VERSION_GIT "")
++ if(NOT "${git_dirty_check_out}" STREQUAL "")
++ set(tini_VERSION_GIT "${tini_VERSION_GIT}-dirty")
++ endif()
++ else()
++ set(tini_VERSION_GIT "")
++ endif()
++endif()
++
++if(NOT ${tini_VERSION_GIT} STREQUAL "")
++ set(tini_VERSION_GIT " - git.${tini_VERSION_GIT}")
+ endif()
+
+ # Flags
diff --git a/external/subpack/utils/tinyionice/Makefile b/external/subpack/utils/tinyionice/Makefile
new file mode 100644
index 0000000..e3acb6d
--- /dev/null
+++ b/external/subpack/utils/tinyionice/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2022 CZ.NIC, z. s. p. o. (https://www.nic.cz/)
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tinyionice
+PKG_VERSION:=1.0.0
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/xyproto/tinyionice/tar.gz/v${PKG_VERSION}?
+PKG_HASH:=65d903b5d69ca1d121bc9ad1a635a49b49233a99121ce40730b3617048ff6a84
+
+PKG_MAINTAINER:=Michal Vasilek <michal.vasilek@nic.cz>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/tinyionice
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Independent fork of ionice from util-linux
+ URL:=https://github.com/xyproto/tinyionice
+endef
+
+define Package/tinyionice/Default/description
+ Independent fork of ionice from util-linux
+endef
+
+define Package/tinyionice/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,tinyionice))
diff --git a/external/subpack/utils/tinyionice/patches/0001-Add-a-makefile.patch b/external/subpack/utils/tinyionice/patches/0001-Add-a-makefile.patch
new file mode 100644
index 0000000..86cdc6d
--- /dev/null
+++ b/external/subpack/utils/tinyionice/patches/0001-Add-a-makefile.patch
@@ -0,0 +1,34 @@
+From fd3c17ad5d4e3acaa5469f408e57bb9375253e4d Mon Sep 17 00:00:00 2001
+From: Michal Vasilek <michal.vasilek@nic.cz>
+Date: Thu, 3 Feb 2022 19:45:26 +0100
+Subject: [PATCH] Add a makefile
+
+---
+ Makefile | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+ create mode 100644 Makefile
+
+--- /dev/null
++++ b/Makefile
+@@ -0,0 +1,21 @@
++CC = cc
++CFLAGS=-O2 -fPIC -fstack-protector-strong -D_GNU_SOURCE -s -z norelro
++PREFIX=/usr
++BINDIR=$(PREFIX)/bin
++
++all: tinyionice
++
++tinyionice: main.c
++ $(CC) $(CFLAGS) $< -o $@
++
++install: tinyionice
++ install -D -m 755 tinyionice $(DESTDIR)/$(BINDIR)/tinyionice
++
++uninstall:
++ rm -f $(DESTDIR)/$(BINDIR)/tinyionice
++
++clean:
++ rm -f tinyionice
++
++
++.PHONY: all install uninstall clean
diff --git a/external/subpack/utils/tinyionice/test.sh b/external/subpack/utils/tinyionice/test.sh
new file mode 100644
index 0000000..6f7a046
--- /dev/null
+++ b/external/subpack/utils/tinyionice/test.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+tinyionice --version | grep "$PKG_VERSION"
diff --git a/external/subpack/utils/tio/Makefile b/external/subpack/utils/tio/Makefile
new file mode 100644
index 0000000..7fa987b
--- /dev/null
+++ b/external/subpack/utils/tio/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2017-2018 Daniel Engberg <daniel.engberg.lists@pyret.net>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tio
+PKG_VERSION:=1.32
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://github.com/tio/tio/releases/download/v$(PKG_VERSION)
+PKG_HASH:=a8f5ed6994cacb96780baa416b19e5a6d7d67e8c162a8ea4fd9eccd64984ae44
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/tio
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=A simple TTY terminal I/O application
+ URL:=https://tio.github.io/
+ SUBMENU:=Terminal
+endef
+
+define Package/tio/description
+ A small and simple TTY terminal I/O application
+endef
+
+define Package/tio/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/tio $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,tio))
diff --git a/external/subpack/utils/tmux/Makefile b/external/subpack/utils/tmux/Makefile
new file mode 100644
index 0000000..d180cad
--- /dev/null
+++ b/external/subpack/utils/tmux/Makefile
@@ -0,0 +1,45 @@
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tmux
+PKG_VERSION:=3.1c
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/tmux/tmux/tar.gz/$(PKG_VERSION)?
+PKG_HASH:=b9617dd4d1c541ebc21b6b5760d58102fc039a593786aab273b5dd95dd514bea
+PKG_MAINTAINER:=Maxim Storchak <m.storchak@gmail.com>
+
+PKG_LICENSE:=ISC
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:nicholas_marriott:tmux
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/tmux
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Terminal
+ TITLE:=Terminal multiplexer
+ DEPENDS:=+libncurses +libevent2 +libpthread +librt
+ URL:=http://tmux.github.io/
+endef
+
+define Package/tmux/description
+ tmux is a modern, BSD-licensed alternative to GNU screen.
+endef
+
+define Package/tmux/conffiles
+/etc/tmux.conf
+endef
+
+define Package/tmux/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/tmux $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,tmux))
diff --git a/external/subpack/utils/tmux/test.sh b/external/subpack/utils/tmux/test.sh
new file mode 100644
index 0000000..f494b5d
--- /dev/null
+++ b/external/subpack/utils/tmux/test.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+tmux -V | grep "$2"
diff --git a/external/subpack/utils/tracertools/Makefile b/external/subpack/utils/tracertools/Makefile
new file mode 100644
index 0000000..6a30a94
--- /dev/null
+++ b/external/subpack/utils/tracertools/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2007-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tracertools
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/dangowrt/tracertools
+PKG_SOURCE_DATE:=2020-08-16
+PKG_SOURCE_VERSION:=d8acfcad1fdf44cd76b8ba9014326f0db6e582d5
+PKG_MIRROR_HASH:=db0748a58385aa600d147d0647ca3261d9407b9004db11d401977c59f93399ff
+
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/tracertools
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Tracer MPPT monitoring and control tools
+endef
+
+define Package/tracertools/description
+ Tools for the Tracer MPPT solar charge controller.
+endef
+
+define Package/tracertools/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/tracerstat $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,tracertools))
diff --git a/external/subpack/utils/tree/Makefile b/external/subpack/utils/tree/Makefile
new file mode 100644
index 0000000..60b6f67
--- /dev/null
+++ b/external/subpack/utils/tree/Makefile
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tree
+PKG_RELEASE:=1
+PKG_VERSION:=2.0.2
+PKG_SOURCE_URL:=http://mama.indstate.edu/users/ice/tree/src
+PKG_HASH:=7d693a1d88d3c4e70a73e03b8dbbdc12c2945d482647494f2f5bd83a479eeeaf
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tgz
+PKG_MAINTAINER:=Banglang Huang <banglang.huang@foxmail.com>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/tree
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=List contents of directories in a tree-like format
+ DEPENDS:=+libc +libgcc
+endef
+
+MAKE_FLAGS += \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ LDFLAGS="$(TARGET_LDFLAGS)"
+
+define Package/tree/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/tree $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,tree))
diff --git a/external/subpack/utils/triggerhappy/Makefile b/external/subpack/utils/triggerhappy/Makefile
new file mode 100644
index 0000000..e25b868
--- /dev/null
+++ b/external/subpack/utils/triggerhappy/Makefile
@@ -0,0 +1,57 @@
+#
+# Copyright (C) 2014-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=triggerhappy
+PKG_VERSION:=0.5.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/wertarbyte/$(PKG_NAME)/archive/release/$(PKG_VERSION)/
+PKG_HASH:=af0fc196202f2d35153be401769a9ad9107b5b6387146cfa8895ae9cafad631c
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-release-$(PKG_VERSION)
+
+PKG_MAINTAINER:=Ted Hess <thess@kitschensync.net>
+PKG_LICENSE:=GPL-3.0
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/triggerhappy
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=handle input events and run configured programs
+ URL:=http://github.com/wertarbyte/triggerhappy
+endef
+
+define Package/triggerhappy/description
+ triggerhappy - handle input events and run configured programs
+ The daemon thd can handle hotplugged input devices and is configured through
+ simple configuration files in /etc/triggerhappy/triggers.d/.
+endef
+
+MAKE_FLAGS += \
+ $(TARGET_CONFIGURE_OPTS) \
+ $(1)
+
+define Package/triggerhappy/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_DIR) $(1)/etc
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_DIR) $(1)/etc/triggerhappy
+ $(INSTALL_DIR) $(1)/etc/triggerhappy/triggers.d/
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/input/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/thd $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/th-cmd $(1)/usr/sbin
+ $(INSTALL_BIN) ./files/triggerhappy.init $(1)/etc/init.d/triggerhappy
+ $(INSTALL_BIN) ./files/triggerhappy.hotplug $(1)/etc/hotplug.d/input/10-triggerhappy
+ $(INSTALL_BIN) ./files/triggerhappy-example.conf $(1)/etc/triggerhappy/triggers.d/example.conf
+endef
+
+$(eval $(call BuildPackage,triggerhappy))
diff --git a/external/subpack/utils/triggerhappy/files/triggerhappy-example.conf b/external/subpack/utils/triggerhappy/files/triggerhappy-example.conf
new file mode 100644
index 0000000..3a8017a
--- /dev/null
+++ b/external/subpack/utils/triggerhappy/files/triggerhappy-example.conf
@@ -0,0 +1,14 @@
+# This is an example configuration for the triggerhappy daemon (thd)
+# please note that every file to be processed must end in ".conf"
+#
+# To view a list of supported event codes, use "thd --listevents" or
+# "thd --dump /dev/input/event*"
+#
+# Format:
+# <eventcode> <value> <command>
+#
+# values for key events are 1 (pressed), 0 (released) or 2 (held)
+#
+## control an mpd instance
+# KEY_NEXTSONG 1 /usr/bin/mpc next
+# KEY_PREVSONG 1 /usr/bin/mpc prev
diff --git a/external/subpack/utils/triggerhappy/files/triggerhappy.hotplug b/external/subpack/utils/triggerhappy/files/triggerhappy.hotplug
new file mode 100644
index 0000000..78ad349
--- /dev/null
+++ b/external/subpack/utils/triggerhappy/files/triggerhappy.hotplug
@@ -0,0 +1,15 @@
+#!/bin/sh
+THD_SOCKET=/tmp/triggerhappy.socket
+[ -S "$THD_SOCKET" ] || exit
+
+case "$ACTION" in
+ add)
+ DEVICE="/dev/$DEVNAME"
+ [ -c "$DEVICE" ] || exit
+ # offer device to triggerhappy daemon
+ /usr/sbin/th-cmd --socket "$THD_SOCKET" --add "$DEVICE"
+ ;;
+ remove)
+ # nothing to do
+ ;;
+esac
diff --git a/external/subpack/utils/triggerhappy/files/triggerhappy.init b/external/subpack/utils/triggerhappy/files/triggerhappy.init
new file mode 100644
index 0000000..e846d29
--- /dev/null
+++ b/external/subpack/utils/triggerhappy/files/triggerhappy.init
@@ -0,0 +1,10 @@
+#!/bin/sh /etc/rc.common
+START=93
+
+start() {
+ /usr/sbin/thd --socket /tmp/triggerhappy.socket --triggers /etc/triggerhappy/triggers.d/ --daemon /dev/input/event*
+}
+
+stop() {
+ /usr/sbin/th-cmd --socket /tmp/triggerhappy.socket --quit
+}
diff --git a/external/subpack/utils/ttyd/Makefile b/external/subpack/utils/ttyd/Makefile
new file mode 100644
index 0000000..d995fc6
--- /dev/null
+++ b/external/subpack/utils/ttyd/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2016 Shuanglei Tao <tsl0922@gmail.com>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ttyd
+PKG_VERSION:=1.6.3
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/tsl0922/ttyd/tar.gz/$(PKG_VERSION)?
+PKG_HASH:=1116419527edfe73717b71407fb6e06f46098fc8a8e6b0bb778c4c75dc9f64b9
+
+PKG_MAINTAINER:=Shuanglei Tao <tsl0922@gmail.com>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/ttyd
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Command-line tool for sharing terminal over the web
+ DEPENDS:=+libopenssl +libjson-c +libuv +zlib +libwebsockets-full
+ URL:=https://github.com/tsl0922/ttyd
+ SUBMENU:=Terminal
+endef
+
+define Package/ttyd/description
+ttyd is a command-line tool for sharing terminal over the web.
+endef
+
+define Package/ttyd/conffiles
+/etc/config/ttyd
+endef
+
+define Package/ttyd/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ttyd $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/etc/config/
+ $(INSTALL_CONF) ./files/ttyd.config $(1)/etc/config/ttyd
+ $(INSTALL_DIR) $(1)/etc/init.d/
+ $(INSTALL_BIN) ./files/ttyd.init $(1)/etc/init.d/ttyd
+endef
+
+$(eval $(call BuildPackage,ttyd))
diff --git a/external/subpack/utils/ttyd/files/ttyd.config b/external/subpack/utils/ttyd/files/ttyd.config
new file mode 100644
index 0000000..8dbde70
--- /dev/null
+++ b/external/subpack/utils/ttyd/files/ttyd.config
@@ -0,0 +1,5 @@
+
+config ttyd
+ option interface '@lan'
+ option command '/bin/login'
+
diff --git a/external/subpack/utils/ttyd/files/ttyd.init b/external/subpack/utils/ttyd/files/ttyd.init
new file mode 100644
index 0000000..0a3d440
--- /dev/null
+++ b/external/subpack/utils/ttyd/files/ttyd.init
@@ -0,0 +1,102 @@
+#!/bin/sh /etc/rc.common
+
+START=99
+STOP=50
+USE_PROCD=1
+
+NAME=ttyd
+PROG=/usr/bin/$NAME
+
+validate_section_ttyd()
+{
+ uci_load_validate ttyd ttyd "$1" "$2" \
+ 'enable:bool:1' \
+ 'port:port' \
+ 'interface:string' \
+ 'credential:string' \
+ 'uid:uinteger' \
+ 'gid:uinteger' \
+ 'signal:uinteger' \
+ 'url_arg:bool' \
+ 'readonly:bool' \
+ 'client_option:list(string)' \
+ 'terminal_type:string' \
+ 'check_origin:bool' \
+ 'max_clients:uinteger' \
+ 'once:bool' \
+ 'index:string' \
+ 'ipv6:bool' \
+ 'ssl:bool' \
+ 'ssl_cert:file' \
+ 'ssl_key:file' \
+ 'ssl_ca:file' \
+ 'debug:uinteger' \
+ 'command:string'
+}
+
+ttyd_instance()
+{
+ [ "$2" = 0 ] || {
+ echo "validation failed"
+ return 1
+ }
+
+ [ "$enable" = 0 ] && return 1
+ [ -z "$command" ] && return 1
+
+ [ "${interface::1}" = @ ] && {
+ interface=$(
+ . /lib/functions/network.sh
+ network_get_device device "${interface:1}"
+ echo -n "$device"
+ )
+ }
+
+ [ "$url_arg" = 0 ] && url_arg=""
+ [ "$readonly" = 0 ] && readonly=""
+ [ "$check_origin" = 0 ] && check_origin=""
+ [ "$once" = 0 ] && once=""
+ [ "$ipv6" = 0 ] && ipv6=""
+ [ "$ssl" = 0 ] && ssl=""
+
+ procd_open_instance
+ procd_set_param command "$PROG" \
+ ${port:+-p $port} \
+ ${interface:+-i $interface} \
+ ${credential:+-c $credential} \
+ ${uid:+-u $uid} \
+ ${gid:+-g $gid} \
+ ${signal:+-s $signal} \
+ ${url_arg:+-a} \
+ ${readonly:+-R} \
+ ${terminal_type:+-T $terminal_type} \
+ ${check_origin:+-O} \
+ ${max_clients:+-m $max_clients} \
+ ${once:+-o} \
+ ${index:+-I $index} \
+ ${ipv6:+-6} \
+ ${ssl:+-S} \
+ ${ssl_cert:+-C $ssl_cert} \
+ ${ssl_key:+-K $ssl_key} \
+ ${ssl_ca:+-A $ssl_ca} \
+ ${debug:+-d $debug}
+ config_list_foreach "$1" client_option "procd_append_param command -t"
+ procd_append_param command $command
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_close_instance
+}
+
+start_service() {
+ config_load "$NAME"
+ config_foreach validate_section_ttyd ttyd ttyd_instance
+}
+
+shutdown() {
+ # close all open connections
+ killall "$NAME"
+}
+
+service_triggers() {
+ procd_add_reload_trigger "$NAME"
+}
diff --git a/external/subpack/utils/ttyd/patches/090-fix-ssl-ca-option-init.patch b/external/subpack/utils/ttyd/patches/090-fix-ssl-ca-option-init.patch
new file mode 100644
index 0000000..06803ae
--- /dev/null
+++ b/external/subpack/utils/ttyd/patches/090-fix-ssl-ca-option-init.patch
@@ -0,0 +1,14 @@
+--- a/src/server.c
++++ b/src/server.c
+@@ -509,9 +509,10 @@ int main(int argc, char **argv) {
+ if (ssl) {
+ info.ssl_cert_filepath = cert_path;
+ info.ssl_private_key_filepath = key_path;
+- if (strlen(ca_path) > 0)
++ if (strlen(ca_path) > 0) {
+ info.ssl_ca_filepath = ca_path;
+ info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
++ }
+ #if LWS_LIBRARY_VERSION_MAJOR >= 2
+ info.options |= LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS;
+ #endif
diff --git a/external/subpack/utils/ttyd/patches/100-log-to-syslog.patch b/external/subpack/utils/ttyd/patches/100-log-to-syslog.patch
new file mode 100644
index 0000000..06012df
--- /dev/null
+++ b/external/subpack/utils/ttyd/patches/100-log-to-syslog.patch
@@ -0,0 +1,20 @@
+--- a/src/server.c
++++ b/src/server.c
+@@ -10,6 +10,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <sys/stat.h>
++#include <syslog.h>
+
+ #include "utils.h"
+
+@@ -478,7 +479,8 @@ int main(int argc, char **argv) {
+ return -1;
+ }
+
+- lws_set_log_level(debug_level, NULL);
++ openlog("ttyd", LOG_NDELAY | LOG_PID, LOG_DAEMON);
++ lws_set_log_level(debug_level, lwsl_emit_syslog);
+
+ #if LWS_LIBRARY_VERSION_MAJOR >= 2
+ char server_hdr[128] = "";
diff --git a/external/subpack/utils/ubnt-manager/Makefile b/external/subpack/utils/ubnt-manager/Makefile
new file mode 100644
index 0000000..8416eff
--- /dev/null
+++ b/external/subpack/utils/ubnt-manager/Makefile
@@ -0,0 +1,40 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ubnt-manager
+PKG_VERSION:=1
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_MAINTAINER:=Nick Hainke <vincent@systemli.org>
+PKG_LICENSE:=GPL-2.0-only
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ubnt-manager
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Managment app for Ubiquiti devices
+ PKGARCH:=all
+ EXTRA_DEPENDS:=dropbear
+endef
+
+define Package/ubnt-manager/description
+Managment app for Ubiquiti devices.
+endef
+
+define Package/ubnt-manager/conffiles
+/etc/config/ubnt-manager
+endef
+
+define Build/Compile
+endef
+
+define Package/ubnt-manager/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) ./files/ubnt-manager.sh $(1)/usr/bin/ubnt-manager
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/ubnt-manager.config $(1)/etc/config/ubnt-manager
+endef
+
+$(eval $(call BuildPackage,ubnt-manager))
diff --git a/external/subpack/utils/ubnt-manager/files/ubnt-manager.config b/external/subpack/utils/ubnt-manager/files/ubnt-manager.config
new file mode 100644
index 0000000..bc29cdf
--- /dev/null
+++ b/external/subpack/utils/ubnt-manager/files/ubnt-manager.config
@@ -0,0 +1,9 @@
+config device 'sample_ap' # make sure to not use dashes in name
+ option target '192.168.1.20'
+ option username 'ubnt'
+ option password 'ubnt'
+
+#config device 'sample_ap1'
+# option target '10.31.81.21'
+# option username 'ubnt'
+# option password '...'
diff --git a/external/subpack/utils/ubnt-manager/files/ubnt-manager.sh b/external/subpack/utils/ubnt-manager/files/ubnt-manager.sh
new file mode 100755
index 0000000..c65eb23
--- /dev/null
+++ b/external/subpack/utils/ubnt-manager/files/ubnt-manager.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+. /usr/share/libubox/jshn.sh
+. /lib/functions.sh
+
+log() {
+ local msg="$1"
+ logger -t ubnt-manager -s "$msg"
+}
+
+rexec() {
+ local target="$1"
+ local username="$2"
+ local password="$3"
+ local cmd="$4"
+ raw=$(DROPBEAR_PASSWORD="$password" ssh -y $username@$target "$cmd" 2>/dev/null)
+ ssh_result=$?
+}
+
+get_json_dump() {
+ local cmd="/usr/www/status.cgi"
+ rexec $* "$cmd"
+ echo $raw
+}
+
+handle_device() {
+ local device="${1//-/_}" # replace "-" with "_"
+ config_load ubnt-manager
+ config_get target "$device" target
+ config_get username "$device" username
+ config_get password "$device" password
+ ssh_result=0
+}
+
+add_device_to_list() {
+ local device="$1"
+ device_list="$device_list $device"
+}
+
+list_devices() {
+ device_list=""
+ config_load ubnt-manager
+ config_foreach add_device_to_list device device_list
+ echo $device_list
+}
+
+usage() {
+ cat <<EOF
+usage: ubnt-manager [command]
+-j | --json Dump json info
+-t | --target Target device
+-l | --list-devices List all devices
+-h | --help Brings up this menu
+EOF
+}
+
+while [ "$1" != "" ]; do
+ case $1 in
+ -t | --target)
+ shift
+ target=$1
+ handle_device $target
+ ;;
+ -j | --json)
+ json=1
+ ;;
+ -l | --list-devices)
+ list_devices
+ ;;
+ -h | --help)
+ usage
+ ;;
+ esac
+ shift
+done
+
+if [ ! -z $json ]; then
+ get_json_dump $target $username $password | sed 's/Content-Type:\ application\/json//'
+fi
diff --git a/external/subpack/utils/uhubctl/Makefile b/external/subpack/utils/uhubctl/Makefile
new file mode 100644
index 0000000..9d0a51a
--- /dev/null
+++ b/external/subpack/utils/uhubctl/Makefile
@@ -0,0 +1,36 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=uhubctl
+PKG_VERSION:=2.4.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/mvp/uhubctl/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=391f24fd1f89cacce801df38ecc289b34c3627bc08ee69eec515af7e1a283d97
+
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING LICENSE
+
+PKG_MAINTAINER:=Steven Honson <steven@honson.id.au>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/uhubctl
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=USB hub per-port power control
+ URL:=https://github.com/mvp/uhubctl
+ DEPENDS:=+libusb-1.0
+endef
+
+define Package/uhubctl/description
+ uhubctl is a utility that allows you to control USB power on USB hubs that
+ implement per-port or ganged power switching.
+endef
+
+define Package/uhubctl/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhubctl $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,uhubctl))
diff --git a/external/subpack/utils/uledd/Makefile b/external/subpack/utils/uledd/Makefile
new file mode 100644
index 0000000..c7689fe
--- /dev/null
+++ b/external/subpack/utils/uledd/Makefile
@@ -0,0 +1,32 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=uledd
+PKG_RELEASE:=1
+
+PKG_SOURCE_URL:=https://github.com/blogic/uledd.git
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_VERSION:=b7abc41ac4e04131e5a81f0f1de4e4ffb6ae16eb
+PKG_MIRROR_HASH:=751d6336619f282aa571cbd3aa64df9b326da74fc56477a425d49cb2b0a12aea
+PKG_MAINTAINER:=John Crispin <john@phrozen.org>
+PKG_LICENSE:=LGPL-2.1-only
+
+CMAKE_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/uledd
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libubox +libubus +libblobmsg-json +libjson-c
+ TITLE:=PWM/RGB LED ubus frontend
+endef
+
+define Package/uledd/install
+ $(INSTALL_DIR) $(1)/sbin $(1)/etc/init.d
+
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/uledd $(1)/sbin/
+ $(INSTALL_BIN) ./files/uledd.init $(1)/etc/init.d/uledd
+endef
+
+$(eval $(call BuildPackage,uledd))
diff --git a/external/subpack/utils/uledd/files/uledd.init b/external/subpack/utils/uledd/files/uledd.init
new file mode 100644
index 0000000..b179267
--- /dev/null
+++ b/external/subpack/utils/uledd/files/uledd.init
@@ -0,0 +1,13 @@
+#!/bin/sh /etc/rc.common
+
+START=95
+
+USE_PROCD=1
+PROG=/sbin/uledd
+
+start_service() {
+ procd_open_instance
+ procd_set_param command "$PROG"
+ procd_set_param respawn
+ procd_close_instance
+}
diff --git a/external/subpack/utils/unrar/Makefile b/external/subpack/utils/unrar/Makefile
new file mode 100644
index 0000000..f106b75
--- /dev/null
+++ b/external/subpack/utils/unrar/Makefile
@@ -0,0 +1,104 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=unrar
+PKG_VERSION:=6.0.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=unrarsrc-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://www.rarlab.com/rar
+PKG_HASH:=1def53392d879f9e304aa6eac1339cf41f9bce1111a2f5845071665738c4aca0
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(BUILD_VARIANT)/unrar
+
+PKG_MAINTAINER:=Álvaro Fernández Rojas <noltari@gmail.com>, \
+ Ted Hess <thess@kitschensync.net>
+PKG_LICENSE:=UnRAR
+PKG_LICENSE_FILES:=license.txt
+PKG_CPE_ID:=cpe:/a:rarlab:unrar
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/uclibc++.mk
+include $(INCLUDE_DIR)/package.mk
+
+ifeq ($(CONFIG_USE_UCLIBCXX),y)
+TARGET_LDFLAGS +=-nodefaultlibs
+endif
+TARGET_CXXFLAGS +=-fno-rtti -flto
+TARGET_LDFLAGS +=$(FPIC) -Wl,--gc-sections $(if $(CONFIG_USE_GLIBC),-lpthread)
+
+define Package/unrar/Default
+ TITLE:=UnRAR
+ SUBMENU:=Compression
+ URL:=https://www.rarlab.com/
+ DEPENDS:=$(CXX_DEPENDS) +libpthread
+endef
+
+define Package/unrar
+$(call Package/unrar/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE+= (application)
+ VARIANT:=bin
+endef
+
+define Package/libunrar
+$(call Package/unrar/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+= (library)
+ VARIANT:=lib
+endef
+
+define Package/unrar/description
+ UnRAR is an application that can decompress files and archives created using
+ the RAR compression scheme
+endef
+
+define Package/libunrar/description
+ UnRAR library is a shared library that provides file extraction from RAR
+ archives
+endef
+
+ifeq ($(BUILD_VARIANT),lib)
+define Build/Compile
+ $(call Build/Compile/Default,lib)
+endef
+
+define Build/Install
+ $(call Build/Install/Default,install-lib)
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include/unrar
+ $(CP) $(PKG_BUILD_DIR)/*.hpp $(1)/usr/include/unrar/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/lib/libunrar.so $(1)/usr/lib/
+endef
+else
+define Build/Compile
+ $(call Build/Compile/Default,unrar)
+endef
+
+define Build/Install
+ $(call Build/Install/Default,install-unrar)
+endef
+endif
+
+define Package/unrar/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/bin/unrar $(1)/usr/bin/
+endef
+
+define Package/libunrar/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/lib/libunrar.so $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,unrar))
+$(eval $(call BuildPackage,libunrar))
diff --git a/external/subpack/utils/unrar/patches/100-makefile_fixes.patch b/external/subpack/utils/unrar/patches/100-makefile_fixes.patch
new file mode 100644
index 0000000..19ec619
--- /dev/null
+++ b/external/subpack/utils/unrar/patches/100-makefile_fixes.patch
@@ -0,0 +1,33 @@
+--- a/makefile
++++ b/makefile
+@@ -2,14 +2,14 @@
+ # Makefile for UNIX - unrar
+
+ # Linux using GCC
+-CXX=c++
+-CXXFLAGS=-O2 -Wno-logical-op-parentheses -Wno-switch -Wno-dangling-else
+-LIBFLAGS=-fPIC
++CXX?=c++
++CXXFLAGS?=-O2 -Wno-logical-op-parentheses -Wno-switch -Wno-dangling-else
++LIBFLAGS?=-fPIC
+ DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DRAR_SMP
+-STRIP=strip
+-AR=ar
+-LDFLAGS=-pthread
+-DESTDIR=/usr
++STRIP?=strip
++AR?=ar
++LDFLAGS?=-lpthread
++DESTDIR?=/usr
+
+ # Linux using LCC
+ #CXX=lcc
+@@ -167,7 +167,7 @@ uninstall-unrar:
+ rm -f $(DESTDIR)/bin/unrar
+
+ install-lib:
+- install libunrar.so $(DESTDIR)/lib
++ install -D libunrar.so $(DESTDIR)/lib/libunrar.so
+ install libunrar.a $(DESTDIR)/lib
+
+ uninstall-lib:
diff --git a/external/subpack/utils/unzip/Makefile b/external/subpack/utils/unzip/Makefile
new file mode 100644
index 0000000..255dfc7
--- /dev/null
+++ b/external/subpack/utils/unzip/Makefile
@@ -0,0 +1,75 @@
+#
+# Copyright (C) 2006-2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=unzip
+PKG_REV:=60
+PKG_VERSION:=6.0
+PKG_RELEASE:=8
+
+PKG_SOURCE:=$(PKG_NAME)$(PKG_REV).tar.gz
+PKG_SOURCE_URL:=@SF/infozip
+PKG_HASH:=036d96991646d0449ed0aa952e4fbe21b476ce994abc276e49d30e686708bd37
+PKG_MAINTAINER:=Álvaro Fernández Rojas <noltari@gmail.com>
+
+PKG_LICENSE:=BSD-4-Clause
+PKG_LICENSE_FILES:=LICENSE
+PKG_CPE_ID:=cpe:/a:info-zip:unzip
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/unzip$(PKG_REV)
+PKG_CHECK_FORMAT_SECURITY:=0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/unzip
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=
+ TITLE:=De-archiver for .zip files
+ URL:=http://infozip.sourceforge.net/UnZip.html
+ SUBMENU:=Compression
+endef
+
+define Package/unzip/description
+ InfoZIP's unzip program. With the exception of multi-volume archives
+ (ie, .ZIP files that are split across several disks using PKZIP's /& option),
+ this can handle any file produced either by PKZIP, or the corresponding
+ InfoZIP zip program.
+endef
+
+define Build/Configure
+endef
+
+TARGET_CFLAGS += \
+ -DNO_LCHMOD \
+ -DLARGE_FILE_SUPPORT \
+ -DUNICODE_WCHAR \
+ -DUNICODE_SUPPORT \
+ -DUTF8_MAYBE_NATIVE \
+ -DZIP64_SUPPORT
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) -f unix/Makefile unzips \
+ $(TARGET_CONFIGURE_OPTS) \
+ prefix="$(PKG_INSTALL_DIR)/usr" \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ CF="$(TARGET_CFLAGS) -O $(TARGET_CPPFLAGS) -I. -DUNIX" \
+ CC="$(TARGET_CC)" \
+ LD="$(TARGET_CC) $(TARGET_LDFLAGS)" \
+ install
+endef
+
+define Package/unzip/install
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(INSTALL_BIN) \
+ $(PKG_INSTALL_DIR)/usr/bin/{funzip,unzip,unzipsfx,zipgrep} \
+ $(1)/usr/bin/
+ $(LN) unzip $(1)/usr/bin/zipinfo
+endef
+
+$(eval $(call BuildPackage,unzip))
diff --git a/external/subpack/utils/unzip/patches/001-CVE-2014-8139-crc-overflow.patch b/external/subpack/utils/unzip/patches/001-CVE-2014-8139-crc-overflow.patch
new file mode 100644
index 0000000..5cae41f
--- /dev/null
+++ b/external/subpack/utils/unzip/patches/001-CVE-2014-8139-crc-overflow.patch
@@ -0,0 +1,49 @@
+--- a/extract.c
++++ b/extract.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
++ Copyright (c) 1990-2014 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2009-Jan-02 or later
+ (the contents of which are also included in unzip.h) for terms of use.
+@@ -298,6 +298,8 @@ char ZCONST Far TruncNTSD[] =
+ #ifndef SFX
+ static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \
+ EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n";
++ static ZCONST char Far TooSmallEBlength[] = "bad extra-field entry:\n \
++ EF block length (%u bytes) invalid (< %d)\n";
+ static ZCONST char Far InvalidComprDataEAs[] =
+ " invalid compressed data for EAs\n";
+ # if (defined(WIN32) && defined(NTSD_EAS))
+@@ -2023,7 +2025,8 @@ static int TestExtraField(__G__ ef, ef_l
+ ebID = makeword(ef);
+ ebLen = (unsigned)makeword(ef+EB_LEN);
+
+- if (ebLen > (ef_len - EB_HEADSIZE)) {
++ if (ebLen > (ef_len - EB_HEADSIZE))
++ {
+ /* Discovered some extra field inconsistency! */
+ if (uO.qflag)
+ Info(slide, 1, ((char *)slide, "%-22s ",
+@@ -2158,11 +2161,19 @@ static int TestExtraField(__G__ ef, ef_l
+ }
+ break;
+ case EF_PKVMS:
+- if (makelong(ef+EB_HEADSIZE) !=
++ if (ebLen < 4)
++ {
++ Info(slide, 1,
++ ((char *)slide, LoadFarString(TooSmallEBlength),
++ ebLen, 4));
++ }
++ else if (makelong(ef+EB_HEADSIZE) !=
+ crc32(CRCVAL_INITIAL, ef+(EB_HEADSIZE+4),
+ (extent)(ebLen-4)))
++ {
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(BadCRC_EAs)));
++ }
+ break;
+ case EF_PKW32:
+ case EF_PKUNIX:
diff --git a/external/subpack/utils/unzip/patches/002-CVE-2014-8140-test-compr-eb.patch b/external/subpack/utils/unzip/patches/002-CVE-2014-8140-test-compr-eb.patch
new file mode 100644
index 0000000..fd4ef00
--- /dev/null
+++ b/external/subpack/utils/unzip/patches/002-CVE-2014-8140-test-compr-eb.patch
@@ -0,0 +1,23 @@
+--- a/extract.c
++++ b/extract.c
+@@ -2232,10 +2232,17 @@ static int test_compr_eb(__G__ eb, eb_si
+ if (compr_offset < 4) /* field is not compressed: */
+ return PK_OK; /* do nothing and signal OK */
+
++ /* Return no/bad-data error status if any problem is found:
++ * 1. eb_size is too small to hold the uncompressed size
++ * (eb_ucsize). (Else extract eb_ucsize.)
++ * 2. eb_ucsize is zero (invalid). 2014-12-04 SMS.
++ * 3. eb_ucsize is positive, but eb_size is too small to hold
++ * the compressed data header.
++ */
+ if ((eb_size < (EB_UCSIZE_P + 4)) ||
+- ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&
+- eb_size <= (compr_offset + EB_CMPRHEADLEN)))
+- return IZ_EF_TRUNC; /* no compressed data! */
++ ((eb_ucsize = makelong( eb+ (EB_HEADSIZE+ EB_UCSIZE_P))) == 0L) ||
++ ((eb_ucsize > 0L) && (eb_size <= (compr_offset + EB_CMPRHEADLEN))))
++ return IZ_EF_TRUNC; /* no/bad compressed data! */
+
+ if (
+ #ifdef INT_16BIT
diff --git a/external/subpack/utils/unzip/patches/003-CVE-2014-8141-getzip64data.patch b/external/subpack/utils/unzip/patches/003-CVE-2014-8141-getzip64data.patch
new file mode 100644
index 0000000..ca52e19
--- /dev/null
+++ b/external/subpack/utils/unzip/patches/003-CVE-2014-8141-getzip64data.patch
@@ -0,0 +1,133 @@
+--- a/fileio.c
++++ b/fileio.c
+@@ -176,6 +176,8 @@ static ZCONST char Far FilenameTooLongTr
+ #endif
+ static ZCONST char Far ExtraFieldTooLong[] =
+ "warning: extra field too long (%d). Ignoring...\n";
++static ZCONST char Far ExtraFieldCorrupt[] =
++ "warning: extra field (type: 0x%04x) corrupt. Continuing...\n";
+
+ #ifdef WINDLL
+ static ZCONST char Far DiskFullQuery[] =
+@@ -2295,7 +2297,12 @@ int do_string(__G__ length, option) /*
+ if (readbuf(__G__ (char *)G.extra_field, length) == 0)
+ return PK_EOF;
+ /* Looks like here is where extra fields are read */
+- getZip64Data(__G__ G.extra_field, length);
++ if (getZip64Data(__G__ G.extra_field, length) != PK_COOL)
++ {
++ Info(slide, 0x401, ((char *)slide,
++ LoadFarString( ExtraFieldCorrupt), EF_PKSZ64));
++ error = PK_WARN;
++ }
+ #ifdef UNICODE_SUPPORT
+ G.unipath_filename = NULL;
+ if (G.UzO.U_flag < 2) {
+--- a/process.c
++++ b/process.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
++ Copyright (c) 1990-2014 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2009-Jan-02 or later
+ (the contents of which are also included in unzip.h) for terms of use.
+@@ -1888,48 +1888,82 @@ int getZip64Data(__G__ ef_buf, ef_len)
+ and a 4-byte version of disk start number.
+ Sets both local header and central header fields. Not terribly clever,
+ but it means that this procedure is only called in one place.
++
++ 2014-12-05 SMS.
++ Added checks to ensure that enough data are available before calling
++ makeint64() or makelong(). Replaced various sizeof() values with
++ simple ("4" or "8") constants. (The Zip64 structures do not depend
++ on our variable sizes.) Error handling is crude, but we should now
++ stay within the buffer.
+ ---------------------------------------------------------------------------*/
+
++#define Z64FLGS 0xffff
++#define Z64FLGL 0xffffffff
++
+ if (ef_len == 0 || ef_buf == NULL)
+ return PK_COOL;
+
+ Trace((stderr,"\ngetZip64Data: scanning extra field of length %u\n",
+ ef_len));
+
+- while (ef_len >= EB_HEADSIZE) {
++ while (ef_len >= EB_HEADSIZE)
++ {
+ eb_id = makeword(EB_ID + ef_buf);
+ eb_len = makeword(EB_LEN + ef_buf);
+
+- if (eb_len > (ef_len - EB_HEADSIZE)) {
+- /* discovered some extra field inconsistency! */
++ if (eb_len > (ef_len - EB_HEADSIZE))
++ {
++ /* Extra block length exceeds remaining extra field length. */
+ Trace((stderr,
+ "getZip64Data: block length %u > rest ef_size %u\n", eb_len,
+ ef_len - EB_HEADSIZE));
+ break;
+ }
+- if (eb_id == EF_PKSZ64) {
+-
++ if (eb_id == EF_PKSZ64)
++ {
+ int offset = EB_HEADSIZE;
+
+- if (G.crec.ucsize == 0xffffffff || G.lrec.ucsize == 0xffffffff){
+- G.lrec.ucsize = G.crec.ucsize = makeint64(offset + ef_buf);
+- offset += sizeof(G.crec.ucsize);
++ if ((G.crec.ucsize == Z64FLGL) || (G.lrec.ucsize == Z64FLGL))
++ {
++ if (offset+ 8 > ef_len)
++ return PK_ERR;
++
++ G.crec.ucsize = G.lrec.ucsize = makeint64(offset + ef_buf);
++ offset += 8;
+ }
+- if (G.crec.csize == 0xffffffff || G.lrec.csize == 0xffffffff){
+- G.csize = G.lrec.csize = G.crec.csize = makeint64(offset + ef_buf);
+- offset += sizeof(G.crec.csize);
++
++ if ((G.crec.csize == Z64FLGL) || (G.lrec.csize == Z64FLGL))
++ {
++ if (offset+ 8 > ef_len)
++ return PK_ERR;
++
++ G.csize = G.crec.csize = G.lrec.csize = makeint64(offset + ef_buf);
++ offset += 8;
+ }
+- if (G.crec.relative_offset_local_header == 0xffffffff){
++
++ if (G.crec.relative_offset_local_header == Z64FLGL)
++ {
++ if (offset+ 8 > ef_len)
++ return PK_ERR;
++
+ G.crec.relative_offset_local_header = makeint64(offset + ef_buf);
+- offset += sizeof(G.crec.relative_offset_local_header);
++ offset += 8;
+ }
+- if (G.crec.disk_number_start == 0xffff){
++
++ if (G.crec.disk_number_start == Z64FLGS)
++ {
++ if (offset+ 4 > ef_len)
++ return PK_ERR;
++
+ G.crec.disk_number_start = (zuvl_t)makelong(offset + ef_buf);
+- offset += sizeof(G.crec.disk_number_start);
++ offset += 4;
+ }
++#if 0
++ break; /* Expect only one EF_PKSZ64 block. */
++#endif /* 0 */
+ }
+
+- /* Skip this extra field block */
++ /* Skip this extra field block. */
+ ef_buf += (eb_len + EB_HEADSIZE);
+ ef_len -= (eb_len + EB_HEADSIZE);
+ }
diff --git a/external/subpack/utils/unzip/patches/004-CVE-2014-9636-test-compr-eb.patch b/external/subpack/utils/unzip/patches/004-CVE-2014-9636-test-compr-eb.patch
new file mode 100644
index 0000000..3bba996
--- /dev/null
+++ b/external/subpack/utils/unzip/patches/004-CVE-2014-9636-test-compr-eb.patch
@@ -0,0 +1,25 @@
+--- a/extract.c
++++ b/extract.c
+@@ -2228,6 +2228,7 @@ static int test_compr_eb(__G__ eb, eb_si
+ ulg eb_ucsize;
+ uch *eb_ucptr;
+ int r;
++ ush eb_compr_method;
+
+ if (compr_offset < 4) /* field is not compressed: */
+ return PK_OK; /* do nothing and signal OK */
+@@ -2244,6 +2245,14 @@ static int test_compr_eb(__G__ eb, eb_si
+ ((eb_ucsize > 0L) && (eb_size <= (compr_offset + EB_CMPRHEADLEN))))
+ return IZ_EF_TRUNC; /* no/bad compressed data! */
+
++ /* 2014-11-03 Michal Zalewski, SMS.
++ * For STORE method, compressed and uncompressed sizes must agree.
++ * http://www.info-zip.org/phpBB3/viewtopic.php?f=7&t=450
++ */
++ eb_compr_method = makeword( eb + (EB_HEADSIZE + compr_offset));
++ if ((eb_compr_method == STORED) && (eb_size - compr_offset != eb_ucsize))
++ return PK_ERR;
++
+ if (
+ #ifdef INT_16BIT
+ (((ulg)(extent)eb_ucsize) != eb_ucsize) ||
diff --git a/external/subpack/utils/unzip/patches/005-CVE-2015-7696-heap-overflow.patch b/external/subpack/utils/unzip/patches/005-CVE-2015-7696-heap-overflow.patch
new file mode 100644
index 0000000..df758a1
--- /dev/null
+++ b/external/subpack/utils/unzip/patches/005-CVE-2015-7696-heap-overflow.patch
@@ -0,0 +1,21 @@
+--- a/crypt.c
++++ b/crypt.c
+@@ -465,7 +465,17 @@ int decrypt(__G__ passwrd)
+ GLOBAL(pInfo->encrypted) = FALSE;
+ defer_leftover_input(__G);
+ for (n = 0; n < RAND_HEAD_LEN; n++) {
+- b = NEXTBYTE;
++ /* 2012-11-23 SMS. (OUSPG report.)
++ * Quit early if compressed size < HEAD_LEN. The resulting
++ * error message ("unable to get password") could be improved,
++ * but it's better than trying to read nonexistent data, and
++ * then continuing with a negative G.csize. (See
++ * fileio.c:readbyte()).
++ */
++ if ((b = NEXTBYTE) == (ush)EOF)
++ {
++ return PK_ERR;
++ }
+ h[n] = (uch)b;
+ Trace((stdout, " (%02x)", h[n]));
+ }
diff --git a/external/subpack/utils/unzip/patches/006-CVE-2015-7697-infinite-loop.patch b/external/subpack/utils/unzip/patches/006-CVE-2015-7697-infinite-loop.patch
new file mode 100644
index 0000000..a8376b2
--- /dev/null
+++ b/external/subpack/utils/unzip/patches/006-CVE-2015-7697-infinite-loop.patch
@@ -0,0 +1,15 @@
+--- a/extract.c
++++ b/extract.c
+@@ -2728,6 +2728,12 @@ __GDEF
+ int repeated_buf_err;
+ bz_stream bstrm;
+
++ if (G.incnt <= 0 && G.csize <= 0L) {
++ /* avoid an infinite loop */
++ Trace((stderr, "UZbunzip2() got empty input\n"));
++ return 2;
++ }
++
+ #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+ if (G.redirect_slide)
+ wsize = G.redirect_size, redirSlide = G.redirect_buffer;
diff --git a/external/subpack/utils/unzip/patches/007-integer-underflow-csiz_decrypted.patch b/external/subpack/utils/unzip/patches/007-integer-underflow-csiz_decrypted.patch
new file mode 100644
index 0000000..738ea52
--- /dev/null
+++ b/external/subpack/utils/unzip/patches/007-integer-underflow-csiz_decrypted.patch
@@ -0,0 +1,21 @@
+--- a/extract.c
++++ b/extract.c
+@@ -1257,8 +1257,17 @@ static int extract_or_test_entrylist(__G
+ if (G.lrec.compression_method == STORED) {
+ zusz_t csiz_decrypted = G.lrec.csize;
+
+- if (G.pInfo->encrypted)
++ if (G.pInfo->encrypted) {
++ if (csiz_decrypted <= 12) {
++ /* handle the error now to prevent unsigned overflow */
++ Info(slide, 0x401, ((char *)slide,
++ LoadFarStringSmall(ErrUnzipNoFile),
++ LoadFarString(InvalidComprData),
++ LoadFarStringSmall2(Inflate)));
++ return PK_ERR;
++ }
+ csiz_decrypted -= 12;
++ }
+ if (G.lrec.ucsize != csiz_decrypted) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarStringSmall2(WrnStorUCSizCSizDiff),
diff --git a/external/subpack/utils/unzip/patches/008-cve-2014-9913-unzip-buffer-overflow.patch b/external/subpack/utils/unzip/patches/008-cve-2014-9913-unzip-buffer-overflow.patch
new file mode 100644
index 0000000..018d014
--- /dev/null
+++ b/external/subpack/utils/unzip/patches/008-cve-2014-9913-unzip-buffer-overflow.patch
@@ -0,0 +1,29 @@
+From: "Steven M. Schweda" <sms@antinode.info>
+Subject: Fix CVE-2014-9913, buffer overflow in unzip
+Bug: https://sourceforge.net/p/infozip/bugs/27/
+Bug-Debian: https://bugs.debian.org/847485
+Bug-Ubuntu: https://launchpad.net/bugs/387350
+X-Debian-version: 6.0-21
+
+--- a/list.c
++++ b/list.c
+@@ -339,7 +339,18 @@ int list_files(__G) /* return PK-type
+ G.crec.compression_method == ENHDEFLATED) {
+ methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];
+ } else if (methnum >= NUM_METHODS) {
+- sprintf(&methbuf[4], "%03u", G.crec.compression_method);
++ /* 2013-02-26 SMS.
++ * http://sourceforge.net/p/infozip/bugs/27/ CVE-2014-9913.
++ * Unexpectedly large compression methods overflow
++ * &methbuf[]. Use the old, three-digit decimal format
++ * for values which fit. Otherwise, sacrifice the
++ * colon, and use four-digit hexadecimal.
++ */
++ if (G.crec.compression_method <= 999) {
++ sprintf( &methbuf[ 4], "%03u", G.crec.compression_method);
++ } else {
++ sprintf( &methbuf[ 3], "%04X", G.crec.compression_method);
++ }
+ }
+
+ #if 0 /* GRR/Euro: add this? */
diff --git a/external/subpack/utils/unzip/patches/009-cve-2016-9844-zipinfo-buffer-overflow.patch b/external/subpack/utils/unzip/patches/009-cve-2016-9844-zipinfo-buffer-overflow.patch
new file mode 100644
index 0000000..4d75857
--- /dev/null
+++ b/external/subpack/utils/unzip/patches/009-cve-2016-9844-zipinfo-buffer-overflow.patch
@@ -0,0 +1,28 @@
+From: "Steven M. Schweda" <sms@antinode.info>
+Subject: Fix CVE-2016-9844, buffer overflow in zipinfo
+Bug-Debian: https://bugs.debian.org/847486
+Bug-Ubuntu: https://launchpad.net/bugs/1643750
+X-Debian-version: 6.0-21
+
+--- a/zipinfo.c
++++ b/zipinfo.c
+@@ -1921,7 +1921,18 @@ static int zi_short(__G) /* return PK-
+ ush dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
+ methbuf[3] = dtype[dnum];
+ } else if (methnum >= NUM_METHODS) { /* unknown */
+- sprintf(&methbuf[1], "%03u", G.crec.compression_method);
++ /* 2016-12-05 SMS.
++ * https://launchpad.net/bugs/1643750
++ * Unexpectedly large compression methods overflow
++ * &methbuf[]. Use the old, three-digit decimal format
++ * for values which fit. Otherwise, sacrifice the "u",
++ * and use four-digit hexadecimal.
++ */
++ if (G.crec.compression_method <= 999) {
++ sprintf( &methbuf[ 1], "%03u", G.crec.compression_method);
++ } else {
++ sprintf( &methbuf[ 0], "%04X", G.crec.compression_method);
++ }
+ }
+
+ for (k = 0; k < 15; ++k)
diff --git a/external/subpack/utils/unzip/patches/010-remove-build-date.patch b/external/subpack/utils/unzip/patches/010-remove-build-date.patch
new file mode 100644
index 0000000..9a33444
--- /dev/null
+++ b/external/subpack/utils/unzip/patches/010-remove-build-date.patch
@@ -0,0 +1,17 @@
+From: Jérémy Bobbio <lunar@debian.org>
+Subject: Remove build date
+Bug-Debian: https://bugs.debian.org/782851
+ In order to make unzip build reproducibly, we remove the
+ (already optional) build date from the binary.
+
+--- a/unix/unix.c
++++ b/unix/unix.c
+@@ -1705,7 +1705,7 @@ void version(__G)
+ #endif /* Sun */
+ #endif /* SGI */
+
+-#ifdef __DATE__
++#if 0
+ " on ", __DATE__
+ #else
+ "", ""
diff --git a/external/subpack/utils/unzip/patches/011-CVE-2018-1000035-overflow-password-protect.patch b/external/subpack/utils/unzip/patches/011-CVE-2018-1000035-overflow-password-protect.patch
new file mode 100644
index 0000000..0c56ace
--- /dev/null
+++ b/external/subpack/utils/unzip/patches/011-CVE-2018-1000035-overflow-password-protect.patch
@@ -0,0 +1,34 @@
+--- a/fileio.c
++++ b/fileio.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
++ Copyright (c) 1990-2017 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2009-Jan-02 or later
+ (the contents of which are also included in unzip.h) for terms of use.
+@@ -1582,6 +1582,8 @@ int UZ_EXP UzpPassword (pG, rcnt, pwbuf,
+ int r = IZ_PW_ENTERED;
+ char *m;
+ char *prompt;
++ char *ep;
++ char *zp;
+
+ #ifndef REENTRANT
+ /* tell picky compilers to shut up about "unused variable" warnings */
+@@ -1590,9 +1592,12 @@ int UZ_EXP UzpPassword (pG, rcnt, pwbuf,
+
+ if (*rcnt == 0) { /* First call for current entry */
+ *rcnt = 2;
+- if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {
+- sprintf(prompt, LoadFarString(PasswPrompt),
+- FnFilter1(zfn), FnFilter2(efn));
++ zp = FnFilter1( zfn);
++ ep = FnFilter2( efn);
++ prompt = (char *)malloc( /* Slightly too long (2* "%s"). */
++ sizeof( PasswPrompt)+ strlen( zp)+ strlen( ep));
++ if (prompt != (char *)NULL) {
++ sprintf(prompt, LoadFarString(PasswPrompt), zp, ep);
+ m = prompt;
+ } else
+ m = (char *)LoadFarString(PasswPrompt2);
diff --git a/external/subpack/utils/usbmuxd/Makefile b/external/subpack/utils/usbmuxd/Makefile
new file mode 100644
index 0000000..32fbc68
--- /dev/null
+++ b/external/subpack/utils/usbmuxd/Makefile
@@ -0,0 +1,59 @@
+#
+# Copyright (C) 2012-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=usbmuxd
+PKG_VERSION:=1.1.1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://www.libimobiledevice.org/downloads
+PKG_HASH:=c0ec9700172bf635ccb5bed98daae607d2925c2bc3597f25706ecd9dfbfd2d9e
+
+PKG_MAINTAINER:=Rosen Penev <rosenp@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING.GPLv2
+PKG_CPE_ID:=cpe:/a:libimobiledevice:usbmuxd
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/usbmuxd
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=libimobiledevice
+ TITLE:=USB multiplexing daemon
+ URL:=https://www.libimobiledevice.org/
+ DEPENDS:=+librt +libusb-1.0 +libusbmuxd +libopenssl +libimobiledevice
+endef
+
+define Package/usbmuxd/description
+ This daemon is in charge of multiplexing connections over USB to an iPhone or
+ iPod touch. To users, it means you can sync your music, contacts, photos, etc.
+ over USB. To developers, it means you can connect to any listening localhost
+ socket on the device. usbmuxd is not used for tethering data transfer, which
+ uses a dedicated USB interface as a virtual network device.
+endef
+
+define Package/usbmuxd/conffiles
+/etc/lockdown
+/etc/lockdown/SystemConfiguration.plist
+endef
+
+CONFIGURE_ARGS += --with-systemd
+
+define Package/usbmuxd/install
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/usbmuxd.init $(1)/etc/init.d/usbmuxd
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/usbmuxd $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,usbmuxd))
diff --git a/external/subpack/utils/usbmuxd/files/usbmuxd.init b/external/subpack/utils/usbmuxd/files/usbmuxd.init
new file mode 100644
index 0000000..9ea9ef5
--- /dev/null
+++ b/external/subpack/utils/usbmuxd/files/usbmuxd.init
@@ -0,0 +1,17 @@
+#!/bin/sh /etc/rc.common
+
+START=94
+
+USE_PROCD=1
+PROG=/usr/sbin/usbmuxd
+
+start_service() {
+ procd_open_instance
+ procd_set_param command $PROG --systemd
+ procd_set_param stderr 1
+ procd_close_instance
+}
+
+reload_service() {
+ procd_send_signal $PROG
+}
diff --git a/external/subpack/utils/usbmuxd/patches/010-config.patch b/external/subpack/utils/usbmuxd/patches/010-config.patch
new file mode 100644
index 0000000..31d9abc
--- /dev/null
+++ b/external/subpack/utils/usbmuxd/patches/010-config.patch
@@ -0,0 +1,11 @@
+--- a/src/conf.c
++++ b/src/conf.c
+@@ -126,7 +126,7 @@ const char *config_get_config_dir()
+ #ifdef __APPLE__
+ base_config_dir = strdup("/var/db");
+ #else
+- base_config_dir = strdup("/var/lib");
++ base_config_dir = strdup("/etc");
+ #endif
+ #endif
+ __config_dir = string_concat(base_config_dir, DIR_SEP_S, CONFIG_DIR, NULL);
diff --git a/external/subpack/utils/usbutils/Makefile b/external/subpack/utils/usbutils/Makefile
new file mode 100644
index 0000000..a8fd949
--- /dev/null
+++ b/external/subpack/utils/usbutils/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2007-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=usbutils
+PKG_VERSION:=017
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/linux/utils/usb/usbutils
+PKG_HASH:=a6a25ffdcf9103e38d7a44732aca17073f4e602b92e4ae55625231a82702e05b
+
+PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/usbutils
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libusb-1.0 +libudev +librt +libpthread +usbids
+ TITLE:=USB devices listing utilities
+ URL:=http://www.linux-usb.org/
+endef
+
+CONFIGURE_ARGS+= \
+ --datadir=/usr/share/hwdata
+
+define Package/usbutils/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lsusb $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/usbreset $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,usbutils))
diff --git a/external/subpack/utils/uvcdynctrl/Makefile b/external/subpack/utils/uvcdynctrl/Makefile
new file mode 100644
index 0000000..2a735dc
--- /dev/null
+++ b/external/subpack/utils/uvcdynctrl/Makefile
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=uvcdynctrl
+PKG_VERSION:=0.2.5
+PKG_RELEASE:=3
+
+PKG_SOURCE:=libwebcam-src-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/libwebcam
+PKG_HASH:=3ca5199c7b8398b655a7c38e3ad4191bb053b1486503287f20d30d141bda9d41
+PKG_BUILD_DIR:=$(BUILD_DIR)/libwebcam-$(PKG_VERSION)
+
+PKG_MAINTAINER:=Roger D <rogerdammit@gmail.com>
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=uvcdynctrl/COPYING
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/uvcdynctrl
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libxml2 $(ICONV_DEPENDS)
+ TITLE:=Manage dynamic controls in uvcvideo
+ URL:=https://sourceforge.net/projects/libwebcam/
+ MENU:=1
+endef
+
+define Package/uvcdynctrl/description
+ The webcam-tools package contains the following two components:
+ - libwebcam: Webcam Library (LGPL)
+ - uvcdynctrl: Manage dynamic controls in uvcvideo (GPL)
+endef
+
+define Package/uvcdynctrl/install
+ $(INSTALL_DIR) $(1)/usr/{bin,share}
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/uvcdynctrl* $(1)/usr/bin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/uvcdynctrl/ $(1)/usr/share/
+endef
+
+$(eval $(call BuildPackage,uvcdynctrl))
diff --git a/external/subpack/utils/uvcdynctrl/patches/010-iconv.patch b/external/subpack/utils/uvcdynctrl/patches/010-iconv.patch
new file mode 100644
index 0000000..5f0e535
--- /dev/null
+++ b/external/subpack/utils/uvcdynctrl/patches/010-iconv.patch
@@ -0,0 +1,11 @@
+--- a/uvcdynctrl/CMakeLists.txt
++++ b/uvcdynctrl/CMakeLists.txt
+@@ -77,7 +77,7 @@ include_directories (../common/include)
+ include_directories (${CMAKE_CURRENT_BINARY_DIR})
+ link_directories (${LIBWEBCAM_BINARY_DIR}/webcam)
+
+-target_link_libraries (uvcdynctrl webcam)
++target_link_libraries (uvcdynctrl webcam iconv)
+
+ # Compiler flags
+ set_target_properties (uvcdynctrl PROPERTIES
diff --git a/external/subpack/utils/uvcdynctrl/patches/020-static.patch b/external/subpack/utils/uvcdynctrl/patches/020-static.patch
new file mode 100644
index 0000000..78304ca
--- /dev/null
+++ b/external/subpack/utils/uvcdynctrl/patches/020-static.patch
@@ -0,0 +1,11 @@
+--- a/uvcdynctrl/CMakeLists.txt
++++ b/uvcdynctrl/CMakeLists.txt
+@@ -77,7 +77,7 @@ include_directories (../common/include)
+ include_directories (${CMAKE_CURRENT_BINARY_DIR})
+ link_directories (${LIBWEBCAM_BINARY_DIR}/webcam)
+
+-target_link_libraries (uvcdynctrl webcam iconv)
++target_link_libraries (uvcdynctrl webcam_static iconv)
+
+ # Compiler flags
+ set_target_properties (uvcdynctrl PROPERTIES
diff --git a/external/subpack/utils/vim/Makefile b/external/subpack/utils/vim/Makefile
new file mode 100644
index 0000000..125acbf
--- /dev/null
+++ b/external/subpack/utils/vim/Makefile
@@ -0,0 +1,253 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=vim
+PKG_VERSION:=9.0
+PKG_RELEASE:=1
+VIMVER:=90
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://ftp.vim.org/pub/vim/unix
+PKG_HASH:=a6456bc154999d83d0c20d968ac7ba6e7df0d02f3cb6427fb248660bacfb336e
+PKG_MAINTAINER:=Marko Ratkaj <markoratkaj@gmail.com>
+PKG_LICENSE:=Vim
+PKG_LICENSE_FILES:=LICENSE
+PKG_CPE_ID:=cpe:/a:vim:vim
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)$(VIMVER)
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/host-build.mk
+
+define Package/vim/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libncurses
+ TITLE:=Vi IMproved - enhanced vi editor
+ URL:=http://www.vim.org/
+ SUBMENU:=Editors
+endef
+
+define Package/vim
+ $(call Package/vim/Default)
+ TITLE+= (Tiny)
+endef
+
+define Package/vim-full
+ $(call Package/vim/Default)
+ TITLE+= (Normal)
+ PROVIDES:=vim
+ CONFLICTS:=vim
+endef
+
+
+define Package/vim-fuller
+ $(call Package/vim/Default)
+ TITLE+= (Big)
+ PROVIDES:=vim vim-full
+ CONFLICTS:=vim vim-full
+endef
+
+define Package/vim-runtime
+ $(call Package/vim/Default)
+ TITLE+= (runtime files)
+endef
+
+define Package/vim-help
+ $(call Package/vim/Default)
+ TITLE+= (help files)
+endef
+
+define Package/xxd
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=make a hexdump or do the reverse
+ URL:=http://www.vim.org/
+endef
+
+define Package/vim-full/conffiles
+/usr/share/vim/vimrc
+/root/.vimrc
+endef
+
+define Package/vim/conffiles
+/usr/share/vim/vimrc
+/root/.vimrc
+endef
+
+define Package/vim/description
+ Vim is an almost compatible version of the UNIX editor Vi.
+ (Tiny build)
+endef
+
+define Package/vim-full/description
+ Vim is an almost compatible version of the UNIX editor Vi.
+ (Normal build)
+endef
+
+
+define Package/vim-fuller/description
+ Vim is an almost compatible version of the UNIX editor Vi.
+ (Big build)
+endef
+
+define Package/vim-runtime/description
+ Vim is an almost compatible version of the UNIX editor Vi.
+ (Runtime files)
+endef
+
+define Package/vim-help/description
+ Vim is an almost compatible version of the UNIX editor Vi.
+ (Help files)
+endef
+
+define Package/xxd/description
+ xxd creates a hex dump of a given file or standard input, it can also convert
+ a hex dump back to its original binary form.
+endef
+
+CONFIGURE_ARGS += \
+ --disable-gui \
+ --disable-gtktest \
+ --disable-xim \
+ --without-x \
+ --disable-netbeans \
+ --disable-cscope \
+ --disable-gpm \
+ --disable-acl \
+ --disable-libsodium \
+ --disable-selinux \
+ --with-tlib=ncurses \
+ --with-compiledby="non-existent-hostname-compiled"
+
+CONFIGURE_VARS += \
+ ac_cv_header_elf_h=no \
+ vim_cv_getcwd_broken=no \
+ vim_cv_memmove_handles_overlap=yes \
+ vim_cv_stat_ignores_slash=yes \
+ vim_cv_tgetent=zero \
+ vim_cv_terminfo=yes \
+ vim_cv_toupper_broken=no \
+ vim_cv_tty_group=root \
+ vim_cv_tty_mode=0620
+
+ifneq ($(HOST_OS),Linux)
+ TARGET_PATH_PKG:=$(CURDIR)/scripts:$(TARGET_PATH_PKG)
+endif
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(MAKE) -C $(PKG_BUILD_DIR)/src autoconf
+endef
+
+ifneq ($(CONFIG_PACKAGE_vim),)
+define Build/Compile/vim
+ $(call Build/Configure/Default, \
+ --with-features=tiny \
+ )
+ +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" all
+ $(CP) $(PKG_BUILD_DIR)/src/$(PKG_NAME) $(PKG_BUILD_DIR)/vim_tiny
+endef
+endif
+
+ifneq ($(CONFIG_PACKAGE_vim-full),)
+define Build/Compile/vim-full
+ $(call Build/Configure/Default, \
+ --with-features=normal \
+ )
+ +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" all
+ $(CP) $(PKG_BUILD_DIR)/src/$(PKG_NAME) $(PKG_BUILD_DIR)/vim_normal
+endef
+endif
+
+ifneq ($(CONFIG_PACKAGE_vim-fuller),)
+define Build/Compile/vim-fuller
+ $(call Build/Configure/Default, \
+ --with-features=big \
+ )
+ +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" all
+ $(CP) $(PKG_BUILD_DIR)/src/$(PKG_NAME) $(PKG_BUILD_DIR)/vim_big
+endef
+endif
+
+
+
+ifneq ($(CONFIG_PACKAGE_xxd),)
+define Build/Compile/xxd
+ +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" all
+endef
+endif
+
+define Build/Compile/vim-runtime
+ $(MAKE) -C $(PKG_BUILD_DIR)/src DESTDIR="$(PKG_INSTALL_DIR)" installrtbase
+ (cd $(PKG_INSTALL_DIR) && tar -cf $(PKG_BUILD_DIR)/docs.tar ./usr/share/vim/vim$(VIMVER)/doc)
+ rm -rf $(PKG_INSTALL_DIR)/usr/share/vim/vim$(VIMVER)/doc
+ rm -rf $(PKG_INSTALL_DIR)/usr/man
+endef
+
+define Build/Compile
+$(call Build/Compile/vim)
+$(call Build/Compile/vim-full)
+$(call Build/Compile/vim-fuller)
+$(call Build/Compile/vim-runtime)
+$(call Build/Compile/xxd)
+endef
+
+define Package/vim/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/vim_tiny $(1)/usr/bin/vim
+ $(INSTALL_DIR) $(1)/usr/share/vim
+ $(INSTALL_CONF) ./files/vimrc $(1)/usr/share/vim/
+endef
+
+define Package/vim-full/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/vim_normal $(1)/usr/bin/vim
+ $(INSTALL_DIR) $(1)/usr/share/vim
+ $(LN) vim $(1)/usr/bin/vimdiff
+ $(INSTALL_CONF) ./files/vimrc.full $(1)/usr/share/vim/vimrc
+endef
+
+
+define Package/vim-fuller/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/vim_big $(1)/usr/bin/vim
+ $(INSTALL_DIR) $(1)/usr/share/vim
+ $(LN) vim $(1)/usr/bin/vimdiff
+ $(CP) $(PKG_INSTALL_DIR)/usr/share/vim/vim$(VIMVER) $(1)/usr/share/vim
+ $(INSTALL_CONF) ./files/vimrc.full $(1)/usr/share/vim/vimrc
+endef
+
+
+
+define Package/vim-runtime/install
+ $(CP) $(PKG_INSTALL_DIR)/* $(1)
+ rm -rf $(1)/usr/share/vim/vim$(VIMVER)/doc
+endef
+
+define Package/vim-help/install
+ tar -C $(1) -xf $(PKG_BUILD_DIR)/docs.tar
+endef
+
+define Package/xxd/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/xxd/xxd $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,vim))
+$(eval $(call BuildPackage,vim-full))
+$(eval $(call BuildPackage,vim-fuller))
+$(eval $(call BuildPackage,vim-runtime))
+$(eval $(call BuildPackage,vim-help))
+$(eval $(call BuildPackage,xxd))
diff --git a/external/subpack/utils/vim/files/vimrc b/external/subpack/utils/vim/files/vimrc
new file mode 100644
index 0000000..d744cfe
--- /dev/null
+++ b/external/subpack/utils/vim/files/vimrc
@@ -0,0 +1,12 @@
+set showcmd " show (partial) command in status line
+set showmatch " show matching brackets
+set incsearch " incremental search
+"set autowrite " automatically save before commands like :next and :make
+set nocompatible " use vim defaults instead of 100% vi compatibility
+set backspace=indent,eol,start " more powerful backspacing
+set autoindent " always set autoindenting on
+set linebreak " don't wrap words by default
+set textwidth=0 " don't wrap lines by default
+set ruler " show the cursor position all the time
+
+set backupskip+=/etc/crontabs.* " fix crontab -e
diff --git a/external/subpack/utils/vim/files/vimrc.full b/external/subpack/utils/vim/files/vimrc.full
new file mode 100644
index 0000000..5cd3669
--- /dev/null
+++ b/external/subpack/utils/vim/files/vimrc.full
@@ -0,0 +1,30 @@
+set showcmd " show (partial) command in status line
+set showmatch " show matching brackets
+set incsearch " incremental search
+"set autowrite " automatically save before commands like :next and :make
+set nocompatible " use Vim defaults instead of 100% vi compatibility
+set backspace=indent,eol,start " more powerful backspacing
+set autoindent " always set autoindenting on
+set linebreak " don't wrap words by default
+set textwidth=0 " don't wrap lines by default
+set ruler " show the cursor position all the time
+
+set backupskip+=/etc/crontabs.* " fix crontab -e
+
+if filereadable(expand("$VIMRUNTIME/syntax/synload.vim"))
+ syntax on
+endif
+if has("syntax") && &term =~ "xterm"
+ set t_Co=8
+ if has("terminfo")
+ set t_Sf=<Esc>[3%p1%dm
+ set t_Sb=<Esc>[4%p1%dm
+ else
+ set t_Sf=<Esc>[3%dm
+ set t_Sb=<Esc>[4%dm
+ endif
+endif
+
+" Uncomment out for line and/or relative numberig
+" set number
+" set rnu
diff --git a/external/subpack/utils/vim/patches/002-remove_helptags_generation.patch b/external/subpack/utils/vim/patches/002-remove_helptags_generation.patch
new file mode 100644
index 0000000..83ec82e
--- /dev/null
+++ b/external/subpack/utils/vim/patches/002-remove_helptags_generation.patch
@@ -0,0 +1,10 @@
+--- a/runtime/doc/Makefile
++++ b/runtime/doc/Makefile
+@@ -345,7 +345,6 @@ all: tags vim.man evim.man vimdiff.man v
+ # Use Vim to generate the tags file. Can only be used when Vim has been
+ # compiled and installed. Supports multiple languages.
+ vimtags: $(DOCS)
+- @$(VIMEXE) --clean -esX -V1 -u doctags.vim
+
+ # Use "doctags" to generate the tags file. Only works for English!
+ tags: doctags $(DOCS)
diff --git a/external/subpack/utils/vim/patches/010-no-msgfmt.patch b/external/subpack/utils/vim/patches/010-no-msgfmt.patch
new file mode 100644
index 0000000..82e19bb
--- /dev/null
+++ b/external/subpack/utils/vim/patches/010-no-msgfmt.patch
@@ -0,0 +1,11 @@
+--- a/src/po/Makefile
++++ b/src/po/Makefile
+@@ -32,7 +32,7 @@ MSGMERGE = OLD_PO_FILE_INPUT=yes OLD_PO_
+ $(VIM) -u NONE -e -X -S check.vim -c "if error == 0 | q | endif" -c cq $<
+ touch $@
+
+-all: $(MOFILES) $(MOCONVERTED) $(MSGFMT_DESKTOP)
++all: $(MOFILES) $(MOCONVERTED)
+
+ check: $(CHECKFILES)
+
diff --git a/external/subpack/utils/vim/scripts/uname b/external/subpack/utils/vim/scripts/uname
new file mode 100755
index 0000000..d2cd568
--- /dev/null
+++ b/external/subpack/utils/vim/scripts/uname
@@ -0,0 +1,2 @@
+#!/bin/sh
+echo "Linux"
diff --git a/external/subpack/utils/vim/test.sh b/external/subpack/utils/vim/test.sh
new file mode 100644
index 0000000..913b9c6
--- /dev/null
+++ b/external/subpack/utils/vim/test.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+case "$1" in
+ vim|vim-full|vim-fuller)
+ vim --version | grep "$2"
+ ;;
+esac
diff --git a/external/subpack/utils/watchcat/Makefile b/external/subpack/utils/watchcat/Makefile
new file mode 100644
index 0000000..cb80a6a
--- /dev/null
+++ b/external/subpack/utils/watchcat/Makefile
@@ -0,0 +1,48 @@
+#
+# Copyright (C) 2010 segal.di.ubi.pt
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=watchcat
+PKG_VERSION:=1
+PKG_RELEASE:=12
+
+PKG_MAINTAINER:=Roger D <rogerdammit@gmail.com>
+PKG_LICENSE:=GPL-2.0
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/watchcat
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Enable the configuration of programmed reboots or network interface restarts
+ PKGARCH:=all
+endef
+
+define Package/watchcat/description
+Restart network interfaces or reboot if pings to hosts fail, or set up periodic reboots. Configured via UCI /etc/config/watchcat
+endef
+
+define Package/watchcat/conffiles
+/etc/config/watchcat
+endef
+
+define Build/Compile
+endef
+
+define Package/watchcat/install
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/watchcat.init $(1)/etc/init.d/watchcat
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) ./files/watchcat.sh $(1)/usr/bin/watchcat.sh
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/watchcat.config $(1)/etc/config/watchcat
+ $(INSTALL_DIR) $(1)/etc/uci-defaults
+ $(INSTALL_BIN) ./files/migrate-watchcat $(1)/etc/uci-defaults/migrate-watchcat
+endef
+
+$(eval $(call BuildPackage,watchcat))
diff --git a/external/subpack/utils/watchcat/files/migrate-watchcat b/external/subpack/utils/watchcat/files/migrate-watchcat
new file mode 100644
index 0000000..93b7ce2
--- /dev/null
+++ b/external/subpack/utils/watchcat/files/migrate-watchcat
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+. /lib/functions.sh
+
+upgrade_watchcat() {
+ local cfg="$1"
+
+ config_get period "$cfg" period
+ config_get mode "$cfg" mode
+ config_get pinghosts "$cfg" pinghosts
+ config_get forcedelay "$cfg" forcedelay
+
+ [ -f "/etc/config/watchcat" ] || touch /etc/config/watchcat
+ uci_add watchcat watchcat
+ uci_set watchcat @watchcat[-1] period "$period"
+ uci_set watchcat @watchcat[-1] mode "$mode"
+ uci_set watchcat @watchcat[-1] pinghosts "$pinghosts"
+ uci_set watchcat @watchcat[-1] forcedelay "$forcedelay"
+
+ uci_remove system "$cfg"
+}
+
+config_load system
+config_foreach upgrade_watchcat watchcat
+
+uci_commit watchcat
+uci commit system
diff --git a/external/subpack/utils/watchcat/files/watchcat.config b/external/subpack/utils/watchcat/files/watchcat.config
new file mode 100644
index 0000000..ed6544c
--- /dev/null
+++ b/external/subpack/utils/watchcat/files/watchcat.config
@@ -0,0 +1,5 @@
+config watchcat
+ option period '6h'
+ option mode 'ping_reboot'
+ option pinghosts '8.8.8.8'
+ option forcedelay '30'
diff --git a/external/subpack/utils/watchcat/files/watchcat.init b/external/subpack/utils/watchcat/files/watchcat.init
new file mode 100644
index 0000000..a48d3fd
--- /dev/null
+++ b/external/subpack/utils/watchcat/files/watchcat.init
@@ -0,0 +1,124 @@
+#!/bin/sh /etc/rc.common
+
+USE_PROCD=1
+
+START=97
+STOP=01
+
+append_string() {
+ varname="$1"
+ add="$2"
+ separator="${3:- }"
+ actual
+ eval "actual=\$$varname"
+
+ new="${actual:+$actual$separator}$add"
+ eval "$varname=\$new"
+}
+
+time_to_seconds() {
+ time=$1
+
+ { [ "$time" -ge 1 ] 2>/dev/null && seconds="$time"; } ||
+ { [ "${time%s}" -ge 1 ] 2>/dev/null && seconds="${time%s}"; } ||
+ { [ "${time%m}" -ge 1 ] 2>/dev/null && seconds=$((${time%m} * 60)); } ||
+ { [ "${time%h}" -ge 1 ] 2>/dev/null && seconds=$((${time%h} * 3600)); } ||
+ { [ "${time%d}" -ge 1 ] 2>/dev/null && seconds=$((${time%d} * 86400)); }
+
+ echo $seconds
+ unset seconds
+ unset time
+}
+
+config_watchcat() {
+ # Read config
+ config_get period "$1" period "120"
+ config_get mode "$1" mode "ping_reboot"
+ config_get pinghosts "$1" pinghosts "8.8.8.8"
+ config_get pingperiod "$1" pingperiod "60"
+ config_get forcedelay "$1" forcedelay "60"
+ config_get pingsize "$1" pingsize "standard"
+ config_get interface "$1" interface
+ config_get mmifacename "$1" mmifacename
+ config_get_bool unlockbands "$1" unlockbands "0"
+
+ # Fix potential typo in mode and provide backward compatibility.
+ [ "$mode" = "allways" ] && mode="periodic_reboot"
+ [ "$mode" = "always" ] && mode="periodic_reboot"
+ [ "$mode" = "ping" ] && mode="ping_reboot"
+
+ # Checks for settings common to all operation modes
+ if [ "$mode" != "periodic_reboot" ] && [ "$mode" != "ping_reboot" ] && [ "$mode" != "restart_iface" ]; then
+ append_string "error" "mode must be 'periodic_reboot' or 'ping_reboot' or 'restart_iface'" "; "
+ fi
+
+ period="$(time_to_seconds "$period")"
+ [ "$period" -ge 1 ] ||
+ append_string "error" "period has invalid format. Use time value(ex: '30'; '4m'; '6h'; '2d')" "; "
+
+ # ping_reboot mode and restart_iface mode specific checks
+ if [ "$mode" = "ping_reboot" ] || [ "$mode" = "restart_iface" ]; then
+ if [ -z "$error" ]; then
+ pingperiod_default="$((period / 5))"
+ pingperiod="$(time_to_seconds "$pingperiod")"
+
+ if [ "$pingperiod" -ge 0 ] && [ "$pingperiod" -ge "$period" ]; then
+ pingperiod="$(time_to_seconds "$pingperiod_default")"
+ append_string "warn" "pingperiod cannot be greater than $period. Defaulted to $pingperiod_default seconds (1/5 of period)" "; "
+ fi
+
+ if [ "$pingperiod" -lt 0 ]; then
+ append_string "warn" "pingperiod cannot be a negative value." "; "
+ fi
+
+ if [ "$mmifacename" != "" ] && [ "$period" -lt 30 ]; then
+ append_string "error" "Check interval is less than 30s. For robust operation with ModemManager modem interfaces it is recommended to set the period to at least 30s."
+ fi
+ fi
+ fi
+
+ # ping_reboot mode and periodic_reboot mode specific checks
+ if [ "$mode" = "ping_reboot" ] || [ "$mode" = "periodic_reboot" ]; then
+ forcedelay="$(time_to_seconds "$forcedelay")"
+ fi
+
+ [ -n "$warn" ] && logger -p user.warn -t "watchcat" "$1: $warn"
+ [ -n "$error" ] && {
+ logger -p user.err -t "watchcat" "reboot program $1 not started - $error"
+ return
+ }
+
+ # Need to conditionally run mode functions because they have different signatures
+ case "$mode" in
+ periodic_reboot)
+ procd_open_instance "watchcat_${1}"
+ procd_set_param command /usr/bin/watchcat.sh "periodic_reboot" "$period" "$forcedelay"
+ procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
+ procd_close_instance
+ ;;
+ ping_reboot)
+ procd_open_instance "watchcat_${1}"
+ procd_set_param command /usr/bin/watchcat.sh "ping_reboot" "$period" "$forcedelay" "$pinghosts" "$pingperiod" "$pingsize"
+ procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
+ procd_close_instance
+ ;;
+ restart_iface)
+ procd_open_instance "watchcat_${1}"
+ procd_set_param command /usr/bin/watchcat.sh "restart_iface" "$period" "$pinghosts" "$pingperiod" "$pingsize" "$interface" "$mmifacename"
+ procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
+ procd_close_instance
+ ;;
+ *)
+ echo "Error starting Watchcat service. Invalid mode selection: $mode"
+ ;;
+ esac
+}
+
+start_service() {
+ config_load watchcat
+ config_foreach config_watchcat watchcat
+}
+
+service_triggers() {
+ procd_add_reload_trigger "watchcat"
+}
diff --git a/external/subpack/utils/watchcat/files/watchcat.sh b/external/subpack/utils/watchcat/files/watchcat.sh
new file mode 100644
index 0000000..cbddffc
--- /dev/null
+++ b/external/subpack/utils/watchcat/files/watchcat.sh
@@ -0,0 +1,223 @@
+#!/bin/sh
+#
+# Copyright (C) 2010 segal.di.ubi.pt
+# Copyright (C) 2020 nbembedded.com
+#
+# This is free software, licensed under the GNU General Public License v2.
+#
+
+get_ping_size() {
+ ps=$1
+ case "$ps" in
+ small)
+ ps="1"
+ ;;
+ windows)
+ ps="32"
+ ;;
+ standard)
+ ps="56"
+ ;;
+ big)
+ ps="248"
+ ;;
+ huge)
+ ps="1492"
+ ;;
+ jumbo)
+ ps="9000"
+ ;;
+ *)
+ echo "Error: invalid ping_size. ping_size should be either: small, windows, standard, big, huge or jumbo"
+ echo "Cooresponding ping packet sizes (bytes): small=1, windows=32, standard=56, big=248, huge=1492, jumbo=9000"
+ ;;
+ esac
+ echo $ps
+}
+
+reboot_now() {
+ reboot &
+
+ [ "$1" -ge 1 ] && {
+ sleep "$1"
+ echo 1 >/proc/sys/kernel/sysrq
+ echo b >/proc/sysrq-trigger # Will immediately reboot the system without syncing or unmounting your disks.
+ }
+}
+
+watchcat_periodic() {
+ failure_period="$1"
+ force_reboot_delay="$2"
+
+ sleep "$failure_period" && reboot_now "$force_reboot_delay"
+}
+
+watchcat_restart_modemmanager_iface() {
+ [ "$2" -gt 0 ] && {
+ logger -t INFO "Resetting current-bands to 'any' on modem: \"$1\" now."
+ /usr/bin/mmcli -m any --set-current-bands=any
+ }
+ logger -t INFO "Reconnecting modem: \"$1\" now."
+ /etc/init.d/modemmanager restart
+ ifup "$1"
+}
+
+watchcat_restart_network_iface() {
+ logger -t INFO "Restarting network interface: \"$1\"."
+ ip link set "$1" down
+ ip link set "$1" up
+}
+
+watchcat_restart_all_network() {
+ logger -t INFO "Restarting networking now by running: /etc/init.d/network restart"
+ /etc/init.d/network restart
+}
+
+watchcat_monitor_network() {
+ failure_period="$1"
+ ping_hosts="$2"
+ ping_frequency_interval="$3"
+ ping_size="$4"
+ iface="$5"
+ mm_iface_name="$6"
+ mm_iface_unlock_bands="$7"
+
+ time_now="$(cat /proc/uptime)"
+ time_now="${time_now%%.*}"
+
+ [ "$time_now" -lt "$failure_period" ] && sleep "$((failure_period - time_now))"
+
+ time_now="$(cat /proc/uptime)"
+ time_now="${time_now%%.*}"
+ time_lastcheck="$time_now"
+ time_lastcheck_withinternet="$time_now"
+
+ ping_size="$(get_ping_size "$ping_size")"
+
+ while true; do
+ # account for the time ping took to return. With a ping time of 5s, ping might take more than that, so it is important to avoid even more delay.
+ time_now="$(cat /proc/uptime)"
+ time_now="${time_now%%.*}"
+ time_diff="$((time_now - time_lastcheck))"
+
+ [ "$time_diff" -lt "$ping_frequency_interval" ] && sleep "$((ping_frequency_interval - time_diff))"
+
+ time_now="$(cat /proc/uptime)"
+ time_now="${time_now%%.*}"
+ time_lastcheck="$time_now"
+
+ for host in $ping_hosts; do
+ if [ "$iface" != "" ]; then
+ ping_result="$(
+ ping -I "$iface" -s "$ping_size" -c 1 "$host" &>/dev/null
+ echo $?
+ )"
+ else
+ ping_result="$(
+ ping -s "$ping_size" -c 1 "$host" &>/dev/null
+ echo $?
+ )"
+ fi
+
+ if [ "$ping_result" -eq 0 ]; then
+ time_lastcheck_withinternet="$time_now"
+ else
+ if [ "$iface" != "" ]; then
+ logger -p daemon.info -t "watchcat[$$]" "Could not reach $host via \"$iface\" for \"$((time_now - time_lastcheck_withinternet))\" seconds. Restarting \"$iface\" after reaching \"$failure_period\" seconds"
+ else
+ logger -p daemon.info -t "watchcat[$$]" "Could not reach $host for \"$((time_now - time_lastcheck_withinternet))\" seconds. Restarting networking after reaching \"$failure_period\" seconds"
+ fi
+ fi
+ done
+
+ [ "$((time_now - time_lastcheck_withinternet))" -ge "$failure_period" ] && {
+ if [ "$mm_iface_name" != "" ]; then
+ watchcat_restart_modemmanager_iface "$mm_iface_name" "$mm_iface_unlock_bands"
+ fi
+ if [ "$iface" != "" ]; then
+ watchcat_restart_network_iface "$iface"
+ else
+ watchcat_restart_all_network
+ fi
+ /etc/init.d/watchcat start
+ }
+
+ done
+}
+
+watchcat_ping() {
+ failure_period="$1"
+ force_reboot_delay="$2"
+ ping_hosts="$3"
+ ping_frequency_interval="$4"
+ ping_size="$5"
+
+ time_now="$(cat /proc/uptime)"
+ time_now="${time_now%%.*}"
+
+ [ "$time_now" -lt "$failure_period" ] && sleep "$((failure_period - time_now))"
+
+ time_now="$(cat /proc/uptime)"
+ time_now="${time_now%%.*}"
+ time_lastcheck="$time_now"
+ time_lastcheck_withinternet="$time_now"
+
+ ping_size="$(get_ping_size "$ping_size")"
+
+ while true; do
+ # account for the time ping took to return. With a ping time of 5s, ping might take more than that, so it is important to avoid even more delay.
+ time_now="$(cat /proc/uptime)"
+ time_now="${time_now%%.*}"
+ time_diff="$((time_now - time_lastcheck))"
+
+ [ "$time_diff" -lt "$ping_frequency_interval" ] && sleep "$((ping_frequency_interval - time_diff))"
+
+ time_now="$(cat /proc/uptime)"
+ time_now="${time_now%%.*}"
+ time_lastcheck="$time_now"
+
+ for host in $ping_hosts; do
+ if [ "$iface" != "" ]; then
+ ping_result="$(
+ ping -I "$iface" -s "$ping_size" -c 1 "$host" &>/dev/null
+ echo $?
+ )"
+ else
+ ping_result="$(
+ ping -s "$ping_size" -c 1 "$host" &>/dev/null
+ echo $?
+ )"
+ fi
+
+ if [ "$ping_result" -eq 0 ]; then
+ time_lastcheck_withinternet="$time_now"
+ else
+ logger -p daemon.info -t "watchcat[$$]" "Could not reach $host for $((time_now - time_lastcheck_withinternet)). Rebooting after reaching $failure_period"
+ fi
+ done
+
+ [ "$((time_now - time_lastcheck_withinternet))" -ge "$failure_period" ] && reboot_now "$force_reboot_delay"
+ done
+}
+
+mode="$1"
+
+# Fix potential typo in mode and provide backward compatibility.
+[ "$mode" = "allways" ] && mode="periodic_reboot"
+[ "$mode" = "always" ] && mode="periodic_reboot"
+[ "$mode" = "ping" ] && mode="ping_reboot"
+
+case "$mode" in
+periodic_reboot)
+ watchcat_periodic "$2" "$3"
+ ;;
+ping_reboot)
+ watchcat_ping "$2" "$3" "$4" "$5" "$6"
+ ;;
+restart_iface)
+ watchcat_monitor_network "$2" "$3" "$4" "$5" "$6" "$7"
+ ;;
+*)
+ echo "Error: invalid mode selected: $mode"
+ ;;
+esac
diff --git a/external/subpack/utils/which/Makefile b/external/subpack/utils/which/Makefile
new file mode 100644
index 0000000..f7817c6
--- /dev/null
+++ b/external/subpack/utils/which/Makefile
@@ -0,0 +1,37 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=which
+PKG_VERSION:=2.21
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@GNU/which
+PKG_HASH:=f4a245b94124b377d8b49646bf421f9155d36aa7614b6ebf83705d3ffc76eaad
+
+PKG_MAINTAINER:=Huangbin Zhan <zhanhb88@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/which
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=which utility - full version
+ URL:=https://carlowood.github.io/which/
+ ALTERNATIVES:=300:/usr/bin/which:/usr/libexec/which-gnu
+endef
+
+define Package/which/description
+ The which command shows the full pathname of a specified program, if the specified program is in your PATH.
+endef
+
+define Package/which/install
+ $(INSTALL_DIR) $(1)/usr/libexec
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/which $(1)/usr/libexec/which-gnu
+endef
+
+$(eval $(call BuildPackage,which))
diff --git a/external/subpack/utils/whois/Makefile b/external/subpack/utils/whois/Makefile
new file mode 100644
index 0000000..9e16a02
--- /dev/null
+++ b/external/subpack/utils/whois/Makefile
@@ -0,0 +1,48 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=whois
+PKG_VERSION:=5.5.9
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=http://ftp.debian.org/debian/pool/main/w/whois
+PKG_HASH:=69088241ed33d2204f153c8005b312a69b60a1429075ff49f42f9f1f73a19c19
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+PKG_BUILD_DEPENDS:=perl/host
+
+PKG_MAINTAINER:=Paul Spooren <mail@aparcar.org>
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/whois
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Intelligent WHOIS client
+ URL:=https://github.com/rfc1036/whois
+endef
+
+define Package/whois/description
+This client is intelligent and can automatically select the appropriate whois
+server for most queries.
+
+The internal database is often more accurate than IANA's published one, but
+please send me any information you have regarding domains and network resources
+which are not correctly handled by the program.
+endef
+
+EXTRA_CFLAGS+=-DHAVE_GETOPT_LONG
+MAKE_FLAGS += PERL=$(STAGING_DIR_HOSTPKG)/usr/bin/perl
+
+define Package/whois/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/whois $(1)/usr/bin/whois
+endef
+
+$(eval $(call BuildPackage,whois))
diff --git a/external/subpack/utils/whois/patches/010-no-mkpasswd.patch b/external/subpack/utils/whois/patches/010-no-mkpasswd.patch
new file mode 100644
index 0000000..93860a5
--- /dev/null
+++ b/external/subpack/utils/whois/patches/010-no-mkpasswd.patch
@@ -0,0 +1,20 @@
+--- a/Makefile
++++ b/Makefile
+@@ -72,7 +72,7 @@ endif
+ CPPFLAGS += $(DEFS) $(INCLUDES)
+
+ ##############################################################################
+-all: Makefile.depend whois mkpasswd pos
++all: Makefile.depend whois
+
+ ##############################################################################
+ %.o: %.c
+@@ -121,7 +121,7 @@ afl-run:
+ nice afl-fuzz -i ../afl_in -o ../afl_out -- ./whois
+
+ ##############################################################################
+-install: install-whois install-mkpasswd install-pos
++install: install-whois
+
+ install-whois: whois
+ $(INSTALL) -d $(BASEDIR)$(prefix)/bin/
diff --git a/external/subpack/utils/whois/patches/020-no-idn2.patch b/external/subpack/utils/whois/patches/020-no-idn2.patch
new file mode 100644
index 0000000..096650c
--- /dev/null
+++ b/external/subpack/utils/whois/patches/020-no-idn2.patch
@@ -0,0 +1,17 @@
+--- a/Makefile
++++ b/Makefile
+@@ -42,14 +42,6 @@ ifdef HAVE_LIBIDN
+ $(error Please fix your build system to stop defining HAVE_LIBIDN!)
+ endif
+
+-ifeq ($(shell $(PKG_CONFIG) --exists 'libidn2 >= 2.0.3' || echo NO),)
+-whois_LDADD += $(shell $(PKG_CONFIG) --libs libidn2)
+-DEFS += -DHAVE_LIBIDN2 $(shell $(PKG_CONFIG) --cflags libidn2)
+-else ifeq ($(shell $(PKG_CONFIG) --exists 'libidn' || echo NO),)
+-whois_LDADD += $(shell $(PKG_CONFIG) --libs libidn)
+-DEFS += -DHAVE_LIBIDN $(shell $(PKG_CONFIG) --cflags libidn)
+-endif
+-
+ ifdef HAVE_ICONV
+ whois_OBJECTS += simple_recode.o
+ DEFS += -DHAVE_ICONV
diff --git a/external/subpack/utils/whois/test.sh b/external/subpack/utils/whois/test.sh
new file mode 100644
index 0000000..8d7455c
--- /dev/null
+++ b/external/subpack/utils/whois/test.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+whois --version | grep "$2"
diff --git a/external/subpack/utils/wifitoggle/Makefile b/external/subpack/utils/wifitoggle/Makefile
new file mode 100644
index 0000000..44919c8
--- /dev/null
+++ b/external/subpack/utils/wifitoggle/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2010-2014 OpenWrt.org
+# Copyright (C) 2010 segal.di.ubi.pt
+# Copyright (C) 2016 Karol Babioch <karol@babioch.de>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=wifitoggle
+PKG_VERSION:=1
+PKG_RELEASE:=6
+PKG_LICENSE:=GPL-2.0-or-later
+
+PKG_MAINTAINER:=Nuno Goncalves <nunojpg@gmail.com>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/wifitoggle
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Script to toggle Wi-Fi with a button and UCI config
+ PKGARCH:=all
+endef
+
+define Package/wifitoggle/description
+Very versatile script to toggle Wi-Fi with a button. Allows to set
+timeouts, persist changes after boot, and set LEDs according to the state.
+endef
+
+define Package/wifitoggle/conffiles
+/etc/config/wifitoggle
+endef
+
+define Build/Compile
+endef
+
+define Package/wifitoggle/install
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/button
+ $(INSTALL_BIN) ./files/wifitoggle.hotplug $(1)/etc/hotplug.d/button/50-wifitoggle
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/wifitoggle.config $(1)/etc/config/wifitoggle
+endef
+
+$(eval $(call BuildPackage,wifitoggle))
diff --git a/external/subpack/utils/wifitoggle/files/wifitoggle.config b/external/subpack/utils/wifitoggle/files/wifitoggle.config
new file mode 100755
index 0000000..a8d0906
--- /dev/null
+++ b/external/subpack/utils/wifitoggle/files/wifitoggle.config
@@ -0,0 +1,13 @@
+config wifitoggle
+ option button 'wps'
+
+ option persistent '0'
+ option timer '600'
+
+ #option led_sysfs 'wrt160nl:amber:wps'
+ # Leaving this option empty, makes sure that no LED is touched
+ option led_sysfs ''
+ option led_enable_trigger 'timer'
+ option led_enable_delayon '500'
+ option led_enable_delayoff '500'
+ option led_disable_default '0'
diff --git a/external/subpack/utils/wifitoggle/files/wifitoggle.hotplug b/external/subpack/utils/wifitoggle/files/wifitoggle.hotplug
new file mode 100755
index 0000000..295a087
--- /dev/null
+++ b/external/subpack/utils/wifitoggle/files/wifitoggle.hotplug
@@ -0,0 +1,174 @@
+# /bin/sh
+
+setled() {
+ if [ -z "${led_sysfs}" ]; then
+ return
+ elif [ -e /sys/class/leds/${led_sysfs}/brightness ]
+ then
+ [ $led_default -eq 1 ] && echo 1 >/sys/class/leds/${led_sysfs}/brightness
+ [ $led_default -eq 1 ] || echo 0 >/sys/class/leds/${led_sysfs}/brightness
+
+ echo $led_trigger > /sys/class/leds/${led_sysfs}/trigger
+
+ [ "$led_trigger" == "netdev" -a -n "$led_dev" ] && {
+ echo $led_dev > /sys/class/leds/${led_sysfs}/device_name
+ echo $led_mode > /sys/class/leds/${led_sysfs}/mode
+ }
+
+ [ "$led_trigger" == "timer" ] && {
+ [ -n "$led_delayon" ] && echo $led_delayon > /sys/class/leds/${led_sysfs}/delay_on
+ [ -n "$led_delayoff" ] && echo $led_delayoff > /sys/class/leds/${led_sysfs}/delay_off
+ }
+ else
+ logger -p user.err -t "wifitoggle" "led: ${led_sysfs} not found"
+ fi
+}
+
+load_wireless() {
+ disabled="$(uci get wireless.${1}.disabled)"
+}
+
+save_wireless() {
+ [ "$device" = "all" -o "$device" = "${1}" ] && {
+ uci set "wireless.${1}.disabled=$disabled"
+ }
+}
+
+setwifi() {
+ setled
+
+ config_load wireless
+ config_foreach save_wireless wifi-device
+
+ if ubus list network.wireless >/dev/null 2>/dev/null; then
+ ubus call network reload
+ else
+ wifi
+ fi
+}
+
+
+save_system() {
+ config_get sysfs $1 sysfs
+ [ "$sysfs" = "$led_sysfs" ] && {
+ uci set "system.${1}.trigger=$led_trigger"
+ uci set "system.${1}.dev=$led_dev"
+ uci set "system.${1}.mode=$led_mode"
+ uci set "system.${1}.default=$led_default"
+ uci set "system.${1}.delayon=$led_delayon"
+ uci set "system.${1}.delayoff=$led_delayoff"
+
+ ledset=1
+ }
+}
+
+commit_changes() {
+ ledset=""
+
+ config_load system
+ config_foreach save_system led
+
+ [ "$ledset" -eq 1 ] || {
+ section=$(uci add system led)
+ uci set "system.${section}.sysfs=$led_sysfs"
+ uci set "system.${section}.trigger=$led_trigger"
+ uci set "system.${section}.dev=$led_dev"
+ uci set "system.${section}.mode=$led_mode"
+ uci set "system.${section}.default=$led_default"
+ uci set "system.${section}.delayon=$led_delayon"
+ uci set "system.${section}.delayoff=$led_delayoff"
+ }
+
+ uci commit
+}
+
+enable() {
+
+ led_trigger="$led_enable_trigger"
+ led_trigger="$led_enable_trigger"
+ led_dev="$led_enable_dev"
+ led_mode="$led_enable_mode"
+ led_default="$led_enable_default"
+ led_delayon="$led_enable_delayon"
+ led_delayoff="$led_enable_delayoff"
+ disabled=0
+
+ setwifi
+
+ [ "$timer" -le 0 -a "$persistent" -eq 1 ] && commit_changes
+
+ logger -p user.info -t "wifitoggle" "device($device) enabled"
+
+ [ "$timer" -gt 0 ] && {
+ sleep "$timer" && disable && rm /tmp/run/wirelesstoggle_${1}.pid &
+ echo $! > /tmp/run/wirelesstoggle_${1}.pid
+ logger -p user.info -t "wifitoggle" "auto-disable timer started($timer seconds)"
+ }
+}
+
+disable() {
+
+ led_trigger="$led_disable_trigger"
+ led_trigger="$led_disable_trigger"
+ led_dev="$led_disable_dev"
+ led_mode="$led_disable_mode"
+ led_default="$led_disable_default"
+ led_delayon="$led_disable_delayon"
+ led_delayoff="$led_disable_delayoff"
+ disabled=1
+
+ setwifi
+
+ [ "$timer" -le 0 -a "$persistent" -eq 1 ] && commit_changes
+
+ logger -p user.info -t "wifitoggle" "device($device) disabled"
+}
+
+
+load_wifitoggle() {
+ config_get device $1 device "all"
+ config_get button $1 button "wps"
+ config_get action $1 action "pressed"
+ config_get_bool persistent $1 persistent "0"
+ config_get timer $1 timer "0"
+
+ config_get led_sysfs $1 led_sysfs
+
+ config_get led_enable_trigger $1 led_enable_trigger "none"
+ config_get led_enable_dev $1 led_enable_dev
+ config_get led_enable_mode $1 led_enable_mode "link"
+ config_get_bool led_enable_default $1 led_enable_default "1"
+ config_get led_enable_delayon $1 led_enable_delayon
+ config_get led_enable_delayoff $1 led_enable_delayoff
+
+ config_get led_disable_trigger $1 led_disable_trigger "none"
+ config_get led_disable_dev $1 led_disable_dev
+ config_get led_disable_mode $1 led_disable_mode "link"
+ config_get_bool led_disable_default $1 led_disable_default "0"
+ config_get led_disable_delayon $1 led_disable_delayon
+ config_get led_disable_delayoff $1 led_disable_delayoff
+
+ [ "$ACTION" = "$action" -a "$BUTTON" = "$button" ] && {
+
+ [ -f /tmp/run/wirelesstoggle_${1}.pid ] && read PID < /tmp/run/wirelesstoggle_${1}.pid && kill $PID && rm /tmp/run/wirelesstoggle_${1}.pid
+
+ if [ "$device" = "all" ]
+ then
+ config_load wireless
+ config_foreach load_wireless wifi-device
+ else
+ disabled="$(uci get wireless."$device".disabled)"
+ fi
+
+
+ if [ "$disabled" = "1" ]
+ then
+ enable $1
+ else
+ disable
+ fi
+ }
+}
+
+config_load wifitoggle
+config_foreach load_wifitoggle wifitoggle
diff --git a/external/subpack/utils/wipe/Makefile b/external/subpack/utils/wipe/Makefile
new file mode 100644
index 0000000..84053d3
--- /dev/null
+++ b/external/subpack/utils/wipe/Makefile
@@ -0,0 +1,42 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=wipe
+PKG_VERSION:=0.24
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/berke/$(PKG_NAME)/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=aefb4403333562f9af5e3e03ecbba4b124e98788c688662240f9b04d80bfdb2f
+
+PKG_MAINTAINER:=Toni Uhlig <matzeton@googlemail.com>
+PKG_LICENSE:=GPL-2.0-only
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/wipe
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=securely erase files
+ URL:=http://lambda-diode.com/software/wipe/
+endef
+
+define Package/wipe/description
+ wipe is a little command for securely erasing files from magnetic media.
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) linux \
+ CC_LINUX="$(TARGET_CC)" \
+ CFLAGS="$(TARGET_CFLAGS)" \
+ LDFLAGS="$(TARGET_LDFLAGS)" \
+ CPPFLAGS="$(TARGET_CPPFLAGS)"
+endef
+
+define Package/wipe/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/wipe $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,wipe))
diff --git a/external/subpack/utils/wipe/patches/001-ignore_git_version_hash_and_fix_release_version.patch b/external/subpack/utils/wipe/patches/001-ignore_git_version_hash_and_fix_release_version.patch
new file mode 100644
index 0000000..a710fb3
--- /dev/null
+++ b/external/subpack/utils/wipe/patches/001-ignore_git_version_hash_and_fix_release_version.patch
@@ -0,0 +1,26 @@
+--- a/Makefile
++++ b/Makefile
+@@ -157,11 +157,7 @@ wipe.o : wipe.c random.h misc.h version.
+ $(CC) $(CCO) $(CCOC) wipe.c -o wipe.o
+
+ version.h: always
+- if which git >/dev/null 2>&1 ; then \
+- git rev-list --max-count=1 HEAD | sed -e 's/^/#define WIPE_GIT "/' -e 's/$$/"/' >version.h ; \
+- else \
+- echo '#define WIPE_GIT "(unknown, compiled without git)"' >version.h ; \
+- fi
++ echo '#define WIPE_GIT "(unknown, compiled without git)"' >version.h ; \
+
+ random.o : random.c misc.h md5.h
+ $(CC) $(CCO) $(CCOC) random.c -o random.o
+--- a/wipe.c
++++ b/wipe.c
+@@ -24,7 +24,7 @@
+
+ /*** defines */
+
+-#define WIPE_VERSION "0.23"
++#define WIPE_VERSION "0.24"
+ #define WIPE_DATE "2016-11-03"
+
+ /* exit codes */
diff --git a/external/subpack/utils/xfsprogs/Makefile b/external/subpack/utils/xfsprogs/Makefile
new file mode 100644
index 0000000..77cb580
--- /dev/null
+++ b/external/subpack/utils/xfsprogs/Makefile
@@ -0,0 +1,98 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=xfsprogs
+PKG_VERSION:=5.9.0
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/linux/utils/fs/xfs/xfsprogs
+PKG_HASH:=bc5c805596bc609a18dc1f1b4ed6a2821dba9f47408ec00e7799ceea1b2097f1
+
+PKG_MAINTAINER:=
+PKG_LICENSE:=GPL-2.0-only
+PKG_LICENSE_FILES:=LICENSES/GPL-2.0
+PKG_CPE_ID:=cpe:/a:sgi:xfsprogs
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/xfsprogs/default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Filesystem
+ DEPENDS:=+libuuid +libpthread
+ URL:=https://xfs.org/
+endef
+
+define Package/xfs-admin
+$(call Package/xfsprogs/default)
+ TITLE:=Utilities for changing parameters of an XFS filesystems
+endef
+
+define Package/xfs-mkfs
+$(call Package/xfsprogs/default)
+ TITLE:=Utility for creating XFS filesystems
+endef
+
+define Package/xfs-fsck
+$(call Package/xfsprogs/default)
+ TITLE:=Utilities for checking and repairing XFS filesystems
+endef
+
+define Package/xfs-growfs
+$(call Package/xfsprogs/default)
+ TITLE:=Utility for increasing the size of XFS filesystems
+endef
+
+CONFIGURE_ARGS += \
+ --disable-gettext \
+ --disable-blkid \
+ --disable-readline \
+ --disable-editline \
+ --disable-termcap \
+ --disable-lib64 \
+ --disable-librt \
+ --disable-ubisan \
+ --disable-addrsan \
+ --disable-threadsan \
+ --disable-scrub \
+ --disable-libicu
+
+TARGET_CFLAGS += -DHAVE_MAP_SYNC
+TARGET_LDFLAGS += $(if $(CONFIG_USE_GLIBC),-lrt)
+
+define Package/xfs-admin/install
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/xfs_db $(1)/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/xfs_admin $(1)/sbin
+endef
+
+define Package/xfs-mkfs/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/mkfs.xfs $(1)/usr/sbin
+endef
+
+define Package/xfs-fsck/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/xfs_repair $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/xfs_db $(1)/usr/sbin
+endef
+
+define Package/xfs-growfs/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/xfs_growfs $(1)/usr/sbin
+endef
+
+$(eval $(call BuildPackage,xfs-admin))
+$(eval $(call BuildPackage,xfs-mkfs))
+$(eval $(call BuildPackage,xfs-fsck))
+$(eval $(call BuildPackage,xfs-growfs))
diff --git a/external/subpack/utils/xfsprogs/patches/110-subdirs.patch b/external/subpack/utils/xfsprogs/patches/110-subdirs.patch
new file mode 100644
index 0000000..ad57d60
--- /dev/null
+++ b/external/subpack/utils/xfsprogs/patches/110-subdirs.patch
@@ -0,0 +1,12 @@
+--- a/Makefile
++++ b/Makefile
+@@ -62,8 +62,7 @@ HDR_SUBDIRS = include libxfs
+ LIBFROG_SUBDIR = libfrog
+ DLIB_SUBDIRS = libxlog libxcmd libhandle
+ LIB_SUBDIRS = libxfs $(DLIB_SUBDIRS)
+-TOOL_SUBDIRS = copy db estimate fsck fsr growfs io logprint mkfs quota \
+- mdrestore repair rtcp m4 man doc debian spaceman
++TOOL_SUBDIRS = db fsck growfs io mkfs repair
+
+ ifeq ("$(ENABLE_SCRUB)","yes")
+ TOOL_SUBDIRS += scrub
diff --git a/external/subpack/utils/xfsprogs/patches/120-disable_assert.patch b/external/subpack/utils/xfsprogs/patches/120-disable_assert.patch
new file mode 100644
index 0000000..5bde4fb
--- /dev/null
+++ b/external/subpack/utils/xfsprogs/patches/120-disable_assert.patch
@@ -0,0 +1,12 @@
+--- a/libxfs/libxfs_priv.h
++++ b/libxfs/libxfs_priv.h
+@@ -87,9 +87,6 @@ struct iomap;
+ /* for all the support code that uses progname in error messages */
+ extern char *progname;
+
+-#undef ASSERT
+-#define ASSERT(ex) assert(ex)
+-
+ /*
+ * We have no need for the "linux" dev_t in userspace, so these
+ * are no-ops, and an xfs_dev_t is stored in VFS_I(ip)->i_rdev
diff --git a/external/subpack/utils/xfsprogs/patches/130-db-malloc-Use-posix_memalign-instead-of-deprecated-v.patch b/external/subpack/utils/xfsprogs/patches/130-db-malloc-Use-posix_memalign-instead-of-deprecated-v.patch
new file mode 100644
index 0000000..a9ab4d3
--- /dev/null
+++ b/external/subpack/utils/xfsprogs/patches/130-db-malloc-Use-posix_memalign-instead-of-deprecated-v.patch
@@ -0,0 +1,26 @@
+From 930f9aa8f08759fa739dd6e615ba8b3a1890008d Mon Sep 17 00:00:00 2001
+From: Rosen Penev <rosenp@gmail.com>
+Date: Mon, 6 May 2019 13:56:13 -0700
+Subject: [PATCH] db/malloc: Use posix_memalign instead of deprecated valloc
+
+valloc is not available with uClibc-ng as well as being deprecated, which
+causes compilation errors. aligned_alloc is not available before C11 so
+used posix_memalign.'
+
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+---
+ db/malloc.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/db/malloc.c
++++ b/db/malloc.c
+@@ -44,8 +44,7 @@ xmalloc(
+ {
+ void *ptr;
+
+- ptr = valloc(size);
+- if (ptr)
++ if(!posix_memalign(&ptr, sysconf(_SC_PAGESIZE), size))
+ return ptr;
+ badmalloc();
+ /* NOTREACHED */
diff --git a/external/subpack/utils/xfsprogs/patches/140-mman.patch b/external/subpack/utils/xfsprogs/patches/140-mman.patch
new file mode 100644
index 0000000..fef5d50
--- /dev/null
+++ b/external/subpack/utils/xfsprogs/patches/140-mman.patch
@@ -0,0 +1,17 @@
+--- a/io/mmap.c
++++ b/io/mmap.c
+@@ -11,6 +11,14 @@
+ #include "init.h"
+ #include "io.h"
+
++#ifndef MAP_SYNC
++#define MAP_SYNC 0
++#endif
++
++#ifndef MAP_SHARED_VALIDATE
++#define MAP_SHARED_VALIDATE 0x03
++#endif
++
+ static cmdinfo_t mmap_cmd;
+ static cmdinfo_t mread_cmd;
+ static cmdinfo_t msync_cmd;
diff --git a/external/subpack/utils/yara/Config.in b/external/subpack/utils/yara/Config.in
new file mode 100644
index 0000000..328ce4c
--- /dev/null
+++ b/external/subpack/utils/yara/Config.in
@@ -0,0 +1,23 @@
+if PACKAGE_yara
+ comment "Optional modules"
+
+ config YARA_module_magic
+ bool "Magic module"
+ default y
+ help
+ Identify the type of the file based on the output of file command
+
+ config YARA_module_cuckoo
+ bool "Cuckoo module"
+ default n
+ help
+ Create rules based on behavioral info generated by a Cuckoo sandbox
+
+ config YARA_module_dotnet
+ bool "Dotnet module"
+ default n
+ help
+ The dotnet module allows you to create more fine-grained rules
+ for .NET files by using attributes and features of the .NET file format
+endif
+
diff --git a/external/subpack/utils/yara/Makefile b/external/subpack/utils/yara/Makefile
new file mode 100644
index 0000000..272ae50
--- /dev/null
+++ b/external/subpack/utils/yara/Makefile
@@ -0,0 +1,74 @@
+#
+# Copyright (C) 2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=yara
+PKG_VERSION:=4.0.2
+PKG_RELEASE:=2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/VirusTotal/yara/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=05ad88eac9a9f0232432fd14516bdaeda14349d6cf0cac802d76e369abcee001
+
+PKG_MAINTAINER:=Marko Ratkaj <marko.ratkaj@sartura.hr>
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=COPYING
+PKG_CPE_ID:=cpe:/a:virustotal:yara
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/yara
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Pattern matching swiss knife for malware researchers
+ URL:=http://virustotal.github.io/yara/
+ DEPENDS:= +libopenssl
+ DEPENDS+= +YARA_module_magic:file
+ DEPENDS+= +YARA_module_cuckoo:jansson
+ MENU:=1
+endef
+
+define Package/yara/description
+ YARA is a tool aimed at (but not limited to) helping malware researchers
+ to identify and classify malware samples. With YARA you can create
+ descriptions of malware families based on textual or binary patterns.
+endef
+
+CONFIGURE_ARGS += \
+ $(if $(CONFIG_YARA_module_dotnet),--enable,--disable)-dotnet \
+ $(if $(CONFIG_YARA_module_magic),--enable,--disable)-magic \
+ $(if $(CONFIG_YARA_module_cuckoo),--enable,--disable)-cuckoo
+
+define Package/yara/config
+ source "$(SOURCE)/Config.in"
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/yara.h $(1)/usr/include
+ $(INSTALL_DIR) $(1)/usr/include/yara
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/yara/* $(1)/usr/include/yara
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libyara.{a,la,so*} $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/yara.pc $(1)/usr/lib/pkgconfig
+endef
+
+define Package/yara/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/yara $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/yarac $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/lib/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libyara.so* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,yara))
diff --git a/external/subpack/utils/yara/patches/010-openssl.patch b/external/subpack/utils/yara/patches/010-openssl.patch
new file mode 100644
index 0000000..a54b000
--- /dev/null
+++ b/external/subpack/utils/yara/patches/010-openssl.patch
@@ -0,0 +1,48 @@
+--- a/libyara/include/yara/pe_utils.h
++++ b/libyara/include/yara/pe_utils.h
+@@ -102,7 +102,7 @@ char *ord_lookup(
+
+ #if HAVE_LIBCRYPTO
+ #include <openssl/asn1.h>
+-time_t ASN1_get_time_t(ASN1_TIME* time);
++time_t ASN1_get_time_t(const ASN1_TIME* time);
+ #endif
+
+ #endif
+--- a/libyara/modules/pe/pe.c
++++ b/libyara/modules/pe/pe.c
+@@ -44,8 +44,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBI
+ #endif
+
+ #if OPENSSL_VERSION_NUMBER < 0x10100000L
+-#define X509_getm_notBefore X509_get_notBefore
+-#define X509_getm_notAfter X509_get_notAfter
++#define X509_get0_notBefore X509_get_notBefore
++#define X509_get0_notAfter X509_get_notAfter
+ #endif
+ #endif
+
+@@ -1433,10 +1433,10 @@ void _parse_pkcs7(
+ }
+ }
+
+- date_time = ASN1_get_time_t(X509_get_notBefore(cert));
++ date_time = ASN1_get_time_t(X509_get0_notBefore(cert));
+ set_integer(date_time, pe->object, "signatures[%i].not_before", *counter);
+
+- date_time = ASN1_get_time_t(X509_get_notAfter(cert));
++ date_time = ASN1_get_time_t(X509_get0_notAfter(cert));
+ set_integer(date_time, pe->object, "signatures[%i].not_after", *counter);
+
+ (*counter)++;
+--- a/libyara/modules/pe/pe_utils.c
++++ b/libyara/modules/pe/pe_utils.c
+@@ -307,7 +307,7 @@ time_t timegm(
+ // and cleaned up. Also uses timegm(3) instead of mktime(3).
+
+ time_t ASN1_get_time_t(
+- ASN1_TIME* time)
++ const ASN1_TIME* time)
+ {
+ struct tm t;
+ const char* str = (const char*) time->data;
diff --git a/external/subpack/utils/ykclient/Makefile b/external/subpack/utils/ykclient/Makefile
new file mode 100644
index 0000000..e654143
--- /dev/null
+++ b/external/subpack/utils/ykclient/Makefile
@@ -0,0 +1,47 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ykclient
+PKG_VERSION:=2.15
+PKG_RELEASE:=1
+
+PKG_SOURCE:=ykclient-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://developers.yubico.com/yubico-c-client/Releases/
+PKG_HASH:=f461cdefe7955d58bbd09d0eb7a15b36cb3576b88adbd68008f40ea978ea5016
+PKG_MAINTAINER:=Stuart B. Wilkins <stuwilkins@mac.com>
+PKG_LICENSE_FILES:=COPYING
+PKG_LICENSE:=BSD-2-Clause
+PKG_BUILD_DEPENDS:=curl
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ykclient
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=The Yuibco yubikey c client library
+ URL:=https://developers.yubico.com/yubico-c-client/
+ DEPENDS:=curl
+endef
+
+define Package/ykclient/description
+ YubiKey C Client Library (libykclient)
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(STAGING_DIR)/usr/include
+ $(CP) $(PKG_BUILD_DIR)/ykclient*.h $(STAGING_DIR)/usr/include
+ $(INSTALL_DIR) $(STAGING_DIR)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/.libs/libykclient.so* $(STAGING_DIR)/usr/lib
+endef
+
+CONFIGURE_ARGS += \
+ --enable-shared \
+ --disable-static
+
+define Package/ykclient/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/ykclient $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/.libs/libykclient.so* $(1)/usr/lib
+endef
+
+$(eval $(call BuildPackage,ykclient))
diff --git a/external/subpack/utils/ykpers/Makefile b/external/subpack/utils/ykpers/Makefile
new file mode 100644
index 0000000..7c2261c
--- /dev/null
+++ b/external/subpack/utils/ykpers/Makefile
@@ -0,0 +1,55 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ykpers
+PKG_VERSION:=1.20.0
+PKG_RELEASE:=3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://developers.yubico.com/yubikey-personalization/Releases
+PKG_HASH:=0ec84d0ea862f45a7d85a1a3afe5e60b8da42df211bb7d27a50f486e31a79b93
+
+PKG_MAINTAINER:=Stuart B. Wilkins <stuwilkins@mac.com>
+PKG_LICENSE:=BSD-2-Clause
+PKG_LICENSE_FILES:=COPYING
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ykpers
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=The Yuibco personalization package
+ URL:=https://developers.yubico.com/yubikey-personalization/
+ DEPENDS:=+curl +libyubikey +libjson-c +libusb-1.0
+endef
+
+define Package/ykpers/description
+ The YubiKey Personalization package contains a library and command
+ line tool used to personalize (i.e., set a AES key) YubiKeys.
+endef
+
+CONFIGURE_ARGS += \
+ --enable-shared \
+ --disable-static
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(STAGING_DIR)/usr/include/ykpers-1
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/ykpers-1/*.h $(STAGING_DIR)/usr/include/ykpers-1
+ $(INSTALL_DIR) $(STAGING_DIR)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libykpers-1.so* $(STAGING_DIR)/usr/lib
+ $(INSTALL_DIR) $(STAGING_DIR)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/ykpers-1.pc $(STAGING_DIR)/usr/lib/pkgconfig
+endef
+
+define Package/ykpers/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ykchalresp $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ykinfo $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ykpersonalize $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libykpers-1.so* $(1)/usr/lib
+endef
+
+$(eval $(call BuildPackage,ykpers))
diff --git a/external/subpack/utils/ykpers/patches/010-gcc10.patch b/external/subpack/utils/ykpers/patches/010-gcc10.patch
new file mode 100644
index 0000000..dcff56a
--- /dev/null
+++ b/external/subpack/utils/ykpers/patches/010-gcc10.patch
@@ -0,0 +1,13 @@
+--- a/ykpers-args.h
++++ b/ykpers-args.h
+@@ -33,8 +33,8 @@
+
+ #include "ykpers.h"
+
+-const char *usage;
+-const char *optstring;
++extern const char *usage;
++extern const char *optstring;
+
+ int args_to_config(int argc, char **argv, YKP_CONFIG *cfg, char *oathid,
+ size_t oathid_len, const char **infname,
diff --git a/external/subpack/utils/ykpers/patches/020-json-c-0.14.patch b/external/subpack/utils/ykpers/patches/020-json-c-0.14.patch
new file mode 100644
index 0000000..2bb27c9
--- /dev/null
+++ b/external/subpack/utils/ykpers/patches/020-json-c-0.14.patch
@@ -0,0 +1,81 @@
+From 0aa2e2cae2e1777863993a10c809bb50f4cde7f8 Mon Sep 17 00:00:00 2001
+From: Christian Hesse <mail@eworm.de>
+Date: Sat, 25 Apr 2020 20:55:28 +0200
+Subject: [PATCH] fix boolean value with json-c 0.14
+
+Upstream removed the TRUE and FALSE defines in commit
+0992aac61f8b087efd7094e9ac2b84fa9c040fcd.
+---
+ ykpers-json.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/ykpers-json.c
++++ b/ykpers-json.c
+@@ -40,7 +40,7 @@
+ #define yk_json_object_object_get(obj, key, value) json_object_object_get_ex(obj, key, &value)
+ #else
+ typedef int json_bool;
+-#define yk_json_object_object_get(obj, key, value) (value = json_object_object_get(obj, key)) == NULL ? (json_bool)FALSE : (json_bool)TRUE
++#define yk_json_object_object_get(obj, key, value) (value = json_object_object_get(obj, key)) == NULL ? 0 : 1
+ #endif
+
+ static void set_json_value(struct map_st *p, int mode, json_object *options, YKP_CONFIG *cfg) {
+@@ -50,7 +50,7 @@ static void set_json_value(struct map_st
+ if(p->mode && (mode & p->mode) == mode) {
+ json_object *joption;
+ json_bool ret = yk_json_object_object_get(options, p->json_text, joption);
+- if(ret == TRUE && json_object_get_type(joption) == json_type_boolean) {
++ if(ret == 1 && json_object_get_type(joption) == json_type_boolean) {
+ int value = json_object_get_boolean(joption);
+ if(value == 1) {
+ p->setter(cfg, true);
+@@ -230,20 +230,20 @@ int _ykp_json_import_cfg(YKP_CONFIG *cfg
+ ykp_errno = YKP_EINVAL;
+ goto out;
+ }
+- if(yk_json_object_object_get(jobj, "yubiProdConfig", yprod_json) == FALSE) {
++ if(yk_json_object_object_get(jobj, "yubiProdConfig", yprod_json) == 0) {
+ ykp_errno = YKP_EINVAL;
+ goto out;
+ }
+- if(yk_json_object_object_get(yprod_json, "mode", jmode) == FALSE) {
++ if(yk_json_object_object_get(yprod_json, "mode", jmode) == 0) {
+ ykp_errno = YKP_EINVAL;
+ goto out;
+ }
+- if(yk_json_object_object_get(yprod_json, "options", options) == FALSE) {
++ if(yk_json_object_object_get(yprod_json, "options", options) == 0) {
+ ykp_errno = YKP_EINVAL;
+ goto out;
+ }
+
+- if(yk_json_object_object_get(yprod_json, "targetConfig", jtarget) == TRUE) {
++ if(yk_json_object_object_get(yprod_json, "targetConfig", jtarget) == 1) {
+ int target_config = json_object_get_int(jtarget);
+ int command;
+ if(target_config == 1) {
+@@ -275,13 +275,13 @@ int _ykp_json_import_cfg(YKP_CONFIG *cfg
+ if(mode == MODE_OATH_HOTP) {
+ json_object *jdigits, *jrandom;
+ ykp_set_tktflag_OATH_HOTP(cfg, true);
+- if(yk_json_object_object_get(options, "oathDigits", jdigits) == TRUE) {
++ if(yk_json_object_object_get(options, "oathDigits", jdigits) == 1) {
+ int digits = json_object_get_int(jdigits);
+ if(digits == 8) {
+ ykp_set_cfgflag_OATH_HOTP8(cfg, true);
+ }
+ }
+- if(yk_json_object_object_get(options, "randomSeed", jrandom) == TRUE) {
++ if(yk_json_object_object_get(options, "randomSeed", jrandom) == 1) {
+ int random = json_object_get_boolean(jrandom);
+ int seed = 0;
+ if(random == 1) {
+@@ -290,7 +290,7 @@ int _ykp_json_import_cfg(YKP_CONFIG *cfg
+ goto out;
+ } else {
+ json_object *jseed;
+- if(yk_json_object_object_get(options, "fixedSeedvalue", jseed) == TRUE) {
++ if(yk_json_object_object_get(options, "fixedSeedvalue", jseed) == 1) {
+ seed = json_object_get_int(jseed);
+ }
+ }
diff --git a/external/subpack/utils/yq/Makefile b/external/subpack/utils/yq/Makefile
new file mode 100644
index 0000000..7cca84b
--- /dev/null
+++ b/external/subpack/utils/yq/Makefile
@@ -0,0 +1,38 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=yq
+PKG_VERSION:=4.29.2
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/mikefarah/yq/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=4a349c7858793463555c12df698757265a3e46d6b107adac75fabc46d9591df6
+
+PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
+PKG_LICENSE:=MIT
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/mikefarah/yq/v4
+GO_PKG_LDFLAGS_X:=$(GO_PKG)/cmd.Version=$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+define Package/yq
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Portable command-line YAML processor
+ URL:=https://mikefarah.gitbook.io/yq/
+ DEPENDS:=$(GO_ARCH_DEPENDS)
+endef
+
+define Package/yq/description
+ The aim of the project is to be the jq or sed of yaml files.
+endef
+
+$(eval $(call GoBinPackage,yq))
+$(eval $(call BuildPackage,yq))
diff --git a/external/subpack/utils/yq/test.sh b/external/subpack/utils/yq/test.sh
new file mode 100644
index 0000000..0fc2336
--- /dev/null
+++ b/external/subpack/utils/yq/test.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+yq --version 2>&1 | grep "$PKG_VERSION"
diff --git a/external/subpack/utils/zile/Makefile b/external/subpack/utils/zile/Makefile
new file mode 100644
index 0000000..6669dd2
--- /dev/null
+++ b/external/subpack/utils/zile/Makefile
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2006-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=zile
+PKG_VERSION:=2.3.24
+PKG_RELEASE:=5
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@GNU/zile
+PKG_HASH:=218bb2af414c6a168101656631a5b2da92f20a965895e1006658cc658b0b7e89
+PKG_MAINTAINER:=Ted Hess <thess@kitschensync.net>
+
+PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+PKG_FIXUP:=autoreconf
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/zile
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libncursesw
+ TITLE:=very small emacs-like editor
+ URL:=http://www.gnu.org/software/zile/
+ SUBMENU:=Editors
+endef
+
+define Package/zile/description
+ Zile is a small Emacs clone. Zile is a customizable, self-documenting
+ real-time display editor. Zile was written to be as similar as possible
+ to Emacs; every Emacs user should feel at home with Zile.
+endef
+
+CONFIGURE_VARS += \
+ gl_cv_func_getopt_gnu=yes \
+ gl_cv_warn__Wmudflap=no \
+ gl_cv_warn__fmudflap=no
+
+CONFIGURE_ARGS += \
+ --with-ncursesw \
+
+
+define Package/zile/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/$(PKG_NAME) $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,zile))
diff --git a/external/subpack/utils/zile/patches/010-remove_gets_definition_warning.patch b/external/subpack/utils/zile/patches/010-remove_gets_definition_warning.patch
new file mode 100644
index 0000000..55ad2c4
--- /dev/null
+++ b/external/subpack/utils/zile/patches/010-remove_gets_definition_warning.patch
@@ -0,0 +1,11 @@
+--- a/lib/stdio.in.h
++++ b/lib/stdio.in.h
+@@ -733,7 +733,7 @@ _GL_CXXALIASWARN (gets);
+ /* It is very rare that the developer ever has full control of stdin,
+ so any use of gets warrants an unconditional warning. Assume it is
+ always declared, since it is required by C89. */
+-_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
++#define gets(a) fgets( a, sizeof(*(a)), stdin)
+ #endif
+
+
diff --git a/external/subpack/utils/zoneinfo/Makefile b/external/subpack/utils/zoneinfo/Makefile
new file mode 100644
index 0000000..469d761
--- /dev/null
+++ b/external/subpack/utils/zoneinfo/Makefile
@@ -0,0 +1,260 @@
+#
+# Copyright (C) 2007-2021 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# Author: Michael Geddes
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=zoneinfo
+PKG_VERSION:=2021a
+PKG_RELEASE:=1
+
+#As i couldn't find real license used "Public Domain"
+#as referense to http://www.iana.org/time-zones/repository/tz-link.html
+PKG_LICENSE:=Public Domain
+
+PKG_SOURCE:=tzdata$(PKG_VERSION).tar.gz
+PKG_SOURCE_CODE:=tzcode$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.iana.org/time-zones/repository/releases
+PKG_HASH:=39e7d2ba08c68cbaefc8de3227aab0dec2521be8042cf56855f7dc3a9fb14e08
+
+include $(INCLUDE_DIR)/package.mk
+
+define Download/tzcode
+ FILE=$(PKG_SOURCE_CODE)
+ URL=$(PKG_SOURCE_URL)
+ HASH:=eb46bfa124b5b6bd13d61a609bfde8351bd192894708d33aa06e5c1e255802d0
+endef
+
+$(eval $(call Download,tzcode))
+
+define Package/zoneinfo/Default
+ SUBMENU:=Zoneinfo
+ TITLE:=Zone Information
+ SECTION:=utils
+ CATEGORY:=Utilities
+ MAINTAINER:=Vladimir Ulrich <admin@evl.su>
+endef
+
+define Package/zoneinfo-core
+$(call Package/zoneinfo/Default)
+ TITLE:=Zone Information (core)
+endef
+
+define Package/zoneinfo-simple
+$(call Package/zoneinfo/Default)
+ TITLE:=Zone Information (simple)
+endef
+
+define Package/zoneinfo-africa
+$(call Package/zoneinfo/Default)
+ TITLE:=Zone Information (Africa)
+endef
+
+define Package/zoneinfo-northamerica
+$(call Package/zoneinfo/Default)
+ TITLE:=Zone Information (NorthAmerica)
+endef
+
+define Package/zoneinfo-southamerica
+$(call Package/zoneinfo/Default)
+ TITLE:=Zone Information (SouthAmerica)
+endef
+
+define Package/zoneinfo-poles
+$(call Package/zoneinfo/Default)
+ TITLE:=Zone Information (Arctic, Antarctic)
+endef
+
+define Package/zoneinfo-asia
+$(call Package/zoneinfo/Default)
+ TITLE:=Zone Information (Asia)
+endef
+
+define Package/zoneinfo-atlantic
+$(call Package/zoneinfo/Default)
+ TITLE:=Zone Information (Atlantic)
+endef
+
+define Package/zoneinfo-australia-nz
+$(call Package/zoneinfo/Default)
+ TITLE:=Zone Information (Australia-NZ)
+endef
+
+define Package/zoneinfo-pacific
+$(call Package/zoneinfo/Default)
+ TITLE:=Zone Information (Pacific)
+endef
+
+define Package/zoneinfo-europe
+$(call Package/zoneinfo/Default)
+ TITLE:=Zone Information (Europe)
+endef
+
+define Package/zoneinfo-india
+$(call Package/zoneinfo/Default)
+ TITLE:=Zone Information (India)
+endef
+
+define Package/zoneinfo-all
+$(call Package/zoneinfo/Default)
+ TITLE:=Zone Information (all zones)
+ DEPENDS:= \
+ +zoneinfo-simple \
+ +zoneinfo-core \
+ +zoneinfo-africa \
+ +zoneinfo-northamerica \
+ +zoneinfo-southamerica \
+ +zoneinfo-poles \
+ +zoneinfo-asia \
+ +zoneinfo-atlantic \
+ +zoneinfo-australia-nz \
+ +zoneinfo-pacific \
+ +zoneinfo-europe \
+ +zoneinfo-india
+endef
+
+define Build/Prepare
+ (cd $(PKG_BUILD_DIR) && tar -xzf $(DL_DIR)/$(PKG_SOURCE_CODE) && tar -xzf $(DL_DIR)/$(PKG_SOURCE))
+endef
+
+define Build/Compile
+ CFLAGS="$(HOST_CFLAGS)" \
+ $(MAKE) -C $(PKG_BUILD_DIR) -f Makefile \
+ $(HOST_CONFIGURE_OPTS) \
+ CC="$(HOSTCC)" \
+ LD="\$$$$(CC)" \
+ CPPFLAGS="$(HOST_CPPFLAGS) -DHAVE_SNPRINTF=1 -DZIC_BLOAT_DEFAULT='\"fat\"'" \
+ LDFLAGS="$(HOST_LDFLAGS)" \
+ TOPDIR="$(PKG_INSTALL_DIR)" \
+ TZDIR="$(PKG_INSTALL_DIR)/zoneinfo" \
+ install
+endef
+
+define Package/zoneinfo-core/install
+ $(INSTALL_DIR) $(1)/usr/share/zoneinfo
+ for i in \
+ CET CST6CDT EET EST EST5EDT GB-Eire Eire \
+ GB GMT GMT+0 GMT-0 GMT0 Greenwich \
+ HST MET MST MST7MDT \
+ PRC PST8PDT ROC ROK UCT UTC \
+ Universal W-SU WET Zulu Etc/* zone.tab ; do \
+ $(CP) $(PKG_INSTALL_DIR)/zoneinfo/$$$$i \
+ $(1)/usr/share/zoneinfo ; \
+ done
+endef
+
+define Package/zoneinfo-simple/install
+ $(INSTALL_DIR) $(1)/usr/share/zoneinfo
+ for i in Pacific/Honolulu \
+ America/Anchorage America/Los_Angeles America/Denver \
+ America/Chicago America/New_York America/Caracas \
+ America/Sao_Paulo Europe/London Europe/Paris \
+ Africa/Cairo Europe/Moscow Asia/Dubai \
+ Asia/Karachi Asia/Dhaka Asia/Bangkok \
+ Asia/Hong_Kong Asia/Tokyo Australia/Darwin \
+ Australia/Adelaide Australia/Brisbane Australia/Sydney \
+ Australia/Perth Pacific/Noumea ; do \
+ $(CP) $(PKG_INSTALL_DIR)/zoneinfo/$$$$i \
+ $(1)/usr/share/zoneinfo ; \
+ done
+endef
+
+define Package/zoneinfo-africa/install
+ $(INSTALL_DIR) $(1)/usr/share/zoneinfo/Africa
+ $(CP) $(PKG_INSTALL_DIR)/zoneinfo/Africa/* \
+ $(1)/usr/share/zoneinfo/Africa
+endef
+
+define Package/zoneinfo-northamerica/install
+ $(INSTALL_DIR) $(1)/usr/share/zoneinfo
+ for i in US America Canada Mexico Cuba Jamaica Navajo ; do \
+ $(CP) $(PKG_INSTALL_DIR)/zoneinfo/$$$$i \
+ $(1)/usr/share/zoneinfo ; \
+ done
+ rm -rf $(1)/usr/share/zoneinfo/America/Argentina
+endef
+
+define Package/zoneinfo-southamerica/install
+ $(INSTALL_DIR) $(1)/usr/share/zoneinfo
+ for i in Brazil Chile ; do \
+ $(CP) $(PKG_INSTALL_DIR)/zoneinfo/$$$$i \
+ $(1)/usr/share/zoneinfo ; \
+ done
+ $(INSTALL_DIR) $(1)/usr/share/zoneinfo/America/Argentina
+ $(CP) $(PKG_INSTALL_DIR)/zoneinfo/America/Argentina/* \
+ $(1)/usr/share/zoneinfo/America/Argentina
+endef
+
+define Package/zoneinfo-poles/install
+ $(INSTALL_DIR) $(1)/usr/share/zoneinfo
+ for i in Antarctica Arctic ; do \
+ $(CP) $(PKG_INSTALL_DIR)/zoneinfo/$$$$i \
+ $(1)/usr/share/zoneinfo ; \
+ done
+endef
+
+define Package/zoneinfo-asia/install
+ $(INSTALL_DIR) $(1)/usr/share/zoneinfo
+ for i in Asia Japan Singapore Hongkong ; do \
+ $(CP) $(PKG_INSTALL_DIR)/zoneinfo/$$$$i \
+ $(1)/usr/share/zoneinfo ; \
+ done
+endef
+
+define Package/zoneinfo-atlantic/install
+ $(INSTALL_DIR) $(1)/usr/share/zoneinfo
+ for i in Atlantic Iceland ; do \
+ $(CP) $(PKG_INSTALL_DIR)/zoneinfo/$$$$i \
+ $(1)/usr/share/zoneinfo ; \
+ done
+endef
+
+define Package/zoneinfo-australia-nz/install
+ $(INSTALL_DIR) $(1)/usr/share/zoneinfo
+ for i in NZ NZ-CHAT Australia ; do \
+ $(CP) $(PKG_INSTALL_DIR)/zoneinfo/$$$$i \
+ $(1)/usr/share/zoneinfo ; \
+ done
+endef
+
+define Package/zoneinfo-pacific/install
+ $(INSTALL_DIR) $(1)/usr/share/zoneinfo
+ for i in Pacific Kwajalein ; do \
+ $(CP) $(PKG_INSTALL_DIR)/zoneinfo/$$$$i \
+ $(1)/usr/share/zoneinfo ; \
+ done
+endef
+
+define Package/zoneinfo-europe/install
+ $(INSTALL_DIR) $(1)/usr/share/zoneinfo
+ for i in Europe Portugal Poland ; do \
+ $(CP) $(PKG_INSTALL_DIR)/zoneinfo/$$$$i \
+ $(1)/usr/share/zoneinfo ; \
+ done
+endef
+
+define Package/zoneinfo-india/install
+ $(INSTALL_DIR) $(1)/usr/share/zoneinfo
+ for i in Indian ; do \
+ $(CP) $(PKG_INSTALL_DIR)/zoneinfo/$$$$i \
+ $(1)/usr/share/zoneinfo ; \
+ done
+endef
+
+$(eval $(call BuildPackage,zoneinfo-simple))
+$(eval $(call BuildPackage,zoneinfo-core))
+$(eval $(call BuildPackage,zoneinfo-africa))
+$(eval $(call BuildPackage,zoneinfo-northamerica))
+$(eval $(call BuildPackage,zoneinfo-southamerica))
+$(eval $(call BuildPackage,zoneinfo-poles))
+$(eval $(call BuildPackage,zoneinfo-asia))
+$(eval $(call BuildPackage,zoneinfo-atlantic))
+$(eval $(call BuildPackage,zoneinfo-australia-nz))
+$(eval $(call BuildPackage,zoneinfo-pacific))
+$(eval $(call BuildPackage,zoneinfo-europe))
+$(eval $(call BuildPackage,zoneinfo-india))
+$(eval $(call BuildPackage,zoneinfo-all))
diff --git a/external/subpack/utils/zsh/Makefile b/external/subpack/utils/zsh/Makefile
new file mode 100644
index 0000000..09bd7c9
--- /dev/null
+++ b/external/subpack/utils/zsh/Makefile
@@ -0,0 +1,120 @@
+#
+# Copyright (C) 2013-2016 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=zsh
+PKG_VERSION:=5.8
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@SF/zsh
+PKG_HASH:=dcc4b54cc5565670a65581760261c163d720991f0d06486da61f8d839b52de27
+
+PKG_MAINTAINER:=Vadim A. Misbakh-Soloviov <openwrt-zsh@mva.name>
+PKG_LICENSE:=ZSH
+PKG_LICENSE_FILES:=LICENCE
+PKG_CPE_ID:=cpe:/a:zsh_project:zsh
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/zsh
+ SECTION:=utils
+ CATEGORY:=Utilities
+ SUBMENU:=Shells
+ TITLE:=The Z shell
+ DEPENDS:=+libcap +libncurses +libncursesw +libpcre +librt
+ URL:=https://www.zsh.org/
+endef
+
+define Package/zsh/description
+ Zsh is a UNIX command interpreter (shell) usable as an interactive
+ login shell and as a shell script command processor. Of the standard
+ shells, zsh most closely resembles ksh but includes many enhancements.
+ Zsh has command line editing, builtin spelling correction, programmable
+ command completion, shell functions (with autoloading), a history
+ mechanism, and a host of other features.
+endef
+
+define Build/Configure
+ $(call Build/Configure/Default, \
+ --disable-etcdir \
+ --disable-gdbm \
+ $(if $(CONFIG_USE_MUSL),--enable-libc-musl) \
+ --enable-pcre \
+ --enable-cap \
+ --enable-multibyte \
+ --enable-unicode9 \
+ --enable-runhelpdir=$(CONFIGURE_PREFIX)/share/zsh/$(PKG_VERSION)/help \
+ --enable-fndir=$(CONFIGURE_PREFIX)/share/zsh/$(PKG_VERSION)/functions \
+ --enable-site-fndir=$(CONFIGURE_PREFIX)/share/zsh/site-functions \
+ --enable-function-subdirs \
+ --with-tcsetpgrp \
+ --with-term-lib="ncursesw", \
+ zsh_cv_shared_environ=yes \
+ zsh_cv_sys_dynamic_clash_ok=yes\
+ zsh_cv_sys_dynamic_execsyms=yes \
+ zsh_cv_sys_dynamic_rtld_global=yes \
+ zsh_cv_sys_dynamic_strip_exe=yes \
+ zsh_cv_sys_dynamic_strip_lib=yes \
+ zsh_cv_sys_nis=no \
+ zsh_cv_sys_nis_plus=no \
+ )
+ # Do not install these functions:
+ $(SED) 's, Completion/AIX/\*/\*,,g' $(PKG_BUILD_DIR)/config.modules
+ $(SED) 's, Completion/BSD/\*/\*,,g' $(PKG_BUILD_DIR)/config.modules
+ $(SED) 's, Completion/Cygwin/\*/\*,,g' $(PKG_BUILD_DIR)/config.modules
+ $(SED) 's, Completion/Darwin/\*/\*,,g' $(PKG_BUILD_DIR)/config.modules
+ $(SED) 's, Completion/Debian/\*/\*,,g' $(PKG_BUILD_DIR)/config.modules
+ $(SED) 's, Completion/Mandriva/\*/\*,,g' $(PKG_BUILD_DIR)/config.modules
+ $(SED) 's, Completion/Redhat/\*/\*,,g' $(PKG_BUILD_DIR)/config.modules
+ $(SED) 's, Completion/Solaris/\*/\*,,g' $(PKG_BUILD_DIR)/config.modules
+ $(SED) 's, Completion/X/\*/\*,,g' $(PKG_BUILD_DIR)/config.modules
+ $(SED) 's, Completion/openSUSE/\*/\*,,g' $(PKG_BUILD_DIR)/config.modules
+ # After mucking with 'config.modules', one must call
+ $(MAKE) -C $(PKG_BUILD_DIR) DESTDIR="$(PKG_INSTALL_DIR)" prep
+endef
+
+TARGET_CFLAGS += $(FPIC) -ffunction-sections -fdata-sections -flto
+TARGET_LDFLAGS += $(FPIC) -Wl,--gc-sections -flto
+
+define Package/zsh/postinst
+#!/bin/sh
+grep zsh $${IPKG_INSTROOT}/etc/shells || \
+ echo "/usr/bin/zsh" >> $${IPKG_INSTROOT}/etc/shells
+
+# Backwards compatibility
+if [ -e /bin/zsh ] && { [ ! -L /bin/zsh ] || [ "$(readlink -fn $${IPKG_INSTROOT}/bin/zsh)" != "../$(CONFIGURE_PREFIX)/bin/zsh" ]; }; then
+ ln -fs "../$(CONFIGURE_PREFIX)/bin/zsh" "$${IPKG_INSTROOT}/bin/zsh"
+fi
+endef
+
+define Package/zsh/install
+ $(INSTALL_DIR) $(1)/bin
+ $(INSTALL_DIR) $(1)/$(CONFIGURE_PREFIX)/bin
+ $(INSTALL_DIR) $(1)/$(CONFIGURE_PREFIX)/share/zsh/$(PKG_VERSION)
+ $(INSTALL_DIR) $(1)/$(CONFIGURE_PREFIX)/lib/zsh/$(PKG_VERSION)/zsh
+ $(INSTALL_DIR) $(1)/$(CONFIGURE_PREFIX)/lib/zsh/$(PKG_VERSION)/zsh/net
+ $(INSTALL_DIR) $(1)/$(CONFIGURE_PREFIX)/lib/zsh/$(PKG_VERSION)/zsh/param
+
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/$(CONFIGURE_PREFIX)/bin/zsh $(1)/$(CONFIGURE_PREFIX)/bin/
+ $(CP) $(PKG_INSTALL_DIR)/$(CONFIGURE_PREFIX)/share/zsh/$(PKG_VERSION)/* $(1)/$(CONFIGURE_PREFIX)/share/zsh/$(PKG_VERSION)/
+ $(CP) $(PKG_INSTALL_DIR)/$(CONFIGURE_PREFIX)/lib/zsh/$(PKG_VERSION)/zsh/* $(1)/$(CONFIGURE_PREFIX)/lib/zsh/$(PKG_VERSION)/zsh/
+ $(CP) $(PKG_INSTALL_DIR)/$(CONFIGURE_PREFIX)/lib/zsh/$(PKG_VERSION)/zsh/net/* $(1)/$(CONFIGURE_PREFIX)/lib/zsh/$(PKG_VERSION)/zsh/net/
+ $(CP) $(PKG_INSTALL_DIR)/$(CONFIGURE_PREFIX)/lib/zsh/$(PKG_VERSION)/zsh/param/* $(1)/$(CONFIGURE_PREFIX)/lib/zsh/$(PKG_VERSION)/zsh/param/
+endef
+
+define Package/zsh/postrm
+#!/bin/sh
+rm -rf "$${IPKG_INSTROOT}/$(CONFIGURE_PREFIX)/share/zsh/$(PKG_VERSION)" \
+ "$${IPKG_INSTROOT}/$(CONFIGURE_PREFIX)/lib/zsh/$(PKG_VERSION)"
+endef
+
+$(eval $(call BuildPackage,zsh))
diff --git a/external/subpack/utils/zstd/Makefile b/external/subpack/utils/zstd/Makefile
new file mode 100644
index 0000000..efca24c
--- /dev/null
+++ b/external/subpack/utils/zstd/Makefile
@@ -0,0 +1,92 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=zstd
+PKG_VERSION:=1.5.6
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/facebook/zstd/releases/download/v$(PKG_VERSION)
+PKG_HASH:=8c29e06cf42aacc1eafc4077ae2ec6c6fcb96a626157e0593d5e82a34fd403c1
+
+PKG_MAINTAINER:=Aleksey Vasilenko <aleksey.vasilenko@gmail.com>
+PKG_LICENSE:=GPL-2.0-or-later
+PKG_LICENSE_FILES:=COPYING
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/meson.mk
+
+MESON_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/build/meson/openwrt-build
+
+define Package/zstd/Default
+ SUBMENU:=Compression
+ URL:=https://github.com/facebook/zstd
+endef
+
+define Package/libzstd
+$(call Package/zstd/Default)
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE:=zstd library.
+ MENU:=1
+endef
+
+define Package/libzstd/description
+ Zstandard - Fast real-time compression algorithm.
+ This package provides libzstd library.
+endef
+
+define Package/libzstd/config
+ config ZSTD_OPTIMIZE_O3
+ bool "Use all optimizations (-O3)"
+ depends on PACKAGE_libzstd
+ default y
+ help
+ This enables additional optmizations using the -O3 compilation flag.
+endef
+
+define Package/zstd
+$(call Package/zstd/Default)
+ SECTION:=utils
+ CATEGORY:=Utilities
+ DEPENDS:=+libzstd
+ TITLE:=Fast real-time compression algorithm.
+endef
+
+define Package/zstd/description
+ Zstandard - Fast real-time compression algorithm.
+ This package provides the zstd binaries.
+endef
+
+ifeq ($(CONFIG_ZSTD_OPTIMIZE_O3),y)
+TARGET_CFLAGS:= $(filter-out -O%,$(TARGET_CFLAGS)) -O3
+endif
+
+MESON_ARGS += \
+ -Dlegacy_level=7 \
+ -Ddebug_level=0 \
+ -Dzlib=disabled \
+ -Dlzma=disabled \
+ -Dlz4=disabled \
+ -Db_lto=true
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/*.h $(1)/usr/include
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libzstd.so* $(1)/usr/lib
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libzstd.pc $(1)/usr/lib/pkgconfig
+endef
+
+define Package/libzstd/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libzstd.so* $(1)/usr/lib
+endef
+
+define Package/zstd/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/{unzstd,zstd,zstdcat,zstdgrep,zstdless,zstdmt} $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,libzstd))
+$(eval $(call BuildPackage,zstd))