diff options
Diffstat (limited to 'package/utils')
154 files changed, 39465 insertions, 0 deletions
diff --git a/package/utils/admswconfig/Makefile b/package/utils/admswconfig/Makefile new file mode 100644 index 0000000..820f854 --- /dev/null +++ b/package/utils/admswconfig/Makefile @@ -0,0 +1,52 @@ +# +# Copyright (C) 2007 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:=admswconfig +PKG_VERSION:=0.1 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://downloads.openwrt.org/sources +PKG_MD5SUM:=faafd4618f970119a665b11b21ac6a26 + +include $(INCLUDE_DIR)/package.mk + +define Package/admswconfig + SECTION:=utils + CATEGORY:=Utilities + TITLE:=ADM5120 Switch configuration tool + DEPENDS:=@TARGET_adm5120 + URL:=http://sharon.esrac.ele.tue.nl/users/pe1rxq/linux-adm/admswconfig/ + MAINTAINER:=Florian Fainelli <florian@openwrt.org> +endef + +define Package/admswconfig/description + A program to configure the internal ethernet switch of an ADM5120 processor. + You need the corresponding driver for the switch in the kernel. + With this program you can configure which ports of the switch belong + to the different ethernet devices. +endef + +define Build/Configure +endef + +define Build/Compile + $(TARGET_CC) $(TARGET_CFLAGS) -Os $(PKG_BUILD_DIR)/admswconfig.c -o $(PKG_BUILD_DIR)/$(PKG_NAME) +endef + +define Package/admswconfig/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/admswconfig $(1)/sbin/ + $(INSTALL_DIR) $(1)/lib/network/ + $(INSTALL_DATA) ./files/admswswitch.sh $(1)/lib/network/admswswitch.sh + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/admswconfig $(1)/etc/init.d/admswconfig +endef + +$(eval $(call BuildPackage,admswconfig)) diff --git a/package/utils/admswconfig/files/admswconfig b/package/utils/admswconfig/files/admswconfig new file mode 100644 index 0000000..7231030 --- /dev/null +++ b/package/utils/admswconfig/files/admswconfig @@ -0,0 +1,68 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006 OpenWrt.org + +START=05 + +start() { + [ -e /etc/config/network ] && exit 0 + + mkdir -p /etc/config + + board_name=$(awk 'BEGIN{FS="[ \t]+:[ \t]"} /system type/ {print $2}' /proc/cpuinfo) + + case "$board_name" in + "Compex WP54"*) + board="Compex WP54";; + esac + + echo "$board" |awk ' + function p(cfgname, name) { + if (c[name] != "") print " option " cfgname " \"" c[name] "\"" + } + + BEGIN { + FS="=" + c["lan_ifname"]="eth0" + c["wan_ifname"]="eth1" + c["eth0ports"]="1 2 3 4" + c["eth1ports"]="0" + } + END { + board=$1 + if (board == "Compex WP54") { + c["eth0ports"]="0" + c["eth1ports"]="1" + } + + print "#### VLAN configuration " + print "config switch" + p("eth0", "eth0ports") + p("eth1", "eth1ports") + print "" + print "" + print "#### Loopback configuration" + print "config interface loopback" + print " option ifname \"lo\"" + print " option proto static" + print " option ipaddr 127.0.0.1" + print " option netmask 255.0.0.0" + print "" + print "" + print "#### LAN configuration" + print "config interface lan" + print " option type bridge" + p("ifname", "lan_ifname") + p("macaddr", "lan_macaddr") + print " option proto static" + print " option ipaddr 192.168.1.1" + print " option netmask 255.255.255.0" + print "" + print "" + print "#### WAN configuration" + print "config interface wan" + p("ifname", "wan_ifname") + p("macaddr", "wan_macaddr") + print " option proto dhcp" + }' > /etc/config/network +} + diff --git a/package/utils/admswconfig/files/admswswitch.sh b/package/utils/admswconfig/files/admswswitch.sh new file mode 100644 index 0000000..3b8aabf --- /dev/null +++ b/package/utils/admswconfig/files/admswswitch.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# Copyright (C) 2006 OpenWrt.org + +setup_switch_vlan() { + config_get ports "$CONFIG_SECTION" "eth$1" + ports=`echo "$ports"| sed s/" "/""/g` + ip link set dev eth$1 down + admswconfig eth$1 ${ports}c + ip link set dev eth$1 up +} + +setup_switch() { + config_cb() { + case "$1" in + switch) + option_cb() { + case "$1" in + eth*) setup_switch_vlan "${1##eth}";; + esac + } + ;; + *) + option_cb() { return 0; } + ;; + esac + } + config_load network +} diff --git a/package/utils/admswconfig/patches/001-matrix.patch b/package/utils/admswconfig/patches/001-matrix.patch new file mode 100644 index 0000000..e50d515 --- /dev/null +++ b/package/utils/admswconfig/patches/001-matrix.patch @@ -0,0 +1,15 @@ +--- a/admswconfig.c ++++ b/admswconfig.c +@@ -111,9 +111,9 @@ int main(int argc, char **argv) + } + } else { + /* display matrix */ +- printf("ethX\tport0\tport1\tport2\tport3\tport4"); +- if (info.ports == 6) +- printf("\tport5"); ++ printf("ethX"); ++ for (i = 0; i < info.ports; i++) ++ printf("\tport%d", i); + printf("\tCPU\n"); + for (i = 0; i < info.ports; i++) { + printf("%d", i); diff --git a/package/utils/admswconfig/patches/002-fix-musl.patch b/package/utils/admswconfig/patches/002-fix-musl.patch new file mode 100644 index 0000000..3dad1f9 --- /dev/null +++ b/package/utils/admswconfig/patches/002-fix-musl.patch @@ -0,0 +1,11 @@ +--- a/admswconfig.c ++++ b/admswconfig.c +@@ -68,7 +68,7 @@ int main(int argc, char **argv) + return 1; + } + strcpy(ifr.ifr_name, device); +- ifr.ifr_data = (caddr_t)&info; ++ ifr.ifr_data = (void *)&info; + if (ioctl(fd, SIOCGADMINFO, &ifr) < 0) { + perror("SIOCGADMINFO"); + return 1; diff --git a/package/utils/busybox/Config-defaults.in b/package/utils/busybox/Config-defaults.in new file mode 100644 index 0000000..5b77f93 --- /dev/null +++ b/package/utils/busybox/Config-defaults.in @@ -0,0 +1,2721 @@ +config BUSYBOX_DEFAULT_HAVE_DOT_CONFIG + bool + default y +config BUSYBOX_DEFAULT_DESKTOP + bool + default n +config BUSYBOX_DEFAULT_EXTRA_COMPAT + bool + default n +config BUSYBOX_DEFAULT_INCLUDE_SUSv2 + bool + default y +config BUSYBOX_DEFAULT_USE_PORTABLE_CODE + bool + default n +config BUSYBOX_DEFAULT_PLATFORM_LINUX + bool + default y +config BUSYBOX_DEFAULT_FEATURE_BUFFERS_USE_MALLOC + bool + default n +config BUSYBOX_DEFAULT_FEATURE_BUFFERS_GO_ON_STACK + bool + default y +config BUSYBOX_DEFAULT_FEATURE_BUFFERS_GO_IN_BSS + bool + default n +config BUSYBOX_DEFAULT_SHOW_USAGE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VERBOSE_USAGE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_COMPRESS_USAGE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_INSTALLER + bool + default n +config BUSYBOX_DEFAULT_INSTALL_NO_USR + bool + default n +config BUSYBOX_DEFAULT_LOCALE_SUPPORT + bool + default n +config BUSYBOX_DEFAULT_UNICODE_SUPPORT + bool + default n +config BUSYBOX_DEFAULT_UNICODE_USING_LOCALE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CHECK_UNICODE_IN_ENV + bool + default n +config BUSYBOX_DEFAULT_SUBST_WCHAR + int + default 0 +config BUSYBOX_DEFAULT_LAST_SUPPORTED_WCHAR + int + default 0 +config BUSYBOX_DEFAULT_UNICODE_COMBINING_WCHARS + bool + default n +config BUSYBOX_DEFAULT_UNICODE_WIDE_WCHARS + bool + default n +config BUSYBOX_DEFAULT_UNICODE_BIDI_SUPPORT + bool + default n +config BUSYBOX_DEFAULT_UNICODE_NEUTRAL_TABLE + bool + default n +config BUSYBOX_DEFAULT_UNICODE_PRESERVE_BROKEN + bool + default n +config BUSYBOX_DEFAULT_PAM + bool + default n +config BUSYBOX_DEFAULT_FEATURE_USE_SENDFILE + bool + default n +config BUSYBOX_DEFAULT_LONG_OPTS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_DEVPTS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_CLEAN_UP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_UTMP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_WTMP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_PIDFILE + bool + default y +config BUSYBOX_DEFAULT_PID_FILE_PATH + string + default "/var/run" +config BUSYBOX_DEFAULT_FEATURE_SUID + bool + default y +config BUSYBOX_DEFAULT_FEATURE_SUID_CONFIG + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SUID_CONFIG_QUIET + bool + default n +config BUSYBOX_DEFAULT_SELINUX + bool + default n +config BUSYBOX_DEFAULT_FEATURE_PREFER_APPLETS + bool + default y +config BUSYBOX_DEFAULT_BUSYBOX_EXEC_PATH + string + default "/proc/self/exe" +config BUSYBOX_DEFAULT_FEATURE_SYSLOG + bool + default y +config BUSYBOX_DEFAULT_FEATURE_HAVE_RPC + bool + default n +config BUSYBOX_DEFAULT_STATIC + bool + default n +config BUSYBOX_DEFAULT_PIE + bool + default n +config BUSYBOX_DEFAULT_NOMMU + bool + default n +config BUSYBOX_DEFAULT_BUILD_LIBBUSYBOX + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INDIVIDUAL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SHARED_BUSYBOX + bool + default n +config BUSYBOX_DEFAULT_LFS + bool + default y +config BUSYBOX_DEFAULT_CROSS_COMPILER_PREFIX + string + default "" +config BUSYBOX_DEFAULT_SYSROOT + string + default "" +config BUSYBOX_DEFAULT_EXTRA_CFLAGS + string + default "" +config BUSYBOX_DEFAULT_EXTRA_LDFLAGS + string + default "" +config BUSYBOX_DEFAULT_EXTRA_LDLIBS + string + default "" +config BUSYBOX_DEFAULT_DEBUG + bool + default n +config BUSYBOX_DEFAULT_DEBUG_PESSIMIZE + bool + default n +config BUSYBOX_DEFAULT_UNIT_TEST + bool + default n +config BUSYBOX_DEFAULT_WERROR + bool + default n +config BUSYBOX_DEFAULT_NO_DEBUG_LIB + bool + default y +config BUSYBOX_DEFAULT_DMALLOC + bool + default n +config BUSYBOX_DEFAULT_EFENCE + bool + default n +config BUSYBOX_DEFAULT_INSTALL_APPLET_SYMLINKS + bool + default y +config BUSYBOX_DEFAULT_INSTALL_APPLET_HARDLINKS + bool + default n +config BUSYBOX_DEFAULT_INSTALL_APPLET_SCRIPT_WRAPPERS + bool + default n +config BUSYBOX_DEFAULT_INSTALL_APPLET_DONT + bool + default n +config BUSYBOX_DEFAULT_INSTALL_SH_APPLET_SYMLINK + bool + default n +config BUSYBOX_DEFAULT_INSTALL_SH_APPLET_HARDLINK + bool + default n +config BUSYBOX_DEFAULT_INSTALL_SH_APPLET_SCRIPT_WRAPPER + bool + default n +config BUSYBOX_DEFAULT_PREFIX + string + default "./_install" +config BUSYBOX_DEFAULT_FEATURE_SYSTEMD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_RTMINMAX + bool + default n +config BUSYBOX_DEFAULT_PASSWORD_MINLEN + int + default 6 +config BUSYBOX_DEFAULT_MD5_SMALL + int + default 1 +config BUSYBOX_DEFAULT_SHA3_SMALL + int + default 1 +config BUSYBOX_DEFAULT_FEATURE_FAST_TOP + bool + default y +config BUSYBOX_DEFAULT_FEATURE_ETC_NETWORKS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_USE_TERMIOS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_EDITING + bool + default y +config BUSYBOX_DEFAULT_FEATURE_EDITING_MAX_LEN + int + default 512 +config BUSYBOX_DEFAULT_FEATURE_EDITING_VI + bool + default n +config BUSYBOX_DEFAULT_FEATURE_EDITING_HISTORY + int + default 256 +config BUSYBOX_DEFAULT_FEATURE_EDITING_SAVEHISTORY + bool + default n +config BUSYBOX_DEFAULT_FEATURE_EDITING_SAVE_ON_EXIT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_REVERSE_SEARCH + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TAB_COMPLETION + bool + default y +config BUSYBOX_DEFAULT_FEATURE_USERNAME_COMPLETION + bool + default n +config BUSYBOX_DEFAULT_FEATURE_EDITING_FANCY_PROMPT + bool + default y +config BUSYBOX_DEFAULT_FEATURE_EDITING_ASK_TERMINAL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_NON_POSIX_CP + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VERBOSE_CP_MESSAGE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_COPYBUF_KB + int + default 4 +config BUSYBOX_DEFAULT_FEATURE_SKIP_ROOTFS + bool + default n +config BUSYBOX_DEFAULT_MONOTONIC_SYSCALL + bool + default n +config BUSYBOX_DEFAULT_IOCTL_HEX2STR_ERROR + bool + default y +config BUSYBOX_DEFAULT_FEATURE_HWIB + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SEAMLESS_XZ + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SEAMLESS_LZMA + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SEAMLESS_BZ2 + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SEAMLESS_GZ + bool + default y +config BUSYBOX_DEFAULT_FEATURE_SEAMLESS_Z + bool + default n +config BUSYBOX_DEFAULT_AR + bool + default n +config BUSYBOX_DEFAULT_FEATURE_AR_LONG_FILENAMES + bool + default n +config BUSYBOX_DEFAULT_FEATURE_AR_CREATE + bool + default n +config BUSYBOX_DEFAULT_UNCOMPRESS + bool + default n +config BUSYBOX_DEFAULT_GUNZIP + bool + default y +config BUSYBOX_DEFAULT_BUNZIP2 + bool + default y +config BUSYBOX_DEFAULT_UNLZMA + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LZMA_FAST + bool + default n +config BUSYBOX_DEFAULT_LZMA + bool + default n +config BUSYBOX_DEFAULT_UNXZ + bool + default n +config BUSYBOX_DEFAULT_XZ + bool + default n +config BUSYBOX_DEFAULT_BZIP2 + bool + default n +config BUSYBOX_DEFAULT_CPIO + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CPIO_O + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CPIO_P + bool + default n +config BUSYBOX_DEFAULT_DPKG + bool + default n +config BUSYBOX_DEFAULT_DPKG_DEB + bool + default n +config BUSYBOX_DEFAULT_FEATURE_DPKG_DEB_EXTRACT_ONLY + bool + default n +config BUSYBOX_DEFAULT_GZIP + bool + default y +config BUSYBOX_DEFAULT_FEATURE_GZIP_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_GZIP_FAST + int + default 0 +config BUSYBOX_DEFAULT_LZOP + bool + default n +config BUSYBOX_DEFAULT_LZOP_COMPR_HIGH + bool + default n +config BUSYBOX_DEFAULT_RPM + bool + default n +config BUSYBOX_DEFAULT_RPM2CPIO + bool + default n +config BUSYBOX_DEFAULT_TAR + bool + default y +config BUSYBOX_DEFAULT_FEATURE_TAR_CREATE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_TAR_AUTODETECT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TAR_FROM + bool + default y +config BUSYBOX_DEFAULT_FEATURE_TAR_OLDGNU_COMPATIBILITY + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TAR_OLDSUN_COMPATIBILITY + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TAR_GNU_EXTENSIONS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_TAR_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TAR_TO_COMMAND + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TAR_UNAME_GNAME + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TAR_NOPRESERVE_TIME + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TAR_SELINUX + bool + default n +config BUSYBOX_DEFAULT_UNZIP + bool + default n +config BUSYBOX_DEFAULT_BASENAME + bool + default y +config BUSYBOX_DEFAULT_CAT + bool + default y +config BUSYBOX_DEFAULT_DATE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_DATE_ISOFMT + bool + default y +config BUSYBOX_DEFAULT_FEATURE_DATE_NANO + bool + default n +config BUSYBOX_DEFAULT_FEATURE_DATE_COMPAT + bool + default n +config BUSYBOX_DEFAULT_HOSTID + bool + default n +config BUSYBOX_DEFAULT_ID + bool + default y +config BUSYBOX_DEFAULT_GROUPS + bool + default n +config BUSYBOX_DEFAULT_SHUF + bool + default n +config BUSYBOX_DEFAULT_TEST + bool + default y +config BUSYBOX_DEFAULT_FEATURE_TEST_64 + bool + default y +config BUSYBOX_DEFAULT_TOUCH + bool + default y +config BUSYBOX_DEFAULT_FEATURE_TOUCH_NODEREF + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TOUCH_SUSV3 + bool + default y +config BUSYBOX_DEFAULT_TR + bool + default y +config BUSYBOX_DEFAULT_FEATURE_TR_CLASSES + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TR_EQUIV + bool + default n +config BUSYBOX_DEFAULT_UNLINK + bool + default n +config BUSYBOX_DEFAULT_BASE64 + bool + default n +config BUSYBOX_DEFAULT_WHO + bool + default n +config BUSYBOX_DEFAULT_USERS + bool + default n +config BUSYBOX_DEFAULT_CAL + bool + default n +config BUSYBOX_DEFAULT_CATV + bool + default n +config BUSYBOX_DEFAULT_CHGRP + bool + default y +config BUSYBOX_DEFAULT_CHMOD + bool + default y +config BUSYBOX_DEFAULT_CHOWN + bool + default y +config BUSYBOX_DEFAULT_FEATURE_CHOWN_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_CHROOT + bool + default y +config BUSYBOX_DEFAULT_CKSUM + bool + default n +config BUSYBOX_DEFAULT_COMM + bool + default n +config BUSYBOX_DEFAULT_CP + bool + default y +config BUSYBOX_DEFAULT_FEATURE_CP_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_CUT + bool + default y +config BUSYBOX_DEFAULT_DD + bool + default y +config BUSYBOX_DEFAULT_FEATURE_DD_SIGNAL_HANDLING + bool + default y +config BUSYBOX_DEFAULT_FEATURE_DD_THIRD_STATUS_LINE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_DD_IBS_OBS + bool + default y +config BUSYBOX_DEFAULT_DF + bool + default y +config BUSYBOX_DEFAULT_FEATURE_DF_FANCY + bool + default n +config BUSYBOX_DEFAULT_DIRNAME + bool + default y +config BUSYBOX_DEFAULT_DOS2UNIX + bool + default n +config BUSYBOX_DEFAULT_UNIX2DOS + bool + default n +config BUSYBOX_DEFAULT_DU + bool + default y +config BUSYBOX_DEFAULT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K + bool + default y +config BUSYBOX_DEFAULT_ECHO + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FANCY_ECHO + bool + default y +config BUSYBOX_DEFAULT_ENV + bool + default y +config BUSYBOX_DEFAULT_FEATURE_ENV_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_EXPAND + bool + default n +config BUSYBOX_DEFAULT_FEATURE_EXPAND_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_EXPR + bool + default y +config BUSYBOX_DEFAULT_EXPR_MATH_SUPPORT_64 + bool + default y +config BUSYBOX_DEFAULT_FALSE + bool + default y +config BUSYBOX_DEFAULT_FOLD + bool + default n +config BUSYBOX_DEFAULT_FSYNC + bool + default y +config BUSYBOX_DEFAULT_HEAD + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FANCY_HEAD + bool + default y +config BUSYBOX_DEFAULT_INSTALL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INSTALL_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_LN + bool + default y +config BUSYBOX_DEFAULT_LOGNAME + bool + default n +config BUSYBOX_DEFAULT_LS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_LS_FILETYPES + bool + default y +config BUSYBOX_DEFAULT_FEATURE_LS_FOLLOWLINKS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_LS_RECURSIVE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_LS_SORTFILES + bool + default y +config BUSYBOX_DEFAULT_FEATURE_LS_TIMESTAMPS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_LS_USERNAME + bool + default y +config BUSYBOX_DEFAULT_FEATURE_LS_COLOR + bool + default y +config BUSYBOX_DEFAULT_FEATURE_LS_COLOR_IS_DEFAULT + bool + default y +config BUSYBOX_DEFAULT_MD5SUM + bool + default y +config BUSYBOX_DEFAULT_MKDIR + bool + default y +config BUSYBOX_DEFAULT_FEATURE_MKDIR_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_MKFIFO + bool + default y +config BUSYBOX_DEFAULT_MKNOD + bool + default y +config BUSYBOX_DEFAULT_MV + bool + default y +config BUSYBOX_DEFAULT_FEATURE_MV_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_NICE + bool + default y +config BUSYBOX_DEFAULT_NOHUP + bool + default n +config BUSYBOX_DEFAULT_OD + bool + default n +config BUSYBOX_DEFAULT_PRINTENV + bool + default n +config BUSYBOX_DEFAULT_PRINTF + bool + default y +config BUSYBOX_DEFAULT_PWD + bool + default y +config BUSYBOX_DEFAULT_READLINK + bool + default y +config BUSYBOX_DEFAULT_FEATURE_READLINK_FOLLOW + bool + default y +config BUSYBOX_DEFAULT_REALPATH + bool + default n +config BUSYBOX_DEFAULT_RM + bool + default y +config BUSYBOX_DEFAULT_RMDIR + bool + default y +config BUSYBOX_DEFAULT_FEATURE_RMDIR_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_SEQ + bool + default y +config BUSYBOX_DEFAULT_SHA1SUM + bool + default n +config BUSYBOX_DEFAULT_SHA256SUM + bool + default n +config BUSYBOX_DEFAULT_SHA512SUM + bool + default n +config BUSYBOX_DEFAULT_SHA3SUM + bool + default n +config BUSYBOX_DEFAULT_SLEEP + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FANCY_SLEEP + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FLOAT_SLEEP + bool + default n +config BUSYBOX_DEFAULT_SORT + bool + default y +config BUSYBOX_DEFAULT_FEATURE_SORT_BIG + bool + default n +config BUSYBOX_DEFAULT_SPLIT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SPLIT_FANCY + bool + default n +config BUSYBOX_DEFAULT_STAT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_STAT_FORMAT + bool + default n +config BUSYBOX_DEFAULT_STTY + bool + default n +config BUSYBOX_DEFAULT_SUM + bool + default n +config BUSYBOX_DEFAULT_SYNC + bool + default y +config BUSYBOX_DEFAULT_TAC + bool + default n +config BUSYBOX_DEFAULT_TAIL + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FANCY_TAIL + bool + default y +config BUSYBOX_DEFAULT_TEE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_TEE_USE_BLOCK_IO + bool + default y +config BUSYBOX_DEFAULT_TRUE + bool + default y +config BUSYBOX_DEFAULT_TTY + bool + default n +config BUSYBOX_DEFAULT_UNAME + bool + default y +config BUSYBOX_DEFAULT_UNEXPAND + bool + default n +config BUSYBOX_DEFAULT_FEATURE_UNEXPAND_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_UNIQ + bool + default y +config BUSYBOX_DEFAULT_USLEEP + bool + default n +config BUSYBOX_DEFAULT_UUDECODE + bool + default n +config BUSYBOX_DEFAULT_UUENCODE + bool + default n +config BUSYBOX_DEFAULT_WC + bool + default y +config BUSYBOX_DEFAULT_FEATURE_WC_LARGE + bool + default n +config BUSYBOX_DEFAULT_WHOAMI + bool + default n +config BUSYBOX_DEFAULT_YES + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VERBOSE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_PRESERVE_HARDLINKS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_AUTOWIDTH + bool + default y +config BUSYBOX_DEFAULT_FEATURE_HUMAN_READABLE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_MD5_SHA1_SUM_CHECK + bool + default y +config BUSYBOX_DEFAULT_CHVT + bool + default n +config BUSYBOX_DEFAULT_FGCONSOLE + bool + default n +config BUSYBOX_DEFAULT_CLEAR + bool + default y +config BUSYBOX_DEFAULT_DEALLOCVT + bool + default n +config BUSYBOX_DEFAULT_DUMPKMAP + bool + default n +config BUSYBOX_DEFAULT_KBD_MODE + bool + default n +config BUSYBOX_DEFAULT_LOADFONT + bool + default n +config BUSYBOX_DEFAULT_LOADKMAP + bool + default n +config BUSYBOX_DEFAULT_OPENVT + bool + default n +config BUSYBOX_DEFAULT_RESET + bool + default y +config BUSYBOX_DEFAULT_RESIZE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_RESIZE_PRINT + bool + default n +config BUSYBOX_DEFAULT_SETCONSOLE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SETCONSOLE_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_SETFONT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SETFONT_TEXTUAL_MAP + bool + default n +config BUSYBOX_DEFAULT_DEFAULT_SETFONT_DIR + string + default "" +config BUSYBOX_DEFAULT_SETKEYCODES + bool + default n +config BUSYBOX_DEFAULT_SETLOGCONS + bool + default n +config BUSYBOX_DEFAULT_SHOWKEY + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LOADFONT_PSF2 + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LOADFONT_RAW + bool + default n +config BUSYBOX_DEFAULT_MKTEMP + bool + default y +config BUSYBOX_DEFAULT_PIPE_PROGRESS + bool + default n +config BUSYBOX_DEFAULT_RUN_PARTS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_RUN_PARTS_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_RUN_PARTS_FANCY + bool + default n +config BUSYBOX_DEFAULT_START_STOP_DAEMON + bool + default y +config BUSYBOX_DEFAULT_FEATURE_START_STOP_DAEMON_FANCY + bool + default n +config BUSYBOX_DEFAULT_FEATURE_START_STOP_DAEMON_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_WHICH + bool + default y +config BUSYBOX_DEFAULT_AWK + bool + default y +config BUSYBOX_DEFAULT_FEATURE_AWK_LIBM + bool + default y +config BUSYBOX_DEFAULT_FEATURE_AWK_GNU_EXTENSIONS + bool + default y +config BUSYBOX_DEFAULT_CMP + bool + default y +config BUSYBOX_DEFAULT_DIFF + bool + default n +config BUSYBOX_DEFAULT_FEATURE_DIFF_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_DIFF_DIR + bool + default n +config BUSYBOX_DEFAULT_ED + bool + default n +config BUSYBOX_DEFAULT_PATCH + bool + default n +config BUSYBOX_DEFAULT_SED + bool + default y +config BUSYBOX_DEFAULT_VI + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VI_MAX_LEN + int + default 1024 +config BUSYBOX_DEFAULT_FEATURE_VI_8BIT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VI_COLON + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VI_YANKMARK + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VI_SEARCH + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VI_REGEX_SEARCH + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VI_USE_SIGNALS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VI_DOT_CMD + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VI_READONLY + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VI_SETOPTS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VI_SET + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VI_WIN_RESIZE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VI_ASK_TERMINAL + bool + default y +config BUSYBOX_DEFAULT_FEATURE_VI_UNDO + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VI_UNDO_QUEUE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VI_UNDO_QUEUE_MAX + int + default 0 +config BUSYBOX_DEFAULT_FEATURE_ALLOW_EXEC + bool + default y +config BUSYBOX_DEFAULT_FIND + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_PRINT0 + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_MTIME + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_MMIN + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FIND_PERM + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_TYPE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_XDEV + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_MAXDEPTH + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_NEWER + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FIND_INUM + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FIND_EXEC + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_EXEC_PLUS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FIND_USER + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_GROUP + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_NOT + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_DEPTH + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_PAREN + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_SIZE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_PRUNE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_DELETE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FIND_PATH + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_REGEX + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FIND_CONTEXT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FIND_LINKS + bool + default n +config BUSYBOX_DEFAULT_GREP + bool + default y +config BUSYBOX_DEFAULT_FEATURE_GREP_EGREP_ALIAS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_GREP_FGREP_ALIAS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_GREP_CONTEXT + bool + default y +config BUSYBOX_DEFAULT_XARGS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_CONFIRMATION + bool + default y +config BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_QUOTES + bool + default y +config BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_TERMOPT + bool + default y +config BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_ZERO_TERM + bool + default y +config BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_REPL_STR + bool + default n +config BUSYBOX_DEFAULT_BOOTCHARTD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_BOOTCHARTD_BLOATED_HEADER + bool + default n +config BUSYBOX_DEFAULT_FEATURE_BOOTCHARTD_CONFIG_FILE + bool + default n +config BUSYBOX_DEFAULT_HALT + bool + default y +config BUSYBOX_DEFAULT_FEATURE_CALL_TELINIT + bool + default n +config BUSYBOX_DEFAULT_TELINIT_PATH + string + default "" +config BUSYBOX_DEFAULT_INIT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_USE_INITTAB + bool + default n +config BUSYBOX_DEFAULT_FEATURE_KILL_REMOVED + bool + default n +config BUSYBOX_DEFAULT_FEATURE_KILL_DELAY + int + default 0 +config BUSYBOX_DEFAULT_FEATURE_INIT_SCTTY + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INIT_SYSLOG + bool + default n +config BUSYBOX_DEFAULT_FEATURE_EXTRA_QUIET + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INIT_COREDUMPS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INITRD + bool + default n +config BUSYBOX_DEFAULT_INIT_TERMINAL_TYPE + string + default "" +config BUSYBOX_DEFAULT_MESG + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MESG_ENABLE_ONLY_GROUP + bool + default n +config BUSYBOX_DEFAULT_ADD_SHELL + bool + default n +config BUSYBOX_DEFAULT_REMOVE_SHELL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SHADOWPASSWDS + bool + default y +config BUSYBOX_DEFAULT_USE_BB_PWD_GRP + bool + default n +config BUSYBOX_DEFAULT_USE_BB_SHADOW + bool + default n +config BUSYBOX_DEFAULT_USE_BB_CRYPT + bool + default n +config BUSYBOX_DEFAULT_USE_BB_CRYPT_SHA + bool + default n +config BUSYBOX_DEFAULT_ADDUSER + bool + default n +config BUSYBOX_DEFAULT_FEATURE_ADDUSER_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CHECK_NAMES + bool + default n +config BUSYBOX_DEFAULT_LAST_ID + int + default 0 +config BUSYBOX_DEFAULT_FIRST_SYSTEM_ID + int + default 0 +config BUSYBOX_DEFAULT_LAST_SYSTEM_ID + int + default 0 +config BUSYBOX_DEFAULT_ADDGROUP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_ADDGROUP_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_ADDUSER_TO_GROUP + bool + default n +config BUSYBOX_DEFAULT_DELUSER + bool + default n +config BUSYBOX_DEFAULT_DELGROUP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_DEL_USER_FROM_GROUP + bool + default n +config BUSYBOX_DEFAULT_GETTY + bool + default n +config BUSYBOX_DEFAULT_LOGIN + bool + default n +config BUSYBOX_DEFAULT_LOGIN_SESSION_AS_CHILD + bool + default n +config BUSYBOX_DEFAULT_LOGIN_SCRIPTS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_NOLOGIN + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SECURETTY + bool + default n +config BUSYBOX_DEFAULT_PASSWD + bool + default y +config BUSYBOX_DEFAULT_FEATURE_PASSWD_WEAK_CHECK + bool + default y +config BUSYBOX_DEFAULT_CRYPTPW + bool + default n +config BUSYBOX_DEFAULT_CHPASSWD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_DEFAULT_PASSWD_ALGO + string + default "md5" +config BUSYBOX_DEFAULT_SU + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SU_SYSLOG + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SU_CHECKS_SHELLS + bool + default n +config BUSYBOX_DEFAULT_SULOGIN + bool + default n +config BUSYBOX_DEFAULT_VLOCK + bool + default n +config BUSYBOX_DEFAULT_CHATTR + bool + default n +config BUSYBOX_DEFAULT_FSCK + bool + default n +config BUSYBOX_DEFAULT_LSATTR + bool + default n +config BUSYBOX_DEFAULT_TUNE2FS + bool + default n +config BUSYBOX_DEFAULT_MODINFO + bool + default n +config BUSYBOX_DEFAULT_MODPROBE_SMALL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED + bool + default n +config BUSYBOX_DEFAULT_INSMOD + bool + default n +config BUSYBOX_DEFAULT_RMMOD + bool + default n +config BUSYBOX_DEFAULT_LSMOD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LSMOD_PRETTY_2_6_OUTPUT + bool + default n +config BUSYBOX_DEFAULT_MODPROBE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MODPROBE_BLACKLIST + bool + default n +config BUSYBOX_DEFAULT_DEPMOD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_2_4_MODULES + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INSMOD_TRY_MMAP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INSMOD_VERSION_CHECKING + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INSMOD_KSYMOOPS_SYMBOLS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INSMOD_LOADINKMEM + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INSMOD_LOAD_MAP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INSMOD_LOAD_MAP_FULL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CHECK_TAINTED_MODULE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MODUTILS_ALIAS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MODUTILS_SYMBOLS + bool + default n +config BUSYBOX_DEFAULT_DEFAULT_MODULES_DIR + string + default "" +config BUSYBOX_DEFAULT_DEFAULT_DEPMOD_FILE + string + default "" +config BUSYBOX_DEFAULT_BLOCKDEV + bool + default n +config BUSYBOX_DEFAULT_FATATTR + bool + default n +config BUSYBOX_DEFAULT_FSTRIM + bool + default n +config BUSYBOX_DEFAULT_MDEV + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MDEV_CONF + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MDEV_RENAME + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MDEV_RENAME_REGEXP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MDEV_EXEC + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MDEV_LOAD_FIRMWARE + bool + default n +config BUSYBOX_DEFAULT_REV + bool + default n +config BUSYBOX_DEFAULT_ACPID + bool + default n +config BUSYBOX_DEFAULT_FEATURE_ACPID_COMPAT + bool + default n +config BUSYBOX_DEFAULT_BLKID + bool + default n +config BUSYBOX_DEFAULT_FEATURE_BLKID_TYPE + bool + default n +config BUSYBOX_DEFAULT_DMESG + bool + default y +config BUSYBOX_DEFAULT_FEATURE_DMESG_PRETTY + bool + default y +config BUSYBOX_DEFAULT_FBSET + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FBSET_FANCY + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FBSET_READMODE + bool + default n +config BUSYBOX_DEFAULT_FDFLUSH + bool + default n +config BUSYBOX_DEFAULT_FDFORMAT + bool + default n +config BUSYBOX_DEFAULT_FDISK + bool + default n +config BUSYBOX_DEFAULT_FDISK_SUPPORT_LARGE_DISKS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FDISK_WRITABLE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_AIX_LABEL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SGI_LABEL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SUN_LABEL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_OSF_LABEL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_GPT_LABEL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FDISK_ADVANCED + bool + default n +config BUSYBOX_DEFAULT_FINDFS + bool + default n +config BUSYBOX_DEFAULT_FLOCK + bool + default n +config BUSYBOX_DEFAULT_FREERAMDISK + bool + default n +config BUSYBOX_DEFAULT_FSCK_MINIX + bool + default n +config BUSYBOX_DEFAULT_MKFS_EXT2 + bool + default n +config BUSYBOX_DEFAULT_MKFS_MINIX + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MINIX2 + bool + default n +config BUSYBOX_DEFAULT_MKFS_REISER + bool + default n +config BUSYBOX_DEFAULT_MKFS_VFAT + bool + default n +config BUSYBOX_DEFAULT_GETOPT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_GETOPT_LONG + bool + default n +config BUSYBOX_DEFAULT_HEXDUMP + bool + default y +config BUSYBOX_DEFAULT_FEATURE_HEXDUMP_REVERSE + bool + default n +config BUSYBOX_DEFAULT_HD + bool + default n +config BUSYBOX_DEFAULT_HWCLOCK + bool + default y +config BUSYBOX_DEFAULT_FEATURE_HWCLOCK_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HWCLOCK_ADJTIME_FHS + bool + default n +config BUSYBOX_DEFAULT_IPCRM + bool + default n +config BUSYBOX_DEFAULT_IPCS + bool + default n +config BUSYBOX_DEFAULT_LOSETUP + bool + default n +config BUSYBOX_DEFAULT_LSPCI + bool + default n +config BUSYBOX_DEFAULT_LSUSB + bool + default n +config BUSYBOX_DEFAULT_MKSWAP + bool + default y +config BUSYBOX_DEFAULT_FEATURE_MKSWAP_UUID + bool + default n +config BUSYBOX_DEFAULT_MORE + bool + default n +config BUSYBOX_DEFAULT_MOUNT + bool + default y +config BUSYBOX_DEFAULT_FEATURE_MOUNT_FAKE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MOUNT_VERBOSE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MOUNT_HELPERS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_MOUNT_LABEL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MOUNT_NFS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MOUNT_CIFS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_MOUNT_FLAGS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_MOUNT_FSTAB + bool + default y +config BUSYBOX_DEFAULT_PIVOT_ROOT + bool + default y +config BUSYBOX_DEFAULT_RDATE + bool + default n +config BUSYBOX_DEFAULT_RDEV + bool + default n +config BUSYBOX_DEFAULT_READPROFILE + bool + default n +config BUSYBOX_DEFAULT_RTCWAKE + bool + default n +config BUSYBOX_DEFAULT_SCRIPT + bool + default n +config BUSYBOX_DEFAULT_SCRIPTREPLAY + bool + default n +config BUSYBOX_DEFAULT_SETARCH + bool + default n +config BUSYBOX_DEFAULT_SWAPONOFF + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SWAPON_DISCARD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SWAPON_PRI + bool + default n +config BUSYBOX_DEFAULT_SWITCH_ROOT + bool + default y +config BUSYBOX_DEFAULT_UMOUNT + bool + default y +config BUSYBOX_DEFAULT_FEATURE_UMOUNT_ALL + bool + default y +config BUSYBOX_DEFAULT_FEATURE_MOUNT_LOOP + bool + default y +config BUSYBOX_DEFAULT_FEATURE_MOUNT_LOOP_CREATE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MTAB_SUPPORT + bool + default n +config BUSYBOX_DEFAULT_VOLUMEID + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_BTRFS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_CRAMFS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EXFAT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EXT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_F2FS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_FAT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_HFS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_ISO9660 + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_JFS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LINUXRAID + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LINUXSWAP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LUKS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_NILFS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_NTFS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_OCFS2 + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_REISERFS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_ROMFS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_SQUASHFS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_SYSV + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_UDF + bool + default n +config BUSYBOX_DEFAULT_FEATURE_VOLUMEID_XFS + bool + default n +config BUSYBOX_DEFAULT_CONSPY + bool + default n +config BUSYBOX_DEFAULT_CROND + bool + default y +config BUSYBOX_DEFAULT_FEATURE_CROND_D + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CROND_CALL_SENDMAIL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CROND_DIR + string + default "/etc" +config BUSYBOX_DEFAULT_LESS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_LESS_MAXLINES + int + default 9999999 +config BUSYBOX_DEFAULT_FEATURE_LESS_BRACKETS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LESS_FLAGS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LESS_MARKS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LESS_REGEXP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LESS_WINCH + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LESS_ASK_TERMINAL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LESS_DASHCMD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LESS_LINENUMS + bool + default n +config BUSYBOX_DEFAULT_NANDWRITE + bool + default n +config BUSYBOX_DEFAULT_NANDDUMP + bool + default n +config BUSYBOX_DEFAULT_RFKILL + bool + default n +config BUSYBOX_DEFAULT_SETSERIAL + bool + default n +config BUSYBOX_DEFAULT_TASKSET + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TASKSET_FANCY + bool + default n +config BUSYBOX_DEFAULT_UBIATTACH + bool + default n +config BUSYBOX_DEFAULT_UBIDETACH + bool + default n +config BUSYBOX_DEFAULT_UBIMKVOL + bool + default n +config BUSYBOX_DEFAULT_UBIRMVOL + bool + default n +config BUSYBOX_DEFAULT_UBIRSVOL + bool + default n +config BUSYBOX_DEFAULT_UBIUPDATEVOL + bool + default n +config BUSYBOX_DEFAULT_WALL + bool + default n +config BUSYBOX_DEFAULT_ADJTIMEX + bool + default n +config BUSYBOX_DEFAULT_BBCONFIG + bool + default n +config BUSYBOX_DEFAULT_FEATURE_COMPRESS_BBCONFIG + bool + default n +config BUSYBOX_DEFAULT_BEEP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_BEEP_FREQ + int + default 0 +config BUSYBOX_DEFAULT_FEATURE_BEEP_LENGTH_MS + int + default 0 +config BUSYBOX_DEFAULT_CHAT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CHAT_NOFAIL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CHAT_TTY_HIFI + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CHAT_IMPLICIT_CR + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CHAT_SWALLOW_OPTS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CHAT_SEND_ESCAPES + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CHAT_VAR_ABORT_LEN + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CHAT_CLR_ABORT + bool + default n +config BUSYBOX_DEFAULT_CHRT + bool + default n +config BUSYBOX_DEFAULT_CRONTAB + bool + default y +config BUSYBOX_DEFAULT_DC + bool + default n +config BUSYBOX_DEFAULT_FEATURE_DC_LIBM + bool + default n +config BUSYBOX_DEFAULT_DEVFSD + bool + default n +config BUSYBOX_DEFAULT_DEVFSD_MODLOAD + bool + default n +config BUSYBOX_DEFAULT_DEVFSD_FG_NP + bool + default n +config BUSYBOX_DEFAULT_DEVFSD_VERBOSE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_DEVFS + bool + default n +config BUSYBOX_DEFAULT_DEVMEM + bool + default n +config BUSYBOX_DEFAULT_EJECT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_EJECT_SCSI + bool + default n +config BUSYBOX_DEFAULT_FBSPLASH + bool + default n +config BUSYBOX_DEFAULT_FLASHCP + bool + default n +config BUSYBOX_DEFAULT_FLASH_LOCK + bool + default n +config BUSYBOX_DEFAULT_FLASH_UNLOCK + bool + default n +config BUSYBOX_DEFAULT_FLASH_ERASEALL + bool + default n +config BUSYBOX_DEFAULT_IONICE + bool + default n +config BUSYBOX_DEFAULT_INOTIFYD + bool + default n +config BUSYBOX_DEFAULT_LAST + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LAST_SMALL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LAST_FANCY + bool + default n +config BUSYBOX_DEFAULT_HDPARM + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HDPARM_GET_IDENTITY + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_SCAN_HWIF + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_DRIVE_RESET + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_TRISTATE_HWIF + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_GETSET_DMA + bool + default n +config BUSYBOX_DEFAULT_LOCK + bool + default y +config BUSYBOX_DEFAULT_MAKEDEVS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MAKEDEVS_LEAF + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MAKEDEVS_TABLE + bool + default n +config BUSYBOX_DEFAULT_MAN + bool + default n +config BUSYBOX_DEFAULT_MICROCOM + bool + default n +config BUSYBOX_DEFAULT_MOUNTPOINT + bool + default n +config BUSYBOX_DEFAULT_MT + bool + default n +config BUSYBOX_DEFAULT_RAIDAUTORUN + bool + default n +config BUSYBOX_DEFAULT_READAHEAD + bool + default n +config BUSYBOX_DEFAULT_RUNLEVEL + bool + default n +config BUSYBOX_DEFAULT_RX + bool + default n +config BUSYBOX_DEFAULT_SETSID + bool + default n +config BUSYBOX_DEFAULT_STRINGS + bool + default y +config BUSYBOX_DEFAULT_TIME + bool + default y +config BUSYBOX_DEFAULT_TIMEOUT + bool + default n +config BUSYBOX_DEFAULT_TTYSIZE + bool + default n +config BUSYBOX_DEFAULT_VOLNAME + bool + default n +config BUSYBOX_DEFAULT_WATCHDOG + bool + default n +config BUSYBOX_DEFAULT_NAMEIF + bool + default n +config BUSYBOX_DEFAULT_FEATURE_NAMEIF_EXTENDED + bool + default n +config BUSYBOX_DEFAULT_NBDCLIENT + bool + default n +config BUSYBOX_DEFAULT_NC + bool + default y +config BUSYBOX_DEFAULT_NC_SERVER + bool + default n +config BUSYBOX_DEFAULT_NC_EXTRA + bool + default n +config BUSYBOX_DEFAULT_NC_110_COMPAT + bool + default n +config BUSYBOX_DEFAULT_PING + bool + default y +config BUSYBOX_DEFAULT_PING6 + bool + default y +config BUSYBOX_DEFAULT_FEATURE_FANCY_PING + bool + default y +config BUSYBOX_DEFAULT_WHOIS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IPV6 + bool + default y +config BUSYBOX_DEFAULT_FEATURE_UNIX_LOCAL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_PREFER_IPV4_ADDRESS + bool + default y +config BUSYBOX_DEFAULT_VERBOSE_RESOLUTION_ERRORS + bool + default y +config BUSYBOX_DEFAULT_ARP + bool + default n +config BUSYBOX_DEFAULT_ARPING + bool + default n +config BUSYBOX_DEFAULT_BRCTL + bool + default y +config BUSYBOX_DEFAULT_FEATURE_BRCTL_FANCY + bool + default y +config BUSYBOX_DEFAULT_FEATURE_BRCTL_SHOW + bool + default y +config BUSYBOX_DEFAULT_DNSD + bool + default n +config BUSYBOX_DEFAULT_ETHER_WAKE + bool + default n +config BUSYBOX_DEFAULT_FAKEIDENTD + bool + default n +config BUSYBOX_DEFAULT_FTPD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FTP_WRITE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FTPD_ACCEPT_BROKEN_LIST + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FTP_AUTHENTICATION + bool + default n +config BUSYBOX_DEFAULT_FTPGET + bool + default n +config BUSYBOX_DEFAULT_FTPPUT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_FTPGETPUT_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_HOSTNAME + bool + default n +config BUSYBOX_DEFAULT_HTTPD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HTTPD_RANGES + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HTTPD_SETUID + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HTTPD_BASIC_AUTH + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HTTPD_AUTH_MD5 + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HTTPD_CGI + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HTTPD_ENCODE_URL_STR + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HTTPD_ERROR_PAGES + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HTTPD_PROXY + bool + default n +config BUSYBOX_DEFAULT_FEATURE_HTTPD_GZIP + bool + default n +config BUSYBOX_DEFAULT_IFCONFIG + bool + default y +config BUSYBOX_DEFAULT_FEATURE_IFCONFIG_STATUS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_IFCONFIG_SLIP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IFCONFIG_HW + bool + default y +config BUSYBOX_DEFAULT_FEATURE_IFCONFIG_BROADCAST_PLUS + bool + default y +config BUSYBOX_DEFAULT_IFENSLAVE + bool + default n +config BUSYBOX_DEFAULT_IFPLUGD + bool + default n +config BUSYBOX_DEFAULT_IFUPDOWN + bool + default n +config BUSYBOX_DEFAULT_IFUPDOWN_IFSTATE_PATH + string + default "" +config BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IP_BUILTIN + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IPV4 + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IPV6 + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_MAPPING + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_EXTERNAL_DHCP + bool + default n +config BUSYBOX_DEFAULT_INETD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_ECHO + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_TIME + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN + bool + default n +config BUSYBOX_DEFAULT_FEATURE_INETD_RPC + bool + default n +config BUSYBOX_DEFAULT_IP + bool + default y +config BUSYBOX_DEFAULT_FEATURE_IP_ADDRESS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_IP_LINK + bool + default y +config BUSYBOX_DEFAULT_FEATURE_IP_ROUTE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_IP_TUNNEL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IP_RULE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IP_SHORT_FORMS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IP_RARE_PROTOCOLS + bool + default n +config BUSYBOX_DEFAULT_IPADDR + bool + default n +config BUSYBOX_DEFAULT_IPLINK + bool + default n +config BUSYBOX_DEFAULT_IPROUTE + bool + default n +config BUSYBOX_DEFAULT_IPTUNNEL + bool + default n +config BUSYBOX_DEFAULT_IPRULE + bool + default n +config BUSYBOX_DEFAULT_IPCALC + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IPCALC_FANCY + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IPCALC_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_NETMSG + bool + default y +config BUSYBOX_DEFAULT_NETSTAT + bool + default y +config BUSYBOX_DEFAULT_FEATURE_NETSTAT_WIDE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_NETSTAT_PRG + bool + default y +config BUSYBOX_DEFAULT_NSLOOKUP + bool + default y +config BUSYBOX_DEFAULT_NTPD + bool + default y +config BUSYBOX_DEFAULT_FEATURE_NTPD_SERVER + bool + default y +config BUSYBOX_DEFAULT_FEATURE_NTPD_CONF + bool + default n +config BUSYBOX_DEFAULT_PSCAN + bool + default n +config BUSYBOX_DEFAULT_ROUTE + bool + default y +config BUSYBOX_DEFAULT_SLATTACH + bool + default n +config BUSYBOX_DEFAULT_TCPSVD + bool + default n +config BUSYBOX_DEFAULT_TELNET + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TELNET_TTYPE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TELNET_AUTOLOGIN + bool + default n +config BUSYBOX_DEFAULT_TELNETD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TELNETD_STANDALONE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TELNETD_INETD_WAIT + bool + default n +config BUSYBOX_DEFAULT_TFTP + bool + default n +config BUSYBOX_DEFAULT_TFTPD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TFTP_GET + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TFTP_PUT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TFTP_BLOCKSIZE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TFTP_PROGRESS_BAR + bool + default n +config BUSYBOX_DEFAULT_TFTP_DEBUG + bool + default n +config BUSYBOX_DEFAULT_TRACEROUTE + bool + default y +config BUSYBOX_DEFAULT_TRACEROUTE6 + bool + default y +config BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_VERBOSE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_SOURCE_ROUTE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_USE_ICMP + bool + default n +config BUSYBOX_DEFAULT_TUNCTL + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TUNCTL_UG + bool + default n +config BUSYBOX_DEFAULT_UDHCPC6 + bool + default n +config BUSYBOX_DEFAULT_UDHCPD + bool + default n +config BUSYBOX_DEFAULT_DHCPRELAY + bool + default n +config BUSYBOX_DEFAULT_DUMPLEASES + bool + default n +config BUSYBOX_DEFAULT_FEATURE_UDHCPD_WRITE_LEASES_EARLY + bool + default n +config BUSYBOX_DEFAULT_FEATURE_UDHCPD_BASE_IP_ON_MAC + bool + default n +config BUSYBOX_DEFAULT_DHCPD_LEASES_FILE + string + default "" +config BUSYBOX_DEFAULT_UDHCPC + bool + default y +config BUSYBOX_DEFAULT_FEATURE_UDHCPC_ARPING + bool + default n +config BUSYBOX_DEFAULT_FEATURE_UDHCPC_SANITIZEOPT + bool + default n +config BUSYBOX_DEFAULT_FEATURE_UDHCP_PORT + bool + default n +config BUSYBOX_DEFAULT_UDHCP_DEBUG + int + default 0 +config BUSYBOX_DEFAULT_FEATURE_UDHCP_RFC3397 + bool + default y +config BUSYBOX_DEFAULT_FEATURE_UDHCP_8021Q + bool + default n +config BUSYBOX_DEFAULT_UDHCPC_DEFAULT_SCRIPT + string + default "/usr/share/udhcpc/default.script" +config BUSYBOX_DEFAULT_UDHCPC_SLACK_FOR_BUGGY_SERVERS + int + default 80 +config BUSYBOX_DEFAULT_IFUPDOWN_UDHCPC_CMD_OPTIONS + string + default "" +config BUSYBOX_DEFAULT_UDPSVD + bool + default n +config BUSYBOX_DEFAULT_VCONFIG + bool + default n +config BUSYBOX_DEFAULT_WGET + bool + default y +config BUSYBOX_DEFAULT_FEATURE_WGET_STATUSBAR + bool + default y +config BUSYBOX_DEFAULT_FEATURE_WGET_AUTHENTICATION + bool + default y +config BUSYBOX_DEFAULT_FEATURE_WGET_LONG_OPTIONS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_WGET_TIMEOUT + bool + default n +config BUSYBOX_DEFAULT_ZCIP + bool + default n +config BUSYBOX_DEFAULT_LPD + bool + default n +config BUSYBOX_DEFAULT_LPR + bool + default n +config BUSYBOX_DEFAULT_LPQ + bool + default n +config BUSYBOX_DEFAULT_MAKEMIME + bool + default n +config BUSYBOX_DEFAULT_FEATURE_MIME_CHARSET + string + default "" +config BUSYBOX_DEFAULT_POPMAILDIR + bool + default n +config BUSYBOX_DEFAULT_FEATURE_POPMAILDIR_DELIVERY + bool + default n +config BUSYBOX_DEFAULT_REFORMIME + bool + default n +config BUSYBOX_DEFAULT_FEATURE_REFORMIME_COMPAT + bool + default n +config BUSYBOX_DEFAULT_SENDMAIL + bool + default n +config BUSYBOX_DEFAULT_IOSTAT + bool + default n +config BUSYBOX_DEFAULT_LSOF + bool + default n +config BUSYBOX_DEFAULT_MPSTAT + bool + default n +config BUSYBOX_DEFAULT_NMETER + bool + default n +config BUSYBOX_DEFAULT_PMAP + bool + default n +config BUSYBOX_DEFAULT_POWERTOP + bool + default n +config BUSYBOX_DEFAULT_PSTREE + bool + default n +config BUSYBOX_DEFAULT_PWDX + bool + default n +config BUSYBOX_DEFAULT_SMEMCAP + bool + default n +config BUSYBOX_DEFAULT_TOP + bool + default y +config BUSYBOX_DEFAULT_FEATURE_TOP_CPU_USAGE_PERCENTAGE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_TOP_CPU_GLOBAL_PERCENTS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_TOP_SMP_CPU + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TOP_DECIMALS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TOP_SMP_PROCESS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_TOPMEM + bool + default n +config BUSYBOX_DEFAULT_UPTIME + bool + default y +config BUSYBOX_DEFAULT_FEATURE_UPTIME_UTMP_SUPPORT + bool + default n +config BUSYBOX_DEFAULT_FREE + bool + default y +config BUSYBOX_DEFAULT_FUSER + bool + default n +config BUSYBOX_DEFAULT_KILL + bool + default y +config BUSYBOX_DEFAULT_KILLALL + bool + default y +config BUSYBOX_DEFAULT_KILLALL5 + bool + default n +config BUSYBOX_DEFAULT_PGREP + bool + default y +config BUSYBOX_DEFAULT_PIDOF + bool + default y +config BUSYBOX_DEFAULT_FEATURE_PIDOF_SINGLE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_PIDOF_OMIT + bool + default n +config BUSYBOX_DEFAULT_PKILL + bool + default n +config BUSYBOX_DEFAULT_PS + bool + default y +config BUSYBOX_DEFAULT_FEATURE_PS_WIDE + bool + default y +config BUSYBOX_DEFAULT_FEATURE_PS_LONG + bool + default n +config BUSYBOX_DEFAULT_FEATURE_PS_TIME + bool + default n +config BUSYBOX_DEFAULT_FEATURE_PS_ADDITIONAL_COLUMNS + bool + default n +config BUSYBOX_DEFAULT_FEATURE_PS_UNUSUAL_SYSTEMS + bool + default n +config BUSYBOX_DEFAULT_RENICE + bool + default n +config BUSYBOX_DEFAULT_BB_SYSCTL + bool + default y +config BUSYBOX_DEFAULT_FEATURE_SHOW_THREADS + bool + default n +config BUSYBOX_DEFAULT_WATCH + bool + default n +config BUSYBOX_DEFAULT_RUNSV + bool + default n +config BUSYBOX_DEFAULT_RUNSVDIR + bool + default n +config BUSYBOX_DEFAULT_FEATURE_RUNSVDIR_LOG + bool + default n +config BUSYBOX_DEFAULT_SV + bool + default n +config BUSYBOX_DEFAULT_SV_DEFAULT_SERVICE_DIR + string + default "" +config BUSYBOX_DEFAULT_SVLOGD + bool + default n +config BUSYBOX_DEFAULT_CHPST + bool + default n +config BUSYBOX_DEFAULT_SETUIDGID + bool + default n +config BUSYBOX_DEFAULT_ENVUIDGID + bool + default n +config BUSYBOX_DEFAULT_ENVDIR + bool + default n +config BUSYBOX_DEFAULT_SOFTLIMIT + bool + default n +config BUSYBOX_DEFAULT_CHCON + bool + default n +config BUSYBOX_DEFAULT_FEATURE_CHCON_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_GETENFORCE + bool + default n +config BUSYBOX_DEFAULT_GETSEBOOL + bool + default n +config BUSYBOX_DEFAULT_LOAD_POLICY + bool + default n +config BUSYBOX_DEFAULT_MATCHPATHCON + bool + default n +config BUSYBOX_DEFAULT_RESTORECON + bool + default n +config BUSYBOX_DEFAULT_RUNCON + bool + default n +config BUSYBOX_DEFAULT_FEATURE_RUNCON_LONG_OPTIONS + bool + default n +config BUSYBOX_DEFAULT_SELINUXENABLED + bool + default n +config BUSYBOX_DEFAULT_SETENFORCE + bool + default n +config BUSYBOX_DEFAULT_SETFILES + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SETFILES_CHECK_OPTION + bool + default n +config BUSYBOX_DEFAULT_SETSEBOOL + bool + default n +config BUSYBOX_DEFAULT_SESTATUS + bool + default n +config BUSYBOX_DEFAULT_ASH + bool + default y +config BUSYBOX_DEFAULT_ASH_BASH_COMPAT + bool + default y +config BUSYBOX_DEFAULT_ASH_IDLE_TIMEOUT + bool + default n +config BUSYBOX_DEFAULT_ASH_JOB_CONTROL + bool + default y +config BUSYBOX_DEFAULT_ASH_ALIAS + bool + default y +config BUSYBOX_DEFAULT_ASH_GETOPTS + bool + default y +config BUSYBOX_DEFAULT_ASH_BUILTIN_ECHO + bool + default y +config BUSYBOX_DEFAULT_ASH_BUILTIN_PRINTF + bool + default y +config BUSYBOX_DEFAULT_ASH_BUILTIN_TEST + bool + default y +config BUSYBOX_DEFAULT_ASH_HELP + bool + default n +config BUSYBOX_DEFAULT_ASH_CMDCMD + bool + default y +config BUSYBOX_DEFAULT_ASH_MAIL + bool + default n +config BUSYBOX_DEFAULT_ASH_OPTIMIZE_FOR_SIZE + bool + default n +config BUSYBOX_DEFAULT_ASH_RANDOM_SUPPORT + bool + default n +config BUSYBOX_DEFAULT_ASH_EXPAND_PRMT + bool + default y +config BUSYBOX_DEFAULT_CTTYHACK + bool + default n +config BUSYBOX_DEFAULT_HUSH + bool + default n +config BUSYBOX_DEFAULT_HUSH_BASH_COMPAT + bool + default n +config BUSYBOX_DEFAULT_HUSH_BRACE_EXPANSION + bool + default n +config BUSYBOX_DEFAULT_HUSH_HELP + bool + default n +config BUSYBOX_DEFAULT_HUSH_INTERACTIVE + bool + default n +config BUSYBOX_DEFAULT_HUSH_SAVEHISTORY + bool + default n +config BUSYBOX_DEFAULT_HUSH_JOB + bool + default n +config BUSYBOX_DEFAULT_HUSH_TICK + bool + default n +config BUSYBOX_DEFAULT_HUSH_IF + bool + default n +config BUSYBOX_DEFAULT_HUSH_LOOPS + bool + default n +config BUSYBOX_DEFAULT_HUSH_CASE + bool + default n +config BUSYBOX_DEFAULT_HUSH_FUNCTIONS + bool + default n +config BUSYBOX_DEFAULT_HUSH_LOCAL + bool + default n +config BUSYBOX_DEFAULT_HUSH_RANDOM_SUPPORT + bool + default n +config BUSYBOX_DEFAULT_HUSH_EXPORT_N + bool + default n +config BUSYBOX_DEFAULT_HUSH_MODE_X + bool + default n +config BUSYBOX_DEFAULT_MSH + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SH_IS_ASH + bool + default y +config BUSYBOX_DEFAULT_FEATURE_SH_IS_HUSH + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SH_IS_NONE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_BASH_IS_ASH + bool + default n +config BUSYBOX_DEFAULT_FEATURE_BASH_IS_HUSH + bool + default n +config BUSYBOX_DEFAULT_FEATURE_BASH_IS_NONE + bool + default y +config BUSYBOX_DEFAULT_SH_MATH_SUPPORT + bool + default y +config BUSYBOX_DEFAULT_SH_MATH_SUPPORT_64 + bool + default y +config BUSYBOX_DEFAULT_FEATURE_SH_EXTRA_QUIET + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SH_STANDALONE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SH_NOFORK + bool + default y +config BUSYBOX_DEFAULT_FEATURE_SH_HISTFILESIZE + bool + default n +config BUSYBOX_DEFAULT_SYSLOGD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_ROTATE_LOGFILE + bool + default n +config BUSYBOX_DEFAULT_FEATURE_REMOTE_LOG + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SYSLOGD_DUP + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SYSLOGD_CFG + bool + default n +config BUSYBOX_DEFAULT_FEATURE_SYSLOGD_READ_BUFFER_SIZE + int + default 0 +config BUSYBOX_DEFAULT_FEATURE_IPC_SYSLOG + bool + default n +config BUSYBOX_DEFAULT_FEATURE_IPC_SYSLOG_BUFFER_SIZE + int + default 0 +config BUSYBOX_DEFAULT_LOGREAD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_LOGREAD_REDUCED_LOCKING + bool + default n +config BUSYBOX_DEFAULT_FEATURE_KMSG_SYSLOG + bool + default n +config BUSYBOX_DEFAULT_KLOGD + bool + default n +config BUSYBOX_DEFAULT_FEATURE_KLOGD_KLOGCTL + bool + default n +config BUSYBOX_DEFAULT_LOGGER + bool + default y diff --git a/package/utils/busybox/Config.in b/package/utils/busybox/Config.in new file mode 100644 index 0000000..917e714 --- /dev/null +++ b/package/utils/busybox/Config.in @@ -0,0 +1,26 @@ +if PACKAGE_busybox + +config BUSYBOX_CUSTOM + bool "Customize busybox options" + default n + help + Enabling this allows full customization of busybox settings. + Note that there are many options here that can result in a build + that doesn't work properly. Enabling customization will mark your + build as "tainted" for the purpose of bug reports. + See the variables written to /etc/openwrt_release + + Unless you know what you are doing, you should leave this as 'n' + + source "Config-defaults.in" + + if BUSYBOX_CUSTOM + source "config/Config.in" + endif + +config BUSYBOX_USE_LIBRPC + bool + default y if BUSYBOX_CUSTOM && BUSYBOX_CONFIG_FEATURE_HAVE_RPC + default y if !BUSYBOX_CUSTOM && BUSYBOX_DEFAULT_FEATURE_HAVE_RPC + +endif diff --git a/package/utils/busybox/Makefile b/package/utils/busybox/Makefile new file mode 100644 index 0000000..5ca4363 --- /dev/null +++ b/package/utils/busybox/Makefile @@ -0,0 +1,118 @@ +# +# 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:=busybox +PKG_VERSION:=1.24.1 +PKG_RELEASE:=1 +PKG_FLAGS:=essential + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=http://www.busybox.net/downloads \ + http://distfiles.gentoo.org/distfiles/ +PKG_MD5SUM:=be98a40cadf84ce2d6b05fa41a275c6a + +PKG_BUILD_DEPENDS:=BUSYBOX_USE_LIBRPC:librpc BUSYBOX_CONFIG_PAM:libpam +PKG_BUILD_PARALLEL:=1 +PKG_CHECK_FORMAT_SECURITY:=0 + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=LICENSE archival/libarchive/bz/LICENSE + +include $(INCLUDE_DIR)/package.mk + +ifeq ($(DUMP),) + STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell $(SH_FUNC) grep '^CONFIG_BUSYBOX_' $(TOPDIR)/.config | md5s) +endif + +ifneq ($(findstring c,$(OPENWRT_VERBOSE)),) + BB_MAKE_VERBOSE := V=1 +else + BB_MAKE_VERBOSE := +endif + +define Package/busybox + SECTION:=base + CATEGORY:=Base system + MAINTAINER:=Felix Fietkau <nbd@openwrt.org> + TITLE:=Core utilities for embedded Linux + URL:=http://busybox.net/ + DEPENDS:=+BUSYBOX_USE_LIBRPC:librpc +BUSYBOX_CONFIG_PAM:libpam + MENU:=1 +endef + +define Package/busybox/description + The Swiss Army Knife of embedded Linux. + It slices, it dices, it makes Julian Fries. +endef + +define Package/busybox/config + source "$(SOURCE)/Config.in" +endef + +BUSYBOX_SYM=$(if $(CONFIG_BUSYBOX_CUSTOM),CONFIG,DEFAULT) + +define Build/Configure + rm -f $(PKG_BUILD_DIR)/.configured* + grep 'CONFIG_BUSYBOX_$(BUSYBOX_SYM)' $(TOPDIR)/.config | sed -e "s,\\(# \)\\?CONFIG_BUSYBOX_$(BUSYBOX_SYM)_\\(.*\\),\\1CONFIG_\\2,g" > $(PKG_BUILD_DIR)/.config + yes 'n' | $(MAKE) -C $(PKG_BUILD_DIR) \ + CC="$(TARGET_CC)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + KBUILD_HAVE_NLS=no \ + ARCH="$(ARCH)" \ + $(BB_MAKE_VERBOSE) \ + oldconfig +endef + +LDLIBS:=m crypt +ifdef CONFIG_BUSYBOX_USE_LIBRPC + TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include + export LDFLAGS=$(TARGET_LDFLAGS) + LDLIBS += rpc +endif + +ifdef CONFIG_BUSYBOX_CONFIG_PAM + TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include + export LDFLAGS=$(TARGET_LDFLAGS) + LDLIBS += pam pam_misc pthread +endif + +define Build/Compile + +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ + CC="$(TARGET_CC)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + KBUILD_HAVE_NLS=no \ + EXTRA_CFLAGS="$(TARGET_CFLAGS)" \ + ARCH="$(ARCH)" \ + SKIP_STRIP=y \ + LDLIBS="$(LDLIBS)" \ + $(BB_MAKE_VERBOSE) \ + all + rm -rf $(PKG_INSTALL_DIR) + $(FIND) $(PKG_BUILD_DIR) -lname "*busybox" -exec rm \{\} \; + $(MAKE) -C $(PKG_BUILD_DIR) \ + CC="$(TARGET_CC)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + EXTRA_CFLAGS="$(TARGET_CFLAGS)" \ + ARCH="$(ARCH)" \ + CONFIG_PREFIX="$(PKG_INSTALL_DIR)" \ + LDLIBS="$(LDLIBS)" \ + $(BB_MAKE_VERBOSE) \ + install +endef + +define Package/busybox/install + $(INSTALL_DIR) $(1)/etc/init.d + $(CP) $(PKG_INSTALL_DIR)/* $(1)/ + $(INSTALL_BIN) ./files/cron $(1)/etc/init.d/cron + $(INSTALL_BIN) ./files/sysntpd $(1)/etc/init.d/sysntpd + $(INSTALL_BIN) ./files/ntpd-hotplug $(1)/usr/sbin/ntpd-hotplug + -rm -rf $(1)/lib64 +endef + +$(eval $(call BuildPackage,busybox)) diff --git a/package/utils/busybox/config/Config.in b/package/utils/busybox/config/Config.in new file mode 100644 index 0000000..6a205f6 --- /dev/null +++ b/package/utils/busybox/config/Config.in @@ -0,0 +1,843 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + + +config BUSYBOX_CONFIG_HAVE_DOT_CONFIG + bool + default BUSYBOX_DEFAULT_HAVE_DOT_CONFIG + +menu "Busybox Settings" + +menu "General Configuration" + +config BUSYBOX_CONFIG_DESKTOP + bool "Enable options for full-blown desktop systems" + default BUSYBOX_DEFAULT_DESKTOP + help + Enable options and features which are not essential. + Select this only if you plan to use busybox on full-blown + desktop machine with common Linux distro, not on an embedded box. + +config BUSYBOX_CONFIG_EXTRA_COMPAT + bool "Provide compatible behavior for rare corner cases (bigger code)" + default BUSYBOX_DEFAULT_EXTRA_COMPAT + help + This option makes grep, sed etc handle rare corner cases + (embedded NUL bytes and such). This makes code bigger and uses + some GNU extensions in libc. You probably only need this option + if you plan to run busybox on desktop. + +config BUSYBOX_CONFIG_INCLUDE_SUSv2 + bool "Enable obsolete features removed before SUSv3" + default BUSYBOX_DEFAULT_INCLUDE_SUSv2 + help + This option will enable backwards compatibility with SuSv2, + specifically, old-style numeric options ('command -1 <file>') + will be supported in head, tail, and fold. (Note: should + affect renice too.) + +config BUSYBOX_CONFIG_USE_PORTABLE_CODE + bool "Avoid using GCC-specific code constructs" + default BUSYBOX_DEFAULT_USE_PORTABLE_CODE + help + Use this option if you are trying to compile busybox with + compiler other than gcc. + If you do use gcc, this option may needlessly increase code size. + +config BUSYBOX_CONFIG_PLATFORM_LINUX + bool "Enable Linux-specific applets and features" + default BUSYBOX_DEFAULT_PLATFORM_LINUX + help + For the most part, busybox requires only POSIX compatibility + from the target system, but some applets and features use + Linux-specific interfaces. + + Answering 'N' here will disable such applets and hide the + corresponding configuration options. + +choice + prompt "Buffer allocation policy" + default BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_ON_STACK + help + There are 3 ways BusyBox can handle buffer allocations: + - Use malloc. This costs code size for the call to xmalloc. + - Put them on stack. For some very small machines with limited stack + space, this can be deadly. For most folks, this works just fine. + - Put them in BSS. This works beautifully for computers with a real + MMU (and OS support), but wastes runtime RAM for uCLinux. This + behavior was the only one available for BusyBox versions 0.48 and + earlier. + +config BUSYBOX_CONFIG_FEATURE_BUFFERS_USE_MALLOC + bool "Allocate with Malloc" + +config BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_ON_STACK + bool "Allocate on the Stack" + +config BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_IN_BSS + bool "Allocate in the .bss section" + +endchoice + +config BUSYBOX_CONFIG_SHOW_USAGE + bool "Show applet usage messages" + default BUSYBOX_DEFAULT_SHOW_USAGE + help + Enabling this option, BusyBox applets will show terse help messages + when invoked with wrong arguments. + If you do not want to show any (helpful) usage message when + issuing wrong command syntax, you can say 'N' here, + saving approximately 7k. + +config BUSYBOX_CONFIG_FEATURE_VERBOSE_USAGE + bool "Show verbose applet usage messages" + default BUSYBOX_DEFAULT_FEATURE_VERBOSE_USAGE + depends on BUSYBOX_CONFIG_SHOW_USAGE + help + All BusyBox applets will show verbose help messages when + busybox is invoked with --help. This will add a lot of text to the + busybox binary. In the default configuration, this will add about + 13k, but it can add much more depending on your configuration. + +config BUSYBOX_CONFIG_FEATURE_COMPRESS_USAGE + bool "Store applet usage messages in compressed form" + default BUSYBOX_DEFAULT_FEATURE_COMPRESS_USAGE + depends on BUSYBOX_CONFIG_SHOW_USAGE + help + Store usage messages in .bz compressed form, uncompress them + on-the-fly when <applet> --help is called. + + If you have a really tiny busybox with few applets enabled (and + bunzip2 isn't one of them), the overhead of the decompressor might + be noticeable. Also, if you run executables directly from ROM + and have very little memory, this might not be a win. Otherwise, + you probably want this. + +config BUSYBOX_CONFIG_FEATURE_INSTALLER + bool "Support --install [-s] to install applet links at runtime" + default BUSYBOX_DEFAULT_FEATURE_INSTALLER + help + Enable 'busybox --install [-s]' support. This will allow you to use + busybox at runtime to create hard links or symlinks for all the + applets that are compiled into busybox. + +config BUSYBOX_CONFIG_INSTALL_NO_USR + bool "Don't use /usr" + default BUSYBOX_DEFAULT_INSTALL_NO_USR + help + Disable use of /usr. busybox --install and "make install" + will install applets only to /bin and /sbin, + never to /usr/bin or /usr/sbin. + +config BUSYBOX_CONFIG_LOCALE_SUPPORT + bool "Enable locale support (system needs locale for this to work)" + default BUSYBOX_DEFAULT_LOCALE_SUPPORT + help + Enable this if your system has locale support and you would like + busybox to support locale settings. + +config BUSYBOX_CONFIG_UNICODE_SUPPORT + bool "Support Unicode" + default BUSYBOX_DEFAULT_UNICODE_SUPPORT + help + This makes various applets aware that one byte is not + one character on screen. + + Busybox aims to eventually work correctly with Unicode displays. + Any older encodings are not guaranteed to work. + Probably by the time when busybox will be fully Unicode-clean, + other encodings will be mainly of historic interest. + +config BUSYBOX_CONFIG_UNICODE_USING_LOCALE + bool "Use libc routines for Unicode (else uses internal ones)" + default BUSYBOX_DEFAULT_UNICODE_USING_LOCALE + depends on BUSYBOX_CONFIG_UNICODE_SUPPORT && BUSYBOX_CONFIG_LOCALE_SUPPORT + help + With this option on, Unicode support is implemented using libc + routines. Otherwise, internal implementation is used. + Internal implementation is smaller. + +config BUSYBOX_CONFIG_FEATURE_CHECK_UNICODE_IN_ENV + bool "Check $LC_ALL, $LC_CTYPE and $LANG environment variables" + default BUSYBOX_DEFAULT_FEATURE_CHECK_UNICODE_IN_ENV + depends on BUSYBOX_CONFIG_UNICODE_SUPPORT && !BUSYBOX_CONFIG_UNICODE_USING_LOCALE + help + With this option on, Unicode support is activated + only if locale-related variables have the value of the form + "xxxx.utf8" + + Otherwise, Unicode support will be always enabled and active. + +config BUSYBOX_CONFIG_SUBST_WCHAR + int "Character code to substitute unprintable characters with" + depends on BUSYBOX_CONFIG_UNICODE_SUPPORT + default BUSYBOX_DEFAULT_SUBST_WCHAR + help + Typical values are 63 for '?' (works with any output device), + 30 for ASCII substitute control code, + 65533 (0xfffd) for Unicode replacement character. + +config BUSYBOX_CONFIG_LAST_SUPPORTED_WCHAR + int "Range of supported Unicode characters" + depends on BUSYBOX_CONFIG_UNICODE_SUPPORT + default BUSYBOX_DEFAULT_LAST_SUPPORTED_WCHAR + help + Any character with Unicode value bigger than this is assumed + to be non-printable on output device. Many applets replace + such chars with substitution character. + + The idea is that many valid printable Unicode chars are + nevertheless are not displayed correctly. Think about + combining charachers, double-wide hieroglyphs, obscure + characters in dozens of ancient scripts... + Many terminals, terminal emulators, xterms etc will fail + to handle them correctly. Choose the smallest value + which suits your needs. + + Typical values are: + 126 - ASCII only + 767 (0x2ff) - there are no combining chars in [0..767] range + (the range includes Latin 1, Latin Ext. A and B), + code is ~700 bytes smaller for this case. + 4351 (0x10ff) - there are no double-wide chars in [0..4351] range, + code is ~300 bytes smaller for this case. + 12799 (0x31ff) - nearly all non-ideographic characters are + available in [0..12799] range, including + East Asian scripts like katakana, hiragana, hangul, + bopomofo... + 0 - off, any valid printable Unicode character will be printed. + +config BUSYBOX_CONFIG_UNICODE_COMBINING_WCHARS + bool "Allow zero-width Unicode characters on output" + default BUSYBOX_DEFAULT_UNICODE_COMBINING_WCHARS + depends on BUSYBOX_CONFIG_UNICODE_SUPPORT + help + With this option off, any Unicode char with width of 0 + is substituted on output. + +config BUSYBOX_CONFIG_UNICODE_WIDE_WCHARS + bool "Allow wide Unicode characters on output" + default BUSYBOX_DEFAULT_UNICODE_WIDE_WCHARS + depends on BUSYBOX_CONFIG_UNICODE_SUPPORT + help + With this option off, any Unicode char with width > 1 + is substituted on output. + +config BUSYBOX_CONFIG_UNICODE_BIDI_SUPPORT + bool "Bidirectional character-aware line input" + default BUSYBOX_DEFAULT_UNICODE_BIDI_SUPPORT + depends on BUSYBOX_CONFIG_UNICODE_SUPPORT && !BUSYBOX_CONFIG_UNICODE_USING_LOCALE + help + With this option on, right-to-left Unicode characters + are treated differently on input (e.g. cursor movement). + +config BUSYBOX_CONFIG_UNICODE_NEUTRAL_TABLE + bool "In bidi input, support non-ASCII neutral chars too" + default BUSYBOX_DEFAULT_UNICODE_NEUTRAL_TABLE + depends on BUSYBOX_CONFIG_UNICODE_BIDI_SUPPORT + help + In most cases it's enough to treat only ASCII non-letters + (i.e. punctuation, numbers and space) as characters + with neutral directionality. + With this option on, more extensive (and bigger) table + of neutral chars will be used. + +config BUSYBOX_CONFIG_UNICODE_PRESERVE_BROKEN + bool "Make it possible to enter sequences of chars which are not Unicode" + default BUSYBOX_DEFAULT_UNICODE_PRESERVE_BROKEN + depends on BUSYBOX_CONFIG_UNICODE_SUPPORT + help + With this option on, on line-editing input (such as used by shells) + invalid UTF-8 bytes are not substituted with the selected + substitution character. + For example, this means that entering 'l', 's', ' ', 0xff, [Enter] + at shell prompt will list file named 0xff (single char name + with char value 255), not file named '?'. + +config BUSYBOX_CONFIG_PAM + bool "Support for PAM (Pluggable Authentication Modules)" + default BUSYBOX_DEFAULT_PAM + help + Use PAM in some busybox applets (currently login and httpd) instead + of direct access to password database. + +config BUSYBOX_CONFIG_FEATURE_USE_SENDFILE + bool "Use sendfile system call" + default BUSYBOX_DEFAULT_FEATURE_USE_SENDFILE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + When enabled, busybox will use the kernel sendfile() function + instead of read/write loops to copy data between file descriptors + (for example, cp command does this a lot). + If sendfile() doesn't work, copying code falls back to read/write + loop. sendfile() was originally implemented for faster I/O + from files to sockets, but since Linux 2.6.33 it was extended + to work for many more file types. + +config BUSYBOX_CONFIG_LONG_OPTS + bool "Support for --long-options" + default BUSYBOX_DEFAULT_LONG_OPTS + help + Enable this if you want busybox applets to use the gnu --long-option + style, in addition to single character -a -b -c style options. + +config BUSYBOX_CONFIG_FEATURE_DEVPTS + bool "Use the devpts filesystem for Unix98 PTYs" + default BUSYBOX_DEFAULT_FEATURE_DEVPTS + help + Enable if you want BusyBox to use Unix98 PTY support. If enabled, + busybox will use /dev/ptmx for the master side of the pseudoterminal + and /dev/pts/<number> for the slave side. Otherwise, BSD style + /dev/ttyp<number> will be used. To use this option, you should have + devpts mounted. + +config BUSYBOX_CONFIG_FEATURE_CLEAN_UP + bool "Clean up all memory before exiting (usually not needed)" + default BUSYBOX_DEFAULT_FEATURE_CLEAN_UP + help + As a size optimization, busybox normally exits without explicitly + freeing dynamically allocated memory or closing files. This saves + space since the OS will clean up for us, but it can confuse debuggers + like valgrind, which report tons of memory and resource leaks. + + Don't enable this unless you have a really good reason to clean + things up manually. + +config BUSYBOX_CONFIG_FEATURE_UTMP + bool "Support utmp file" + default BUSYBOX_DEFAULT_FEATURE_UTMP + help + The file /var/run/utmp is used to track who is currently logged in. + With this option on, certain applets (getty, login, telnetd etc) + will create and delete entries there. + "who" applet requires this option. + +config BUSYBOX_CONFIG_FEATURE_WTMP + bool "Support wtmp file" + default BUSYBOX_DEFAULT_FEATURE_WTMP + depends on BUSYBOX_CONFIG_FEATURE_UTMP + help + The file /var/run/wtmp is used to track when users have logged into + and logged out of the system. + With this option on, certain applets (getty, login, telnetd etc) + will append new entries there. + "last" applet requires this option. + +config BUSYBOX_CONFIG_FEATURE_PIDFILE + bool "Support writing pidfiles" + default BUSYBOX_DEFAULT_FEATURE_PIDFILE + help + This option makes some applets (e.g. crond, syslogd, inetd) write + a pidfile at the configured PID_FILE_PATH. It has no effect + on applets which require pidfiles to run. + +config BUSYBOX_CONFIG_PID_FILE_PATH + string "Path to directory for pidfile" + default BUSYBOX_DEFAULT_PID_FILE_PATH + depends on BUSYBOX_CONFIG_FEATURE_PIDFILE + help + This is the default path where pidfiles are created. Applets which + allow you to set the pidfile path on the command line will override + this value. The option has no effect on applets that require you to + specify a pidfile path. + +config BUSYBOX_CONFIG_FEATURE_SUID + bool "Support for SUID/SGID handling" + default BUSYBOX_DEFAULT_FEATURE_SUID + help + With this option you can install the busybox binary belonging + to root with the suid bit set, enabling some applets to perform + root-level operations even when run by ordinary users + (for example, mounting of user mounts in fstab needs this). + + Busybox will automatically drop privileges for applets + that don't need root access. + + If you are really paranoid and don't want to do this, build two + busybox binaries with different applets in them (and the appropriate + symlinks pointing to each binary), and only set the suid bit on the + one that needs it. + + The applets which require root rights (need suid bit or + to be run by root) and will refuse to execute otherwise: + crontab, login, passwd, su, vlock, wall. + + The applets which will use root rights if they have them + (via suid bit, or because run by root), but would try to work + without root right nevertheless: + findfs, ping[6], traceroute[6], mount. + + Note that if you DONT select this option, but DO make busybox + suid root, ALL applets will run under root, which is a huge + security hole (think "cp /some/file /etc/passwd"). + +config BUSYBOX_CONFIG_FEATURE_SUID_CONFIG + bool "Runtime SUID/SGID configuration via /etc/busybox.conf" + default BUSYBOX_DEFAULT_FEATURE_SUID_CONFIG + depends on BUSYBOX_CONFIG_FEATURE_SUID + help + Allow the SUID / SGID state of an applet to be determined at runtime + by checking /etc/busybox.conf. (This is sort of a poor man's sudo.) + The format of this file is as follows: + + APPLET = [Ssx-][Ssx-][x-] [USER.GROUP] + + s: USER or GROUP is allowed to execute APPLET. + APPLET will run under USER or GROUP + (reagardless of who's running it). + S: USER or GROUP is NOT allowed to execute APPLET. + APPLET will run under USER or GROUP. + This option is not very sensical. + x: USER/GROUP/others are allowed to execute APPLET. + No UID/GID change will be done when it is run. + -: USER/GROUP/others are not allowed to execute APPLET. + + An example might help: + + [SUID] + su = ssx root.0 # applet su can be run by anyone and runs with + # euid=0/egid=0 + su = ssx # exactly the same + + mount = sx- root.disk # applet mount can be run by root and members + # of group disk (but not anyone else) + # and runs with euid=0 (egid is not changed) + + cp = --- # disable applet cp for everyone + + The file has to be owned by user root, group root and has to be + writeable only by root: + (chown 0.0 /etc/busybox.conf; chmod 600 /etc/busybox.conf) + The busybox executable has to be owned by user root, group + root and has to be setuid root for this to work: + (chown 0.0 /bin/busybox; chmod 4755 /bin/busybox) + + Robert 'sandman' Griebl has more information here: + <url: http://www.softforge.de/bb/suid.html >. + +config BUSYBOX_CONFIG_FEATURE_SUID_CONFIG_QUIET + bool "Suppress warning message if /etc/busybox.conf is not readable" + default BUSYBOX_DEFAULT_FEATURE_SUID_CONFIG_QUIET + depends on BUSYBOX_CONFIG_FEATURE_SUID_CONFIG + help + /etc/busybox.conf should be readable by the user needing the SUID, + check this option to avoid users to be notified about missing + permissions. + +config BUSYBOX_CONFIG_SELINUX + bool "Support NSA Security Enhanced Linux" + default BUSYBOX_DEFAULT_SELINUX + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Enable support for SELinux in applets ls, ps, and id. Also provide + the option of compiling in SELinux applets. + + If you do not have a complete SELinux userland installed, this stuff + will not compile. Specifially, libselinux 1.28 or better is + directly required by busybox. If the installation is located in a + non-standard directory, provide it by invoking make as follows: + CFLAGS=-I<libselinux-include-path> \ + LDFLAGS=-L<libselinux-lib-path> \ + make + + Most people will leave this set to 'N'. + +config BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS + bool "exec prefers applets" + default BUSYBOX_DEFAULT_FEATURE_PREFER_APPLETS + help + This is an experimental option which directs applets about to + call 'exec' to try and find an applicable busybox applet before + searching the PATH. This is typically done by exec'ing + /proc/self/exe. + This may affect shell, find -exec, xargs and similar applets. + They will use applets even if /bin/<applet> -> busybox link + is missing (or is not a link to busybox). However, this causes + problems in chroot jails without mounted /proc and with ps/top + (command name can be shown as 'exe' for applets started this way). + +config BUSYBOX_CONFIG_BUSYBOX_EXEC_PATH + string "Path to BusyBox executable" + default BUSYBOX_DEFAULT_BUSYBOX_EXEC_PATH + help + When Busybox applets need to run other busybox applets, BusyBox + sometimes needs to exec() itself. When the /proc filesystem is + mounted, /proc/self/exe always points to the currently running + executable. If you haven't got /proc, set this to wherever you + want to run BusyBox from. + +# These are auto-selected by other options + +config BUSYBOX_CONFIG_FEATURE_SYSLOG + bool #No description makes it a hidden option + default BUSYBOX_DEFAULT_FEATURE_SYSLOG + #help + # This option is auto-selected when you select any applet which may + # send its output to syslog. You do not need to select it manually. + +config BUSYBOX_CONFIG_FEATURE_HAVE_RPC + bool #No description makes it a hidden option + default BUSYBOX_DEFAULT_FEATURE_HAVE_RPC + #help + # This is automatically selected if any of enabled applets need it. + # You do not need to select it manually. + +endmenu + +menu 'Build Options' + +config BUSYBOX_CONFIG_STATIC + bool "Build BusyBox as a static binary (no shared libs)" + default BUSYBOX_DEFAULT_STATIC + help + If you want to build a static BusyBox binary, which does not + use or require any shared libraries, then enable this option. + This can cause BusyBox to be considerably larger, so you should + leave this option false unless you have a good reason (i.e. + your target platform does not support shared libraries, or + you are building an initrd which doesn't need anything but + BusyBox, etc). + + Most people will leave this set to 'N'. + +config BUSYBOX_CONFIG_PIE + bool "Build BusyBox as a position independent executable" + default BUSYBOX_DEFAULT_PIE + depends on !BUSYBOX_CONFIG_STATIC + help + Hardened code option. PIE binaries are loaded at a different + address at each invocation. This has some overhead, + particularly on x86-32 which is short on registers. + + Most people will leave this set to 'N'. + +config BUSYBOX_CONFIG_NOMMU + bool "Force NOMMU build" + default BUSYBOX_DEFAULT_NOMMU + help + Busybox tries to detect whether architecture it is being + built against supports MMU or not. If this detection fails, + or if you want to build NOMMU version of busybox for testing, + you may force NOMMU build here. + + Most people will leave this set to 'N'. + +# PIE can be made to work with BUILD_LIBBUSYBOX, but currently +# build system does not support that +config BUSYBOX_CONFIG_BUILD_LIBBUSYBOX + bool "Build shared libbusybox" + default BUSYBOX_DEFAULT_BUILD_LIBBUSYBOX + depends on !BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS && !BUSYBOX_CONFIG_PIE && !BUSYBOX_CONFIG_STATIC + help + Build a shared library libbusybox.so.N.N.N which contains all + busybox code. + + This feature allows every applet to be built as a tiny + separate executable. Enabling it for "one big busybox binary" + approach serves no purpose and increases code size. + You should almost certainly say "no" to this. + +### config FEATURE_FULL_LIBBUSYBOX +### bool "Feature-complete libbusybox" +### default n if !FEATURE_SHARED_BUSYBOX +### depends on BUILD_LIBBUSYBOX +### help +### Build a libbusybox with the complete feature-set, disregarding +### the actually selected config. +### +### Normally, libbusybox will only contain the features which are +### used by busybox itself. If you plan to write a separate +### standalone application which uses libbusybox say 'Y'. +### +### Note: libbusybox is GPL, not LGPL, and exports no stable API that +### might act as a copyright barrier. We can and will modify the +### exported function set between releases (even minor version number +### changes), and happily break out-of-tree features. +### +### Say 'N' if in doubt. + +config BUSYBOX_CONFIG_FEATURE_INDIVIDUAL + bool "Produce a binary for each applet, linked against libbusybox" + default BUSYBOX_DEFAULT_FEATURE_INDIVIDUAL + depends on BUSYBOX_CONFIG_BUILD_LIBBUSYBOX + help + If your CPU architecture doesn't allow for sharing text/rodata + sections of running binaries, but allows for runtime dynamic + libraries, this option will allow you to reduce memory footprint + when you have many different applets running at once. + + If your CPU architecture allows for sharing text/rodata, + having single binary is more optimal. + + Each applet will be a tiny program, dynamically linked + against libbusybox.so.N.N.N. + + You need to have a working dynamic linker. + +config BUSYBOX_CONFIG_FEATURE_SHARED_BUSYBOX + bool "Produce additional busybox binary linked against libbusybox" + default BUSYBOX_DEFAULT_FEATURE_SHARED_BUSYBOX + depends on BUSYBOX_CONFIG_BUILD_LIBBUSYBOX + help + Build busybox, dynamically linked against libbusybox.so.N.N.N. + + You need to have a working dynamic linker. + +### config BUILD_AT_ONCE +### bool "Compile all sources at once" +### default n +### help +### Normally each source-file is compiled with one invocation of +### the compiler. +### If you set this option, all sources are compiled at once. +### This gives the compiler more opportunities to optimize which can +### result in smaller and/or faster binaries. +### +### Setting this option will consume alot of memory, e.g. if you +### enable all applets with all features, gcc uses more than 300MB +### RAM during compilation of busybox. +### +### This option is most likely only beneficial for newer compilers +### such as gcc-4.1 and above. +### +### Say 'N' unless you know what you are doing. + +config BUSYBOX_CONFIG_LFS + bool + default BUSYBOX_DEFAULT_LFS + help + If you want to build BusyBox with large file support, then enable + this option. This will have no effect if your kernel or your C + library lacks large file support for large files. Some of the + programs that can benefit from large file support include dd, gzip, + cp, mount, tar, and many others. If you want to access files larger + than 2 Gigabytes, enable this option. Otherwise, leave it set to 'N'. + +config BUSYBOX_CONFIG_CROSS_COMPILER_PREFIX + string "Cross Compiler prefix" + default BUSYBOX_DEFAULT_CROSS_COMPILER_PREFIX + help + If you want to build BusyBox with a cross compiler, then you + will need to set this to the cross-compiler prefix, for example, + "i386-uclibc-". + + Note that CROSS_COMPILE environment variable or + "make CROSS_COMPILE=xxx ..." will override this selection. + + Native builds leave this empty. + +config BUSYBOX_CONFIG_SYSROOT + string "Path to sysroot" + default BUSYBOX_DEFAULT_SYSROOT + help + If you want to build BusyBox with a cross compiler, then you + might also need to specify where /usr/include and /usr/lib + will be found. + + For example, BusyBox can be built against an installed + Android NDK, platform version 9, for ARM ABI with + + CONFIG_SYSROOT=/opt/android-ndk/platforms/android-9/arch-arm + + Native builds leave this empty. + +config BUSYBOX_CONFIG_EXTRA_CFLAGS + string "Additional CFLAGS" + default BUSYBOX_DEFAULT_EXTRA_CFLAGS + help + Additional CFLAGS to pass to the compiler verbatim. + +config BUSYBOX_CONFIG_EXTRA_LDFLAGS + string "Additional LDFLAGS" + default BUSYBOX_DEFAULT_EXTRA_LDFLAGS + help + Additional LDFLAGS to pass to the linker verbatim. + +config BUSYBOX_CONFIG_EXTRA_LDLIBS + string "Additional LDLIBS" + default BUSYBOX_DEFAULT_EXTRA_LDLIBS + help + Additional LDLIBS to pass to the linker with -l. + +endmenu + +menu 'Debugging Options' + +config BUSYBOX_CONFIG_DEBUG + bool "Build BusyBox with extra Debugging symbols" + default BUSYBOX_DEFAULT_DEBUG + help + Say Y here if you wish to examine BusyBox internals while applets are + running. This increases the size of the binary considerably, and + should only be used when doing development. If you are doing + development and want to debug BusyBox, answer Y. + + Most people should answer N. + +config BUSYBOX_CONFIG_DEBUG_PESSIMIZE + bool "Disable compiler optimizations" + default BUSYBOX_DEFAULT_DEBUG_PESSIMIZE + depends on BUSYBOX_CONFIG_DEBUG + help + The compiler's optimization of source code can eliminate and reorder + code, resulting in an executable that's hard to understand when + stepping through it with a debugger. This switches it off, resulting + in a much bigger executable that more closely matches the source + code. + +config BUSYBOX_CONFIG_UNIT_TEST + bool "Build unit tests" + default BUSYBOX_DEFAULT_UNIT_TEST + help + Say Y here if you want to build unit tests (both the framework and + test cases) as a Busybox applet. This results in bigger code, so you + probably don't want this option in production builds. + +config BUSYBOX_CONFIG_WERROR + bool "Abort compilation on any warning" + default BUSYBOX_DEFAULT_WERROR + help + Selecting this will add -Werror to gcc command line. + + Most people should answer N. + +choice + prompt "Additional debugging library" + default BUSYBOX_CONFIG_NO_DEBUG_LIB + help + Using an additional debugging library will make BusyBox become + considerable larger and will cause it to run more slowly. You + should always leave this option disabled for production use. + + dmalloc support: + ---------------- + This enables compiling with dmalloc ( http://dmalloc.com/ ) + which is an excellent public domain mem leak and malloc problem + detector. To enable dmalloc, before running busybox you will + want to properly set your environment, for example: + export DMALLOC_OPTIONS=debug=0x34f47d83,inter=100,log=logfile + The 'debug=' value is generated using the following command + dmalloc -p log-stats -p log-non-free -p log-bad-space \ + -p log-elapsed-time -p check-fence -p check-heap \ + -p check-lists -p check-blank -p check-funcs -p realloc-copy \ + -p allow-free-null + + Electric-fence support: + ----------------------- + This enables compiling with Electric-fence support. Electric + fence is another very useful malloc debugging library which uses + your computer's virtual memory hardware to detect illegal memory + accesses. This support will make BusyBox be considerable larger + and run slower, so you should leave this option disabled unless + you are hunting a hard to find memory problem. + + +config BUSYBOX_CONFIG_NO_DEBUG_LIB + bool "None" + +config BUSYBOX_CONFIG_DMALLOC + bool "Dmalloc" + +config BUSYBOX_CONFIG_EFENCE + bool "Electric-fence" + +endchoice + +endmenu + +menu 'Installation Options ("make install" behavior)' + +choice + prompt "What kind of applet links to install" + default BUSYBOX_CONFIG_INSTALL_APPLET_SYMLINKS + help + Choose what kind of links to applets are created by "make install". + +config BUSYBOX_CONFIG_INSTALL_APPLET_SYMLINKS + bool "as soft-links" + help + Install applets as soft-links to the busybox binary. This needs some + free inodes on the filesystem, but might help with filesystem + generators that can't cope with hard-links. + +config BUSYBOX_CONFIG_INSTALL_APPLET_HARDLINKS + bool "as hard-links" + help + Install applets as hard-links to the busybox binary. This might + count on a filesystem with few inodes. + +config BUSYBOX_CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS + bool "as script wrappers" + help + Install applets as script wrappers that call the busybox binary. + +config BUSYBOX_CONFIG_INSTALL_APPLET_DONT + bool "not installed" + help + Do not install applet links. Useful when you plan to use + busybox --install for installing links, or plan to use + a standalone shell and thus don't need applet links. + +endchoice + +choice + prompt "/bin/sh applet link" + default BUSYBOX_CONFIG_INSTALL_SH_APPLET_SYMLINK + depends on BUSYBOX_CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS + help + Choose how you install /bin/sh applet link. + +config BUSYBOX_CONFIG_INSTALL_SH_APPLET_SYMLINK + bool "as soft-link" + help + Install /bin/sh applet as soft-link to the busybox binary. + +config BUSYBOX_CONFIG_INSTALL_SH_APPLET_HARDLINK + bool "as hard-link" + help + Install /bin/sh applet as hard-link to the busybox binary. + +config BUSYBOX_CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER + bool "as script wrapper" + help + Install /bin/sh applet as script wrapper that calls + the busybox binary. + +endchoice + +config BUSYBOX_CONFIG_PREFIX + string "BusyBox installation prefix" + default BUSYBOX_DEFAULT_PREFIX + help + Define your directory to install BusyBox files/subdirs in. + +endmenu + +source package/utils/busybox/config/libbb/Config.in + +endmenu + +comment "Applets" + +source package/utils/busybox/config/archival/Config.in +source package/utils/busybox/config/coreutils/Config.in +source package/utils/busybox/config/console-tools/Config.in +source package/utils/busybox/config/debianutils/Config.in +source package/utils/busybox/config/editors/Config.in +source package/utils/busybox/config/findutils/Config.in +source package/utils/busybox/config/init/Config.in +source package/utils/busybox/config/loginutils/Config.in +source package/utils/busybox/config/e2fsprogs/Config.in +source package/utils/busybox/config/modutils/Config.in +source package/utils/busybox/config/util-linux/Config.in +source package/utils/busybox/config/miscutils/Config.in +source package/utils/busybox/config/networking/Config.in +source package/utils/busybox/config/printutils/Config.in +source package/utils/busybox/config/mailutils/Config.in +source package/utils/busybox/config/procps/Config.in +source package/utils/busybox/config/runit/Config.in +source package/utils/busybox/config/selinux/Config.in +source package/utils/busybox/config/shell/Config.in +source package/utils/busybox/config/sysklogd/Config.in diff --git a/package/utils/busybox/config/archival/Config.in b/package/utils/busybox/config/archival/Config.in new file mode 100644 index 0000000..e977bb4 --- /dev/null +++ b/package/utils/busybox/config/archival/Config.in @@ -0,0 +1,372 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Archival Utilities" + +config BUSYBOX_CONFIG_FEATURE_SEAMLESS_XZ + bool "Make tar, rpm, modprobe etc understand .xz data" + default BUSYBOX_DEFAULT_FEATURE_SEAMLESS_XZ + help + Make tar, rpm, modprobe etc understand .xz data. + +config BUSYBOX_CONFIG_FEATURE_SEAMLESS_LZMA + bool "Make tar, rpm, modprobe etc understand .lzma data" + default BUSYBOX_DEFAULT_FEATURE_SEAMLESS_LZMA + help + Make tar, rpm, modprobe etc understand .lzma data. + +config BUSYBOX_CONFIG_FEATURE_SEAMLESS_BZ2 + bool "Make tar, rpm, modprobe etc understand .bz2 data" + default BUSYBOX_DEFAULT_FEATURE_SEAMLESS_BZ2 + help + Make tar, rpm, modprobe etc understand .bz2 data. + +config BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ + bool "Make tar, rpm, modprobe etc understand .gz data" + default BUSYBOX_DEFAULT_FEATURE_SEAMLESS_GZ + help + Make tar, rpm, modprobe etc understand .gz data. + +config BUSYBOX_CONFIG_FEATURE_SEAMLESS_Z + bool "tar, rpm, modprobe etc understand .Z data" + default BUSYBOX_DEFAULT_FEATURE_SEAMLESS_Z + help + Make tar, rpm, modprobe etc understand .Z data. + +config BUSYBOX_CONFIG_AR + bool "ar" + default BUSYBOX_DEFAULT_AR # needs to be improved to be able to replace binutils ar + help + ar is an archival utility program used to create, modify, and + extract contents from archives. An archive is a single file holding + a collection of other files in a structure that makes it possible to + retrieve the original individual files (called archive members). + The original files' contents, mode (permissions), timestamp, owner, + and group are preserved in the archive, and can be restored on + extraction. + + The stored filename is limited to 15 characters. (for more information + see long filename support). + ar has 60 bytes of overheads for every stored file. + + This implementation of ar can extract archives, it cannot create or + modify them. + On an x86 system, the ar applet adds about 1K. + + Unless you have a specific application which requires ar, you should + probably say N here. + +config BUSYBOX_CONFIG_FEATURE_AR_LONG_FILENAMES + bool "Support for long filenames (not needed for debs)" + default BUSYBOX_DEFAULT_FEATURE_AR_LONG_FILENAMES + depends on BUSYBOX_CONFIG_AR + help + By default the ar format can only store the first 15 characters + of the filename, this option removes that limitation. + It supports the GNU ar long filename method which moves multiple long + filenames into a the data section of a new ar entry. + +config BUSYBOX_CONFIG_FEATURE_AR_CREATE + bool "Support archive creation" + default BUSYBOX_DEFAULT_FEATURE_AR_CREATE + depends on BUSYBOX_CONFIG_AR + help + This enables archive creation (-c and -r) with busybox ar. +config BUSYBOX_CONFIG_UNCOMPRESS + bool "uncompress" + default BUSYBOX_DEFAULT_UNCOMPRESS + help + uncompress is used to decompress archives created by compress. + Not much used anymore, replaced by gzip/gunzip. +config BUSYBOX_CONFIG_GUNZIP + bool "gunzip" + default BUSYBOX_DEFAULT_GUNZIP + help + gunzip is used to decompress archives created by gzip. + You can use the `-t' option to test the integrity of + an archive, without decompressing it. +config BUSYBOX_CONFIG_BUNZIP2 + bool "bunzip2" + default BUSYBOX_DEFAULT_BUNZIP2 + help + bunzip2 is a compression utility using the Burrows-Wheeler block + sorting text compression algorithm, and Huffman coding. Compression + is generally considerably better than that achieved by more + conventional LZ77/LZ78-based compressors, and approaches the + performance of the PPM family of statistical compressors. + + Unless you have a specific application which requires bunzip2, you + should probably say N here. +config BUSYBOX_CONFIG_UNLZMA + bool "unlzma" + default BUSYBOX_DEFAULT_UNLZMA + help + unlzma is a compression utility using the Lempel-Ziv-Markov chain + compression algorithm, and range coding. Compression + is generally considerably better than that achieved by the bzip2 + compressors. + + The BusyBox unlzma applet is limited to decompression only. + On an x86 system, this applet adds about 4K. + +config BUSYBOX_CONFIG_FEATURE_LZMA_FAST + bool "Optimize unlzma for speed" + default BUSYBOX_DEFAULT_FEATURE_LZMA_FAST + depends on BUSYBOX_CONFIG_UNLZMA + help + This option reduces decompression time by about 25% at the cost of + a 1K bigger binary. + +config BUSYBOX_CONFIG_LZMA + bool "Provide lzma alias which supports only unpacking" + default BUSYBOX_DEFAULT_LZMA + depends on BUSYBOX_CONFIG_UNLZMA + help + Enable this option if you want commands like "lzma -d" to work. + IOW: you'll get lzma applet, but it will always require -d option. +config BUSYBOX_CONFIG_UNXZ + bool "unxz" + default BUSYBOX_DEFAULT_UNXZ + help + unxz is a unlzma successor. + +config BUSYBOX_CONFIG_XZ + bool "Provide xz alias which supports only unpacking" + default BUSYBOX_DEFAULT_XZ + depends on BUSYBOX_CONFIG_UNXZ + help + Enable this option if you want commands like "xz -d" to work. + IOW: you'll get xz applet, but it will always require -d option. +config BUSYBOX_CONFIG_BZIP2 + bool "bzip2" + default BUSYBOX_DEFAULT_BZIP2 + help + bzip2 is a compression utility using the Burrows-Wheeler block + sorting text compression algorithm, and Huffman coding. Compression + is generally considerably better than that achieved by more + conventional LZ77/LZ78-based compressors, and approaches the + performance of the PPM family of statistical compressors. + + Unless you have a specific application which requires bzip2, you + should probably say N here. +config BUSYBOX_CONFIG_CPIO + bool "cpio" + default BUSYBOX_DEFAULT_CPIO + help + cpio is an archival utility program used to create, modify, and + extract contents from archives. + cpio has 110 bytes of overheads for every stored file. + + This implementation of cpio can extract cpio archives created in the + "newc" or "crc" format, it cannot create or modify them. + + Unless you have a specific application which requires cpio, you + should probably say N here. + +config BUSYBOX_CONFIG_FEATURE_CPIO_O + bool "Support for archive creation" + default BUSYBOX_DEFAULT_FEATURE_CPIO_O + depends on BUSYBOX_CONFIG_CPIO + help + This implementation of cpio can create cpio archives in the "newc" + format only. + +config BUSYBOX_CONFIG_FEATURE_CPIO_P + bool "Support for passthrough mode" + default BUSYBOX_DEFAULT_FEATURE_CPIO_P + depends on BUSYBOX_CONFIG_FEATURE_CPIO_O + help + Passthrough mode. Rarely used. +config BUSYBOX_CONFIG_DPKG + bool "dpkg" + default BUSYBOX_DEFAULT_DPKG + select BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ + help + dpkg is a medium-level tool to install, build, remove and manage + Debian packages. + + This implementation of dpkg has a number of limitations, + you should use the official dpkg if possible. +config BUSYBOX_CONFIG_DPKG_DEB + bool "dpkg_deb" + default BUSYBOX_DEFAULT_DPKG_DEB + select BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ + help + dpkg-deb unpacks and provides information about Debian archives. + + This implementation of dpkg-deb cannot pack archives. + + Unless you have a specific application which requires dpkg-deb, + say N here. + +config BUSYBOX_CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY + bool "Extract only (-x)" + default BUSYBOX_DEFAULT_FEATURE_DPKG_DEB_EXTRACT_ONLY + depends on BUSYBOX_CONFIG_DPKG_DEB + help + This reduces dpkg-deb to the equivalent of + "ar -p <deb> data.tar.gz | tar -zx". However it saves space as none + of the extra dpkg-deb, ar or tar options are needed, they are linked + to internally. +config BUSYBOX_CONFIG_GZIP + bool "gzip" + default BUSYBOX_DEFAULT_GZIP + help + gzip is used to compress files. + It's probably the most widely used UNIX compression program. + +config BUSYBOX_CONFIG_FEATURE_GZIP_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_GZIP_LONG_OPTIONS + depends on BUSYBOX_CONFIG_GZIP && BUSYBOX_CONFIG_LONG_OPTS + help + Enable use of long options, increases size by about 106 Bytes + +config BUSYBOX_CONFIG_GZIP_FAST + int "Trade memory for gzip speed (0:small,slow - 2:fast,big)" + default BUSYBOX_DEFAULT_GZIP_FAST + range 0 2 + depends on BUSYBOX_CONFIG_GZIP + help + Enable big memory options for gzip. + 0: small buffers, small hash-tables + 1: larger buffers, larger hash-tables + 2: larger buffers, largest hash-tables + Larger models may give slightly better compression +config BUSYBOX_CONFIG_LZOP + bool "lzop" + default BUSYBOX_DEFAULT_LZOP + help + Lzop compression/decompresion. + +config BUSYBOX_CONFIG_LZOP_COMPR_HIGH + bool "lzop compression levels 7,8,9 (not very useful)" + default BUSYBOX_DEFAULT_LZOP_COMPR_HIGH + depends on BUSYBOX_CONFIG_LZOP + help + High levels (7,8,9) of lzop compression. These levels + are actually slower than gzip at equivalent compression ratios + and take up 3.2K of code. +config BUSYBOX_CONFIG_RPM + bool "rpm" + default BUSYBOX_DEFAULT_RPM + help + Mini RPM applet - queries and extracts RPM packages. +config BUSYBOX_CONFIG_RPM2CPIO + bool "rpm2cpio" + default BUSYBOX_DEFAULT_RPM2CPIO + help + Converts a RPM file into a CPIO archive. +config BUSYBOX_CONFIG_TAR + bool "tar" + default BUSYBOX_DEFAULT_TAR + help + tar is an archiving program. It's commonly used with gzip to + create compressed archives. It's probably the most widely used + UNIX archive program. + +config BUSYBOX_CONFIG_FEATURE_TAR_CREATE + bool "Enable archive creation" + default BUSYBOX_DEFAULT_FEATURE_TAR_CREATE + depends on BUSYBOX_CONFIG_TAR + help + If you enable this option you'll be able to create + tar archives using the `-c' option. + +config BUSYBOX_CONFIG_FEATURE_TAR_AUTODETECT + bool "Autodetect compressed tarballs" + default BUSYBOX_DEFAULT_FEATURE_TAR_AUTODETECT + depends on BUSYBOX_CONFIG_TAR && (BUSYBOX_CONFIG_FEATURE_SEAMLESS_Z || BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ || BUSYBOX_CONFIG_FEATURE_SEAMLESS_BZ2 || BUSYBOX_CONFIG_FEATURE_SEAMLESS_LZMA || BUSYBOX_CONFIG_FEATURE_SEAMLESS_XZ) + help + With this option tar can automatically detect compressed + tarballs. Currently it works only on files (not pipes etc). + +config BUSYBOX_CONFIG_FEATURE_TAR_FROM + bool "Enable -X (exclude from) and -T (include from) options)" + default BUSYBOX_DEFAULT_FEATURE_TAR_FROM + depends on BUSYBOX_CONFIG_TAR + help + If you enable this option you'll be able to specify + a list of files to include or exclude from an archive. + +config BUSYBOX_CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY + bool "Support for old tar header format" + default BUSYBOX_DEFAULT_FEATURE_TAR_OLDGNU_COMPATIBILITY + depends on BUSYBOX_CONFIG_TAR || BUSYBOX_CONFIG_DPKG + help + This option is required to unpack archives created in + the old GNU format; help to kill this old format by + repacking your ancient archives with the new format. + +config BUSYBOX_CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY + bool "Enable untarring of tarballs with checksums produced by buggy Sun tar" + default BUSYBOX_DEFAULT_FEATURE_TAR_OLDSUN_COMPATIBILITY + depends on BUSYBOX_CONFIG_TAR || BUSYBOX_CONFIG_DPKG + help + This option is required to unpack archives created by some old + version of Sun's tar (it was calculating checksum using signed + arithmetic). It is said to be fixed in newer Sun tar, but "old" + tarballs still exist. + +config BUSYBOX_CONFIG_FEATURE_TAR_GNU_EXTENSIONS + bool "Support for GNU tar extensions (long filenames)" + default BUSYBOX_DEFAULT_FEATURE_TAR_GNU_EXTENSIONS + depends on BUSYBOX_CONFIG_TAR || BUSYBOX_CONFIG_DPKG + help + With this option busybox supports GNU long filenames and + linknames. + +config BUSYBOX_CONFIG_FEATURE_TAR_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_TAR_LONG_OPTIONS + depends on BUSYBOX_CONFIG_TAR && BUSYBOX_CONFIG_LONG_OPTS + help + Enable use of long options, increases size by about 400 Bytes + +config BUSYBOX_CONFIG_FEATURE_TAR_TO_COMMAND + bool "Support for writing to an external program" + default BUSYBOX_DEFAULT_FEATURE_TAR_TO_COMMAND + depends on BUSYBOX_CONFIG_TAR && BUSYBOX_CONFIG_FEATURE_TAR_LONG_OPTIONS + help + If you enable this option you'll be able to instruct tar to send + the contents of each extracted file to the standard input of an + external program. + +config BUSYBOX_CONFIG_FEATURE_TAR_UNAME_GNAME + bool "Enable use of user and group names" + default BUSYBOX_DEFAULT_FEATURE_TAR_UNAME_GNAME + depends on BUSYBOX_CONFIG_TAR + help + Enables use of user and group names in tar. This affects contents + listings (-t) and preserving permissions when unpacking (-p). + +200 bytes. + +config BUSYBOX_CONFIG_FEATURE_TAR_NOPRESERVE_TIME + bool "Enable -m (do not preserve time) option" + default BUSYBOX_DEFAULT_FEATURE_TAR_NOPRESERVE_TIME + depends on BUSYBOX_CONFIG_TAR + help + With this option busybox supports GNU tar -m + (do not preserve time) option. + +config BUSYBOX_CONFIG_FEATURE_TAR_SELINUX + bool "Support for extracting SELinux labels" + default BUSYBOX_DEFAULT_FEATURE_TAR_SELINUX + depends on BUSYBOX_CONFIG_TAR && BUSYBOX_CONFIG_SELINUX + help + With this option busybox supports restoring SELinux labels + when extracting files from tar archives. +config BUSYBOX_CONFIG_UNZIP + bool "unzip" + default BUSYBOX_DEFAULT_UNZIP + help + unzip will list or extract files from a ZIP archive, + commonly found on DOS/WIN systems. The default behavior + (with no options) is to extract the archive into the + current directory. Use the `-d' option to extract to a + directory of your choice. + +endmenu diff --git a/package/utils/busybox/config/console-tools/Config.in b/package/utils/busybox/config/console-tools/Config.in new file mode 100644 index 0000000..53937d2 --- /dev/null +++ b/package/utils/busybox/config/console-tools/Config.in @@ -0,0 +1,176 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Console Utilities" + + +config BUSYBOX_CONFIG_CHVT + bool "chvt" + default BUSYBOX_DEFAULT_CHVT + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program is used to change to another terminal. + Example: chvt 4 (change to terminal /dev/tty4) + +config BUSYBOX_CONFIG_FGCONSOLE + bool "fgconsole" + default BUSYBOX_DEFAULT_FGCONSOLE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program prints active (foreground) console number. + +config BUSYBOX_CONFIG_CLEAR + bool "clear" + default BUSYBOX_DEFAULT_CLEAR + help + This program clears the terminal screen. + +config BUSYBOX_CONFIG_DEALLOCVT + bool "deallocvt" + default BUSYBOX_DEFAULT_DEALLOCVT + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program deallocates unused virtual consoles. + +config BUSYBOX_CONFIG_DUMPKMAP + bool "dumpkmap" + default BUSYBOX_DEFAULT_DUMPKMAP + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program dumps the kernel's keyboard translation table to + stdout, in binary format. You can then use loadkmap to load it. + +config BUSYBOX_CONFIG_KBD_MODE + bool "kbd_mode" + default BUSYBOX_DEFAULT_KBD_MODE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program reports and sets keyboard mode. + +config BUSYBOX_CONFIG_LOADFONT + bool "loadfont" + default BUSYBOX_DEFAULT_LOADFONT + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program loads a console font from standard input. + +config BUSYBOX_CONFIG_LOADKMAP + bool "loadkmap" + default BUSYBOX_DEFAULT_LOADKMAP + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program loads a keyboard translation table from + standard input. + +config BUSYBOX_CONFIG_OPENVT + bool "openvt" + default BUSYBOX_DEFAULT_OPENVT + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program is used to start a command on an unused + virtual terminal. + +config BUSYBOX_CONFIG_RESET + bool "reset" + default BUSYBOX_DEFAULT_RESET + help + This program is used to reset the terminal screen, if it + gets messed up. + +config BUSYBOX_CONFIG_RESIZE + bool "resize" + default BUSYBOX_DEFAULT_RESIZE + help + This program is used to (re)set the width and height of your current + terminal. + +config BUSYBOX_CONFIG_FEATURE_RESIZE_PRINT + bool "Print environment variables" + default BUSYBOX_DEFAULT_FEATURE_RESIZE_PRINT + depends on BUSYBOX_CONFIG_RESIZE + help + Prints the newly set size (number of columns and rows) of + the terminal. + E.g.: + COLUMNS=80;LINES=44;export COLUMNS LINES; + +config BUSYBOX_CONFIG_SETCONSOLE + bool "setconsole" + default BUSYBOX_DEFAULT_SETCONSOLE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program redirects the system console to another device, + like the current tty while logged in via telnet. + +config BUSYBOX_CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_SETCONSOLE_LONG_OPTIONS + depends on BUSYBOX_CONFIG_SETCONSOLE && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the setconsole applet. + +config BUSYBOX_CONFIG_SETFONT + bool "setfont" + default BUSYBOX_DEFAULT_SETFONT + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Allows to load console screen map. Useful for i18n. + +config BUSYBOX_CONFIG_FEATURE_SETFONT_TEXTUAL_MAP + bool "Support reading textual screen maps" + default BUSYBOX_DEFAULT_FEATURE_SETFONT_TEXTUAL_MAP + depends on BUSYBOX_CONFIG_SETFONT + help + Support reading textual screen maps. + +config BUSYBOX_CONFIG_DEFAULT_SETFONT_DIR + string "Default directory for console-tools files" + default BUSYBOX_DEFAULT_DEFAULT_SETFONT_DIR + depends on BUSYBOX_CONFIG_SETFONT + help + Directory to use if setfont's params are simple filenames + (not /path/to/file or ./file). Default is "" (no default directory). + +config BUSYBOX_CONFIG_SETKEYCODES + bool "setkeycodes" + default BUSYBOX_DEFAULT_SETKEYCODES + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program loads entries into the kernel's scancode-to-keycode + map, allowing unusual keyboards to generate usable keycodes. + +config BUSYBOX_CONFIG_SETLOGCONS + bool "setlogcons" + default BUSYBOX_DEFAULT_SETLOGCONS + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program redirects the output console of kernel messages. + +config BUSYBOX_CONFIG_SHOWKEY + bool "showkey" + default BUSYBOX_DEFAULT_SHOWKEY + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Shows keys pressed. + +comment "Common options for loadfont and setfont" + depends on BUSYBOX_CONFIG_LOADFONT || BUSYBOX_CONFIG_SETFONT + +config BUSYBOX_CONFIG_FEATURE_LOADFONT_PSF2 + bool "Support for PSF2 console fonts" + default BUSYBOX_DEFAULT_FEATURE_LOADFONT_PSF2 + depends on BUSYBOX_CONFIG_LOADFONT || BUSYBOX_CONFIG_SETFONT + help + Support PSF2 console fonts. + +config BUSYBOX_CONFIG_FEATURE_LOADFONT_RAW + bool "Support for old (raw) console fonts" + default BUSYBOX_DEFAULT_FEATURE_LOADFONT_RAW + depends on BUSYBOX_CONFIG_LOADFONT || BUSYBOX_CONFIG_SETFONT + help + Support old (raw) console fonts. + +endmenu diff --git a/package/utils/busybox/config/coreutils/Config.in b/package/utils/busybox/config/coreutils/Config.in new file mode 100644 index 0000000..f50823f --- /dev/null +++ b/package/utils/busybox/config/coreutils/Config.in @@ -0,0 +1,954 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Coreutils" + +config BUSYBOX_CONFIG_BASENAME + bool "basename" + default BUSYBOX_DEFAULT_BASENAME + help + basename is used to strip the directory and suffix from filenames, + leaving just the filename itself. Enable this option if you wish + to enable the 'basename' utility. +config BUSYBOX_CONFIG_CAT + bool "cat" + default BUSYBOX_DEFAULT_CAT + help + cat is used to concatenate files and print them to the standard + output. Enable this option if you wish to enable the 'cat' utility. +config BUSYBOX_CONFIG_DATE + bool "date" + default BUSYBOX_DEFAULT_DATE + help + date is used to set the system date or display the + current time in the given format. + +config BUSYBOX_CONFIG_FEATURE_DATE_ISOFMT + bool "Enable ISO date format output (-I)" + default BUSYBOX_DEFAULT_FEATURE_DATE_ISOFMT + depends on BUSYBOX_CONFIG_DATE + help + Enable option (-I) to output an ISO-8601 compliant + date/time string. + +# defaults to "no": stat's nanosecond field is a bit non-portable +config BUSYBOX_CONFIG_FEATURE_DATE_NANO + bool "Support %[num]N nanosecond format specifier" + default BUSYBOX_DEFAULT_FEATURE_DATE_NANO + depends on BUSYBOX_CONFIG_DATE # syscall(__NR_clock_gettime) + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Support %[num]N format specifier. Adds ~250 bytes of code. + +config BUSYBOX_CONFIG_FEATURE_DATE_COMPAT + bool "Support weird 'date MMDDhhmm[[YY]YY][.ss]' format" + default BUSYBOX_DEFAULT_FEATURE_DATE_COMPAT + depends on BUSYBOX_CONFIG_DATE + help + System time can be set by 'date -s DATE' and simply 'date DATE', + but formats of DATE string are different. 'date DATE' accepts + a rather weird MMDDhhmm[[YY]YY][.ss] format with completely + unnatural placement of year between minutes and seconds. + date -s (and other commands like touch -d) use more sensible + formats (for one, ISO format YYYY-MM-DD hh:mm:ss.ssssss). + + With this option off, 'date DATE' is 'date -s DATE' support + the same format. With it on, 'date DATE' additionally supports + MMDDhhmm[[YY]YY][.ss] format. +config BUSYBOX_CONFIG_HOSTID + bool "hostid" + default BUSYBOX_DEFAULT_HOSTID + help + hostid prints the numeric identifier (in hexadecimal) for + the current host. +config BUSYBOX_CONFIG_ID + bool "id" + default BUSYBOX_DEFAULT_ID + help + id displays the current user and group ID names. +config BUSYBOX_CONFIG_GROUPS + bool "groups" + default BUSYBOX_DEFAULT_GROUPS + help + Print the group names associated with current user id. +config BUSYBOX_CONFIG_SHUF + bool "shuf" + default BUSYBOX_DEFAULT_SHUF + help + Generate random permutations +config BUSYBOX_CONFIG_TEST + bool "test" + default BUSYBOX_DEFAULT_TEST + help + test is used to check file types and compare values, + returning an appropriate exit code. The bash shell + has test built in, ash can build it in optionally. + +config BUSYBOX_CONFIG_FEATURE_TEST_64 + bool "Extend test to 64 bit" + default BUSYBOX_DEFAULT_FEATURE_TEST_64 + depends on BUSYBOX_CONFIG_TEST || BUSYBOX_CONFIG_ASH_BUILTIN_TEST || BUSYBOX_CONFIG_HUSH + help + Enable 64-bit support in test. +config BUSYBOX_CONFIG_TOUCH + bool "touch" + default BUSYBOX_DEFAULT_TOUCH + help + touch is used to create or change the access and/or + modification timestamp of specified files. + +config BUSYBOX_CONFIG_FEATURE_TOUCH_NODEREF + bool "Add support for -h" + default BUSYBOX_DEFAULT_FEATURE_TOUCH_NODEREF + depends on BUSYBOX_CONFIG_TOUCH + help + Enable touch to have the -h option. + This requires libc support for lutimes() function. + +config BUSYBOX_CONFIG_FEATURE_TOUCH_SUSV3 + bool "Add support for SUSV3 features (-d -t -r)" + default BUSYBOX_DEFAULT_FEATURE_TOUCH_SUSV3 + depends on BUSYBOX_CONFIG_TOUCH + help + Enable touch to use a reference file or a given date/time argument. +config BUSYBOX_CONFIG_TR + bool "tr" + default BUSYBOX_DEFAULT_TR + help + tr is used to squeeze, and/or delete characters from standard + input, writing to standard output. + +config BUSYBOX_CONFIG_FEATURE_TR_CLASSES + bool "Enable character classes (such as [:upper:])" + default BUSYBOX_DEFAULT_FEATURE_TR_CLASSES + depends on BUSYBOX_CONFIG_TR + help + Enable character classes, enabling commands such as: + tr [:upper:] [:lower:] to convert input into lowercase. + +config BUSYBOX_CONFIG_FEATURE_TR_EQUIV + bool "Enable equivalence classes" + default BUSYBOX_DEFAULT_FEATURE_TR_EQUIV + depends on BUSYBOX_CONFIG_TR + help + Enable equivalence classes, which essentially add the enclosed + character to the current set. For instance, tr [=a=] xyz would + replace all instances of 'a' with 'xyz'. This option is mainly + useful for cases when no other way of expressing a character + is possible. +config BUSYBOX_CONFIG_UNLINK + bool "unlink" + default BUSYBOX_DEFAULT_UNLINK + help + unlink deletes a file by calling unlink() +config BUSYBOX_CONFIG_BASE64 + bool "base64" + default BUSYBOX_DEFAULT_BASE64 + help + Base64 encode and decode +config BUSYBOX_CONFIG_WHO + bool "who" + default BUSYBOX_DEFAULT_WHO + depends on BUSYBOX_CONFIG_FEATURE_UTMP + help + who is used to show who is logged on. +config BUSYBOX_CONFIG_USERS + bool "users" + default BUSYBOX_DEFAULT_USERS + depends on BUSYBOX_CONFIG_FEATURE_UTMP + help + Print users currently logged on. + +config BUSYBOX_CONFIG_CAL + bool "cal" + default BUSYBOX_DEFAULT_CAL + help + cal is used to display a monthly calender. + +config BUSYBOX_CONFIG_CATV + bool "catv" + default BUSYBOX_DEFAULT_CATV + help + Display nonprinting characters as escape sequences (like some + implementations' cat -v option). + +config BUSYBOX_CONFIG_CHGRP + bool "chgrp" + default BUSYBOX_DEFAULT_CHGRP + help + chgrp is used to change the group ownership of files. + +config BUSYBOX_CONFIG_CHMOD + bool "chmod" + default BUSYBOX_DEFAULT_CHMOD + help + chmod is used to change the access permission of files. + +config BUSYBOX_CONFIG_CHOWN + bool "chown" + default BUSYBOX_DEFAULT_CHOWN + help + chown is used to change the user and/or group ownership + of files. + +config BUSYBOX_CONFIG_FEATURE_CHOWN_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_CHOWN_LONG_OPTIONS + depends on BUSYBOX_CONFIG_CHOWN && BUSYBOX_CONFIG_LONG_OPTS + help + Enable use of long options + +config BUSYBOX_CONFIG_CHROOT + bool "chroot" + default BUSYBOX_DEFAULT_CHROOT + help + chroot is used to change the root directory and run a command. + The default command is `/bin/sh'. + +config BUSYBOX_CONFIG_CKSUM + bool "cksum" + default BUSYBOX_DEFAULT_CKSUM + help + cksum is used to calculate the CRC32 checksum of a file. + +config BUSYBOX_CONFIG_COMM + bool "comm" + default BUSYBOX_DEFAULT_COMM + help + comm is used to compare two files line by line and return + a three-column output. + +config BUSYBOX_CONFIG_CP + bool "cp" + default BUSYBOX_DEFAULT_CP + help + cp is used to copy files and directories. + +config BUSYBOX_CONFIG_FEATURE_CP_LONG_OPTIONS + bool "Enable long options for cp" + default BUSYBOX_DEFAULT_FEATURE_CP_LONG_OPTIONS + depends on BUSYBOX_CONFIG_CP && BUSYBOX_CONFIG_LONG_OPTS + help + Enable long options for cp. + Also add support for --parents option. + +config BUSYBOX_CONFIG_CUT + bool "cut" + default BUSYBOX_DEFAULT_CUT + help + cut is used to print selected parts of lines from + each file to stdout. + +config BUSYBOX_CONFIG_DD + bool "dd" + default BUSYBOX_DEFAULT_DD + help + dd copies a file (from standard input to standard output, + by default) using specific input and output blocksizes, + while optionally performing conversions on it. + +config BUSYBOX_CONFIG_FEATURE_DD_SIGNAL_HANDLING + bool "Enable DD signal handling for status reporting" + default BUSYBOX_DEFAULT_FEATURE_DD_SIGNAL_HANDLING + depends on BUSYBOX_CONFIG_DD + help + Sending a SIGUSR1 signal to a running `dd' process makes it + print to standard error the number of records read and written + so far, then to resume copying. + + $ dd if=/dev/zero of=/dev/null& + $ pid=$! kill -USR1 $pid; sleep 1; kill $pid + 10899206+0 records in + 10899206+0 records out + +config BUSYBOX_CONFIG_FEATURE_DD_THIRD_STATUS_LINE + bool "Enable the third status line upon signal" + default BUSYBOX_DEFAULT_FEATURE_DD_THIRD_STATUS_LINE + depends on BUSYBOX_CONFIG_DD && BUSYBOX_CONFIG_FEATURE_DD_SIGNAL_HANDLING + help + Displays a coreutils-like third status line with transferred bytes, + elapsed time and speed. + +config BUSYBOX_CONFIG_FEATURE_DD_IBS_OBS + bool "Enable ibs, obs and conv options" + default BUSYBOX_DEFAULT_FEATURE_DD_IBS_OBS + depends on BUSYBOX_CONFIG_DD + help + Enables support for writing a certain number of bytes in and out, + at a time, and performing conversions on the data stream. + +config BUSYBOX_CONFIG_DF + bool "df" + default BUSYBOX_DEFAULT_DF + help + df reports the amount of disk space used and available + on filesystems. + +config BUSYBOX_CONFIG_FEATURE_DF_FANCY + bool "Enable -a, -i, -B" + default BUSYBOX_DEFAULT_FEATURE_DF_FANCY + depends on BUSYBOX_CONFIG_DF + help + This option enables -a, -i and -B. + + -a Show all filesystems + -i Inodes + -B <SIZE> Blocksize + +config BUSYBOX_CONFIG_DIRNAME + bool "dirname" + default BUSYBOX_DEFAULT_DIRNAME + help + dirname is used to strip a non-directory suffix from + a file name. + +config BUSYBOX_CONFIG_DOS2UNIX + bool "dos2unix/unix2dos" + default BUSYBOX_DEFAULT_DOS2UNIX + help + dos2unix is used to convert a text file from DOS format to + UNIX format, and vice versa. + +config BUSYBOX_CONFIG_UNIX2DOS + bool + default BUSYBOX_DEFAULT_UNIX2DOS + depends on BUSYBOX_CONFIG_DOS2UNIX + help + unix2dos is used to convert a text file from UNIX format to + DOS format, and vice versa. + +config BUSYBOX_CONFIG_DU + bool "du (default blocksize of 512 bytes)" + default BUSYBOX_DEFAULT_DU + help + du is used to report the amount of disk space used + for specified files. + +config BUSYBOX_CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K + bool "Use a default blocksize of 1024 bytes (1K)" + default BUSYBOX_DEFAULT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K + depends on BUSYBOX_CONFIG_DU + help + Use a blocksize of (1K) instead of the default 512b. + +config BUSYBOX_CONFIG_ECHO + bool "echo (basic SuSv3 version taking no options)" + default BUSYBOX_DEFAULT_ECHO + help + echo is used to print a specified string to stdout. + +# this entry also appears in shell/Config.in, next to the echo builtin +config BUSYBOX_CONFIG_FEATURE_FANCY_ECHO + bool "Enable echo options (-n and -e)" + default BUSYBOX_DEFAULT_FEATURE_FANCY_ECHO + depends on BUSYBOX_CONFIG_ECHO || BUSYBOX_CONFIG_ASH_BUILTIN_ECHO || BUSYBOX_CONFIG_HUSH + help + This adds options (-n and -e) to echo. + +config BUSYBOX_CONFIG_ENV + bool "env" + default BUSYBOX_DEFAULT_ENV + help + env is used to set an environment variable and run + a command; without options it displays the current + environment. + +config BUSYBOX_CONFIG_FEATURE_ENV_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_ENV_LONG_OPTIONS + depends on BUSYBOX_CONFIG_ENV && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the env applet. + +config BUSYBOX_CONFIG_EXPAND + bool "expand" + default BUSYBOX_DEFAULT_EXPAND + help + By default, convert all tabs to spaces. + +config BUSYBOX_CONFIG_FEATURE_EXPAND_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_EXPAND_LONG_OPTIONS + depends on BUSYBOX_CONFIG_EXPAND && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the expand applet. + +config BUSYBOX_CONFIG_EXPR + bool "expr" + default BUSYBOX_DEFAULT_EXPR + help + expr is used to calculate numbers and print the result + to standard output. + +config BUSYBOX_CONFIG_EXPR_MATH_SUPPORT_64 + bool "Extend Posix numbers support to 64 bit" + default BUSYBOX_DEFAULT_EXPR_MATH_SUPPORT_64 + depends on BUSYBOX_CONFIG_EXPR + help + Enable 64-bit math support in the expr applet. This will make + the applet slightly larger, but will allow computation with very + large numbers. + +config BUSYBOX_CONFIG_FALSE + bool "false" + default BUSYBOX_DEFAULT_FALSE + help + false returns an exit code of FALSE (1). + +config BUSYBOX_CONFIG_FOLD + bool "fold" + default BUSYBOX_DEFAULT_FOLD + help + Wrap text to fit a specific width. + +config BUSYBOX_CONFIG_FSYNC + bool "fsync" + default BUSYBOX_DEFAULT_FSYNC + help + fsync is used to flush file-related cached blocks to disk. + +config BUSYBOX_CONFIG_HEAD + bool "head" + default BUSYBOX_DEFAULT_HEAD + help + head is used to print the first specified number of lines + from files. + +config BUSYBOX_CONFIG_FEATURE_FANCY_HEAD + bool "Enable head options (-c, -q, and -v)" + default BUSYBOX_DEFAULT_FEATURE_FANCY_HEAD + depends on BUSYBOX_CONFIG_HEAD + help + This enables the head options (-c, -q, and -v). + +config BUSYBOX_CONFIG_INSTALL + bool "install" + default BUSYBOX_DEFAULT_INSTALL + help + Copy files and set attributes. + +config BUSYBOX_CONFIG_FEATURE_INSTALL_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_INSTALL_LONG_OPTIONS + depends on BUSYBOX_CONFIG_INSTALL && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the install applet. + +####config LENGTH +#### bool "length" +#### default y +#### help +#### length is used to print out the length of a specified string. + +config BUSYBOX_CONFIG_LN + bool "ln" + default BUSYBOX_DEFAULT_LN + help + ln is used to create hard or soft links between files. + +config BUSYBOX_CONFIG_LOGNAME + bool "logname" + default BUSYBOX_DEFAULT_LOGNAME + help + logname is used to print the current user's login name. + +config BUSYBOX_CONFIG_LS + bool "ls" + default BUSYBOX_DEFAULT_LS + help + ls is used to list the contents of directories. + +config BUSYBOX_CONFIG_FEATURE_LS_FILETYPES + bool "Enable filetyping options (-p and -F)" + default BUSYBOX_DEFAULT_FEATURE_LS_FILETYPES + depends on BUSYBOX_CONFIG_LS + help + Enable the ls options (-p and -F). + +config BUSYBOX_CONFIG_FEATURE_LS_FOLLOWLINKS + bool "Enable symlinks dereferencing (-L)" + default BUSYBOX_DEFAULT_FEATURE_LS_FOLLOWLINKS + depends on BUSYBOX_CONFIG_LS + help + Enable the ls option (-L). + +config BUSYBOX_CONFIG_FEATURE_LS_RECURSIVE + bool "Enable recursion (-R)" + default BUSYBOX_DEFAULT_FEATURE_LS_RECURSIVE + depends on BUSYBOX_CONFIG_LS + help + Enable the ls option (-R). + +config BUSYBOX_CONFIG_FEATURE_LS_SORTFILES + bool "Sort the file names" + default BUSYBOX_DEFAULT_FEATURE_LS_SORTFILES + depends on BUSYBOX_CONFIG_LS + help + Allow ls to sort file names alphabetically. + +config BUSYBOX_CONFIG_FEATURE_LS_TIMESTAMPS + bool "Show file timestamps" + default BUSYBOX_DEFAULT_FEATURE_LS_TIMESTAMPS + depends on BUSYBOX_CONFIG_LS + help + Allow ls to display timestamps for files. + +config BUSYBOX_CONFIG_FEATURE_LS_USERNAME + bool "Show username/groupnames" + default BUSYBOX_DEFAULT_FEATURE_LS_USERNAME + depends on BUSYBOX_CONFIG_LS + help + Allow ls to display username/groupname for files. + +config BUSYBOX_CONFIG_FEATURE_LS_COLOR + bool "Allow use of color to identify file types" + default BUSYBOX_DEFAULT_FEATURE_LS_COLOR + depends on BUSYBOX_CONFIG_LS && BUSYBOX_CONFIG_LONG_OPTS + help + This enables the --color option to ls. + +config BUSYBOX_CONFIG_FEATURE_LS_COLOR_IS_DEFAULT + bool "Produce colored ls output by default" + default BUSYBOX_DEFAULT_FEATURE_LS_COLOR_IS_DEFAULT + depends on BUSYBOX_CONFIG_FEATURE_LS_COLOR + help + Saying yes here will turn coloring on by default, + even if no "--color" option is given to the ls command. + This is not recommended, since the colors are not + configurable, and the output may not be legible on + many output screens. + +config BUSYBOX_CONFIG_MD5SUM + bool "md5sum" + default BUSYBOX_DEFAULT_MD5SUM + help + md5sum is used to print or check MD5 checksums. + +config BUSYBOX_CONFIG_MKDIR + bool "mkdir" + default BUSYBOX_DEFAULT_MKDIR + help + mkdir is used to create directories with the specified names. + +config BUSYBOX_CONFIG_FEATURE_MKDIR_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_MKDIR_LONG_OPTIONS + depends on BUSYBOX_CONFIG_MKDIR && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the mkdir applet. + +config BUSYBOX_CONFIG_MKFIFO + bool "mkfifo" + default BUSYBOX_DEFAULT_MKFIFO + help + mkfifo is used to create FIFOs (named pipes). + The `mknod' program can also create FIFOs. + +config BUSYBOX_CONFIG_MKNOD + bool "mknod" + default BUSYBOX_DEFAULT_MKNOD + help + mknod is used to create FIFOs or block/character special + files with the specified names. + +config BUSYBOX_CONFIG_MV + bool "mv" + default BUSYBOX_DEFAULT_MV + help + mv is used to move or rename files or directories. + +config BUSYBOX_CONFIG_FEATURE_MV_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_MV_LONG_OPTIONS + depends on BUSYBOX_CONFIG_MV && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the mv applet. + +config BUSYBOX_CONFIG_NICE + bool "nice" + default BUSYBOX_DEFAULT_NICE + help + nice runs a program with modified scheduling priority. + +config BUSYBOX_CONFIG_NOHUP + bool "nohup" + default BUSYBOX_DEFAULT_NOHUP + help + run a command immune to hangups, with output to a non-tty. + +config BUSYBOX_CONFIG_OD + bool "od" + default BUSYBOX_DEFAULT_OD + help + od is used to dump binary files in octal and other formats. + +config BUSYBOX_CONFIG_PRINTENV + bool "printenv" + default BUSYBOX_DEFAULT_PRINTENV + help + printenv is used to print all or part of environment. + +config BUSYBOX_CONFIG_PRINTF + bool "printf" + default BUSYBOX_DEFAULT_PRINTF + help + printf is used to format and print specified strings. + It's similar to `echo' except it has more options. + +config BUSYBOX_CONFIG_PWD + bool "pwd" + default BUSYBOX_DEFAULT_PWD + help + pwd is used to print the current directory. + +config BUSYBOX_CONFIG_READLINK + bool "readlink" + default BUSYBOX_DEFAULT_READLINK + help + This program reads a symbolic link and returns the name + of the file it points to + +config BUSYBOX_CONFIG_FEATURE_READLINK_FOLLOW + bool "Enable canonicalization by following all symlinks (-f)" + default BUSYBOX_DEFAULT_FEATURE_READLINK_FOLLOW + depends on BUSYBOX_CONFIG_READLINK + help + Enable the readlink option (-f). + +config BUSYBOX_CONFIG_REALPATH + bool "realpath" + default BUSYBOX_DEFAULT_REALPATH + help + Return the canonicalized absolute pathname. + This isn't provided by GNU shellutils, but where else does it belong. + +config BUSYBOX_CONFIG_RM + bool "rm" + default BUSYBOX_DEFAULT_RM + help + rm is used to remove files or directories. + +config BUSYBOX_CONFIG_RMDIR + bool "rmdir" + default BUSYBOX_DEFAULT_RMDIR + help + rmdir is used to remove empty directories. + +config BUSYBOX_CONFIG_FEATURE_RMDIR_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_RMDIR_LONG_OPTIONS + depends on BUSYBOX_CONFIG_RMDIR && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the rmdir applet, including + --ignore-fail-on-non-empty for compatibility with GNU rmdir. + +config BUSYBOX_CONFIG_SEQ + bool "seq" + default BUSYBOX_DEFAULT_SEQ + help + print a sequence of numbers + +config BUSYBOX_CONFIG_SHA1SUM + bool "sha1sum" + default BUSYBOX_DEFAULT_SHA1SUM + help + Compute and check SHA1 message digest + +config BUSYBOX_CONFIG_SHA256SUM + bool "sha256sum" + default BUSYBOX_DEFAULT_SHA256SUM + help + Compute and check SHA256 message digest + +config BUSYBOX_CONFIG_SHA512SUM + bool "sha512sum" + default BUSYBOX_DEFAULT_SHA512SUM + help + Compute and check SHA512 message digest + +config BUSYBOX_CONFIG_SHA3SUM + bool "sha3sum" + default BUSYBOX_DEFAULT_SHA3SUM + help + Compute and check SHA3 (512-bit) message digest + +config BUSYBOX_CONFIG_SLEEP + bool "sleep" + default BUSYBOX_DEFAULT_SLEEP + help + sleep is used to pause for a specified number of seconds. + It comes in 3 versions: + - small: takes one integer parameter + - fancy: takes multiple integer arguments with suffixes: + sleep 1d 2h 3m 15s + - fancy with fractional numbers: + sleep 2.3s 4.5h sleeps for 16202.3 seconds + Last one is "the most compatible" with coreutils sleep, + but it adds around 1k of code. + +config BUSYBOX_CONFIG_FEATURE_FANCY_SLEEP + bool "Enable multiple arguments and s/m/h/d suffixes" + default BUSYBOX_DEFAULT_FEATURE_FANCY_SLEEP + depends on BUSYBOX_CONFIG_SLEEP + help + Allow sleep to pause for specified minutes, hours, and days. + +config BUSYBOX_CONFIG_FEATURE_FLOAT_SLEEP + bool "Enable fractional arguments" + default BUSYBOX_DEFAULT_FEATURE_FLOAT_SLEEP + depends on BUSYBOX_CONFIG_FEATURE_FANCY_SLEEP + help + Allow for fractional numeric parameters. + +config BUSYBOX_CONFIG_SORT + bool "sort" + default BUSYBOX_DEFAULT_SORT + help + sort is used to sort lines of text in specified files. + +config BUSYBOX_CONFIG_FEATURE_SORT_BIG + bool "Full SuSv3 compliant sort (support -ktcsbdfiozgM)" + default BUSYBOX_DEFAULT_FEATURE_SORT_BIG + depends on BUSYBOX_CONFIG_SORT + help + Without this, sort only supports -r, -u, and an integer version + of -n. Selecting this adds sort keys, floating point support, and + more. This adds a little over 3k to a nonstatic build on x86. + + The SuSv3 sort standard is available at: + http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html + +config BUSYBOX_CONFIG_SPLIT + bool "split" + default BUSYBOX_DEFAULT_SPLIT + help + split a file into pieces. + +config BUSYBOX_CONFIG_FEATURE_SPLIT_FANCY + bool "Fancy extensions" + default BUSYBOX_DEFAULT_FEATURE_SPLIT_FANCY + depends on BUSYBOX_CONFIG_SPLIT + help + Add support for features not required by SUSv3. + Supports additional suffixes 'b' for 512 bytes, + 'g' for 1GiB for the -b option. + +config BUSYBOX_CONFIG_STAT + bool "stat" + default BUSYBOX_DEFAULT_STAT + select BUSYBOX_CONFIG_PLATFORM_LINUX # statfs() + help + display file or filesystem status. + +config BUSYBOX_CONFIG_FEATURE_STAT_FORMAT + bool "Enable custom formats (-c)" + default BUSYBOX_DEFAULT_FEATURE_STAT_FORMAT + depends on BUSYBOX_CONFIG_STAT + help + Without this, stat will not support the '-c format' option where + users can pass a custom format string for output. This adds about + 7k to a nonstatic build on amd64. + +config BUSYBOX_CONFIG_STTY + bool "stty" + default BUSYBOX_DEFAULT_STTY + help + stty is used to change and print terminal line settings. + +config BUSYBOX_CONFIG_SUM + bool "sum" + default BUSYBOX_DEFAULT_SUM + help + checksum and count the blocks in a file + +config BUSYBOX_CONFIG_SYNC + bool "sync" + default BUSYBOX_DEFAULT_SYNC + help + sync is used to flush filesystem buffers. + +config BUSYBOX_CONFIG_TAC + bool "tac" + default BUSYBOX_DEFAULT_TAC + help + tac is used to concatenate and print files in reverse. + +config BUSYBOX_CONFIG_TAIL + bool "tail" + default BUSYBOX_DEFAULT_TAIL + help + tail is used to print the last specified number of lines + from files. + +config BUSYBOX_CONFIG_FEATURE_FANCY_TAIL + bool "Enable extra tail options (-q, -s, -v, and -F)" + default BUSYBOX_DEFAULT_FEATURE_FANCY_TAIL + depends on BUSYBOX_CONFIG_TAIL + help + The options (-q, -s, -v and -F) are provided by GNU tail, but + are not specific in the SUSv3 standard. + + -q Never output headers giving file names + -s SEC Wait SEC seconds between reads with -f + -v Always output headers giving file names + -F Same as -f, but keep retrying + +config BUSYBOX_CONFIG_TEE + bool "tee" + default BUSYBOX_DEFAULT_TEE + help + tee is used to read from standard input and write + to standard output and files. + +config BUSYBOX_CONFIG_FEATURE_TEE_USE_BLOCK_IO + bool "Enable block I/O (larger/faster) instead of byte I/O" + default BUSYBOX_DEFAULT_FEATURE_TEE_USE_BLOCK_IO + depends on BUSYBOX_CONFIG_TEE + help + Enable this option for a faster tee, at expense of size. + +config BUSYBOX_CONFIG_TRUE + bool "true" + default BUSYBOX_DEFAULT_TRUE + help + true returns an exit code of TRUE (0). + +config BUSYBOX_CONFIG_TTY + bool "tty" + default BUSYBOX_DEFAULT_TTY + help + tty is used to print the name of the current terminal to + standard output. + +config BUSYBOX_CONFIG_UNAME + bool "uname" + default BUSYBOX_DEFAULT_UNAME + help + uname is used to print system information. + +config BUSYBOX_CONFIG_UNEXPAND + bool "unexpand" + default BUSYBOX_DEFAULT_UNEXPAND + help + By default, convert only leading sequences of blanks to tabs. + +config BUSYBOX_CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_UNEXPAND_LONG_OPTIONS + depends on BUSYBOX_CONFIG_UNEXPAND && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the unexpand applet. + +config BUSYBOX_CONFIG_UNIQ + bool "uniq" + default BUSYBOX_DEFAULT_UNIQ + help + uniq is used to remove duplicate lines from a sorted file. + +config BUSYBOX_CONFIG_USLEEP + bool "usleep" + default BUSYBOX_DEFAULT_USLEEP + help + usleep is used to pause for a specified number of microseconds. + +config BUSYBOX_CONFIG_UUDECODE + bool "uudecode" + default BUSYBOX_DEFAULT_UUDECODE + help + uudecode is used to decode a uuencoded file. + +config BUSYBOX_CONFIG_UUENCODE + bool "uuencode" + default BUSYBOX_DEFAULT_UUENCODE + help + uuencode is used to uuencode a file. + +config BUSYBOX_CONFIG_WC + bool "wc" + default BUSYBOX_DEFAULT_WC + help + wc is used to print the number of bytes, words, and lines, + in specified files. + +config BUSYBOX_CONFIG_FEATURE_WC_LARGE + bool "Support very large files in wc" + default BUSYBOX_DEFAULT_FEATURE_WC_LARGE + depends on BUSYBOX_CONFIG_WC + help + Use "unsigned long long" in wc for counter variables. + +config BUSYBOX_CONFIG_WHOAMI + bool "whoami" + default BUSYBOX_DEFAULT_WHOAMI + help + whoami is used to print the username of the current + user id (same as id -un). + +config BUSYBOX_CONFIG_YES + bool "yes" + default BUSYBOX_DEFAULT_YES + help + yes is used to repeatedly output a specific string, or + the default string `y'. + +comment "Common options" + +config BUSYBOX_CONFIG_FEATURE_VERBOSE + bool "Support verbose options (usually -v) for various applets" + default BUSYBOX_DEFAULT_FEATURE_VERBOSE + help + Enable cp -v, rm -v and similar messages. + Also enables long option (--verbose) if it exists. + Without this option, -v is accepted but ignored. + +comment "Common options for cp and mv" + depends on BUSYBOX_CONFIG_CP || BUSYBOX_CONFIG_MV + +config BUSYBOX_CONFIG_FEATURE_PRESERVE_HARDLINKS + bool "Preserve hard links" + default BUSYBOX_DEFAULT_FEATURE_PRESERVE_HARDLINKS + depends on BUSYBOX_CONFIG_CP || BUSYBOX_CONFIG_MV + help + Allow cp and mv to preserve hard links. + +comment "Common options for ls, more and telnet" + depends on BUSYBOX_CONFIG_LS || BUSYBOX_CONFIG_MORE || BUSYBOX_CONFIG_TELNET + +config BUSYBOX_CONFIG_FEATURE_AUTOWIDTH + bool "Calculate terminal & column widths" + default BUSYBOX_DEFAULT_FEATURE_AUTOWIDTH + depends on BUSYBOX_CONFIG_LS || BUSYBOX_CONFIG_MORE || BUSYBOX_CONFIG_TELNET + help + This option allows utilities such as 'ls', 'more' and 'telnet' + to determine the width of the screen, which can allow them to + display additional text or avoid wrapping text onto the next line. + If you leave this disabled, your utilities will be especially + primitive and will be unable to determine the current screen width. + +comment "Common options for df, du, ls" + depends on BUSYBOX_CONFIG_DF || BUSYBOX_CONFIG_DU || BUSYBOX_CONFIG_LS + +config BUSYBOX_CONFIG_FEATURE_HUMAN_READABLE + bool "Support for human readable output (example 13k, 23M, 235G)" + default BUSYBOX_DEFAULT_FEATURE_HUMAN_READABLE + depends on BUSYBOX_CONFIG_DF || BUSYBOX_CONFIG_DU || BUSYBOX_CONFIG_LS + help + Allow df, du, and ls to have human readable output. + +comment "Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum" + depends on BUSYBOX_CONFIG_MD5SUM || BUSYBOX_CONFIG_SHA1SUM || BUSYBOX_CONFIG_SHA256SUM || BUSYBOX_CONFIG_SHA512SUM || BUSYBOX_CONFIG_SHA3SUM + +config BUSYBOX_CONFIG_FEATURE_MD5_SHA1_SUM_CHECK + bool "Enable -c, -s and -w options" + default BUSYBOX_DEFAULT_FEATURE_MD5_SHA1_SUM_CHECK + depends on BUSYBOX_CONFIG_MD5SUM || BUSYBOX_CONFIG_SHA1SUM || BUSYBOX_CONFIG_SHA256SUM || BUSYBOX_CONFIG_SHA512SUM || BUSYBOX_CONFIG_SHA3SUM + help + Enabling the -c options allows files to be checked + against pre-calculated hash values. + + -s and -w are useful options when verifying checksums. + +endmenu diff --git a/package/utils/busybox/config/debianutils/Config.in b/package/utils/busybox/config/debianutils/Config.in new file mode 100644 index 0000000..533ad47 --- /dev/null +++ b/package/utils/busybox/config/debianutils/Config.in @@ -0,0 +1,85 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Debian Utilities" + + +config BUSYBOX_CONFIG_MKTEMP + bool "mktemp" + default BUSYBOX_DEFAULT_MKTEMP + help + mktemp is used to create unique temporary files + +config BUSYBOX_CONFIG_PIPE_PROGRESS + bool "pipe_progress" + default BUSYBOX_DEFAULT_PIPE_PROGRESS + help + Display a dot to indicate pipe activity. + +config BUSYBOX_CONFIG_RUN_PARTS + bool "run-parts" + default BUSYBOX_DEFAULT_RUN_PARTS + help + run-parts is a utility designed to run all the scripts in a directory. + + It is useful to set up a directory like cron.daily, where you need to + execute all the scripts in that directory. + + In this implementation of run-parts some features (such as report + mode) are not implemented. + + Unless you know that run-parts is used in some of your scripts + you can safely say N here. + +config BUSYBOX_CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_RUN_PARTS_LONG_OPTIONS + depends on BUSYBOX_CONFIG_RUN_PARTS && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the run-parts applet. + +config BUSYBOX_CONFIG_FEATURE_RUN_PARTS_FANCY + bool "Support additional arguments" + default BUSYBOX_DEFAULT_FEATURE_RUN_PARTS_FANCY + depends on BUSYBOX_CONFIG_RUN_PARTS + help + Support additional options: + -l --list print the names of the all matching files (not + limited to executables), but don't actually run them. + +config BUSYBOX_CONFIG_START_STOP_DAEMON + bool "start-stop-daemon" + default BUSYBOX_DEFAULT_START_STOP_DAEMON + help + start-stop-daemon is used to control the creation and + termination of system-level processes, usually the ones + started during the startup of the system. + +config BUSYBOX_CONFIG_FEATURE_START_STOP_DAEMON_FANCY + bool "Support additional arguments" + default BUSYBOX_DEFAULT_FEATURE_START_STOP_DAEMON_FANCY + depends on BUSYBOX_CONFIG_START_STOP_DAEMON + help + Support additional arguments. + -o|--oknodo ignored since we exit with 0 anyway + -v|--verbose + -N|--nicelevel N + +config BUSYBOX_CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_START_STOP_DAEMON_LONG_OPTIONS + depends on BUSYBOX_CONFIG_START_STOP_DAEMON && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the start-stop-daemon applet. + +config BUSYBOX_CONFIG_WHICH + bool "which" + default BUSYBOX_DEFAULT_WHICH + help + which is used to find programs in your PATH and + print out their pathnames. + +endmenu diff --git a/package/utils/busybox/config/e2fsprogs/Config.in b/package/utils/busybox/config/e2fsprogs/Config.in new file mode 100644 index 0000000..f826240 --- /dev/null +++ b/package/utils/busybox/config/e2fsprogs/Config.in @@ -0,0 +1,71 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Linux Ext2 FS Progs" + + +config BUSYBOX_CONFIG_CHATTR + bool "chattr" + default BUSYBOX_DEFAULT_CHATTR + help + chattr changes the file attributes on a second extended file system. + +### config E2FSCK +### bool "e2fsck" +### default y +### help +### e2fsck is used to check Linux second extended file systems (ext2fs). +### e2fsck also supports ext2 filesystems countaining a journal (ext3). +### The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also +### provided. + +config BUSYBOX_CONFIG_FSCK + bool "fsck" + default BUSYBOX_DEFAULT_FSCK + help + fsck is used to check and optionally repair one or more filesystems. + In actuality, fsck is simply a front-end for the various file system + checkers (fsck.fstype) available under Linux. + +config BUSYBOX_CONFIG_LSATTR + bool "lsattr" + default BUSYBOX_DEFAULT_LSATTR + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + lsattr lists the file attributes on a second extended file system. + +### config MKE2FS +### bool "mke2fs" +### default y +### help +### mke2fs is used to create an ext2/ext3 filesystem. The normal compat +### symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided. + +config BUSYBOX_CONFIG_TUNE2FS + bool "tune2fs" + default BUSYBOX_DEFAULT_TUNE2FS # off: it is too limited compared to upstream version + help + tune2fs allows the system administrator to adjust various tunable + filesystem parameters on Linux ext2/ext3 filesystems. + +### config E2LABEL +### bool "e2label" +### default y +### depends on TUNE2FS +### help +### e2label will display or change the filesystem label on the ext2 +### filesystem located on device. + +### NB: this one is now provided by util-linux/volume_id/* +### config FINDFS +### bool "findfs" +### default y +### depends on TUNE2FS +### help +### findfs will search the disks in the system looking for a filesystem +### which has a label matching label or a UUID equal to uuid. + +endmenu diff --git a/package/utils/busybox/config/e2fsprogs/old_e2fsprogs/Config.in b/package/utils/busybox/config/e2fsprogs/old_e2fsprogs/Config.in new file mode 100644 index 0000000..d7a5396 --- /dev/null +++ b/package/utils/busybox/config/e2fsprogs/old_e2fsprogs/Config.in @@ -0,0 +1,69 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Linux Ext2 FS Progs" + + +config BUSYBOX_CONFIG_CHATTR + bool "chattr" + default BUSYBOX_DEFAULT_CHATTR + help + chattr changes the file attributes on a second extended file system. + +config BUSYBOX_CONFIG_E2FSCK + bool "e2fsck" + default BUSYBOX_DEFAULT_E2FSCK + help + e2fsck is used to check Linux second extended file systems (ext2fs). + e2fsck also supports ext2 filesystems countaining a journal (ext3). + The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also + provided. + +config BUSYBOX_CONFIG_FSCK + bool "fsck" + default BUSYBOX_DEFAULT_FSCK + help + fsck is used to check and optionally repair one or more filesystems. + In actuality, fsck is simply a front-end for the various file system + checkers (fsck.fstype) available under Linux. + +config BUSYBOX_CONFIG_LSATTR + bool "lsattr" + default BUSYBOX_DEFAULT_LSATTR + help + lsattr lists the file attributes on a second extended file system. + +config BUSYBOX_CONFIG_MKE2FS + bool "mke2fs" + default BUSYBOX_DEFAULT_MKE2FS + help + mke2fs is used to create an ext2/ext3 filesystem. The normal compat + symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided. + +config BUSYBOX_CONFIG_TUNE2FS + bool "tune2fs" + default BUSYBOX_DEFAULT_TUNE2FS + help + tune2fs allows the system administrator to adjust various tunable + filesystem parameters on Linux ext2/ext3 filesystems. + +config BUSYBOX_CONFIG_E2LABEL + bool "e2label" + default BUSYBOX_DEFAULT_E2LABEL + depends on BUSYBOX_CONFIG_TUNE2FS + help + e2label will display or change the filesystem label on the ext2 + filesystem located on device. + +config BUSYBOX_CONFIG_FINDFS + bool "findfs" + default BUSYBOX_DEFAULT_FINDFS + depends on BUSYBOX_CONFIG_TUNE2FS + help + findfs will search the disks in the system looking for a filesystem + which has a label matching label or a UUID equal to uuid. + +endmenu diff --git a/package/utils/busybox/config/editors/Config.in b/package/utils/busybox/config/editors/Config.in new file mode 100644 index 0000000..6ae361f --- /dev/null +++ b/package/utils/busybox/config/editors/Config.in @@ -0,0 +1,234 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Editors" + +config BUSYBOX_CONFIG_AWK + bool "awk" + default BUSYBOX_DEFAULT_AWK + help + Awk is used as a pattern scanning and processing language. This is + the BusyBox implementation of that programming language. + +config BUSYBOX_CONFIG_FEATURE_AWK_LIBM + bool "Enable math functions (requires libm)" + default BUSYBOX_DEFAULT_FEATURE_AWK_LIBM + depends on BUSYBOX_CONFIG_AWK + help + Enable math functions of the Awk programming language. + NOTE: This will require libm to be present for linking. + +config BUSYBOX_CONFIG_FEATURE_AWK_GNU_EXTENSIONS + bool "Enable a few GNU extensions" + default BUSYBOX_DEFAULT_FEATURE_AWK_GNU_EXTENSIONS + depends on BUSYBOX_CONFIG_AWK + help + Enable a few features from gawk: + * command line option -e AWK_PROGRAM + * simultaneous use of -f and -e on the command line. + This enables the use of awk library files. + Ex: awk -f mylib.awk -e '{print myfunction($1);}' ... +config BUSYBOX_CONFIG_CMP + bool "cmp" + default BUSYBOX_DEFAULT_CMP + help + cmp is used to compare two files and returns the result + to standard output. +config BUSYBOX_CONFIG_DIFF + bool "diff" + default BUSYBOX_DEFAULT_DIFF + help + diff compares two files or directories and outputs the + differences between them in a form that can be given to + the patch command. + +config BUSYBOX_CONFIG_FEATURE_DIFF_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_DIFF_LONG_OPTIONS + depends on BUSYBOX_CONFIG_DIFF && BUSYBOX_CONFIG_LONG_OPTS + help + Enable use of long options. + +config BUSYBOX_CONFIG_FEATURE_DIFF_DIR + bool "Enable directory support" + default BUSYBOX_DEFAULT_FEATURE_DIFF_DIR + depends on BUSYBOX_CONFIG_DIFF + help + This option enables support for directory and subdirectory + comparison. +config BUSYBOX_CONFIG_ED + bool "ed" + default BUSYBOX_DEFAULT_ED + help + The original 1970's Unix text editor, from the days of teletypes. + Small, simple, evil. Part of SUSv3. If you're not already using + this, you don't need it. +config BUSYBOX_CONFIG_PATCH + bool "patch" + default BUSYBOX_DEFAULT_PATCH + help + Apply a unified diff formatted patch. +config BUSYBOX_CONFIG_SED + bool "sed" + default BUSYBOX_DEFAULT_SED + help + sed is used to perform text transformations on a file + or input from a pipeline. +config BUSYBOX_CONFIG_VI + bool "vi" + default BUSYBOX_DEFAULT_VI + help + 'vi' is a text editor. More specifically, it is the One True + text editor <grin>. It does, however, have a rather steep + learning curve. If you are not already comfortable with 'vi' + you may wish to use something else. + +config BUSYBOX_CONFIG_FEATURE_VI_MAX_LEN + int "Maximum screen width in vi" + range 256 16384 + default BUSYBOX_DEFAULT_FEATURE_VI_MAX_LEN + depends on BUSYBOX_CONFIG_VI + help + Contrary to what you may think, this is not eating much. + Make it smaller than 4k only if you are very limited on memory. + +config BUSYBOX_CONFIG_FEATURE_VI_8BIT + bool "Allow vi to display 8-bit chars (otherwise shows dots)" + default BUSYBOX_DEFAULT_FEATURE_VI_8BIT + depends on BUSYBOX_CONFIG_VI + help + If your terminal can display characters with high bit set, + you may want to enable this. Note: vi is not Unicode-capable. + If your terminal combines several 8-bit bytes into one character + (as in Unicode mode), this will not work properly. + +config BUSYBOX_CONFIG_FEATURE_VI_COLON + bool "Enable \":\" colon commands (no \"ex\" mode)" + default BUSYBOX_DEFAULT_FEATURE_VI_COLON + depends on BUSYBOX_CONFIG_VI + help + Enable a limited set of colon commands for vi. This does not + provide an "ex" mode. + +config BUSYBOX_CONFIG_FEATURE_VI_YANKMARK + bool "Enable yank/put commands and mark cmds" + default BUSYBOX_DEFAULT_FEATURE_VI_YANKMARK + depends on BUSYBOX_CONFIG_VI + help + This will enable you to use yank and put, as well as mark in + busybox vi. + +config BUSYBOX_CONFIG_FEATURE_VI_SEARCH + bool "Enable search and replace cmds" + default BUSYBOX_DEFAULT_FEATURE_VI_SEARCH + depends on BUSYBOX_CONFIG_VI + help + Select this if you wish to be able to do search and replace in + busybox vi. + +config BUSYBOX_CONFIG_FEATURE_VI_REGEX_SEARCH + bool "Enable regex in search and replace" + default BUSYBOX_DEFAULT_FEATURE_VI_REGEX_SEARCH # Uses GNU regex, which may be unavailable. FIXME + depends on BUSYBOX_CONFIG_FEATURE_VI_SEARCH + help + Use extended regex search. + +config BUSYBOX_CONFIG_FEATURE_VI_USE_SIGNALS + bool "Catch signals" + default BUSYBOX_DEFAULT_FEATURE_VI_USE_SIGNALS + depends on BUSYBOX_CONFIG_VI + help + Selecting this option will make busybox vi signal aware. This will + make busybox vi support SIGWINCH to deal with Window Changes, catch + Ctrl-Z and Ctrl-C and alarms. + +config BUSYBOX_CONFIG_FEATURE_VI_DOT_CMD + bool "Remember previous cmd and \".\" cmd" + default BUSYBOX_DEFAULT_FEATURE_VI_DOT_CMD + depends on BUSYBOX_CONFIG_VI + help + Make busybox vi remember the last command and be able to repeat it. + +config BUSYBOX_CONFIG_FEATURE_VI_READONLY + bool "Enable -R option and \"view\" mode" + default BUSYBOX_DEFAULT_FEATURE_VI_READONLY + depends on BUSYBOX_CONFIG_VI + help + Enable the read-only command line option, which allows the user to + open a file in read-only mode. + +config BUSYBOX_CONFIG_FEATURE_VI_SETOPTS + bool "Enable set-able options, ai ic showmatch" + default BUSYBOX_DEFAULT_FEATURE_VI_SETOPTS + depends on BUSYBOX_CONFIG_VI + help + Enable the editor to set some (ai, ic, showmatch) options. + +config BUSYBOX_CONFIG_FEATURE_VI_SET + bool "Support for :set" + default BUSYBOX_DEFAULT_FEATURE_VI_SET + depends on BUSYBOX_CONFIG_VI + help + Support for ":set". + +config BUSYBOX_CONFIG_FEATURE_VI_WIN_RESIZE + bool "Handle window resize" + default BUSYBOX_DEFAULT_FEATURE_VI_WIN_RESIZE + depends on BUSYBOX_CONFIG_VI + help + Make busybox vi behave nicely with terminals that get resized. + +config BUSYBOX_CONFIG_FEATURE_VI_ASK_TERMINAL + bool "Use 'tell me cursor position' ESC sequence to measure window" + default BUSYBOX_DEFAULT_FEATURE_VI_ASK_TERMINAL + depends on BUSYBOX_CONFIG_VI + help + If terminal size can't be retrieved and $LINES/$COLUMNS are not set, + this option makes vi perform a last-ditch effort to find it: + position cursor to 999,999 and ask terminal to report real + cursor position using "ESC [ 6 n" escape sequence, then read stdin. + + This is not clean but helps a lot on serial lines and such. +config BUSYBOX_CONFIG_FEATURE_VI_UNDO + bool "Support undo command 'u'" + default BUSYBOX_DEFAULT_FEATURE_VI_UNDO + depends on BUSYBOX_CONFIG_VI + help + Support the 'u' command to undo insertion, deletion, and replacement + of text. +config BUSYBOX_CONFIG_FEATURE_VI_UNDO_QUEUE + bool "Enable undo operation queuing" + default BUSYBOX_DEFAULT_FEATURE_VI_UNDO_QUEUE + depends on BUSYBOX_CONFIG_FEATURE_VI_UNDO + help + The vi undo functions can use an intermediate queue to greatly lower + malloc() calls and overhead. When the maximum size of this queue is + reached, the contents of the queue are committed to the undo stack. + This increases the size of the undo code and allows some undo + operations (especially un-typing/backspacing) to be far more useful. +config BUSYBOX_CONFIG_FEATURE_VI_UNDO_QUEUE_MAX + int "Maximum undo character queue size" + default BUSYBOX_DEFAULT_FEATURE_VI_UNDO_QUEUE_MAX + range 32 65536 + depends on BUSYBOX_CONFIG_FEATURE_VI_UNDO_QUEUE + help + This option sets the number of bytes used at runtime for the queue. + Smaller values will create more undo objects and reduce the amount + of typed or backspaced characters that are grouped into one undo + operation; larger values increase the potential size of each undo + and will generally malloc() larger objects and less frequently. + Unless you want more (or less) frequent "undo points" while typing, + you should probably leave this unchanged. + +config BUSYBOX_CONFIG_FEATURE_ALLOW_EXEC + bool "Allow vi and awk to execute shell commands" + default BUSYBOX_DEFAULT_FEATURE_ALLOW_EXEC + depends on BUSYBOX_CONFIG_VI || BUSYBOX_CONFIG_AWK + help + Enables vi and awk features which allows user to execute + shell commands (using system() C call). + +endmenu diff --git a/package/utils/busybox/config/findutils/Config.in b/package/utils/busybox/config/findutils/Config.in new file mode 100644 index 0000000..85ee1db --- /dev/null +++ b/package/utils/busybox/config/findutils/Config.in @@ -0,0 +1,269 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Finding Utilities" + +config BUSYBOX_CONFIG_FIND + bool "find" + default BUSYBOX_DEFAULT_FIND + help + find is used to search your system to find specified files. + +config BUSYBOX_CONFIG_FEATURE_FIND_PRINT0 + bool "Enable -print0: NUL-terminated output" + default BUSYBOX_DEFAULT_FEATURE_FIND_PRINT0 + depends on BUSYBOX_CONFIG_FIND + help + Causes output names to be separated by a NUL character + rather than a newline. This allows names that contain + newlines and other whitespace to be more easily + interpreted by other programs. + +config BUSYBOX_CONFIG_FEATURE_FIND_MTIME + bool "Enable -mtime: modified time matching" + default BUSYBOX_DEFAULT_FEATURE_FIND_MTIME + depends on BUSYBOX_CONFIG_FIND + help + Allow searching based on the modification time of + files, in days. + +config BUSYBOX_CONFIG_FEATURE_FIND_MMIN + bool "Enable -mmin: modified time matching by minutes" + default BUSYBOX_DEFAULT_FEATURE_FIND_MMIN + depends on BUSYBOX_CONFIG_FIND + help + Allow searching based on the modification time of + files, in minutes. + +config BUSYBOX_CONFIG_FEATURE_FIND_PERM + bool "Enable -perm: permissions matching" + default BUSYBOX_DEFAULT_FEATURE_FIND_PERM + depends on BUSYBOX_CONFIG_FIND + help + Enable searching based on file permissions. + +config BUSYBOX_CONFIG_FEATURE_FIND_TYPE + bool "Enable -type: file type matching (file/dir/link/...)" + default BUSYBOX_DEFAULT_FEATURE_FIND_TYPE + depends on BUSYBOX_CONFIG_FIND + help + Enable searching based on file type (file, + directory, socket, device, etc.). + +config BUSYBOX_CONFIG_FEATURE_FIND_XDEV + bool "Enable -xdev: 'stay in filesystem'" + default BUSYBOX_DEFAULT_FEATURE_FIND_XDEV + depends on BUSYBOX_CONFIG_FIND + help + This option allows find to restrict searches to a single filesystem. + +config BUSYBOX_CONFIG_FEATURE_FIND_MAXDEPTH + bool "Enable -mindepth N and -maxdepth N" + default BUSYBOX_DEFAULT_FEATURE_FIND_MAXDEPTH + depends on BUSYBOX_CONFIG_FIND + help + This option enables -mindepth N and -maxdepth N option. + +config BUSYBOX_CONFIG_FEATURE_FIND_NEWER + bool "Enable -newer: compare file modification times" + default BUSYBOX_DEFAULT_FEATURE_FIND_NEWER + depends on BUSYBOX_CONFIG_FIND + help + Support the 'find -newer' option for finding any files which have + modification time that is more recent than the specified FILE. + +config BUSYBOX_CONFIG_FEATURE_FIND_INUM + bool "Enable -inum: inode number matching" + default BUSYBOX_DEFAULT_FEATURE_FIND_INUM + depends on BUSYBOX_CONFIG_FIND + help + Support the 'find -inum' option for searching by inode number. + +config BUSYBOX_CONFIG_FEATURE_FIND_EXEC + bool "Enable -exec: execute commands" + default BUSYBOX_DEFAULT_FEATURE_FIND_EXEC + depends on BUSYBOX_CONFIG_FIND + help + Support the 'find -exec' option for executing commands based upon + the files matched. + +config BUSYBOX_CONFIG_FEATURE_FIND_EXEC_PLUS + bool "Enable -exec ... {} +" + default BUSYBOX_DEFAULT_FEATURE_FIND_EXEC_PLUS + depends on BUSYBOX_CONFIG_FEATURE_FIND_EXEC + help + Support the 'find -exec ... {} +' option for executing commands + for all matched files at once. + Without this option, -exec + is a synonym for -exec ; + (IOW: it works correctly, but without expected speedup) + +config BUSYBOX_CONFIG_FEATURE_FIND_USER + bool "Enable -user: username/uid matching" + default BUSYBOX_DEFAULT_FEATURE_FIND_USER + depends on BUSYBOX_CONFIG_FIND + help + Support the 'find -user' option for searching by username or uid. + +config BUSYBOX_CONFIG_FEATURE_FIND_GROUP + bool "Enable -group: group/gid matching" + default BUSYBOX_DEFAULT_FEATURE_FIND_GROUP + depends on BUSYBOX_CONFIG_FIND + help + Support the 'find -group' option for searching by group name or gid. + +config BUSYBOX_CONFIG_FEATURE_FIND_NOT + bool "Enable the 'not' (!) operator" + default BUSYBOX_DEFAULT_FEATURE_FIND_NOT + depends on BUSYBOX_CONFIG_FIND + help + Support the '!' operator to invert the test results. + If 'Enable full-blown desktop' is enabled, then will also support + the non-POSIX notation '-not'. + +config BUSYBOX_CONFIG_FEATURE_FIND_DEPTH + bool "Enable -depth" + default BUSYBOX_DEFAULT_FEATURE_FIND_DEPTH + depends on BUSYBOX_CONFIG_FIND + help + Process each directory's contents before the directory itself. + +config BUSYBOX_CONFIG_FEATURE_FIND_PAREN + bool "Enable parens in options" + default BUSYBOX_DEFAULT_FEATURE_FIND_PAREN + depends on BUSYBOX_CONFIG_FIND + help + Enable usage of parens '(' to specify logical order of arguments. + +config BUSYBOX_CONFIG_FEATURE_FIND_SIZE + bool "Enable -size: file size matching" + default BUSYBOX_DEFAULT_FEATURE_FIND_SIZE + depends on BUSYBOX_CONFIG_FIND + help + Support the 'find -size' option for searching by file size. + +config BUSYBOX_CONFIG_FEATURE_FIND_PRUNE + bool "Enable -prune: exclude subdirectories" + default BUSYBOX_DEFAULT_FEATURE_FIND_PRUNE + depends on BUSYBOX_CONFIG_FIND + help + If the file is a directory, dont descend into it. Useful for + exclusion .svn and CVS directories. + +config BUSYBOX_CONFIG_FEATURE_FIND_DELETE + bool "Enable -delete: delete files/dirs" + default BUSYBOX_DEFAULT_FEATURE_FIND_DELETE + depends on BUSYBOX_CONFIG_FIND && BUSYBOX_CONFIG_FEATURE_FIND_DEPTH + help + Support the 'find -delete' option for deleting files and directories. + WARNING: This option can do much harm if used wrong. Busybox will not + try to protect the user from doing stupid things. Use with care. + +config BUSYBOX_CONFIG_FEATURE_FIND_PATH + bool "Enable -path: match pathname with shell pattern" + default BUSYBOX_DEFAULT_FEATURE_FIND_PATH + depends on BUSYBOX_CONFIG_FIND + help + The -path option matches whole pathname instead of just filename. + +config BUSYBOX_CONFIG_FEATURE_FIND_REGEX + bool "Enable -regex: match pathname with regex" + default BUSYBOX_DEFAULT_FEATURE_FIND_REGEX + depends on BUSYBOX_CONFIG_FIND + help + The -regex option matches whole pathname against regular expression. + +config BUSYBOX_CONFIG_FEATURE_FIND_CONTEXT + bool "Enable -context: security context matching" + default BUSYBOX_DEFAULT_FEATURE_FIND_CONTEXT + depends on BUSYBOX_CONFIG_FIND && BUSYBOX_CONFIG_SELINUX + help + Support the 'find -context' option for matching security context. + +config BUSYBOX_CONFIG_FEATURE_FIND_LINKS + bool "Enable -links: link count matching" + default BUSYBOX_DEFAULT_FEATURE_FIND_LINKS + depends on BUSYBOX_CONFIG_FIND + help + Support the 'find -links' option for matching number of links. +config BUSYBOX_CONFIG_GREP + bool "grep" + default BUSYBOX_DEFAULT_GREP + help + grep is used to search files for a specified pattern. + +config BUSYBOX_CONFIG_FEATURE_GREP_EGREP_ALIAS + bool "Enable extended regular expressions (egrep & grep -E)" + default BUSYBOX_DEFAULT_FEATURE_GREP_EGREP_ALIAS + depends on BUSYBOX_CONFIG_GREP + help + Enabled support for extended regular expressions. Extended + regular expressions allow for alternation (foo|bar), grouping, + and various repetition operators. + +config BUSYBOX_CONFIG_FEATURE_GREP_FGREP_ALIAS + bool "Alias fgrep to grep -F" + default BUSYBOX_DEFAULT_FEATURE_GREP_FGREP_ALIAS + depends on BUSYBOX_CONFIG_GREP + help + fgrep sees the search pattern as a normal string rather than + regular expressions. + grep -F always works, this just creates the fgrep alias. + +config BUSYBOX_CONFIG_FEATURE_GREP_CONTEXT + bool "Enable before and after context flags (-A, -B and -C)" + default BUSYBOX_DEFAULT_FEATURE_GREP_CONTEXT + depends on BUSYBOX_CONFIG_GREP + help + Print the specified number of leading (-B) and/or trailing (-A) + context surrounding our matching lines. + Print the specified number of context lines (-C). +config BUSYBOX_CONFIG_XARGS + bool "xargs" + default BUSYBOX_DEFAULT_XARGS + help + xargs is used to execute a specified command for + every item from standard input. + +config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION + bool "Enable -p: prompt and confirmation" + default BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_CONFIRMATION + depends on BUSYBOX_CONFIG_XARGS + help + Support -p: prompt the user whether to run each command + line and read a line from the terminal. + +config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_QUOTES + bool "Enable single and double quotes and backslash" + default BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_QUOTES + depends on BUSYBOX_CONFIG_XARGS + help + Support quoting in the input. + +config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT + bool "Enable -x: exit if -s or -n is exceeded" + default BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_TERMOPT + depends on BUSYBOX_CONFIG_XARGS + help + Support -x: exit if the command size (see the -s or -n option) + is exceeded. + +config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM + bool "Enable -0: NUL-terminated input" + default BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_ZERO_TERM + depends on BUSYBOX_CONFIG_XARGS + help + Support -0: input items are terminated by a NUL character + instead of whitespace, and the quotes and backslash + are not special. + +config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR + bool "Enable -I STR: string to replace" + default BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_REPL_STR + depends on BUSYBOX_CONFIG_XARGS + help + Support -I STR and -i[STR] options. + +endmenu diff --git a/package/utils/busybox/config/init/Config.in b/package/utils/busybox/config/init/Config.in new file mode 100644 index 0000000..634207f --- /dev/null +++ b/package/utils/busybox/config/init/Config.in @@ -0,0 +1,184 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Init Utilities" + +config BUSYBOX_CONFIG_BOOTCHARTD + bool "bootchartd" + default BUSYBOX_DEFAULT_BOOTCHARTD + help + bootchartd is commonly used to profile the boot process + for the purpose of speeding it up. In this case, it is started + by the kernel as the init process. This is configured by adding + the init=/sbin/bootchartd option to the kernel command line. + + It can also be used to monitor the resource usage of a specific + application or the running system in general. In this case, + bootchartd is started interactively by running bootchartd start + and stopped using bootchartd stop. + +config BUSYBOX_CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER + bool "Compatible, bloated header" + default BUSYBOX_DEFAULT_FEATURE_BOOTCHARTD_BLOATED_HEADER + depends on BUSYBOX_CONFIG_BOOTCHARTD + help + Create extended header file compatible with "big" bootchartd. + "Big" bootchartd is a shell script and it dumps some + "convenient" info int the header, such as: + title = Boot chart for `hostname` (`date`) + system.uname = `uname -srvm` + system.release = `cat /etc/DISTRO-release` + system.cpu = `grep '^model name' /proc/cpuinfo | head -1` ($cpucount) + system.kernel.options = `cat /proc/cmdline` + This data is not mandatory for bootchart graph generation, + and is considered bloat. Nevertheless, this option + makes bootchartd applet to dump a subset of it. + +config BUSYBOX_CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE + bool "Support bootchartd.conf" + default BUSYBOX_DEFAULT_FEATURE_BOOTCHARTD_CONFIG_FILE + depends on BUSYBOX_CONFIG_BOOTCHARTD + help + Enable reading and parsing of $PWD/bootchartd.conf + and /etc/bootchartd.conf files. +config BUSYBOX_CONFIG_HALT + bool "poweroff, halt, and reboot" + default BUSYBOX_DEFAULT_HALT + help + Stop all processes and either halt, reboot, or power off the system. + +config BUSYBOX_CONFIG_FEATURE_CALL_TELINIT + bool "Call telinit on shutdown and reboot" + default BUSYBOX_DEFAULT_FEATURE_CALL_TELINIT + depends on BUSYBOX_CONFIG_HALT && !BUSYBOX_CONFIG_INIT + help + Call an external program (normally telinit) to facilitate + a switch to a proper runlevel. + + This option is only available if you selected halt and friends, + but did not select init. + +config BUSYBOX_CONFIG_TELINIT_PATH + string "Path to telinit executable" + default BUSYBOX_DEFAULT_TELINIT_PATH + depends on BUSYBOX_CONFIG_FEATURE_CALL_TELINIT + help + When busybox halt and friends have to call external telinit + to facilitate proper shutdown, this path is to be used when + locating telinit executable. +config BUSYBOX_CONFIG_INIT + bool "init" + default BUSYBOX_DEFAULT_INIT + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + init is the first program run when the system boots. + +config BUSYBOX_CONFIG_FEATURE_USE_INITTAB + bool "Support reading an inittab file" + default BUSYBOX_DEFAULT_FEATURE_USE_INITTAB + depends on BUSYBOX_CONFIG_INIT + help + Allow init to read an inittab file when the system boot. + +config BUSYBOX_CONFIG_FEATURE_KILL_REMOVED + bool "Support killing processes that have been removed from inittab" + default BUSYBOX_DEFAULT_FEATURE_KILL_REMOVED + depends on BUSYBOX_CONFIG_FEATURE_USE_INITTAB + help + When respawn entries are removed from inittab and a SIGHUP is + sent to init, this option will make init kill the processes + that have been removed. + +config BUSYBOX_CONFIG_FEATURE_KILL_DELAY + int "How long to wait between TERM and KILL (0 - send TERM only)" if FEATURE_KILL_REMOVED + range 0 1024 + default BUSYBOX_DEFAULT_FEATURE_KILL_DELAY + depends on BUSYBOX_CONFIG_FEATURE_KILL_REMOVED + help + With nonzero setting, init sends TERM, forks, child waits N + seconds, sends KILL and exits. Setting it too high is unwise + (child will hang around for too long and could actually kill + the wrong process!) + +config BUSYBOX_CONFIG_FEATURE_INIT_SCTTY + bool "Run commands with leading dash with controlling tty" + default BUSYBOX_DEFAULT_FEATURE_INIT_SCTTY + depends on BUSYBOX_CONFIG_INIT + help + If this option is enabled, init will try to give a controlling + tty to any command which has leading hyphen (often it's "-/bin/sh"). + More precisely, init will do "ioctl(STDIN_FILENO, TIOCSCTTY, 0)". + If device attached to STDIN_FILENO can be a ctty but is not yet + a ctty for other session, it will become this process' ctty. + This is not the traditional init behavour, but is often what you want + in an embedded system where the console is only accessed during + development or for maintenance. + NB: using cttyhack applet may work better. + +config BUSYBOX_CONFIG_FEATURE_INIT_SYSLOG + bool "Enable init to write to syslog" + default BUSYBOX_DEFAULT_FEATURE_INIT_SYSLOG + depends on BUSYBOX_CONFIG_INIT + +config BUSYBOX_CONFIG_FEATURE_EXTRA_QUIET + bool "Be _extra_ quiet on boot" + default BUSYBOX_DEFAULT_FEATURE_EXTRA_QUIET + depends on BUSYBOX_CONFIG_INIT + help + Prevent init from logging some messages to the console during boot. + +config BUSYBOX_CONFIG_FEATURE_INIT_COREDUMPS + bool "Support dumping core for child processes (debugging only)" + default BUSYBOX_DEFAULT_FEATURE_INIT_COREDUMPS + depends on BUSYBOX_CONFIG_INIT + help + If this option is enabled and the file /.init_enable_core + exists, then init will call setrlimit() to allow unlimited + core file sizes. If this option is disabled, processes + will not generate any core files. + +config BUSYBOX_CONFIG_FEATURE_INITRD + bool "Support running init from within an initrd (not initramfs)" + default BUSYBOX_DEFAULT_FEATURE_INITRD + depends on BUSYBOX_CONFIG_INIT + help + Legacy support for running init under the old-style initrd. Allows + the name linuxrc to act as init, and it doesn't assume init is PID 1. + + This does not apply to initramfs, which runs /init as PID 1 and + requires no special support. + +config BUSYBOX_CONFIG_INIT_TERMINAL_TYPE + string "Initial terminal type" + default BUSYBOX_DEFAULT_INIT_TERMINAL_TYPE + depends on BUSYBOX_CONFIG_INIT + help + This is the initial value set by init for the TERM environment + variable. This variable is used by programs which make use of + extended terminal capabilities. + + Note that on Linux, init attempts to detect serial terminal and + sets TERM to "vt102" if one is found. +config BUSYBOX_CONFIG_MESG + bool "mesg" + default BUSYBOX_DEFAULT_MESG + help + Mesg controls access to your terminal by others. It is typically + used to allow or disallow other users to write to your terminal + +config BUSYBOX_CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP + bool "Enable writing to tty only by group, not by everybody" + default BUSYBOX_DEFAULT_FEATURE_MESG_ENABLE_ONLY_GROUP + depends on BUSYBOX_CONFIG_MESG + help + Usually, ttys are owned by group "tty", and "write" tool is + setgid to this group. This way, "mesg y" only needs to enable + "write by owning group" bit in tty mode. + + If you set this option to N, "mesg y" will enable writing + by anybody at all. This is not recommended. + +endmenu diff --git a/package/utils/busybox/config/libbb/Config.in b/package/utils/busybox/config/libbb/Config.in new file mode 100644 index 0000000..e66a15b --- /dev/null +++ b/package/utils/busybox/config/libbb/Config.in @@ -0,0 +1,249 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Busybox Library Tuning" + +config BUSYBOX_CONFIG_FEATURE_SYSTEMD + bool "Enable systemd support" + default BUSYBOX_DEFAULT_FEATURE_SYSTEMD + help + If you plan to use busybox daemons on a system where daemons + are controlled by systemd, enable this option. + If you don't use systemd, it is still safe to enable it, + but the downside is increased code size. +config BUSYBOX_CONFIG_FEATURE_RTMINMAX + bool "Support RTMIN[+n] and RTMAX[-n] signal names" + default BUSYBOX_DEFAULT_FEATURE_RTMINMAX + help + Support RTMIN[+n] and RTMAX[-n] signal names + in kill, killall etc. This costs ~250 bytes. + +config BUSYBOX_CONFIG_PASSWORD_MINLEN + int "Minimum password length" + default BUSYBOX_DEFAULT_PASSWORD_MINLEN + range 5 32 + help + Minimum allowable password length. + +config BUSYBOX_CONFIG_MD5_SMALL + int "MD5: Trade bytes for speed (0:fast, 3:slow)" + default BUSYBOX_DEFAULT_MD5_SMALL + range 0 3 + help + Trade binary size versus speed for the md5sum algorithm. + Approximate values running uClibc and hashing + linux-2.4.4.tar.bz2 were: + user times (sec) text size (386) + 0 (fastest) 1.1 6144 + 1 1.4 5392 + 2 3.0 5088 + 3 (smallest) 5.1 4912 + +config BUSYBOX_CONFIG_SHA3_SMALL + int "SHA3: Trade bytes for speed (0:fast, 1:slow)" + default BUSYBOX_DEFAULT_SHA3_SMALL + range 0 1 + help + Trade binary size versus speed for the sha3sum algorithm. + SHA3_SMALL=0 compared to SHA3_SMALL=1 (approximate): + 64-bit x86: +270 bytes of code, 45% faster + 32-bit x86: +450 bytes of code, 75% faster + +config BUSYBOX_CONFIG_FEATURE_FAST_TOP + bool "Faster /proc scanning code (+100 bytes)" + default BUSYBOX_DEFAULT_FEATURE_FAST_TOP + help + This option makes top (and ps) ~20% faster (or 20% less CPU hungry), + but code size is slightly bigger. + +config BUSYBOX_CONFIG_FEATURE_ETC_NETWORKS + bool "Support for /etc/networks" + default BUSYBOX_DEFAULT_FEATURE_ETC_NETWORKS + help + Enable support for network names in /etc/networks. This is + a rarely used feature which allows you to use names + instead of IP/mask pairs in route command. + +config BUSYBOX_CONFIG_FEATURE_USE_TERMIOS + bool "Use termios to manipulate the screen" + default BUSYBOX_DEFAULT_FEATURE_USE_TERMIOS + depends on BUSYBOX_CONFIG_MORE || BUSYBOX_CONFIG_TOP || BUSYBOX_CONFIG_POWERTOP + help + This option allows utilities such as 'more' and 'top' to determine + the size of the screen. If you leave this disabled, your utilities + that display things on the screen will be especially primitive and + will be unable to determine the current screen size, and will be + unable to move the cursor. + +config BUSYBOX_CONFIG_FEATURE_EDITING + bool "Command line editing" + default BUSYBOX_DEFAULT_FEATURE_EDITING + help + Enable line editing (mainly for shell command line). + +config BUSYBOX_CONFIG_FEATURE_EDITING_MAX_LEN + int "Maximum length of input" + range 128 8192 + default BUSYBOX_DEFAULT_FEATURE_EDITING_MAX_LEN + depends on BUSYBOX_CONFIG_FEATURE_EDITING + help + Line editing code uses on-stack buffers for storage. + You may want to decrease this parameter if your target machine + benefits from smaller stack usage. + +config BUSYBOX_CONFIG_FEATURE_EDITING_VI + bool "vi-style line editing commands" + default BUSYBOX_DEFAULT_FEATURE_EDITING_VI + depends on BUSYBOX_CONFIG_FEATURE_EDITING + help + Enable vi-style line editing. In shells, this mode can be + turned on and off with "set -o vi" and "set +o vi". + +config BUSYBOX_CONFIG_FEATURE_EDITING_HISTORY + int "History size" + # Don't allow way too big values here, code uses fixed "char *history[N]" struct member + range 0 9999 + default BUSYBOX_DEFAULT_FEATURE_EDITING_HISTORY + depends on BUSYBOX_CONFIG_FEATURE_EDITING + help + Specify command history size (0 - disable). + +config BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY + bool "History saving" + default BUSYBOX_DEFAULT_FEATURE_EDITING_SAVEHISTORY + depends on BUSYBOX_CONFIG_FEATURE_EDITING + help + Enable history saving in shells. + +config BUSYBOX_CONFIG_FEATURE_EDITING_SAVE_ON_EXIT + bool "Save history on shell exit, not after every command" + default BUSYBOX_DEFAULT_FEATURE_EDITING_SAVE_ON_EXIT + depends on BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY + help + Save history on shell exit, not after every command. + +config BUSYBOX_CONFIG_FEATURE_REVERSE_SEARCH + bool "Reverse history search" + default BUSYBOX_DEFAULT_FEATURE_REVERSE_SEARCH + depends on BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY + help + Enable readline-like Ctrl-R combination for reverse history search. + Increases code by about 0.5k. + +config BUSYBOX_CONFIG_FEATURE_TAB_COMPLETION + bool "Tab completion" + default BUSYBOX_DEFAULT_FEATURE_TAB_COMPLETION + depends on BUSYBOX_CONFIG_FEATURE_EDITING + help + Enable tab completion. + +config BUSYBOX_CONFIG_FEATURE_USERNAME_COMPLETION + bool "Username completion" + default BUSYBOX_DEFAULT_FEATURE_USERNAME_COMPLETION + depends on BUSYBOX_CONFIG_FEATURE_TAB_COMPLETION + help + Enable username completion. + +config BUSYBOX_CONFIG_FEATURE_EDITING_FANCY_PROMPT + bool "Fancy shell prompts" + default BUSYBOX_DEFAULT_FEATURE_EDITING_FANCY_PROMPT + depends on BUSYBOX_CONFIG_FEATURE_EDITING + help + Setting this option allows for prompts to use things like \w and + \$ and escape codes. + +config BUSYBOX_CONFIG_FEATURE_EDITING_ASK_TERMINAL + bool "Query cursor position from terminal" + default BUSYBOX_DEFAULT_FEATURE_EDITING_ASK_TERMINAL + depends on BUSYBOX_CONFIG_FEATURE_EDITING + help + Allow usage of "ESC [ 6 n" sequence. Terminal answers back with + current cursor position. This information is used to make line + editing more robust in some cases. + If you are not sure whether your terminals respond to this code + correctly, or want to save on code size (about 400 bytes), + then do not turn this option on. + +config BUSYBOX_CONFIG_FEATURE_NON_POSIX_CP + bool "Non-POSIX, but safer, copying to special nodes" + default BUSYBOX_DEFAULT_FEATURE_NON_POSIX_CP + help + With this option, "cp file symlink" will delete symlink + and create a regular file. This does not conform to POSIX, + but prevents a symlink attack. + Similarly, "cp file device" will not send file's data + to the device. (To do that, use "cat file >device") + +config BUSYBOX_CONFIG_FEATURE_VERBOSE_CP_MESSAGE + bool "Give more precise messages when copy fails (cp, mv etc)" + default BUSYBOX_DEFAULT_FEATURE_VERBOSE_CP_MESSAGE + help + Error messages with this feature enabled: + $ cp file /does_not_exist/file + cp: cannot create '/does_not_exist/file': Path does not exist + $ cp file /vmlinuz/file + cp: cannot stat '/vmlinuz/file': Path has non-directory component + If this feature is not enabled, they will be, respectively: + cp: cannot create '/does_not_exist/file': No such file or directory + cp: cannot stat '/vmlinuz/file': Not a directory + This will cost you ~60 bytes. + +config BUSYBOX_CONFIG_FEATURE_COPYBUF_KB + int "Copy buffer size, in kilobytes" + range 1 1024 + default BUSYBOX_DEFAULT_FEATURE_COPYBUF_KB + help + Size of buffer used by cp, mv, install, wget etc. + Buffers which are 4 kb or less will be allocated on stack. + Bigger buffers will be allocated with mmap, with fallback to 4 kb + stack buffer if mmap fails. + +config BUSYBOX_CONFIG_FEATURE_SKIP_ROOTFS + bool "Skip rootfs in mount table" + default BUSYBOX_DEFAULT_FEATURE_SKIP_ROOTFS + help + Ignore rootfs entry in mount table. + + In Linux, kernel has a special filesystem, rootfs, which is initially + mounted on /. It contains initramfs data, if kernel is configured + to have one. Usually, another file system is mounted over / early + in boot process, and therefore most tools which manipulate + mount table, such as df, will skip rootfs entry. + + However, some systems do not mount anything on /. + If you need to configure busybox for one of these systems, + you may find it useful to turn this option off to make df show + initramfs statistics. + + Otherwise, choose Y. + +config BUSYBOX_CONFIG_MONOTONIC_SYSCALL + bool "Use clock_gettime(CLOCK_MONOTONIC) syscall" + default BUSYBOX_DEFAULT_MONOTONIC_SYSCALL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring + time intervals (time, ping, traceroute etc need this). + Probably requires Linux 2.6+. If not selected, gettimeofday + will be used instead (which gives wrong results if date/time + is reset). + +config BUSYBOX_CONFIG_IOCTL_HEX2STR_ERROR + bool "Use ioctl names rather than hex values in error messages" + default BUSYBOX_DEFAULT_IOCTL_HEX2STR_ERROR + help + Use ioctl names rather than hex values in error messages + (e.g. VT_DISALLOCATE rather than 0x5608). If disabled this + saves about 1400 bytes. + +config BUSYBOX_CONFIG_FEATURE_HWIB + bool "Support infiniband HW" + default BUSYBOX_DEFAULT_FEATURE_HWIB + help + Support for printing infiniband addresses in + network applets. + +endmenu diff --git a/package/utils/busybox/config/loginutils/Config.in b/package/utils/busybox/config/loginutils/Config.in new file mode 100644 index 0000000..f5ecf6f --- /dev/null +++ b/package/utils/busybox/config/loginutils/Config.in @@ -0,0 +1,342 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Login/Password Management Utilities" + +config BUSYBOX_CONFIG_ADD_SHELL + bool "add-shell" + default BUSYBOX_DEFAULT_ADD_SHELL if BUSYBOX_CONFIG_DESKTOP + help + Add shells to /etc/shells. + +config BUSYBOX_CONFIG_REMOVE_SHELL + bool "remove-shell" + default BUSYBOX_DEFAULT_REMOVE_SHELL if BUSYBOX_CONFIG_DESKTOP + help + Remove shells from /etc/shells. + +config BUSYBOX_CONFIG_FEATURE_SHADOWPASSWDS + bool "Support for shadow passwords" + default BUSYBOX_DEFAULT_FEATURE_SHADOWPASSWDS + help + Build support for shadow password in /etc/shadow. This file is only + readable by root and thus the encrypted passwords are no longer + publicly readable. + +config BUSYBOX_CONFIG_USE_BB_PWD_GRP + bool "Use internal password and group functions rather than system functions" + default BUSYBOX_DEFAULT_USE_BB_PWD_GRP + help + If you leave this disabled, busybox will use the system's password + and group functions. And if you are using the GNU C library + (glibc), you will then need to install the /etc/nsswitch.conf + configuration file and the required /lib/libnss_* libraries in + order for the password and group functions to work. This generally + makes your embedded system quite a bit larger. + + Enabling this option will cause busybox to directly access the + system's /etc/password, /etc/group files (and your system will be + smaller, and I will get fewer emails asking about how glibc NSS + works). When this option is enabled, you will not be able to use + PAM to access remote LDAP password servers and whatnot. And if you + want hostname resolution to work with glibc, you still need the + /lib/libnss_* libraries. + + If you need to use glibc's nsswitch.conf mechanism + (e.g. if user/group database is NOT stored in /etc/passwd etc), + you must NOT use this option. + + If you enable this option, it will add about 1.5k. + +config BUSYBOX_CONFIG_USE_BB_SHADOW + bool "Use internal shadow password functions" + default BUSYBOX_DEFAULT_USE_BB_SHADOW + depends on BUSYBOX_CONFIG_USE_BB_PWD_GRP && BUSYBOX_CONFIG_FEATURE_SHADOWPASSWDS + help + If you leave this disabled, busybox will use the system's shadow + password handling functions. And if you are using the GNU C library + (glibc), you will then need to install the /etc/nsswitch.conf + configuration file and the required /lib/libnss_* libraries in + order for the shadow password functions to work. This generally + makes your embedded system quite a bit larger. + + Enabling this option will cause busybox to directly access the + system's /etc/shadow file when handling shadow passwords. This + makes your system smaller (and I will get fewer emails asking about + how glibc NSS works). When this option is enabled, you will not be + able to use PAM to access shadow passwords from remote LDAP + password servers and whatnot. + +config BUSYBOX_CONFIG_USE_BB_CRYPT + bool "Use internal crypt functions" + default BUSYBOX_DEFAULT_USE_BB_CRYPT + help + Busybox has internal DES and MD5 crypt functions. + They produce results which are identical to corresponding + standard C library functions. + + If you leave this disabled, busybox will use the system's + crypt functions. Most C libraries use large (~70k) + static buffers there, and also combine them with more general + DES encryption/decryption. + + For busybox, having large static buffers is undesirable, + especially on NOMMU machines. Busybox also doesn't need + DES encryption/decryption and can do with smaller code. + + If you enable this option, it will add about 4.8k of code + if you are building dynamically linked executable. + In static build, it makes code _smaller_ by about 1.2k, + and likely many kilobytes less of bss. + +config BUSYBOX_CONFIG_USE_BB_CRYPT_SHA + bool "Enable SHA256/512 crypt functions" + default BUSYBOX_DEFAULT_USE_BB_CRYPT_SHA + depends on BUSYBOX_CONFIG_USE_BB_CRYPT + help + Enable this if you have passwords starting with "$5$" or "$6$" + in your /etc/passwd or /etc/shadow files. These passwords + are hashed using SHA256 and SHA512 algorithms. Support for them + was added to glibc in 2008. + With this option off, login will fail password check for any + user which has password encrypted with these algorithms. + +config BUSYBOX_CONFIG_ADDUSER + bool "adduser" + default BUSYBOX_DEFAULT_ADDUSER + help + Utility for creating a new user account. + +config BUSYBOX_CONFIG_FEATURE_ADDUSER_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_ADDUSER_LONG_OPTIONS + depends on BUSYBOX_CONFIG_ADDUSER && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the adduser applet. + +config BUSYBOX_CONFIG_FEATURE_CHECK_NAMES + bool "Enable sanity check on user/group names in adduser and addgroup" + default BUSYBOX_DEFAULT_FEATURE_CHECK_NAMES + depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP + help + Enable sanity check on user and group names in adduser and addgroup. + To avoid problems, the user or group name should consist only of + letters, digits, underscores, periods, at signs and dashes, + and not start with a dash (as defined by IEEE Std 1003.1-2001). + For compatibility with Samba machine accounts "$" is also supported + at the end of the user or group name. + +config BUSYBOX_CONFIG_LAST_ID + int "Last valid uid or gid for adduser and addgroup" + depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP + default BUSYBOX_DEFAULT_LAST_ID + help + Last valid uid or gid for adduser and addgroup + +config BUSYBOX_CONFIG_FIRST_SYSTEM_ID + int "First valid system uid or gid for adduser and addgroup" + depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP + range 0 BUSYBOX_CONFIG_LAST_ID + default BUSYBOX_DEFAULT_FIRST_SYSTEM_ID + help + First valid system uid or gid for adduser and addgroup + +config BUSYBOX_CONFIG_LAST_SYSTEM_ID + int "Last valid system uid or gid for adduser and addgroup" + depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP + range BUSYBOX_CONFIG_FIRST_SYSTEM_ID BUSYBOX_CONFIG_LAST_ID + default BUSYBOX_DEFAULT_LAST_SYSTEM_ID + help + Last valid system uid or gid for adduser and addgroup + +config BUSYBOX_CONFIG_ADDGROUP + bool "addgroup" + default BUSYBOX_DEFAULT_ADDGROUP + help + Utility for creating a new group account. + +config BUSYBOX_CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_ADDGROUP_LONG_OPTIONS + depends on BUSYBOX_CONFIG_ADDGROUP && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the addgroup applet. + +config BUSYBOX_CONFIG_FEATURE_ADDUSER_TO_GROUP + bool "Support for adding users to groups" + default BUSYBOX_DEFAULT_FEATURE_ADDUSER_TO_GROUP + depends on BUSYBOX_CONFIG_ADDGROUP + help + If called with two non-option arguments, + addgroup will add an existing user to an + existing group. + +config BUSYBOX_CONFIG_DELUSER + bool "deluser" + default BUSYBOX_DEFAULT_DELUSER + help + Utility for deleting a user account. + +config BUSYBOX_CONFIG_DELGROUP + bool "delgroup" + default BUSYBOX_DEFAULT_DELGROUP + help + Utility for deleting a group account. + +config BUSYBOX_CONFIG_FEATURE_DEL_USER_FROM_GROUP + bool "Support for removing users from groups" + default BUSYBOX_DEFAULT_FEATURE_DEL_USER_FROM_GROUP + depends on BUSYBOX_CONFIG_DELGROUP + help + If called with two non-option arguments, deluser + or delgroup will remove an user from a specified group. + +config BUSYBOX_CONFIG_GETTY + bool "getty" + default BUSYBOX_DEFAULT_GETTY + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + getty lets you log in on a tty. It is normally invoked by init. + + Note that you can save a few bytes by disabling it and + using login applet directly. + If you need to reset tty attributes before calling login, + this script approximates getty: + + exec </dev/$1 >/dev/$1 2>&1 || exit 1 + reset + stty sane; stty ispeed 38400; stty ospeed 38400 + printf "%s login: " "`hostname`" + read -r login + exec /bin/login "$login" + +config BUSYBOX_CONFIG_LOGIN + bool "login" + default BUSYBOX_DEFAULT_LOGIN + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + login is used when signing onto a system. + + Note that Busybox binary must be setuid root for this applet to + work properly. + +config BUSYBOX_CONFIG_LOGIN_SESSION_AS_CHILD + bool "Run logged in session in a child process" + default BUSYBOX_DEFAULT_LOGIN_SESSION_AS_CHILD if BUSYBOX_CONFIG_PAM + depends on BUSYBOX_CONFIG_LOGIN + help + Run the logged in session in a child process. This allows + login to clean up things such as utmp entries or PAM sessions + when the login session is complete. If you use PAM, you + almost always would want this to be set to Y, else PAM session + will not be cleaned up. + +config BUSYBOX_CONFIG_LOGIN_SCRIPTS + bool "Support for login scripts" + depends on BUSYBOX_CONFIG_LOGIN + default BUSYBOX_DEFAULT_LOGIN_SCRIPTS + help + Enable this if you want login to execute $LOGIN_PRE_SUID_SCRIPT + just prior to switching from root to logged-in user. + +config BUSYBOX_CONFIG_FEATURE_NOLOGIN + bool "Support for /etc/nologin" + default BUSYBOX_DEFAULT_FEATURE_NOLOGIN + depends on BUSYBOX_CONFIG_LOGIN + help + The file /etc/nologin is used by (some versions of) login(1). + If it exists, non-root logins are prohibited. + +config BUSYBOX_CONFIG_FEATURE_SECURETTY + bool "Support for /etc/securetty" + default BUSYBOX_DEFAULT_FEATURE_SECURETTY + depends on BUSYBOX_CONFIG_LOGIN + help + The file /etc/securetty is used by (some versions of) login(1). + The file contains the device names of tty lines (one per line, + without leading /dev/) on which root is allowed to login. + +config BUSYBOX_CONFIG_PASSWD + bool "passwd" + default BUSYBOX_DEFAULT_PASSWD + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + passwd changes passwords for user and group accounts. A normal user + may only change the password for his/her own account, the super user + may change the password for any account. The administrator of a group + may change the password for the group. + + Note that Busybox binary must be setuid root for this applet to + work properly. + +config BUSYBOX_CONFIG_FEATURE_PASSWD_WEAK_CHECK + bool "Check new passwords for weakness" + default BUSYBOX_DEFAULT_FEATURE_PASSWD_WEAK_CHECK + depends on BUSYBOX_CONFIG_PASSWD + help + With this option passwd will refuse new passwords which are "weak". + +config BUSYBOX_CONFIG_CRYPTPW + bool "cryptpw" + default BUSYBOX_DEFAULT_CRYPTPW + help + Encrypts the given password with the crypt(3) libc function + using the given salt. Debian has this utility under mkpasswd + name. Busybox provides mkpasswd as an alias for cryptpw. + +config BUSYBOX_CONFIG_CHPASSWD + bool "chpasswd" + default BUSYBOX_DEFAULT_CHPASSWD + help + Reads a file of user name and password pairs from standard input + and uses this information to update a group of existing users. + +config BUSYBOX_CONFIG_FEATURE_DEFAULT_PASSWD_ALGO + string "Default password encryption method (passwd -a, cryptpw -m parameter)" + default BUSYBOX_DEFAULT_FEATURE_DEFAULT_PASSWD_ALGO + depends on BUSYBOX_CONFIG_PASSWD || BUSYBOX_CONFIG_CRYPTPW + help + Possible choices are "d[es]", "m[d5]", "s[ha256]" or "sha512". + +config BUSYBOX_CONFIG_SU + bool "su" + default BUSYBOX_DEFAULT_SU + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + su is used to become another user during a login session. + Invoked without a username, su defaults to becoming the super user. + + Note that Busybox binary must be setuid root for this applet to + work properly. + +config BUSYBOX_CONFIG_FEATURE_SU_SYSLOG + bool "Enable su to write to syslog" + default BUSYBOX_DEFAULT_FEATURE_SU_SYSLOG + depends on BUSYBOX_CONFIG_SU + +config BUSYBOX_CONFIG_FEATURE_SU_CHECKS_SHELLS + bool "Enable su to check user's shell to be listed in /etc/shells" + depends on BUSYBOX_CONFIG_SU + default BUSYBOX_DEFAULT_FEATURE_SU_CHECKS_SHELLS + +config BUSYBOX_CONFIG_SULOGIN + bool "sulogin" + default BUSYBOX_DEFAULT_SULOGIN + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + sulogin is invoked when the system goes into single user + mode (this is done through an entry in inittab). + +config BUSYBOX_CONFIG_VLOCK + bool "vlock" + default BUSYBOX_DEFAULT_VLOCK + help + Build the "vlock" applet which allows you to lock (virtual) terminals. + + Note that Busybox binary must be setuid root for this applet to + work properly. + +endmenu diff --git a/package/utils/busybox/config/mailutils/Config.in b/package/utils/busybox/config/mailutils/Config.in new file mode 100644 index 0000000..64b9a2b --- /dev/null +++ b/package/utils/busybox/config/mailutils/Config.in @@ -0,0 +1,55 @@ +# DO NOT EDIT. This file is generated from Config.src +menu "Mail Utilities" + + +config BUSYBOX_CONFIG_MAKEMIME + bool "makemime" + default BUSYBOX_DEFAULT_MAKEMIME + help + Create MIME-formatted messages. + +config BUSYBOX_CONFIG_FEATURE_MIME_CHARSET + string "Default charset" + default BUSYBOX_DEFAULT_FEATURE_MIME_CHARSET + depends on BUSYBOX_CONFIG_MAKEMIME || BUSYBOX_CONFIG_REFORMIME || BUSYBOX_CONFIG_SENDMAIL + help + Default charset of the message. + +config BUSYBOX_CONFIG_POPMAILDIR + bool "popmaildir" + default BUSYBOX_DEFAULT_POPMAILDIR + help + Simple yet powerful POP3 mail popper. Delivers content + of remote mailboxes to local Maildir. + +config BUSYBOX_CONFIG_FEATURE_POPMAILDIR_DELIVERY + bool "Allow message filters and custom delivery program" + default BUSYBOX_DEFAULT_FEATURE_POPMAILDIR_DELIVERY + depends on BUSYBOX_CONFIG_POPMAILDIR + help + Allow to use a custom program to filter the content + of the message before actual delivery (-F "prog [args...]"). + Allow to use a custom program for message actual delivery + (-M "prog [args...]"). + +config BUSYBOX_CONFIG_REFORMIME + bool "reformime" + default BUSYBOX_DEFAULT_REFORMIME + help + Parse MIME-formatted messages. + +config BUSYBOX_CONFIG_FEATURE_REFORMIME_COMPAT + bool "Accept and ignore options other than -x and -X" + default BUSYBOX_DEFAULT_FEATURE_REFORMIME_COMPAT + depends on BUSYBOX_CONFIG_REFORMIME + help + Accept (for compatibility only) and ignore options + other than -x and -X. + +config BUSYBOX_CONFIG_SENDMAIL + bool "sendmail" + default BUSYBOX_DEFAULT_SENDMAIL + help + Barebones sendmail. + +endmenu diff --git a/package/utils/busybox/config/miscutils/Config.in b/package/utils/busybox/config/miscutils/Config.in new file mode 100644 index 0000000..7819e30 --- /dev/null +++ b/package/utils/busybox/config/miscutils/Config.in @@ -0,0 +1,760 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Miscellaneous Utilities" + +config BUSYBOX_CONFIG_CONSPY + bool "conspy" + default BUSYBOX_DEFAULT_CONSPY + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + A text-mode VNC like program for Linux virtual terminals. + example: conspy NUM shared access to console num + or conspy -nd NUM screenshot of console num + or conspy -cs NUM poor man's GNU screen like +config BUSYBOX_CONFIG_CROND + bool "crond" + default BUSYBOX_DEFAULT_CROND + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + Crond is a background daemon that parses individual crontab + files and executes commands on behalf of the users in question. + This is a port of dcron from slackware. It uses files of the + format /var/spool/cron/crontabs/<username> files, for example: + $ cat /var/spool/cron/crontabs/root + # Run daily cron jobs at 4:40 every day: + 40 4 * * * /etc/cron/daily > /dev/null 2>&1 + +config BUSYBOX_CONFIG_FEATURE_CROND_D + bool "Support option -d to redirect output to stderr" + depends on BUSYBOX_CONFIG_CROND + default BUSYBOX_DEFAULT_FEATURE_CROND_D + help + -d N sets loglevel (0:most verbose) and directs all output to stderr. + +config BUSYBOX_CONFIG_FEATURE_CROND_CALL_SENDMAIL + bool "Report command output via email (using sendmail)" + default BUSYBOX_DEFAULT_FEATURE_CROND_CALL_SENDMAIL + depends on BUSYBOX_CONFIG_CROND + help + Command output will be sent to corresponding user via email. + +config BUSYBOX_CONFIG_FEATURE_CROND_DIR + string "crond spool directory" + default BUSYBOX_DEFAULT_FEATURE_CROND_DIR + depends on BUSYBOX_CONFIG_CROND || BUSYBOX_CONFIG_CRONTAB + help + Location of crond spool. +config BUSYBOX_CONFIG_LESS + bool "less" + default BUSYBOX_DEFAULT_LESS + help + 'less' is a pager, meaning that it displays text files. It possesses + a wide array of features, and is an improvement over 'more'. + +config BUSYBOX_CONFIG_FEATURE_LESS_MAXLINES + int "Max number of input lines less will try to eat" + default BUSYBOX_DEFAULT_FEATURE_LESS_MAXLINES + depends on BUSYBOX_CONFIG_LESS + +config BUSYBOX_CONFIG_FEATURE_LESS_BRACKETS + bool "Enable bracket searching" + default BUSYBOX_DEFAULT_FEATURE_LESS_BRACKETS + depends on BUSYBOX_CONFIG_LESS + help + This option adds the capability to search for matching left and right + brackets, facilitating programming. + +config BUSYBOX_CONFIG_FEATURE_LESS_FLAGS + bool "Enable -m/-M" + default BUSYBOX_DEFAULT_FEATURE_LESS_FLAGS + depends on BUSYBOX_CONFIG_LESS + help + The -M/-m flag enables a more sophisticated status line. + +config BUSYBOX_CONFIG_FEATURE_LESS_MARKS + bool "Enable marks" + default BUSYBOX_DEFAULT_FEATURE_LESS_MARKS + depends on BUSYBOX_CONFIG_LESS + help + Marks enable positions in a file to be stored for easy reference. + +config BUSYBOX_CONFIG_FEATURE_LESS_REGEXP + bool "Enable regular expressions" + default BUSYBOX_DEFAULT_FEATURE_LESS_REGEXP + depends on BUSYBOX_CONFIG_LESS + help + Enable regular expressions, allowing complex file searches. + +config BUSYBOX_CONFIG_FEATURE_LESS_WINCH + bool "Enable automatic resizing on window size changes" + default BUSYBOX_DEFAULT_FEATURE_LESS_WINCH + depends on BUSYBOX_CONFIG_LESS + help + Makes less track window size changes. + +config BUSYBOX_CONFIG_FEATURE_LESS_ASK_TERMINAL + bool "Use 'tell me cursor position' ESC sequence to measure window" + default BUSYBOX_DEFAULT_FEATURE_LESS_ASK_TERMINAL + depends on BUSYBOX_CONFIG_FEATURE_LESS_WINCH + help + Makes less track window size changes. + If terminal size can't be retrieved and $LINES/$COLUMNS are not set, + this option makes less perform a last-ditch effort to find it: + position cursor to 999,999 and ask terminal to report real + cursor position using "ESC [ 6 n" escape sequence, then read stdin. + + This is not clean but helps a lot on serial lines and such. + +config BUSYBOX_CONFIG_FEATURE_LESS_DASHCMD + bool "Enable flag changes ('-' command)" + default BUSYBOX_DEFAULT_FEATURE_LESS_DASHCMD + depends on BUSYBOX_CONFIG_LESS + help + This enables the ability to change command-line flags within + less itself ('-' keyboard command). + +config BUSYBOX_CONFIG_FEATURE_LESS_LINENUMS + bool "Enable dynamic switching of line numbers" + default BUSYBOX_DEFAULT_FEATURE_LESS_LINENUMS + depends on BUSYBOX_CONFIG_FEATURE_LESS_DASHCMD + help + Enables "-N" command. +config BUSYBOX_CONFIG_NANDWRITE + bool "nandwrite" + default BUSYBOX_DEFAULT_NANDWRITE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Write to the specified MTD device, with bad blocks awareness + +config BUSYBOX_CONFIG_NANDDUMP + bool "nanddump" + default BUSYBOX_DEFAULT_NANDDUMP + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Dump the content of raw NAND chip +config BUSYBOX_CONFIG_RFKILL + bool "rfkill" + default BUSYBOX_DEFAULT_RFKILL # doesn't build on Ubuntu 9.04 + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Enable/disable wireless devices. + + rfkill list : list all wireless devices + rfkill list bluetooth : list all bluetooth devices + rfkill list 1 : list device corresponding to the given index + rfkill block|unblock wlan : block/unblock all wlan(wifi) devices + +config BUSYBOX_CONFIG_SETSERIAL + bool "setserial" + default BUSYBOX_DEFAULT_SETSERIAL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Retrieve or set Linux serial port. +config BUSYBOX_CONFIG_TASKSET + bool "taskset" + default BUSYBOX_DEFAULT_TASKSET # doesn't build on some non-x86 targets (m68k) + help + Retrieve or set a processes's CPU affinity. + This requires sched_{g,s}etaffinity support in your libc. + +config BUSYBOX_CONFIG_FEATURE_TASKSET_FANCY + bool "Fancy output" + default BUSYBOX_DEFAULT_FEATURE_TASKSET_FANCY + depends on BUSYBOX_CONFIG_TASKSET + help + Add code for fancy output. This merely silences a compiler-warning + and adds about 135 Bytes. May be needed for machines with alot + of CPUs. +config BUSYBOX_CONFIG_UBIATTACH + bool "ubiattach" + default BUSYBOX_DEFAULT_UBIATTACH + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Attach MTD device to an UBI device. + +config BUSYBOX_CONFIG_UBIDETACH + bool "ubidetach" + default BUSYBOX_DEFAULT_UBIDETACH + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Detach MTD device from an UBI device. + +config BUSYBOX_CONFIG_UBIMKVOL + bool "ubimkvol" + default BUSYBOX_DEFAULT_UBIMKVOL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Create a UBI volume. + +config BUSYBOX_CONFIG_UBIRMVOL + bool "ubirmvol" + default BUSYBOX_DEFAULT_UBIRMVOL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Delete a UBI volume. + +config BUSYBOX_CONFIG_UBIRSVOL + bool "ubirsvol" + default BUSYBOX_DEFAULT_UBIRSVOL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Resize a UBI volume. + +config BUSYBOX_CONFIG_UBIUPDATEVOL + bool "ubiupdatevol" + default BUSYBOX_DEFAULT_UBIUPDATEVOL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Update a UBI volume. +config BUSYBOX_CONFIG_WALL + bool "wall" + default BUSYBOX_DEFAULT_WALL + depends on BUSYBOX_CONFIG_FEATURE_UTMP + help + Write a message to all users that are logged in. + +config BUSYBOX_CONFIG_ADJTIMEX + bool "adjtimex" + default BUSYBOX_DEFAULT_ADJTIMEX + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Adjtimex reads and optionally sets adjustment parameters for + the Linux clock adjustment algorithm. + +config BUSYBOX_CONFIG_BBCONFIG + bool "bbconfig" + default BUSYBOX_DEFAULT_BBCONFIG + help + The bbconfig applet will print the config file with which + busybox was built. + +config BUSYBOX_CONFIG_FEATURE_COMPRESS_BBCONFIG + bool "Compress bbconfig data" + default BUSYBOX_DEFAULT_FEATURE_COMPRESS_BBCONFIG + depends on BUSYBOX_CONFIG_BBCONFIG + help + Store bbconfig data in compressed form, uncompress them on-the-fly + before output. + + If you have a really tiny busybox with few applets enabled (and + bunzip2 isn't one of them), the overhead of the decompressor might + be noticeable. Also, if you run executables directly from ROM + and have very little memory, this might not be a win. Otherwise, + you probably want this. + +config BUSYBOX_CONFIG_BEEP + bool "beep" + default BUSYBOX_DEFAULT_BEEP + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + The beep applets beeps in a given freq/Hz. + +config BUSYBOX_CONFIG_FEATURE_BEEP_FREQ + int "default frequency" + range 0 2147483647 + default BUSYBOX_DEFAULT_FEATURE_BEEP_FREQ + depends on BUSYBOX_CONFIG_BEEP + help + Frequency for default beep. + +config BUSYBOX_CONFIG_FEATURE_BEEP_LENGTH_MS + int "default length" + range 0 2147483647 + default BUSYBOX_DEFAULT_FEATURE_BEEP_LENGTH_MS + depends on BUSYBOX_CONFIG_BEEP + help + Length in ms for default beep. + +config BUSYBOX_CONFIG_CHAT + bool "chat" + default BUSYBOX_DEFAULT_CHAT + help + Simple chat utility. + +config BUSYBOX_CONFIG_FEATURE_CHAT_NOFAIL + bool "Enable NOFAIL expect strings" + depends on BUSYBOX_CONFIG_CHAT + default BUSYBOX_DEFAULT_FEATURE_CHAT_NOFAIL + help + When enabled expect strings which are started with a dash trigger + no-fail mode. That is when expectation is not met within timeout + the script is not terminated but sends next SEND string and waits + for next EXPECT string. This allows to compose far more flexible + scripts. + +config BUSYBOX_CONFIG_FEATURE_CHAT_TTY_HIFI + bool "Force STDIN to be a TTY" + depends on BUSYBOX_CONFIG_CHAT + default BUSYBOX_DEFAULT_FEATURE_CHAT_TTY_HIFI + help + Original chat always treats STDIN as a TTY device and sets for it + so-called raw mode. This option turns on such behaviour. + +config BUSYBOX_CONFIG_FEATURE_CHAT_IMPLICIT_CR + bool "Enable implicit Carriage Return" + depends on BUSYBOX_CONFIG_CHAT + default BUSYBOX_DEFAULT_FEATURE_CHAT_IMPLICIT_CR + help + When enabled make chat to terminate all SEND strings with a "\r" + unless "\c" is met anywhere in the string. + +config BUSYBOX_CONFIG_FEATURE_CHAT_SWALLOW_OPTS + bool "Swallow options" + depends on BUSYBOX_CONFIG_CHAT + default BUSYBOX_DEFAULT_FEATURE_CHAT_SWALLOW_OPTS + help + Busybox chat require no options. To make it not fail when used + in place of original chat (which has a bunch of options) turn + this on. + +config BUSYBOX_CONFIG_FEATURE_CHAT_SEND_ESCAPES + bool "Support weird SEND escapes" + depends on BUSYBOX_CONFIG_CHAT + default BUSYBOX_DEFAULT_FEATURE_CHAT_SEND_ESCAPES + help + Original chat uses some escape sequences in SEND arguments which + are not sent to device but rather performs special actions. + E.g. "\K" means to send a break sequence to device. + "\d" delays execution for a second, "\p" -- for a 1/100 of second. + Before turning this option on think twice: do you really need them? + +config BUSYBOX_CONFIG_FEATURE_CHAT_VAR_ABORT_LEN + bool "Support variable-length ABORT conditions" + depends on BUSYBOX_CONFIG_CHAT + default BUSYBOX_DEFAULT_FEATURE_CHAT_VAR_ABORT_LEN + help + Original chat uses fixed 50-bytes length ABORT conditions. Say N here. + +config BUSYBOX_CONFIG_FEATURE_CHAT_CLR_ABORT + bool "Support revoking of ABORT conditions" + depends on BUSYBOX_CONFIG_CHAT + default BUSYBOX_DEFAULT_FEATURE_CHAT_CLR_ABORT + help + Support CLR_ABORT directive. + +config BUSYBOX_CONFIG_CHRT + bool "chrt" + default BUSYBOX_DEFAULT_CHRT + help + manipulate real-time attributes of a process. + This requires sched_{g,s}etparam support in your libc. + +config BUSYBOX_CONFIG_CRONTAB + bool "crontab" + default BUSYBOX_DEFAULT_CRONTAB + help + Crontab manipulates the crontab for a particular user. Only + the superuser may specify a different user and/or crontab directory. + Note that Busybox binary must be setuid root for this applet to + work properly. + +config BUSYBOX_CONFIG_DC + bool "dc" + default BUSYBOX_DEFAULT_DC + help + Dc is a reverse-polish desk calculator which supports unlimited + precision arithmetic. + +config BUSYBOX_CONFIG_FEATURE_DC_LIBM + bool "Enable power and exp functions (requires libm)" + default BUSYBOX_DEFAULT_FEATURE_DC_LIBM + depends on BUSYBOX_CONFIG_DC + help + Enable power and exp functions. + NOTE: This will require libm to be present for linking. + +config BUSYBOX_CONFIG_DEVFSD + bool "devfsd (obsolete)" + default BUSYBOX_DEFAULT_DEVFSD + select BUSYBOX_CONFIG_PLATFORM_LINUX + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + This is deprecated and should NOT be used anymore. + Use linux >= 2.6 (optionally with hotplug) and mdev instead! + See docs/mdev.txt for detailed instructions on how to use mdev + instead. + + Provides compatibility with old device names on a devfs systems. + You should set it to true if you have devfs enabled. + The following keywords in devsfd.conf are supported: + "CLEAR_CONFIG", "INCLUDE", "OPTIONAL_INCLUDE", "RESTORE", + "PERMISSIONS", "EXECUTE", "COPY", "IGNORE", + "MKOLDCOMPAT", "MKNEWCOMPAT","RMOLDCOMPAT", "RMNEWCOMPAT". + + But only if they are written UPPERCASE!!!!!!!! + +config BUSYBOX_CONFIG_DEVFSD_MODLOAD + bool "Adds support for MODLOAD keyword in devsfd.conf" + default BUSYBOX_DEFAULT_DEVFSD_MODLOAD + depends on BUSYBOX_CONFIG_DEVFSD + help + This actually doesn't work with busybox modutils but needs + the external modutils. + +config BUSYBOX_CONFIG_DEVFSD_FG_NP + bool "Enables the -fg and -np options" + default BUSYBOX_DEFAULT_DEVFSD_FG_NP + depends on BUSYBOX_CONFIG_DEVFSD + help + -fg Run the daemon in the foreground. + -np Exit after parsing the configuration file. + Do not poll for events. + +config BUSYBOX_CONFIG_DEVFSD_VERBOSE + bool "Increases logging (and size)" + default BUSYBOX_DEFAULT_DEVFSD_VERBOSE + depends on BUSYBOX_CONFIG_DEVFSD + help + Increases logging to stderr or syslog. + +config BUSYBOX_CONFIG_FEATURE_DEVFS + bool "Use devfs names for all devices (obsolete)" + default BUSYBOX_DEFAULT_FEATURE_DEVFS + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This is obsolete and should NOT be used anymore. + Use linux >= 2.6 (optionally with hotplug) and mdev instead! + + For legacy systems -- if there is no way around devfsd -- this + tells busybox to look for names like /dev/loop/0 instead of + /dev/loop0. If your /dev directory has normal names instead of + devfs names, you don't want this. + +config BUSYBOX_CONFIG_DEVMEM + bool "devmem" + default BUSYBOX_DEFAULT_DEVMEM + help + devmem is a small program that reads and writes from physical + memory using /dev/mem. + +config BUSYBOX_CONFIG_EJECT + bool "eject" + default BUSYBOX_DEFAULT_EJECT + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Used to eject cdroms. (defaults to /dev/cdrom) + +config BUSYBOX_CONFIG_FEATURE_EJECT_SCSI + bool "SCSI support" + default BUSYBOX_DEFAULT_FEATURE_EJECT_SCSI + depends on BUSYBOX_CONFIG_EJECT + help + Add the -s option to eject, this allows to eject SCSI-Devices and + usb-storage devices. + +config BUSYBOX_CONFIG_FBSPLASH + bool "fbsplash" + default BUSYBOX_DEFAULT_FBSPLASH + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Shows splash image and progress bar on framebuffer device. + Can be used during boot phase of an embedded device. ~2kb. + Usage: + - use kernel option 'vga=xxx' or otherwise enable fb device. + - put somewhere fbsplash.cfg file and an image in .ppm format. + - $ setsid fbsplash [params] & + -c: hide cursor + -d /dev/fbN: framebuffer device (if not /dev/fb0) + -s path_to_image_file (can be "-" for stdin) + -i path_to_cfg_file (can be "-" for stdin) + -f path_to_fifo (can be "-" for stdin) + - if you want to run it only in presence of kernel parameter: + grep -q "fbsplash=on" </proc/cmdline && setsid fbsplash [params] & + - commands for fifo: + "NN" (ASCII decimal number) - percentage to show on progress bar + "exit" - well you guessed it + +config BUSYBOX_CONFIG_FLASHCP + bool "flashcp" + default BUSYBOX_DEFAULT_FLASHCP # doesn't build on Ubuntu 8.04 + help + The flashcp binary, inspired by mtd-utils as of git head 5eceb74f7. + This utility is used to copy images into a MTD device. + +config BUSYBOX_CONFIG_FLASH_LOCK + bool "flash_lock" + default BUSYBOX_DEFAULT_FLASH_LOCK # doesn't build on Ubuntu 8.04 + help + The flash_lock binary from mtd-utils as of git head 5ec0c10d0. This + utility locks part or all of the flash device. + +config BUSYBOX_CONFIG_FLASH_UNLOCK + bool "flash_unlock" + default BUSYBOX_DEFAULT_FLASH_UNLOCK # doesn't build on Ubuntu 8.04 + help + The flash_unlock binary from mtd-utils as of git head 5ec0c10d0. This + utility unlocks part or all of the flash device. + +config BUSYBOX_CONFIG_FLASH_ERASEALL + bool "flash_eraseall" + default BUSYBOX_DEFAULT_FLASH_ERASEALL # doesn't build on Ubuntu 8.04 + help + The flash_eraseall binary from mtd-utils as of git head c4c6a59eb. + This utility is used to erase the whole MTD device. + +config BUSYBOX_CONFIG_IONICE + bool "ionice" + default BUSYBOX_DEFAULT_IONICE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Set/set program io scheduling class and priority + Requires kernel >= 2.6.13 + +config BUSYBOX_CONFIG_INOTIFYD + bool "inotifyd" + default BUSYBOX_DEFAULT_INOTIFYD # doesn't build on Knoppix 5 + help + Simple inotify daemon. Reports filesystem changes. Requires + kernel >= 2.6.13 + +config BUSYBOX_CONFIG_LAST + bool "last" + default BUSYBOX_DEFAULT_LAST + depends on BUSYBOX_CONFIG_FEATURE_WTMP + help + 'last' displays a list of the last users that logged into the system. + +choice + prompt "Choose last implementation" + depends on BUSYBOX_CONFIG_LAST + default BUSYBOX_CONFIG_FEATURE_LAST_FANCY + +config BUSYBOX_CONFIG_FEATURE_LAST_SMALL + bool "small" + help + This is a small version of last with just the basic set of + features. + +config BUSYBOX_CONFIG_FEATURE_LAST_FANCY + bool "huge" + help + 'last' displays detailed information about the last users that + logged into the system (mimics sysvinit last). +900 bytes. +endchoice + +config BUSYBOX_CONFIG_HDPARM + bool "hdparm" + default BUSYBOX_DEFAULT_HDPARM + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Get/Set hard drive parameters. Primarily intended for ATA + drives. Adds about 13k (or around 30k if you enable the + FEATURE_HDPARM_GET_IDENTITY option).... + +config BUSYBOX_CONFIG_FEATURE_HDPARM_GET_IDENTITY + bool "Support obtaining detailed information directly from drives" + default BUSYBOX_DEFAULT_FEATURE_HDPARM_GET_IDENTITY + depends on BUSYBOX_CONFIG_HDPARM + help + Enables the -I and -i options to obtain detailed information + directly from drives about their capabilities and supported ATA + feature set. If no device name is specified, hdparm will read + identify data from stdin. Enabling this option will add about 16k... + +config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF + bool "Register an IDE interface (DANGEROUS)" + default BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_SCAN_HWIF + depends on BUSYBOX_CONFIG_HDPARM + help + Enables the 'hdparm -R' option to register an IDE interface. + This is dangerous stuff, so you should probably say N. + +config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF + bool "Un-register an IDE interface (DANGEROUS)" + default BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF + depends on BUSYBOX_CONFIG_HDPARM + help + Enables the 'hdparm -U' option to un-register an IDE interface. + This is dangerous stuff, so you should probably say N. + +config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET + bool "Perform device reset (DANGEROUS)" + default BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_DRIVE_RESET + depends on BUSYBOX_CONFIG_HDPARM + help + Enables the 'hdparm -w' option to perform a device reset. + This is dangerous stuff, so you should probably say N. + +config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF + bool "Tristate device for hotswap (DANGEROUS)" + default BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_TRISTATE_HWIF + depends on BUSYBOX_CONFIG_HDPARM + help + Enables the 'hdparm -x' option to tristate device for hotswap, + and the '-b' option to get/set bus state. This is dangerous + stuff, so you should probably say N. + +config BUSYBOX_CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA + bool "Get/set using_dma flag" + default BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_GETSET_DMA + depends on BUSYBOX_CONFIG_HDPARM + help + Enables the 'hdparm -d' option to get/set using_dma flag. + +config BUSYBOX_CONFIG_LOCK + bool "lock" + default BUSYBOX_DEFAULT_LOCK + help + Small utility for using locks in scripts + +config BUSYBOX_CONFIG_MAKEDEVS + bool "makedevs" + default BUSYBOX_DEFAULT_MAKEDEVS + help + 'makedevs' is a utility used to create a batch of devices with + one command. + + There are two choices for command line behaviour, the interface + as used by LEAF/Linux Router Project, or a device table file. + + 'leaf' is traditionally what busybox follows, it allows multiple + devices of a particluar type to be created per command. + e.g. /dev/hda[0-9] + Device properties are passed as command line arguments. + + 'table' reads device properties from a file or stdin, allowing + a batch of unrelated devices to be made with one command. + User/group names are allowed as an alternative to uid/gid. + +choice + prompt "Choose makedevs behaviour" + depends on BUSYBOX_CONFIG_MAKEDEVS + default BUSYBOX_CONFIG_FEATURE_MAKEDEVS_TABLE + +config BUSYBOX_CONFIG_FEATURE_MAKEDEVS_LEAF + bool "leaf" + +config BUSYBOX_CONFIG_FEATURE_MAKEDEVS_TABLE + bool "table" + +endchoice + +config BUSYBOX_CONFIG_MAN + bool "man" + default BUSYBOX_DEFAULT_MAN + help + Format and display manual pages. + +config BUSYBOX_CONFIG_MICROCOM + bool "microcom" + default BUSYBOX_DEFAULT_MICROCOM + help + The poor man's minicom utility for chatting with serial port devices. + +config BUSYBOX_CONFIG_MOUNTPOINT + bool "mountpoint" + default BUSYBOX_DEFAULT_MOUNTPOINT + help + mountpoint checks if the directory is a mountpoint. + +config BUSYBOX_CONFIG_MT + bool "mt" + default BUSYBOX_DEFAULT_MT + help + mt is used to control tape devices. You can use the mt utility + to advance or rewind a tape past a specified number of archive + files on the tape. + +config BUSYBOX_CONFIG_RAIDAUTORUN + bool "raidautorun" + default BUSYBOX_DEFAULT_RAIDAUTORUN + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + raidautorun tells the kernel md driver to + search and start RAID arrays. + +config BUSYBOX_CONFIG_READAHEAD + bool "readahead" + default BUSYBOX_DEFAULT_READAHEAD + depends on BUSYBOX_CONFIG_LFS + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Preload the files listed on the command line into RAM cache so that + subsequent reads on these files will not block on disk I/O. + + This applet just calls the readahead(2) system call on each file. + It is mainly useful in system startup scripts to preload files + or executables before they are used. When used at the right time + (in particular when a CPU bound process is running) it can + significantly speed up system startup. + + As readahead(2) blocks until each file has been read, it is best to + run this applet as a background job. + +config BUSYBOX_CONFIG_RUNLEVEL + bool "runlevel" + default BUSYBOX_DEFAULT_RUNLEVEL + depends on BUSYBOX_CONFIG_FEATURE_UTMP + help + find the current and previous system runlevel. + + This applet uses utmp but does not rely on busybox supporing + utmp on purpose. It is used by e.g. emdebian via /etc/init.d/rc. + +config BUSYBOX_CONFIG_RX + bool "rx" + default BUSYBOX_DEFAULT_RX + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Receive files using the Xmodem protocol. + +config BUSYBOX_CONFIG_SETSID + bool "setsid" + default BUSYBOX_DEFAULT_SETSID + help + setsid runs a program in a new session + +config BUSYBOX_CONFIG_STRINGS + bool "strings" + default BUSYBOX_DEFAULT_STRINGS + help + strings prints the printable character sequences for each file + specified. + +config BUSYBOX_CONFIG_TIME + bool "time" + default BUSYBOX_DEFAULT_TIME + help + The time command runs the specified program with the given arguments. + When the command finishes, time writes a message to standard output + giving timing statistics about this program run. + +config BUSYBOX_CONFIG_TIMEOUT + bool "timeout" + default BUSYBOX_DEFAULT_TIMEOUT + help + Runs a program and watches it. If it does not terminate in + specified number of seconds, it is sent a signal. + +config BUSYBOX_CONFIG_TTYSIZE + bool "ttysize" + default BUSYBOX_DEFAULT_TTYSIZE + help + A replacement for "stty size". Unlike stty, can report only width, + only height, or both, in any order. It also does not complain on + error, but returns default 80x24. + Usage in shell scripts: width=`ttysize w`. + +config BUSYBOX_CONFIG_VOLNAME + bool "volname" + default BUSYBOX_DEFAULT_VOLNAME + help + Prints a CD-ROM volume name. + +config BUSYBOX_CONFIG_WATCHDOG + bool "watchdog" + default BUSYBOX_DEFAULT_WATCHDOG + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + The watchdog utility is used with hardware or software watchdog + device drivers. It opens the specified watchdog device special file + and periodically writes a magic character to the device. If the + watchdog applet ever fails to write the magic character within a + certain amount of time, the watchdog device assumes the system has + hung, and will cause the hardware to reboot. + +endmenu diff --git a/package/utils/busybox/config/modutils/Config.in b/package/utils/busybox/config/modutils/Config.in new file mode 100644 index 0000000..9add56e --- /dev/null +++ b/package/utils/busybox/config/modutils/Config.in @@ -0,0 +1,269 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Linux Module Utilities" + +config BUSYBOX_CONFIG_MODINFO + bool "modinfo" + default BUSYBOX_DEFAULT_MODINFO + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Show information about a Linux Kernel module + +config BUSYBOX_CONFIG_MODPROBE_SMALL + bool "Simplified modutils" + default BUSYBOX_DEFAULT_MODPROBE_SMALL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Simplified modutils. + + With this option modprobe does not require modules.dep file + and does not use /etc/modules.conf file. + It scans module files in /lib/modules/`uname -r` and + determines dependencies and module alias names on the fly. + This may make module loading slower, most notably + when one needs to load module by alias (this requires + scanning through module _bodies_). + + At the first attempt to load a module by alias modprobe + will try to generate modules.dep.bb file in order to speed up + future loads by alias. Failure to do so (read-only /lib/modules, + etc) is not reported, and future modprobes will be slow too. + + NB: modules.dep.bb file format is not compatible + with modules.dep file as created/used by standard module tools. + + Additional module parameters can be stored in + /etc/modules/$module_name files. + + Apart from modprobe, other utilities are also provided: + - insmod is an alias to modprobe + - rmmod is an alias to modprobe -r + - depmod generates modules.dep.bb + + As of 2008-07, this code is experimental. It is 14kb smaller + than "non-small" modutils. + +config BUSYBOX_CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE + bool "Accept module options on modprobe command line" + default BUSYBOX_DEFAULT_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE + depends on BUSYBOX_CONFIG_MODPROBE_SMALL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Allow insmod and modprobe take module options from command line. + +config BUSYBOX_CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED + bool "Skip loading of already loaded modules" + default BUSYBOX_DEFAULT_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED + depends on BUSYBOX_CONFIG_MODPROBE_SMALL + help + Check if the module is already loaded. + +config BUSYBOX_CONFIG_INSMOD + bool "insmod" + default BUSYBOX_DEFAULT_INSMOD + depends on !BUSYBOX_CONFIG_MODPROBE_SMALL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + insmod is used to load specified modules in the running kernel. + +config BUSYBOX_CONFIG_RMMOD + bool "rmmod" + default BUSYBOX_DEFAULT_RMMOD + depends on !BUSYBOX_CONFIG_MODPROBE_SMALL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + rmmod is used to unload specified modules from the kernel. + +config BUSYBOX_CONFIG_LSMOD + bool "lsmod" + default BUSYBOX_DEFAULT_LSMOD + depends on !BUSYBOX_CONFIG_MODPROBE_SMALL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + lsmod is used to display a list of loaded modules. + +config BUSYBOX_CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT + bool "Pretty output" + default BUSYBOX_DEFAULT_FEATURE_LSMOD_PRETTY_2_6_OUTPUT + depends on BUSYBOX_CONFIG_LSMOD + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This option makes output format of lsmod adjusted to + the format of module-init-tools for Linux kernel 2.6. + Increases size somewhat. + +config BUSYBOX_CONFIG_MODPROBE + bool "modprobe" + default BUSYBOX_DEFAULT_MODPROBE + depends on !BUSYBOX_CONFIG_MODPROBE_SMALL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Handle the loading of modules, and their dependencies on a high + level. + +config BUSYBOX_CONFIG_FEATURE_MODPROBE_BLACKLIST + bool "Blacklist support" + default BUSYBOX_DEFAULT_FEATURE_MODPROBE_BLACKLIST + depends on BUSYBOX_CONFIG_MODPROBE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Say 'y' here to enable support for the 'blacklist' command in + modprobe.conf. This prevents the alias resolver to resolve + blacklisted modules. This is useful if you want to prevent your + hardware autodetection scripts to load modules like evdev, frame + buffer drivers etc. + +config BUSYBOX_CONFIG_DEPMOD + bool "depmod" + default BUSYBOX_DEFAULT_DEPMOD + depends on !BUSYBOX_CONFIG_MODPROBE_SMALL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + depmod generates modules.dep (and potentially modules.alias + and modules.symbols) that contain dependency information + for modprobe. + +comment "Options common to multiple modutils" + +config BUSYBOX_CONFIG_FEATURE_2_4_MODULES + bool "Support version 2.2/2.4 Linux kernels" + default BUSYBOX_DEFAULT_FEATURE_2_4_MODULES + depends on BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_RMMOD || BUSYBOX_CONFIG_LSMOD + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Support module loading for 2.2.x and 2.4.x Linux kernels. + This increases size considerably. Say N unless you plan + to run ancient kernels. + +config BUSYBOX_CONFIG_FEATURE_INSMOD_TRY_MMAP + bool "Try to load module from a mmap'ed area" + default BUSYBOX_DEFAULT_FEATURE_INSMOD_TRY_MMAP + depends on BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE_SMALL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This option causes module loading code to try to mmap + module first. If it does not work (for example, + it does not work for compressed modules), module will be read + (and unpacked if needed) into a memory block allocated by malloc. + + The only case when mmap works but malloc does not is when + you are trying to load a big module on a very memory-constrained + machine. Malloc will momentarily need 2x as much memory as mmap. + + Choosing N saves about 250 bytes of code (on 32-bit x86). + +config BUSYBOX_CONFIG_FEATURE_INSMOD_VERSION_CHECKING + bool "Enable module version checking" + default BUSYBOX_DEFAULT_FEATURE_INSMOD_VERSION_CHECKING + depends on BUSYBOX_CONFIG_FEATURE_2_4_MODULES && (BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE) + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Support checking of versions for modules. This is used to + ensure that the kernel and module are made for each other. + +config BUSYBOX_CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS + bool "Add module symbols to kernel symbol table" + default BUSYBOX_DEFAULT_FEATURE_INSMOD_KSYMOOPS_SYMBOLS + depends on BUSYBOX_CONFIG_FEATURE_2_4_MODULES && (BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE) + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + By adding module symbols to the kernel symbol table, Oops messages + occuring within kernel modules can be properly debugged. By enabling + this feature, module symbols will always be added to the kernel symbol + table for proper debugging support. If you are not interested in + Oops messages from kernel modules, say N. + +config BUSYBOX_CONFIG_FEATURE_INSMOD_LOADINKMEM + bool "In kernel memory optimization (uClinux only)" + default BUSYBOX_DEFAULT_FEATURE_INSMOD_LOADINKMEM + depends on BUSYBOX_CONFIG_FEATURE_2_4_MODULES && (BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_MODPROBE) + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This is a special uClinux only memory optimization that lets insmod + load the specified kernel module directly into kernel space, reducing + memory usage by preventing the need for two copies of the module + being loaded into memory. + +config BUSYBOX_CONFIG_FEATURE_INSMOD_LOAD_MAP + bool "Enable insmod load map (-m) option" + default BUSYBOX_DEFAULT_FEATURE_INSMOD_LOAD_MAP + depends on BUSYBOX_CONFIG_FEATURE_2_4_MODULES && BUSYBOX_CONFIG_INSMOD + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Enabling this, one would be able to get a load map + output on stdout. This makes kernel module debugging + easier. + If you don't plan to debug kernel modules, you + don't need this option. + +config BUSYBOX_CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL + bool "Symbols in load map" + default BUSYBOX_DEFAULT_FEATURE_INSMOD_LOAD_MAP_FULL + depends on BUSYBOX_CONFIG_FEATURE_INSMOD_LOAD_MAP && !BUSYBOX_CONFIG_MODPROBE_SMALL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Without this option, -m will only output section + load map. With this option, -m will also output + symbols load map. + +config BUSYBOX_CONFIG_FEATURE_CHECK_TAINTED_MODULE + bool "Support tainted module checking with new kernels" + default BUSYBOX_DEFAULT_FEATURE_CHECK_TAINTED_MODULE + depends on (BUSYBOX_CONFIG_LSMOD || BUSYBOX_CONFIG_FEATURE_2_4_MODULES) && !BUSYBOX_CONFIG_MODPROBE_SMALL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Support checking for tainted modules. These are usually binary + only modules that will make the linux-kernel list ignore your + support request. + This option is required to support GPLONLY modules. + +config BUSYBOX_CONFIG_FEATURE_MODUTILS_ALIAS + bool "Support for module.aliases file" + default BUSYBOX_DEFAULT_FEATURE_MODUTILS_ALIAS + depends on BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_MODPROBE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Generate and parse modules.alias containing aliases for bus + identifiers: + alias pcmcia:m*c*f03fn*pfn*pa*pb*pc*pd* parport_cs + + and aliases for logical modules names e.g.: + alias padlock_aes aes + alias aes_i586 aes + alias aes_generic aes + + Say Y if unsure. + +config BUSYBOX_CONFIG_FEATURE_MODUTILS_SYMBOLS + bool "Support for module.symbols file" + default BUSYBOX_DEFAULT_FEATURE_MODUTILS_SYMBOLS + depends on BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_MODPROBE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Generate and parse modules.symbols containing aliases for + symbol_request() kernel calls, such as: + alias symbol:usb_sg_init usbcore + + Say Y if unsure. + +config BUSYBOX_CONFIG_DEFAULT_MODULES_DIR + string "Default directory containing modules" + default BUSYBOX_DEFAULT_DEFAULT_MODULES_DIR + depends on BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_MODPROBE || BUSYBOX_CONFIG_MODPROBE_SMALL || BUSYBOX_CONFIG_MODINFO + help + Directory that contains kernel modules. + Defaults to "/lib/modules" + +config BUSYBOX_CONFIG_DEFAULT_DEPMOD_FILE + string "Default name of modules.dep" + default BUSYBOX_DEFAULT_DEFAULT_DEPMOD_FILE + depends on BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_MODPROBE || BUSYBOX_CONFIG_MODPROBE_SMALL || BUSYBOX_CONFIG_MODINFO + help + Filename that contains kernel modules dependencies. + Defaults to "modules.dep" + +endmenu diff --git a/package/utils/busybox/config/networking/Config.in b/package/utils/busybox/config/networking/Config.in new file mode 100644 index 0000000..b3dd8c8 --- /dev/null +++ b/package/utils/busybox/config/networking/Config.in @@ -0,0 +1,1105 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Networking Utilities" + +config BUSYBOX_CONFIG_NAMEIF + bool "nameif" + default BUSYBOX_DEFAULT_NAMEIF + select BUSYBOX_CONFIG_PLATFORM_LINUX + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + nameif is used to rename network interface by its MAC address. + Renamed interfaces MUST be in the down state. + It is possible to use a file (default: /etc/mactab) + with list of new interface names and MACs. + Maximum interface name length: IFNAMSIZ = 16 + File fields are separated by space or tab. + File format: + # Comment + new_interface_name XX:XX:XX:XX:XX:XX + +config BUSYBOX_CONFIG_FEATURE_NAMEIF_EXTENDED + bool "Extended nameif" + default BUSYBOX_DEFAULT_FEATURE_NAMEIF_EXTENDED + depends on BUSYBOX_CONFIG_NAMEIF + help + This extends the nameif syntax to support the bus_info, driver, + phyaddr selectors. The syntax is compatible to the normal nameif. + File format: + new_interface_name driver=asix bus=usb-0000:00:08.2-3 + new_interface_name bus=usb-0000:00:08.2-3 00:80:C8:38:91:B5 + new_interface_name phy_address=2 00:80:C8:38:91:B5 + new_interface_name mac=00:80:C8:38:91:B5 + new_interface_name 00:80:C8:38:91:B5 +config BUSYBOX_CONFIG_NBDCLIENT + bool "nbd-client" + default BUSYBOX_DEFAULT_NBDCLIENT + help + Network block device client +config BUSYBOX_CONFIG_NC + bool "nc" + default BUSYBOX_DEFAULT_NC + help + A simple Unix utility which reads and writes data across network + connections. + +config BUSYBOX_CONFIG_NC_SERVER + bool "Netcat server options (-l)" + default BUSYBOX_DEFAULT_NC_SERVER + depends on BUSYBOX_CONFIG_NC + help + Allow netcat to act as a server. + +config BUSYBOX_CONFIG_NC_EXTRA + bool "Netcat extensions (-eiw and -f FILE)" + default BUSYBOX_DEFAULT_NC_EXTRA + depends on BUSYBOX_CONFIG_NC + help + Add -e (support for executing the rest of the command line after + making or receiving a successful connection), -i (delay interval for + lines sent), -w (timeout for initial connection). + +config BUSYBOX_CONFIG_NC_110_COMPAT + bool "Netcat 1.10 compatibility (+2.5k)" + default BUSYBOX_DEFAULT_NC_110_COMPAT # off specially for Rob + depends on BUSYBOX_CONFIG_NC + help + This option makes nc closely follow original nc-1.10. + The code is about 2.5k bigger. It enables + -s ADDR, -n, -u, -v, -o FILE, -z options, but loses + busybox-specific extensions: -f FILE. +config BUSYBOX_CONFIG_PING + bool "ping" + default BUSYBOX_DEFAULT_PING + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to + elicit an ICMP ECHO_RESPONSE from a host or gateway. + +config BUSYBOX_CONFIG_PING6 + bool "ping6" + default BUSYBOX_DEFAULT_PING6 + depends on BUSYBOX_CONFIG_FEATURE_IPV6 && BUSYBOX_CONFIG_PING + help + This will give you a ping that can talk IPv6. + +config BUSYBOX_CONFIG_FEATURE_FANCY_PING + bool "Enable fancy ping output" + default BUSYBOX_DEFAULT_FEATURE_FANCY_PING + depends on BUSYBOX_CONFIG_PING + help + Make the output from the ping applet include statistics, and at the + same time provide full support for ICMP packets. +config BUSYBOX_CONFIG_WHOIS + bool "whois" + default BUSYBOX_DEFAULT_WHOIS + help + whois is a client for the whois directory service + +config BUSYBOX_CONFIG_FEATURE_IPV6 + bool "Enable IPv6 support" + default BUSYBOX_DEFAULT_FEATURE_IPV6 + help + Enable IPv6 support in busybox. + This adds IPv6 support in the networking applets. + +config BUSYBOX_CONFIG_FEATURE_UNIX_LOCAL + bool "Enable Unix domain socket support (usually not needed)" + default BUSYBOX_DEFAULT_FEATURE_UNIX_LOCAL + help + Enable Unix domain socket support in all busybox networking + applets. Address of the form local:/path/to/unix/socket + will be recognized. + + This extension is almost never used in real world usage. + You most likely want to say N. + +config BUSYBOX_CONFIG_FEATURE_PREFER_IPV4_ADDRESS + bool "Prefer IPv4 addresses from DNS queries" + default BUSYBOX_DEFAULT_FEATURE_PREFER_IPV4_ADDRESS + depends on BUSYBOX_CONFIG_FEATURE_IPV6 + help + Use IPv4 address of network host if it has one. + + If this option is off, the first returned address will be used. + This may cause problems when your DNS server is IPv6-capable and + is returning IPv6 host addresses too. If IPv6 address + precedes IPv4 one in DNS reply, busybox network applets + (e.g. wget) will use IPv6 address. On an IPv6-incapable host + or network applets will fail to connect to the host + using IPv6 address. + +config BUSYBOX_CONFIG_VERBOSE_RESOLUTION_ERRORS + bool "Verbose resolution errors" + default BUSYBOX_DEFAULT_VERBOSE_RESOLUTION_ERRORS + help + Enable if you are not satisfied with simplistic + "can't resolve 'hostname.com'" and want to know more. + This may increase size of your executable a bit. + +config BUSYBOX_CONFIG_ARP + bool "arp" + default BUSYBOX_DEFAULT_ARP + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Manipulate the system ARP cache. + +config BUSYBOX_CONFIG_ARPING + bool "arping" + default BUSYBOX_DEFAULT_ARPING + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Ping hosts by ARP packets. + +config BUSYBOX_CONFIG_BRCTL + bool "brctl" + default BUSYBOX_DEFAULT_BRCTL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Manage ethernet bridges. + Supports addbr/delbr and addif/delif. + +config BUSYBOX_CONFIG_FEATURE_BRCTL_FANCY + bool "Fancy options" + default BUSYBOX_DEFAULT_FEATURE_BRCTL_FANCY + depends on BUSYBOX_CONFIG_BRCTL + help + Add support for extended option like: + setageing, setfd, sethello, setmaxage, + setpathcost, setportprio, setbridgeprio, + stp + This adds about 600 bytes. + +config BUSYBOX_CONFIG_FEATURE_BRCTL_SHOW + bool "Support show" + default BUSYBOX_DEFAULT_FEATURE_BRCTL_SHOW + depends on BUSYBOX_CONFIG_BRCTL && BUSYBOX_CONFIG_FEATURE_BRCTL_FANCY + help + Add support for option which prints the current config: + show + +config BUSYBOX_CONFIG_DNSD + bool "dnsd" + default BUSYBOX_DEFAULT_DNSD + help + Small and static DNS server daemon. + +config BUSYBOX_CONFIG_ETHER_WAKE + bool "ether-wake" + default BUSYBOX_DEFAULT_ETHER_WAKE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Send a magic packet to wake up sleeping machines. + +config BUSYBOX_CONFIG_FAKEIDENTD + bool "fakeidentd" + default BUSYBOX_DEFAULT_FAKEIDENTD + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + fakeidentd listens on the ident port and returns a predefined + fake value on any query. + +config BUSYBOX_CONFIG_FTPD + bool "ftpd" + default BUSYBOX_DEFAULT_FTPD + help + simple FTP daemon. You have to run it via inetd. + +config BUSYBOX_CONFIG_FEATURE_FTP_WRITE + bool "Enable upload commands" + default BUSYBOX_DEFAULT_FEATURE_FTP_WRITE + depends on BUSYBOX_CONFIG_FTPD + help + Enable all kinds of FTP upload commands (-w option) + +config BUSYBOX_CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST + bool "Enable workaround for RFC-violating clients" + default BUSYBOX_DEFAULT_FEATURE_FTPD_ACCEPT_BROKEN_LIST + depends on BUSYBOX_CONFIG_FTPD + help + Some ftp clients (among them KDE's Konqueror) issue illegal + "LIST -l" requests. This option works around such problems. + It might prevent you from listing files starting with "-" and + it increases the code size by ~40 bytes. + Most other ftp servers seem to behave similar to this. + +config BUSYBOX_CONFIG_FEATURE_FTP_AUTHENTICATION + bool "Enable authentication" + default BUSYBOX_DEFAULT_FEATURE_FTP_AUTHENTICATION + depends on BUSYBOX_CONFIG_FTPD + help + Enable basic system login as seen in telnet etc. + +config BUSYBOX_CONFIG_FTPGET + bool "ftpget" + default BUSYBOX_DEFAULT_FTPGET + help + Retrieve a remote file via FTP. + +config BUSYBOX_CONFIG_FTPPUT + bool "ftpput" + default BUSYBOX_DEFAULT_FTPPUT + help + Store a remote file via FTP. + +config BUSYBOX_CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS + bool "Enable long options in ftpget/ftpput" + default BUSYBOX_DEFAULT_FEATURE_FTPGETPUT_LONG_OPTIONS + depends on BUSYBOX_CONFIG_LONG_OPTS && (BUSYBOX_CONFIG_FTPGET || BUSYBOX_CONFIG_FTPPUT) + help + Support long options for the ftpget/ftpput applet. + +config BUSYBOX_CONFIG_HOSTNAME + bool "hostname" + default BUSYBOX_DEFAULT_HOSTNAME + help + Show or set the system's host name. + +config BUSYBOX_CONFIG_HTTPD + bool "httpd" + default BUSYBOX_DEFAULT_HTTPD + help + Serve web pages via an HTTP server. + +config BUSYBOX_CONFIG_FEATURE_HTTPD_RANGES + bool "Support 'Ranges:' header" + default BUSYBOX_DEFAULT_FEATURE_HTTPD_RANGES + depends on BUSYBOX_CONFIG_HTTPD + help + Makes httpd emit "Accept-Ranges: bytes" header and understand + "Range: bytes=NNN-[MMM]" header. Allows for resuming interrupted + downloads, seeking in multimedia players etc. + +config BUSYBOX_CONFIG_FEATURE_HTTPD_SETUID + bool "Enable -u <user> option" + default BUSYBOX_DEFAULT_FEATURE_HTTPD_SETUID + depends on BUSYBOX_CONFIG_HTTPD + help + This option allows the server to run as a specific user + rather than defaulting to the user that starts the server. + Use of this option requires special privileges to change to a + different user. + +config BUSYBOX_CONFIG_FEATURE_HTTPD_BASIC_AUTH + bool "Enable Basic http Authentication" + default BUSYBOX_DEFAULT_FEATURE_HTTPD_BASIC_AUTH + depends on BUSYBOX_CONFIG_HTTPD + help + Utilizes password settings from /etc/httpd.conf for basic + authentication on a per url basis. + Example for httpd.conf file: + /adm:toor:PaSsWd + +config BUSYBOX_CONFIG_FEATURE_HTTPD_AUTH_MD5 + bool "Support MD5 crypted passwords for http Authentication" + default BUSYBOX_DEFAULT_FEATURE_HTTPD_AUTH_MD5 + depends on BUSYBOX_CONFIG_FEATURE_HTTPD_BASIC_AUTH + help + Enables encrypted passwords, and wildcard user/passwords + in httpd.conf file. + User '*' means 'any system user name is ok', + password of '*' means 'use system password for this user' + Examples: + /adm:toor:$1$P/eKnWXS$aI1aPGxT.dJD5SzqAKWrF0 + /adm:root:* + /wiki:*:* + +config BUSYBOX_CONFIG_FEATURE_HTTPD_CGI + bool "Support Common Gateway Interface (CGI)" + default BUSYBOX_DEFAULT_FEATURE_HTTPD_CGI + depends on BUSYBOX_CONFIG_HTTPD + help + This option allows scripts and executables to be invoked + when specific URLs are requested. + +config BUSYBOX_CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR + bool "Support for running scripts through an interpreter" + default BUSYBOX_DEFAULT_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR + depends on BUSYBOX_CONFIG_FEATURE_HTTPD_CGI + help + This option enables support for running scripts through an + interpreter. Turn this on if you want PHP scripts to work + properly. You need to supply an additional line in your + httpd.conf file: + *.php:/path/to/your/php + +config BUSYBOX_CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV + bool "Set REMOTE_PORT environment variable for CGI" + default BUSYBOX_DEFAULT_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV + depends on BUSYBOX_CONFIG_FEATURE_HTTPD_CGI + help + Use of this option can assist scripts in generating + references that contain a unique port number. + +config BUSYBOX_CONFIG_FEATURE_HTTPD_ENCODE_URL_STR + bool "Enable -e option (useful for CGIs written as shell scripts)" + default BUSYBOX_DEFAULT_FEATURE_HTTPD_ENCODE_URL_STR + depends on BUSYBOX_CONFIG_HTTPD + help + This option allows html encoding of arbitrary strings for display + by the browser. Output goes to stdout. + For example, httpd -e "<Hello World>" produces + "<Hello World>". + +config BUSYBOX_CONFIG_FEATURE_HTTPD_ERROR_PAGES + bool "Support for custom error pages" + default BUSYBOX_DEFAULT_FEATURE_HTTPD_ERROR_PAGES + depends on BUSYBOX_CONFIG_HTTPD + help + This option allows you to define custom error pages in + the configuration file instead of the default HTTP status + error pages. For instance, if you add the line: + E404:/path/e404.html + in the config file, the server will respond the specified + '/path/e404.html' file instead of the terse '404 NOT FOUND' + message. + +config BUSYBOX_CONFIG_FEATURE_HTTPD_PROXY + bool "Support for reverse proxy" + default BUSYBOX_DEFAULT_FEATURE_HTTPD_PROXY + depends on BUSYBOX_CONFIG_HTTPD + help + This option allows you to define URLs that will be forwarded + to another HTTP server. To setup add the following line to the + configuration file + P:/url/:http://hostname[:port]/new/path/ + Then a request to /url/myfile will be forwarded to + http://hostname[:port]/new/path/myfile. + +config BUSYBOX_CONFIG_FEATURE_HTTPD_GZIP + bool "Support for GZIP content encoding" + default BUSYBOX_DEFAULT_FEATURE_HTTPD_GZIP + depends on BUSYBOX_CONFIG_HTTPD + help + Makes httpd send files using GZIP content encoding if the + client supports it and a pre-compressed <file>.gz exists. + +config BUSYBOX_CONFIG_IFCONFIG + bool "ifconfig" + default BUSYBOX_DEFAULT_IFCONFIG + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Ifconfig is used to configure the kernel-resident network interfaces. + +config BUSYBOX_CONFIG_FEATURE_IFCONFIG_STATUS + bool "Enable status reporting output (+7k)" + default BUSYBOX_DEFAULT_FEATURE_IFCONFIG_STATUS + depends on BUSYBOX_CONFIG_IFCONFIG + help + If ifconfig is called with no arguments it will display the status + of the currently active interfaces. + +config BUSYBOX_CONFIG_FEATURE_IFCONFIG_SLIP + bool "Enable slip-specific options \"keepalive\" and \"outfill\"" + default BUSYBOX_DEFAULT_FEATURE_IFCONFIG_SLIP + depends on BUSYBOX_CONFIG_IFCONFIG + help + Allow "keepalive" and "outfill" support for SLIP. If you're not + planning on using serial lines, leave this unchecked. + +config BUSYBOX_CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ + bool "Enable options \"mem_start\", \"io_addr\", and \"irq\"" + default BUSYBOX_DEFAULT_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ + depends on BUSYBOX_CONFIG_IFCONFIG + help + Allow the start address for shared memory, start address for I/O, + and/or the interrupt line used by the specified device. + +config BUSYBOX_CONFIG_FEATURE_IFCONFIG_HW + bool "Enable option \"hw\" (ether only)" + default BUSYBOX_DEFAULT_FEATURE_IFCONFIG_HW + depends on BUSYBOX_CONFIG_IFCONFIG + help + Set the hardware address of this interface, if the device driver + supports this operation. Currently, we only support the 'ether' + class. + +config BUSYBOX_CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS + bool "Set the broadcast automatically" + default BUSYBOX_DEFAULT_FEATURE_IFCONFIG_BROADCAST_PLUS + depends on BUSYBOX_CONFIG_IFCONFIG + help + Setting this will make ifconfig attempt to find the broadcast + automatically if the value '+' is used. + +config BUSYBOX_CONFIG_IFENSLAVE + bool "ifenslave" + default BUSYBOX_DEFAULT_IFENSLAVE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Userspace application to bind several interfaces + to a logical interface (use with kernel bonding driver). + +config BUSYBOX_CONFIG_IFPLUGD + bool "ifplugd" + default BUSYBOX_DEFAULT_IFPLUGD + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Network interface plug detection daemon. + +config BUSYBOX_CONFIG_IFUPDOWN + bool "ifupdown" + default BUSYBOX_DEFAULT_IFUPDOWN + help + Activate or deactivate the specified interfaces. This applet makes + use of either "ifconfig" and "route" or the "ip" command to actually + configure network interfaces. Therefore, you will probably also want + to enable either IFCONFIG and ROUTE, or enable + FEATURE_IFUPDOWN_IP and the various IP options. Of + course you could use non-busybox versions of these programs, so + against my better judgement (since this will surely result in plenty + of support questions on the mailing list), I do not force you to + enable these additional options. It is up to you to supply either + "ifconfig", "route" and "run-parts" or the "ip" command, either + via busybox or via standalone utilities. + +config BUSYBOX_CONFIG_IFUPDOWN_IFSTATE_PATH + string "Absolute path to ifstate file" + default BUSYBOX_DEFAULT_IFUPDOWN_IFSTATE_PATH + depends on BUSYBOX_CONFIG_IFUPDOWN + help + ifupdown keeps state information in a file called ifstate. + Typically it is located in /var/run/ifstate, however + some distributions tend to put it in other places + (debian, for example, uses /etc/network/run/ifstate). + This config option defines location of ifstate. + +config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IP + bool "Use ip applet" + default BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IP + depends on BUSYBOX_CONFIG_IFUPDOWN + help + Use the iproute "ip" command to implement "ifup" and "ifdown", rather + than the default of using the older 'ifconfig' and 'route' utilities. + +config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN + bool "Use busybox ip applet" + default BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IP_BUILTIN + depends on BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IP + select BUSYBOX_CONFIG_PLATFORM_LINUX + select BUSYBOX_CONFIG_IP + select BUSYBOX_CONFIG_FEATURE_IP_ADDRESS + select BUSYBOX_CONFIG_FEATURE_IP_LINK + select BUSYBOX_CONFIG_FEATURE_IP_ROUTE + help + Use the busybox iproute "ip" applet to implement "ifupdown". + + If left disabled, you must install the full-blown iproute2 + utility or the "ifup" and "ifdown" applets will not work. + +config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN + bool "Use busybox ifconfig and route applets" + default BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN + depends on BUSYBOX_CONFIG_IFUPDOWN && !BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IP + select BUSYBOX_CONFIG_IFCONFIG + select BUSYBOX_CONFIG_ROUTE + help + Use the busybox iproute "ifconfig" and "route" applets to + implement the "ifup" and "ifdown" utilities. + + If left disabled, you must install the full-blown ifconfig + and route utilities, or the "ifup" and "ifdown" applets will not + work. + +config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IPV4 + bool "Support for IPv4" + default BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IPV4 + depends on BUSYBOX_CONFIG_IFUPDOWN + help + If you want ifup/ifdown to talk IPv4, leave this on. + +config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IPV6 + bool "Support for IPv6" + default BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IPV6 + depends on BUSYBOX_CONFIG_IFUPDOWN && BUSYBOX_CONFIG_FEATURE_IPV6 + help + If you need support for IPv6, turn this option on. + +### UNUSED +###config FEATURE_IFUPDOWN_IPX +### bool "Support for IPX" +### default y +### depends on IFUPDOWN +### help +### If this option is selected you can use busybox to work with IPX +### networks. + +config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_MAPPING + bool "Enable mapping support" + default BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_MAPPING + depends on BUSYBOX_CONFIG_IFUPDOWN + help + This enables support for the "mapping" stanza, unless you have + a weird network setup you don't need it. + +config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP + bool "Support for external dhcp clients" + default BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_EXTERNAL_DHCP + depends on BUSYBOX_CONFIG_IFUPDOWN + help + This enables support for the external dhcp clients. Clients are + tried in the following order: dhcpcd, dhclient, pump and udhcpc. + Otherwise, if udhcpc applet is enabled, it is used. + Otherwise, ifup/ifdown will have no support for DHCP. + +config BUSYBOX_CONFIG_INETD + bool "inetd" + default BUSYBOX_DEFAULT_INETD + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + Internet superserver daemon + +config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO + bool "Support echo service" + default BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_ECHO + depends on BUSYBOX_CONFIG_INETD + help + Echo received data internal inetd service + +config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD + bool "Support discard service" + default BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD + depends on BUSYBOX_CONFIG_INETD + help + Internet /dev/null internal inetd service + +config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME + bool "Support time service" + default BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_TIME + depends on BUSYBOX_CONFIG_INETD + help + Return 32 bit time since 1900 internal inetd service + +config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME + bool "Support daytime service" + default BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME + depends on BUSYBOX_CONFIG_INETD + help + Return human-readable time internal inetd service + +config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN + bool "Support chargen service" + default BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN + depends on BUSYBOX_CONFIG_INETD + help + Familiar character generator internal inetd service + +config BUSYBOX_CONFIG_FEATURE_INETD_RPC + bool "Support RPC services" + default BUSYBOX_DEFAULT_FEATURE_INETD_RPC + depends on BUSYBOX_CONFIG_INETD + select BUSYBOX_CONFIG_FEATURE_HAVE_RPC + help + Support Sun-RPC based services + +config BUSYBOX_CONFIG_IP + bool "ip" + default BUSYBOX_DEFAULT_IP + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + The "ip" applet is a TCP/IP interface configuration and routing + utility. You generally don't need "ip" to use busybox with + TCP/IP. + +config BUSYBOX_CONFIG_FEATURE_IP_ADDRESS + bool "ip address" + default BUSYBOX_DEFAULT_FEATURE_IP_ADDRESS + depends on BUSYBOX_CONFIG_IP + help + Address manipulation support for the "ip" applet. + +config BUSYBOX_CONFIG_FEATURE_IP_LINK + bool "ip link" + default BUSYBOX_DEFAULT_FEATURE_IP_LINK + depends on BUSYBOX_CONFIG_IP + help + Configure network devices with "ip". + +config BUSYBOX_CONFIG_FEATURE_IP_ROUTE + bool "ip route" + default BUSYBOX_DEFAULT_FEATURE_IP_ROUTE + depends on BUSYBOX_CONFIG_IP + help + Add support for routing table management to "ip". + +config BUSYBOX_CONFIG_FEATURE_IP_TUNNEL + bool "ip tunnel" + default BUSYBOX_DEFAULT_FEATURE_IP_TUNNEL + depends on BUSYBOX_CONFIG_IP + help + Add support for tunneling commands to "ip". + +config BUSYBOX_CONFIG_FEATURE_IP_RULE + bool "ip rule" + default BUSYBOX_DEFAULT_FEATURE_IP_RULE + depends on BUSYBOX_CONFIG_IP + help + Add support for rule commands to "ip". + +config BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS + bool "Support short forms of ip commands" + default BUSYBOX_DEFAULT_FEATURE_IP_SHORT_FORMS + depends on BUSYBOX_CONFIG_IP + help + Also support short-form of ip <OBJECT> commands: + ip addr -> ipaddr + ip link -> iplink + ip route -> iproute + ip tunnel -> iptunnel + ip rule -> iprule + + Say N unless you desparately need the short form of the ip + object commands. + +config BUSYBOX_CONFIG_FEATURE_IP_RARE_PROTOCOLS + bool "Support displaying rarely used link types" + default BUSYBOX_DEFAULT_FEATURE_IP_RARE_PROTOCOLS + depends on BUSYBOX_CONFIG_IP + help + If you are not going to use links of type "frad", "econet", + "bif" etc, you probably don't need to enable this. + Ethernet, wireless, infrared, ppp/slip, ip tunnelling + link types are supported without this option selected. + +config BUSYBOX_CONFIG_IPADDR + bool + default BUSYBOX_DEFAULT_IPADDR + depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_ADDRESS + +config BUSYBOX_CONFIG_IPLINK + bool + default BUSYBOX_DEFAULT_IPLINK + depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_LINK + +config BUSYBOX_CONFIG_IPROUTE + bool + default BUSYBOX_DEFAULT_IPROUTE + depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_ROUTE + +config BUSYBOX_CONFIG_IPTUNNEL + bool + default BUSYBOX_DEFAULT_IPTUNNEL + depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_TUNNEL + +config BUSYBOX_CONFIG_IPRULE + bool + default BUSYBOX_DEFAULT_IPRULE + depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_RULE + +config BUSYBOX_CONFIG_IPCALC + bool "ipcalc" + default BUSYBOX_DEFAULT_IPCALC + help + ipcalc takes an IP address and netmask and calculates the + resulting broadcast, network, and host range. + +config BUSYBOX_CONFIG_FEATURE_IPCALC_FANCY + bool "Fancy IPCALC, more options, adds 1 kbyte" + default BUSYBOX_DEFAULT_FEATURE_IPCALC_FANCY + depends on BUSYBOX_CONFIG_IPCALC + help + Adds the options hostname, prefix and silent to the output of + "ipcalc". + +config BUSYBOX_CONFIG_FEATURE_IPCALC_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_IPCALC_LONG_OPTIONS + depends on BUSYBOX_CONFIG_IPCALC && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the ipcalc applet. + +config BUSYBOX_CONFIG_NETMSG + bool "netmsg" + default BUSYBOX_DEFAULT_NETMSG + help + simple program for sending udp broadcast messages + +config BUSYBOX_CONFIG_NETSTAT + bool "netstat" + default BUSYBOX_DEFAULT_NETSTAT + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + netstat prints information about the Linux networking subsystem. + +config BUSYBOX_CONFIG_FEATURE_NETSTAT_WIDE + bool "Enable wide netstat output" + default BUSYBOX_DEFAULT_FEATURE_NETSTAT_WIDE + depends on BUSYBOX_CONFIG_NETSTAT + help + Add support for wide columns. Useful when displaying IPv6 addresses + (-W option). + +config BUSYBOX_CONFIG_FEATURE_NETSTAT_PRG + bool "Enable PID/Program name output" + default BUSYBOX_DEFAULT_FEATURE_NETSTAT_PRG + depends on BUSYBOX_CONFIG_NETSTAT + help + Add support for -p flag to print out PID and program name. + +700 bytes of code. + +config BUSYBOX_CONFIG_NSLOOKUP + bool "nslookup" + default BUSYBOX_DEFAULT_NSLOOKUP + help + nslookup is a tool to query Internet name servers. + +config BUSYBOX_CONFIG_NTPD + bool "ntpd" + default BUSYBOX_DEFAULT_NTPD + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + The NTP client/server daemon. + +config BUSYBOX_CONFIG_FEATURE_NTPD_SERVER + bool "Make ntpd usable as a NTP server" + default BUSYBOX_DEFAULT_FEATURE_NTPD_SERVER + depends on BUSYBOX_CONFIG_NTPD + help + Make ntpd usable as a NTP server. If you disable this option + ntpd will be usable only as a NTP client. + +config BUSYBOX_CONFIG_FEATURE_NTPD_CONF + bool "Make ntpd understand /etc/ntp.conf" + default BUSYBOX_DEFAULT_FEATURE_NTPD_CONF + depends on BUSYBOX_CONFIG_NTPD + help + Make ntpd look in /etc/ntp.conf for peers. Only "server address" + is supported. + +config BUSYBOX_CONFIG_PSCAN + bool "pscan" + default BUSYBOX_DEFAULT_PSCAN + help + Simple network port scanner. + +config BUSYBOX_CONFIG_ROUTE + bool "route" + default BUSYBOX_DEFAULT_ROUTE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Route displays or manipulates the kernel's IP routing tables. + +config BUSYBOX_CONFIG_SLATTACH + bool "slattach" + default BUSYBOX_DEFAULT_SLATTACH + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + slattach is a small utility to attach network interfaces to serial + lines. + +#config TC +# bool "tc" +# default y +# help +# show / manipulate traffic control settings +# +#config FEATURE_TC_INGRESS +# def_bool n +# depends on TC + +config BUSYBOX_CONFIG_TCPSVD + bool "tcpsvd" + default BUSYBOX_DEFAULT_TCPSVD + help + tcpsvd listens on a TCP port and runs a program for each new + connection. + +config BUSYBOX_CONFIG_TELNET + bool "telnet" + default BUSYBOX_DEFAULT_TELNET + help + Telnet is an interface to the TELNET protocol, but is also commonly + used to test other simple protocols. + +config BUSYBOX_CONFIG_FEATURE_TELNET_TTYPE + bool "Pass TERM type to remote host" + default BUSYBOX_DEFAULT_FEATURE_TELNET_TTYPE + depends on BUSYBOX_CONFIG_TELNET + help + Setting this option will forward the TERM environment variable to the + remote host you are connecting to. This is useful to make sure that + things like ANSI colors and other control sequences behave. + +config BUSYBOX_CONFIG_FEATURE_TELNET_AUTOLOGIN + bool "Pass USER type to remote host" + default BUSYBOX_DEFAULT_FEATURE_TELNET_AUTOLOGIN + depends on BUSYBOX_CONFIG_TELNET + help + Setting this option will forward the USER environment variable to the + remote host you are connecting to. This is useful when you need to + log into a machine without telling the username (autologin). This + option enables `-a' and `-l USER' arguments. + +config BUSYBOX_CONFIG_TELNETD + bool "telnetd" + default BUSYBOX_DEFAULT_TELNETD + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + A daemon for the TELNET protocol, allowing you to log onto the host + running the daemon. Please keep in mind that the TELNET protocol + sends passwords in plain text. If you can't afford the space for an + SSH daemon and you trust your network, you may say 'y' here. As a + more secure alternative, you should seriously consider installing the + very small Dropbear SSH daemon instead: + http://matt.ucc.asn.au/dropbear/dropbear.html + + Note that for busybox telnetd to work you need several things: + First of all, your kernel needs: + UNIX98_PTYS=y + DEVPTS_FS=y + + Next, you need a /dev/pts directory on your root filesystem: + + $ ls -ld /dev/pts + drwxr-xr-x 2 root root 0 Sep 23 13:21 /dev/pts/ + + Next you need the pseudo terminal master multiplexer /dev/ptmx: + + $ ls -la /dev/ptmx + crw-rw-rw- 1 root tty 5, 2 Sep 23 13:55 /dev/ptmx + + Any /dev/ttyp[0-9]* files you may have can be removed. + Next, you need to mount the devpts filesystem on /dev/pts using: + + mount -t devpts devpts /dev/pts + + You need to be sure that busybox has LOGIN and + FEATURE_SUID enabled. And finally, you should make + certain that Busybox has been installed setuid root: + + chown root.root /bin/busybox + chmod 4755 /bin/busybox + + with all that done, telnetd _should_ work.... + + +config BUSYBOX_CONFIG_FEATURE_TELNETD_STANDALONE + bool "Support standalone telnetd (not inetd only)" + default BUSYBOX_DEFAULT_FEATURE_TELNETD_STANDALONE + depends on BUSYBOX_CONFIG_TELNETD + help + Selecting this will make telnetd able to run standalone. + +config BUSYBOX_CONFIG_FEATURE_TELNETD_INETD_WAIT + bool "Support -w SEC option (inetd wait mode)" + default BUSYBOX_DEFAULT_FEATURE_TELNETD_INETD_WAIT + depends on BUSYBOX_CONFIG_FEATURE_TELNETD_STANDALONE + help + This option allows you to run telnetd in "inet wait" mode. + Example inetd.conf line (note "wait", not usual "nowait"): + + telnet stream tcp wait root /bin/telnetd telnetd -w10 + + In this example, inetd passes _listening_ socket_ as fd 0 + to telnetd when connection appears. + telnetd will wait for connections until all existing + connections are closed, and no new connections + appear during 10 seconds. Then it exits, and inetd continues + to listen for new connections. + + This option is rarely used. "tcp nowait" is much more usual + way of running tcp services, including telnetd. + You most probably want to say N here. + +config BUSYBOX_CONFIG_TFTP + bool "tftp" + default BUSYBOX_DEFAULT_TFTP + help + This enables the Trivial File Transfer Protocol client program. TFTP + is usually used for simple, small transfers such as a root image + for a network-enabled bootloader. + +config BUSYBOX_CONFIG_TFTPD + bool "tftpd" + default BUSYBOX_DEFAULT_TFTPD + help + This enables the Trivial File Transfer Protocol server program. + It expects that stdin is a datagram socket and a packet + is already pending on it. It will exit after one transfer. + In other words: it should be run from inetd in nowait mode, + or from udpsvd. Example: "udpsvd -E 0 69 tftpd DIR" + +comment "Common options for tftp/tftpd" + depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD + +config BUSYBOX_CONFIG_FEATURE_TFTP_GET + bool "Enable 'tftp get' and/or tftpd upload code" + default BUSYBOX_DEFAULT_FEATURE_TFTP_GET + depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD + help + Add support for the GET command within the TFTP client. This allows + a client to retrieve a file from a TFTP server. + Also enable upload support in tftpd, if tftpd is selected. + + Note: this option does _not_ make tftpd capable of download + (the usual operation people need from it)! + +config BUSYBOX_CONFIG_FEATURE_TFTP_PUT + bool "Enable 'tftp put' and/or tftpd download code" + default BUSYBOX_DEFAULT_FEATURE_TFTP_PUT + depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD + help + Add support for the PUT command within the TFTP client. This allows + a client to transfer a file to a TFTP server. + Also enable download support in tftpd, if tftpd is selected. + +config BUSYBOX_CONFIG_FEATURE_TFTP_BLOCKSIZE + bool "Enable 'blksize' and 'tsize' protocol options" + default BUSYBOX_DEFAULT_FEATURE_TFTP_BLOCKSIZE + depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD + help + Allow tftp to specify block size, and tftpd to understand + "blksize" and "tsize" options. + +config BUSYBOX_CONFIG_FEATURE_TFTP_PROGRESS_BAR + bool "Enable tftp progress meter" + default BUSYBOX_DEFAULT_FEATURE_TFTP_PROGRESS_BAR + depends on BUSYBOX_CONFIG_TFTP && BUSYBOX_CONFIG_FEATURE_TFTP_BLOCKSIZE + help + Show progress bar. + +config BUSYBOX_CONFIG_TFTP_DEBUG + bool "Enable debug" + default BUSYBOX_DEFAULT_TFTP_DEBUG + depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD + help + Make tftp[d] print debugging messages on stderr. + This is useful if you are diagnosing a bug in tftp[d]. + +config BUSYBOX_CONFIG_TRACEROUTE + bool "traceroute" + default BUSYBOX_DEFAULT_TRACEROUTE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Utility to trace the route of IP packets. + +config BUSYBOX_CONFIG_TRACEROUTE6 + bool "traceroute6" + default BUSYBOX_DEFAULT_TRACEROUTE6 + depends on BUSYBOX_CONFIG_FEATURE_IPV6 && BUSYBOX_CONFIG_TRACEROUTE + help + Utility to trace the route of IPv6 packets. + +config BUSYBOX_CONFIG_FEATURE_TRACEROUTE_VERBOSE + bool "Enable verbose output" + default BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_VERBOSE + depends on BUSYBOX_CONFIG_TRACEROUTE + help + Add some verbosity to traceroute. This includes among other things + hostnames and ICMP response types. + +config BUSYBOX_CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE + bool "Enable loose source route" + default BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_SOURCE_ROUTE + depends on BUSYBOX_CONFIG_TRACEROUTE + help + Add option to specify a loose source route gateway + (8 maximum). + +config BUSYBOX_CONFIG_FEATURE_TRACEROUTE_USE_ICMP + bool "Use ICMP instead of UDP" + default BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_USE_ICMP + depends on BUSYBOX_CONFIG_TRACEROUTE + help + Add option -I to use ICMP ECHO instead of UDP datagrams. + +config BUSYBOX_CONFIG_TUNCTL + bool "tunctl" + default BUSYBOX_DEFAULT_TUNCTL + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + tunctl creates or deletes tun devices. + +config BUSYBOX_CONFIG_FEATURE_TUNCTL_UG + bool "Support owner:group assignment" + default BUSYBOX_DEFAULT_FEATURE_TUNCTL_UG + depends on BUSYBOX_CONFIG_TUNCTL + help + Allow to specify owner and group of newly created interface. + 340 bytes of pure bloat. Say no here. + +source package/utils/busybox/config/networking/udhcp/Config.in + +config BUSYBOX_CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS + string "ifup udhcpc command line options" + default BUSYBOX_DEFAULT_IFUPDOWN_UDHCPC_CMD_OPTIONS + depends on BUSYBOX_CONFIG_IFUPDOWN && BUSYBOX_CONFIG_UDHCPC + help + Command line options to pass to udhcpc from ifup. + Intended to alter options not available in /etc/network/interfaces. + (IE: --syslog --background etc...) + +config BUSYBOX_CONFIG_UDPSVD + bool "udpsvd" + default BUSYBOX_DEFAULT_UDPSVD + help + udpsvd listens on an UDP port and runs a program for each new + connection. + +config BUSYBOX_CONFIG_VCONFIG + bool "vconfig" + default BUSYBOX_DEFAULT_VCONFIG + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Creates, removes, and configures VLAN interfaces + +config BUSYBOX_CONFIG_WGET + bool "wget" + default BUSYBOX_DEFAULT_WGET + help + wget is a utility for non-interactive download of files from HTTP + and FTP servers. + +config BUSYBOX_CONFIG_FEATURE_WGET_STATUSBAR + bool "Enable a nifty process meter (+2k)" + default BUSYBOX_DEFAULT_FEATURE_WGET_STATUSBAR + depends on BUSYBOX_CONFIG_WGET + help + Enable the transfer progress bar for wget transfers. + +config BUSYBOX_CONFIG_FEATURE_WGET_AUTHENTICATION + bool "Enable HTTP authentication" + default BUSYBOX_DEFAULT_FEATURE_WGET_AUTHENTICATION + depends on BUSYBOX_CONFIG_WGET + help + Support authenticated HTTP transfers. + +config BUSYBOX_CONFIG_FEATURE_WGET_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_WGET_LONG_OPTIONS + depends on BUSYBOX_CONFIG_WGET && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the wget applet. + +config BUSYBOX_CONFIG_FEATURE_WGET_TIMEOUT + bool "Enable timeout option -T SEC" + default BUSYBOX_DEFAULT_FEATURE_WGET_TIMEOUT + depends on BUSYBOX_CONFIG_WGET + help + Supports network read and connect timeouts for wget, + so that wget will give up and timeout, through the -T + command line option. + + Currently only connect and network data read timeout are + supported (i.e., timeout is not applied to the DNS query). When + FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option + will work in addition to -T. + +config BUSYBOX_CONFIG_ZCIP + bool "zcip" + default BUSYBOX_DEFAULT_ZCIP + select BUSYBOX_CONFIG_PLATFORM_LINUX + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + ZCIP provides ZeroConf IPv4 address selection, according to RFC 3927. + It's a daemon that allocates and defends a dynamically assigned + address on the 169.254/16 network, requiring no system administrator. + + See http://www.zeroconf.org for further details, and "zcip.script" + in the busybox examples. + +endmenu diff --git a/package/utils/busybox/config/networking/udhcp/Config.in b/package/utils/busybox/config/networking/udhcp/Config.in new file mode 100644 index 0000000..4f48400 --- /dev/null +++ b/package/utils/busybox/config/networking/udhcp/Config.in @@ -0,0 +1,171 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +config BUSYBOX_CONFIG_UDHCPC6 + bool "udhcp client for DHCPv6 (udhcpc6)" + default BUSYBOX_DEFAULT_UDHCPC6 # not yet ready + depends on BUSYBOX_CONFIG_FEATURE_IPV6 + help + udhcpc6 is a DHCPv6 client + +config BUSYBOX_CONFIG_UDHCPD + bool "udhcp server (udhcpd)" + default BUSYBOX_DEFAULT_UDHCPD + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + udhcpd is a DHCP server geared primarily toward embedded systems, + while striving to be fully functional and RFC compliant. + +config BUSYBOX_CONFIG_DHCPRELAY + bool "dhcprelay" + default BUSYBOX_DEFAULT_DHCPRELAY + depends on BUSYBOX_CONFIG_UDHCPD + help + dhcprelay listens for dhcp requests on one or more interfaces + and forwards these requests to a different interface or dhcp + server. + +config BUSYBOX_CONFIG_DUMPLEASES + bool "Lease display utility (dumpleases)" + default BUSYBOX_DEFAULT_DUMPLEASES + depends on BUSYBOX_CONFIG_UDHCPD + help + dumpleases displays the leases written out by the udhcpd server. + Lease times are stored in the file by time remaining in lease, or + by the absolute time that it expires in seconds from epoch. + +config BUSYBOX_CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY + bool "Rewrite the lease file at every new acknowledge" + default BUSYBOX_DEFAULT_FEATURE_UDHCPD_WRITE_LEASES_EARLY + depends on BUSYBOX_CONFIG_UDHCPD + help + If selected, udhcpd will write a new file with leases every + time a new lease has been accepted, thus eliminating the need + to send SIGUSR1 for the initial writing or updating. Any timed + rewriting remains undisturbed. + +config BUSYBOX_CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC + bool "Select IP address based on client MAC" + default BUSYBOX_DEFAULT_FEATURE_UDHCPD_BASE_IP_ON_MAC + depends on BUSYBOX_CONFIG_UDHCPD + help + If selected, udhcpd will base its selection of IP address to offer + on the client's hardware address. Otherwise udhcpd uses the next + consecutive free address. + + This reduces the frequency of IP address changes for clients + which let their lease expire, and makes consecutive DHCPOFFERS + for the same client to (almost always) contain the same + IP address. + +config BUSYBOX_CONFIG_DHCPD_LEASES_FILE + string "Absolute path to lease file" + default BUSYBOX_DEFAULT_DHCPD_LEASES_FILE + depends on BUSYBOX_CONFIG_UDHCPD + help + udhcpd stores addresses in a lease file. This is the absolute path + of the file. Normally it is safe to leave it untouched. + +config BUSYBOX_CONFIG_UDHCPC + bool "udhcp client (udhcpc)" + default BUSYBOX_DEFAULT_UDHCPC + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + udhcpc is a DHCP client geared primarily toward embedded systems, + while striving to be fully functional and RFC compliant. + + The udhcp client negotiates a lease with the DHCP server and + runs a script when a lease is obtained or lost. + +config BUSYBOX_CONFIG_FEATURE_UDHCPC_ARPING + bool "Verify that the offered address is free, using ARP ping" + default BUSYBOX_DEFAULT_FEATURE_UDHCPC_ARPING + depends on BUSYBOX_CONFIG_UDHCPC + help + If selected, udhcpc will send ARP probes and make sure + the offered address is really not in use by anyone. The client + will DHCPDECLINE the offer if the address is in use, + and restart the discover process. + +config BUSYBOX_CONFIG_FEATURE_UDHCPC_SANITIZEOPT + bool "Do not pass malformed host and domain names" + default BUSYBOX_DEFAULT_FEATURE_UDHCPC_SANITIZEOPT + depends on BUSYBOX_CONFIG_UDHCPC + help + If selected, udhcpc will check some options (such as option 12 - + hostname) and if they don't look like valid hostnames + (for example, if they start with dash or contain spaces), + they will be replaced with string "bad" when exporting + to the environment. + +config BUSYBOX_CONFIG_FEATURE_UDHCP_PORT + bool "Enable '-P port' option for udhcpd and udhcpc" + default BUSYBOX_DEFAULT_FEATURE_UDHCP_PORT + depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC + help + At the cost of ~300 bytes, enables -P port option. + This feature is typically not needed. + +config BUSYBOX_CONFIG_UDHCP_DEBUG + int "Maximum verbosity level for udhcp applets (0..9)" + default BUSYBOX_DEFAULT_UDHCP_DEBUG + range 0 9 + depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC || BUSYBOX_CONFIG_DHCPRELAY + help + Verbosity can be increased with multiple -v options. + This option controls how high it can be cranked up. + + Bigger values result in bigger code. Levels above 1 + are very verbose and useful for debugging only. + +config BUSYBOX_CONFIG_FEATURE_UDHCP_RFC3397 + bool "Support for RFC3397 domain search (experimental)" + default BUSYBOX_DEFAULT_FEATURE_UDHCP_RFC3397 + depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC + help + If selected, both client and server will support passing of domain + search lists via option 119, specified in RFC 3397, + and SIP servers option 120, specified in RFC 3361. + +config BUSYBOX_CONFIG_FEATURE_UDHCP_8021Q + bool "Support for 802.1Q VLAN parameters" + default BUSYBOX_DEFAULT_FEATURE_UDHCP_8021Q + depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC + help + If selected, both client and server will support passing of VLAN + ID and priority via options 132 and 133 as per 802.1Q. + +config BUSYBOX_CONFIG_UDHCPC_DEFAULT_SCRIPT + string "Absolute path to config script" + default BUSYBOX_DEFAULT_UDHCPC_DEFAULT_SCRIPT + depends on BUSYBOX_CONFIG_UDHCPC + help + This script is called after udhcpc receives an answer. See + examples/udhcp for a working example. Normally it is safe + to leave this untouched. + +config BUSYBOX_CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS + int "DHCP options slack buffer size" + default BUSYBOX_DEFAULT_UDHCPC_SLACK_FOR_BUGGY_SERVERS + range 0 924 + depends on BUSYBOX_CONFIG_UDHCPD || BUSYBOX_CONFIG_UDHCPC + help + Some buggy DHCP servers send DHCP offer packets with option + field larger than we expect (which might also be considered a + buffer overflow attempt). These packets are normally discarded. + If circumstances beyond your control force you to support such + servers, this may help. The upper limit (924) makes dhcpc accept + even 1500 byte packets (maximum-sized ethernet packets). + + This option does not make dhcp[cd] emit non-standard + sized packets. + + Known buggy DHCP servers: + 3Com OfficeConnect Remote 812 ADSL Router: + seems to confuse maximum allowed UDP packet size with + maximum size of entire IP packet, and sends packets which are + 28 bytes too large. + Seednet (ISP) VDSL: sends packets 2 bytes too large. diff --git a/package/utils/busybox/config/printutils/Config.in b/package/utils/busybox/config/printutils/Config.in new file mode 100644 index 0000000..cccc4a5 --- /dev/null +++ b/package/utils/busybox/config/printutils/Config.in @@ -0,0 +1,28 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Print Utilities" + + +config BUSYBOX_CONFIG_LPD + bool "lpd" + default BUSYBOX_DEFAULT_LPD + help + lpd is a print spooling daemon. + +config BUSYBOX_CONFIG_LPR + bool "lpr" + default BUSYBOX_DEFAULT_LPR + help + lpr sends files (or standard input) to a print spooling daemon. + +config BUSYBOX_CONFIG_LPQ + bool "lpq" + default BUSYBOX_DEFAULT_LPQ + help + lpq is a print spool queue examination and manipulation program. + +endmenu diff --git a/package/utils/busybox/config/procps/Config.in b/package/utils/busybox/config/procps/Config.in new file mode 100644 index 0000000..6eafbda --- /dev/null +++ b/package/utils/busybox/config/procps/Config.in @@ -0,0 +1,273 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Process Utilities" + +config BUSYBOX_CONFIG_IOSTAT + bool "iostat" + default BUSYBOX_DEFAULT_IOSTAT + help + Report CPU and I/O statistics +config BUSYBOX_CONFIG_LSOF + bool "lsof" + default BUSYBOX_DEFAULT_LSOF + help + Show open files in the format of: + PID <TAB> /path/to/executable <TAB> /path/to/opened/file +config BUSYBOX_CONFIG_MPSTAT + bool "mpstat" + default BUSYBOX_DEFAULT_MPSTAT + help + Per-processor statistics +config BUSYBOX_CONFIG_NMETER + bool "nmeter" + default BUSYBOX_DEFAULT_NMETER + help + Prints selected system stats continuously, one line per update. +config BUSYBOX_CONFIG_PMAP + bool "pmap" + default BUSYBOX_DEFAULT_PMAP + help + Display processes' memory mappings. +config BUSYBOX_CONFIG_POWERTOP + bool "powertop" + default BUSYBOX_DEFAULT_POWERTOP + help + Analyze power consumption on Intel-based laptops +config BUSYBOX_CONFIG_PSTREE + bool "pstree" + default BUSYBOX_DEFAULT_PSTREE + help + Display a tree of processes. +config BUSYBOX_CONFIG_PWDX + bool "pwdx" + default BUSYBOX_DEFAULT_PWDX + help + Report current working directory of a process +config BUSYBOX_CONFIG_SMEMCAP + bool "smemcap" + default BUSYBOX_DEFAULT_SMEMCAP + help + smemcap is a tool for capturing process data for smem, + a memory usage statistic tool. +config BUSYBOX_CONFIG_TOP + bool "top" + default BUSYBOX_DEFAULT_TOP + help + The top program provides a dynamic real-time view of a running + system. + +config BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE + bool "Show CPU per-process usage percentage" + default BUSYBOX_DEFAULT_FEATURE_TOP_CPU_USAGE_PERCENTAGE + depends on BUSYBOX_CONFIG_TOP + help + Make top display CPU usage for each process. + This adds about 2k. + +config BUSYBOX_CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS + bool "Show CPU global usage percentage" + default BUSYBOX_DEFAULT_FEATURE_TOP_CPU_GLOBAL_PERCENTS + depends on BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE + help + Makes top display "CPU: NN% usr NN% sys..." line. + This adds about 0.5k. + +config BUSYBOX_CONFIG_FEATURE_TOP_SMP_CPU + bool "SMP CPU usage display ('c' key)" + default BUSYBOX_DEFAULT_FEATURE_TOP_SMP_CPU + depends on BUSYBOX_CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS + help + Allow 'c' key to switch between individual/cumulative CPU stats + This adds about 0.5k. + +config BUSYBOX_CONFIG_FEATURE_TOP_DECIMALS + bool "Show 1/10th of a percent in CPU/mem statistics" + default BUSYBOX_DEFAULT_FEATURE_TOP_DECIMALS + depends on BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE + help + Show 1/10th of a percent in CPU/mem statistics. + This adds about 0.3k. + +config BUSYBOX_CONFIG_FEATURE_TOP_SMP_PROCESS + bool "Show CPU process runs on ('j' field)" + default BUSYBOX_DEFAULT_FEATURE_TOP_SMP_PROCESS + depends on BUSYBOX_CONFIG_TOP + help + Show CPU where process was last found running on. + This is the 'j' field. + +config BUSYBOX_CONFIG_FEATURE_TOPMEM + bool "Topmem command ('s' key)" + default BUSYBOX_DEFAULT_FEATURE_TOPMEM + depends on BUSYBOX_CONFIG_TOP + help + Enable 's' in top (gives lots of memory info). +config BUSYBOX_CONFIG_UPTIME + bool "uptime" + default BUSYBOX_DEFAULT_UPTIME + select BUSYBOX_CONFIG_PLATFORM_LINUX #sysinfo() + help + uptime gives a one line display of the current time, how long + the system has been running, how many users are currently logged + on, and the system load averages for the past 1, 5, and 15 minutes. + +config BUSYBOX_CONFIG_FEATURE_UPTIME_UTMP_SUPPORT + bool "Support for showing the number of users" + default BUSYBOX_DEFAULT_FEATURE_UPTIME_UTMP_SUPPORT + depends on BUSYBOX_CONFIG_UPTIME && BUSYBOX_CONFIG_FEATURE_UTMP + help + Makes uptime display the number of users currently logged on. + +config BUSYBOX_CONFIG_FREE + bool "free" + default BUSYBOX_DEFAULT_FREE + select BUSYBOX_CONFIG_PLATFORM_LINUX #sysinfo() + help + free displays the total amount of free and used physical and swap + memory in the system, as well as the buffers used by the kernel. + The shared memory column should be ignored; it is obsolete. + +config BUSYBOX_CONFIG_FUSER + bool "fuser" + default BUSYBOX_DEFAULT_FUSER + help + fuser lists all PIDs (Process IDs) that currently have a given + file open. fuser can also list all PIDs that have a given network + (TCP or UDP) port open. + +config BUSYBOX_CONFIG_KILL + bool "kill" + default BUSYBOX_DEFAULT_KILL + help + The command kill sends the specified signal to the specified + process or process group. If no signal is specified, the TERM + signal is sent. + +config BUSYBOX_CONFIG_KILLALL + bool "killall" + default BUSYBOX_DEFAULT_KILLALL + depends on BUSYBOX_CONFIG_KILL + help + killall sends a signal to all processes running any of the + specified commands. If no signal name is specified, SIGTERM is + sent. + +config BUSYBOX_CONFIG_KILLALL5 + bool "killall5" + default BUSYBOX_DEFAULT_KILLALL5 + depends on BUSYBOX_CONFIG_KILL + +config BUSYBOX_CONFIG_PGREP + bool "pgrep" + default BUSYBOX_DEFAULT_PGREP + help + Look for processes by name. + +config BUSYBOX_CONFIG_PIDOF + bool "pidof" + default BUSYBOX_DEFAULT_PIDOF + help + Pidof finds the process id's (pids) of the named programs. It prints + those id's on the standard output. + +config BUSYBOX_CONFIG_FEATURE_PIDOF_SINGLE + bool "Enable argument for single shot (-s)" + default BUSYBOX_DEFAULT_FEATURE_PIDOF_SINGLE + depends on BUSYBOX_CONFIG_PIDOF + help + Support argument '-s' for returning only the first pid found. + +config BUSYBOX_CONFIG_FEATURE_PIDOF_OMIT + bool "Enable argument for omitting pids (-o)" + default BUSYBOX_DEFAULT_FEATURE_PIDOF_OMIT + depends on BUSYBOX_CONFIG_PIDOF + help + Support argument '-o' for omitting the given pids in output. + The special pid %PPID can be used to name the parent process + of the pidof, in other words the calling shell or shell script. + +config BUSYBOX_CONFIG_PKILL + bool "pkill" + default BUSYBOX_DEFAULT_PKILL + help + Send signals to processes by name. + +config BUSYBOX_CONFIG_PS + bool "ps" + default BUSYBOX_DEFAULT_PS + help + ps gives a snapshot of the current processes. + +config BUSYBOX_CONFIG_FEATURE_PS_WIDE + bool "Enable wide output option (-w)" + default BUSYBOX_DEFAULT_FEATURE_PS_WIDE + depends on BUSYBOX_CONFIG_PS && !BUSYBOX_CONFIG_DESKTOP + help + Support argument 'w' for wide output. + If given once, 132 chars are printed, and if given more + than once, the length is unlimited. + +config BUSYBOX_CONFIG_FEATURE_PS_LONG + bool "Enable long output option (-l)" + default BUSYBOX_DEFAULT_FEATURE_PS_LONG + depends on BUSYBOX_CONFIG_PS && !BUSYBOX_CONFIG_DESKTOP + help + Support argument 'l' for long output. + Adds fields PPID, RSS, START, TIME & TTY + +config BUSYBOX_CONFIG_FEATURE_PS_TIME + bool "Enable time and elapsed time output" + default BUSYBOX_DEFAULT_FEATURE_PS_TIME + depends on BUSYBOX_CONFIG_PS && BUSYBOX_CONFIG_DESKTOP + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Support -o time and -o etime output specifiers. + +config BUSYBOX_CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS + bool "Enable additional ps columns" + default BUSYBOX_DEFAULT_FEATURE_PS_ADDITIONAL_COLUMNS + depends on BUSYBOX_CONFIG_PS && BUSYBOX_CONFIG_DESKTOP + help + Support -o rgroup, -o ruser, -o nice output specifiers. + +config BUSYBOX_CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS + bool "Support Linux prior to 2.4.0 and non-ELF systems" + default BUSYBOX_DEFAULT_FEATURE_PS_UNUSUAL_SYSTEMS + depends on BUSYBOX_CONFIG_FEATURE_PS_TIME + help + Include support for measuring HZ on old kernels and non-ELF systems + (if you are on Linux 2.4.0+ and use ELF, you don't need this) + +config BUSYBOX_CONFIG_RENICE + bool "renice" + default BUSYBOX_DEFAULT_RENICE + help + Renice alters the scheduling priority of one or more running + processes. + +config BUSYBOX_CONFIG_BB_SYSCTL + bool "sysctl" + default BUSYBOX_DEFAULT_BB_SYSCTL + help + Configure kernel parameters at runtime. + +config BUSYBOX_CONFIG_FEATURE_SHOW_THREADS + bool "Support for showing threads in ps/pstree/top" + default BUSYBOX_DEFAULT_FEATURE_SHOW_THREADS + depends on BUSYBOX_CONFIG_PS || BUSYBOX_CONFIG_TOP || BUSYBOX_CONFIG_PSTREE + help + Enables the ps -T option, showing of threads in pstree, + and 'h' command in top. + +config BUSYBOX_CONFIG_WATCH + bool "watch" + default BUSYBOX_DEFAULT_WATCH + help + watch is used to execute a program periodically, showing + output to the screen. + +endmenu diff --git a/package/utils/busybox/config/runit/Config.in b/package/utils/busybox/config/runit/Config.in new file mode 100644 index 0000000..8074fb1 --- /dev/null +++ b/package/utils/busybox/config/runit/Config.in @@ -0,0 +1,89 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Runit Utilities" + + +config BUSYBOX_CONFIG_RUNSV + bool "runsv" + default BUSYBOX_DEFAULT_RUNSV + help + runsv starts and monitors a service and optionally an appendant log + service. + +config BUSYBOX_CONFIG_RUNSVDIR + bool "runsvdir" + default BUSYBOX_DEFAULT_RUNSVDIR + help + runsvdir starts a runsv process for each subdirectory, or symlink to + a directory, in the services directory dir, up to a limit of 1000 + subdirectories, and restarts a runsv process if it terminates. + +config BUSYBOX_CONFIG_FEATURE_RUNSVDIR_LOG + bool "Enable scrolling argument log" + depends on BUSYBOX_CONFIG_RUNSVDIR + default BUSYBOX_DEFAULT_FEATURE_RUNSVDIR_LOG + help + Enable feature where second parameter of runsvdir holds last error + message (viewable via top/ps). Otherwise (feature is off + or no parameter), error messages go to stderr only. + +config BUSYBOX_CONFIG_SV + bool "sv" + default BUSYBOX_DEFAULT_SV + help + sv reports the current status and controls the state of services + monitored by the runsv supervisor. + +config BUSYBOX_CONFIG_SV_DEFAULT_SERVICE_DIR + string "Default directory for services" + default BUSYBOX_DEFAULT_SV_DEFAULT_SERVICE_DIR + depends on BUSYBOX_CONFIG_SV + help + Default directory for services. + Defaults to "/var/service" + +config BUSYBOX_CONFIG_SVLOGD + bool "svlogd" + default BUSYBOX_DEFAULT_SVLOGD + help + svlogd continuously reads log data from its standard input, optionally + filters log messages, and writes the data to one or more automatically + rotated logs. + +config BUSYBOX_CONFIG_CHPST + bool "chpst" + default BUSYBOX_DEFAULT_CHPST + help + chpst changes the process state according to the given options, and + execs specified program. + +config BUSYBOX_CONFIG_SETUIDGID + bool "setuidgid" + default BUSYBOX_DEFAULT_SETUIDGID + help + Sets soft resource limits as specified by options + +config BUSYBOX_CONFIG_ENVUIDGID + bool "envuidgid" + default BUSYBOX_DEFAULT_ENVUIDGID + help + Sets $UID to account's uid and $GID to account's gid + +config BUSYBOX_CONFIG_ENVDIR + bool "envdir" + default BUSYBOX_DEFAULT_ENVDIR + help + Sets various environment variables as specified by files + in the given directory + +config BUSYBOX_CONFIG_SOFTLIMIT + bool "softlimit" + default BUSYBOX_DEFAULT_SOFTLIMIT + help + Sets soft resource limits as specified by options + +endmenu diff --git a/package/utils/busybox/config/selinux/Config.in b/package/utils/busybox/config/selinux/Config.in new file mode 100644 index 0000000..3340e4b --- /dev/null +++ b/package/utils/busybox/config/selinux/Config.in @@ -0,0 +1,124 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "SELinux Utilities" + depends on BUSYBOX_CONFIG_SELINUX + + +config BUSYBOX_CONFIG_CHCON + bool "chcon" + default BUSYBOX_DEFAULT_CHCON + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support to change the security context of file. + +config BUSYBOX_CONFIG_FEATURE_CHCON_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_CHCON_LONG_OPTIONS + depends on BUSYBOX_CONFIG_CHCON && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the chcon applet. + +config BUSYBOX_CONFIG_GETENFORCE + bool "getenforce" + default BUSYBOX_DEFAULT_GETENFORCE + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support to get the current mode of SELinux. + +config BUSYBOX_CONFIG_GETSEBOOL + bool "getsebool" + default BUSYBOX_DEFAULT_GETSEBOOL + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support to get SELinux boolean values. + +config BUSYBOX_CONFIG_LOAD_POLICY + bool "load_policy" + default BUSYBOX_DEFAULT_LOAD_POLICY + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support to load SELinux policy. + +config BUSYBOX_CONFIG_MATCHPATHCON + bool "matchpathcon" + default BUSYBOX_DEFAULT_MATCHPATHCON + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support to get default security context of the + specified path from the file contexts configuration. + +config BUSYBOX_CONFIG_RESTORECON + bool "restorecon" + default BUSYBOX_DEFAULT_RESTORECON + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support to relabel files. The feature is almost + the same as setfiles, but usage is a little different. + +config BUSYBOX_CONFIG_RUNCON + bool "runcon" + default BUSYBOX_DEFAULT_RUNCON + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support to run command in speficied security context. + +config BUSYBOX_CONFIG_FEATURE_RUNCON_LONG_OPTIONS + bool "Enable long options" + default BUSYBOX_DEFAULT_FEATURE_RUNCON_LONG_OPTIONS + depends on BUSYBOX_CONFIG_RUNCON && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the runcon applet. + +config BUSYBOX_CONFIG_SELINUXENABLED + bool "selinuxenabled" + default BUSYBOX_DEFAULT_SELINUXENABLED + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support for this command to be used within shell scripts + to determine if selinux is enabled. + +config BUSYBOX_CONFIG_SETENFORCE + bool "setenforce" + default BUSYBOX_DEFAULT_SETENFORCE + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support to modify the mode SELinux is running in. + +config BUSYBOX_CONFIG_SETFILES + bool "setfiles" + default BUSYBOX_DEFAULT_SETFILES + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support to modify to relabel files. + Notice: If you built libselinux with -D_FILE_OFFSET_BITS=64, + (It is default in libselinux's Makefile), you _must_ enable + CONFIG_LFS. + +config BUSYBOX_CONFIG_FEATURE_SETFILES_CHECK_OPTION + bool "Enable check option" + default BUSYBOX_DEFAULT_FEATURE_SETFILES_CHECK_OPTION + depends on BUSYBOX_CONFIG_SETFILES + help + Support "-c" option (check the validity of the contexts against + the specified binary policy) for setfiles. Requires libsepol. + +config BUSYBOX_CONFIG_SETSEBOOL + bool "setsebool" + default BUSYBOX_DEFAULT_SETSEBOOL + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support for change boolean. + semanage and -P option is not supported yet. + +config BUSYBOX_CONFIG_SESTATUS + bool "sestatus" + default BUSYBOX_DEFAULT_SESTATUS + depends on BUSYBOX_CONFIG_SELINUX + help + Displays the status of SELinux. + +endmenu diff --git a/package/utils/busybox/config/shell/Config.in b/package/utils/busybox/config/shell/Config.in new file mode 100644 index 0000000..69ecf14 --- /dev/null +++ b/package/utils/busybox/config/shell/Config.in @@ -0,0 +1,444 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Shells" + +config BUSYBOX_CONFIG_ASH + bool "ash" + default BUSYBOX_DEFAULT_ASH + depends on !BUSYBOX_CONFIG_NOMMU + help + Tha 'ash' shell adds about 60k in the default configuration and is + the most complete and most pedantically correct shell included with + busybox. This shell is actually a derivative of the Debian 'dash' + shell (by Herbert Xu), which was created by porting the 'ash' shell + (written by Kenneth Almquist) from NetBSD. + +config BUSYBOX_CONFIG_ASH_BASH_COMPAT + bool "bash-compatible extensions" + default BUSYBOX_DEFAULT_ASH_BASH_COMPAT + depends on BUSYBOX_CONFIG_ASH + help + Enable bash-compatible extensions. + +config BUSYBOX_CONFIG_ASH_IDLE_TIMEOUT + bool "Idle timeout variable" + default BUSYBOX_DEFAULT_ASH_IDLE_TIMEOUT + depends on BUSYBOX_CONFIG_ASH + help + Enables bash-like auto-logout after $TMOUT seconds of idle time. + +config BUSYBOX_CONFIG_ASH_JOB_CONTROL + bool "Job control" + default BUSYBOX_DEFAULT_ASH_JOB_CONTROL + depends on BUSYBOX_CONFIG_ASH + help + Enable job control in the ash shell. + +config BUSYBOX_CONFIG_ASH_ALIAS + bool "Alias support" + default BUSYBOX_DEFAULT_ASH_ALIAS + depends on BUSYBOX_CONFIG_ASH + help + Enable alias support in the ash shell. + +config BUSYBOX_CONFIG_ASH_GETOPTS + bool "Builtin getopt to parse positional parameters" + default BUSYBOX_DEFAULT_ASH_GETOPTS + depends on BUSYBOX_CONFIG_ASH + help + Enable support for getopts builtin in ash. + +config BUSYBOX_CONFIG_ASH_BUILTIN_ECHO + bool "Builtin version of 'echo'" + default BUSYBOX_DEFAULT_ASH_BUILTIN_ECHO + depends on BUSYBOX_CONFIG_ASH + help + Enable support for echo builtin in ash. + +config BUSYBOX_CONFIG_ASH_BUILTIN_PRINTF + bool "Builtin version of 'printf'" + default BUSYBOX_DEFAULT_ASH_BUILTIN_PRINTF + depends on BUSYBOX_CONFIG_ASH + help + Enable support for printf builtin in ash. + +config BUSYBOX_CONFIG_ASH_BUILTIN_TEST + bool "Builtin version of 'test'" + default BUSYBOX_DEFAULT_ASH_BUILTIN_TEST + depends on BUSYBOX_CONFIG_ASH + help + Enable support for test builtin in ash. + +config BUSYBOX_CONFIG_ASH_HELP + bool "help builtin" + default BUSYBOX_DEFAULT_ASH_HELP + depends on BUSYBOX_CONFIG_ASH + help + Enable help builtin in ash. + +config BUSYBOX_CONFIG_ASH_CMDCMD + bool "'command' command to override shell builtins" + default BUSYBOX_DEFAULT_ASH_CMDCMD + depends on BUSYBOX_CONFIG_ASH + help + Enable support for the ash 'command' builtin, which allows + you to run the specified command with the specified arguments, + even when there is an ash builtin command with the same name. + +config BUSYBOX_CONFIG_ASH_MAIL + bool "Check for new mail on interactive shells" + default BUSYBOX_DEFAULT_ASH_MAIL + depends on BUSYBOX_CONFIG_ASH + help + Enable "check for new mail" function in the ash shell. + +config BUSYBOX_CONFIG_ASH_OPTIMIZE_FOR_SIZE + bool "Optimize for size instead of speed" + default BUSYBOX_DEFAULT_ASH_OPTIMIZE_FOR_SIZE + depends on BUSYBOX_CONFIG_ASH + help + Compile ash for reduced size at the price of speed. + +config BUSYBOX_CONFIG_ASH_RANDOM_SUPPORT + bool "Pseudorandom generator and $RANDOM variable" + default BUSYBOX_DEFAULT_ASH_RANDOM_SUPPORT + depends on BUSYBOX_CONFIG_ASH + help + Enable pseudorandom generator and dynamic variable "$RANDOM". + Each read of "$RANDOM" will generate a new pseudorandom value. + You can reset the generator by using a specified start value. + After "unset RANDOM" the generator will switch off and this + variable will no longer have special treatment. + +config BUSYBOX_CONFIG_ASH_EXPAND_PRMT + bool "Expand prompt string" + default BUSYBOX_DEFAULT_ASH_EXPAND_PRMT + depends on BUSYBOX_CONFIG_ASH + help + "PS#" may contain volatile content, such as backquote commands. + This option recreates the prompt string from the environment + variable each time it is displayed. + +config BUSYBOX_CONFIG_CTTYHACK + bool "cttyhack" + default BUSYBOX_DEFAULT_CTTYHACK + help + One common problem reported on the mailing list is the "can't + access tty; job control turned off" error message, which typically + appears when one tries to use a shell with stdin/stdout on + /dev/console. + This device is special - it cannot be a controlling tty. + + The proper solution is to use the correct device instead of + /dev/console. + + cttyhack provides a "quick and dirty" solution to this problem. + It analyzes stdin with various ioctls, trying to determine whether + it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line). + On Linux it also checks sysfs for a pointer to the active console. + If cttyhack is able to find the real console device, it closes + stdin/out/err and reopens that device. + Then it executes the given program. Opening the device will make + that device a controlling tty. This may require cttyhack + to be a session leader. + + Example for /etc/inittab (for busybox init): + + ::respawn:/bin/cttyhack /bin/sh + + Starting an interactive shell from boot shell script: + + setsid cttyhack sh + + Giving controlling tty to shell running with PID 1: + + # exec cttyhack sh + + Without cttyhack, you need to know exact tty name, + and do something like this: + + # exec setsid sh -c 'exec sh </dev/tty1 >/dev/tty1 2>&1' + + Starting getty on a controlling tty from a shell script: + + # getty 115200 $(cttyhack) +config BUSYBOX_CONFIG_HUSH + bool "hush" + default BUSYBOX_DEFAULT_HUSH + help + hush is a small shell (25k). It handles the normal flow control + constructs such as if/then/elif/else/fi, for/in/do/done, while loops, + case/esac. Redirections, here documents, $((arithmetic)) + and functions are supported. + + It will compile and work on no-mmu systems. + + It does not handle select, aliases, tilde expansion, + &>file and >&file redirection of stdout+stderr. + +config BUSYBOX_CONFIG_HUSH_BASH_COMPAT + bool "bash-compatible extensions" + default BUSYBOX_DEFAULT_HUSH_BASH_COMPAT + depends on BUSYBOX_CONFIG_HUSH + help + Enable bash-compatible extensions. + +config BUSYBOX_CONFIG_HUSH_BRACE_EXPANSION + bool "Brace expansion" + default BUSYBOX_DEFAULT_HUSH_BRACE_EXPANSION + depends on BUSYBOX_CONFIG_HUSH_BASH_COMPAT + help + Enable {abc,def} extension. + +config BUSYBOX_CONFIG_HUSH_HELP + bool "help builtin" + default BUSYBOX_DEFAULT_HUSH_HELP + depends on BUSYBOX_CONFIG_HUSH + help + Enable help builtin in hush. Code size + ~1 kbyte. + +config BUSYBOX_CONFIG_HUSH_INTERACTIVE + bool "Interactive mode" + default BUSYBOX_DEFAULT_HUSH_INTERACTIVE + depends on BUSYBOX_CONFIG_HUSH + help + Enable interactive mode (prompt and command editing). + Without this, hush simply reads and executes commands + from stdin just like a shell script from a file. + No prompt, no PS1/PS2 magic shell variables. + +config BUSYBOX_CONFIG_HUSH_SAVEHISTORY + bool "Save command history to .hush_history" + default BUSYBOX_DEFAULT_HUSH_SAVEHISTORY + depends on BUSYBOX_CONFIG_HUSH_INTERACTIVE && BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY + help + Enable history saving in hush. + +config BUSYBOX_CONFIG_HUSH_JOB + bool "Job control" + default BUSYBOX_DEFAULT_HUSH_JOB + depends on BUSYBOX_CONFIG_HUSH_INTERACTIVE + help + Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current + command (not entire shell), fg/bg builtins work. Without this option, + "cmd &" still works by simply spawning a process and immediately + prompting for next command (or executing next command in a script), + but no separate process group is formed. + +config BUSYBOX_CONFIG_HUSH_TICK + bool "Process substitution" + default BUSYBOX_DEFAULT_HUSH_TICK + depends on BUSYBOX_CONFIG_HUSH + help + Enable process substitution `command` and $(command) in hush. + +config BUSYBOX_CONFIG_HUSH_IF + bool "Support if/then/elif/else/fi" + default BUSYBOX_DEFAULT_HUSH_IF + depends on BUSYBOX_CONFIG_HUSH + help + Enable if/then/elif/else/fi in hush. + +config BUSYBOX_CONFIG_HUSH_LOOPS + bool "Support for, while and until loops" + default BUSYBOX_DEFAULT_HUSH_LOOPS + depends on BUSYBOX_CONFIG_HUSH + help + Enable for, while and until loops in hush. + +config BUSYBOX_CONFIG_HUSH_CASE + bool "Support case ... esac statement" + default BUSYBOX_DEFAULT_HUSH_CASE + depends on BUSYBOX_CONFIG_HUSH + help + Enable case ... esac statement in hush. +400 bytes. + +config BUSYBOX_CONFIG_HUSH_FUNCTIONS + bool "Support funcname() { commands; } syntax" + default BUSYBOX_DEFAULT_HUSH_FUNCTIONS + depends on BUSYBOX_CONFIG_HUSH + help + Enable support for shell functions in hush. +800 bytes. + +config BUSYBOX_CONFIG_HUSH_LOCAL + bool "Support local builtin" + default BUSYBOX_DEFAULT_HUSH_LOCAL + depends on BUSYBOX_CONFIG_HUSH_FUNCTIONS + help + Enable support for local variables in functions. + +config BUSYBOX_CONFIG_HUSH_RANDOM_SUPPORT + bool "Pseudorandom generator and $RANDOM variable" + default BUSYBOX_DEFAULT_HUSH_RANDOM_SUPPORT + depends on BUSYBOX_CONFIG_HUSH + help + Enable pseudorandom generator and dynamic variable "$RANDOM". + Each read of "$RANDOM" will generate a new pseudorandom value. + +config BUSYBOX_CONFIG_HUSH_EXPORT_N + bool "Support 'export -n' option" + default BUSYBOX_DEFAULT_HUSH_EXPORT_N + depends on BUSYBOX_CONFIG_HUSH + help + export -n unexports variables. It is a bash extension. + +config BUSYBOX_CONFIG_HUSH_MODE_X + bool "Support 'hush -x' option and 'set -x' command" + default BUSYBOX_DEFAULT_HUSH_MODE_X + depends on BUSYBOX_CONFIG_HUSH + help + This instructs hush to print commands before execution. + Adds ~300 bytes. + +config BUSYBOX_CONFIG_MSH + bool "msh (deprecated: aliased to hush)" + default BUSYBOX_DEFAULT_MSH + select BUSYBOX_CONFIG_HUSH + help + msh is deprecated and will be removed, please migrate to hush. + + + +choice + prompt "Choose which shell is aliased to 'sh' name" + default BUSYBOX_CONFIG_FEATURE_SH_IS_ASH + help + Choose which shell you want to be executed by 'sh' alias. + The ash shell is the most bash compatible and full featured one. + +# note: cannot use "select ASH" here, it breaks "make allnoconfig" +config BUSYBOX_CONFIG_FEATURE_SH_IS_ASH + depends on BUSYBOX_CONFIG_ASH + bool "ash" + depends on !BUSYBOX_CONFIG_NOMMU + +config BUSYBOX_CONFIG_FEATURE_SH_IS_HUSH + depends on BUSYBOX_CONFIG_HUSH + bool "hush" + +config BUSYBOX_CONFIG_FEATURE_SH_IS_NONE + bool "none" + +endchoice + +choice + prompt "Choose which shell is aliased to 'bash' name" + default BUSYBOX_CONFIG_FEATURE_BASH_IS_NONE + help + Choose which shell you want to be executed by 'bash' alias. + The ash shell is the most bash compatible and full featured one. + + Note that selecting this option does not switch on any bash + compatibility code. It merely makes it possible to install + /bin/bash (sym)link and run scripts which start with + #!/bin/bash line. + + Many systems use it in scripts which use bash-specific features, + even simple ones like $RANDOM. Without this option, busybox + can't be used for running them because it won't recongnize + "bash" as a supported applet name. + +config BUSYBOX_CONFIG_FEATURE_BASH_IS_ASH + depends on BUSYBOX_CONFIG_ASH + bool "ash" + depends on !BUSYBOX_CONFIG_NOMMU + +config BUSYBOX_CONFIG_FEATURE_BASH_IS_HUSH + depends on BUSYBOX_CONFIG_HUSH + bool "hush" + +config BUSYBOX_CONFIG_FEATURE_BASH_IS_NONE + bool "none" + +endchoice + + +config BUSYBOX_CONFIG_SH_MATH_SUPPORT + bool "POSIX math support" + default BUSYBOX_DEFAULT_SH_MATH_SUPPORT + depends on BUSYBOX_CONFIG_ASH || BUSYBOX_CONFIG_HUSH + help + Enable math support in the shell via $((...)) syntax. + +config BUSYBOX_CONFIG_SH_MATH_SUPPORT_64 + bool "Extend POSIX math support to 64 bit" + default BUSYBOX_DEFAULT_SH_MATH_SUPPORT_64 + depends on BUSYBOX_CONFIG_SH_MATH_SUPPORT + help + Enable 64-bit math support in the shell. This will make the shell + slightly larger, but will allow computation with very large numbers. + This is not in POSIX, so do not rely on this in portable code. + +config BUSYBOX_CONFIG_FEATURE_SH_EXTRA_QUIET + bool "Hide message on interactive shell startup" + default BUSYBOX_DEFAULT_FEATURE_SH_EXTRA_QUIET + depends on BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH + help + Remove the busybox introduction when starting a shell. + +config BUSYBOX_CONFIG_FEATURE_SH_STANDALONE + bool "Standalone shell" + default BUSYBOX_DEFAULT_FEATURE_SH_STANDALONE + depends on (BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH) && BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS + help + This option causes busybox shells to use busybox applets + in preference to executables in the PATH whenever possible. For + example, entering the command 'ifconfig' into the shell would cause + busybox to use the ifconfig busybox applet. Specifying the fully + qualified executable name, such as '/sbin/ifconfig' will still + execute the /sbin/ifconfig executable on the filesystem. This option + is generally used when creating a statically linked version of busybox + for use as a rescue shell, in the event that you screw up your system. + + This is implemented by re-execing /proc/self/exe (typically) + with right parameters. Some selected applets ("NOFORK" applets) + can even be executed without creating new process. + Instead, busybox will call <applet>_main() internally. + + However, this causes problems in chroot jails without mounted /proc + and with ps/top (command name can be shown as 'exe' for applets + started this way). +# untrue? +# Note that this will *also* cause applets to take precedence +# over shell builtins of the same name. So turning this on will +# eliminate any performance gained by turning on the builtin "echo" +# and "test" commands in ash. +# untrue? +# Note that when using this option, the shell will attempt to directly +# run '/bin/busybox'. If you do not have the busybox binary sitting in +# that exact location with that exact name, this option will not work at +# all. + +config BUSYBOX_CONFIG_FEATURE_SH_NOFORK + bool "Run 'nofork' applets directly" + default BUSYBOX_DEFAULT_FEATURE_SH_NOFORK + depends on (BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH) && BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS + help + This option causes busybox shells to not execute typical + fork/exec/wait sequence, but call <applet>_main directly, + if possible. (Sometimes it is not possible: for example, + this is not possible in pipes). + + This will be done only for some applets (those which are marked + NOFORK in include/applets.h). + + This may significantly speed up some shell scripts. + + This feature is relatively new. Use with care. Report bugs + to project mailing list. + +config BUSYBOX_CONFIG_FEATURE_SH_HISTFILESIZE + bool "Use $HISTFILESIZE" + default BUSYBOX_DEFAULT_FEATURE_SH_HISTFILESIZE + depends on BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH + help + This option makes busybox shells to use $HISTFILESIZE variable + to set shell history size. Note that its max value is capped + by "History size" setting in library tuning section. + + +endmenu diff --git a/package/utils/busybox/config/sysklogd/Config.in b/package/utils/busybox/config/sysklogd/Config.in new file mode 100644 index 0000000..de36a1e --- /dev/null +++ b/package/utils/busybox/config/sysklogd/Config.in @@ -0,0 +1,169 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "System Logging Utilities" + + +config BUSYBOX_CONFIG_SYSLOGD + bool "syslogd" + default BUSYBOX_DEFAULT_SYSLOGD + help + The syslogd utility is used to record logs of all the + significant events that occur on a system. Every + message that is logged records the date and time of the + event, and will generally also record the name of the + application that generated the message. When used in + conjunction with klogd, messages from the Linux kernel + can also be recorded. This is terribly useful, + especially for finding what happened when something goes + wrong. And something almost always will go wrong if + you wait long enough.... + +config BUSYBOX_CONFIG_FEATURE_ROTATE_LOGFILE + bool "Rotate message files" + default BUSYBOX_DEFAULT_FEATURE_ROTATE_LOGFILE + depends on BUSYBOX_CONFIG_SYSLOGD + help + This enables syslogd to rotate the message files + on his own. No need to use an external rotatescript. + +config BUSYBOX_CONFIG_FEATURE_REMOTE_LOG + bool "Remote Log support" + default BUSYBOX_DEFAULT_FEATURE_REMOTE_LOG + depends on BUSYBOX_CONFIG_SYSLOGD + help + When you enable this feature, the syslogd utility can + be used to send system log messages to another system + connected via a network. This allows the remote + machine to log all the system messages, which can be + terribly useful for reducing the number of serial + cables you use. It can also be a very good security + measure to prevent system logs from being tampered with + by an intruder. + +config BUSYBOX_CONFIG_FEATURE_SYSLOGD_DUP + bool "Support -D (drop dups) option" + default BUSYBOX_DEFAULT_FEATURE_SYSLOGD_DUP + depends on BUSYBOX_CONFIG_SYSLOGD + help + Option -D instructs syslogd to drop consecutive messages + which are totally the same. + +config BUSYBOX_CONFIG_FEATURE_SYSLOGD_CFG + bool "Support syslog.conf" + default BUSYBOX_DEFAULT_FEATURE_SYSLOGD_CFG + depends on BUSYBOX_CONFIG_SYSLOGD + help + Supports restricted syslogd config. See docs/syslog.conf.txt + +config BUSYBOX_CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE + int "Read buffer size in bytes" + default BUSYBOX_DEFAULT_FEATURE_SYSLOGD_READ_BUFFER_SIZE + range 256 20000 + depends on BUSYBOX_CONFIG_SYSLOGD + help + This option sets the size of the syslog read buffer. + Actual memory usage increases around five times the + change done here. + +config BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG + bool "Circular Buffer support" + default BUSYBOX_DEFAULT_FEATURE_IPC_SYSLOG + depends on BUSYBOX_CONFIG_SYSLOGD + help + When you enable this feature, the syslogd utility will + use a circular buffer to record system log messages. + When the buffer is filled it will continue to overwrite + the oldest messages. This can be very useful for + systems with little or no permanent storage, since + otherwise system logs can eventually fill up your + entire filesystem, which may cause your system to + break badly. + +config BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE + int "Circular buffer size in Kbytes (minimum 4KB)" + default BUSYBOX_DEFAULT_FEATURE_IPC_SYSLOG_BUFFER_SIZE + range 4 2147483647 + depends on BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG + help + This option sets the size of the circular buffer + used to record system log messages. + +config BUSYBOX_CONFIG_LOGREAD + bool "logread" + default BUSYBOX_DEFAULT_LOGREAD + depends on BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG + help + If you enabled Circular Buffer support, you almost + certainly want to enable this feature as well. This + utility will allow you to read the messages that are + stored in the syslogd circular buffer. + +config BUSYBOX_CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING + bool "Double buffering" + default BUSYBOX_DEFAULT_FEATURE_LOGREAD_REDUCED_LOCKING + depends on BUSYBOX_CONFIG_LOGREAD + help + 'logread' ouput to slow serial terminals can have + side effects on syslog because of the semaphore. + This option make logread to double buffer copy + from circular buffer, minimizing semaphore + contention at some minor memory expense. + +config BUSYBOX_CONFIG_FEATURE_KMSG_SYSLOG + bool "Linux kernel printk buffer support" + default BUSYBOX_DEFAULT_FEATURE_KMSG_SYSLOG + depends on BUSYBOX_CONFIG_SYSLOGD + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + When you enable this feature, the syslogd utility will + write system log message to the Linux kernel's printk buffer. + This can be used as a smaller alternative to the syslogd IPC + support, as klogd and logread aren't needed. + + NOTICE: Syslog facilities in log entries needs kernel 3.5+. + +config BUSYBOX_CONFIG_KLOGD + bool "klogd" + default BUSYBOX_DEFAULT_KLOGD + help + klogd is a utility which intercepts and logs all + messages from the Linux kernel and sends the messages + out to the 'syslogd' utility so they can be logged. If + you wish to record the messages produced by the kernel, + you should enable this option. + +comment "klogd should not be used together with syslog to kernel printk buffer" + depends on BUSYBOX_CONFIG_KLOGD && BUSYBOX_CONFIG_FEATURE_KMSG_SYSLOG + +config BUSYBOX_CONFIG_FEATURE_KLOGD_KLOGCTL + bool "Use the klogctl() interface" + default BUSYBOX_DEFAULT_FEATURE_KLOGD_KLOGCTL + depends on BUSYBOX_CONFIG_KLOGD + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + The klogd applet supports two interfaces for reading + kernel messages. Linux provides the klogctl() interface + which allows reading messages from the kernel ring buffer + independently from the file system. + + If you answer 'N' here, klogd will use the more portable + approach of reading them from /proc or a device node. + However, this method requires the file to be available. + + If in doubt, say 'Y'. + +config BUSYBOX_CONFIG_LOGGER + bool "logger" + default BUSYBOX_DEFAULT_LOGGER + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + The logger utility allows you to send arbitrary text + messages to the system log (i.e. the 'syslogd' utility) so + they can be logged. This is generally used to help locate + problems that occur within programs and scripts. + +endmenu diff --git a/package/utils/busybox/config/util-linux/Config.in b/package/utils/busybox/config/util-linux/Config.in new file mode 100644 index 0000000..8d1464d --- /dev/null +++ b/package/utils/busybox/config/util-linux/Config.in @@ -0,0 +1,792 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +menu "Linux System Utilities" + +config BUSYBOX_CONFIG_BLOCKDEV + bool "blockdev" + default BUSYBOX_DEFAULT_BLOCKDEV + help + Performs some ioctls with block devices. +config BUSYBOX_CONFIG_FATATTR + bool "fatattr" + default BUSYBOX_DEFAULT_FATATTR + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + fatattr lists or changes the file attributes on a fat file system. +config BUSYBOX_CONFIG_FSTRIM + bool "fstrim" + default BUSYBOX_DEFAULT_FSTRIM + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Discard unused blocks on a mounted filesystem. +config BUSYBOX_CONFIG_MDEV + bool "mdev" + default BUSYBOX_DEFAULT_MDEV + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + mdev is a mini-udev implementation for dynamically creating device + nodes in the /dev directory. + + For more information, please see docs/mdev.txt + +config BUSYBOX_CONFIG_FEATURE_MDEV_CONF + bool "Support /etc/mdev.conf" + default BUSYBOX_DEFAULT_FEATURE_MDEV_CONF + depends on BUSYBOX_CONFIG_MDEV + help + Add support for the mdev config file to control ownership and + permissions of the device nodes. + + For more information, please see docs/mdev.txt + +config BUSYBOX_CONFIG_FEATURE_MDEV_RENAME + bool "Support subdirs/symlinks" + default BUSYBOX_DEFAULT_FEATURE_MDEV_RENAME + depends on BUSYBOX_CONFIG_FEATURE_MDEV_CONF + help + Add support for renaming devices and creating symlinks. + + For more information, please see docs/mdev.txt + +config BUSYBOX_CONFIG_FEATURE_MDEV_RENAME_REGEXP + bool "Support regular expressions substitutions when renaming device" + default BUSYBOX_DEFAULT_FEATURE_MDEV_RENAME_REGEXP + depends on BUSYBOX_CONFIG_FEATURE_MDEV_RENAME + help + Add support for regular expressions substitutions when renaming + device. + +config BUSYBOX_CONFIG_FEATURE_MDEV_EXEC + bool "Support command execution at device addition/removal" + default BUSYBOX_DEFAULT_FEATURE_MDEV_EXEC + depends on BUSYBOX_CONFIG_FEATURE_MDEV_CONF + help + This adds support for an optional field to /etc/mdev.conf for + executing commands when devices are created/removed. + + For more information, please see docs/mdev.txt + +config BUSYBOX_CONFIG_FEATURE_MDEV_LOAD_FIRMWARE + bool "Support loading of firmwares" + default BUSYBOX_DEFAULT_FEATURE_MDEV_LOAD_FIRMWARE + depends on BUSYBOX_CONFIG_MDEV + help + Some devices need to load firmware before they can be usable. + + These devices will request userspace look up the files in + /lib/firmware/ and if it exists, send it to the kernel for + loading into the hardware. +config BUSYBOX_CONFIG_REV + bool "rev" + default BUSYBOX_DEFAULT_REV + help + Reverse lines of a file or files. + +config BUSYBOX_CONFIG_ACPID + bool "acpid" + default BUSYBOX_DEFAULT_ACPID + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + acpid listens to ACPI events coming either in textual form from + /proc/acpi/event (though it is marked deprecated it is still widely + used and _is_ a standard) or in binary form from specified evdevs + (just use /dev/input/event*). + + It parses the event to retrieve ACTION and a possible PARAMETER. + It then spawns /etc/acpi/<ACTION>[/<PARAMETER>] either via run-parts + (if the resulting path is a directory) or directly as an executable. + + N.B. acpid relies on run-parts so have the latter installed. + +config BUSYBOX_CONFIG_FEATURE_ACPID_COMPAT + bool "Accept and ignore redundant options" + default BUSYBOX_DEFAULT_FEATURE_ACPID_COMPAT + depends on BUSYBOX_CONFIG_ACPID + help + Accept and ignore compatibility options -g -m -s -S -v. + +config BUSYBOX_CONFIG_BLKID + bool "blkid" + default BUSYBOX_DEFAULT_BLKID + select BUSYBOX_CONFIG_PLATFORM_LINUX + select BUSYBOX_CONFIG_VOLUMEID + help + Lists labels and UUIDs of all filesystems. + WARNING: + With all submodules selected, it will add ~8k to busybox. + +config BUSYBOX_CONFIG_FEATURE_BLKID_TYPE + bool "Print filesystem type" + default BUSYBOX_DEFAULT_FEATURE_BLKID_TYPE + depends on BUSYBOX_CONFIG_BLKID + help + Show TYPE="filesystem type" + +config BUSYBOX_CONFIG_DMESG + bool "dmesg" + default BUSYBOX_DEFAULT_DMESG + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + dmesg is used to examine or control the kernel ring buffer. When the + Linux kernel prints messages to the system log, they are stored in + the kernel ring buffer. You can use dmesg to print the kernel's ring + buffer, clear the kernel ring buffer, change the size of the kernel + ring buffer, and change the priority level at which kernel messages + are also logged to the system console. Enable this option if you + wish to enable the 'dmesg' utility. + +config BUSYBOX_CONFIG_FEATURE_DMESG_PRETTY + bool "Pretty dmesg output" + default BUSYBOX_DEFAULT_FEATURE_DMESG_PRETTY + depends on BUSYBOX_CONFIG_DMESG + help + If you wish to scrub the syslog level from the output, say 'Y' here. + The syslog level is a string prefixed to every line with the form + "<#>". + + With this option you will see: + # dmesg + Linux version 2.6.17.4 ..... + BIOS-provided physical RAM map: + BIOS-e820: 0000000000000000 - 000000000009f000 (usable) + + Without this option you will see: + # dmesg + <5>Linux version 2.6.17.4 ..... + <6>BIOS-provided physical RAM map: + <6> BIOS-e820: 0000000000000000 - 000000000009f000 (usable) + +config BUSYBOX_CONFIG_FBSET + bool "fbset" + default BUSYBOX_DEFAULT_FBSET + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + fbset is used to show or change the settings of a Linux frame buffer + device. The frame buffer device provides a simple and unique + interface to access a graphics display. Enable this option + if you wish to enable the 'fbset' utility. + +config BUSYBOX_CONFIG_FEATURE_FBSET_FANCY + bool "Turn on extra fbset options" + default BUSYBOX_DEFAULT_FEATURE_FBSET_FANCY + depends on BUSYBOX_CONFIG_FBSET + help + This option enables extended fbset options, allowing one to set the + framebuffer size, color depth, etc. interface to access a graphics + display. Enable this option if you wish to enable extended fbset + options. + +config BUSYBOX_CONFIG_FEATURE_FBSET_READMODE + bool "Turn on fbset readmode support" + default BUSYBOX_DEFAULT_FEATURE_FBSET_READMODE + depends on BUSYBOX_CONFIG_FBSET + help + This option allows fbset to read the video mode database stored by + default BUSYBOX_DEFAULT_FEATURE_FBSET_READMODE /etc/fb.modes, which can be used to set frame buffer + device to pre-defined video modes. + +config BUSYBOX_CONFIG_FDFLUSH + bool "fdflush" + default BUSYBOX_DEFAULT_FDFLUSH + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + fdflush is only needed when changing media on slightly-broken + removable media drives. It is used to make Linux believe that a + hardware disk-change switch has been actuated, which causes Linux to + forget anything it has cached from the previous media. If you have + such a slightly-broken drive, you will need to run fdflush every time + you change a disk. Most people have working hardware and can safely + leave this disabled. + +config BUSYBOX_CONFIG_FDFORMAT + bool "fdformat" + default BUSYBOX_DEFAULT_FDFORMAT + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + fdformat is used to low-level format a floppy disk. + +config BUSYBOX_CONFIG_FDISK + bool "fdisk" + default BUSYBOX_DEFAULT_FDISK + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + The fdisk utility is used to divide hard disks into one or more + logical disks, which are generally called partitions. This utility + can be used to list and edit the set of partitions or BSD style + 'disk slices' that are defined on a hard drive. + +config BUSYBOX_CONFIG_FDISK_SUPPORT_LARGE_DISKS + bool "Support over 4GB disks" + default BUSYBOX_DEFAULT_FDISK_SUPPORT_LARGE_DISKS + depends on BUSYBOX_CONFIG_FDISK + depends on !BUSYBOX_CONFIG_LFS # with LFS no special code is needed + help + Enable this option to support large disks > 4GB. + +config BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE + bool "Write support" + default BUSYBOX_DEFAULT_FEATURE_FDISK_WRITABLE + depends on BUSYBOX_CONFIG_FDISK + help + Enabling this option allows you to create or change a partition table + and write those changes out to disk. If you leave this option + disabled, you will only be able to view the partition table. + +config BUSYBOX_CONFIG_FEATURE_AIX_LABEL + bool "Support AIX disklabels" + default BUSYBOX_DEFAULT_FEATURE_AIX_LABEL + depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE + help + Enabling this option allows you to create or change AIX disklabels. + Most people can safely leave this option disabled. + +config BUSYBOX_CONFIG_FEATURE_SGI_LABEL + bool "Support SGI disklabels" + default BUSYBOX_DEFAULT_FEATURE_SGI_LABEL + depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE + help + Enabling this option allows you to create or change SGI disklabels. + Most people can safely leave this option disabled. + +config BUSYBOX_CONFIG_FEATURE_SUN_LABEL + bool "Support SUN disklabels" + default BUSYBOX_DEFAULT_FEATURE_SUN_LABEL + depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE + help + Enabling this option allows you to create or change SUN disklabels. + Most people can safely leave this option disabled. + +config BUSYBOX_CONFIG_FEATURE_OSF_LABEL + bool "Support BSD disklabels" + default BUSYBOX_DEFAULT_FEATURE_OSF_LABEL + depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE + help + Enabling this option allows you to create or change BSD disklabels + and define and edit BSD disk slices. + +config BUSYBOX_CONFIG_FEATURE_GPT_LABEL + bool "Support GPT disklabels" + default BUSYBOX_DEFAULT_FEATURE_GPT_LABEL + depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE + help + Enabling this option allows you to view GUID Partition Table + disklabels. + +config BUSYBOX_CONFIG_FEATURE_FDISK_ADVANCED + bool "Support expert mode" + default BUSYBOX_DEFAULT_FEATURE_FDISK_ADVANCED + depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE + help + Enabling this option allows you to do terribly unsafe things like + define arbitrary drive geometry, move the beginning of data in a + partition, and similarly evil things. Unless you have a very good + reason you would be wise to leave this disabled. + +config BUSYBOX_CONFIG_FINDFS + bool "findfs" + default BUSYBOX_DEFAULT_FINDFS + select BUSYBOX_CONFIG_PLATFORM_LINUX + select BUSYBOX_CONFIG_VOLUMEID + help + Prints the name of a filesystem with given label or UUID. + WARNING: + With all submodules selected, it will add ~8k to busybox. + +config BUSYBOX_CONFIG_FLOCK + bool "flock" + default BUSYBOX_DEFAULT_FLOCK + help + Manage locks from shell scripts + +config BUSYBOX_CONFIG_FREERAMDISK + bool "freeramdisk" + default BUSYBOX_DEFAULT_FREERAMDISK + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Linux allows you to create ramdisks. This utility allows you to + delete them and completely free all memory that was used for the + ramdisk. For example, if you boot Linux into a ramdisk and later + pivot_root, you may want to free the memory that is allocated to the + ramdisk. If you have no use for freeing memory from a ramdisk, leave + this disabled. + +config BUSYBOX_CONFIG_FSCK_MINIX + bool "fsck_minix" + default BUSYBOX_DEFAULT_FSCK_MINIX + help + The minix filesystem is a nice, small, compact, read-write filesystem + with little overhead. It is not a journaling filesystem however and + can experience corruption if it is not properly unmounted or if the + power goes off in the middle of a write. This utility allows you to + check for and attempt to repair any corruption that occurs to a minix + filesystem. + +config BUSYBOX_CONFIG_MKFS_EXT2 + bool "mkfs_ext2" + default BUSYBOX_DEFAULT_MKFS_EXT2 + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Utility to create EXT2 filesystems. + +config BUSYBOX_CONFIG_MKFS_MINIX + bool "mkfs_minix" + default BUSYBOX_DEFAULT_MKFS_MINIX + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + The minix filesystem is a nice, small, compact, read-write filesystem + with little overhead. If you wish to be able to create minix + filesystems this utility will do the job for you. + +config BUSYBOX_CONFIG_FEATURE_MINIX2 + bool "Support Minix fs v2 (fsck_minix/mkfs_minix)" + default BUSYBOX_DEFAULT_FEATURE_MINIX2 + depends on BUSYBOX_CONFIG_FSCK_MINIX || BUSYBOX_CONFIG_MKFS_MINIX + help + If you wish to be able to create version 2 minix filesystems, enable + this. If you enabled 'mkfs_minix' then you almost certainly want to + be using the version 2 filesystem support. + +config BUSYBOX_CONFIG_MKFS_REISER + bool "mkfs_reiser" + default BUSYBOX_DEFAULT_MKFS_REISER + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Utility to create ReiserFS filesystems. + Note: this applet needs a lot of testing and polishing. + +config BUSYBOX_CONFIG_MKFS_VFAT + bool "mkfs_vfat" + default BUSYBOX_DEFAULT_MKFS_VFAT + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Utility to create FAT32 filesystems. + +config BUSYBOX_CONFIG_GETOPT + bool "getopt" + default BUSYBOX_DEFAULT_GETOPT + help + The getopt utility is used to break up (parse) options in command + lines to make it easy to write complex shell scripts that also check + for legal (and illegal) options. If you want to write horribly + complex shell scripts, or use some horribly complex shell script + written by others, this utility may be for you. Most people will + wisely leave this disabled. + +config BUSYBOX_CONFIG_FEATURE_GETOPT_LONG + bool "Support option -l" + default BUSYBOX_DEFAULT_FEATURE_GETOPT_LONG if BUSYBOX_CONFIG_LONG_OPTS + depends on BUSYBOX_CONFIG_GETOPT + help + Enable support for long options (option -l). + +config BUSYBOX_CONFIG_HEXDUMP + bool "hexdump" + default BUSYBOX_DEFAULT_HEXDUMP + help + The hexdump utility is used to display binary data in a readable + way that is comparable to the output from most hex editors. + +config BUSYBOX_CONFIG_FEATURE_HEXDUMP_REVERSE + bool "Support -R, reverse of 'hexdump -Cv'" + default BUSYBOX_DEFAULT_FEATURE_HEXDUMP_REVERSE + depends on BUSYBOX_CONFIG_HEXDUMP + help + The hexdump utility is used to display binary data in an ascii + readable way. This option creates binary data from an ascii input. + NB: this option is non-standard. It's unwise to use it in scripts + aimed to be portable. + +config BUSYBOX_CONFIG_HD + bool "hd" + default BUSYBOX_DEFAULT_HD + depends on BUSYBOX_CONFIG_HEXDUMP + help + hd is an alias to hexdump -C. + +config BUSYBOX_CONFIG_HWCLOCK + bool "hwclock" + default BUSYBOX_DEFAULT_HWCLOCK + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + The hwclock utility is used to read and set the hardware clock + on a system. This is primarily used to set the current time on + shutdown in the hardware clock, so the hardware will keep the + correct time when Linux is _not_ running. + +config BUSYBOX_CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS + bool "Support long options (--hctosys,...)" + default BUSYBOX_DEFAULT_FEATURE_HWCLOCK_LONG_OPTIONS + depends on BUSYBOX_CONFIG_HWCLOCK && BUSYBOX_CONFIG_LONG_OPTS + help + By default, the hwclock utility only uses short options. If you + are overly fond of its long options, such as --hctosys, --utc, etc) + then enable this option. + +config BUSYBOX_CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS + bool "Use FHS /var/lib/hwclock/adjtime" + default BUSYBOX_DEFAULT_FEATURE_HWCLOCK_ADJTIME_FHS # util-linux-ng in Fedora 13 still uses /etc/adjtime + depends on BUSYBOX_CONFIG_HWCLOCK + help + Starting with FHS 2.3, the adjtime state file is supposed to exist + at /var/lib/hwclock/adjtime instead of /etc/adjtime. If you wish + to use the FHS behavior, answer Y here, otherwise answer N for the + classic /etc/adjtime path. + + pathname.com/fhs/pub/fhs-2.3.html#VARLIBHWCLOCKSTATEDIRECTORYFORHWCLO + +config BUSYBOX_CONFIG_IPCRM + bool "ipcrm" + default BUSYBOX_DEFAULT_IPCRM + help + The ipcrm utility allows the removal of System V interprocess + communication (IPC) objects and the associated data structures + from the system. + +config BUSYBOX_CONFIG_IPCS + bool "ipcs" + default BUSYBOX_DEFAULT_IPCS + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + The ipcs utility is used to provide information on the currently + allocated System V interprocess (IPC) objects in the system. + +config BUSYBOX_CONFIG_LOSETUP + bool "losetup" + default BUSYBOX_DEFAULT_LOSETUP + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + losetup is used to associate or detach a loop device with a regular + file or block device, and to query the status of a loop device. This + version does not currently support enabling data encryption. + +config BUSYBOX_CONFIG_LSPCI + bool "lspci" + default BUSYBOX_DEFAULT_LSPCI + #select PLATFORM_LINUX + help + lspci is a utility for displaying information about PCI buses in the + system and devices connected to them. + + This version uses sysfs (/sys/bus/pci/devices) only. + +config BUSYBOX_CONFIG_LSUSB + bool "lsusb" + default BUSYBOX_DEFAULT_LSUSB + #select PLATFORM_LINUX + help + lsusb is a utility for displaying information about USB buses in the + system and devices connected to them. + + This version uses sysfs (/sys/bus/usb/devices) only. + +config BUSYBOX_CONFIG_MKSWAP + bool "mkswap" + default BUSYBOX_DEFAULT_MKSWAP + help + The mkswap utility is used to configure a file or disk partition as + Linux swap space. This allows Linux to use the entire file or + partition as if it were additional RAM, which can greatly increase + the capability of low-memory machines. This additional memory is + much slower than real RAM, but can be very helpful at preventing your + applications being killed by the Linux out of memory (OOM) killer. + Once you have created swap space using 'mkswap' you need to enable + the swap space using the 'swapon' utility. + +config BUSYBOX_CONFIG_FEATURE_MKSWAP_UUID + bool "UUID support" + default BUSYBOX_DEFAULT_FEATURE_MKSWAP_UUID + depends on BUSYBOX_CONFIG_MKSWAP + help + Generate swap spaces with universally unique identifiers. + +config BUSYBOX_CONFIG_MORE + bool "more" + default BUSYBOX_DEFAULT_MORE + help + more is a simple utility which allows you to read text one screen + sized page at a time. If you want to read text that is larger than + the screen, and you are using anything faster than a 300 baud modem, + you will probably find this utility very helpful. If you don't have + any need to reading text files, you can leave this disabled. + +config BUSYBOX_CONFIG_MOUNT + bool "mount" + default BUSYBOX_DEFAULT_MOUNT + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + All files and filesystems in Unix are arranged into one big directory + tree. The 'mount' utility is used to graft a filesystem onto a + particular part of the tree. A filesystem can either live on a block + device, or it can be accessible over the network, as is the case with + NFS filesystems. Most people using BusyBox will also want to enable + the 'mount' utility. + +config BUSYBOX_CONFIG_FEATURE_MOUNT_FAKE + bool "Support option -f" + default BUSYBOX_DEFAULT_FEATURE_MOUNT_FAKE + depends on BUSYBOX_CONFIG_MOUNT + help + Enable support for faking a file system mount. + +config BUSYBOX_CONFIG_FEATURE_MOUNT_VERBOSE + bool "Support option -v" + default BUSYBOX_DEFAULT_FEATURE_MOUNT_VERBOSE + depends on BUSYBOX_CONFIG_MOUNT + help + Enable multi-level -v[vv...] verbose messages. Useful if you + debug mount problems and want to see what is exactly passed + to the kernel. + +config BUSYBOX_CONFIG_FEATURE_MOUNT_HELPERS + bool "Support mount helpers" + default BUSYBOX_DEFAULT_FEATURE_MOUNT_HELPERS + depends on BUSYBOX_CONFIG_MOUNT + help + Enable mounting of virtual file systems via external helpers. + E.g. "mount obexfs#-b00.11.22.33.44.55 /mnt" will in effect call + "obexfs -b00.11.22.33.44.55 /mnt" + Also "mount -t sometype [-o opts] fs /mnt" will try + "sometype [-o opts] fs /mnt" if simple mount syscall fails. + The idea is to use such virtual filesystems in /etc/fstab. + +config BUSYBOX_CONFIG_FEATURE_MOUNT_LABEL + bool "Support specifying devices by label or UUID" + default BUSYBOX_DEFAULT_FEATURE_MOUNT_LABEL + depends on BUSYBOX_CONFIG_MOUNT + select BUSYBOX_CONFIG_VOLUMEID + help + This allows for specifying a device by label or uuid, rather than by + name. This feature utilizes the same functionality as blkid/findfs. + This also enables label or uuid support for swapon. + +config BUSYBOX_CONFIG_FEATURE_MOUNT_NFS + bool "Support mounting NFS file systems on Linux < 2.6.23" + default BUSYBOX_DEFAULT_FEATURE_MOUNT_NFS + depends on BUSYBOX_CONFIG_MOUNT + select BUSYBOX_CONFIG_FEATURE_HAVE_RPC + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + Enable mounting of NFS file systems on Linux kernels prior + to version 2.6.23. Note that in this case mounting of NFS + over IPv6 will not be possible. + + Note that this option links in RPC support from libc, + which is rather large (~10 kbytes on uclibc). + +config BUSYBOX_CONFIG_FEATURE_MOUNT_CIFS + bool "Support mounting CIFS/SMB file systems" + default BUSYBOX_DEFAULT_FEATURE_MOUNT_CIFS + depends on BUSYBOX_CONFIG_MOUNT + help + Enable support for samba mounts. + +config BUSYBOX_CONFIG_FEATURE_MOUNT_FLAGS + depends on BUSYBOX_CONFIG_MOUNT + bool "Support lots of -o flags in mount" + default BUSYBOX_DEFAULT_FEATURE_MOUNT_FLAGS + help + Without this, mount only supports ro/rw/remount. With this, it + supports nosuid, suid, dev, nodev, exec, noexec, sync, async, atime, + noatime, diratime, nodiratime, loud, bind, move, shared, slave, + private, unbindable, rshared, rslave, rprivate, and runbindable. + +config BUSYBOX_CONFIG_FEATURE_MOUNT_FSTAB + depends on BUSYBOX_CONFIG_MOUNT + bool "Support /etc/fstab and -a" + default BUSYBOX_DEFAULT_FEATURE_MOUNT_FSTAB + help + Support mount all and looking for files in /etc/fstab. + +config BUSYBOX_CONFIG_PIVOT_ROOT + bool "pivot_root" + default BUSYBOX_DEFAULT_PIVOT_ROOT + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + The pivot_root utility swaps the mount points for the root filesystem + with some other mounted filesystem. This allows you to do all sorts + of wild and crazy things with your Linux system and is far more + powerful than 'chroot'. + + Note: This is for initrd in linux 2.4. Under initramfs (introduced + in linux 2.6) use switch_root instead. + +config BUSYBOX_CONFIG_RDATE + bool "rdate" + default BUSYBOX_DEFAULT_RDATE + help + The rdate utility allows you to synchronize the date and time of your + system clock with the date and time of a remote networked system using + the RFC868 protocol, which is built into the inetd daemon on most + systems. + +config BUSYBOX_CONFIG_RDEV + bool "rdev" + default BUSYBOX_DEFAULT_RDEV + help + Print the device node associated with the filesystem mounted at '/'. + +config BUSYBOX_CONFIG_READPROFILE + bool "readprofile" + default BUSYBOX_DEFAULT_READPROFILE + #select PLATFORM_LINUX + help + This allows you to parse /proc/profile for basic profiling. + +config BUSYBOX_CONFIG_RTCWAKE + bool "rtcwake" + default BUSYBOX_DEFAULT_RTCWAKE + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Enter a system sleep state until specified wakeup time. + +config BUSYBOX_CONFIG_SCRIPT + bool "script" + default BUSYBOX_DEFAULT_SCRIPT + help + The script makes typescript of terminal session. + +config BUSYBOX_CONFIG_SCRIPTREPLAY + bool "scriptreplay" + default BUSYBOX_DEFAULT_SCRIPTREPLAY + help + This program replays a typescript, using timing information + given by script -t. + +config BUSYBOX_CONFIG_SETARCH + bool "setarch" + default BUSYBOX_DEFAULT_SETARCH + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + The linux32 utility is used to create a 32bit environment for the + specified program (usually a shell). It only makes sense to have + this util on a system that supports both 64bit and 32bit userland + (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...). + +config BUSYBOX_CONFIG_SWAPONOFF + bool "swaponoff" + default BUSYBOX_DEFAULT_SWAPONOFF + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This option enables both the 'swapon' and the 'swapoff' utilities. + Once you have created some swap space using 'mkswap', you also need + to enable your swap space with the 'swapon' utility. The 'swapoff' + utility is used, typically at system shutdown, to disable any swap + space. If you are not using any swap space, you can leave this + option disabled. + +config BUSYBOX_CONFIG_FEATURE_SWAPON_DISCARD + bool "Support discard option -d" + default BUSYBOX_DEFAULT_FEATURE_SWAPON_DISCARD + depends on BUSYBOX_CONFIG_SWAPONOFF + help + Enable support for discarding swap area blocks at swapon and/or as + the kernel frees them. This option enables both the -d option on + 'swapon' and the 'discard' option for swap entries in /etc/fstab. + +config BUSYBOX_CONFIG_FEATURE_SWAPON_PRI + bool "Support priority option -p" + default BUSYBOX_DEFAULT_FEATURE_SWAPON_PRI + depends on BUSYBOX_CONFIG_SWAPONOFF + help + Enable support for setting swap device priority in swapon. + +config BUSYBOX_CONFIG_SWITCH_ROOT + bool "switch_root" + default BUSYBOX_DEFAULT_SWITCH_ROOT + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + The switch_root utility is used from initramfs to select a new + root device. Under initramfs, you have to use this instead of + pivot_root. (Stop reading here if you don't care why.) + + Booting with initramfs extracts a gzipped cpio archive into rootfs + (which is a variant of ramfs/tmpfs). Because rootfs can't be moved + or unmounted*, pivot_root will not work from initramfs. Instead, + switch_root deletes everything out of rootfs (including itself), + does a mount --move that overmounts rootfs with the new root, and + then execs the specified init program. + + * Because the Linux kernel uses rootfs internally as the starting + and ending point for searching through the kernel's doubly linked + list of active mount points. That's why. + +config BUSYBOX_CONFIG_UMOUNT + bool "umount" + default BUSYBOX_DEFAULT_UMOUNT + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + When you want to remove a mounted filesystem from its current mount + point, for example when you are shutting down the system, the + 'umount' utility is the tool to use. If you enabled the 'mount' + utility, you almost certainly also want to enable 'umount'. + +config BUSYBOX_CONFIG_FEATURE_UMOUNT_ALL + bool "Support option -a" + default BUSYBOX_DEFAULT_FEATURE_UMOUNT_ALL + depends on BUSYBOX_CONFIG_UMOUNT + help + Support -a option to unmount all currently mounted filesystems. + +comment "Common options for mount/umount" + depends on BUSYBOX_CONFIG_MOUNT || BUSYBOX_CONFIG_UMOUNT + +config BUSYBOX_CONFIG_FEATURE_MOUNT_LOOP + bool "Support loopback mounts" + default BUSYBOX_DEFAULT_FEATURE_MOUNT_LOOP + depends on BUSYBOX_CONFIG_MOUNT || BUSYBOX_CONFIG_UMOUNT + help + Enabling this feature allows automatic mounting of files (containing + filesystem images) via the linux kernel's loopback devices. + The mount command will detect you are trying to mount a file instead + of a block device, and transparently associate the file with a + loopback device. The umount command will also free that loopback + device. + + You can still use the 'losetup' utility (to manually associate files + with loop devices) if you need to do something advanced, such as + specify an offset or cryptographic options to the loopback device. + (If you don't want umount to free the loop device, use "umount -D".) + +config BUSYBOX_CONFIG_FEATURE_MOUNT_LOOP_CREATE + bool "Create new loopback devices if needed" + default BUSYBOX_DEFAULT_FEATURE_MOUNT_LOOP_CREATE + depends on BUSYBOX_CONFIG_FEATURE_MOUNT_LOOP + help + Linux kernels >= 2.6.24 support unlimited loopback devices. They are + allocated for use when trying to use a loop device. The loop device + must however exist. + + This feature lets mount to try to create next /dev/loopN device + if it does not find a free one. + +config BUSYBOX_CONFIG_FEATURE_MTAB_SUPPORT + bool "Support for the old /etc/mtab file" + default BUSYBOX_DEFAULT_FEATURE_MTAB_SUPPORT + depends on BUSYBOX_CONFIG_MOUNT || BUSYBOX_CONFIG_UMOUNT + select BUSYBOX_CONFIG_FEATURE_MOUNT_FAKE + help + Historically, Unix systems kept track of the currently mounted + partitions in the file "/etc/mtab". These days, the kernel exports + the list of currently mounted partitions in "/proc/mounts", rendering + the old mtab file obsolete. (In modern systems, /etc/mtab should be + a symlink to /proc/mounts.) + + The only reason to have mount maintain an /etc/mtab file itself is if + your stripped-down embedded system does not have a /proc directory. + If you must use this, keep in mind it's inherently brittle (for + example a mount under chroot won't update it), can't handle modern + features like separate per-process filesystem namespaces, requires + that your /etc directory be writable, tends to get easily confused + by --bind or --move mounts, won't update if you rename a directory + that contains a mount point, and so on. (In brief: avoid.) + + About the only reason to use this is if you've removed /proc from + your kernel. + +source package/utils/busybox/config/util-linux/volume_id/Config.in + +endmenu diff --git a/package/utils/busybox/config/util-linux/volume_id/Config.in b/package/utils/busybox/config/util-linux/volume_id/Config.in new file mode 100644 index 0000000..306550b --- /dev/null +++ b/package/utils/busybox/config/util-linux/volume_id/Config.in @@ -0,0 +1,304 @@ +# DO NOT EDIT. This file is generated from Config.src +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +config BUSYBOX_CONFIG_VOLUMEID + bool #No description makes it a hidden option + default BUSYBOX_DEFAULT_VOLUMEID + +menu "Filesystem/Volume identification" + depends on BUSYBOX_CONFIG_VOLUMEID + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_BTRFS + bool "btrfs filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_BTRFS + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_CRAMFS + bool "cramfs filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_CRAMFS + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_EXFAT + bool "exFAT filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EXFAT + depends on BUSYBOX_CONFIG_VOLUMEID + help + exFAT (extended FAT) is a proprietary file system designed especially + for flash drives. It has many features from NTFS, but with less + overhead. exFAT is used on most SDXC cards for consumer electronics. + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_EXT + bool "Ext filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EXT + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_F2FS + bool "f2fs filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_F2FS + depends on BUSYBOX_CONFIG_VOLUMEID + help + F2FS (aka Flash-Friendly File System) is a log-structured file system, + which is adapted to newer forms of storage. F2FS also remedies some + known issues of the older log structured file systems, such as high + cleaning overhead. + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_FAT + bool "fat filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_FAT + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_HFS + bool "hfs filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_HFS + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_ISO9660 + bool "iso9660 filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_ISO9660 + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_JFS + bool "jfs filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_JFS + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_LINUXRAID + bool "linuxraid" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LINUXRAID + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_LINUXSWAP + bool "linux swap filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LINUXSWAP + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_LUKS + bool "luks filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LUKS + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_NILFS + bool "nilfs filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_NILFS + depends on BUSYBOX_CONFIG_VOLUMEID + help + NILFS is a New Implementation of a Log-Structured File System (LFS) + that supports continuous snapshots. This provides features like + versioning of the entire filesystem, restoration of files that + were deleted a few minutes ago. NILFS keeps consistency like + conventional LFS, so it provides quick recovery after system crashes. + + The possible use of NILFS includes versioning, tamper detection, + SOX compliance logging, and so forth. It can serve as an alternative + filesystem for Linux desktop environment, or as a basis of advanced + storage appliances. + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_NTFS + bool "ntfs filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_NTFS + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_OCFS2 + bool "ocfs2 filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_OCFS2 + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_REISERFS + bool "Reiser filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_REISERFS + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_ROMFS + bool "romfs filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_ROMFS + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_SQUASHFS + bool "SquashFS filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_SQUASHFS + depends on BUSYBOX_CONFIG_VOLUMEID && BUSYBOX_CONFIG_FEATURE_BLKID_TYPE + help + Squashfs is a compressed read-only filesystem for Linux. Squashfs is + intended for general read-only filesystem use and in constrained block + device/memory systems (e.g. embedded systems) where low overhead is + needed. + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_SYSV + bool "sysv filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_SYSV + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_UDF + bool "udf filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_UDF + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +### config FEATURE_VOLUMEID_HIGHPOINTRAID +### bool "highpoint raid" +### default y +### depends on VOLUMEID +### help +### TODO + + +### config FEATURE_VOLUMEID_HPFS +### bool "hpfs filesystem" +### default y +### depends on VOLUMEID +### help +### TODO + + +### config FEATURE_VOLUMEID_ISWRAID +### bool "intel raid" +### default y +### depends on VOLUMEID +### help +### TODO + + +### config FEATURE_VOLUMEID_LSIRAID +### bool "lsi raid" +### default y +### depends on VOLUMEID +### help +### TODO + + +### config FEATURE_VOLUMEID_LVM +### bool "lvm" +### default y +### depends on VOLUMEID +### help +### TODO + + +### config FEATURE_VOLUMEID_MAC +### bool "mac filesystem" +### default y +### depends on VOLUMEID +### help +### TODO + + +### config FEATURE_VOLUMEID_MINIX +### bool "minix filesystem" +### default y +### depends on VOLUMEID +### help +### TODO + + +### config FEATURE_VOLUMEID_MSDOS +### bool "msdos filesystem" +### default y +### depends on VOLUMEID +### help +### TODO + + +### config FEATURE_VOLUMEID_NVIDIARAID +### bool "nvidia raid" +### default y +### depends on VOLUMEID +### help +### TODO + + +### config FEATURE_VOLUMEID_PROMISERAID +### bool "promise raid" +### default y +### depends on VOLUMEID +### help +### TODO + + +### config FEATURE_VOLUMEID_SILICONRAID +### bool "silicon raid" +### default y +### depends on VOLUMEID +### help +### TODO + + +### config FEATURE_VOLUMEID_UFS +### bool "ufs filesystem" +### default y +### depends on VOLUMEID +### help +### TODO + + +### config FEATURE_VOLUMEID_VIARAID +### bool "via raid" +### default y +### depends on VOLUMEID +### help +### TODO + + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_XFS + bool "xfs filesystem" + default BUSYBOX_DEFAULT_FEATURE_VOLUMEID_XFS + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + + +endmenu diff --git a/package/utils/busybox/convert_defaults.pl b/package/utils/busybox/convert_defaults.pl new file mode 100755 index 0000000..dada6ef --- /dev/null +++ b/package/utils/busybox/convert_defaults.pl @@ -0,0 +1,13 @@ +#!/usr/bin/env perl + +while (<>) { + /^(# )?CONFIG_([^=]+)(=(.+)| is not set)/ and do { + my $default = $4; + $1 and $default = "n"; + my $name = $2; + my $type = "bool"; + $default =~ /^\"/ and $type = "string"; + $default =~ /^\d/ and $type = "int"; + print "config BUSYBOX_DEFAULT_$name\n\t$type\n\tdefault $default\n"; + }; +} diff --git a/package/utils/busybox/convert_menuconfig.pl b/package/utils/busybox/convert_menuconfig.pl new file mode 100755 index 0000000..fd99349 --- /dev/null +++ b/package/utils/busybox/convert_menuconfig.pl @@ -0,0 +1,75 @@ +#!/usr/bin/perl +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +use strict; +my $PATH = $ARGV[0]; +($PATH and -d $PATH) or die 'invalid path'; + +my %config; + +open FIND, "find \"$PATH\" -name Config.in |"; +while (<FIND>) { + chomp; + my $input = $_; + s/^$PATH\///g; + s/sysdeps\/linux\///g; + my $output = $_; + print STDERR "$input => $output\n"; + $output =~ /^(.+)\/[^\/]+$/ and system("mkdir -p $1"); + + open INPUT, $input; + open OUTPUT, ">$output"; + my ($cur, $default_set, $line); + while ($line = <INPUT>) { + next if $line =~ /^\s*mainmenu/; + + # FIXME: make this dynamic + $line =~ s/default FEATURE_BUFFERS_USE_MALLOC/default FEATURE_BUFFERS_GO_ON_STACK/; + $line =~ s/default FEATURE_SH_IS_NONE/default FEATURE_SH_IS_ASH/; + + if ($line =~ /^\s*config\s*([\w_]+)/) { + $cur = $1; + undef $default_set; + } + if ($line =~ /^\s*(menu|choice|end|source)/) { + undef $cur; + undef $default_set; + } + $line =~ s/^(\s*source\s+)/$1package\/utils\/busybox\/config\//; + if ($line =~ /^(\s*range\s*)(\w+)(\s+)(\w+)\s*$/) { + my $prefix = $1; + my $r1 = $2; + my $r2 = $4; + $r1 =~ s/^([a-zA-Z]+)/BUSYBOX_CONFIG_$1/; + $r2 =~ s/^([a-zA-Z]+)/BUSYBOX_CONFIG_$1/; + $line = "$prefix$r1 $r2\n"; + } + + $line =~ s/^(\s*(prompt "[^"]+" if|config|depends|depends on|select|default|default \w if)\s+\!?)([A-Z_])/$1BUSYBOX_CONFIG_$3/g; + $line =~ s/(( \|\| | \&\& | \( )!?)([A-Z_])/$1BUSYBOX_CONFIG_$3/g; + $line =~ s/(\( ?!?)([A-Z_]+ (\|\||&&))/$1BUSYBOX_CONFIG_$2/g; + + if ($cur) { + ($cur eq 'LFS') and do { + $line =~ s/^(\s*(bool|tristate|string))\s*".+"$/$1/; + }; + if ($line =~ /^\s*default/) { + my $c; + $default_set = 1; + $c = "BUSYBOX_DEFAULT_$cur"; + + $line =~ s/^(\s*default\s*)(\w+|"[^"]*")(.*)/$1$c$3/; + } + } + + print OUTPUT $line; + } + close OUTPUT; + close INPUT; +} +close FIND; diff --git a/package/utils/busybox/files/cron b/package/utils/busybox/files/cron new file mode 100755 index 0000000..19ecc43 --- /dev/null +++ b/package/utils/busybox/files/cron @@ -0,0 +1,38 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006-2011 OpenWrt.org + +START=50 + +USE_PROCD=1 +PROG=/usr/sbin/crond + +validate_cron_section() { + uci_validate_section system system "${1}" \ + 'cronloglevel:uinteger' +} + +start_service () { + [ -z "$(ls /etc/crontabs/)" ] && return 1 + + loglevel=$(uci_get "system.@system[0].cronloglevel") + + [ -z "${loglevel}" ] || { + /sbin/validate_data uinteger "${loglevel}" 2>/dev/null + [ "$?" -eq 0 ] || { + echo "validation failed" + return 1 + } + } + + mkdir -p /var/spool/cron + ln -s /etc/crontabs /var/spool/cron/ 2>/dev/null + + procd_open_instance + procd_set_param command "$PROG" -f -c /etc/crontabs -l ${loglevel:-5} + procd_close_instance +} + +service_triggers() +{ + procd_add_validation validate_cron_section +} diff --git a/package/utils/busybox/files/ntpd-hotplug b/package/utils/busybox/files/ntpd-hotplug new file mode 100755 index 0000000..ddc1490 --- /dev/null +++ b/package/utils/busybox/files/ntpd-hotplug @@ -0,0 +1,3 @@ +#!/bin/sh +[ "$1" = stratum ] || exit 0 +ACTION="$1" /sbin/hotplug-call ntp diff --git a/package/utils/busybox/files/sysntpd b/package/utils/busybox/files/sysntpd new file mode 100755 index 0000000..f73bb83 --- /dev/null +++ b/package/utils/busybox/files/sysntpd @@ -0,0 +1,42 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2011 OpenWrt.org + +START=98 + +USE_PROCD=1 +PROG=/usr/sbin/ntpd +HOTPLUG_SCRIPT=/usr/sbin/ntpd-hotplug + +validate_ntp_section() { + uci_validate_section system timeserver "${1}" \ + 'server:list(host)' 'enabled:bool:1' 'enable_server:bool:0' +} + +start_service() { + local server enabled enable_server peer + + validate_ntp_section ntp || { + echo "validation failed" + return 1 + } + + [ $enabled = 0 ] && return + + [ -z "$server" ] && return + + procd_open_instance + procd_set_param command "$PROG" -n + [ "$enable_server" = "1" ] && procd_append_param command -l + [ -x "$HOTPLUG_SCRIPT" ] && procd_append_param command -S "$HOTPLUG_SCRIPT" + for peer in $server; do + procd_append_param command -p $peer + done + procd_set_param respawn + procd_close_instance +} + +service_triggers() +{ + procd_add_reload_trigger "system" + procd_add_validation validate_ntp_section +} diff --git a/package/utils/busybox/patches/001-resource_h_include.patch b/package/utils/busybox/patches/001-resource_h_include.patch new file mode 100644 index 0000000..5e2f172 --- /dev/null +++ b/package/utils/busybox/patches/001-resource_h_include.patch @@ -0,0 +1,10 @@ +--- a/include/libbb.h ++++ b/include/libbb.h +@@ -40,6 +40,7 @@ + #include <poll.h> + #include <sys/ioctl.h> + #include <sys/mman.h> ++#include <sys/resource.h> + #include <sys/socket.h> + #include <sys/stat.h> + #include <sys/time.h> diff --git a/package/utils/busybox/patches/100-trylink_bash.patch b/package/utils/busybox/patches/100-trylink_bash.patch new file mode 100644 index 0000000..f9571fc --- /dev/null +++ b/package/utils/busybox/patches/100-trylink_bash.patch @@ -0,0 +1,8 @@ +--- a/scripts/trylink ++++ b/scripts/trylink +@@ -1,4 +1,4 @@ +-#!/bin/sh ++#!/usr/bin/env bash + + debug=false + diff --git a/package/utils/busybox/patches/101-gen_build_files_bash.patch b/package/utils/busybox/patches/101-gen_build_files_bash.patch new file mode 100644 index 0000000..d258fb8 --- /dev/null +++ b/package/utils/busybox/patches/101-gen_build_files_bash.patch @@ -0,0 +1,8 @@ +--- a/scripts/gen_build_files.sh ++++ b/scripts/gen_build_files.sh +@@ -1,4 +1,4 @@ +-#!/bin/sh ++#!/usr/bin/env bash + + # Note: was using sed OPTS CMD -- FILES + # but users complain that many sed implementations diff --git a/package/utils/busybox/patches/102-trylink_mktemp_fix.patch b/package/utils/busybox/patches/102-trylink_mktemp_fix.patch new file mode 100644 index 0000000..ed1dcbb --- /dev/null +++ b/package/utils/busybox/patches/102-trylink_mktemp_fix.patch @@ -0,0 +1,20 @@ +--- a/scripts/trylink ++++ b/scripts/trylink +@@ -46,7 +46,7 @@ try() { + } + + check_cc() { +- local tempname="$(mktemp)" ++ local tempname="$(mktemp /tmp/tmp.XXXXXXXXXX)" + local r + echo "int main(int argc,char**argv){return argv?argc:0;}" >"$tempname".c + # Can use "-o /dev/null", but older gcc tend to *unlink it* on failure! :( +@@ -61,7 +61,7 @@ check_cc() { + } + + check_libc_is_glibc() { +- local tempname="$(mktemp)" ++ local tempname="$(mktemp /tmp/tmp.XXXXXXXXXX)" + local r + echo "\ + #include <stdlib.h> diff --git a/package/utils/busybox/patches/110-no_static_libgcc.patch b/package/utils/busybox/patches/110-no_static_libgcc.patch new file mode 100644 index 0000000..2148a09 --- /dev/null +++ b/package/utils/busybox/patches/110-no_static_libgcc.patch @@ -0,0 +1,11 @@ +--- a/Makefile.flags ++++ b/Makefile.flags +@@ -51,7 +51,7 @@ CFLAGS += $(call cc-option,-fno-builtin- + # -fno-guess-branch-probability: prohibit pseudo-random guessing + # of branch probabilities (hopefully makes bloatcheck more stable): + CFLAGS += $(call cc-option,-fno-guess-branch-probability,) +-CFLAGS += $(call cc-option,-funsigned-char -static-libgcc,) ++CFLAGS += $(call cc-option,-funsigned-char,) + CFLAGS += $(call cc-option,-falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1,) + # Defeat .eh_frame bloat (gcc 4.6.3 x86-32 defconfig: 20% smaller busybox binary): + CFLAGS += $(call cc-option,-fno-unwind-tables,) diff --git a/package/utils/busybox/patches/120-remove_uclibc_rpc_check.patch b/package/utils/busybox/patches/120-remove_uclibc_rpc_check.patch new file mode 100644 index 0000000..5499efd --- /dev/null +++ b/package/utils/busybox/patches/120-remove_uclibc_rpc_check.patch @@ -0,0 +1,12 @@ +--- a/util-linux/mount.c ++++ b/util-linux/mount.c +@@ -236,9 +236,6 @@ + #if ENABLE_FEATURE_MOUNT_NFS + /* This is just a warning of a common mistake. Possibly this should be a + * uclibc faq entry rather than in busybox... */ +-# if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__) +-# error "You need to build uClibc with UCLIBC_HAS_RPC for NFS support" +-# endif + # include <rpc/rpc.h> + # include <rpc/pmap_prot.h> + # include <rpc/pmap_clnt.h> diff --git a/package/utils/busybox/patches/130-mconf_missing_sigwinch.patch b/package/utils/busybox/patches/130-mconf_missing_sigwinch.patch new file mode 100644 index 0000000..54f878a --- /dev/null +++ b/package/utils/busybox/patches/130-mconf_missing_sigwinch.patch @@ -0,0 +1,13 @@ +--- a/scripts/kconfig/mconf.c ++++ b/scripts/kconfig/mconf.c +@@ -27,6 +27,10 @@ + #include <unistd.h> + #include <locale.h> + ++#ifndef SIGWINCH ++#define SIGWINCH 28 ++#endif ++ + #define LKC_DIRECT_LINK + #include "lkc.h" + diff --git a/package/utils/busybox/patches/200-udhcpc_reduce_msgs.patch b/package/utils/busybox/patches/200-udhcpc_reduce_msgs.patch new file mode 100644 index 0000000..1083675 --- /dev/null +++ b/package/utils/busybox/patches/200-udhcpc_reduce_msgs.patch @@ -0,0 +1,18 @@ +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -695,6 +695,7 @@ static int bcast_or_ucast(struct dhcp_pa + static NOINLINE int send_discover(uint32_t xid, uint32_t requested) + { + struct dhcp_packet packet; ++ static int msgs = 0; + + /* Fill in: op, htype, hlen, cookie, chaddr fields, + * random xid field (we override it below), +@@ -712,6 +713,7 @@ static NOINLINE int send_discover(uint32 + */ + add_client_options(&packet); + ++ if (msgs++ < 3) + bb_info_msg("Sending discover..."); + return raw_bcast_from_client_config_ifindex(&packet); + } diff --git a/package/utils/busybox/patches/201-udhcpc_changed_ifindex.patch b/package/utils/busybox/patches/201-udhcpc_changed_ifindex.patch new file mode 100644 index 0000000..f32cea2 --- /dev/null +++ b/package/utils/busybox/patches/201-udhcpc_changed_ifindex.patch @@ -0,0 +1,15 @@ +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -1418,6 +1418,12 @@ int udhcpc_main(int argc UNUSED_PARAM, c + /* silence "uninitialized!" warning */ + unsigned timestamp_before_wait = timestamp_before_wait; + ++ /* When running on a bridge, the ifindex may have changed (e.g. if ++ * member interfaces were added/removed or if the status of the ++ * bridge changed). ++ * Workaround: refresh it here before processing the next packet */ ++ udhcp_read_interface(client_config.interface, &client_config.ifindex, NULL, client_config.client_mac); ++ + //bb_error_msg("sockfd:%d, listen_mode:%d", sockfd, listen_mode); + + /* Was opening raw or udp socket here diff --git a/package/utils/busybox/patches/203-udhcpc_renew_no_deconfig.patch b/package/utils/busybox/patches/203-udhcpc_renew_no_deconfig.patch new file mode 100644 index 0000000..f38b128 --- /dev/null +++ b/package/utils/busybox/patches/203-udhcpc_renew_no_deconfig.patch @@ -0,0 +1,10 @@ +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -1101,7 +1101,6 @@ static void perform_renew(void) + state = RENEW_REQUESTED; + break; + case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ +- udhcp_run_script(NULL, "deconfig"); + case REQUESTING: + case RELEASED: + change_listen_mode(LISTEN_RAW); diff --git a/package/utils/busybox/patches/204-udhcpc_src_ip_rebind.patch b/package/utils/busybox/patches/204-udhcpc_src_ip_rebind.patch new file mode 100644 index 0000000..21fec51 --- /dev/null +++ b/package/utils/busybox/patches/204-udhcpc_src_ip_rebind.patch @@ -0,0 +1,51 @@ +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -673,10 +673,10 @@ static void add_client_options(struct dh + * client reverts to using the IP broadcast address. + */ + +-static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet) ++static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet, uint32_t src_nip) + { + return udhcp_send_raw_packet(packet, +- /*src*/ INADDR_ANY, CLIENT_PORT, ++ /*src*/ src_nip, CLIENT_PORT, + /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, + client_config.ifindex); + } +@@ -687,7 +687,7 @@ static int bcast_or_ucast(struct dhcp_pa + return udhcp_send_kernel_packet(packet, + ciaddr, CLIENT_PORT, + server, SERVER_PORT); +- return raw_bcast_from_client_config_ifindex(packet); ++ return raw_bcast_from_client_config_ifindex(packet, ciaddr); + } + + /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ +@@ -715,7 +715,7 @@ static NOINLINE int send_discover(uint32 + + if (msgs++ < 3) + bb_info_msg("Sending discover..."); +- return raw_bcast_from_client_config_ifindex(&packet); ++ return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); + } + + /* Broadcast a DHCP request message */ +@@ -759,7 +759,7 @@ static NOINLINE int send_select(uint32_t + + addr.s_addr = requested; + bb_info_msg("Sending select for %s...", inet_ntoa(addr)); +- return raw_bcast_from_client_config_ifindex(&packet); ++ return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); + } + + /* Unicast or broadcast a DHCP renew message */ +@@ -827,7 +827,7 @@ static NOINLINE int send_decline(/*uint3 + udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); + + bb_info_msg("Sending decline..."); +- return raw_bcast_from_client_config_ifindex(&packet); ++ return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); + } + #endif + diff --git a/package/utils/busybox/patches/210-add_netmsg_util.patch b/package/utils/busybox/patches/210-add_netmsg_util.patch new file mode 100644 index 0000000..8162e3b --- /dev/null +++ b/package/utils/busybox/patches/210-add_netmsg_util.patch @@ -0,0 +1,103 @@ +--- a/include/applets.src.h ++++ b/include/applets.src.h +@@ -254,6 +254,7 @@ IF_MT(APPLET(mt, BB_DIR_BIN, BB_SUID_DRO + IF_MV(APPLET(mv, BB_DIR_BIN, BB_SUID_DROP)) + IF_NAMEIF(APPLET(nameif, BB_DIR_SBIN, BB_SUID_DROP)) + IF_NC(APPLET(nc, BB_DIR_USR_BIN, BB_SUID_DROP)) ++IF_NETMSG(APPLET(netmsg, BB_DIR_BIN, BB_SUID_REQUIRE)) + IF_NETSTAT(APPLET(netstat, BB_DIR_BIN, BB_SUID_DROP)) + IF_NICE(APPLET(nice, BB_DIR_BIN, BB_SUID_DROP)) + IF_NOHUP(APPLET(nohup, BB_DIR_USR_BIN, BB_SUID_DROP)) +--- a/networking/Config.src ++++ b/networking/Config.src +@@ -626,6 +626,12 @@ config FEATURE_IPCALC_LONG_OPTIONS + help + Support long options for the ipcalc applet. + ++config NETMSG ++ bool "netmsg" ++ default n ++ help ++ simple program for sending udp broadcast messages ++ + config NETSTAT + bool "netstat" + default y +--- a/networking/Kbuild.src ++++ b/networking/Kbuild.src +@@ -27,6 +27,7 @@ lib-$(CONFIG_IP) += ip.o + lib-$(CONFIG_IPCALC) += ipcalc.o + lib-$(CONFIG_NAMEIF) += nameif.o + lib-$(CONFIG_NC) += nc.o ++lib-$(CONFIG_NETMSG) += netmsg.o + lib-$(CONFIG_NETSTAT) += netstat.o + lib-$(CONFIG_NSLOOKUP) += nslookup.o + lib-$(CONFIG_NTPD) += ntpd.o +--- /dev/null ++++ b/networking/netmsg.c +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> ++ * ++ * This is free software, licensed under the GNU General Public License v2. ++ */ ++#include <sys/types.h> ++#include <sys/socket.h> ++#include <netinet/in.h> ++#include <netdb.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include "busybox.h" ++ ++//usage:#define netmsg_trivial_usage NOUSAGE_STR ++//usage:#define netmsg_full_usage "" ++ ++#ifndef CONFIG_NETMSG ++int main(int argc, char **argv) ++#else ++int netmsg_main(int argc, char **argv) ++#endif ++{ ++ int s; ++ struct sockaddr_in addr; ++ int optval = 1; ++ unsigned char buf[1001]; ++ ++ if (argc != 3) { ++ fprintf(stderr, "usage: %s <ip> \"<message>\"\n", argv[0]); ++ exit(1); ++ } ++ ++ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { ++ perror("Opening socket"); ++ exit(1); ++ } ++ ++ memset(&addr, 0, sizeof(addr)); ++ addr.sin_family = AF_INET; ++ addr.sin_addr.s_addr = inet_addr(argv[1]); ++ addr.sin_port = htons(0x1337); ++ ++ memset(buf, 0, 1001); ++ buf[0] = 0xde; ++ buf[1] = 0xad; ++ ++ strncpy(buf + 2, argv[2], 998); ++ ++ if (setsockopt (s, SOL_SOCKET, SO_BROADCAST, (caddr_t) &optval, sizeof (optval)) < 0) { ++ perror("setsockopt()"); ++ goto fail; ++ } ++ ++ if (sendto(s, buf, 1001, 0, (struct sockaddr *) &addr, sizeof(addr)) < 0) { ++ perror("sendto()"); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ close(s); ++ exit(1); ++} diff --git a/package/utils/busybox/patches/220-add_lock_util.patch b/package/utils/busybox/patches/220-add_lock_util.patch new file mode 100644 index 0000000..9cac9e6 --- /dev/null +++ b/package/utils/busybox/patches/220-add_lock_util.patch @@ -0,0 +1,182 @@ +--- a/include/applets.src.h ++++ b/include/applets.src.h +@@ -211,6 +211,7 @@ IF_LN(APPLET_NOEXEC(ln, ln, BB_DIR_BIN, + IF_LOAD_POLICY(APPLET(load_policy, BB_DIR_USR_SBIN, BB_SUID_DROP)) + IF_LOADFONT(APPLET(loadfont, BB_DIR_USR_SBIN, BB_SUID_DROP)) + IF_LOADKMAP(APPLET(loadkmap, BB_DIR_SBIN, BB_SUID_DROP)) ++IF_LOCK(APPLET(lock, BB_DIR_BIN, BB_SUID_DROP)) + IF_LOGGER(APPLET(logger, BB_DIR_USR_BIN, BB_SUID_DROP)) + /* Needs to be run by root or be suid root - needs to change uid and gid: */ + IF_LOGIN(APPLET(login, BB_DIR_BIN, BB_SUID_REQUIRE)) +--- a/miscutils/Config.src ++++ b/miscutils/Config.src +@@ -385,6 +385,12 @@ config FEATURE_HDPARM_HDIO_GETSET_DMA + help + Enables the 'hdparm -d' option to get/set using_dma flag. + ++config LOCK ++ bool "lock" ++ default n ++ help ++ Small utility for using locks in scripts ++ + config MAKEDEVS + bool "makedevs" + default y +--- a/miscutils/Kbuild.src ++++ b/miscutils/Kbuild.src +@@ -28,6 +28,7 @@ lib-$(CONFIG_INOTIFYD) += inotifyd.o + lib-$(CONFIG_FEATURE_LAST_SMALL)+= last.o + lib-$(CONFIG_FEATURE_LAST_FANCY)+= last_fancy.o + lib-$(CONFIG_LESS) += less.o ++lib-$(CONFIG_LOCK) += lock.o + lib-$(CONFIG_MAKEDEVS) += makedevs.o + lib-$(CONFIG_MAN) += man.o + lib-$(CONFIG_MICROCOM) += microcom.o +--- /dev/null ++++ b/miscutils/lock.c +@@ -0,0 +1,144 @@ ++/* ++ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> ++ * ++ * This is free software, licensed under the GNU General Public License v2. ++ */ ++#include <sys/types.h> ++#include <sys/file.h> ++#include <sys/stat.h> ++#include <signal.h> ++#include <fcntl.h> ++#include <unistd.h> ++#include <stdio.h> ++#include "busybox.h" ++ ++//usage:#define lock_trivial_usage NOUSAGE_STR ++//usage:#define lock_full_usage "" ++ ++static int unlock = 0; ++static int shared = 0; ++static int waitonly = 0; ++static int try_lock = 0; ++static int fd; ++static char *file; ++ ++static void usage(char *name) ++{ ++ fprintf(stderr, "Usage: %s [-suw] <filename>\n" ++ " -s Use shared locking\n" ++ " -u Unlock\n" ++ " -w Wait for the lock to become free, don't acquire lock\n" ++ " -n Don't wait for the lock to become free. Fail with exit code\n" ++ "\n", name); ++ exit(1); ++} ++ ++static void exit_unlock(int sig) ++{ ++ flock(fd, LOCK_UN); ++ exit(0); ++} ++ ++static int do_unlock(void) ++{ ++ FILE *f; ++ int i; ++ ++ if ((f = fopen(file, "r")) == NULL) ++ return 0; ++ ++ fscanf(f, "%d", &i); ++ if (i > 0) ++ kill(i, SIGTERM); ++ ++ fclose(f); ++ ++ return 0; ++} ++ ++static int do_lock(void) ++{ ++ int pid; ++ int flags; ++ char pidstr[8]; ++ ++ if ((fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0700)) < 0) { ++ if ((fd = open(file, O_RDWR)) < 0) { ++ fprintf(stderr, "Can't open %s\n", file); ++ return 1; ++ } ++ } ++ ++ flags = shared ? LOCK_SH : LOCK_EX; ++ flags |= try_lock ? LOCK_NB : 0; ++ ++ if (flock(fd, flags) < 0) { ++ fprintf(stderr, "Can't lock %s\n", file); ++ return 1; ++ } ++ ++ pid = fork(); ++ ++ if (pid < 0) ++ return -1; ++ ++ if (pid == 0) { ++ signal(SIGKILL, exit_unlock); ++ signal(SIGTERM, exit_unlock); ++ signal(SIGINT, exit_unlock); ++ if (waitonly) ++ exit_unlock(0); ++ else ++ while (1) ++ sleep(1); ++ } else { ++ if (!waitonly) { ++ lseek(fd, 0, SEEK_SET); ++ ftruncate(fd, 0); ++ sprintf(pidstr, "%d\n", pid); ++ write(fd, pidstr, strlen(pidstr)); ++ close(fd); ++ } ++ ++ return 0; ++ } ++ return 0; ++} ++ ++int lock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; ++int lock_main(int argc, char **argv) ++{ ++ char **args = &argv[1]; ++ int c = argc - 1; ++ ++ while ((*args != NULL) && (*args)[0] == '-') { ++ char *ch = *args; ++ while (*(++ch) > 0) { ++ switch(*ch) { ++ case 'w': ++ waitonly = 1; ++ break; ++ case 's': ++ shared = 1; ++ break; ++ case 'u': ++ unlock = 1; ++ break; ++ case 'n': ++ try_lock = 1; ++ break; ++ } ++ } ++ c--; ++ args++; ++ } ++ ++ if (c != 1) ++ usage(argv[0]); ++ ++ file = *args; ++ if (unlock) ++ return do_unlock(); ++ else ++ return do_lock(); ++} diff --git a/package/utils/busybox/patches/230-ntpd_delayed_resolve.patch b/package/utils/busybox/patches/230-ntpd_delayed_resolve.patch new file mode 100644 index 0000000..b0af08e --- /dev/null +++ b/package/utils/busybox/patches/230-ntpd_delayed_resolve.patch @@ -0,0 +1,48 @@ +--- a/networking/ntpd.c ++++ b/networking/ntpd.c +@@ -265,6 +265,7 @@ typedef struct { + typedef struct { + len_and_sockaddr *p_lsa; + char *p_dotted; ++ char *p_hostname; + int p_fd; + int datapoint_idx; + uint32_t lastpkt_refid; +@@ -766,8 +767,9 @@ add_peers(const char *s) + peer_t *p; + + p = xzalloc(sizeof(*p)); +- p->p_lsa = xhost2sockaddr(s, 123); +- p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa); ++ p->p_hostname = s; ++ p->p_lsa = NULL; ++ p->p_dotted = NULL; + p->p_fd = -1; + p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3); + p->next_action_time = G.cur_time; /* = set_next(p, 0); */ +@@ -816,6 +818,25 @@ send_query_to_peer(peer_t *p) + * + * Uncomment this and use strace to see it in action: + */ ++ ++ /* See if the peer hostname already resolved yet, if not, retry to resolv and return on failure */ ++ if (!p->p_lsa) ++ { ++ p->p_lsa = host2sockaddr(p->p_hostname, 123); ++ ++ if (p->p_lsa) ++ { ++ p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa); ++ VERB1 bb_error_msg("resolved peer %s to %s", p->p_hostname, p->p_dotted); ++ } ++ else ++ { ++ set_next(p, RETRY_INTERVAL); ++ VERB1 bb_error_msg("could not resolve peer %s, skipping", p->p_hostname); ++ return; ++ } ++ } ++ + #define PROBE_LOCAL_ADDR /* { len_and_sockaddr lsa; lsa.len = LSA_SIZEOF_SA; getsockname(p->query.fd, &lsa.u.sa, &lsa.len); } */ + + if (p->p_fd == -1) { diff --git a/package/utils/busybox/patches/240-telnetd_intr.patch b/package/utils/busybox/patches/240-telnetd_intr.patch new file mode 100644 index 0000000..ccb4ea4 --- /dev/null +++ b/package/utils/busybox/patches/240-telnetd_intr.patch @@ -0,0 +1,10 @@ +--- a/networking/telnetd.c ++++ b/networking/telnetd.c +@@ -331,6 +331,7 @@ make_new_session( + + /* Restore default signal handling ASAP */ + bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL); ++ signal(SIGINT, SIG_DFL); + + pid = getpid(); + diff --git a/package/utils/busybox/patches/250-date-k-flag.patch b/package/utils/busybox/patches/250-date-k-flag.patch new file mode 100644 index 0000000..f0dab26 --- /dev/null +++ b/package/utils/busybox/patches/250-date-k-flag.patch @@ -0,0 +1,87 @@ +--- a/coreutils/date.c ++++ b/coreutils/date.c +@@ -123,6 +123,7 @@ + //usage: IF_FEATURE_DATE_ISOFMT( + //usage: "\n -D FMT Use FMT for -d TIME conversion" + //usage: ) ++//usage: "\n -k Set Kernel timezone from localtime and exit" + //usage: "\n" + //usage: "\nRecognized TIME formats:" + //usage: "\n hh:mm[:ss]" +@@ -138,6 +139,7 @@ + //usage: "Wed Apr 12 18:52:41 MDT 2000\n" + + #include "libbb.h" ++#include <sys/time.h> + #if ENABLE_FEATURE_DATE_NANO + # include <sys/syscall.h> + #endif +@@ -148,8 +150,9 @@ enum { + OPT_UTC = (1 << 2), /* u */ + OPT_DATE = (1 << 3), /* d */ + OPT_REFERENCE = (1 << 4), /* r */ +- OPT_TIMESPEC = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ +- OPT_HINT = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ ++ OPT_KERNELTZ = (1 << 5), /* k */ ++ OPT_TIMESPEC = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ ++ OPT_HINT = (1 << 7) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ + }; + + static void maybe_set_utc(int opt) +@@ -167,12 +170,15 @@ static const char date_longopts[] ALIGN1 + /* "universal\0" No_argument "u" */ + "date\0" Required_argument "d" + "reference\0" Required_argument "r" ++ "set-kernel-tz\0" No_argument "k" + ; + #endif + + int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; + int date_main(int argc UNUSED_PARAM, char **argv) + { ++ time_t tt; ++ struct timezone tz; + struct timespec ts; + struct tm tm_time; + char buf_fmt_dt2str[64]; +@@ -187,7 +193,7 @@ int date_main(int argc UNUSED_PARAM, cha + opt_complementary = "d--s:s--d" + IF_FEATURE_DATE_ISOFMT(":R--I:I--R"); + IF_LONG_OPTS(applet_long_options = date_longopts;) +- opt = getopt32(argv, "Rs:ud:r:" ++ opt = getopt32(argv, "Rs:ud:r:k" + IF_FEATURE_DATE_ISOFMT("I::D:"), + &date_str, &date_str, &filename + IF_FEATURE_DATE_ISOFMT(, &isofmt_arg, &fmt_str2dt)); +@@ -244,6 +250,31 @@ int date_main(int argc UNUSED_PARAM, cha + if (*argv) + bb_show_usage(); + ++ /* Setting of kernel timezone was requested */ ++ if (opt & OPT_KERNELTZ) { ++ tt = time(NULL); ++ localtime_r(&tt, &tm_time); ++ ++ /* workaround warp_clock() on first invocation */ ++ memset(&tz, 0, sizeof(tz)); ++ settimeofday(NULL, &tz); ++ ++ memset(&tz, 0, sizeof(tz)); ++#ifdef __USE_MISC ++ tz.tz_minuteswest = -(tm_time.tm_gmtoff / 60); ++#else ++ tz.tz_minuteswest = -(tm_time.__tm_gmtoff / 60); ++#endif ++ ++ if (settimeofday(NULL, &tz)) ++ { ++ bb_perror_msg("can't set kernel time zone"); ++ return EXIT_FAILURE; ++ } ++ ++ return EXIT_SUCCESS; ++ } ++ + /* Now we have parsed all the information except the date format + * which depends on whether the clock is being set or read */ + diff --git a/package/utils/busybox/patches/260-arping_missing_includes.patch b/package/utils/busybox/patches/260-arping_missing_includes.patch new file mode 100644 index 0000000..a9d4a62 --- /dev/null +++ b/package/utils/busybox/patches/260-arping_missing_includes.patch @@ -0,0 +1,11 @@ +--- a/networking/arping.c ++++ b/networking/arping.c +@@ -24,6 +24,8 @@ + + #include <arpa/inet.h> + #include <net/if.h> ++#include <net/if_arp.h> ++#include <netinet/if_ether.h> + #include <netinet/ether.h> + #include <netpacket/packet.h> + diff --git a/package/utils/busybox/patches/270-libbb_make_unicode_printable.patch b/package/utils/busybox/patches/270-libbb_make_unicode_printable.patch new file mode 100644 index 0000000..0ae8340 --- /dev/null +++ b/package/utils/busybox/patches/270-libbb_make_unicode_printable.patch @@ -0,0 +1,20 @@ +--- a/libbb/printable_string.c ++++ b/libbb/printable_string.c +@@ -28,8 +28,6 @@ const char* FAST_FUNC printable_string(u + } + if (c < ' ') + break; +- if (c >= 0x7f) +- break; + s++; + } + +@@ -42,7 +40,7 @@ const char* FAST_FUNC printable_string(u + unsigned char c = *d; + if (c == '\0') + break; +- if (c < ' ' || c >= 0x7f) ++ if (c < ' ') + *d = '?'; + d++; + } diff --git a/package/utils/busybox/patches/301-ip-link-fix-netlink-msg-size.patch b/package/utils/busybox/patches/301-ip-link-fix-netlink-msg-size.patch new file mode 100644 index 0000000..360324b --- /dev/null +++ b/package/utils/busybox/patches/301-ip-link-fix-netlink-msg-size.patch @@ -0,0 +1,11 @@ +--- a/networking/libiproute/iplink.c ++++ b/networking/libiproute/iplink.c +@@ -470,7 +470,7 @@ static int do_add_or_delete(char **argv, + } + xrtnl_open(&rth); + ll_init_map(&rth); +- if (type_str) { ++ if (type_str && rtm == RTM_NEWLINK) { + struct rtattr *linkinfo = NLMSG_TAIL(&req.n); + + addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); diff --git a/package/utils/bzip2/Makefile b/package/utils/bzip2/Makefile new file mode 100644 index 0000000..ba47cfb --- /dev/null +++ b/package/utils/bzip2/Makefile @@ -0,0 +1,109 @@ +# +# Copyright (C) 2007-2008 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:=bzip2 +PKG_VERSION:=1.0.6 +PKG_RELEASE:=2 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://www.bzip.org/$(PKG_VERSION) +PKG_MD5SUM:=00b516f4704d4a7cb50a1d97e6e8e15b +PKG_MAINTAINER:=Steven Barth <cyrus@openwrt.org> + +PKG_LICENSE:=BZIP2 +PKG_LICENSE_FILES:=LICENSE + +include $(INCLUDE_DIR)/host-build.mk +include $(INCLUDE_DIR)/package.mk + +define Package/bzip2/Default + SUBMENU:=Compression + URL:=http://www.bzip.org/ +endef + +define Package/libbz2 +$(call Package/bzip2/Default) + SECTION:=libs + CATEGORY:=Libraries + DEPENDS:= + TITLE:=bzip2 library. +endef + +define Package/libbz2/description + bzip2 is a freely available, patent free, high-quality + data compressor. This packages provides libbz2 library. +endef + +define Package/bzip2 +$(call Package/bzip2/Default) + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=+libbz2 + TITLE:=bzip2 is a compression utility. +endef + +define Package/bzip2/description + bzip2 is a freely available, patent free, high-quality + data compressor. This package provides the binary. +endef + +TARGET_CFLAGS += \ + $(FPIC) \ + $(TARGET_LDFLAGS) + +CONFIGURE_ARGS += --prefix=/usr + +MAKE_FLAGS += \ + -f Makefile-libbz2_so \ + CFLAGS="$(TARGET_CFLAGS)" \ + all + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/bzlib.h $(1)/usr/include/ + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/libbz2.so.$(PKG_VERSION) $(1)/usr/lib/ + $(LN) libbz2.so.$(PKG_VERSION) $(1)/usr/lib/libbz2.so.1.0 + $(LN) libbz2.so.$(PKG_VERSION) $(1)/usr/lib/libbz2.so +endef + +define Package/libbz2/install + $(INSTALL_DIR) $(1)/usr/lib/ + $(CP) $(PKG_BUILD_DIR)/libbz2.so.$(PKG_VERSION) $(1)/usr/lib/ + $(LN) libbz2.so.$(PKG_VERSION) $(1)/usr/lib/libbz2.so.1.0 +endef + +define Package/bzip2/install + $(INSTALL_DIR) $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/bzip2-shared $(1)/usr/bin/bzip2 +endef + +HOST_CFLAGS += \ + $(FPIC) \ + $(HOST_LDFLAGS) + +HOST_MAKE_FLAGS+= \ + -f Makefile-libbz2_so \ + CFLAGS="$(HOST_CFLAGS)" \ + all + +HOST_CONFIGURE_ARGS+= \ + --prefix=$(STAGING_DIR_HOST) + +define Host/Install + $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin/ $(STAGING_DIR_HOST)/usr/lib + $(MAKE) -C $(HOST_BUILD_DIR) PREFIX=$(STAGING_DIR_HOST)/usr/ install + $(CP) $(HOST_BUILD_DIR)/libbz2.so* $(STAGING_DIR_HOST)/usr/lib/ + $(CP) $(HOST_BUILD_DIR)/libbz2.so.1.0 $(STAGING_DIR_HOST)/usr/lib/libbz2.so +endef + +$(eval $(call HostBuild)) + +$(eval $(call BuildPackage,libbz2)) +$(eval $(call BuildPackage,bzip2)) diff --git a/package/utils/e2fsprogs/Makefile b/package/utils/e2fsprogs/Makefile new file mode 100644 index 0000000..6c835e6 --- /dev/null +++ b/package/utils/e2fsprogs/Makefile @@ -0,0 +1,230 @@ +# +# Copyright (C) 2006-2014 OpenWrt.org +# Copyright 2010 Vertical Communications +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=e2fsprogs +PKG_VERSION:=1.42.12 +PKG_MD5SUM:=68255f51be017a93f2f6402fab06c2bf +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=@SF/e2fsprogs + +PKG_BUILD_DEPENDS:=util-linux +PKG_INSTALL:=1 + +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/e2fsprogs/Default + URL:=http://e2fsprogs.sourceforge.net/ + SUBMENU:=Filesystem +endef + +define Package/e2fsprogs +$(call Package/e2fsprogs/Default) + SECTION:=utils + CATEGORY:=Utilities + TITLE:=Ext2/3/4 filesystem utilities + DEPENDS:=+libuuid +libext2fs +endef + +define Package/e2fsprogs/description + This package contains essential ext2 filesystem utilities which consists of + e2fsck, mke2fs and most of the other core ext2 filesystem utilities. +endef + +define Package/libext2fs +$(call Package/e2fsprogs/Default) + SECTION:=libs + CATEGORY:=Libraries + TITLE:=ext2/3/4 filesystem library +endef + +define Package/libext2fs/description + libext2fs is a library which can access ext2, ext3 and ext4 filesystems. +endef + +define Package/tune2fs +$(call Package/e2fsprogs) + TITLE:=Ext2 Filesystem tune utility + DEPENDS:= +e2fsprogs +endef + +define Package/resize2fs +$(call Package/e2fsprogs) + TITLE:=Ext2 Filesystem resize utility + DEPENDS:= +e2fsprogs +endef + +define Package/badblocks +$(call Package/e2fsprogs) + TITLE:=Ext2 Filesystem badblocks utility + DEPENDS:= +e2fsprogs +endef + +define Package/dumpe2fs +$(call Package/e2fsprogs) + TITLE:=Ext2 Filesystem information dumping utility + DEPENDS:= +e2fsprogs +endef + +define Package/e2freefrag +$(call Package/e2fsprogs) + TITLE:=Ext2 Filesystem free space fragmentation information utility + DEPENDS:= +e2fsprogs +endef + +define Package/filefrag +$(call Package/e2fsprogs) + TITLE:=Ext2 Filesystem file fragmentation report utility + DEPENDS:= +e2fsprogs +endef + +define Package/debugfs +$(call Package/e2fsprogs) + TITLE:=Ext2 Filesystem debugger + DEPENDS:= +e2fsprogs +endef + +TARGET_CFLAGS += $(FPIC) -ffunction-sections -fdata-sections + +CONFIGURE_VARS += \ + ac_cv_lib_pthread_sem_init=no + +CONFIGURE_ARGS += \ + --disable-testio-debug \ + --enable-elf-shlibs \ + --disable-libuuid \ + --enable-libblkid \ + --disable-uuidd \ + --disable-tls \ + --disable-nls \ + --disable-rpath + +define Build/Prepare + $(call Build/Prepare/Default) + $(CP) $(SCRIPT_DIR)/config.{guess,sub} $(PKG_BUILD_DIR)/config/ +endef + +define Build/Compile + +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/util \ + BUILDCC="$(HOSTCC)" \ + CFLAGS="" \ + CPPFLAGS="" \ + LDFLAGS="" \ + subst + +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ + LDFLAGS=-Wl,--gc-sections \ + BUILDCC="$(HOSTCC)" \ + DESTDIR="$(PKG_INSTALL_DIR)" \ + LIBBLKID="$(PKG_BUILD_DIR)/lib/libblkid.a -luuid" \ + all +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) $(PKG_BUILD_DIR)/lib/ext2fs/ext2fs.pc $(1)/usr/lib/pkgconfig + $(CP) $(PKG_BUILD_DIR)/lib/et/com_err.pc $(1)/usr/lib/pkgconfig + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/lib/libext2fs.{so,a}* $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/lib/libcom_err.{so,a}* $(1)/usr/lib + + $(INSTALL_DIR) $(1)/usr/include/ext2fs + $(CP) $(PKG_BUILD_DIR)/lib/ext2fs/*.h $(1)/usr/include/ext2fs + $(INSTALL_DIR) $(1)/usr/include/et + $(CP) $(PKG_BUILD_DIR)/lib/et/*.h $(1)/usr/include/et +endef + +define Package/e2fsprogs/conffiles +/etc/e2fsck.conf +endef + +define Package/e2fsprogs/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/e2fsck $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/mke2fs $(1)/usr/sbin/ + $(LN) mke2fs $(1)/usr/sbin/mkfs.ext2 + $(LN) mke2fs $(1)/usr/sbin/mkfs.ext3 + $(LN) mke2fs $(1)/usr/sbin/mkfs.ext4 + $(LN) e2fsck $(1)/usr/sbin/fsck.ext2 + $(LN) e2fsck $(1)/usr/sbin/fsck.ext3 + $(LN) e2fsck $(1)/usr/sbin/fsck.ext4 + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libe2p.so.* $(1)/usr/lib/ + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_DIR) $(1)/lib/functions/fsck + $(INSTALL_DATA) ./files/e2fsck.sh $(1)/lib/functions/fsck/ + $(INSTALL_DATA) ./files/e2fsck.conf $(1)/etc/e2fsck.conf +endef + +define Package/libcom_err/install +endef + +define Package/libext2fs/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libext2fs.so.* \ + $(PKG_INSTALL_DIR)/usr/lib/libcom_err.so.* \ + $(1)/usr/lib/ +endef + +define Package/libext2fs/install_lib + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/lib/ext2fs/libext2fs.a $(1)/usr/lib/libext2fs_pic.a +endef + +define Package/tune2fs/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/tune2fs $(1)/usr/sbin/ + $(LN) tune2fs $(1)/usr/sbin/findfs +endef + +define Package/resize2fs/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/resize2fs $(1)/usr/sbin/ +endef + +define Package/badblocks/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/badblocks $(1)/usr/sbin/ +endef + +define Package/dumpe2fs/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/dumpe2fs $(1)/usr/sbin/ +endef + +define Package/e2freefrag/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/e2freefrag $(1)/usr/sbin/ +endef + +define Package/filefrag/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/filefrag $(1)/usr/sbin/ +endef + +define Package/debugfs/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/debugfs $(1)/usr/sbin/ + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libss.so.* $(1)/usr/lib/ +endef + +$(eval $(call BuildPackage,e2fsprogs)) +$(eval $(call BuildPackage,libext2fs)) +$(eval $(call BuildPackage,tune2fs)) +$(eval $(call BuildPackage,resize2fs)) +$(eval $(call BuildPackage,badblocks)) +$(eval $(call BuildPackage,dumpe2fs)) +$(eval $(call BuildPackage,e2freefrag)) +$(eval $(call BuildPackage,filefrag)) +$(eval $(call BuildPackage,debugfs)) diff --git a/package/utils/e2fsprogs/files/e2fsck.conf b/package/utils/e2fsprogs/files/e2fsck.conf new file mode 100644 index 0000000..9c96b49 --- /dev/null +++ b/package/utils/e2fsprogs/files/e2fsck.conf @@ -0,0 +1,3 @@ +[options] +broken_system_clock = true + diff --git a/package/utils/e2fsprogs/files/e2fsck.sh b/package/utils/e2fsprogs/files/e2fsck.sh new file mode 100644 index 0000000..22031ed --- /dev/null +++ b/package/utils/e2fsprogs/files/e2fsck.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# Copyright 2010 Vertical Communications +# Copyright 2012 OpenWrt.org +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +fsck_e2fsck() { + set -o pipefail + e2fsck -p "$device" 2>&1 | logger -t "fstab: e2fsck ($device)" + local status="$?" + set +o pipefail + case "$status" in + 0|1) ;; #success + 2) reboot;; + 4) echo "e2fsck ($device): Warning! Uncorrected errors."| logger -t fstab + return 1 + ;; + *) echo "e2fsck ($device): Error $status. Check not complete."| logger -t fstab;; + esac + return 0 +} + +fsck_ext2() { + fsck_e2fsck "$@" +} + +fsck_ext3() { + fsck_e2fsck "$@" +} + +fsck_ext4() { + fsck_e2fsck "$@" +} + +append libmount_known_fsck "ext2" +append libmount_known_fsck "ext3" +append libmount_known_fsck "ext4" diff --git a/package/utils/e2fsprogs/patches/001-com_err_version.patch b/package/utils/e2fsprogs/patches/001-com_err_version.patch new file mode 100644 index 0000000..62f1e08 --- /dev/null +++ b/package/utils/e2fsprogs/patches/001-com_err_version.patch @@ -0,0 +1,13 @@ +--- a/lib/et/Makefile.in ++++ b/lib/et/Makefile.in +@@ -25,8 +25,8 @@ SHARE_FILES= et_c.awk et_h.awk + LIBRARY= libcom_err + LIBDIR= et + +-ELF_VERSION = 2.1 +-ELF_SO_VERSION = 2 ++ELF_VERSION = 0.0 ++ELF_SO_VERSION = 0 + ELF_IMAGE = libcom_err + ELF_MYDIR = et + ELF_INSTALL_DIR = $(root_libdir) diff --git a/package/utils/fbtest/Makefile b/package/utils/fbtest/Makefile new file mode 100644 index 0000000..05e67cb --- /dev/null +++ b/package/utils/fbtest/Makefile @@ -0,0 +1,44 @@ +# +# Copyright (C) 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:=fbtest +PKG_RELEASE:=1 + +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/fbtest + SECTION:=utils + CATEGORY:=Utilities + TITLE:=Frame buffer device testing tool + DEPENDS:=@DISPLAY_SUPPORT +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Configure +endef + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + CC="$(TARGET_CC)" \ + CFLAGS="$(TARGET_CFLAGS) -Wall" \ + LDFLAGS="$(TARGET_LDFLAGS)" +endef + +define Package/fbtest/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/fbtest $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,fbtest)) diff --git a/package/utils/fbtest/src/Makefile b/package/utils/fbtest/src/Makefile new file mode 100644 index 0000000..075bc0e --- /dev/null +++ b/package/utils/fbtest/src/Makefile @@ -0,0 +1,14 @@ +CC = gcc +CFLAGS = -Wall +OBJS = fbtest.o + +all: fbtest + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +fbtest: $(OBJS) + $(CC) -o $@ $(OBJS) + +clean: + rm -f rbcfg *.o diff --git a/package/utils/fbtest/src/fbtest.c b/package/utils/fbtest/src/fbtest.c new file mode 100644 index 0000000..021b803 --- /dev/null +++ b/package/utils/fbtest/src/fbtest.c @@ -0,0 +1,446 @@ +/****************************************************************************** + * fbtest - fbtest.c + * test program for the tuxbox-framebuffer device + * tests all GTX/eNX supported modes + * + * (c) 2003 Carsten Juttner (carjay@gmx.net) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * The Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + ****************************************************************************** + * $Id: fbtest.c,v 1.5 2005/01/14 23:14:41 carjay Exp $ + ******************************************************************************/ + +// TODO: - should restore the colour map and mode to what it was before +// - is colour map handled correctly? + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <fcntl.h> + +#include <linux/fb.h> + +#define FBDEV "/dev/fb0" + +struct vidsize{ + int width; + int height; +}; +static +const struct vidsize vidsizetable[]={ // all supported sizes + {720,576},{720,480},{720,288},{720,240}, + {640,576},{640,480},{640,288},{640,240}, + {360,576},{360,480},{360,288},{360,240}, + {320,576},{320,480},{320,288},{320,240} +}; +#define VIDSIZENUM (sizeof(vidsizetable)/sizeof(struct vidsize)) + +enum pixenum{ // keep in sync with pixname ! + CLUT4=0, + CLUT8, + RGB565, + ARGB1555, + ARGB +}; +const char *pixname[] = { + "CLUT4", + "CLUT8", + "RGB565", + "ARGB1555", + "ARGB" +}; + +struct pixelformat{ + char *name; + struct fb_bitfield red; + struct fb_bitfield green; + struct fb_bitfield blue; + struct fb_bitfield transp; + char bpp; + char pixenum; +}; + +static // so far these are all modes supported by the eNX (only partially by GTX) +const struct pixelformat pixelformattable[] = { + { .name = "CLUT4 ARGB8888", // CLUT4 (ARGB8888) + .bpp = 4, .pixenum = CLUT4, + .red = { .offset = 0, .length=8, .msb_right =0 }, + .green = { .offset = 0, .length=8, .msb_right =0 }, + .blue = { .offset = 0, .length=8, .msb_right =0 }, + .transp= { .offset = 0, .length=8, .msb_right =0 } + }, + { .name = "CLUT4 ARGB1555", // CLUT4 (ARGB1555) + .bpp = 4, .pixenum = CLUT4, + .red = { .offset = 0, .length=5, .msb_right =0 }, + .green = { .offset = 0, .length=5, .msb_right =0 }, + .blue = { .offset = 0, .length=5, .msb_right =0 }, + .transp= { .offset = 0, .length=1, .msb_right =0 } + }, + { .name = "CLUT8 ARGB8888", // CLUT8 (ARGB8888) + .bpp = 8, .pixenum = CLUT8, + .red = { .offset = 0, .length=8, .msb_right =0 }, + .green = { .offset = 0, .length=8, .msb_right =0 }, + .blue = { .offset = 0, .length=8, .msb_right =0 }, + .transp= { .offset = 0, .length=8, .msb_right =0 } + }, + { .name = "CLUT8 ARGB1555", // CLUT8 (ARGB1555) + .bpp = 8, .pixenum = CLUT8, + .red = { .offset = 0, .length=5, .msb_right =0 }, + .green = { .offset = 0, .length=5, .msb_right =0 }, + .blue = { .offset = 0, .length=5, .msb_right =0 }, + .transp= { .offset = 0, .length=1, .msb_right =0 } + }, + { .name = "ARGB1555", // ARGB1555 + .bpp = 16, .pixenum = ARGB1555, + .red = { .offset = 10, .length=5, .msb_right =0 }, + .green = { .offset = 5, .length=5, .msb_right =0 }, + .blue = { .offset = 0, .length=5, .msb_right =0 }, + .transp= { .offset = 15, .length=1, .msb_right =0 } + }, + { .name = "RGB565", // RGB565 + .bpp = 16, .pixenum = RGB565, + .red = { .offset = 11, .length=5, .msb_right =0 }, + .green = { .offset = 5, .length=6, .msb_right =0 }, + .blue = { .offset = 0, .length=5, .msb_right =0 }, + .transp= { .offset = 0, .length=0, .msb_right =0 } + }, + { .name = "ARGB", // 32 f*cking bits, the real McCoy :) + .bpp = 32, .pixenum = ARGB, + .red = { .offset = 16, .length=8, .msb_right =0 }, + .green = { .offset = 8, .length=8, .msb_right =0 }, + .blue = { .offset = 0, .length=8, .msb_right =0 }, + .transp= { .offset = 24, .length=8, .msb_right =0 } + } +}; +#define PIXELFORMATNUM (sizeof(pixelformattable)/sizeof(struct pixelformat)) + +struct colour { + __u16 r; + __u16 g; + __u16 b; + __u16 a; +}; +static +struct colour colourtable[] = { + {.r =0xffff, .g = 0xffff, .b=0xffff, .a=0xffff}, // fully transparent white + {.r =0xffff, .g = 0x0000, .b=0x0000, .a=0x0000}, // red + {.r =0x0000, .g = 0xffff, .b=0x0000, .a=0x0000}, // green + {.r =0x0000, .g = 0x0000, .b=0xffff, .a=0x0000}, // blue + {.r =0x0000, .g = 0x0000, .b=0x0000, .a=0x0000} // black +}; +#define COLOURNUM (sizeof(colourtable)/sizeof(struct colour)) + +struct rect{ + int x; + int y; + int width; + int height; + const struct colour *col; +}; +struct pixel{ // up to 32 bits of pixel information + char byte[4]; +}; + +void col2pixel (struct pixel *pix, const struct pixelformat *pixf, const struct colour *col){ + switch (pixf->pixenum){ + case RGB565: + pix->byte[0]=(col->r&0xf8)|(col->g&0xfc)>>5; + pix->byte[1]=(col->g&0xfc)<<3|(col->b&0xf8)>>3; + break; + case ARGB1555: + pix->byte[0]=(col->a&0x80)|(col->r&0xf8)>>1|(col->g&0xf8)>>6; + pix->byte[1]=(col->g&0xf8)<<2|(col->b&0xf8)>>3; + break; + case ARGB: + pix->byte[0]=col->a; + pix->byte[1]=col->r; + pix->byte[2]=col->g; + pix->byte[3]=col->b; + break; + default: + printf ("unknown pixelformat\n"); + exit(1); + } +} + +int setmode(int fbd, const struct pixelformat *pixf,const struct vidsize *vids){ + struct fb_var_screeninfo var; + int stat; + stat = ioctl (fbd, FBIOGET_VSCREENINFO,&var); + if (stat<0) return -2; + + var.xres= vids->width; + var.xres_virtual = vids->width; + var.yres= vids->height; + var.yres_virtual = vids->height; + + var.bits_per_pixel = pixf->bpp; + var.red = pixf->red; + var.green = pixf->green; + var.blue = pixf->blue; + var.transp = pixf->transp; + + stat = ioctl (fbd, FBIOPUT_VSCREENINFO,&var); + if (stat<0) return -1; + return 0; +} + +// unefficient implementation, do NOT use it for your next ego shooter, please :) +// for 4-Bit only rectangles with even width are supported +// CLUT-modes use value of red component as index +void drawrect(void *videoram, struct rect *r, const struct pixelformat *pixf, const struct vidsize *vids){ + int x,y,corwidth, bpp = 0, tocopy = 1; + struct pixel pix; + unsigned char *pmem = videoram; + corwidth = r->width; // actually only "corrected" for 4 Bit + + if (pixf->pixenum!=CLUT4&&pixf->pixenum!=CLUT8){ + switch (pixf->pixenum){ + case ARGB1555: + case RGB565: + bpp = 16; + tocopy = 2; + break; + case ARGB: + bpp = 32; + tocopy = 4; + break; + default: + printf ("drawrect: unknown pixelformat(%d) bpp:%d\n",pixf->pixenum,pixf->bpp); + exit(1); + } + col2pixel(&pix,pixf,r->col); + } else { + switch (pixf->pixenum){ // CLUT = Colour LookUp Table (palette) + case CLUT4: // take red value as index in this case + pix.byte[0]=(r->col->r)<<4|(r->col->r&0xf); // slightly cryptic... "rect->colour->red" + corwidth>>=1; // we copy bytes + bpp=4; + tocopy=1; + break; + case CLUT8: + pix.byte[0]=(r->col->r&0xff); + bpp=8; + tocopy=1; + break; + } + } + pmem=videoram+((((r->y*vids->width)+r->x)*bpp)>>3); + for (y=0;y<r->height;y++){ + int offset = 0; + for (x=0;x<corwidth;x++){ + memcpy (pmem+offset,pix.byte,tocopy); + offset+=tocopy; + } + pmem +=((vids->width*bpp)>>3); // skip one whole line, actually should be taken from "fix-info" + } +} + +// create quick little test image, 4 colours from table +void draw4field(void *videoram, const struct pixelformat *pixf, const struct vidsize *vids){ + struct rect r; + struct colour c; + int height, width; + c.r = 1; // only used for the indexed modes, r is taken as index + height = vids->height; + width = vids->width; + + r.height = height>>1; + r.width = width>>1; + r.x = 0; r.y = 0; + if (pixf->pixenum==CLUT4||pixf->pixenum==CLUT8) r.col = &c; + else r.col = &colourtable[1]; + drawrect (videoram, &r, pixf, vids); + + r.x = width/2; r.y = 0; + if (pixf->pixenum==CLUT4||pixf->pixenum==CLUT8) c.r = 2; + else r.col = &colourtable[2]; + drawrect (videoram, &r, pixf, vids); + + r.x = 0; r.y = height/2; + if (pixf->pixenum==CLUT4||pixf->pixenum==CLUT8) c.r = 3; + else r.col = &colourtable[3]; + drawrect (videoram, &r, pixf, vids); + + r.x = width/2; r.y = height/2; + if (pixf->pixenum==CLUT4||pixf->pixenum==CLUT8) c.r = 0; + else r.col = &colourtable[0]; + drawrect (videoram, &r, pixf, vids); +} + +void usage(char *name){ + printf ("Usage: %s [options]\n" + "Options: -f<pixelformat>\n" + " where format is one of:\n" + " CLUT4,CLUT8,ARGB1555,RGB565,ARGB\n" + " -s<width>x<heigth>\n" + " where width is either 720,640,360,320\n" + " and height is either 288,240,480,576\n" + " -n\n" + " disables clearing the framebuffer after drawing\n" + " the testimage. This can be useful to keep the last\n" + " drawn image onscreen.\n" + "\nExample: %s -fRGB322\n",name,name); + exit(0); +} + +int main (int argc,char **argv){ + struct fb_fix_screeninfo fix; + struct fb_var_screeninfo var; + struct fb_cmap cmap; + struct rect r; + int fbd; + unsigned char *pfb; + int stat; + int optchar,fmode=-1,smode=-1,clear=1; + int i_cmap,i_size,i_pix; + extern char *optarg; + + if (argc!=0&&argc>4) usage(argv[0]); + while ( (optchar = getopt (argc,argv,"f:s:n"))!= -1){ + int i,height,width; + switch (optchar){ + case 'f': + for (i=0;i<(sizeof(pixname)/sizeof(char*));i++){ + if (!strncmp (optarg,pixname[i],strlen(pixname[i]))){ + fmode=i; + printf ("displaying only %s-modes\n",pixname[i]); + break; + } + } + if (fmode==-1){ + printf ("unknown pixelformat\n"); + exit(0); + } + break; + case 's': + if (sscanf (optarg,"%dx%d",&width,&height)!=2){ + printf ("parsing size failed\n"); + exit(0); + } else { + printf ("requested size %dx%d\n",width,height); + for (i=0;i<VIDSIZENUM;i++){ + if (vidsizetable[i].width == width && + vidsizetable[i].height == height){ + smode = i; + break; + } + } + if (smode==-1){ + printf ("this size is not supported\n"); + exit(0); + } + } + break; + case 'n': + clear = 0; + printf ("clearing framebuffer after drawing is disabled\n"); + break; + case '?': + usage (argv[0]); + } + } + + fbd = open (FBDEV, O_RDWR); + if (fbd<0){ + perror ("Error opening framebuffer device"); + return 1; + } + stat = ioctl (fbd, FBIOGET_FSCREENINFO,&fix); + if (stat<0){ + perror ("Error getting fix screeninfo"); + return 1; + } + stat = ioctl (fbd, FBIOGET_VSCREENINFO,&var); + if (stat<0){ + perror ("Error getting var screeninfo"); + return 1; + } + stat = ioctl (fbd, FBIOPUT_VSCREENINFO,&var); + if (stat<0){ + perror ("Error setting mode"); + return 1; + } + pfb = mmap (0, fix.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, fbd, 0); + if (pfb == MAP_FAILED){ + perror ("Error mmap'ing framebuffer device"); + return 1; + } + + // iterate over all modes + for (i_pix=0;i_pix<PIXELFORMATNUM;i_pix++){ + if (fmode!=-1 && pixelformattable[i_pix].pixenum != fmode) continue; + printf ("testing: %s",pixelformattable[i_pix].name); + printf (" for sizes: \n"); + for (i_size=0;i_size<VIDSIZENUM;i_size++){ + if (smode!=-1 && i_size!=smode) continue; + printf ("%dx%d ",vidsizetable[i_size].width,vidsizetable[i_size].height); + fflush(stdout); + if ((i_size%4)==3) printf ("\n"); + + // try to set mode + stat = setmode(fbd,&pixelformattable[i_pix],&vidsizetable[i_size]); + if (stat==-2) perror ("fbtest: could not get fb_var-screeninfo from fb-device"); + else if (stat==-1){ + printf ("\nCould not set mode %s (%dx%d), possible reasons:\n" + "- you have a GTX (soz m8)\n" + "- your configuration does not have enough graphics RAM\n" + "- you found a bug\n" + "choose your poison accordingly...\n", + pixelformattable[i_pix].name,vidsizetable[i_size].width,vidsizetable[i_size].height); + continue; + } + // fill cmap; + cmap.len = 1; + if ((pixelformattable[i_pix].bpp==4)|| + ((pixelformattable[i_pix].bpp==8)&&(pixelformattable[i_pix].red.length!=3))){ + for (i_cmap=0;i_cmap<COLOURNUM;i_cmap++){ + cmap.start=i_cmap; + cmap.red=&colourtable[i_cmap].r; + cmap.green=&colourtable[i_cmap].g; + cmap.blue=&colourtable[i_cmap].b; + cmap.transp=&colourtable[i_cmap].a; + stat = ioctl (fbd, FBIOPUTCMAP, &cmap); + if (stat<0) printf ("setting colourmap failed\n"); + } + } + // create the test image + draw4field(pfb,&pixelformattable[i_pix],&vidsizetable[i_size]); + usleep (500000); + // clear screen + if (clear){ + r.x=r.y=0;r.width = vidsizetable[i_size].width; r.height = vidsizetable[i_size].height; + r.col = &colourtable[4]; + drawrect(pfb,&r,&pixelformattable[i_pix],&vidsizetable[i_size]); + } + } + printf ("\n"); + } + + stat = munmap (pfb,fix.smem_len); + if (stat<0){ + perror ("Error munmap'ing framebuffer device"); + return 1; + } + close (fbd); + return 0; +} diff --git a/package/utils/fuse/Makefile b/package/utils/fuse/Makefile new file mode 100644 index 0000000..9adb6d3 --- /dev/null +++ b/package/utils/fuse/Makefile @@ -0,0 +1,101 @@ +# +# 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.3 +PKG_RELEASE:=2 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=@SF/$(PKG_NAME) +PKG_MD5SUM:=33cae22ca50311446400daf8a6255c6a + +PKG_LICENSE:=LGPLv2.1 GPLv2 +PKG_LICENSE_FILES:=COPYING.LIB COPYING + +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/fuse/Default + TITLE:=FUSE + URL:=http://fuse.sourceforge.net/ +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 +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 +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,fuse-utils)) +$(eval $(call BuildPackage,libfuse)) diff --git a/package/utils/fuse/patches/001-fix_exec_environment_for_mount_and_umount.patch b/package/utils/fuse/patches/001-fix_exec_environment_for_mount_and_umount.patch new file mode 100644 index 0000000..392bb5e --- /dev/null +++ b/package/utils/fuse/patches/001-fix_exec_environment_for_mount_and_umount.patch @@ -0,0 +1,59 @@ +From cfe13b7a217075ae741c018da50cd600e5330de2 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi <mszeredi@suse.cz> +Date: Fri, 22 May 2015 10:58:43 +0200 +Subject: [PATCH] libfuse: fix exec environment for mount and umount + +Found by Tavis Ormandy (CVE-2015-3202). +--- +--- a/lib/mount_util.c ++++ b/lib/mount_util.c +@@ -95,10 +95,12 @@ static int add_mount(const char *prognam + goto out_restore; + } + if (res == 0) { ++ char *env = NULL; ++ + sigprocmask(SIG_SETMASK, &oldmask, NULL); + setuid(geteuid()); +- execl("/bin/mount", "/bin/mount", "--no-canonicalize", "-i", +- "-f", "-t", type, "-o", opts, fsname, mnt, NULL); ++ execle("/bin/mount", "/bin/mount", "--no-canonicalize", "-i", ++ "-f", "-t", type, "-o", opts, fsname, mnt, NULL, &env); + fprintf(stderr, "%s: failed to execute /bin/mount: %s\n", + progname, strerror(errno)); + exit(1); +@@ -146,10 +148,17 @@ static int exec_umount(const char *progn + goto out_restore; + } + if (res == 0) { ++ char *env = NULL; ++ + sigprocmask(SIG_SETMASK, &oldmask, NULL); + setuid(geteuid()); +- execl("/bin/umount", "/bin/umount", "-i", rel_mnt, +- lazy ? "-l" : NULL, NULL); ++ if (lazy) { ++ execle("/bin/umount", "/bin/umount", "-i", rel_mnt, ++ "-l", NULL, &env); ++ } else { ++ execle("/bin/umount", "/bin/umount", "-i", rel_mnt, ++ NULL, &env); ++ } + fprintf(stderr, "%s: failed to execute /bin/umount: %s\n", + progname, strerror(errno)); + exit(1); +@@ -205,10 +214,12 @@ static int remove_mount(const char *prog + goto out_restore; + } + if (res == 0) { ++ char *env = NULL; ++ + sigprocmask(SIG_SETMASK, &oldmask, NULL); + setuid(geteuid()); +- execl("/bin/umount", "/bin/umount", "--no-canonicalize", "-i", +- "--fake", mnt, NULL); ++ execle("/bin/umount", "/bin/umount", "--no-canonicalize", "-i", ++ "--fake", mnt, NULL, &env); + fprintf(stderr, "%s: failed to execute /bin/umount: %s\n", + progname, strerror(errno)); + exit(1); diff --git a/package/utils/fuse/patches/100-missing_includes.patch b/package/utils/fuse/patches/100-missing_includes.patch new file mode 100644 index 0000000..0790bff --- /dev/null +++ b/package/utils/fuse/patches/100-missing_includes.patch @@ -0,0 +1,20 @@ +--- a/lib/mount_util.c ++++ b/lib/mount_util.c +@@ -16,6 +16,7 @@ + #include <errno.h> + #include <fcntl.h> + #include <limits.h> ++#include <paths.h> + #ifndef __NetBSD__ + #include <mntent.h> + #endif +--- 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/package/utils/fuse/patches/112-no_break_on_mknod.patch b/package/utils/fuse/patches/112-no_break_on_mknod.patch new file mode 100644 index 0000000..33f7c6c --- /dev/null +++ b/package/utils/fuse/patches/112-no_break_on_mknod.patch @@ -0,0 +1,11 @@ +--- a/util/Makefile.in ++++ b/util/Makefile.in +@@ -676,7 +676,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/package/utils/fuse/patches/200-backport_arm64_fuse_kernel_h_clean_includes.patch b/package/utils/fuse/patches/200-backport_arm64_fuse_kernel_h_clean_includes.patch new file mode 100644 index 0000000..d45da84 --- /dev/null +++ b/package/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/package/utils/hostap-utils/Makefile b/package/utils/hostap-utils/Makefile new file mode 100644 index 0000000..1d7b221 --- /dev/null +++ b/package/utils/hostap-utils/Makefile @@ -0,0 +1,44 @@ +# Copyright (C) 2006 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:=hostap-utils +PKG_VERSION:=0.4.7 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://hostap.epitest.fi/releases/ +PKG_MD5SUM:=afe041581b8f01666e353bec20917c85 + +include $(INCLUDE_DIR)/package.mk + +define Package/hostap-utils + SECTION:=net + CATEGORY:=Network + DEPENDS:=kmod-hostap + TITLE:=Host AP driver utility programs + URL:=http://hostap.epitest.fi/ +endef + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + $(TARGET_CONFIGURE_OPTS) \ + CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS) -Wall" \ + all +endef + +define Package/hostap-utils/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostap_crypt_conf $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostap_diag $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostap_io_debug $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostap_rid $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/prism2_srec $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/split_combined_hex $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,hostap-utils)) diff --git a/package/utils/jsonfilter/Makefile b/package/utils/jsonfilter/Makefile new file mode 100644 index 0000000..34020df --- /dev/null +++ b/package/utils/jsonfilter/Makefile @@ -0,0 +1,33 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=jsonfilter +PKG_VERSION:=2014-06-19 +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=http://git.openwrt.org/project/jsonpath.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=cdc760c58077f44fc40adbbe41e1556a67c1b9a9 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +CMAKE_INSTALL:=1 + +PKG_MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org> +PKG_LICENSE:=ISC + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/jsonfilter + SECTION:=base + CATEGORY:=Base system + DEPENDS:=+libubox +libjson-c + TITLE:=OpenWrt JSON filter utility + URL:=http://git.openwrt.org/?p=project/jsonpath.git +endef + +define Package/jsonfilter/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/jsonpath $(1)/usr/bin/jsonfilter +endef + +$(eval $(call BuildPackage,jsonfilter)) diff --git a/package/utils/lua/Makefile b/package/utils/lua/Makefile new file mode 100644 index 0000000..e81833d --- /dev/null +++ b/package/utils/lua/Makefile @@ -0,0 +1,183 @@ +# +# 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:=lua +PKG_VERSION:=5.1.5 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://www.lua.org/ftp/ \ + http://ftp.gwdg.de/pub/languages/lua/ \ + http://mirrors.dotsrc.org/lua/ \ + http://www.tecgraf.puc-rio.br/lua/ftp/ +PKG_MD5SUM:=2e115fe26e435e33b0d5c022e4490567 +PKG_BUILD_PARALLEL:=1 + +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=COPYRIGHT + +HOST_PATCH_DIR := ./patches-host + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/host-build.mk + +define Package/lua/Default + SUBMENU:=Lua + SECTION:=lang + CATEGORY:=Languages + TITLE:=Lua programming language + URL:=http://www.lua.org/ + MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org> +endef + +define Package/lua/Default/description + Lua is a powerful light-weight programming language designed for extending + applications. Lua is also frequently used as a general-purpose, stand-alone + language. Lua is free software. +endef + +define Package/liblua +$(call Package/lua/Default) + SUBMENU:= + SECTION:=libs + CATEGORY:=Libraries + TITLE+= (libraries) +endef + +define Package/liblua/description +$(call Package/lua/Default/description) + This package contains the Lua shared libraries, needed by other programs. +endef + +define Package/lua +$(call Package/lua/Default) + DEPENDS:=+liblua + TITLE+= (interpreter) +endef + +define Package/lua/description +$(call Package/lua/Default/description) + This package contains the Lua language interpreter. +endef + +define Package/luac +$(call Package/lua/Default) + DEPENDS:=+liblua + TITLE+= (compiler) +endef + +define Package/luac/description +$(call Package/lua/Default/description) + This package contains the Lua language compiler. +endef + +define Package/lua-examples +$(call Package/lua/Default) + DEPENDS:=lua + TITLE+= (examples) +endef + +define Package/lua-examples/description +$(call Package/lua/Default/description) + This package contains Lua language examples. +endef + +define Build/Configure +endef + +TARGET_CFLAGS += -DLUA_USE_LINUX $(FPIC) -std=gnu99 + +ifneq ($(CONFIG_USE_GLIBC),) + ifeq ($(CONFIG_EGLIBC_OPTION_EGLIBC_UTMP),) + TARGET_CFLAGS += -DNO_GETLOGIN + endif +endif + +define Build/Compile + $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ + CC="$(TARGET_CROSS)gcc" \ + AR="$(TARGET_CROSS)ar rcu" \ + RANLIB="$(TARGET_CROSS)ranlib" \ + INSTALL_ROOT=/usr \ + CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \ + MYLDFLAGS="$(TARGET_LDFLAGS)" \ + PKG_VERSION=$(PKG_VERSION) \ + linux + rm -rf $(PKG_INSTALL_DIR) + mkdir -p $(PKG_INSTALL_DIR) + $(MAKE) -C $(PKG_BUILD_DIR) \ + INSTALL_TOP="$(PKG_INSTALL_DIR)/usr" \ + install +endef + +define Host/Configure + $(SED) 's,"/usr/local/","$(STAGING_DIR_HOST)/",' $(HOST_BUILD_DIR)/src/luaconf.h +endef + +ifeq ($(HOST_OS),Darwin) + LUA_OS:=macosx +else + ifeq ($(HOST_OS),FreeBSD) + LUA_OS:=freebsd + else + LUA_OS:=linux + endif +endif + +define Host/Compile + $(MAKE) -C $(HOST_BUILD_DIR) \ + CC="$(HOSTCC) -std=gnu99" \ + $(LUA_OS) +endef + +define Host/Install + $(MAKE) -C $(HOST_BUILD_DIR) \ + INSTALL_TOP="$(STAGING_DIR_HOST)" \ + install +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_INSTALL_DIR)/usr/include/lua{,lib,conf}.h $(1)/usr/include/ + $(CP) $(PKG_INSTALL_DIR)/usr/include/lauxlib.h $(1)/usr/include/ + $(CP) $(PKG_INSTALL_DIR)/usr/include/lnum_config.h $(1)/usr/include/ + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/liblua.{a,so*} $(1)/usr/lib/ + $(LN) liblua.so.$(PKG_VERSION) $(1)/usr/lib/liblualib.so + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) $(PKG_BUILD_DIR)/etc/lua.pc $(1)/usr/lib/pkgconfig/ +endef + +define Package/liblua/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/liblua.so.* $(1)/usr/lib/ +endef + +define Package/lua/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lua $(1)/usr/bin/ +endef + +define Package/luac/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/luac $(1)/usr/bin/ +endef + +define Package/lua-examples/install + $(INSTALL_DIR) $(1)/usr/share/lua/examples + $(INSTALL_DATA) $(PKG_BUILD_DIR)/test/*.lua \ + $(1)/usr/share/lua/examples/ +endef + +$(eval $(call BuildPackage,liblua)) +$(eval $(call BuildPackage,lua)) +$(eval $(call BuildPackage,luac)) +$(eval $(call BuildPackage,lua-examples)) +$(eval $(call HostBuild)) + diff --git a/package/utils/lua/patches-host/010-lua-5.1.3-lnum-full-260308.patch b/package/utils/lua/patches-host/010-lua-5.1.3-lnum-full-260308.patch new file mode 100644 index 0000000..74b8c6f --- /dev/null +++ b/package/utils/lua/patches-host/010-lua-5.1.3-lnum-full-260308.patch @@ -0,0 +1,3736 @@ +--- a/src/Makefile ++++ b/src/Makefile +@@ -25,7 +25,7 @@ PLATS= aix ansi bsd freebsd generic linu + LUA_A= liblua.a + CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ + lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \ +- lundump.o lvm.o lzio.o ++ lundump.o lvm.o lzio.o lnum.o + LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ + lstrlib.o loadlib.o linit.o + +@@ -148,6 +148,7 @@ llex.o: llex.c lua.h luaconf.h ldo.h lob + lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h + lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h ++lnum.o: lnum.c lua.h llex.h lnum.h + loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h + lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \ + ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h +@@ -179,4 +180,18 @@ lzio.o: lzio.c lua.h luaconf.h llimits.h + print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h lopcodes.h lundump.h + ++luaconf.h: lnum_config.h ++lapi.c: lnum.h ++lauxlib.c: llimits.h ++lbaselib.c: llimits.h lobject.h lapi.h ++lcode.c: lnum.h ++liolib.c: lnum.h llex.h ++llex.c: lnum.h ++lnum.h: lobject.h ++lobject.c: llex.h lnum.h ++ltable.c: lnum.h ++lua.c: llimits.h ++lvm.c: llex.h lnum.h ++print.c: lnum.h ++ + # (end of Makefile) +--- a/src/lapi.c ++++ b/src/lapi.c +@@ -28,7 +28,7 @@ + #include "ltm.h" + #include "lundump.h" + #include "lvm.h" +- ++#include "lnum.h" + + + const char lua_ident[] = +@@ -241,12 +241,13 @@ LUA_API void lua_pushvalue (lua_State *L + + LUA_API int lua_type (lua_State *L, int idx) { + StkId o = index2adr(L, idx); +- return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); ++ return (o == luaO_nilobject) ? LUA_TNONE : ttype_ext(o); + } + + + LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); ++ lua_assert( t!= LUA_TINT ); + return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; + } + +@@ -264,6 +265,14 @@ LUA_API int lua_isnumber (lua_State *L, + } + + ++LUA_API int lua_isinteger (lua_State *L, int idx) { ++ TValue tmp; ++ lua_Integer dum; ++ const TValue *o = index2adr(L, idx); ++ return tonumber(o,&tmp) && (ttisint(o) || tt_integer_valued(o,&dum)); ++} ++ ++ + LUA_API int lua_isstring (lua_State *L, int idx) { + int t = lua_type(L, idx); + return (t == LUA_TSTRING || t == LUA_TNUMBER); +@@ -309,31 +318,66 @@ LUA_API int lua_lessthan (lua_State *L, + } + + +- + LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); +- if (tonumber(o, &n)) ++ if (tonumber(o, &n)) { ++#ifdef LNUM_COMPLEX ++ if (nvalue_img(o) != 0) ++ luaG_runerror(L, "expecting a real number"); ++#endif + return nvalue(o); +- else +- return 0; ++ } ++ return 0; + } + + + LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { + TValue n; ++ /* Lua 5.1 documented behaviour is to return nonzero for non-integer: ++ * "If the number is not an integer, it is truncated in some non-specified way." ++ * I would suggest to change this, to return 0 for anything that would ++ * not fit in 'lua_Integer'. ++ */ ++#ifdef LUA_COMPAT_TOINTEGER ++ /* Lua 5.1 compatible */ + const TValue *o = index2adr(L, idx); + if (tonumber(o, &n)) { +- lua_Integer res; +- lua_Number num = nvalue(o); +- lua_number2integer(res, num); +- return res; ++ lua_Integer i; ++ lua_Number d; ++ if (ttisint(o)) return ivalue(o); ++ d= nvalue_fast(o); ++# ifdef LNUM_COMPLEX ++ if (nvalue_img_fast(o) != 0) ++ luaG_runerror(L, "expecting a real number"); ++# endif ++ lua_number2integer(i, d); ++ return i; + } +- else +- return 0; ++#else ++ /* New suggestion */ ++ const TValue *o = index2adr(L, idx); ++ if (tonumber(o, &n)) { ++ lua_Integer i; ++ if (ttisint(o)) return ivalue(o); ++ if (tt_integer_valued(o,&i)) return i; ++ } ++#endif ++ return 0; + } + + ++#ifdef LNUM_COMPLEX ++LUA_API lua_Complex lua_tocomplex (lua_State *L, int idx) { ++ TValue tmp; ++ const TValue *o = index2adr(L, idx); ++ if (tonumber(o, &tmp)) ++ return nvalue_complex(o); ++ return 0; ++} ++#endif ++ ++ + LUA_API int lua_toboolean (lua_State *L, int idx) { + const TValue *o = index2adr(L, idx); + return !l_isfalse(o); +@@ -364,6 +408,7 @@ LUA_API size_t lua_objlen (lua_State *L, + case LUA_TSTRING: return tsvalue(o)->len; + case LUA_TUSERDATA: return uvalue(o)->len; + case LUA_TTABLE: return luaH_getn(hvalue(o)); ++ case LUA_TINT: + case LUA_TNUMBER: { + size_t l; + lua_lock(L); /* `luaV_tostring' may create a new string */ +@@ -426,6 +471,8 @@ LUA_API void lua_pushnil (lua_State *L) + } + + ++/* 'lua_pushnumber()' may lose accuracy on integers, 'lua_pushinteger' will not. ++ */ + LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { + lua_lock(L); + setnvalue(L->top, n); +@@ -434,12 +481,22 @@ LUA_API void lua_pushnumber (lua_State * + } + + +-LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { ++LUA_API void lua_pushinteger (lua_State *L, lua_Integer i) { ++ lua_lock(L); ++ setivalue(L->top, i); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++#ifdef LNUM_COMPLEX ++LUA_API void lua_pushcomplex (lua_State *L, lua_Complex v) { + lua_lock(L); +- setnvalue(L->top, cast_num(n)); ++ setnvalue_complex( L->top, v ); + api_incr_top(L); + lua_unlock(L); + } ++#endif + + + LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { +@@ -569,7 +626,7 @@ LUA_API void lua_rawgeti (lua_State *L, + lua_lock(L); + o = index2adr(L, idx); + api_check(L, ttistable(o)); +- setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); ++ setobj2s(L, L->top, luaH_getint(hvalue(o), n)); + api_incr_top(L); + lua_unlock(L); + } +@@ -597,6 +654,9 @@ LUA_API int lua_getmetatable (lua_State + case LUA_TUSERDATA: + mt = uvalue(obj)->metatable; + break; ++ case LUA_TINT: ++ mt = G(L)->mt[LUA_TNUMBER]; ++ break; + default: + mt = G(L)->mt[ttype(obj)]; + break; +@@ -687,7 +747,7 @@ LUA_API void lua_rawseti (lua_State *L, + api_checknelems(L, 1); + o = index2adr(L, idx); + api_check(L, ttistable(o)); +- setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); ++ setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1); + luaC_barriert(L, hvalue(o), L->top-1); + L->top--; + lua_unlock(L); +@@ -721,7 +781,7 @@ LUA_API int lua_setmetatable (lua_State + break; + } + default: { +- G(L)->mt[ttype(obj)] = mt; ++ G(L)->mt[ttype_ext(obj)] = mt; + break; + } + } +@@ -1085,3 +1145,32 @@ LUA_API const char *lua_setupvalue (lua_ + return name; + } + ++ ++/* Help function for 'luaB_tonumber()', avoids multiple str->number ++ * conversions for Lua "tonumber()". ++ * ++ * Also pushes floating point numbers with integer value as integer, which ++ * can be used by 'tonumber()' in scripts to bring values back to integer ++ * realm. ++ * ++ * Note: The 'back to integer realm' is _not_ to affect string conversions: ++ * 'tonumber("4294967295.1")' should give a floating point value, although ++ * the value would be 4294967296 (and storable in int64 realm). ++ */ ++int lua_pushvalue_as_number (lua_State *L, int idx) ++{ ++ const TValue *o = index2adr(L, idx); ++ TValue tmp; ++ lua_Integer i; ++ if (ttisnumber(o)) { ++ if ( (!ttisint(o)) && tt_integer_valued(o,&i)) { ++ lua_pushinteger( L, i ); ++ return 1; ++ } ++ } else if (!tonumber(o, &tmp)) { ++ return 0; ++ } ++ if (ttisint(o)) lua_pushinteger( L, ivalue(o) ); ++ else lua_pushnumber( L, nvalue_fast(o) ); ++ return 1; ++} +--- a/src/lapi.h ++++ b/src/lapi.h +@@ -13,4 +13,6 @@ + + LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); + ++int lua_pushvalue_as_number (lua_State *L, int idx); ++ + #endif +--- a/src/lauxlib.c ++++ b/src/lauxlib.c +@@ -23,7 +23,7 @@ + #include "lua.h" + + #include "lauxlib.h" +- ++#include "llimits.h" + + #define FREELIST_REF 0 /* free list of references */ + +@@ -66,7 +66,7 @@ LUALIB_API int luaL_typerror (lua_State + + + static void tag_error (lua_State *L, int narg, int tag) { +- luaL_typerror(L, narg, lua_typename(L, tag)); ++ luaL_typerror(L, narg, tag==LUA_TINT ? "integer" : lua_typename(L, tag)); + } + + +@@ -188,8 +188,8 @@ LUALIB_API lua_Number luaL_optnumber (lu + + LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { + lua_Integer d = lua_tointeger(L, narg); +- if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ +- tag_error(L, narg, LUA_TNUMBER); ++ if (d == 0 && !lua_isinteger(L, narg)) /* avoid extra test when d is not 0 */ ++ tag_error(L, narg, LUA_TINT); + return d; + } + +@@ -200,6 +200,16 @@ LUALIB_API lua_Integer luaL_optinteger ( + } + + ++#ifdef LNUM_COMPLEX ++LUALIB_API lua_Complex luaL_checkcomplex (lua_State *L, int narg) { ++ lua_Complex c = lua_tocomplex(L, narg); ++ if (c == 0 && !lua_isnumber(L, narg)) /* avoid extra test when c is not 0 */ ++ tag_error(L, narg, LUA_TNUMBER); ++ return c; ++} ++#endif ++ ++ + LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return 0; +--- a/src/lauxlib.h ++++ b/src/lauxlib.h +@@ -57,6 +57,12 @@ LUALIB_API lua_Number (luaL_optnumber) ( + LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); + LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, + lua_Integer def); ++#define luaL_checkint32(L,narg) ((int)luaL_checkinteger(L,narg)) ++#define luaL_optint32(L,narg,def) ((int)luaL_optinteger(L,narg,def)) ++ ++#ifdef LNUM_COMPLEX ++ LUALIB_API lua_Complex (luaL_checkcomplex) (lua_State *L, int narg); ++#endif + + LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); + LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); +--- a/src/lbaselib.c ++++ b/src/lbaselib.c +@@ -18,7 +18,9 @@ + + #include "lauxlib.h" + #include "lualib.h" +- ++#include "llimits.h" ++#include "lobject.h" ++#include "lapi.h" + + + +@@ -54,20 +56,25 @@ static int luaB_tonumber (lua_State *L) + int base = luaL_optint(L, 2, 10); + if (base == 10) { /* standard conversion */ + luaL_checkany(L, 1); +- if (lua_isnumber(L, 1)) { +- lua_pushnumber(L, lua_tonumber(L, 1)); ++ if (lua_isnumber(L, 1)) { /* numeric string, or a number */ ++ lua_pushvalue_as_number(L,1); /* API extension (not to lose accuracy here) */ + return 1; +- } ++ } + } + else { + const char *s1 = luaL_checkstring(L, 1); + char *s2; +- unsigned long n; ++ unsigned LUA_INTEGER n; + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); +- n = strtoul(s1, &s2, base); ++ n = lua_str2ul(s1, &s2, base); + if (s1 != s2) { /* at least one valid digit? */ + while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ + if (*s2 == '\0') { /* no invalid trailing characters? */ ++ ++ /* Push as number, there needs to be separate 'luaB_tointeger' for ++ * when the caller wants to preserve the bits (matters if unsigned ++ * values are used). ++ */ + lua_pushnumber(L, (lua_Number)n); + return 1; + } +@@ -144,7 +151,7 @@ static int luaB_setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + getfunc(L, 0); + lua_pushvalue(L, 2); +- if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { ++ if (lua_isnumber(L, 1) && lua_tointeger(L, 1) == 0) { + /* change environment of current thread */ + lua_pushthread(L); + lua_insert(L, -2); +@@ -209,7 +216,7 @@ static int luaB_collectgarbage (lua_Stat + return 1; + } + default: { +- lua_pushnumber(L, res); ++ lua_pushinteger(L, res); + return 1; + } + } +@@ -631,6 +638,8 @@ static void base_open (lua_State *L) { + luaL_register(L, "_G", base_funcs); + lua_pushliteral(L, LUA_VERSION); + lua_setglobal(L, "_VERSION"); /* set global _VERSION */ ++ lua_pushliteral(L, LUA_LNUM); ++ lua_setglobal(L, "_LNUM"); /* "[complex] double|float|ldouble int32|int64" */ + /* `ipairs' and `pairs' need auxiliary functions as upvalues */ + auxopen(L, "ipairs", luaB_ipairs, ipairsaux); + auxopen(L, "pairs", luaB_pairs, luaB_next); +--- a/src/lcode.c ++++ b/src/lcode.c +@@ -22,13 +22,18 @@ + #include "lopcodes.h" + #include "lparser.h" + #include "ltable.h" ++#include "lnum.h" + + + #define hasjumps(e) ((e)->t != (e)->f) + +- + static int isnumeral(expdesc *e) { +- return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); ++ int ek= ++#ifdef LNUM_COMPLEX ++ (e->k == VKNUM2) || ++#endif ++ (e->k == VKINT) || (e->k == VKNUM); ++ return (ek && e->t == NO_JUMP && e->f == NO_JUMP); + } + + +@@ -231,12 +236,16 @@ static int addk (FuncState *fs, TValue * + TValue *idx = luaH_set(L, fs->h, k); + Proto *f = fs->f; + int oldsize = f->sizek; +- if (ttisnumber(idx)) { +- lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); +- return cast_int(nvalue(idx)); ++ if (ttype(idx)==LUA_TNUMBER) { ++ luai_normalize(idx); ++ lua_assert( ttype(idx)==LUA_TINT ); /* had no fraction */ ++ } ++ if (ttisint(idx)) { ++ lua_assert(luaO_rawequalObj(&fs->f->k[ivalue(idx)], v)); ++ return cast_int(ivalue(idx)); + } + else { /* constant not found; create a new entry */ +- setnvalue(idx, cast_num(fs->nk)); ++ setivalue(idx, fs->nk); + luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, + MAXARG_Bx, "constant table overflow"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); +@@ -261,6 +270,21 @@ int luaK_numberK (FuncState *fs, lua_Num + } + + ++int luaK_integerK (FuncState *fs, lua_Integer r) { ++ TValue o; ++ setivalue(&o, r); ++ return addk(fs, &o, &o); ++} ++ ++ ++#ifdef LNUM_COMPLEX ++static int luaK_imagK (FuncState *fs, lua_Number r) { ++ TValue o; ++ setnvalue_complex(&o, r*I); ++ return addk(fs, &o, &o); ++} ++#endif ++ + static int boolK (FuncState *fs, int b) { + TValue o; + setbvalue(&o, b); +@@ -359,6 +383,16 @@ static void discharge2reg (FuncState *fs + luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); + break; + } ++ case VKINT: { ++ luaK_codeABx(fs, OP_LOADK, reg, luaK_integerK(fs, e->u.ival)); ++ break; ++ } ++#ifdef LNUM_COMPLEX ++ case VKNUM2: { ++ luaK_codeABx(fs, OP_LOADK, reg, luaK_imagK(fs, e->u.nval)); ++ break; ++ } ++#endif + case VRELOCABLE: { + Instruction *pc = &getcode(fs, e); + SETARG_A(*pc, reg); +@@ -444,6 +478,10 @@ void luaK_exp2val (FuncState *fs, expdes + int luaK_exp2RK (FuncState *fs, expdesc *e) { + luaK_exp2val(fs, e); + switch (e->k) { ++#ifdef LNUM_COMPLEX ++ case VKNUM2: ++#endif ++ case VKINT: + case VKNUM: + case VTRUE: + case VFALSE: +@@ -451,6 +489,10 @@ int luaK_exp2RK (FuncState *fs, expdesc + if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ + e->u.s.info = (e->k == VNIL) ? nilK(fs) : + (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : ++ (e->k == VKINT) ? luaK_integerK(fs, e->u.ival) : ++#ifdef LNUM_COMPLEX ++ (e->k == VKNUM2) ? luaK_imagK(fs, e->u.nval) : ++#endif + boolK(fs, (e->k == VTRUE)); + e->k = VK; + return RKASK(e->u.s.info); +@@ -540,7 +582,10 @@ void luaK_goiftrue (FuncState *fs, expde + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { +- case VK: case VKNUM: case VTRUE: { ++#ifdef LNUM_COMPLEX ++ case VKNUM2: ++#endif ++ case VKINT: case VK: case VKNUM: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + break; + } +@@ -590,7 +635,10 @@ static void codenot (FuncState *fs, expd + e->k = VTRUE; + break; + } +- case VK: case VKNUM: case VTRUE: { ++#ifdef LNUM_COMPLEX ++ case VKNUM2: ++#endif ++ case VKINT: case VK: case VKNUM: case VTRUE: { + e->k = VFALSE; + break; + } +@@ -626,25 +674,70 @@ void luaK_indexed (FuncState *fs, expdes + + static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { + lua_Number v1, v2, r; ++ int vkres= VKNUM; + if (!isnumeral(e1) || !isnumeral(e2)) return 0; +- v1 = e1->u.nval; +- v2 = e2->u.nval; ++ ++ /* real and imaginary parts don't mix. */ ++#ifdef LNUM_COMPLEX ++ if (e1->k == VKNUM2) { ++ if ((op != OP_UNM) && (e2->k != VKNUM2)) return 0; ++ vkres= VKNUM2; } ++ else if (e2->k == VKNUM2) { return 0; } ++#endif ++ if ((e1->k == VKINT) && (e2->k == VKINT)) { ++ lua_Integer i1= e1->u.ival, i2= e2->u.ival; ++ lua_Integer rr; ++ int done= 0; ++ /* Integer/integer calculations (may end up producing floating point) */ ++ switch (op) { ++ case OP_ADD: done= try_addint( &rr, i1, i2 ); break; ++ case OP_SUB: done= try_subint( &rr, i1, i2 ); break; ++ case OP_MUL: done= try_mulint( &rr, i1, i2 ); break; ++ case OP_DIV: done= try_divint( &rr, i1, i2 ); break; ++ case OP_MOD: done= try_modint( &rr, i1, i2 ); break; ++ case OP_POW: done= try_powint( &rr, i1, i2 ); break; ++ case OP_UNM: done= try_unmint( &rr, i1 ); break; ++ default: done= 0; break; ++ } ++ if (done) { ++ e1->u.ival = rr; /* remained within integer range */ ++ return 1; ++ } ++ } ++ v1 = (e1->k == VKINT) ? ((lua_Number)e1->u.ival) : e1->u.nval; ++ v2 = (e2->k == VKINT) ? ((lua_Number)e2->u.ival) : e2->u.nval; ++ + switch (op) { + case OP_ADD: r = luai_numadd(v1, v2); break; + case OP_SUB: r = luai_numsub(v1, v2); break; +- case OP_MUL: r = luai_nummul(v1, v2); break; ++ case OP_MUL: ++#ifdef LNUM_COMPLEX ++ if (vkres==VKNUM2) return 0; /* leave to runtime (could do here, but not worth it?) */ ++#endif ++ r = luai_nummul(v1, v2); break; + case OP_DIV: + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ +- r = luai_numdiv(v1, v2); break; ++#ifdef LNUM_COMPLEX ++ if (vkres==VKNUM2) return 0; /* leave to runtime */ ++#endif ++ r = luai_numdiv(v1, v2); break; + case OP_MOD: + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ ++#ifdef LNUM_COMPLEX ++ if (vkres==VKNUM2) return 0; /* leave to runtime */ ++#endif + r = luai_nummod(v1, v2); break; +- case OP_POW: r = luai_numpow(v1, v2); break; ++ case OP_POW: ++#ifdef LNUM_COMPLEX ++ if (vkres==VKNUM2) return 0; /* leave to runtime */ ++#endif ++ r = luai_numpow(v1, v2); break; + case OP_UNM: r = luai_numunm(v1); break; + case OP_LEN: return 0; /* no constant folding for 'len' */ + default: lua_assert(0); r = 0; break; + } + if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ ++ e1->k = cast(expkind,vkres); + e1->u.nval = r; + return 1; + } +@@ -688,7 +781,8 @@ static void codecomp (FuncState *fs, OpC + + void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { + expdesc e2; +- e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; ++ e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0; ++ + switch (op) { + case OPR_MINUS: { + if (!isnumeral(e)) +--- a/src/lcode.h ++++ b/src/lcode.h +@@ -71,6 +71,6 @@ LUAI_FUNC void luaK_prefix (FuncState *f + LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); + LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); + LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); +- ++LUAI_FUNC int luaK_integerK (FuncState *fs, lua_Integer r); + + #endif +--- a/src/ldebug.c ++++ b/src/ldebug.c +@@ -183,7 +183,7 @@ static void collectvalidlines (lua_State + int *lineinfo = f->l.p->lineinfo; + int i; + for (i=0; i<f->l.p->sizelineinfo; i++) +- setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); ++ setbvalue(luaH_setint(L, t, lineinfo[i]), 1); + sethvalue(L, L->top, t); + } + incr_top(L); +@@ -566,7 +566,7 @@ static int isinstack (CallInfo *ci, cons + + void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + const char *name = NULL; +- const char *t = luaT_typenames[ttype(o)]; ++ const char *t = luaT_typenames[ttype_ext(o)]; + const char *kind = (isinstack(L->ci, o)) ? + getobjname(L, L->ci, cast_int(o - L->base), &name) : + NULL; +@@ -594,8 +594,8 @@ void luaG_aritherror (lua_State *L, cons + + + int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { +- const char *t1 = luaT_typenames[ttype(p1)]; +- const char *t2 = luaT_typenames[ttype(p2)]; ++ const char *t1 = luaT_typenames[ttype_ext(p1)]; ++ const char *t2 = luaT_typenames[ttype_ext(p2)]; + if (t1[2] == t2[2]) + luaG_runerror(L, "attempt to compare two %s values", t1); + else +--- a/src/ldo.c ++++ b/src/ldo.c +@@ -220,9 +220,9 @@ static StkId adjust_varargs (lua_State * + luaD_checkstack(L, p->maxstacksize); + htab = luaH_new(L, nvar, 1); /* create `arg' table */ + for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */ +- setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i); ++ setobj2n(L, luaH_setint(L, htab, i+1), L->top - nvar + i); + /* store counter in field `n' */ +- setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); ++ setivalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), nvar); + } + #endif + /* move fixed parameters to final position */ +--- a/src/ldump.c ++++ b/src/ldump.c +@@ -52,6 +52,11 @@ static void DumpNumber(lua_Number x, Dum + DumpVar(x,D); + } + ++static void DumpInteger(lua_Integer x, DumpState* D) ++{ ++ DumpVar(x,D); ++} ++ + static void DumpVector(const void* b, int n, size_t size, DumpState* D) + { + DumpInt(n,D); +@@ -93,8 +98,11 @@ static void DumpConstants(const Proto* f + DumpChar(bvalue(o),D); + break; + case LUA_TNUMBER: +- DumpNumber(nvalue(o),D); ++ DumpNumber(nvalue_fast(o),D); + break; ++ case LUA_TINT: ++ DumpInteger(ivalue(o),D); ++ break; + case LUA_TSTRING: + DumpString(rawtsvalue(o),D); + break; +--- a/src/liolib.c ++++ b/src/liolib.c +@@ -9,6 +9,7 @@ + #include <stdio.h> + #include <stdlib.h> + #include <string.h> ++#include <ctype.h> + + #define liolib_c + #define LUA_LIB +@@ -18,7 +19,8 @@ + #include "lauxlib.h" + #include "lualib.h" + +- ++#include "lnum.h" ++#include "llex.h" + + #define IO_INPUT 1 + #define IO_OUTPUT 2 +@@ -269,6 +271,13 @@ static int io_lines (lua_State *L) { + ** ======================================================= + */ + ++/* ++* Many problems if we intend the same 'n' format specifier (see 'file:read()') ++* to work for both FP and integer numbers, without losing their accuracy. So ++* we don't. 'n' reads numbers as floating points, 'i' as integers. Old code ++* remains valid, but won't provide full integer accuracy (this only matters ++* with float FP and/or 64-bit integers). ++*/ + + static int read_number (lua_State *L, FILE *f) { + lua_Number d; +@@ -282,6 +291,43 @@ static int read_number (lua_State *L, FI + } + } + ++static int read_integer (lua_State *L, FILE *f) { ++ lua_Integer i; ++ if (fscanf(f, LUA_INTEGER_SCAN, &i) == 1) { ++ lua_pushinteger(L, i); ++ return 1; ++ } ++ else return 0; /* read fails */ ++} ++ ++#ifdef LNUM_COMPLEX ++static int read_complex (lua_State *L, FILE *f) { ++ /* NNN / NNNi / NNN+MMMi / NNN-MMMi */ ++ lua_Number a,b; ++ if (fscanf(f, LUA_NUMBER_SCAN, &a) == 1) { ++ int c=fgetc(f); ++ switch(c) { ++ case 'i': ++ lua_pushcomplex(L, a*I); ++ return 1; ++ case '+': ++ case '-': ++ /* "i" is consumed if at the end; just 'NNN+MMM' will most likely ++ * behave as if "i" was there? (TBD: test) ++ */ ++ if (fscanf(f, LUA_NUMBER_SCAN "i", &b) == 1) { ++ lua_pushcomplex(L, a+ (c=='+' ? b:-b)*I); ++ return 1; ++ } ++ } ++ ungetc( c,f ); ++ lua_pushnumber(L,a); /*real part only*/ ++ return 1; ++ } ++ return 0; /* read fails */ ++} ++#endif ++ + + static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); +@@ -355,6 +401,14 @@ static int g_read (lua_State *L, FILE *f + case 'n': /* number */ + success = read_number(L, f); + break; ++ case 'i': /* integer (full accuracy) */ ++ success = read_integer(L, f); ++ break; ++#ifdef LNUM_COMPLEX ++ case 'c': /* complex */ ++ success = read_complex(L, f); ++ break; ++#endif + case 'l': /* line */ + success = read_line(L, f); + break; +@@ -415,9 +469,10 @@ static int g_write (lua_State *L, FILE * + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { +- /* optimization: could be done exactly as for strings */ +- status = status && +- fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; ++ if (lua_isinteger(L,arg)) ++ status = status && fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg)) > 0; ++ else ++ status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + } + else { + size_t l; +@@ -460,7 +515,7 @@ static int f_setvbuf (lua_State *L) { + static const char *const modenames[] = {"no", "full", "line", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, NULL, modenames); +- lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); ++ size_t sz = luaL_optint32(L, 3, LUAL_BUFFERSIZE); + int res = setvbuf(f, NULL, mode[op], sz); + return pushresult(L, res == 0, NULL); + } +--- a/src/llex.c ++++ b/src/llex.c +@@ -22,6 +22,7 @@ + #include "lstring.h" + #include "ltable.h" + #include "lzio.h" ++#include "lnum.h" + + + +@@ -34,13 +35,17 @@ + + + /* ORDER RESERVED */ +-const char *const luaX_tokens [] = { ++static const char *const luaX_tokens [] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "..", "...", "==", ">=", "<=", "~=", + "<number>", "<name>", "<string>", "<eof>", ++ "<integer>", ++#ifdef LNUM_COMPLEX ++ "<number2>", ++#endif + NULL + }; + +@@ -90,7 +95,11 @@ static const char *txtToken (LexState *l + switch (token) { + case TK_NAME: + case TK_STRING: ++ case TK_INT: + case TK_NUMBER: ++#ifdef LNUM_COMPLEX ++ case TK_NUMBER2: ++#endif + save(ls, '\0'); + return luaZ_buffer(ls->buff); + default: +@@ -175,23 +184,27 @@ static void buffreplace (LexState *ls, c + if (p[n] == from) p[n] = to; + } + +- +-static void trydecpoint (LexState *ls, SemInfo *seminfo) { ++/* TK_NUMBER (/ TK_NUMBER2) */ ++static int trydecpoint (LexState *ls, SemInfo *seminfo) { + /* format error: try to update decimal point separator */ + struct lconv *cv = localeconv(); + char old = ls->decpoint; ++ int ret; + ls->decpoint = (cv ? cv->decimal_point[0] : '.'); + buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ +- if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { ++ ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, NULL); ++ if (!ret) { + /* format error with correct decimal point: no more options */ + buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ + luaX_lexerror(ls, "malformed number", TK_NUMBER); + } ++ return ret; + } + + +-/* LUA_NUMBER */ +-static void read_numeral (LexState *ls, SemInfo *seminfo) { ++/* TK_NUMBER / TK_INT (/TK_NUMBER2) */ ++static int read_numeral (LexState *ls, SemInfo *seminfo) { ++ int ret; + lua_assert(isdigit(ls->current)); + do { + save_and_next(ls); +@@ -202,8 +215,9 @@ static void read_numeral (LexState *ls, + save_and_next(ls); + save(ls, '\0'); + buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ +- if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ +- trydecpoint(ls, seminfo); /* try to update decimal point separator */ ++ ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, &seminfo->i ); ++ if (!ret) return trydecpoint(ls, seminfo); /* try to update decimal point separator */ ++ return ret; + } + + +@@ -331,6 +345,7 @@ static void read_string (LexState *ls, i + } + + ++/* char / TK_* */ + static int llex (LexState *ls, SemInfo *seminfo) { + luaZ_resetbuffer(ls->buff); + for (;;) { +@@ -402,8 +417,7 @@ static int llex (LexState *ls, SemInfo * + } + else if (!isdigit(ls->current)) return '.'; + else { +- read_numeral(ls, seminfo); +- return TK_NUMBER; ++ return read_numeral(ls, seminfo); + } + } + case EOZ: { +@@ -416,8 +430,7 @@ static int llex (LexState *ls, SemInfo * + continue; + } + else if (isdigit(ls->current)) { +- read_numeral(ls, seminfo); +- return TK_NUMBER; ++ return read_numeral(ls, seminfo); + } + else if (isalpha(ls->current) || ls->current == '_') { + /* identifier or reserved word */ +--- a/src/llex.h ++++ b/src/llex.h +@@ -29,19 +29,22 @@ enum RESERVED { + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, + /* other terminal symbols */ + TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, +- TK_NAME, TK_STRING, TK_EOS ++ TK_NAME, TK_STRING, TK_EOS, TK_INT ++#ifdef LNUM_COMPLEX ++ , TK_NUMBER2 /* imaginary constants: Ni */ ++#endif + }; + + /* number of reserved words */ + #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) + + +-/* array with token `names' */ +-LUAI_DATA const char *const luaX_tokens []; +- +- ++/* SemInfo is a local data structure of 'llex.c', used for carrying a string ++ * or a number. A separate token (TK_*) will tell, how to interpret the data. ++ */ + typedef union { + lua_Number r; ++ lua_Integer i; + TString *ts; + } SemInfo; /* semantics information */ + +--- a/src/llimits.h ++++ b/src/llimits.h +@@ -49,6 +49,7 @@ typedef LUAI_USER_ALIGNMENT_T L_Umaxalig + + /* result of a `usual argument conversion' over lua_Number */ + typedef LUAI_UACNUMBER l_uacNumber; ++typedef LUAI_UACINTEGER l_uacInteger; + + + /* internal assertions for in-house debugging */ +@@ -80,7 +81,6 @@ typedef LUAI_UACNUMBER l_uacNumber; + #define cast_int(i) cast(int, (i)) + + +- + /* + ** type for virtual-machine instructions + ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +--- a/src/lmathlib.c ++++ b/src/lmathlib.c +@@ -4,7 +4,6 @@ + ** See Copyright Notice in lua.h + */ + +- + #include <stdlib.h> + #include <math.h> + +@@ -16,113 +15,210 @@ + #include "lauxlib.h" + #include "lualib.h" + ++/* 'luai_vectpow()' as a replacement for 'cpow()'. Defined in the header; we ++ * don't intrude the code libs internal functions. ++ */ ++#ifdef LNUM_COMPLEX ++# include "lnum.h" ++#endif + + #undef PI +-#define PI (3.14159265358979323846) +-#define RADIANS_PER_DEGREE (PI/180.0) +- ++#ifdef LNUM_FLOAT ++# define PI (3.14159265358979323846F) ++#elif defined(M_PI) ++# define PI M_PI ++#else ++# define PI (3.14159265358979323846264338327950288) ++#endif ++#define RADIANS_PER_DEGREE (PI/180) + ++#undef HUGE ++#ifdef LNUM_FLOAT ++# define HUGE HUGE_VALF ++#elif defined(LNUM_LDOUBLE) ++# define HUGE HUGE_VALL ++#else ++# define HUGE HUGE_VAL ++#endif + + static int math_abs (lua_State *L) { +- lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushnumber(L, _LF(cabs) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(fabs) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_sin (lua_State *L) { +- lua_pushnumber(L, sin(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(csin) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(sin) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_sinh (lua_State *L) { +- lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(csinh) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(sinh) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_cos (lua_State *L) { +- lua_pushnumber(L, cos(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(ccos) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(cos) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_cosh (lua_State *L) { +- lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(ccosh) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(cosh) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_tan (lua_State *L) { +- lua_pushnumber(L, tan(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(ctan) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(tan) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_tanh (lua_State *L) { +- lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(ctanh) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(tanh) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_asin (lua_State *L) { +- lua_pushnumber(L, asin(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(casin) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(asin) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_acos (lua_State *L) { +- lua_pushnumber(L, acos(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(cacos) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(acos) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_atan (lua_State *L) { +- lua_pushnumber(L, atan(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(catan) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(atan) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_atan2 (lua_State *L) { +- lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); ++ /* scalars only */ ++ lua_pushnumber(L, _LF(atan2) (luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; + } + + static int math_ceil (lua_State *L) { +- lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_Complex v= luaL_checkcomplex(L, 1); ++ lua_pushcomplex(L, _LF(ceil) (_LF(creal)(v)) + _LF(ceil) (_LF(cimag)(v))*I); ++#else ++ lua_pushnumber(L, _LF(ceil) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_floor (lua_State *L) { +- lua_pushnumber(L, floor(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_Complex v= luaL_checkcomplex(L, 1); ++ lua_pushcomplex(L, _LF(floor) (_LF(creal)(v)) + _LF(floor) (_LF(cimag)(v))*I); ++#else ++ lua_pushnumber(L, _LF(floor) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + +-static int math_fmod (lua_State *L) { +- lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); ++static int math_fmod (lua_State *L) { ++ /* scalars only */ ++ lua_pushnumber(L, _LF(fmod) (luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; + } + + static int math_modf (lua_State *L) { +- double ip; +- double fp = modf(luaL_checknumber(L, 1), &ip); ++ /* scalars only */ ++ lua_Number ip; ++ lua_Number fp = _LF(modf) (luaL_checknumber(L, 1), &ip); + lua_pushnumber(L, ip); + lua_pushnumber(L, fp); + return 2; + } + + static int math_sqrt (lua_State *L) { +- lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(csqrt) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(sqrt) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_pow (lua_State *L) { +- lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); ++#ifdef LNUM_COMPLEX ++ /* C99 'cpow' gives somewhat inaccurate results (i.e. (-1)^2 = -1+1.2246467991474e-16i). ++ * 'luai_vectpow' smoothens such, reusing it is the reason we need to #include "lnum.h". ++ */ ++ lua_pushcomplex(L, luai_vectpow(luaL_checkcomplex(L,1), luaL_checkcomplex(L,2))); ++#else ++ lua_pushnumber(L, _LF(pow) (luaL_checknumber(L, 1), luaL_checknumber(L, 2))); ++#endif + return 1; + } + + static int math_log (lua_State *L) { +- lua_pushnumber(L, log(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(log) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_log10 (lua_State *L) { +- lua_pushnumber(L, log10(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ /* Not in standard <complex.h> , but easy to calculate: log_a(x) = log_b(x) / log_b(a) ++ */ ++ lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)) / _LF(log) (10)); ++#else ++ lua_pushnumber(L, _LF(log10) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_exp (lua_State *L) { +- lua_pushnumber(L, exp(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(cexp) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(exp) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + +@@ -138,19 +234,20 @@ static int math_rad (lua_State *L) { + + static int math_frexp (lua_State *L) { + int e; +- lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); ++ lua_pushnumber(L, _LF(frexp) (luaL_checknumber(L, 1), &e)); + lua_pushinteger(L, e); + return 2; + } + + static int math_ldexp (lua_State *L) { +- lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); ++ lua_pushnumber(L, _LF(ldexp) (luaL_checknumber(L, 1), luaL_checkint(L, 2))); + return 1; + } + + + + static int math_min (lua_State *L) { ++ /* scalars only */ + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmin = luaL_checknumber(L, 1); + int i; +@@ -165,6 +262,7 @@ static int math_min (lua_State *L) { + + + static int math_max (lua_State *L) { ++ /* scalars only */ + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmax = luaL_checknumber(L, 1); + int i; +@@ -182,25 +280,20 @@ static int math_random (lua_State *L) { + /* the `%' avoids the (rare) case of r==1, and is needed also because on + some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ + lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; +- switch (lua_gettop(L)) { /* check number of arguments */ +- case 0: { /* no arguments */ +- lua_pushnumber(L, r); /* Number between 0 and 1 */ +- break; +- } +- case 1: { /* only upper limit */ +- int u = luaL_checkint(L, 1); +- luaL_argcheck(L, 1<=u, 1, "interval is empty"); +- lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ +- break; +- } +- case 2: { /* lower and upper limits */ +- int l = luaL_checkint(L, 1); +- int u = luaL_checkint(L, 2); +- luaL_argcheck(L, l<=u, 2, "interval is empty"); +- lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ +- break; +- } +- default: return luaL_error(L, "wrong number of arguments"); ++ int n= lua_gettop(L); /* number of arguments */ ++ if (n==0) { /* no arguments: range [0,1) */ ++ lua_pushnumber(L, r); ++ } else if (n<=2) { /* int range [1,u] or [l,u] */ ++ int l= n==1 ? 1 : luaL_checkint(L, 1); ++ int u = luaL_checkint(L, n); ++ int tmp; ++ lua_Number d; ++ luaL_argcheck(L, l<=u, n, "interval is empty"); ++ d= _LF(floor)(r*(u-l+1)); ++ lua_number2int(tmp,d); ++ lua_pushinteger(L, l+tmp); ++ } else { ++ return luaL_error(L, "wrong number of arguments"); + } + return 1; + } +@@ -211,6 +304,66 @@ static int math_randomseed (lua_State *L + return 0; + } + ++/* ++* Lua 5.1 does not have acosh, asinh, atanh for scalars (not ANSI C) ++*/ ++#if __STDC_VERSION__ >= 199901L ++static int math_acosh (lua_State *L) { ++# ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(cacosh) (luaL_checkcomplex(L,1))); ++# else ++ lua_pushnumber(L, _LF(acosh) (luaL_checknumber(L,1))); ++# endif ++ return 1; ++} ++static int math_asinh (lua_State *L) { ++# ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(casinh) (luaL_checkcomplex(L,1))); ++# else ++ lua_pushnumber(L, _LF(asinh) (luaL_checknumber(L,1))); ++# endif ++ return 1; ++} ++static int math_atanh (lua_State *L) { ++# ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(catanh) (luaL_checkcomplex(L,1))); ++# else ++ lua_pushnumber(L, _LF(atanh) (luaL_checknumber(L,1))); ++# endif ++ return 1; ++} ++#endif ++ ++/* ++ * C99 complex functions, not covered above. ++*/ ++#ifdef LNUM_COMPLEX ++static int math_arg (lua_State *L) { ++ lua_pushnumber(L, _LF(carg) (luaL_checkcomplex(L,1))); ++ return 1; ++} ++ ++static int math_imag (lua_State *L) { ++ lua_pushnumber(L, _LF(cimag) (luaL_checkcomplex(L,1))); ++ return 1; ++} ++ ++static int math_real (lua_State *L) { ++ lua_pushnumber(L, _LF(creal) (luaL_checkcomplex(L,1))); ++ return 1; ++} ++ ++static int math_conj (lua_State *L) { ++ lua_pushcomplex(L, _LF(conj) (luaL_checkcomplex(L,1))); ++ return 1; ++} ++ ++static int math_proj (lua_State *L) { ++ lua_pushcomplex(L, _LF(cproj) (luaL_checkcomplex(L,1))); ++ return 1; ++} ++#endif ++ + + static const luaL_Reg mathlib[] = { + {"abs", math_abs}, +@@ -241,6 +394,18 @@ static const luaL_Reg mathlib[] = { + {"sqrt", math_sqrt}, + {"tanh", math_tanh}, + {"tan", math_tan}, ++#if __STDC_VERSION__ >= 199901L ++ {"acosh", math_acosh}, ++ {"asinh", math_asinh}, ++ {"atanh", math_atanh}, ++#endif ++#ifdef LNUM_COMPLEX ++ {"arg", math_arg}, ++ {"imag", math_imag}, ++ {"real", math_real}, ++ {"conj", math_conj}, ++ {"proj", math_proj}, ++#endif + {NULL, NULL} + }; + +@@ -252,8 +417,10 @@ LUALIB_API int luaopen_math (lua_State * + luaL_register(L, LUA_MATHLIBNAME, mathlib); + lua_pushnumber(L, PI); + lua_setfield(L, -2, "pi"); +- lua_pushnumber(L, HUGE_VAL); ++ lua_pushnumber(L, HUGE); + lua_setfield(L, -2, "huge"); ++ lua_pushinteger(L, LUA_INTEGER_MAX ); ++ lua_setfield(L, -2, "hugeint"); + #if defined(LUA_COMPAT_MOD) + lua_getfield(L, -1, "fmod"); + lua_setfield(L, -2, "mod"); +--- /dev/null ++++ b/src/lnum.c +@@ -0,0 +1,312 @@ ++/* ++** $Id: lnum.c,v ... $ ++** Internal number model ++** See Copyright Notice in lua.h ++*/ ++ ++#include <stdlib.h> ++#include <math.h> ++#include <ctype.h> ++#include <string.h> ++#include <stdio.h> ++#include <errno.h> ++ ++#define lnum_c ++#define LUA_CORE ++ ++#include "lua.h" ++#include "llex.h" ++#include "lnum.h" ++ ++/* ++** lua_real2str converts a (non-complex) number to a string. ++** lua_str2real converts a string to a (non-complex) number. ++*/ ++#define lua_real2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) ++ ++/* ++* Note: Only 'strtod()' is part of ANSI C; others are C99 and ++* may need '--std=c99' compiler setting (at least on Ubuntu 7.10). ++* ++* Visual C++ 2008 Express does not have 'strtof()', nor 'strtold()'. ++* References to '_strtold()' exist but don't compile. It seems best ++* to leave Windows users with DOUBLE only (or compile with MinGW). ++* ++* In practise, using '(long double)strtod' is a risky thing, since ++* it will cause accuracy loss in reading in numbers, and such losses ++* will pile up in later processing. Get a real 'strtold()' or don't ++* use that mode at all. ++*/ ++#ifdef LNUM_DOUBLE ++# define lua_str2real strtod ++#elif defined(LNUM_FLOAT) ++# define lua_str2real strtof ++#elif defined(LNUM_LDOUBLE) ++# define lua_str2real strtold ++#endif ++ ++#define lua_integer2str(s,v) sprintf((s), LUA_INTEGER_FMT, (v)) ++ ++/* 's' is expected to be LUAI_MAXNUMBER2STR long (enough for any number) ++*/ ++void luaO_num2buf( char *s, const TValue *o ) ++{ ++ lua_Number n; ++ lua_assert( ttisnumber(o) ); ++ ++ /* Reason to handle integers differently is not only speed, but accuracy as ++ * well. We want to make any integer tostring() without roundings, at all. ++ */ ++ if (ttisint(o)) { ++ lua_integer2str( s, ivalue(o) ); ++ return; ++ } ++ n= nvalue_fast(o); ++ lua_real2str(s, n); ++ ++#ifdef LNUM_COMPLEX ++ lua_Number n2= nvalue_img_fast(o); ++ if (n2!=0) { /* Postfix with +-Ni */ ++ int re0= (n == 0); ++ char *s2= re0 ? s : strchr(s,'\0'); ++ if ((!re0) && (n2>0)) *s2++= '+'; ++ lua_real2str( s2, n2 ); ++ strcat(s2,"i"); ++ } ++#endif ++} ++ ++/* ++* If a LUA_TNUMBER has integer value, give it. ++*/ ++int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref ) { ++ lua_Number d; ++ lua_Integer i; ++ ++ lua_assert( ttype(o)==LUA_TNUMBER ); ++ lua_assert( ref ); ++#ifdef LNUM_COMPLEX ++ if (nvalue_img_fast(o)!=0) return 0; ++#endif ++ d= nvalue_fast(o); ++ lua_number2integer(i, d); ++ if (cast_num(i) == d) { ++ *ref= i; return 1; ++ } ++ return 0; ++} ++ ++/* ++ * Lua 5.1.3 (using 'strtod()') allows 0x+hex but not 0+octal. This is good, ++ * and we should NOT use 'autobase' 0 with 'strtoul[l]()' for this reason. ++ * ++ * Lua 5.1.3 allows '0x...' numbers to overflow and lose precision; this is not ++ * good. On Visual C++ 2008, 'strtod()' does not even take them in. Better to ++ * require hex values to fit 'lua_Integer' or give an error that they don't? ++ * ++ * Full hex range (0 .. 0xff..ff) is stored as integers, not to lose any bits. ++ * Numerical value of 0xff..ff will be -1, if used in calculations. ++ * ++ * Returns: TK_INT for a valid integer, '*endptr_ref' updated ++ * TK_NUMBER for seemingly numeric, to be parsed as floating point ++ * 0 for bad characters, not a number (or '0x' out of range) ++ */ ++static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) { ++ char *endptr; ++ /* 'v' gets ULONG_MAX on possible overflow (which is > LUA_INTEGER_MAX); ++ * we don't have to check 'errno' here. ++ */ ++ unsigned LUA_INTEGER v= lua_str2ul(s, &endptr, 10); ++ if (endptr == s) return 0; /* nothing numeric */ ++ if (v==0 && *endptr=='x') { ++ errno= 0; /* needs to be set, 'strtoul[l]' does not clear it */ ++ v= lua_str2ul(endptr+1, &endptr, 16); /* retry as hex, unsigned range */ ++ if (errno==ERANGE) { /* clamped to 0xff..ff */ ++#if (defined(LNUM_INT32) && !defined(LNUM_FLOAT)) || defined(LNUM_LDOUBLE) ++ return TK_NUMBER; /* Allow to be read as floating point (has more integer range) */ ++#else ++ return 0; /* Reject the number */ ++#endif ++ } ++ } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) { ++ return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */ ++ } ++ *res= (lua_Integer)v; ++ *endptr_ref= endptr; ++ return TK_INT; ++} ++ ++/* 0 / TK_NUMBER / TK_INT (/ TK_NUMBER2) */ ++int luaO_str2d (const char *s, lua_Number *res_n, lua_Integer *res_i) { ++ char *endptr; ++ int ret= TK_NUMBER; ++ /* Check integers first, if caller is allowing. ++ * If 'res2'==NULL, they're only looking for floating point. ++ */ ++ if (res_i) { ++ ret= luaO_str2i(s,res_i,&endptr); ++ if (ret==0) return 0; ++ } ++ if (ret==TK_NUMBER) { ++ lua_assert(res_n); ++ /* Note: Visual C++ 2008 Express 'strtod()' does not read in "0x..." ++ * numbers; it will read '0' and spit 'x' as endptr. ++ * This means hex constants not fitting in 'lua_Integer' won't ++ * be read in at all. What to do? ++ */ ++ *res_n = lua_str2real(s, &endptr); ++ if (endptr == s) return 0; /* conversion failed */ ++ /* Visual C++ 2008 'strtod()' does not allow "0x..." input. */ ++#if defined(_MSC_VER) && !defined(LNUM_FLOAT) && !defined(LNUM_INT64) ++ if (*res_n==0 && *endptr=='x') { ++ /* Hex constant too big for 'lua_Integer' but that could fit in 'lua_Number' ++ * integer bits ++ */ ++ unsigned __int64 v= _strtoui64( s, &endptr, 16 ); ++ /* We just let > 64 bit values be clamped to _UI64_MAX (MSDN does not say 'errno'==ERANGE would be set) */ ++ *res_n= cast_num(v); ++ if (*res_n != v) return 0; /* Would have lost accuracy */ ++ } ++#endif ++#ifdef LNUM_COMPLEX ++ if (*endptr == 'i') { endptr++; ret= TK_NUMBER2; } ++#endif ++ } ++ if (*endptr) { ++ while (isspace(cast(unsigned char, *endptr))) endptr++; ++ if (*endptr) return 0; /* invalid trail */ ++ } ++ return ret; ++} ++ ++ ++/* Functions for finding out, when integer operations remain in range ++ * (and doing them). ++ */ ++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { ++ lua_Integer v= ib+ic; /* may overflow */ ++ if (ib>0 && ic>0) { if (v < 0) return 0; /*overflow, use floats*/ } ++ else if (ib<0 && ic<0) { if (v >= 0) return 0; } ++ *r= v; ++ return 1; ++} ++ ++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { ++ lua_Integer v= ib-ic; /* may overflow */ ++ if (ib>=0 && ic<0) { if (v < 0) return 0; /*overflow, use floats*/ } ++ else if (ib<0 && ic>0) { if (v >= 0) return 0; } ++ *r= v; ++ return 1; ++} ++ ++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { ++ if (ib!=LUA_INTEGER_MIN && ic!=LUA_INTEGER_MIN) { ++ lua_Integer b= luai_abs(ib), c= luai_abs(ic); ++ if ( (ib==0) || (LUA_INTEGER_MAX/b >= c) ) { ++ *r= ib*ic; /* no overflow */ ++ return 1; ++ } ++ } else if (ib==0 || ic==0) { ++ *r= 0; return 1; ++ } ++ ++ /* Result can be LUA_INTEGER_MIN; if it is, calculating it using floating ++ * point will not cause accuracy loss. ++ */ ++ if ( luai_nummul( cast_num(ib), cast_num(ic) ) == LUA_INTEGER_MIN ) { ++ *r= LUA_INTEGER_MIN; ++ return 1; ++ } ++ return 0; ++} ++ ++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { ++ /* N/0: leave to float side, to give an error ++ */ ++ if (ic==0) return 0; ++ ++ /* N/LUA_INTEGER_MIN: always non-integer results, or 0 or +1 ++ */ ++ if (ic==LUA_INTEGER_MIN) { ++ if (ib==LUA_INTEGER_MIN) { *r=1; return 1; } ++ if (ib==0) { *r=0; return 1; } ++ ++ /* LUA_INTEGER_MIN (-2^31|63)/N: calculate using float side (either the division ++ * causes non-integer results, or there is no accuracy loss in int->fp->int ++ * conversions (N=2,4,8,..,256 and N=2^30,2^29,..2^23). ++ */ ++ } else if (ib==LUA_INTEGER_MIN) { ++ lua_Number d= luai_numdiv( cast_num(LUA_INTEGER_MIN), cast_num(ic) ); ++ lua_Integer i; lua_number2integer(i,d); ++ if (cast_num(i)==d) { *r= i; return 1; } ++ ++ } else { ++ /* Note: We _can_ use ANSI C mod here, even on negative values, since ++ * we only test for == 0 (the sign would be implementation dependent). ++ */ ++ if (ib%ic == 0) { *r= ib/ic; return 1; } ++ } ++ ++ return 0; ++} ++ ++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { ++ if (ic!=0) { ++ /* ANSI C can be trusted when b%c==0, or when values are non-negative. ++ * b - (floor(b/c) * c) ++ * --> ++ * + +: b - (b/c) * c (b % c can be used) ++ * - -: b - (b/c) * c (b % c could work, but not defined by ANSI C) ++ * 0 -: b - (b/c) * c (=0, b % c could work, but not defined by ANSI C) ++ * - +: b - (b/c-1) * c (when b!=-c) ++ * + -: b - (b/c-1) * c (when b!=-c) ++ * ++ * o MIN%MIN ends up 0, via overflow in calcs but that does not matter. ++ * o MIN%MAX ends up MAX-1 (and other such numbers), also after overflow, ++ * but that does not matter, results do. ++ */ ++ lua_Integer v= ib % ic; ++ if ( v!=0 && (ib<0 || ic<0) ) { ++ v= ib - ((ib/ic) - ((ib<=0 && ic<0) ? 0:1)) * ic; ++ } ++ /* Result should always have same sign as 2nd argument. (PIL2) */ ++ lua_assert( (v<0) ? (ic<0) : (v>0) ? (ic>0) : 1 ); ++ *r= v; ++ return 1; ++ } ++ return 0; /* let float side return NaN */ ++} ++ ++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { ++ ++ /* In FLOAT/INT32 or FLOAT|DOUBLE/INT64 modes, calculating integer powers ++ * via FP realm may lose accuracy (i.e. 7^11 = 1977326743, which fits int32 ++ * but not 23-bit float mantissa). ++ * ++ * The current solution is dumb, but it works and uses little code. Use of ++ * integer powers is not anticipated to be very frequent (apart from 2^x, ++ * which is separately optimized). ++ */ ++ if (ib==0) *r=0; ++ else if (ic<0) return 0; /* FP realm */ ++ else if (ib==2 && ic < (int)sizeof(lua_Integer)*8-1) *r= ((lua_Integer)1)<<ic; /* 1,2,4,...2^30 | 2^62 optimization */ ++ else if (ic==0) *r=1; ++ else if (luai_abs(ib)==1) *r= (ic%2) ? ib:1; ++ else { ++ lua_Integer x= ib; ++ while( --ic ) { ++ if (!try_mulint( &x, x, ib )) ++ return 0; /* FP realm */ ++ } ++ *r= x; ++ } ++ return 1; ++} ++ ++int try_unmint( lua_Integer *r, lua_Integer ib ) { ++ /* Negating LUA_INTEGER_MIN leaves the range. */ ++ if ( ib != LUA_INTEGER_MIN ) ++ { *r= -ib; return 1; } ++ return 0; ++} ++ +--- /dev/null ++++ b/src/lnum.h +@@ -0,0 +1,116 @@ ++/* ++** $Id: lnum.h,v ... $ ++** Internal Number model ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lnum_h ++#define lnum_h ++ ++#include <math.h> ++ ++#include "lobject.h" ++ ++/* ++** The luai_num* macros define the primitive operations over 'lua_Number's ++** (not 'lua_Integer's, not 'lua_Complex'). ++*/ ++#define luai_numadd(a,b) ((a)+(b)) ++#define luai_numsub(a,b) ((a)-(b)) ++#define luai_nummul(a,b) ((a)*(b)) ++#define luai_numdiv(a,b) ((a)/(b)) ++#define luai_nummod(a,b) ((a) - _LF(floor)((a)/(b))*(b)) ++#define luai_numpow(a,b) (_LF(pow)(a,b)) ++#define luai_numunm(a) (-(a)) ++#define luai_numeq(a,b) ((a)==(b)) ++#define luai_numlt(a,b) ((a)<(b)) ++#define luai_numle(a,b) ((a)<=(b)) ++#define luai_numisnan(a) (!luai_numeq((a), (a))) ++ ++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); ++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); ++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); ++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); ++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); ++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); ++int try_unmint( lua_Integer *r, lua_Integer ib ); ++ ++#ifdef LNUM_COMPLEX ++ static inline lua_Complex luai_vectunm( lua_Complex a ) { return -a; } ++ static inline lua_Complex luai_vectadd( lua_Complex a, lua_Complex b ) { return a+b; } ++ static inline lua_Complex luai_vectsub( lua_Complex a, lua_Complex b ) { return a-b; } ++ static inline lua_Complex luai_vectmul( lua_Complex a, lua_Complex b ) { return a*b; } ++ static inline lua_Complex luai_vectdiv( lua_Complex a, lua_Complex b ) { return a/b; } ++ ++/* ++ * C99 does not provide modulus for complex numbers. It most likely is not ++ * meaningful at all. ++ */ ++ ++/* ++ * Complex power ++ * ++ * C99 'cpow' gives inaccurate results for many common cases s.a. (1i)^2 -> ++ * -1+1.2246467991474e-16i (OS X 10.4, gcc 4.0.1 build 5367) ++ * ++ * [(a+bi)^(c+di)] = (r^c) * exp(-d*t) * cos(c*t + d*ln(r)) + ++ * = (r^c) * exp(-d*t) * sin(c*t + d*ln(r)) *i ++ * r = sqrt(a^2+b^2), t = arctan( b/a ) ++ * ++ * Reference: <http://home.att.net/~srschmitt/complexnumbers.html> ++ * Could also be calculated using: x^y = exp(ln(x)*y) ++ * ++ * Note: Defined here (and not in .c) so 'lmathlib.c' can share the ++ * implementation. ++ */ ++ static inline ++ lua_Complex luai_vectpow( lua_Complex a, lua_Complex b ) ++ { ++# if 1 ++ lua_Number ar= _LF(creal)(a), ai= _LF(cimag)(a); ++ lua_Number br= _LF(creal)(b), bi= _LF(cimag)(b); ++ ++ if (ai==0 && bi==0) { /* a^c (real) */ ++ return luai_numpow( ar, br ); ++ } ++ ++ int br_int= (int)br; ++ ++ if ( ai!=0 && bi==0 && br_int==br && br_int!=0 && br_int!=INT_MIN ) { ++ /* (a+bi)^N, N = { +-1,+-2, ... +-INT_MAX } ++ */ ++ lua_Number k= luai_numpow( _LF(sqrt) (ar*ar + ai*ai), br ); ++ lua_Number cos_z, sin_z; ++ ++ /* Situation depends upon c (N) in the following manner: ++ * ++ * N%4==0 => cos(c*t)=1, sin(c*t)=0 ++ * (N*sign(b))%4==1 or (N*sign(b))%4==-3 => cos(c*t)=0, sin(c*t)=1 ++ * N%4==2 or N%4==-2 => cos(c*t)=-1, sin(c*t)=0 ++ * (N*sign(b))%4==-1 or (N*sign(b))%4==3 => cos(c*t)=0, sin(c*t)=-1 ++ */ ++ int br_int_abs = br_int<0 ? -br_int:br_int; ++ ++ switch( (br_int_abs%4) * (br_int<0 ? -1:1) * (ai<0 ? -1:1) ) { ++ case 0: cos_z=1, sin_z=0; break; ++ case 2: case -2: cos_z=-1, sin_z=0; break; ++ case 1: case -3: cos_z=0, sin_z=1; break; ++ case 3: case -1: cos_z=0, sin_z=-1; break; ++ default: lua_assert(0); return 0; ++ } ++ return k*cos_z + (k*sin_z)*I; ++ } ++# endif ++ return _LF(cpow) ( a, b ); ++ } ++#endif ++ ++LUAI_FUNC int luaO_str2d (const char *s, lua_Number *res1, lua_Integer *res2); ++LUAI_FUNC void luaO_num2buf( char *s, const TValue *o ); ++ ++LUAI_FUNC int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref ); ++ ++#define luai_normalize(o) \ ++{ lua_Integer _i; if (tt_integer_valued(o,&_i)) setivalue(o,_i); } ++ ++#endif +--- /dev/null ++++ b/src/lnum_config.h +@@ -0,0 +1,221 @@ ++/* ++** $Id: lnum_config.h,v ... $ ++** Internal Number model ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lnum_config_h ++#define lnum_config_h ++ ++/* ++** Default number modes ++*/ ++#if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE) ++# define LNUM_FLOAT ++#endif ++#if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64) ++# define LNUM_INT32 ++#endif ++ ++/* ++** Require C99 mode for COMPLEX, FLOAT and LDOUBLE (only DOUBLE is ANSI C). ++*/ ++#if defined(LNUM_COMPLEX) && (__STDC_VERSION__ < 199901L) ++# error "Need C99 for complex (use '--std=c99' or similar)" ++#elif defined(LNUM_LDOUBLE) && (__STDC_VERSION__ < 199901L) && !defined(_MSC_VER) ++# error "Need C99 for 'long double' (use '--std=c99' or similar)" ++#elif defined(LNUM_FLOAT) && (__STDC_VERSION__ < 199901L) ++/* LNUM_FLOAT not supported on Windows */ ++# error "Need C99 for 'float' (use '--std=c99' or similar)" ++#endif ++ ++/* ++** Number mode identifier to accompany the version string. ++*/ ++#ifdef LNUM_COMPLEX ++# define _LNUM1 "complex " ++#else ++# define _LNUM1 "" ++#endif ++#ifdef LNUM_DOUBLE ++# define _LNUM2 "double" ++#elif defined(LNUM_FLOAT) ++# define _LNUM2 "float" ++#elif defined(LNUM_LDOUBLE) ++# define _LNUM2 "ldouble" ++#endif ++#ifdef LNUM_INT32 ++# define _LNUM3 "int32" ++#elif defined(LNUM_INT64) ++# define _LNUM3 "int64" ++#elif defined(LNUM_INT16) ++# define _LNUM3 "int16" ++#endif ++#define LUA_LNUM _LNUM1 _LNUM2 " " _LNUM3 ++ ++/* ++** LUA_NUMBER is the type of floating point number in Lua ++** LUA_NUMBER_SCAN is the format for reading numbers. ++** LUA_NUMBER_FMT is the format for writing numbers. ++*/ ++#ifdef LNUM_FLOAT ++# define LUA_NUMBER float ++# define LUA_NUMBER_SCAN "%f" ++# define LUA_NUMBER_FMT "%g" ++#elif (defined LNUM_DOUBLE) ++# define LUA_NUMBER double ++# define LUA_NUMBER_SCAN "%lf" ++# define LUA_NUMBER_FMT "%.14g" ++#elif (defined LNUM_LDOUBLE) ++# define LUA_NUMBER long double ++# define LUA_NUMBER_SCAN "%Lg" ++# define LUA_NUMBER_FMT "%.20Lg" ++#endif ++ ++ ++/* ++** LUAI_MAXNUMBER2STR: size of a buffer fitting any number->string result. ++** ++** double: 24 (sign, x.xxxxxxxxxxxxxxe+nnnn, and \0) ++** int64: 21 (19 digits, sign, and \0) ++** long double: 43 for 128-bit (sign, x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxe+nnnn, and \0) ++** 30 for 80-bit (sign, x.xxxxxxxxxxxxxxxxxxxxe+nnnn, and \0) ++*/ ++#ifdef LNUM_LDOUBLE ++# define _LUAI_MN2S 44 ++#else ++# define _LUAI_MN2S 24 ++#endif ++ ++#ifdef LNUM_COMPLEX ++# define LUAI_MAXNUMBER2STR (2*_LUAI_MN2S) ++#else ++# define LUAI_MAXNUMBER2STR _LUAI_MN2S ++#endif ++ ++/* ++** LUA_INTEGER is the integer type used by lua_pushinteger/lua_tointeger/lua_isinteger. ++** LUA_INTEGER_SCAN is the format for reading integers ++** LUA_INTEGER_FMT is the format for writing integers ++** ++** Note: Visual C++ 2005 does not have 'strtoull()', use '_strtoui64()' instead. ++*/ ++#ifdef LNUM_INT32 ++# if LUAI_BITSINT > 16 ++# define LUA_INTEGER int ++# define LUA_INTEGER_SCAN "%d" ++# define LUA_INTEGER_FMT "%d" ++# else ++/* Note: 'LUA_INTEGER' being 'ptrdiff_t' (as in Lua 5.1) causes problems with ++ * 'printf()' operations. Also 'unsigned ptrdiff_t' is invalid. ++ */ ++# define LUA_INTEGER long ++# define LUA_INTEGER_SCAN "%ld" ++# define LUA_INTEGER_FMT "%ld" ++# endif ++# define LUA_INTEGER_MAX 0x7FFFFFFF /* 2^31-1 */ ++/* */ ++#elif defined(LNUM_INT64) ++# define LUA_INTEGER long long ++# ifdef _MSC_VER ++# define lua_str2ul _strtoui64 ++# else ++# define lua_str2ul strtoull ++# endif ++# define LUA_INTEGER_SCAN "%lld" ++# define LUA_INTEGER_FMT "%lld" ++# define LUA_INTEGER_MAX 0x7fffffffffffffffLL /* 2^63-1 */ ++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX - 1LL) /* -2^63 */ ++/* */ ++#elif defined(LNUM_INT16) ++# if LUAI_BITSINT > 16 ++# define LUA_INTEGER short ++# define LUA_INTEGER_SCAN "%hd" ++# define LUA_INTEGER_FMT "%hd" ++# else ++# define LUA_INTEGER int ++# define LUA_INTEGER_SCAN "%d" ++# define LUA_INTEGER_FMT "%d" ++# endif ++# define LUA_INTEGER_MAX 0x7FFF /* 2^16-1 */ ++#endif ++ ++#ifndef lua_str2ul ++# define lua_str2ul (unsigned LUA_INTEGER)strtoul ++#endif ++#ifndef LUA_INTEGER_MIN ++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1) /* -2^16|32 */ ++#endif ++ ++/* ++@@ lua_number2int is a macro to convert lua_Number to int. ++@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. ++** CHANGE them if you know a faster way to convert a lua_Number to ++** int (with any rounding method and without throwing errors) in your ++** system. In Pentium machines, a naive typecast from double to int ++** in C is extremely slow, so any alternative is worth trying. ++*/ ++ ++/* On a Pentium, resort to a trick */ ++#if defined(LNUM_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ ++ (defined(__i386) || defined (_M_IX86) || defined(__i386__)) ++ ++/* On a Microsoft compiler, use assembler */ ++# if defined(_MSC_VER) ++# define lua_number2int(i,d) __asm fld d __asm fistp i ++# else ++ ++/* the next trick should work on any Pentium, but sometimes clashes ++ with a DirectX idiosyncrasy */ ++union luai_Cast { double l_d; long l_l; }; ++# define lua_number2int(i,d) \ ++ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } ++# endif ++ ++# ifndef LNUM_INT64 ++# define lua_number2integer lua_number2int ++# endif ++ ++/* this option always works, but may be slow */ ++#else ++# define lua_number2int(i,d) ((i)=(int)(d)) ++#endif ++ ++/* Note: Some compilers (OS X gcc 4.0?) may choke on double->long long conversion ++ * since it can lose precision. Others do require 'long long' there. ++ */ ++#ifndef lua_number2integer ++# define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) ++#endif ++ ++/* ++** 'luai_abs()' to give absolute value of 'lua_Integer' ++*/ ++#ifdef LNUM_INT32 ++# define luai_abs abs ++#elif defined(LNUM_INT64) && (__STDC_VERSION__ >= 199901L) ++# define luai_abs llabs ++#else ++# define luai_abs(v) ((v) >= 0 ? (v) : -(v)) ++#endif ++ ++/* ++** LUAI_UACNUMBER is the result of an 'usual argument conversion' over a number. ++** LUAI_UACINTEGER the same, over an integer. ++*/ ++#define LUAI_UACNUMBER double ++#define LUAI_UACINTEGER long ++ ++/* ANSI C only has math funcs for 'double. C99 required for float and long double ++ * variants. ++ */ ++#ifdef LNUM_DOUBLE ++# define _LF(name) name ++#elif defined(LNUM_FLOAT) ++# define _LF(name) name ## f ++#elif defined(LNUM_LDOUBLE) ++# define _LF(name) name ## l ++#endif ++ ++#endif ++ +--- a/src/lobject.c ++++ b/src/lobject.c +@@ -21,7 +21,8 @@ + #include "lstate.h" + #include "lstring.h" + #include "lvm.h" +- ++#include "llex.h" ++#include "lnum.h" + + + const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; +@@ -70,12 +71,31 @@ int luaO_log2 (unsigned int x) { + + + int luaO_rawequalObj (const TValue *t1, const TValue *t2) { +- if (ttype(t1) != ttype(t2)) return 0; ++ if (!ttype_ext_same(t1,t2)) return 0; + else switch (ttype(t1)) { + case LUA_TNIL: + return 1; ++ case LUA_TINT: ++ if (ttype(t2)==LUA_TINT) ++ return ivalue(t1) == ivalue(t2); ++ else { /* t1:int, t2:num */ ++#ifdef LNUM_COMPLEX ++ if (nvalue_img_fast(t2) != 0) return 0; ++#endif ++ /* Avoid doing accuracy losing cast, if possible. */ ++ lua_Integer tmp; ++ if (tt_integer_valued(t2,&tmp)) ++ return ivalue(t1) == tmp; ++ else ++ return luai_numeq( cast_num(ivalue(t1)), nvalue_fast(t2) ); ++ } + case LUA_TNUMBER: +- return luai_numeq(nvalue(t1), nvalue(t2)); ++ if (ttype(t2)==LUA_TINT) ++ return luaO_rawequalObj(t2, t1); /* swap LUA_TINT to left */ ++#ifdef LNUM_COMPLEX ++ if (!luai_numeq(nvalue_img_fast(t1), nvalue_img_fast(t2))) return 0; ++#endif ++ return luai_numeq(nvalue_fast(t1), nvalue_fast(t2)); + case LUA_TBOOLEAN: + return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ + case LUA_TLIGHTUSERDATA: +@@ -86,21 +106,6 @@ int luaO_rawequalObj (const TValue *t1, + } + } + +- +-int luaO_str2d (const char *s, lua_Number *result) { +- char *endptr; +- *result = lua_str2number(s, &endptr); +- if (endptr == s) return 0; /* conversion failed */ +- if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ +- *result = cast_num(strtoul(s, &endptr, 16)); +- if (*endptr == '\0') return 1; /* most common case */ +- while (isspace(cast(unsigned char, *endptr))) endptr++; +- if (*endptr != '\0') return 0; /* invalid trailing characters? */ +- return 1; +-} +- +- +- + static void pushstr (lua_State *L, const char *str) { + setsvalue2s(L, L->top, luaS_new(L, str)); + incr_top(L); +@@ -131,7 +136,11 @@ const char *luaO_pushvfstring (lua_State + break; + } + case 'd': { +- setnvalue(L->top, cast_num(va_arg(argp, int))); ++ /* This is tricky for 64-bit integers; maybe they even cannot be ++ * supported on all compilers; depends on the conversions applied to ++ * variable argument lists. TBD: test! ++ */ ++ setivalue(L->top, (lua_Integer) va_arg(argp, l_uacInteger)); + incr_top(L); + break; + } +@@ -212,3 +221,4 @@ void luaO_chunkid (char *out, const char + } + } + } ++ +--- a/src/lobject.h ++++ b/src/lobject.h +@@ -17,7 +17,11 @@ + + + /* tags for values visible from Lua */ +-#define LAST_TAG LUA_TTHREAD ++#if LUA_TINT > LUA_TTHREAD ++# define LAST_TAG LUA_TINT ++#else ++# define LAST_TAG LUA_TTHREAD ++#endif + + #define NUM_TAGS (LAST_TAG+1) + +@@ -59,7 +63,12 @@ typedef struct GCheader { + typedef union { + GCObject *gc; + void *p; ++#ifdef LNUM_COMPLEX ++ lua_Complex n; ++#else + lua_Number n; ++#endif ++ lua_Integer i; + int b; + } Value; + +@@ -77,7 +86,11 @@ typedef struct lua_TValue { + + /* Macros to test type */ + #define ttisnil(o) (ttype(o) == LUA_TNIL) +-#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) ++#define ttisint(o) (ttype(o) == LUA_TINT) ++#define ttisnumber(o) ((ttype(o) == LUA_TINT) || (ttype(o) == LUA_TNUMBER)) ++#ifdef LNUM_COMPLEX ++# define ttiscomplex(o) ((ttype(o) == LUA_TNUMBER) && (nvalue_img_fast(o)!=0)) ++#endif + #define ttisstring(o) (ttype(o) == LUA_TSTRING) + #define ttistable(o) (ttype(o) == LUA_TTABLE) + #define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) +@@ -90,7 +103,25 @@ typedef struct lua_TValue { + #define ttype(o) ((o)->tt) + #define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) + #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) +-#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) ++ ++#define ttype_ext(o) ( ttype(o) == LUA_TINT ? LUA_TNUMBER : ttype(o) ) ++#define ttype_ext_same(o1,o2) ( (ttype(o1)==ttype(o2)) || (ttisnumber(o1) && ttisnumber(o2)) ) ++ ++/* '_fast' variants are for cases where 'ttype(o)' is known to be LUA_TNUMBER. ++ */ ++#ifdef LNUM_COMPLEX ++# define nvalue_complex_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n ) ++# define nvalue_fast(o) ( _LF(creal) ( nvalue_complex_fast(o) ) ) ++# define nvalue_img_fast(o) ( _LF(cimag) ( nvalue_complex_fast(o) ) ) ++# define nvalue_complex(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? (o)->value.i : (o)->value.n ) ++# define nvalue_img(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? 0 : _LF(cimag)( (o)->value.n ) ) ++# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : _LF(creal)((o)->value.n) ) ++#else ++# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : (o)->value.n ) ++# define nvalue_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n ) ++#endif ++#define ivalue(o) check_exp( ttype(o)==LUA_TINT, (o)->value.i ) ++ + #define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) + #define tsvalue(o) (&rawtsvalue(o)->tsv) + #define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) +@@ -116,8 +147,27 @@ typedef struct lua_TValue { + /* Macros to set values */ + #define setnilvalue(obj) ((obj)->tt=LUA_TNIL) + +-#define setnvalue(obj,x) \ +- { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } ++/* Must not have side effects, 'x' may be expression. ++*/ ++#define setivalue(obj,x) \ ++ { TValue *i_o=(obj); i_o->value.i=(x); i_o->tt=LUA_TINT; } ++ ++# define setnvalue(obj,x) \ ++ { TValue *i_o=(obj); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; } ++ ++/* Note: Complex always has "inline", both are C99. ++*/ ++#ifdef LNUM_COMPLEX ++ static inline void setnvalue_complex_fast( TValue *obj, lua_Complex x ) { ++ lua_assert( _LF(cimag)(x) != 0 ); ++ obj->value.n= x; obj->tt= LUA_TNUMBER; ++ } ++ static inline void setnvalue_complex( TValue *obj, lua_Complex x ) { ++ if (_LF(cimag)(x) == 0) { setnvalue(obj, _LF(creal)(x)); } ++ else { obj->value.n= x; obj->tt= LUA_TNUMBER; } ++ } ++#endif ++ + + #define setpvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } +@@ -155,9 +205,6 @@ typedef struct lua_TValue { + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ + checkliveness(G(L),i_o); } + +- +- +- + #define setobj(L,obj1,obj2) \ + { const TValue *o2=(obj2); TValue *o1=(obj1); \ + o1->value = o2->value; o1->tt=o2->tt; \ +@@ -185,8 +232,11 @@ typedef struct lua_TValue { + + #define setttype(obj, tt) (ttype(obj) = (tt)) + +- +-#define iscollectable(o) (ttype(o) >= LUA_TSTRING) ++#if LUA_TINT >= LUA_TSTRING ++# define iscollectable(o) ((ttype(o) >= LUA_TSTRING) && (ttype(o) != LUA_TINT)) ++#else ++# define iscollectable(o) (ttype(o) >= LUA_TSTRING) ++#endif + + + +@@ -370,12 +420,10 @@ LUAI_FUNC int luaO_log2 (unsigned int x) + LUAI_FUNC int luaO_int2fb (unsigned int x); + LUAI_FUNC int luaO_fb2int (int x); + LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); +-LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); + LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, + va_list argp); + LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); + LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); + +- + #endif + +--- a/src/loslib.c ++++ b/src/loslib.c +@@ -186,15 +186,30 @@ static int os_time (lua_State *L) { + } + if (t == (time_t)(-1)) + lua_pushnil(L); +- else +- lua_pushnumber(L, (lua_Number)t); ++ else { ++ /* On float systems the pushed value must be an integer, NOT a number. ++ * Otherwise, accuracy is lost in the time_t->float conversion. ++ */ ++#ifdef LNUM_FLOAT ++ lua_pushinteger(L, (lua_Integer) t); ++#else ++ lua_pushnumber(L, (lua_Number) t); ++#endif ++ } + return 1; + } + + + static int os_difftime (lua_State *L) { ++#ifdef LNUM_FLOAT ++ lua_Integer i= (lua_Integer) ++ difftime( (time_t)(luaL_checkinteger(L, 1)), ++ (time_t)(luaL_optinteger(L, 2, 0))); ++ lua_pushinteger(L, i); ++#else + lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), + (time_t)(luaL_optnumber(L, 2, 0)))); ++#endif + return 1; + } + +--- a/src/lparser.c ++++ b/src/lparser.c +@@ -33,7 +33,6 @@ + + #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) + +- + /* + ** nodes for block list (list of active blocks) + */ +@@ -72,7 +71,7 @@ static void errorlimit (FuncState *fs, i + const char *msg = (fs->f->linedefined == 0) ? + luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : + luaO_pushfstring(fs->L, "function at line %d has more than %d %s", +- fs->f->linedefined, limit, what); ++ (fs->f->linedefined), limit, what); + luaX_lexerror(fs->ls, msg, 0); + } + +@@ -733,6 +732,18 @@ static void simpleexp (LexState *ls, exp + v->u.nval = ls->t.seminfo.r; + break; + } ++ case TK_INT: { ++ init_exp(v, VKINT, 0); ++ v->u.ival = ls->t.seminfo.i; ++ break; ++ } ++#ifdef LNUM_COMPLEX ++ case TK_NUMBER2: { ++ init_exp(v, VKNUM2, 0); ++ v->u.nval = ls->t.seminfo.r; ++ break; ++ } ++#endif + case TK_STRING: { + codestring(ls, v, ls->t.seminfo.ts); + break; +@@ -1079,7 +1090,7 @@ static void fornum (LexState *ls, TStrin + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else { /* default step = 1 */ +- luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); ++ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_integerK(fs, 1)); + luaK_reserveregs(fs, 1); + } + forbody(ls, base, line, 1, 1); +--- a/src/lparser.h ++++ b/src/lparser.h +@@ -31,7 +31,11 @@ typedef enum { + VRELOCABLE, /* info = instruction pc */ + VNONRELOC, /* info = result register */ + VCALL, /* info = instruction pc */ +- VVARARG /* info = instruction pc */ ++ VVARARG, /* info = instruction pc */ ++ VKINT /* ival = integer value */ ++#ifdef LNUM_COMPLEX ++ ,VKNUM2 /* nval = imaginary value */ ++#endif + } expkind; + + typedef struct expdesc { +@@ -39,6 +43,7 @@ typedef struct expdesc { + union { + struct { int info, aux; } s; + lua_Number nval; ++ lua_Integer ival; + } u; + int t; /* patch list of `exit when true' */ + int f; /* patch list of `exit when false' */ +--- a/src/lstrlib.c ++++ b/src/lstrlib.c +@@ -43,8 +43,8 @@ static ptrdiff_t posrelat (ptrdiff_t pos + static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); +- ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); +- ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); ++ ptrdiff_t start = posrelat(luaL_checkint32(L, 2), l); ++ ptrdiff_t end = posrelat(luaL_optint32(L, 3, -1), l); + if (start < 1) start = 1; + if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; + if (start <= end) +@@ -106,8 +106,8 @@ static int str_rep (lua_State *L) { + static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); +- ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); +- ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); ++ ptrdiff_t posi = posrelat(luaL_optint32(L, 2, 1), l); ++ ptrdiff_t pose = posrelat(luaL_optint32(L, 3, posi), l); + int n, i; + if (posi <= 0) posi = 1; + if ((size_t)pose > l) pose = l; +@@ -496,7 +496,7 @@ static int str_find_aux (lua_State *L, i + size_t l1, l2; + const char *s = luaL_checklstring(L, 1, &l1); + const char *p = luaL_checklstring(L, 2, &l2); +- ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; ++ ptrdiff_t init = posrelat(luaL_optint32(L, 3, 1), l1) - 1; + if (init < 0) init = 0; + else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; + if (find && (lua_toboolean(L, 4) || /* explicit request? */ +@@ -690,7 +690,7 @@ static int str_gsub (lua_State *L) { + ** maximum size of each format specification (such as '%-099.99d') + ** (+10 accounts for %99.99x plus margin of error) + */ +-#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) ++#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTEGER_FMT)-2 + 10) + + + static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { +@@ -747,9 +747,9 @@ static const char *scanformat (lua_State + static void addintlen (char *form) { + size_t l = strlen(form); + char spec = form[l - 1]; +- strcpy(form + l - 1, LUA_INTFRMLEN); +- form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; +- form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; ++ const char *tmp= LUA_INTEGER_FMT; /* "%lld" or "%ld" */ ++ strcpy(form + l - 1, tmp+1); ++ form[l + sizeof(LUA_INTEGER_FMT)-4] = spec; + } + + +@@ -779,12 +779,12 @@ static int str_format (lua_State *L) { + } + case 'd': case 'i': { + addintlen(form); +- sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); ++ sprintf(buff, form, luaL_checkinteger(L, arg)); + break; + } + case 'o': case 'u': case 'x': case 'X': { + addintlen(form); +- sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); ++ sprintf(buff, form, (unsigned LUA_INTEGER)luaL_checkinteger(L, arg)); + break; + } + case 'e': case 'E': case 'f': +--- a/src/ltable.c ++++ b/src/ltable.c +@@ -33,6 +33,7 @@ + #include "lobject.h" + #include "lstate.h" + #include "ltable.h" ++#include "lnum.h" + + + /* +@@ -51,25 +52,15 @@ + + #define hashstr(t,str) hashpow2(t, (str)->tsv.hash) + #define hashboolean(t,p) hashpow2(t, p) +- ++#define hashint(t,i) hashpow2(t,i) + + /* + ** for some types, it is better to avoid modulus by power of 2, as + ** they tend to have many 2 factors. + */ + #define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) +- +- + #define hashpointer(t,p) hashmod(t, IntPoint(p)) + +- +-/* +-** number of ints inside a lua_Number +-*/ +-#define numints cast_int(sizeof(lua_Number)/sizeof(int)) +- +- +- + #define dummynode (&dummynode_) + + static const Node dummynode_ = { +@@ -80,27 +71,46 @@ static const Node dummynode_ = { + + /* + ** hash for lua_Numbers ++** ++** for non-complex modes, never called with 'lua_Integer' value range (s.a. 0) + */ + static Node *hashnum (const Table *t, lua_Number n) { +- unsigned int a[numints]; +- int i; +- if (luai_numeq(n, 0)) /* avoid problems with -0 */ +- return gnode(t, 0); +- memcpy(a, &n, sizeof(a)); +- for (i = 1; i < numints; i++) a[0] += a[i]; +- return hashmod(t, a[0]); ++ const unsigned int *p= cast(const unsigned int *,&n); ++ unsigned int sum= *p; ++ unsigned int m= sizeof(lua_Number)/sizeof(int); ++ unsigned int i; ++ /* OS X Intel has 'm'==4 and gives "Bus error" if the last integer of ++ * 'n' is read; the actual size of long double is only 80 bits = 10 bytes. ++ * Linux x86 has 'm'==3, and does not require reduction. ++ */ ++#if defined(LNUM_LDOUBLE) && defined(__i386__) ++ if (m>3) m--; ++#endif ++ for (i = 1; i < m; i++) sum += p[i]; ++ return hashmod(t, sum); + } + + +- + /* + ** returns the `main' position of an element in a table (that is, the index + ** of its hash value) ++** ++** Floating point numbers with integer value give the hash position of the ++** integer (so they use the same table position). + */ + static Node *mainposition (const Table *t, const TValue *key) { ++ lua_Integer i; + switch (ttype(key)) { + case LUA_TNUMBER: +- return hashnum(t, nvalue(key)); ++ if (tt_integer_valued(key,&i)) ++ return hashint(t, i); ++#ifdef LNUM_COMPLEX ++ if (nvalue_img_fast(key)!=0 && luai_numeq(nvalue_fast(key),0)) ++ return gnode(t, 0); /* 0 and -0 to give same hash */ ++#endif ++ return hashnum(t, nvalue_fast(key)); ++ case LUA_TINT: ++ return hashint(t, ivalue(key)); + case LUA_TSTRING: + return hashstr(t, rawtsvalue(key)); + case LUA_TBOOLEAN: +@@ -116,16 +126,20 @@ static Node *mainposition (const Table * + /* + ** returns the index for `key' if `key' is an appropriate key to live in + ** the array part of the table, -1 otherwise. ++** ++** Anything <=0 is taken as not being in the array part. + */ +-static int arrayindex (const TValue *key) { +- if (ttisnumber(key)) { +- lua_Number n = nvalue(key); +- int k; +- lua_number2int(k, n); +- if (luai_numeq(cast_num(k), n)) +- return k; ++static int arrayindex (const TValue *key, int max) { ++ lua_Integer k; ++ switch( ttype(key) ) { ++ case LUA_TINT: ++ k= ivalue(key); break; ++ case LUA_TNUMBER: ++ if (tt_integer_valued(key,&k)) break; ++ default: ++ return -1; /* not to be used as array index */ + } +- return -1; /* `key' did not match some condition */ ++ return ((k>0) && (k <= max)) ? cast_int(k) : -1; + } + + +@@ -137,8 +151,8 @@ static int arrayindex (const TValue *key + static int findindex (lua_State *L, Table *t, StkId key) { + int i; + if (ttisnil(key)) return -1; /* first iteration */ +- i = arrayindex(key); +- if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ ++ i = arrayindex(key, t->sizearray); ++ if (i>0) /* inside array part? */ + return i-1; /* yes; that's the index (corrected to C) */ + else { + Node *n = mainposition(t, key); +@@ -163,7 +177,7 @@ int luaH_next (lua_State *L, Table *t, S + int i = findindex(L, t, key); /* find original element */ + for (i++; i < t->sizearray; i++) { /* try first array part */ + if (!ttisnil(&t->array[i])) { /* a non-nil value? */ +- setnvalue(key, cast_num(i+1)); ++ setivalue(key, i+1); + setobj2s(L, key+1, &t->array[i]); + return 1; + } +@@ -209,8 +223,8 @@ static int computesizes (int nums[], int + + + static int countint (const TValue *key, int *nums) { +- int k = arrayindex(key); +- if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ ++ int k = arrayindex(key,MAXASIZE); ++ if (k>0) { /* appropriate array index? */ + nums[ceillog2(k)]++; /* count as such */ + return 1; + } +@@ -308,7 +322,7 @@ static void resize (lua_State *L, Table + /* re-insert elements from vanishing slice */ + for (i=nasize; i<oldasize; i++) { + if (!ttisnil(&t->array[i])) +- setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); ++ setobjt2t(L, luaH_setint(L, t, i+1), &t->array[i]); + } + /* shrink array */ + luaM_reallocvector(L, t->array, oldasize, nasize, TValue); +@@ -409,7 +423,9 @@ static TValue *newkey (lua_State *L, Tab + othern = mainposition(t, key2tval(mp)); + if (othern != mp) { /* is colliding node out of its main position? */ + /* yes; move colliding node into free position */ +- while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ ++ while (gnext(othern) != mp) { ++ othern = gnext(othern); /* find previous */ ++ } + gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ + *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + gnext(mp) = NULL; /* now `mp' is free */ +@@ -432,17 +448,18 @@ static TValue *newkey (lua_State *L, Tab + /* + ** search function for integers + */ +-const TValue *luaH_getnum (Table *t, int key) { ++const TValue *luaH_getint (Table *t, lua_Integer key) { + /* (1 <= key && key <= t->sizearray) */ + if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) + return &t->array[key-1]; + else { +- lua_Number nk = cast_num(key); +- Node *n = hashnum(t, nk); ++ Node *n = hashint(t, key); + do { /* check whether `key' is somewhere in the chain */ +- if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) ++ if (ttisint(gkey(n)) && (ivalue(gkey(n)) == key)) { + return gval(n); /* that's it */ +- else n = gnext(n); ++ } else { ++ n = gnext(n); ++ } + } while (n); + return luaO_nilobject; + } +@@ -470,14 +487,12 @@ const TValue *luaH_get (Table *t, const + switch (ttype(key)) { + case LUA_TNIL: return luaO_nilobject; + case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); ++ case LUA_TINT: return luaH_getint(t, ivalue(key)); + case LUA_TNUMBER: { +- int k; +- lua_Number n = nvalue(key); +- lua_number2int(k, n); +- if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ +- return luaH_getnum(t, k); /* use specialized version */ +- /* else go through */ +- } ++ lua_Integer i; ++ if (tt_integer_valued(key,&i)) ++ return luaH_getint(t,i); ++ } /* pass through */ + default: { + Node *n = mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ +@@ -498,20 +513,25 @@ TValue *luaH_set (lua_State *L, Table *t + return cast(TValue *, p); + else { + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); +- else if (ttisnumber(key) && luai_numisnan(nvalue(key))) +- luaG_runerror(L, "table index is NaN"); ++ else if (ttype(key)==LUA_TNUMBER) { ++ lua_Integer k; ++ if (luai_numisnan(nvalue_fast(key))) ++ luaG_runerror(L, "table index is NaN"); ++ if (tt_integer_valued(key,&k)) ++ return luaH_setint(L, t, k); ++ } + return newkey(L, t, key); + } + } + + +-TValue *luaH_setnum (lua_State *L, Table *t, int key) { +- const TValue *p = luaH_getnum(t, key); ++TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key) { ++ const TValue *p = luaH_getint(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + TValue k; +- setnvalue(&k, cast_num(key)); ++ setivalue(&k, key); + return newkey(L, t, &k); + } + } +@@ -533,20 +553,21 @@ static int unbound_search (Table *t, uns + unsigned int i = j; /* i is zero or a present index */ + j++; + /* find `i' and `j' such that i is present and j is not */ +- while (!ttisnil(luaH_getnum(t, j))) { ++ while (!ttisnil(luaH_getint(t, j))) { + i = j; + j *= 2; + if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ + /* table was built with bad purposes: resort to linear search */ +- i = 1; +- while (!ttisnil(luaH_getnum(t, i))) i++; +- return i - 1; ++ for( i = 1; i<MAX_INT+1; i++ ) { ++ if (ttisnil(luaH_getint(t, i))) break; ++ } ++ return i - 1; /* up to MAX_INT */ + } + } + /* now do a binary search between them */ + while (j - i > 1) { + unsigned int m = (i+j)/2; +- if (ttisnil(luaH_getnum(t, m))) j = m; ++ if (ttisnil(luaH_getint(t, m))) j = m; + else i = m; + } + return i; +--- a/src/ltable.h ++++ b/src/ltable.h +@@ -18,8 +18,8 @@ + #define key2tval(n) (&(n)->i_key.tvk) + + +-LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); +-LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); ++LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); ++LUAI_FUNC TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key); + LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); + LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); + LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); +--- a/src/ltm.c ++++ b/src/ltm.c +@@ -19,7 +19,6 @@ + #include "ltm.h" + + +- + const char *const luaT_typenames[] = { + "nil", "boolean", "userdata", "number", + "string", "table", "function", "userdata", "thread", +@@ -67,6 +66,9 @@ const TValue *luaT_gettmbyobj (lua_State + case LUA_TUSERDATA: + mt = uvalue(o)->metatable; + break; ++ case LUA_TINT: ++ mt = G(L)->mt[LUA_TNUMBER]; ++ break; + default: + mt = G(L)->mt[ttype(o)]; + } +--- a/src/lua.c ++++ b/src/lua.c +@@ -16,7 +16,7 @@ + + #include "lauxlib.h" + #include "lualib.h" +- ++#include "llimits.h" + + + static lua_State *globalL = NULL; +@@ -382,6 +382,15 @@ int main (int argc, char **argv) { + l_message(argv[0], "cannot create state: not enough memory"); + return EXIT_FAILURE; + } ++ /* Checking 'sizeof(lua_Integer)' cannot be made in preprocessor on all compilers. ++ */ ++#ifdef LNUM_INT16 ++ lua_assert( sizeof(lua_Integer) == 2 ); ++#elif defined(LNUM_INT32) ++ lua_assert( sizeof(lua_Integer) == 4 ); ++#elif defined(LNUM_INT64) ++ lua_assert( sizeof(lua_Integer) == 8 ); ++#endif + s.argc = argc; + s.argv = argv; + status = lua_cpcall(L, &pmain, &s); +--- a/src/lua.h ++++ b/src/lua.h +@@ -19,7 +19,7 @@ + #define LUA_VERSION "Lua 5.1" + #define LUA_RELEASE "Lua 5.1.5" + #define LUA_VERSION_NUM 501 +-#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio" ++#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio" " (" LUA_LNUM ")" + #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" + + +@@ -71,6 +71,16 @@ typedef void * (*lua_Alloc) (void *ud, v + */ + #define LUA_TNONE (-1) + ++/* LUA_TINT is an internal type, not visible to applications. There are three ++ * potential values where it can be tweaked to (code autoadjusts to these): ++ * ++ * -2: not 'usual' type value; good since 'LUA_TINT' is not part of the API ++ * LUA_TNUMBER+1: shifts other type values upwards, breaking binary compatibility ++ * not acceptable for 5.1, maybe 5.2 onwards? ++ * 9: greater than existing (5.1) type values. ++*/ ++#define LUA_TINT (-2) ++ + #define LUA_TNIL 0 + #define LUA_TBOOLEAN 1 + #define LUA_TLIGHTUSERDATA 2 +@@ -139,6 +149,8 @@ LUA_API int (lua_isuserdata) + LUA_API int (lua_type) (lua_State *L, int idx); + LUA_API const char *(lua_typename) (lua_State *L, int tp); + ++LUA_API int (lua_isinteger) (lua_State *L, int idx); ++ + LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); + LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); + LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); +@@ -244,6 +256,19 @@ LUA_API lua_Alloc (lua_getallocf) (lua_S + LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); + + ++/* ++* It is unnecessary to break Lua C API 'lua_tonumber()' compatibility, just ++* because the Lua number type is complex. Most C modules would use scalars ++* only. We'll introduce new 'lua_tocomplex' and 'lua_pushcomplex' for when ++* the module really wants to use them. ++*/ ++#ifdef LNUM_COMPLEX ++ #include <complex.h> ++ typedef LUA_NUMBER complex lua_Complex; ++ LUA_API lua_Complex (lua_tocomplex) (lua_State *L, int idx); ++ LUA_API void (lua_pushcomplex) (lua_State *L, lua_Complex v); ++#endif ++ + + /* + ** =============================================================== +@@ -268,7 +293,12 @@ LUA_API void lua_setallocf (lua_State *L + #define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) + #define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) + #define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +-#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) ++ ++#if LUA_TINT < 0 ++# define lua_isnoneornil(L, n) ( (lua_type(L,(n)) <= 0) && (lua_type(L,(n)) != LUA_TINT) ) ++#else ++# define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) ++#endif + + #define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) +@@ -386,3 +416,4 @@ struct lua_Debug { + + + #endif ++ +--- a/src/luaconf.h ++++ b/src/luaconf.h +@@ -10,7 +10,9 @@ + + #include <limits.h> + #include <stddef.h> +- ++#ifdef lua_assert ++# include <assert.h> ++#endif + + /* + ** ================================================================== +@@ -136,14 +138,38 @@ + + + /* +-@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. +-** CHANGE that if ptrdiff_t is not adequate on your machine. (On most +-** machines, ptrdiff_t gives a good choice between int or long.) ++@@ LUAI_BITSINT defines the number of bits in an int. ++** CHANGE here if Lua cannot automatically detect the number of bits of ++** your machine. Probably you do not need to change this. + */ +-#define LUA_INTEGER ptrdiff_t ++/* avoid overflows in comparison */ ++#if INT_MAX-20 < 32760 ++#define LUAI_BITSINT 16 ++#elif INT_MAX > 2147483640L ++/* int has at least 32 bits */ ++#define LUAI_BITSINT 32 ++#else ++#error "you must define LUA_BITSINT with number of bits in an integer" ++#endif + + + /* ++@@ LNUM_DOUBLE | LNUM_FLOAT | LNUM_LDOUBLE: Generic Lua number mode ++@@ LNUM_INT32 | LNUM_INT64: Integer type ++@@ LNUM_COMPLEX: Define for using 'a+bi' numbers ++@@ ++@@ You can combine LNUM_xxx but only one of each group. I.e. '-DLNUM_FLOAT ++@@ -DLNUM_INT32 -DLNUM_COMPLEX' gives float range complex numbers, with ++@@ 32-bit scalar integer range optimized. ++** ++** These are kept in a separate configuration file mainly for ease of patching ++** (can be changed if integerated to Lua proper). ++*/ ++/*#define LNUM_DOUBLE*/ ++/*#define LNUM_INT32*/ ++#include "lnum_config.h" ++ ++/* + @@ LUA_API is a mark for all core API functions. + @@ LUALIB_API is a mark for all standard library functions. + ** CHANGE them if you need to define those functions in some special way. +@@ -383,22 +409,6 @@ + + + /* +-@@ LUAI_BITSINT defines the number of bits in an int. +-** CHANGE here if Lua cannot automatically detect the number of bits of +-** your machine. Probably you do not need to change this. +-*/ +-/* avoid overflows in comparison */ +-#if INT_MAX-20 < 32760 +-#define LUAI_BITSINT 16 +-#elif INT_MAX > 2147483640L +-/* int has at least 32 bits */ +-#define LUAI_BITSINT 32 +-#else +-#error "you must define LUA_BITSINT with number of bits in an integer" +-#endif +- +- +-/* + @@ LUAI_UINT32 is an unsigned integer with at least 32 bits. + @@ LUAI_INT32 is an signed integer with at least 32 bits. + @@ LUAI_UMEM is an unsigned integer big enough to count the total +@@ -425,6 +435,15 @@ + #define LUAI_MEM long + #endif + ++/* ++@@ LUAI_BOOL carries 0 and nonzero (normally 1). It may be defined as 'char' ++** (to save memory), 'int' (for speed), 'bool' (for C++) or '_Bool' (C99) ++*/ ++#ifdef __cplusplus ++# define LUAI_BOOL bool ++#else ++# define LUAI_BOOL int ++#endif + + /* + @@ LUAI_MAXCALLS limits the number of nested calls. +@@ -490,101 +509,6 @@ + /* }================================================================== */ + + +- +- +-/* +-** {================================================================== +-@@ LUA_NUMBER is the type of numbers in Lua. +-** CHANGE the following definitions only if you want to build Lua +-** with a number type different from double. You may also need to +-** change lua_number2int & lua_number2integer. +-** =================================================================== +-*/ +- +-#define LUA_NUMBER_DOUBLE +-#define LUA_NUMBER double +- +-/* +-@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' +-@* over a number. +-*/ +-#define LUAI_UACNUMBER double +- +- +-/* +-@@ LUA_NUMBER_SCAN is the format for reading numbers. +-@@ LUA_NUMBER_FMT is the format for writing numbers. +-@@ lua_number2str converts a number to a string. +-@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. +-@@ lua_str2number converts a string to a number. +-*/ +-#define LUA_NUMBER_SCAN "%lf" +-#define LUA_NUMBER_FMT "%.14g" +-#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +-#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ +-#define lua_str2number(s,p) strtod((s), (p)) +- +- +-/* +-@@ The luai_num* macros define the primitive operations over numbers. +-*/ +-#if defined(LUA_CORE) +-#include <math.h> +-#define luai_numadd(a,b) ((a)+(b)) +-#define luai_numsub(a,b) ((a)-(b)) +-#define luai_nummul(a,b) ((a)*(b)) +-#define luai_numdiv(a,b) ((a)/(b)) +-#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) +-#define luai_numpow(a,b) (pow(a,b)) +-#define luai_numunm(a) (-(a)) +-#define luai_numeq(a,b) ((a)==(b)) +-#define luai_numlt(a,b) ((a)<(b)) +-#define luai_numle(a,b) ((a)<=(b)) +-#define luai_numisnan(a) (!luai_numeq((a), (a))) +-#endif +- +- +-/* +-@@ lua_number2int is a macro to convert lua_Number to int. +-@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. +-** CHANGE them if you know a faster way to convert a lua_Number to +-** int (with any rounding method and without throwing errors) in your +-** system. In Pentium machines, a naive typecast from double to int +-** in C is extremely slow, so any alternative is worth trying. +-*/ +- +-/* On a Pentium, resort to a trick */ +-#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ +- (defined(__i386) || defined (_M_IX86) || defined(__i386__)) +- +-/* On a Microsoft compiler, use assembler */ +-#if defined(_MSC_VER) +- +-#define lua_number2int(i,d) __asm fld d __asm fistp i +-#define lua_number2integer(i,n) lua_number2int(i, n) +- +-/* the next trick should work on any Pentium, but sometimes clashes +- with a DirectX idiosyncrasy */ +-#else +- +-union luai_Cast { double l_d; long l_l; }; +-#define lua_number2int(i,d) \ +- { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } +-#define lua_number2integer(i,n) lua_number2int(i, n) +- +-#endif +- +- +-/* this option always works, but may be slow */ +-#else +-#define lua_number2int(i,d) ((i)=(int)(d)) +-#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) +- +-#endif +- +-/* }================================================================== */ +- +- + /* + @@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. + ** CHANGE it if your system requires alignments larger than double. (For +@@ -728,28 +652,6 @@ union luai_Cast { double l_d; long l_l; + #define luai_userstateyield(L,n) ((void)L) + + +-/* +-@@ LUA_INTFRMLEN is the length modifier for integer conversions +-@* in 'string.format'. +-@@ LUA_INTFRM_T is the integer type correspoding to the previous length +-@* modifier. +-** CHANGE them if your system supports long long or does not support long. +-*/ +- +-#if defined(LUA_USELONGLONG) +- +-#define LUA_INTFRMLEN "ll" +-#define LUA_INTFRM_T long long +- +-#else +- +-#define LUA_INTFRMLEN "l" +-#define LUA_INTFRM_T long +- +-#endif +- +- +- + /* =================================================================== */ + + /* +--- a/src/lundump.c ++++ b/src/lundump.c +@@ -73,6 +73,13 @@ static lua_Number LoadNumber(LoadState* + return x; + } + ++static lua_Integer LoadInteger(LoadState* S) ++{ ++ lua_Integer x; ++ LoadVar(S,x); ++ return x; ++} ++ + static TString* LoadString(LoadState* S) + { + size_t size; +@@ -119,6 +126,9 @@ static void LoadConstants(LoadState* S, + case LUA_TNUMBER: + setnvalue(o,LoadNumber(S)); + break; ++ case LUA_TINT: /* Integer type saved in bytecode (see lcode.c) */ ++ setivalue(o,LoadInteger(S)); ++ break; + case LUA_TSTRING: + setsvalue2n(S->L,o,LoadString(S)); + break; +@@ -223,5 +233,22 @@ void luaU_header (char* h) + *h++=(char)sizeof(size_t); + *h++=(char)sizeof(Instruction); + *h++=(char)sizeof(lua_Number); +- *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ ++ ++ /* ++ * Last byte of header (0/1 in unpatched Lua 5.1.3): ++ * ++ * 0: lua_Number is float or double, lua_Integer not used. (nonpatched only) ++ * 1: lua_Number is integer (nonpatched only) ++ * ++ * +2: LNUM_INT16: sizeof(lua_Integer) ++ * +4: LNUM_INT32: sizeof(lua_Integer) ++ * +8: LNUM_INT64: sizeof(lua_Integer) ++ * ++ * +0x80: LNUM_COMPLEX ++ */ ++ *h++ = (char)(sizeof(lua_Integer) ++#ifdef LNUM_COMPLEX ++ | 0x80 ++#endif ++ ); + } +--- a/src/lvm.c ++++ b/src/lvm.c +@@ -25,22 +25,35 @@ + #include "ltable.h" + #include "ltm.h" + #include "lvm.h" +- +- ++#include "llex.h" ++#include "lnum.h" + + /* limit for table tag-method chains (to avoid loops) */ + #define MAXTAGLOOP 100 + + +-const TValue *luaV_tonumber (const TValue *obj, TValue *n) { +- lua_Number num; ++/* ++ * If 'obj' is a string, it is tried to be interpreted as a number. ++ */ ++const TValue *luaV_tonumber ( const TValue *obj, TValue *n) { ++ lua_Number d; ++ lua_Integer i; ++ + if (ttisnumber(obj)) return obj; +- if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { +- setnvalue(n, num); +- return n; +- } +- else +- return NULL; ++ ++ if (ttisstring(obj)) { ++ switch( luaO_str2d( svalue(obj), &d, &i ) ) { ++ case TK_INT: ++ setivalue(n,i); return n; ++ case TK_NUMBER: ++ setnvalue(n,d); return n; ++#ifdef LNUM_COMPLEX ++ case TK_NUMBER2: /* "N.NNNi", != 0 */ ++ setnvalue_complex_fast(n, d*I); return n; ++#endif ++ } ++ } ++ return NULL; + } + + +@@ -49,8 +62,7 @@ int luaV_tostring (lua_State *L, StkId o + return 0; + else { + char s[LUAI_MAXNUMBER2STR]; +- lua_Number n = nvalue(obj); +- lua_number2str(s, n); ++ luaO_num2buf(s,obj); + setsvalue2s(L, obj, luaS_new(L, s)); + return 1; + } +@@ -222,59 +234,127 @@ static int l_strcmp (const TString *ls, + } + + ++#ifdef LNUM_COMPLEX ++void error_complex( lua_State *L, const TValue *l, const TValue *r ) ++{ ++ char buf1[ LUAI_MAXNUMBER2STR ]; ++ char buf2[ LUAI_MAXNUMBER2STR ]; ++ luaO_num2buf( buf1, l ); ++ luaO_num2buf( buf2, r ); ++ luaG_runerror( L, "unable to compare: %s with %s", buf1, buf2 ); ++ /* no return */ ++} ++#endif ++ ++ + int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { + int res; +- if (ttype(l) != ttype(r)) ++ int tl,tr; ++ lua_Integer tmp; ++ ++ if (!ttype_ext_same(l,r)) + return luaG_ordererror(L, l, r); +- else if (ttisnumber(l)) +- return luai_numlt(nvalue(l), nvalue(r)); +- else if (ttisstring(l)) +- return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; +- else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) ++#ifdef LNUM_COMPLEX ++ if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) ) ++ error_complex( L, l, r ); ++#endif ++ tl= ttype(l); tr= ttype(r); ++ if (tl==tr) { /* clear arithmetics */ ++ switch(tl) { ++ case LUA_TINT: return ivalue(l) < ivalue(r); ++ case LUA_TNUMBER: return luai_numlt(nvalue_fast(l), nvalue_fast(r)); ++ case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; ++ } ++ } else if (tl==LUA_TINT) { /* l:int, r:num */ ++ /* Avoid accuracy losing casts: if 'r' is integer by value, do comparisons ++ * in integer realm. Only otherwise cast 'l' to FP (which might change its ++ * value). ++ */ ++ if (tt_integer_valued(r,&tmp)) ++ return ivalue(l) < tmp; ++ else ++ return luai_numlt( cast_num(ivalue(l)), nvalue_fast(r) ); ++ ++ } else if (tl==LUA_TNUMBER) { /* l:num, r:int */ ++ if (tt_integer_valued(l,&tmp)) ++ return tmp < ivalue(r); ++ else ++ return luai_numlt( nvalue_fast(l), cast_num(ivalue(r)) ); ++ ++ } else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) + return res; ++ + return luaG_ordererror(L, l, r); + } + + + static int lessequal (lua_State *L, const TValue *l, const TValue *r) { + int res; +- if (ttype(l) != ttype(r)) ++ int tl, tr; ++ lua_Integer tmp; ++ ++ if (!ttype_ext_same(l,r)) + return luaG_ordererror(L, l, r); +- else if (ttisnumber(l)) +- return luai_numle(nvalue(l), nvalue(r)); +- else if (ttisstring(l)) +- return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; +- else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ ++#ifdef LNUM_COMPLEX ++ if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) ) ++ error_complex( L, l, r ); ++#endif ++ tl= ttype(l); tr= ttype(r); ++ if (tl==tr) { /* clear arithmetics */ ++ switch(tl) { ++ case LUA_TINT: return ivalue(l) <= ivalue(r); ++ case LUA_TNUMBER: return luai_numle(nvalue_fast(l), nvalue_fast(r)); ++ case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; ++ } ++ } ++ if (tl==LUA_TINT) { /* l:int, r:num */ ++ if (tt_integer_valued(r,&tmp)) ++ return ivalue(l) <= tmp; ++ else ++ return luai_numle( cast_num(ivalue(l)), nvalue_fast(r) ); ++ ++ } else if (tl==LUA_TNUMBER) { /* l:num, r:int */ ++ if (tt_integer_valued(l,&tmp)) ++ return tmp <= ivalue(r); ++ else ++ return luai_numle( nvalue_fast(l), cast_num(ivalue(r)) ); ++ ++ } else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ + return res; + else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ + return !res; ++ + return luaG_ordererror(L, l, r); + } + + +-int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { ++/* Note: 'luaV_equalval()' and 'luaO_rawequalObj()' have largely overlapping ++ * implementation. LUA_TNIL..LUA_TLIGHTUSERDATA cases could be handled ++ * simply by the 'default' case here. ++ */ ++int luaV_equalval (lua_State *L, const TValue *l, const TValue *r) { + const TValue *tm; +- lua_assert(ttype(t1) == ttype(t2)); +- switch (ttype(t1)) { ++ lua_assert(ttype_ext_same(l,r)); ++ switch (ttype(l)) { + case LUA_TNIL: return 1; +- case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); +- case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ +- case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); ++ case LUA_TINT: ++ case LUA_TNUMBER: return luaO_rawequalObj(l,r); ++ case LUA_TBOOLEAN: return bvalue(l) == bvalue(r); /* true must be 1 !! */ ++ case LUA_TLIGHTUSERDATA: return pvalue(l) == pvalue(r); + case LUA_TUSERDATA: { +- if (uvalue(t1) == uvalue(t2)) return 1; +- tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, +- TM_EQ); ++ if (uvalue(l) == uvalue(r)) return 1; ++ tm = get_compTM(L, uvalue(l)->metatable, uvalue(r)->metatable, TM_EQ); + break; /* will try TM */ + } + case LUA_TTABLE: { +- if (hvalue(t1) == hvalue(t2)) return 1; +- tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); ++ if (hvalue(l) == hvalue(r)) return 1; ++ tm = get_compTM(L, hvalue(l)->metatable, hvalue(r)->metatable, TM_EQ); + break; /* will try TM */ + } +- default: return gcvalue(t1) == gcvalue(t2); ++ default: return gcvalue(l) == gcvalue(r); + } + if (tm == NULL) return 0; /* no TM? */ +- callTMres(L, L->top, tm, t1, t2); /* call TM */ ++ callTMres(L, L->top, tm, l, r); /* call TM */ + return !l_isfalse(L->top); + } + +@@ -314,30 +394,6 @@ void luaV_concat (lua_State *L, int tota + } + + +-static void Arith (lua_State *L, StkId ra, const TValue *rb, +- const TValue *rc, TMS op) { +- TValue tempb, tempc; +- const TValue *b, *c; +- if ((b = luaV_tonumber(rb, &tempb)) != NULL && +- (c = luaV_tonumber(rc, &tempc)) != NULL) { +- lua_Number nb = nvalue(b), nc = nvalue(c); +- switch (op) { +- case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; +- case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; +- case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; +- case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; +- case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; +- case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; +- case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; +- default: lua_assert(0); break; +- } +- } +- else if (!call_binTM(L, rb, rc, ra, op)) +- luaG_aritherror(L, rb, rc); +-} +- +- +- + /* + ** some macros for common tasks in `luaV_execute' + */ +@@ -361,17 +417,154 @@ static void Arith (lua_State *L, StkId r + #define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } + + +-#define arith_op(op,tm) { \ +- TValue *rb = RKB(i); \ +- TValue *rc = RKC(i); \ +- if (ttisnumber(rb) && ttisnumber(rc)) { \ +- lua_Number nb = nvalue(rb), nc = nvalue(rc); \ +- setnvalue(ra, op(nb, nc)); \ +- } \ +- else \ +- Protect(Arith(L, ra, rb, rc, tm)); \ ++/* Note: if called for unary operations, 'rc'=='rb'. ++ */ ++static void Arith (lua_State *L, StkId ra, const TValue *rb, ++ const TValue *rc, TMS op) { ++ TValue tempb, tempc; ++ const TValue *b, *c; ++ lua_Number nb,nc; ++ ++ if ((b = luaV_tonumber(rb, &tempb)) != NULL && ++ (c = luaV_tonumber(rc, &tempc)) != NULL) { ++ ++ /* Keep integer arithmetics in the integer realm, if possible. ++ */ ++ if (ttisint(b) && ttisint(c)) { ++ lua_Integer ib = ivalue(b), ic = ivalue(c); ++ lua_Integer *ri = &ra->value.i; ++ ra->tt= LUA_TINT; /* part of 'setivalue(ra)' */ ++ switch (op) { ++ case TM_ADD: if (try_addint( ri, ib, ic)) return; break; ++ case TM_SUB: if (try_subint( ri, ib, ic)) return; break; ++ case TM_MUL: if (try_mulint( ri, ib, ic)) return; break; ++ case TM_DIV: if (try_divint( ri, ib, ic)) return; break; ++ case TM_MOD: if (try_modint( ri, ib, ic)) return; break; ++ case TM_POW: if (try_powint( ri, ib, ic)) return; break; ++ case TM_UNM: if (try_unmint( ri, ib)) return; break; ++ default: lua_assert(0); ++ } ++ } ++ /* Fallback to floating point, when leaving range. */ ++ ++#ifdef LNUM_COMPLEX ++ if ((nvalue_img(b)!=0) || (nvalue_img(c)!=0)) { ++ lua_Complex r; ++ if (op==TM_UNM) { ++ r= -nvalue_complex_fast(b); /* never an integer (or scalar) */ ++ setnvalue_complex_fast( ra, r ); ++ } else { ++ lua_Complex bb= nvalue_complex(b), cc= nvalue_complex(c); ++ switch (op) { ++ case TM_ADD: r= bb + cc; break; ++ case TM_SUB: r= bb - cc; break; ++ case TM_MUL: r= bb * cc; break; ++ case TM_DIV: r= bb / cc; break; ++ case TM_MOD: ++ luaG_runerror(L, "attempt to use %% on complex numbers"); /* no return */ ++ case TM_POW: r= luai_vectpow( bb, cc ); break; ++ default: lua_assert(0); r=0; ++ } ++ setnvalue_complex( ra, r ); + } ++ return; ++ } ++#endif ++ nb = nvalue(b); nc = nvalue(c); ++ switch (op) { ++ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); return; ++ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); return; ++ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); return; ++ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); return; ++ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); return; ++ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); return; ++ case TM_UNM: setnvalue(ra, luai_numunm(nb)); return; ++ default: lua_assert(0); ++ } ++ } ++ ++ /* Either operand not a number */ ++ if (!call_binTM(L, rb, rc, ra, op)) ++ luaG_aritherror(L, rb, rc); ++} + ++/* Helper macro to sort arithmetic operations into four categories: ++ * TK_INT: integer - integer operands ++ * TK_NUMBER: number - number (non complex, either may be integer) ++ * TK_NUMBER2: complex numbers (at least the other) ++ * 0: non-numeric (at least the other) ++*/ ++#ifdef LNUM_COMPLEX ++static inline int arith_mode( const TValue *rb, const TValue *rc ) { ++ if (ttisint(rb) && ttisint(rc)) return TK_INT; ++ if (ttiscomplex(rb) || ttiscomplex(rc)) return TK_NUMBER2; ++ if (ttisnumber(rb) && ttisnumber(rc)) return TK_NUMBER; ++ return 0; ++} ++#else ++# define arith_mode(rb,rc) \ ++ ( (ttisint(rb) && ttisint(rc)) ? TK_INT : \ ++ (ttisnumber(rb) && ttisnumber(rc)) ? TK_NUMBER : 0 ) ++#endif ++ ++/* arith_op macro for two operators: ++ * automatically chooses, which function (number, integer, complex) to use ++ */ ++#define ARITH_OP2_START( op_num, op_int ) \ ++ int failed= 0; \ ++ switch( arith_mode(rb,rc) ) { \ ++ case TK_INT: \ ++ if (op_int ( &(ra)->value.i, ivalue(rb), ivalue(rc) )) \ ++ { ra->tt= LUA_TINT; break; } /* else flow through */ \ ++ case TK_NUMBER: \ ++ setnvalue(ra, op_num ( nvalue(rb), nvalue(rc) )); break; ++ ++#define ARITH_OP2_END \ ++ default: \ ++ failed= 1; break; \ ++ } if (!failed) continue; ++ ++#define arith_op_continue_scalar( op_num, op_int ) \ ++ ARITH_OP2_START( op_num, op_int ) \ ++ ARITH_OP2_END ++ ++#ifdef LNUM_COMPLEX ++# define arith_op_continue( op_num, op_int, op_complex ) \ ++ ARITH_OP2_START( op_num, op_int ) \ ++ case TK_NUMBER2: \ ++ setnvalue_complex( ra, op_complex ( nvalue_complex(rb), nvalue_complex(rc) ) ); break; \ ++ ARITH_OP2_END ++#else ++# define arith_op_continue(op_num,op_int,_) arith_op_continue_scalar(op_num,op_int) ++#endif ++ ++/* arith_op macro for one operator: ++ */ ++#define ARITH_OP1_START( op_num, op_int ) \ ++ int failed= 0; \ ++ switch( arith_mode(rb,rb) ) { \ ++ case TK_INT: \ ++ if (op_int ( &(ra)->value.i, ivalue(rb) )) \ ++ { ra->tt= LUA_TINT; break; } /* else flow through */ \ ++ case TK_NUMBER: \ ++ setnvalue(ra, op_num (nvalue(rb))); break; \ ++ ++#define ARITH_OP1_END \ ++ default: \ ++ failed= 1; break; \ ++ } if (!failed) continue; ++ ++#ifdef LNUM_COMPLEX ++# define arith_op1_continue( op_num, op_int, op_complex ) \ ++ ARITH_OP1_START( op_num, op_int ) \ ++ case TK_NUMBER2: \ ++ setnvalue_complex( ra, op_complex ( nvalue_complex_fast(rb) )); break; \ ++ ARITH_OP1_END ++#else ++# define arith_op1_continue( op_num, op_int, _ ) \ ++ ARITH_OP1_START( op_num, op_int ) \ ++ ARITH_OP1_END ++#endif + + + void luaV_execute (lua_State *L, int nexeccalls) { +@@ -472,38 +665,45 @@ void luaV_execute (lua_State *L, int nex + continue; + } + case OP_ADD: { +- arith_op(luai_numadd, TM_ADD); ++ TValue *rb = RKB(i), *rc= RKC(i); ++ arith_op_continue( luai_numadd, try_addint, luai_vectadd ); ++ Protect(Arith(L, ra, rb, rc, TM_ADD)); \ + continue; + } + case OP_SUB: { +- arith_op(luai_numsub, TM_SUB); ++ TValue *rb = RKB(i), *rc= RKC(i); ++ arith_op_continue( luai_numsub, try_subint, luai_vectsub ); ++ Protect(Arith(L, ra, rb, rc, TM_SUB)); + continue; + } + case OP_MUL: { +- arith_op(luai_nummul, TM_MUL); ++ TValue *rb = RKB(i), *rc= RKC(i); ++ arith_op_continue(luai_nummul, try_mulint, luai_vectmul); ++ Protect(Arith(L, ra, rb, rc, TM_MUL)); + continue; + } + case OP_DIV: { +- arith_op(luai_numdiv, TM_DIV); ++ TValue *rb = RKB(i), *rc= RKC(i); ++ arith_op_continue(luai_numdiv, try_divint, luai_vectdiv); ++ Protect(Arith(L, ra, rb, rc, TM_DIV)); + continue; + } + case OP_MOD: { +- arith_op(luai_nummod, TM_MOD); ++ TValue *rb = RKB(i), *rc= RKC(i); ++ arith_op_continue_scalar(luai_nummod, try_modint); /* scalars only */ ++ Protect(Arith(L, ra, rb, rc, TM_MOD)); + continue; + } + case OP_POW: { +- arith_op(luai_numpow, TM_POW); ++ TValue *rb = RKB(i), *rc= RKC(i); ++ arith_op_continue(luai_numpow, try_powint, luai_vectpow); ++ Protect(Arith(L, ra, rb, rc, TM_POW)); + continue; + } + case OP_UNM: { + TValue *rb = RB(i); +- if (ttisnumber(rb)) { +- lua_Number nb = nvalue(rb); +- setnvalue(ra, luai_numunm(nb)); +- } +- else { +- Protect(Arith(L, ra, rb, rb, TM_UNM)); +- } ++ arith_op1_continue(luai_numunm, try_unmint, luai_vectunm); ++ Protect(Arith(L, ra, rb, rb, TM_UNM)); + continue; + } + case OP_NOT: { +@@ -515,11 +715,11 @@ void luaV_execute (lua_State *L, int nex + const TValue *rb = RB(i); + switch (ttype(rb)) { + case LUA_TTABLE: { +- setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); ++ setivalue(ra, luaH_getn(hvalue(rb))); + break; + } + case LUA_TSTRING: { +- setnvalue(ra, cast_num(tsvalue(rb)->len)); ++ setivalue(ra, tsvalue(rb)->len); + break; + } + default: { /* try metamethod */ +@@ -652,14 +852,30 @@ void luaV_execute (lua_State *L, int nex + } + } + case OP_FORLOOP: { +- lua_Number step = nvalue(ra+2); +- lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ +- lua_Number limit = nvalue(ra+1); +- if (luai_numlt(0, step) ? luai_numle(idx, limit) +- : luai_numle(limit, idx)) { +- dojump(L, pc, GETARG_sBx(i)); /* jump back */ +- setnvalue(ra, idx); /* update internal index... */ +- setnvalue(ra+3, idx); /* ...and external index */ ++ /* If start,step and limit are all integers, we don't need to check ++ * against overflow in the looping. ++ */ ++ if (ttisint(ra) && ttisint(ra+1) && ttisint(ra+2)) { ++ lua_Integer step = ivalue(ra+2); ++ lua_Integer idx = ivalue(ra) + step; /* increment index */ ++ lua_Integer limit = ivalue(ra+1); ++ if (step > 0 ? (idx <= limit) : (limit <= idx)) { ++ dojump(L, pc, GETARG_sBx(i)); /* jump back */ ++ setivalue(ra, idx); /* update internal index... */ ++ setivalue(ra+3, idx); /* ...and external index */ ++ } ++ } else { ++ /* non-integer looping (don't use 'nvalue_fast', some may be integer!) ++ */ ++ lua_Number step = nvalue(ra+2); ++ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ ++ lua_Number limit = nvalue(ra+1); ++ if (luai_numlt(0, step) ? luai_numle(idx, limit) ++ : luai_numle(limit, idx)) { ++ dojump(L, pc, GETARG_sBx(i)); /* jump back */ ++ setnvalue(ra, idx); /* update internal index... */ ++ setnvalue(ra+3, idx); /* ...and external index */ ++ } + } + continue; + } +@@ -668,13 +884,21 @@ void luaV_execute (lua_State *L, int nex + const TValue *plimit = ra+1; + const TValue *pstep = ra+2; + L->savedpc = pc; /* next steps may throw errors */ ++ /* Using same location for tonumber's both arguments, effectively does ++ * in-place modification (string->number). */ + if (!tonumber(init, ra)) + luaG_runerror(L, LUA_QL("for") " initial value must be a number"); + else if (!tonumber(plimit, ra+1)) + luaG_runerror(L, LUA_QL("for") " limit must be a number"); + else if (!tonumber(pstep, ra+2)) + luaG_runerror(L, LUA_QL("for") " step must be a number"); +- setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); ++ /* Step back one value (keep within integers if we can) ++ */ ++ if (!( ttisint(ra) && ttisint(pstep) && ++ try_subint( &ra->value.i, ivalue(ra), ivalue(pstep) ) )) { ++ /* don't use 'nvalue_fast()', values may be integer */ ++ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); ++ } + dojump(L, pc, GETARG_sBx(i)); + continue; + } +@@ -711,7 +935,7 @@ void luaV_execute (lua_State *L, int nex + luaH_resizearray(L, h, last); /* pre-alloc it at once */ + for (; n > 0; n--) { + TValue *val = ra+n; +- setobj2t(L, luaH_setnum(L, h, last--), val); ++ setobj2t(L, luaH_setint(L, h, last--), val); + luaC_barriert(L, h, val); + } + continue; +--- a/src/lvm.h ++++ b/src/lvm.h +@@ -15,11 +15,9 @@ + + #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) + +-#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ +- (((o) = luaV_tonumber(o,n)) != NULL)) ++#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) + +-#define equalobj(L,o1,o2) \ +- (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) ++#define equalobj(L,o1,o2) (ttype_ext_same(o1,o2) && luaV_equalval(L, o1, o2)) + + + LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); +--- a/src/print.c ++++ b/src/print.c +@@ -14,6 +14,7 @@ + #include "lobject.h" + #include "lopcodes.h" + #include "lundump.h" ++#include "lnum.h" + + #define PrintFunction luaU_print + +@@ -59,8 +60,16 @@ static void PrintConstant(const Proto* f + case LUA_TBOOLEAN: + printf(bvalue(o) ? "true" : "false"); + break; ++ case LUA_TINT: ++ printf(LUA_INTEGER_FMT,ivalue(o)); ++ break; + case LUA_TNUMBER: +- printf(LUA_NUMBER_FMT,nvalue(o)); ++#ifdef LNUM_COMPLEX ++ // TBD: Do we get complex values here? ++ { lua_Number b= nvalue_img_fast(o); ++ printf( LUA_NUMBER_FMT "%s" LUA_NUMBER_FMT "i", nvalue_fast(o), b>=0 ? "+":"", b ); } ++#endif ++ printf(LUA_NUMBER_FMT,nvalue_fast(o)); + break; + case LUA_TSTRING: + PrintString(rawtsvalue(o)); diff --git a/package/utils/lua/patches-host/011-lnum-use-double.patch b/package/utils/lua/patches-host/011-lnum-use-double.patch new file mode 100644 index 0000000..14c720b --- /dev/null +++ b/package/utils/lua/patches-host/011-lnum-use-double.patch @@ -0,0 +1,11 @@ +--- a/src/lnum_config.h ++++ b/src/lnum_config.h +@@ -11,7 +11,7 @@ + ** Default number modes + */ + #if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE) +-# define LNUM_FLOAT ++# define LNUM_DOUBLE + #endif + #if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64) + # define LNUM_INT32 diff --git a/package/utils/lua/patches-host/015-lnum-ppc-compat.patch b/package/utils/lua/patches-host/015-lnum-ppc-compat.patch new file mode 100644 index 0000000..2ea59f1 --- /dev/null +++ b/package/utils/lua/patches-host/015-lnum-ppc-compat.patch @@ -0,0 +1,11 @@ +--- a/src/lua.h ++++ b/src/lua.h +@@ -79,7 +79,7 @@ typedef void * (*lua_Alloc) (void *ud, v + * not acceptable for 5.1, maybe 5.2 onwards? + * 9: greater than existing (5.1) type values. + */ +-#define LUA_TINT (-2) ++#define LUA_TINT 9 + + #define LUA_TNIL 0 + #define LUA_TBOOLEAN 1 diff --git a/package/utils/lua/patches-host/030-archindependent-bytecode.patch b/package/utils/lua/patches-host/030-archindependent-bytecode.patch new file mode 100644 index 0000000..8dfef85 --- /dev/null +++ b/package/utils/lua/patches-host/030-archindependent-bytecode.patch @@ -0,0 +1,111 @@ +--- a/src/ldump.c ++++ b/src/ldump.c +@@ -67,12 +67,12 @@ static void DumpString(const TString* s, + { + if (s==NULL || getstr(s)==NULL) + { +- size_t size=0; ++ unsigned int size=0; + DumpVar(size,D); + } + else + { +- size_t size=s->tsv.len+1; /* include trailing '\0' */ ++ unsigned int size=s->tsv.len+1; /* include trailing '\0' */ + DumpVar(size,D); + DumpBlock(getstr(s),size,D); + } +--- a/src/lundump.c ++++ b/src/lundump.c +@@ -25,6 +25,7 @@ typedef struct { + ZIO* Z; + Mbuffer* b; + const char* name; ++ int swap; + } LoadState; + + #ifdef LUAC_TRUST_BINARIES +@@ -40,7 +41,6 @@ static void error(LoadState* S, const ch + } + #endif + +-#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) + #define LoadByte(S) (lu_byte)LoadChar(S) + #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) + #define LoadVector(S,b,n,size) LoadMem(S,b,n,size) +@@ -51,6 +51,49 @@ static void LoadBlock(LoadState* S, void + IF (r!=0, "unexpected end"); + } + ++static void LoadMem (LoadState* S, void* b, int n, size_t size) ++{ ++ LoadBlock(S,b,n*size); ++ if (S->swap) ++ { ++ char* p=(char*) b; ++ char c; ++ switch (size) ++ { ++ case 1: ++ break; ++ case 2: ++ while (n--) ++ { ++ c=p[0]; p[0]=p[1]; p[1]=c; ++ p+=2; ++ } ++ break; ++ case 4: ++ while (n--) ++ { ++ c=p[0]; p[0]=p[3]; p[3]=c; ++ c=p[1]; p[1]=p[2]; p[2]=c; ++ p+=4; ++ } ++ break; ++ case 8: ++ while (n--) ++ { ++ c=p[0]; p[0]=p[7]; p[7]=c; ++ c=p[1]; p[1]=p[6]; p[6]=c; ++ c=p[2]; p[2]=p[5]; p[5]=c; ++ c=p[3]; p[3]=p[4]; p[4]=c; ++ p+=8; ++ } ++ break; ++ default: ++ IF(1, "bad size"); ++ break; ++ } ++ } ++} ++ + static int LoadChar(LoadState* S) + { + char x; +@@ -82,7 +125,7 @@ static lua_Integer LoadInteger(LoadState + + static TString* LoadString(LoadState* S) + { +- size_t size; ++ unsigned int size; + LoadVar(S,size); + if (size==0) + return NULL; +@@ -196,6 +239,7 @@ static void LoadHeader(LoadState* S) + char s[LUAC_HEADERSIZE]; + luaU_header(h); + LoadBlock(S,s,LUAC_HEADERSIZE); ++ S->swap=(s[6]!=h[6]); s[6]=h[6]; + IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); + } + +@@ -230,7 +274,7 @@ void luaU_header (char* h) + *h++=(char)LUAC_FORMAT; + *h++=(char)*(char*)&x; /* endianness */ + *h++=(char)sizeof(int); +- *h++=(char)sizeof(size_t); ++ *h++=(char)sizeof(unsigned int); + *h++=(char)sizeof(Instruction); + *h++=(char)sizeof(lua_Number); + diff --git a/package/utils/lua/patches-host/100-no_readline.patch b/package/utils/lua/patches-host/100-no_readline.patch new file mode 100644 index 0000000..209c302 --- /dev/null +++ b/package/utils/lua/patches-host/100-no_readline.patch @@ -0,0 +1,49 @@ +--- a/src/luaconf.h ++++ b/src/luaconf.h +@@ -38,7 +38,6 @@ + #if defined(LUA_USE_LINUX) + #define LUA_USE_POSIX + #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +-#define LUA_USE_READLINE /* needs some extra libraries */ + #endif + + #if defined(LUA_USE_MACOSX) +--- a/src/Makefile ++++ b/src/Makefile +@@ -17,6 +17,7 @@ + MYCFLAGS= + MYLDFLAGS= + MYLIBS= ++# USE_READLINE=1 + + # == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= + +@@ -75,7 +76,7 @@ + @echo "MYLIBS = $(MYLIBS)" + + # convenience targets for popular platforms +- ++RFLAG=$(if $(USE_READLINE),-DLUA_USE_READLINE) + none: + @echo "Please choose a platform:" + @echo " $(PLATS)" +@@ -90,16 +91,16 @@ + $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E" + + freebsd: +- $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline" ++ $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" $(RFLAG)" MYLIBS="-Wl,-E$(if $(USE_READLINE), -lreadline)" + + generic: + $(MAKE) all MYCFLAGS= + + linux: +- $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses" ++ $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX $(RFLAG)" MYLIBS="-Wl,-E -ldl $(if $(USE_READLINE), -lreadline -lhistory -lncurses)" + + macosx: +- $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline" ++ $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX $(if $(USE_READLINE), MYLIBS="-lreadline") + # use this on Mac OS X 10.3- + # $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX + diff --git a/package/utils/lua/patches/010-lua-5.1.3-lnum-full-260308.patch b/package/utils/lua/patches/010-lua-5.1.3-lnum-full-260308.patch new file mode 100644 index 0000000..74b8c6f --- /dev/null +++ b/package/utils/lua/patches/010-lua-5.1.3-lnum-full-260308.patch @@ -0,0 +1,3736 @@ +--- a/src/Makefile ++++ b/src/Makefile +@@ -25,7 +25,7 @@ PLATS= aix ansi bsd freebsd generic linu + LUA_A= liblua.a + CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ + lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \ +- lundump.o lvm.o lzio.o ++ lundump.o lvm.o lzio.o lnum.o + LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ + lstrlib.o loadlib.o linit.o + +@@ -148,6 +148,7 @@ llex.o: llex.c lua.h luaconf.h ldo.h lob + lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h + lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h ++lnum.o: lnum.c lua.h llex.h lnum.h + loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h + lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \ + ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h +@@ -179,4 +180,18 @@ lzio.o: lzio.c lua.h luaconf.h llimits.h + print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h lopcodes.h lundump.h + ++luaconf.h: lnum_config.h ++lapi.c: lnum.h ++lauxlib.c: llimits.h ++lbaselib.c: llimits.h lobject.h lapi.h ++lcode.c: lnum.h ++liolib.c: lnum.h llex.h ++llex.c: lnum.h ++lnum.h: lobject.h ++lobject.c: llex.h lnum.h ++ltable.c: lnum.h ++lua.c: llimits.h ++lvm.c: llex.h lnum.h ++print.c: lnum.h ++ + # (end of Makefile) +--- a/src/lapi.c ++++ b/src/lapi.c +@@ -28,7 +28,7 @@ + #include "ltm.h" + #include "lundump.h" + #include "lvm.h" +- ++#include "lnum.h" + + + const char lua_ident[] = +@@ -241,12 +241,13 @@ LUA_API void lua_pushvalue (lua_State *L + + LUA_API int lua_type (lua_State *L, int idx) { + StkId o = index2adr(L, idx); +- return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); ++ return (o == luaO_nilobject) ? LUA_TNONE : ttype_ext(o); + } + + + LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); ++ lua_assert( t!= LUA_TINT ); + return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; + } + +@@ -264,6 +265,14 @@ LUA_API int lua_isnumber (lua_State *L, + } + + ++LUA_API int lua_isinteger (lua_State *L, int idx) { ++ TValue tmp; ++ lua_Integer dum; ++ const TValue *o = index2adr(L, idx); ++ return tonumber(o,&tmp) && (ttisint(o) || tt_integer_valued(o,&dum)); ++} ++ ++ + LUA_API int lua_isstring (lua_State *L, int idx) { + int t = lua_type(L, idx); + return (t == LUA_TSTRING || t == LUA_TNUMBER); +@@ -309,31 +318,66 @@ LUA_API int lua_lessthan (lua_State *L, + } + + +- + LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); +- if (tonumber(o, &n)) ++ if (tonumber(o, &n)) { ++#ifdef LNUM_COMPLEX ++ if (nvalue_img(o) != 0) ++ luaG_runerror(L, "expecting a real number"); ++#endif + return nvalue(o); +- else +- return 0; ++ } ++ return 0; + } + + + LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { + TValue n; ++ /* Lua 5.1 documented behaviour is to return nonzero for non-integer: ++ * "If the number is not an integer, it is truncated in some non-specified way." ++ * I would suggest to change this, to return 0 for anything that would ++ * not fit in 'lua_Integer'. ++ */ ++#ifdef LUA_COMPAT_TOINTEGER ++ /* Lua 5.1 compatible */ + const TValue *o = index2adr(L, idx); + if (tonumber(o, &n)) { +- lua_Integer res; +- lua_Number num = nvalue(o); +- lua_number2integer(res, num); +- return res; ++ lua_Integer i; ++ lua_Number d; ++ if (ttisint(o)) return ivalue(o); ++ d= nvalue_fast(o); ++# ifdef LNUM_COMPLEX ++ if (nvalue_img_fast(o) != 0) ++ luaG_runerror(L, "expecting a real number"); ++# endif ++ lua_number2integer(i, d); ++ return i; + } +- else +- return 0; ++#else ++ /* New suggestion */ ++ const TValue *o = index2adr(L, idx); ++ if (tonumber(o, &n)) { ++ lua_Integer i; ++ if (ttisint(o)) return ivalue(o); ++ if (tt_integer_valued(o,&i)) return i; ++ } ++#endif ++ return 0; + } + + ++#ifdef LNUM_COMPLEX ++LUA_API lua_Complex lua_tocomplex (lua_State *L, int idx) { ++ TValue tmp; ++ const TValue *o = index2adr(L, idx); ++ if (tonumber(o, &tmp)) ++ return nvalue_complex(o); ++ return 0; ++} ++#endif ++ ++ + LUA_API int lua_toboolean (lua_State *L, int idx) { + const TValue *o = index2adr(L, idx); + return !l_isfalse(o); +@@ -364,6 +408,7 @@ LUA_API size_t lua_objlen (lua_State *L, + case LUA_TSTRING: return tsvalue(o)->len; + case LUA_TUSERDATA: return uvalue(o)->len; + case LUA_TTABLE: return luaH_getn(hvalue(o)); ++ case LUA_TINT: + case LUA_TNUMBER: { + size_t l; + lua_lock(L); /* `luaV_tostring' may create a new string */ +@@ -426,6 +471,8 @@ LUA_API void lua_pushnil (lua_State *L) + } + + ++/* 'lua_pushnumber()' may lose accuracy on integers, 'lua_pushinteger' will not. ++ */ + LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { + lua_lock(L); + setnvalue(L->top, n); +@@ -434,12 +481,22 @@ LUA_API void lua_pushnumber (lua_State * + } + + +-LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { ++LUA_API void lua_pushinteger (lua_State *L, lua_Integer i) { ++ lua_lock(L); ++ setivalue(L->top, i); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++#ifdef LNUM_COMPLEX ++LUA_API void lua_pushcomplex (lua_State *L, lua_Complex v) { + lua_lock(L); +- setnvalue(L->top, cast_num(n)); ++ setnvalue_complex( L->top, v ); + api_incr_top(L); + lua_unlock(L); + } ++#endif + + + LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { +@@ -569,7 +626,7 @@ LUA_API void lua_rawgeti (lua_State *L, + lua_lock(L); + o = index2adr(L, idx); + api_check(L, ttistable(o)); +- setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); ++ setobj2s(L, L->top, luaH_getint(hvalue(o), n)); + api_incr_top(L); + lua_unlock(L); + } +@@ -597,6 +654,9 @@ LUA_API int lua_getmetatable (lua_State + case LUA_TUSERDATA: + mt = uvalue(obj)->metatable; + break; ++ case LUA_TINT: ++ mt = G(L)->mt[LUA_TNUMBER]; ++ break; + default: + mt = G(L)->mt[ttype(obj)]; + break; +@@ -687,7 +747,7 @@ LUA_API void lua_rawseti (lua_State *L, + api_checknelems(L, 1); + o = index2adr(L, idx); + api_check(L, ttistable(o)); +- setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); ++ setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1); + luaC_barriert(L, hvalue(o), L->top-1); + L->top--; + lua_unlock(L); +@@ -721,7 +781,7 @@ LUA_API int lua_setmetatable (lua_State + break; + } + default: { +- G(L)->mt[ttype(obj)] = mt; ++ G(L)->mt[ttype_ext(obj)] = mt; + break; + } + } +@@ -1085,3 +1145,32 @@ LUA_API const char *lua_setupvalue (lua_ + return name; + } + ++ ++/* Help function for 'luaB_tonumber()', avoids multiple str->number ++ * conversions for Lua "tonumber()". ++ * ++ * Also pushes floating point numbers with integer value as integer, which ++ * can be used by 'tonumber()' in scripts to bring values back to integer ++ * realm. ++ * ++ * Note: The 'back to integer realm' is _not_ to affect string conversions: ++ * 'tonumber("4294967295.1")' should give a floating point value, although ++ * the value would be 4294967296 (and storable in int64 realm). ++ */ ++int lua_pushvalue_as_number (lua_State *L, int idx) ++{ ++ const TValue *o = index2adr(L, idx); ++ TValue tmp; ++ lua_Integer i; ++ if (ttisnumber(o)) { ++ if ( (!ttisint(o)) && tt_integer_valued(o,&i)) { ++ lua_pushinteger( L, i ); ++ return 1; ++ } ++ } else if (!tonumber(o, &tmp)) { ++ return 0; ++ } ++ if (ttisint(o)) lua_pushinteger( L, ivalue(o) ); ++ else lua_pushnumber( L, nvalue_fast(o) ); ++ return 1; ++} +--- a/src/lapi.h ++++ b/src/lapi.h +@@ -13,4 +13,6 @@ + + LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); + ++int lua_pushvalue_as_number (lua_State *L, int idx); ++ + #endif +--- a/src/lauxlib.c ++++ b/src/lauxlib.c +@@ -23,7 +23,7 @@ + #include "lua.h" + + #include "lauxlib.h" +- ++#include "llimits.h" + + #define FREELIST_REF 0 /* free list of references */ + +@@ -66,7 +66,7 @@ LUALIB_API int luaL_typerror (lua_State + + + static void tag_error (lua_State *L, int narg, int tag) { +- luaL_typerror(L, narg, lua_typename(L, tag)); ++ luaL_typerror(L, narg, tag==LUA_TINT ? "integer" : lua_typename(L, tag)); + } + + +@@ -188,8 +188,8 @@ LUALIB_API lua_Number luaL_optnumber (lu + + LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { + lua_Integer d = lua_tointeger(L, narg); +- if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ +- tag_error(L, narg, LUA_TNUMBER); ++ if (d == 0 && !lua_isinteger(L, narg)) /* avoid extra test when d is not 0 */ ++ tag_error(L, narg, LUA_TINT); + return d; + } + +@@ -200,6 +200,16 @@ LUALIB_API lua_Integer luaL_optinteger ( + } + + ++#ifdef LNUM_COMPLEX ++LUALIB_API lua_Complex luaL_checkcomplex (lua_State *L, int narg) { ++ lua_Complex c = lua_tocomplex(L, narg); ++ if (c == 0 && !lua_isnumber(L, narg)) /* avoid extra test when c is not 0 */ ++ tag_error(L, narg, LUA_TNUMBER); ++ return c; ++} ++#endif ++ ++ + LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return 0; +--- a/src/lauxlib.h ++++ b/src/lauxlib.h +@@ -57,6 +57,12 @@ LUALIB_API lua_Number (luaL_optnumber) ( + LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); + LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, + lua_Integer def); ++#define luaL_checkint32(L,narg) ((int)luaL_checkinteger(L,narg)) ++#define luaL_optint32(L,narg,def) ((int)luaL_optinteger(L,narg,def)) ++ ++#ifdef LNUM_COMPLEX ++ LUALIB_API lua_Complex (luaL_checkcomplex) (lua_State *L, int narg); ++#endif + + LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); + LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); +--- a/src/lbaselib.c ++++ b/src/lbaselib.c +@@ -18,7 +18,9 @@ + + #include "lauxlib.h" + #include "lualib.h" +- ++#include "llimits.h" ++#include "lobject.h" ++#include "lapi.h" + + + +@@ -54,20 +56,25 @@ static int luaB_tonumber (lua_State *L) + int base = luaL_optint(L, 2, 10); + if (base == 10) { /* standard conversion */ + luaL_checkany(L, 1); +- if (lua_isnumber(L, 1)) { +- lua_pushnumber(L, lua_tonumber(L, 1)); ++ if (lua_isnumber(L, 1)) { /* numeric string, or a number */ ++ lua_pushvalue_as_number(L,1); /* API extension (not to lose accuracy here) */ + return 1; +- } ++ } + } + else { + const char *s1 = luaL_checkstring(L, 1); + char *s2; +- unsigned long n; ++ unsigned LUA_INTEGER n; + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); +- n = strtoul(s1, &s2, base); ++ n = lua_str2ul(s1, &s2, base); + if (s1 != s2) { /* at least one valid digit? */ + while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ + if (*s2 == '\0') { /* no invalid trailing characters? */ ++ ++ /* Push as number, there needs to be separate 'luaB_tointeger' for ++ * when the caller wants to preserve the bits (matters if unsigned ++ * values are used). ++ */ + lua_pushnumber(L, (lua_Number)n); + return 1; + } +@@ -144,7 +151,7 @@ static int luaB_setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + getfunc(L, 0); + lua_pushvalue(L, 2); +- if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { ++ if (lua_isnumber(L, 1) && lua_tointeger(L, 1) == 0) { + /* change environment of current thread */ + lua_pushthread(L); + lua_insert(L, -2); +@@ -209,7 +216,7 @@ static int luaB_collectgarbage (lua_Stat + return 1; + } + default: { +- lua_pushnumber(L, res); ++ lua_pushinteger(L, res); + return 1; + } + } +@@ -631,6 +638,8 @@ static void base_open (lua_State *L) { + luaL_register(L, "_G", base_funcs); + lua_pushliteral(L, LUA_VERSION); + lua_setglobal(L, "_VERSION"); /* set global _VERSION */ ++ lua_pushliteral(L, LUA_LNUM); ++ lua_setglobal(L, "_LNUM"); /* "[complex] double|float|ldouble int32|int64" */ + /* `ipairs' and `pairs' need auxiliary functions as upvalues */ + auxopen(L, "ipairs", luaB_ipairs, ipairsaux); + auxopen(L, "pairs", luaB_pairs, luaB_next); +--- a/src/lcode.c ++++ b/src/lcode.c +@@ -22,13 +22,18 @@ + #include "lopcodes.h" + #include "lparser.h" + #include "ltable.h" ++#include "lnum.h" + + + #define hasjumps(e) ((e)->t != (e)->f) + +- + static int isnumeral(expdesc *e) { +- return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); ++ int ek= ++#ifdef LNUM_COMPLEX ++ (e->k == VKNUM2) || ++#endif ++ (e->k == VKINT) || (e->k == VKNUM); ++ return (ek && e->t == NO_JUMP && e->f == NO_JUMP); + } + + +@@ -231,12 +236,16 @@ static int addk (FuncState *fs, TValue * + TValue *idx = luaH_set(L, fs->h, k); + Proto *f = fs->f; + int oldsize = f->sizek; +- if (ttisnumber(idx)) { +- lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); +- return cast_int(nvalue(idx)); ++ if (ttype(idx)==LUA_TNUMBER) { ++ luai_normalize(idx); ++ lua_assert( ttype(idx)==LUA_TINT ); /* had no fraction */ ++ } ++ if (ttisint(idx)) { ++ lua_assert(luaO_rawequalObj(&fs->f->k[ivalue(idx)], v)); ++ return cast_int(ivalue(idx)); + } + else { /* constant not found; create a new entry */ +- setnvalue(idx, cast_num(fs->nk)); ++ setivalue(idx, fs->nk); + luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, + MAXARG_Bx, "constant table overflow"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); +@@ -261,6 +270,21 @@ int luaK_numberK (FuncState *fs, lua_Num + } + + ++int luaK_integerK (FuncState *fs, lua_Integer r) { ++ TValue o; ++ setivalue(&o, r); ++ return addk(fs, &o, &o); ++} ++ ++ ++#ifdef LNUM_COMPLEX ++static int luaK_imagK (FuncState *fs, lua_Number r) { ++ TValue o; ++ setnvalue_complex(&o, r*I); ++ return addk(fs, &o, &o); ++} ++#endif ++ + static int boolK (FuncState *fs, int b) { + TValue o; + setbvalue(&o, b); +@@ -359,6 +383,16 @@ static void discharge2reg (FuncState *fs + luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); + break; + } ++ case VKINT: { ++ luaK_codeABx(fs, OP_LOADK, reg, luaK_integerK(fs, e->u.ival)); ++ break; ++ } ++#ifdef LNUM_COMPLEX ++ case VKNUM2: { ++ luaK_codeABx(fs, OP_LOADK, reg, luaK_imagK(fs, e->u.nval)); ++ break; ++ } ++#endif + case VRELOCABLE: { + Instruction *pc = &getcode(fs, e); + SETARG_A(*pc, reg); +@@ -444,6 +478,10 @@ void luaK_exp2val (FuncState *fs, expdes + int luaK_exp2RK (FuncState *fs, expdesc *e) { + luaK_exp2val(fs, e); + switch (e->k) { ++#ifdef LNUM_COMPLEX ++ case VKNUM2: ++#endif ++ case VKINT: + case VKNUM: + case VTRUE: + case VFALSE: +@@ -451,6 +489,10 @@ int luaK_exp2RK (FuncState *fs, expdesc + if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ + e->u.s.info = (e->k == VNIL) ? nilK(fs) : + (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : ++ (e->k == VKINT) ? luaK_integerK(fs, e->u.ival) : ++#ifdef LNUM_COMPLEX ++ (e->k == VKNUM2) ? luaK_imagK(fs, e->u.nval) : ++#endif + boolK(fs, (e->k == VTRUE)); + e->k = VK; + return RKASK(e->u.s.info); +@@ -540,7 +582,10 @@ void luaK_goiftrue (FuncState *fs, expde + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { +- case VK: case VKNUM: case VTRUE: { ++#ifdef LNUM_COMPLEX ++ case VKNUM2: ++#endif ++ case VKINT: case VK: case VKNUM: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + break; + } +@@ -590,7 +635,10 @@ static void codenot (FuncState *fs, expd + e->k = VTRUE; + break; + } +- case VK: case VKNUM: case VTRUE: { ++#ifdef LNUM_COMPLEX ++ case VKNUM2: ++#endif ++ case VKINT: case VK: case VKNUM: case VTRUE: { + e->k = VFALSE; + break; + } +@@ -626,25 +674,70 @@ void luaK_indexed (FuncState *fs, expdes + + static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { + lua_Number v1, v2, r; ++ int vkres= VKNUM; + if (!isnumeral(e1) || !isnumeral(e2)) return 0; +- v1 = e1->u.nval; +- v2 = e2->u.nval; ++ ++ /* real and imaginary parts don't mix. */ ++#ifdef LNUM_COMPLEX ++ if (e1->k == VKNUM2) { ++ if ((op != OP_UNM) && (e2->k != VKNUM2)) return 0; ++ vkres= VKNUM2; } ++ else if (e2->k == VKNUM2) { return 0; } ++#endif ++ if ((e1->k == VKINT) && (e2->k == VKINT)) { ++ lua_Integer i1= e1->u.ival, i2= e2->u.ival; ++ lua_Integer rr; ++ int done= 0; ++ /* Integer/integer calculations (may end up producing floating point) */ ++ switch (op) { ++ case OP_ADD: done= try_addint( &rr, i1, i2 ); break; ++ case OP_SUB: done= try_subint( &rr, i1, i2 ); break; ++ case OP_MUL: done= try_mulint( &rr, i1, i2 ); break; ++ case OP_DIV: done= try_divint( &rr, i1, i2 ); break; ++ case OP_MOD: done= try_modint( &rr, i1, i2 ); break; ++ case OP_POW: done= try_powint( &rr, i1, i2 ); break; ++ case OP_UNM: done= try_unmint( &rr, i1 ); break; ++ default: done= 0; break; ++ } ++ if (done) { ++ e1->u.ival = rr; /* remained within integer range */ ++ return 1; ++ } ++ } ++ v1 = (e1->k == VKINT) ? ((lua_Number)e1->u.ival) : e1->u.nval; ++ v2 = (e2->k == VKINT) ? ((lua_Number)e2->u.ival) : e2->u.nval; ++ + switch (op) { + case OP_ADD: r = luai_numadd(v1, v2); break; + case OP_SUB: r = luai_numsub(v1, v2); break; +- case OP_MUL: r = luai_nummul(v1, v2); break; ++ case OP_MUL: ++#ifdef LNUM_COMPLEX ++ if (vkres==VKNUM2) return 0; /* leave to runtime (could do here, but not worth it?) */ ++#endif ++ r = luai_nummul(v1, v2); break; + case OP_DIV: + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ +- r = luai_numdiv(v1, v2); break; ++#ifdef LNUM_COMPLEX ++ if (vkres==VKNUM2) return 0; /* leave to runtime */ ++#endif ++ r = luai_numdiv(v1, v2); break; + case OP_MOD: + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ ++#ifdef LNUM_COMPLEX ++ if (vkres==VKNUM2) return 0; /* leave to runtime */ ++#endif + r = luai_nummod(v1, v2); break; +- case OP_POW: r = luai_numpow(v1, v2); break; ++ case OP_POW: ++#ifdef LNUM_COMPLEX ++ if (vkres==VKNUM2) return 0; /* leave to runtime */ ++#endif ++ r = luai_numpow(v1, v2); break; + case OP_UNM: r = luai_numunm(v1); break; + case OP_LEN: return 0; /* no constant folding for 'len' */ + default: lua_assert(0); r = 0; break; + } + if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ ++ e1->k = cast(expkind,vkres); + e1->u.nval = r; + return 1; + } +@@ -688,7 +781,8 @@ static void codecomp (FuncState *fs, OpC + + void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { + expdesc e2; +- e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; ++ e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0; ++ + switch (op) { + case OPR_MINUS: { + if (!isnumeral(e)) +--- a/src/lcode.h ++++ b/src/lcode.h +@@ -71,6 +71,6 @@ LUAI_FUNC void luaK_prefix (FuncState *f + LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); + LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); + LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); +- ++LUAI_FUNC int luaK_integerK (FuncState *fs, lua_Integer r); + + #endif +--- a/src/ldebug.c ++++ b/src/ldebug.c +@@ -183,7 +183,7 @@ static void collectvalidlines (lua_State + int *lineinfo = f->l.p->lineinfo; + int i; + for (i=0; i<f->l.p->sizelineinfo; i++) +- setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); ++ setbvalue(luaH_setint(L, t, lineinfo[i]), 1); + sethvalue(L, L->top, t); + } + incr_top(L); +@@ -566,7 +566,7 @@ static int isinstack (CallInfo *ci, cons + + void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + const char *name = NULL; +- const char *t = luaT_typenames[ttype(o)]; ++ const char *t = luaT_typenames[ttype_ext(o)]; + const char *kind = (isinstack(L->ci, o)) ? + getobjname(L, L->ci, cast_int(o - L->base), &name) : + NULL; +@@ -594,8 +594,8 @@ void luaG_aritherror (lua_State *L, cons + + + int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { +- const char *t1 = luaT_typenames[ttype(p1)]; +- const char *t2 = luaT_typenames[ttype(p2)]; ++ const char *t1 = luaT_typenames[ttype_ext(p1)]; ++ const char *t2 = luaT_typenames[ttype_ext(p2)]; + if (t1[2] == t2[2]) + luaG_runerror(L, "attempt to compare two %s values", t1); + else +--- a/src/ldo.c ++++ b/src/ldo.c +@@ -220,9 +220,9 @@ static StkId adjust_varargs (lua_State * + luaD_checkstack(L, p->maxstacksize); + htab = luaH_new(L, nvar, 1); /* create `arg' table */ + for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */ +- setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i); ++ setobj2n(L, luaH_setint(L, htab, i+1), L->top - nvar + i); + /* store counter in field `n' */ +- setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); ++ setivalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), nvar); + } + #endif + /* move fixed parameters to final position */ +--- a/src/ldump.c ++++ b/src/ldump.c +@@ -52,6 +52,11 @@ static void DumpNumber(lua_Number x, Dum + DumpVar(x,D); + } + ++static void DumpInteger(lua_Integer x, DumpState* D) ++{ ++ DumpVar(x,D); ++} ++ + static void DumpVector(const void* b, int n, size_t size, DumpState* D) + { + DumpInt(n,D); +@@ -93,8 +98,11 @@ static void DumpConstants(const Proto* f + DumpChar(bvalue(o),D); + break; + case LUA_TNUMBER: +- DumpNumber(nvalue(o),D); ++ DumpNumber(nvalue_fast(o),D); + break; ++ case LUA_TINT: ++ DumpInteger(ivalue(o),D); ++ break; + case LUA_TSTRING: + DumpString(rawtsvalue(o),D); + break; +--- a/src/liolib.c ++++ b/src/liolib.c +@@ -9,6 +9,7 @@ + #include <stdio.h> + #include <stdlib.h> + #include <string.h> ++#include <ctype.h> + + #define liolib_c + #define LUA_LIB +@@ -18,7 +19,8 @@ + #include "lauxlib.h" + #include "lualib.h" + +- ++#include "lnum.h" ++#include "llex.h" + + #define IO_INPUT 1 + #define IO_OUTPUT 2 +@@ -269,6 +271,13 @@ static int io_lines (lua_State *L) { + ** ======================================================= + */ + ++/* ++* Many problems if we intend the same 'n' format specifier (see 'file:read()') ++* to work for both FP and integer numbers, without losing their accuracy. So ++* we don't. 'n' reads numbers as floating points, 'i' as integers. Old code ++* remains valid, but won't provide full integer accuracy (this only matters ++* with float FP and/or 64-bit integers). ++*/ + + static int read_number (lua_State *L, FILE *f) { + lua_Number d; +@@ -282,6 +291,43 @@ static int read_number (lua_State *L, FI + } + } + ++static int read_integer (lua_State *L, FILE *f) { ++ lua_Integer i; ++ if (fscanf(f, LUA_INTEGER_SCAN, &i) == 1) { ++ lua_pushinteger(L, i); ++ return 1; ++ } ++ else return 0; /* read fails */ ++} ++ ++#ifdef LNUM_COMPLEX ++static int read_complex (lua_State *L, FILE *f) { ++ /* NNN / NNNi / NNN+MMMi / NNN-MMMi */ ++ lua_Number a,b; ++ if (fscanf(f, LUA_NUMBER_SCAN, &a) == 1) { ++ int c=fgetc(f); ++ switch(c) { ++ case 'i': ++ lua_pushcomplex(L, a*I); ++ return 1; ++ case '+': ++ case '-': ++ /* "i" is consumed if at the end; just 'NNN+MMM' will most likely ++ * behave as if "i" was there? (TBD: test) ++ */ ++ if (fscanf(f, LUA_NUMBER_SCAN "i", &b) == 1) { ++ lua_pushcomplex(L, a+ (c=='+' ? b:-b)*I); ++ return 1; ++ } ++ } ++ ungetc( c,f ); ++ lua_pushnumber(L,a); /*real part only*/ ++ return 1; ++ } ++ return 0; /* read fails */ ++} ++#endif ++ + + static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); +@@ -355,6 +401,14 @@ static int g_read (lua_State *L, FILE *f + case 'n': /* number */ + success = read_number(L, f); + break; ++ case 'i': /* integer (full accuracy) */ ++ success = read_integer(L, f); ++ break; ++#ifdef LNUM_COMPLEX ++ case 'c': /* complex */ ++ success = read_complex(L, f); ++ break; ++#endif + case 'l': /* line */ + success = read_line(L, f); + break; +@@ -415,9 +469,10 @@ static int g_write (lua_State *L, FILE * + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { +- /* optimization: could be done exactly as for strings */ +- status = status && +- fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; ++ if (lua_isinteger(L,arg)) ++ status = status && fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg)) > 0; ++ else ++ status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + } + else { + size_t l; +@@ -460,7 +515,7 @@ static int f_setvbuf (lua_State *L) { + static const char *const modenames[] = {"no", "full", "line", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, NULL, modenames); +- lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); ++ size_t sz = luaL_optint32(L, 3, LUAL_BUFFERSIZE); + int res = setvbuf(f, NULL, mode[op], sz); + return pushresult(L, res == 0, NULL); + } +--- a/src/llex.c ++++ b/src/llex.c +@@ -22,6 +22,7 @@ + #include "lstring.h" + #include "ltable.h" + #include "lzio.h" ++#include "lnum.h" + + + +@@ -34,13 +35,17 @@ + + + /* ORDER RESERVED */ +-const char *const luaX_tokens [] = { ++static const char *const luaX_tokens [] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "..", "...", "==", ">=", "<=", "~=", + "<number>", "<name>", "<string>", "<eof>", ++ "<integer>", ++#ifdef LNUM_COMPLEX ++ "<number2>", ++#endif + NULL + }; + +@@ -90,7 +95,11 @@ static const char *txtToken (LexState *l + switch (token) { + case TK_NAME: + case TK_STRING: ++ case TK_INT: + case TK_NUMBER: ++#ifdef LNUM_COMPLEX ++ case TK_NUMBER2: ++#endif + save(ls, '\0'); + return luaZ_buffer(ls->buff); + default: +@@ -175,23 +184,27 @@ static void buffreplace (LexState *ls, c + if (p[n] == from) p[n] = to; + } + +- +-static void trydecpoint (LexState *ls, SemInfo *seminfo) { ++/* TK_NUMBER (/ TK_NUMBER2) */ ++static int trydecpoint (LexState *ls, SemInfo *seminfo) { + /* format error: try to update decimal point separator */ + struct lconv *cv = localeconv(); + char old = ls->decpoint; ++ int ret; + ls->decpoint = (cv ? cv->decimal_point[0] : '.'); + buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ +- if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { ++ ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, NULL); ++ if (!ret) { + /* format error with correct decimal point: no more options */ + buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ + luaX_lexerror(ls, "malformed number", TK_NUMBER); + } ++ return ret; + } + + +-/* LUA_NUMBER */ +-static void read_numeral (LexState *ls, SemInfo *seminfo) { ++/* TK_NUMBER / TK_INT (/TK_NUMBER2) */ ++static int read_numeral (LexState *ls, SemInfo *seminfo) { ++ int ret; + lua_assert(isdigit(ls->current)); + do { + save_and_next(ls); +@@ -202,8 +215,9 @@ static void read_numeral (LexState *ls, + save_and_next(ls); + save(ls, '\0'); + buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ +- if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ +- trydecpoint(ls, seminfo); /* try to update decimal point separator */ ++ ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, &seminfo->i ); ++ if (!ret) return trydecpoint(ls, seminfo); /* try to update decimal point separator */ ++ return ret; + } + + +@@ -331,6 +345,7 @@ static void read_string (LexState *ls, i + } + + ++/* char / TK_* */ + static int llex (LexState *ls, SemInfo *seminfo) { + luaZ_resetbuffer(ls->buff); + for (;;) { +@@ -402,8 +417,7 @@ static int llex (LexState *ls, SemInfo * + } + else if (!isdigit(ls->current)) return '.'; + else { +- read_numeral(ls, seminfo); +- return TK_NUMBER; ++ return read_numeral(ls, seminfo); + } + } + case EOZ: { +@@ -416,8 +430,7 @@ static int llex (LexState *ls, SemInfo * + continue; + } + else if (isdigit(ls->current)) { +- read_numeral(ls, seminfo); +- return TK_NUMBER; ++ return read_numeral(ls, seminfo); + } + else if (isalpha(ls->current) || ls->current == '_') { + /* identifier or reserved word */ +--- a/src/llex.h ++++ b/src/llex.h +@@ -29,19 +29,22 @@ enum RESERVED { + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, + /* other terminal symbols */ + TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, +- TK_NAME, TK_STRING, TK_EOS ++ TK_NAME, TK_STRING, TK_EOS, TK_INT ++#ifdef LNUM_COMPLEX ++ , TK_NUMBER2 /* imaginary constants: Ni */ ++#endif + }; + + /* number of reserved words */ + #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) + + +-/* array with token `names' */ +-LUAI_DATA const char *const luaX_tokens []; +- +- ++/* SemInfo is a local data structure of 'llex.c', used for carrying a string ++ * or a number. A separate token (TK_*) will tell, how to interpret the data. ++ */ + typedef union { + lua_Number r; ++ lua_Integer i; + TString *ts; + } SemInfo; /* semantics information */ + +--- a/src/llimits.h ++++ b/src/llimits.h +@@ -49,6 +49,7 @@ typedef LUAI_USER_ALIGNMENT_T L_Umaxalig + + /* result of a `usual argument conversion' over lua_Number */ + typedef LUAI_UACNUMBER l_uacNumber; ++typedef LUAI_UACINTEGER l_uacInteger; + + + /* internal assertions for in-house debugging */ +@@ -80,7 +81,6 @@ typedef LUAI_UACNUMBER l_uacNumber; + #define cast_int(i) cast(int, (i)) + + +- + /* + ** type for virtual-machine instructions + ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +--- a/src/lmathlib.c ++++ b/src/lmathlib.c +@@ -4,7 +4,6 @@ + ** See Copyright Notice in lua.h + */ + +- + #include <stdlib.h> + #include <math.h> + +@@ -16,113 +15,210 @@ + #include "lauxlib.h" + #include "lualib.h" + ++/* 'luai_vectpow()' as a replacement for 'cpow()'. Defined in the header; we ++ * don't intrude the code libs internal functions. ++ */ ++#ifdef LNUM_COMPLEX ++# include "lnum.h" ++#endif + + #undef PI +-#define PI (3.14159265358979323846) +-#define RADIANS_PER_DEGREE (PI/180.0) +- ++#ifdef LNUM_FLOAT ++# define PI (3.14159265358979323846F) ++#elif defined(M_PI) ++# define PI M_PI ++#else ++# define PI (3.14159265358979323846264338327950288) ++#endif ++#define RADIANS_PER_DEGREE (PI/180) + ++#undef HUGE ++#ifdef LNUM_FLOAT ++# define HUGE HUGE_VALF ++#elif defined(LNUM_LDOUBLE) ++# define HUGE HUGE_VALL ++#else ++# define HUGE HUGE_VAL ++#endif + + static int math_abs (lua_State *L) { +- lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushnumber(L, _LF(cabs) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(fabs) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_sin (lua_State *L) { +- lua_pushnumber(L, sin(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(csin) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(sin) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_sinh (lua_State *L) { +- lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(csinh) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(sinh) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_cos (lua_State *L) { +- lua_pushnumber(L, cos(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(ccos) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(cos) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_cosh (lua_State *L) { +- lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(ccosh) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(cosh) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_tan (lua_State *L) { +- lua_pushnumber(L, tan(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(ctan) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(tan) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_tanh (lua_State *L) { +- lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(ctanh) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(tanh) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_asin (lua_State *L) { +- lua_pushnumber(L, asin(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(casin) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(asin) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_acos (lua_State *L) { +- lua_pushnumber(L, acos(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(cacos) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(acos) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_atan (lua_State *L) { +- lua_pushnumber(L, atan(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(catan) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(atan) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_atan2 (lua_State *L) { +- lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); ++ /* scalars only */ ++ lua_pushnumber(L, _LF(atan2) (luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; + } + + static int math_ceil (lua_State *L) { +- lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_Complex v= luaL_checkcomplex(L, 1); ++ lua_pushcomplex(L, _LF(ceil) (_LF(creal)(v)) + _LF(ceil) (_LF(cimag)(v))*I); ++#else ++ lua_pushnumber(L, _LF(ceil) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_floor (lua_State *L) { +- lua_pushnumber(L, floor(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_Complex v= luaL_checkcomplex(L, 1); ++ lua_pushcomplex(L, _LF(floor) (_LF(creal)(v)) + _LF(floor) (_LF(cimag)(v))*I); ++#else ++ lua_pushnumber(L, _LF(floor) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + +-static int math_fmod (lua_State *L) { +- lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); ++static int math_fmod (lua_State *L) { ++ /* scalars only */ ++ lua_pushnumber(L, _LF(fmod) (luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; + } + + static int math_modf (lua_State *L) { +- double ip; +- double fp = modf(luaL_checknumber(L, 1), &ip); ++ /* scalars only */ ++ lua_Number ip; ++ lua_Number fp = _LF(modf) (luaL_checknumber(L, 1), &ip); + lua_pushnumber(L, ip); + lua_pushnumber(L, fp); + return 2; + } + + static int math_sqrt (lua_State *L) { +- lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(csqrt) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(sqrt) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_pow (lua_State *L) { +- lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); ++#ifdef LNUM_COMPLEX ++ /* C99 'cpow' gives somewhat inaccurate results (i.e. (-1)^2 = -1+1.2246467991474e-16i). ++ * 'luai_vectpow' smoothens such, reusing it is the reason we need to #include "lnum.h". ++ */ ++ lua_pushcomplex(L, luai_vectpow(luaL_checkcomplex(L,1), luaL_checkcomplex(L,2))); ++#else ++ lua_pushnumber(L, _LF(pow) (luaL_checknumber(L, 1), luaL_checknumber(L, 2))); ++#endif + return 1; + } + + static int math_log (lua_State *L) { +- lua_pushnumber(L, log(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(log) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_log10 (lua_State *L) { +- lua_pushnumber(L, log10(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ /* Not in standard <complex.h> , but easy to calculate: log_a(x) = log_b(x) / log_b(a) ++ */ ++ lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)) / _LF(log) (10)); ++#else ++ lua_pushnumber(L, _LF(log10) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + + static int math_exp (lua_State *L) { +- lua_pushnumber(L, exp(luaL_checknumber(L, 1))); ++#ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(cexp) (luaL_checkcomplex(L,1))); ++#else ++ lua_pushnumber(L, _LF(exp) (luaL_checknumber(L, 1))); ++#endif + return 1; + } + +@@ -138,19 +234,20 @@ static int math_rad (lua_State *L) { + + static int math_frexp (lua_State *L) { + int e; +- lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); ++ lua_pushnumber(L, _LF(frexp) (luaL_checknumber(L, 1), &e)); + lua_pushinteger(L, e); + return 2; + } + + static int math_ldexp (lua_State *L) { +- lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); ++ lua_pushnumber(L, _LF(ldexp) (luaL_checknumber(L, 1), luaL_checkint(L, 2))); + return 1; + } + + + + static int math_min (lua_State *L) { ++ /* scalars only */ + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmin = luaL_checknumber(L, 1); + int i; +@@ -165,6 +262,7 @@ static int math_min (lua_State *L) { + + + static int math_max (lua_State *L) { ++ /* scalars only */ + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmax = luaL_checknumber(L, 1); + int i; +@@ -182,25 +280,20 @@ static int math_random (lua_State *L) { + /* the `%' avoids the (rare) case of r==1, and is needed also because on + some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ + lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; +- switch (lua_gettop(L)) { /* check number of arguments */ +- case 0: { /* no arguments */ +- lua_pushnumber(L, r); /* Number between 0 and 1 */ +- break; +- } +- case 1: { /* only upper limit */ +- int u = luaL_checkint(L, 1); +- luaL_argcheck(L, 1<=u, 1, "interval is empty"); +- lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ +- break; +- } +- case 2: { /* lower and upper limits */ +- int l = luaL_checkint(L, 1); +- int u = luaL_checkint(L, 2); +- luaL_argcheck(L, l<=u, 2, "interval is empty"); +- lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ +- break; +- } +- default: return luaL_error(L, "wrong number of arguments"); ++ int n= lua_gettop(L); /* number of arguments */ ++ if (n==0) { /* no arguments: range [0,1) */ ++ lua_pushnumber(L, r); ++ } else if (n<=2) { /* int range [1,u] or [l,u] */ ++ int l= n==1 ? 1 : luaL_checkint(L, 1); ++ int u = luaL_checkint(L, n); ++ int tmp; ++ lua_Number d; ++ luaL_argcheck(L, l<=u, n, "interval is empty"); ++ d= _LF(floor)(r*(u-l+1)); ++ lua_number2int(tmp,d); ++ lua_pushinteger(L, l+tmp); ++ } else { ++ return luaL_error(L, "wrong number of arguments"); + } + return 1; + } +@@ -211,6 +304,66 @@ static int math_randomseed (lua_State *L + return 0; + } + ++/* ++* Lua 5.1 does not have acosh, asinh, atanh for scalars (not ANSI C) ++*/ ++#if __STDC_VERSION__ >= 199901L ++static int math_acosh (lua_State *L) { ++# ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(cacosh) (luaL_checkcomplex(L,1))); ++# else ++ lua_pushnumber(L, _LF(acosh) (luaL_checknumber(L,1))); ++# endif ++ return 1; ++} ++static int math_asinh (lua_State *L) { ++# ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(casinh) (luaL_checkcomplex(L,1))); ++# else ++ lua_pushnumber(L, _LF(asinh) (luaL_checknumber(L,1))); ++# endif ++ return 1; ++} ++static int math_atanh (lua_State *L) { ++# ifdef LNUM_COMPLEX ++ lua_pushcomplex(L, _LF(catanh) (luaL_checkcomplex(L,1))); ++# else ++ lua_pushnumber(L, _LF(atanh) (luaL_checknumber(L,1))); ++# endif ++ return 1; ++} ++#endif ++ ++/* ++ * C99 complex functions, not covered above. ++*/ ++#ifdef LNUM_COMPLEX ++static int math_arg (lua_State *L) { ++ lua_pushnumber(L, _LF(carg) (luaL_checkcomplex(L,1))); ++ return 1; ++} ++ ++static int math_imag (lua_State *L) { ++ lua_pushnumber(L, _LF(cimag) (luaL_checkcomplex(L,1))); ++ return 1; ++} ++ ++static int math_real (lua_State *L) { ++ lua_pushnumber(L, _LF(creal) (luaL_checkcomplex(L,1))); ++ return 1; ++} ++ ++static int math_conj (lua_State *L) { ++ lua_pushcomplex(L, _LF(conj) (luaL_checkcomplex(L,1))); ++ return 1; ++} ++ ++static int math_proj (lua_State *L) { ++ lua_pushcomplex(L, _LF(cproj) (luaL_checkcomplex(L,1))); ++ return 1; ++} ++#endif ++ + + static const luaL_Reg mathlib[] = { + {"abs", math_abs}, +@@ -241,6 +394,18 @@ static const luaL_Reg mathlib[] = { + {"sqrt", math_sqrt}, + {"tanh", math_tanh}, + {"tan", math_tan}, ++#if __STDC_VERSION__ >= 199901L ++ {"acosh", math_acosh}, ++ {"asinh", math_asinh}, ++ {"atanh", math_atanh}, ++#endif ++#ifdef LNUM_COMPLEX ++ {"arg", math_arg}, ++ {"imag", math_imag}, ++ {"real", math_real}, ++ {"conj", math_conj}, ++ {"proj", math_proj}, ++#endif + {NULL, NULL} + }; + +@@ -252,8 +417,10 @@ LUALIB_API int luaopen_math (lua_State * + luaL_register(L, LUA_MATHLIBNAME, mathlib); + lua_pushnumber(L, PI); + lua_setfield(L, -2, "pi"); +- lua_pushnumber(L, HUGE_VAL); ++ lua_pushnumber(L, HUGE); + lua_setfield(L, -2, "huge"); ++ lua_pushinteger(L, LUA_INTEGER_MAX ); ++ lua_setfield(L, -2, "hugeint"); + #if defined(LUA_COMPAT_MOD) + lua_getfield(L, -1, "fmod"); + lua_setfield(L, -2, "mod"); +--- /dev/null ++++ b/src/lnum.c +@@ -0,0 +1,312 @@ ++/* ++** $Id: lnum.c,v ... $ ++** Internal number model ++** See Copyright Notice in lua.h ++*/ ++ ++#include <stdlib.h> ++#include <math.h> ++#include <ctype.h> ++#include <string.h> ++#include <stdio.h> ++#include <errno.h> ++ ++#define lnum_c ++#define LUA_CORE ++ ++#include "lua.h" ++#include "llex.h" ++#include "lnum.h" ++ ++/* ++** lua_real2str converts a (non-complex) number to a string. ++** lua_str2real converts a string to a (non-complex) number. ++*/ ++#define lua_real2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) ++ ++/* ++* Note: Only 'strtod()' is part of ANSI C; others are C99 and ++* may need '--std=c99' compiler setting (at least on Ubuntu 7.10). ++* ++* Visual C++ 2008 Express does not have 'strtof()', nor 'strtold()'. ++* References to '_strtold()' exist but don't compile. It seems best ++* to leave Windows users with DOUBLE only (or compile with MinGW). ++* ++* In practise, using '(long double)strtod' is a risky thing, since ++* it will cause accuracy loss in reading in numbers, and such losses ++* will pile up in later processing. Get a real 'strtold()' or don't ++* use that mode at all. ++*/ ++#ifdef LNUM_DOUBLE ++# define lua_str2real strtod ++#elif defined(LNUM_FLOAT) ++# define lua_str2real strtof ++#elif defined(LNUM_LDOUBLE) ++# define lua_str2real strtold ++#endif ++ ++#define lua_integer2str(s,v) sprintf((s), LUA_INTEGER_FMT, (v)) ++ ++/* 's' is expected to be LUAI_MAXNUMBER2STR long (enough for any number) ++*/ ++void luaO_num2buf( char *s, const TValue *o ) ++{ ++ lua_Number n; ++ lua_assert( ttisnumber(o) ); ++ ++ /* Reason to handle integers differently is not only speed, but accuracy as ++ * well. We want to make any integer tostring() without roundings, at all. ++ */ ++ if (ttisint(o)) { ++ lua_integer2str( s, ivalue(o) ); ++ return; ++ } ++ n= nvalue_fast(o); ++ lua_real2str(s, n); ++ ++#ifdef LNUM_COMPLEX ++ lua_Number n2= nvalue_img_fast(o); ++ if (n2!=0) { /* Postfix with +-Ni */ ++ int re0= (n == 0); ++ char *s2= re0 ? s : strchr(s,'\0'); ++ if ((!re0) && (n2>0)) *s2++= '+'; ++ lua_real2str( s2, n2 ); ++ strcat(s2,"i"); ++ } ++#endif ++} ++ ++/* ++* If a LUA_TNUMBER has integer value, give it. ++*/ ++int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref ) { ++ lua_Number d; ++ lua_Integer i; ++ ++ lua_assert( ttype(o)==LUA_TNUMBER ); ++ lua_assert( ref ); ++#ifdef LNUM_COMPLEX ++ if (nvalue_img_fast(o)!=0) return 0; ++#endif ++ d= nvalue_fast(o); ++ lua_number2integer(i, d); ++ if (cast_num(i) == d) { ++ *ref= i; return 1; ++ } ++ return 0; ++} ++ ++/* ++ * Lua 5.1.3 (using 'strtod()') allows 0x+hex but not 0+octal. This is good, ++ * and we should NOT use 'autobase' 0 with 'strtoul[l]()' for this reason. ++ * ++ * Lua 5.1.3 allows '0x...' numbers to overflow and lose precision; this is not ++ * good. On Visual C++ 2008, 'strtod()' does not even take them in. Better to ++ * require hex values to fit 'lua_Integer' or give an error that they don't? ++ * ++ * Full hex range (0 .. 0xff..ff) is stored as integers, not to lose any bits. ++ * Numerical value of 0xff..ff will be -1, if used in calculations. ++ * ++ * Returns: TK_INT for a valid integer, '*endptr_ref' updated ++ * TK_NUMBER for seemingly numeric, to be parsed as floating point ++ * 0 for bad characters, not a number (or '0x' out of range) ++ */ ++static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) { ++ char *endptr; ++ /* 'v' gets ULONG_MAX on possible overflow (which is > LUA_INTEGER_MAX); ++ * we don't have to check 'errno' here. ++ */ ++ unsigned LUA_INTEGER v= lua_str2ul(s, &endptr, 10); ++ if (endptr == s) return 0; /* nothing numeric */ ++ if (v==0 && *endptr=='x') { ++ errno= 0; /* needs to be set, 'strtoul[l]' does not clear it */ ++ v= lua_str2ul(endptr+1, &endptr, 16); /* retry as hex, unsigned range */ ++ if (errno==ERANGE) { /* clamped to 0xff..ff */ ++#if (defined(LNUM_INT32) && !defined(LNUM_FLOAT)) || defined(LNUM_LDOUBLE) ++ return TK_NUMBER; /* Allow to be read as floating point (has more integer range) */ ++#else ++ return 0; /* Reject the number */ ++#endif ++ } ++ } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) { ++ return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */ ++ } ++ *res= (lua_Integer)v; ++ *endptr_ref= endptr; ++ return TK_INT; ++} ++ ++/* 0 / TK_NUMBER / TK_INT (/ TK_NUMBER2) */ ++int luaO_str2d (const char *s, lua_Number *res_n, lua_Integer *res_i) { ++ char *endptr; ++ int ret= TK_NUMBER; ++ /* Check integers first, if caller is allowing. ++ * If 'res2'==NULL, they're only looking for floating point. ++ */ ++ if (res_i) { ++ ret= luaO_str2i(s,res_i,&endptr); ++ if (ret==0) return 0; ++ } ++ if (ret==TK_NUMBER) { ++ lua_assert(res_n); ++ /* Note: Visual C++ 2008 Express 'strtod()' does not read in "0x..." ++ * numbers; it will read '0' and spit 'x' as endptr. ++ * This means hex constants not fitting in 'lua_Integer' won't ++ * be read in at all. What to do? ++ */ ++ *res_n = lua_str2real(s, &endptr); ++ if (endptr == s) return 0; /* conversion failed */ ++ /* Visual C++ 2008 'strtod()' does not allow "0x..." input. */ ++#if defined(_MSC_VER) && !defined(LNUM_FLOAT) && !defined(LNUM_INT64) ++ if (*res_n==0 && *endptr=='x') { ++ /* Hex constant too big for 'lua_Integer' but that could fit in 'lua_Number' ++ * integer bits ++ */ ++ unsigned __int64 v= _strtoui64( s, &endptr, 16 ); ++ /* We just let > 64 bit values be clamped to _UI64_MAX (MSDN does not say 'errno'==ERANGE would be set) */ ++ *res_n= cast_num(v); ++ if (*res_n != v) return 0; /* Would have lost accuracy */ ++ } ++#endif ++#ifdef LNUM_COMPLEX ++ if (*endptr == 'i') { endptr++; ret= TK_NUMBER2; } ++#endif ++ } ++ if (*endptr) { ++ while (isspace(cast(unsigned char, *endptr))) endptr++; ++ if (*endptr) return 0; /* invalid trail */ ++ } ++ return ret; ++} ++ ++ ++/* Functions for finding out, when integer operations remain in range ++ * (and doing them). ++ */ ++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { ++ lua_Integer v= ib+ic; /* may overflow */ ++ if (ib>0 && ic>0) { if (v < 0) return 0; /*overflow, use floats*/ } ++ else if (ib<0 && ic<0) { if (v >= 0) return 0; } ++ *r= v; ++ return 1; ++} ++ ++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { ++ lua_Integer v= ib-ic; /* may overflow */ ++ if (ib>=0 && ic<0) { if (v < 0) return 0; /*overflow, use floats*/ } ++ else if (ib<0 && ic>0) { if (v >= 0) return 0; } ++ *r= v; ++ return 1; ++} ++ ++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { ++ if (ib!=LUA_INTEGER_MIN && ic!=LUA_INTEGER_MIN) { ++ lua_Integer b= luai_abs(ib), c= luai_abs(ic); ++ if ( (ib==0) || (LUA_INTEGER_MAX/b >= c) ) { ++ *r= ib*ic; /* no overflow */ ++ return 1; ++ } ++ } else if (ib==0 || ic==0) { ++ *r= 0; return 1; ++ } ++ ++ /* Result can be LUA_INTEGER_MIN; if it is, calculating it using floating ++ * point will not cause accuracy loss. ++ */ ++ if ( luai_nummul( cast_num(ib), cast_num(ic) ) == LUA_INTEGER_MIN ) { ++ *r= LUA_INTEGER_MIN; ++ return 1; ++ } ++ return 0; ++} ++ ++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { ++ /* N/0: leave to float side, to give an error ++ */ ++ if (ic==0) return 0; ++ ++ /* N/LUA_INTEGER_MIN: always non-integer results, or 0 or +1 ++ */ ++ if (ic==LUA_INTEGER_MIN) { ++ if (ib==LUA_INTEGER_MIN) { *r=1; return 1; } ++ if (ib==0) { *r=0; return 1; } ++ ++ /* LUA_INTEGER_MIN (-2^31|63)/N: calculate using float side (either the division ++ * causes non-integer results, or there is no accuracy loss in int->fp->int ++ * conversions (N=2,4,8,..,256 and N=2^30,2^29,..2^23). ++ */ ++ } else if (ib==LUA_INTEGER_MIN) { ++ lua_Number d= luai_numdiv( cast_num(LUA_INTEGER_MIN), cast_num(ic) ); ++ lua_Integer i; lua_number2integer(i,d); ++ if (cast_num(i)==d) { *r= i; return 1; } ++ ++ } else { ++ /* Note: We _can_ use ANSI C mod here, even on negative values, since ++ * we only test for == 0 (the sign would be implementation dependent). ++ */ ++ if (ib%ic == 0) { *r= ib/ic; return 1; } ++ } ++ ++ return 0; ++} ++ ++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { ++ if (ic!=0) { ++ /* ANSI C can be trusted when b%c==0, or when values are non-negative. ++ * b - (floor(b/c) * c) ++ * --> ++ * + +: b - (b/c) * c (b % c can be used) ++ * - -: b - (b/c) * c (b % c could work, but not defined by ANSI C) ++ * 0 -: b - (b/c) * c (=0, b % c could work, but not defined by ANSI C) ++ * - +: b - (b/c-1) * c (when b!=-c) ++ * + -: b - (b/c-1) * c (when b!=-c) ++ * ++ * o MIN%MIN ends up 0, via overflow in calcs but that does not matter. ++ * o MIN%MAX ends up MAX-1 (and other such numbers), also after overflow, ++ * but that does not matter, results do. ++ */ ++ lua_Integer v= ib % ic; ++ if ( v!=0 && (ib<0 || ic<0) ) { ++ v= ib - ((ib/ic) - ((ib<=0 && ic<0) ? 0:1)) * ic; ++ } ++ /* Result should always have same sign as 2nd argument. (PIL2) */ ++ lua_assert( (v<0) ? (ic<0) : (v>0) ? (ic>0) : 1 ); ++ *r= v; ++ return 1; ++ } ++ return 0; /* let float side return NaN */ ++} ++ ++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) { ++ ++ /* In FLOAT/INT32 or FLOAT|DOUBLE/INT64 modes, calculating integer powers ++ * via FP realm may lose accuracy (i.e. 7^11 = 1977326743, which fits int32 ++ * but not 23-bit float mantissa). ++ * ++ * The current solution is dumb, but it works and uses little code. Use of ++ * integer powers is not anticipated to be very frequent (apart from 2^x, ++ * which is separately optimized). ++ */ ++ if (ib==0) *r=0; ++ else if (ic<0) return 0; /* FP realm */ ++ else if (ib==2 && ic < (int)sizeof(lua_Integer)*8-1) *r= ((lua_Integer)1)<<ic; /* 1,2,4,...2^30 | 2^62 optimization */ ++ else if (ic==0) *r=1; ++ else if (luai_abs(ib)==1) *r= (ic%2) ? ib:1; ++ else { ++ lua_Integer x= ib; ++ while( --ic ) { ++ if (!try_mulint( &x, x, ib )) ++ return 0; /* FP realm */ ++ } ++ *r= x; ++ } ++ return 1; ++} ++ ++int try_unmint( lua_Integer *r, lua_Integer ib ) { ++ /* Negating LUA_INTEGER_MIN leaves the range. */ ++ if ( ib != LUA_INTEGER_MIN ) ++ { *r= -ib; return 1; } ++ return 0; ++} ++ +--- /dev/null ++++ b/src/lnum.h +@@ -0,0 +1,116 @@ ++/* ++** $Id: lnum.h,v ... $ ++** Internal Number model ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lnum_h ++#define lnum_h ++ ++#include <math.h> ++ ++#include "lobject.h" ++ ++/* ++** The luai_num* macros define the primitive operations over 'lua_Number's ++** (not 'lua_Integer's, not 'lua_Complex'). ++*/ ++#define luai_numadd(a,b) ((a)+(b)) ++#define luai_numsub(a,b) ((a)-(b)) ++#define luai_nummul(a,b) ((a)*(b)) ++#define luai_numdiv(a,b) ((a)/(b)) ++#define luai_nummod(a,b) ((a) - _LF(floor)((a)/(b))*(b)) ++#define luai_numpow(a,b) (_LF(pow)(a,b)) ++#define luai_numunm(a) (-(a)) ++#define luai_numeq(a,b) ((a)==(b)) ++#define luai_numlt(a,b) ((a)<(b)) ++#define luai_numle(a,b) ((a)<=(b)) ++#define luai_numisnan(a) (!luai_numeq((a), (a))) ++ ++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); ++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); ++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); ++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); ++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); ++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic ); ++int try_unmint( lua_Integer *r, lua_Integer ib ); ++ ++#ifdef LNUM_COMPLEX ++ static inline lua_Complex luai_vectunm( lua_Complex a ) { return -a; } ++ static inline lua_Complex luai_vectadd( lua_Complex a, lua_Complex b ) { return a+b; } ++ static inline lua_Complex luai_vectsub( lua_Complex a, lua_Complex b ) { return a-b; } ++ static inline lua_Complex luai_vectmul( lua_Complex a, lua_Complex b ) { return a*b; } ++ static inline lua_Complex luai_vectdiv( lua_Complex a, lua_Complex b ) { return a/b; } ++ ++/* ++ * C99 does not provide modulus for complex numbers. It most likely is not ++ * meaningful at all. ++ */ ++ ++/* ++ * Complex power ++ * ++ * C99 'cpow' gives inaccurate results for many common cases s.a. (1i)^2 -> ++ * -1+1.2246467991474e-16i (OS X 10.4, gcc 4.0.1 build 5367) ++ * ++ * [(a+bi)^(c+di)] = (r^c) * exp(-d*t) * cos(c*t + d*ln(r)) + ++ * = (r^c) * exp(-d*t) * sin(c*t + d*ln(r)) *i ++ * r = sqrt(a^2+b^2), t = arctan( b/a ) ++ * ++ * Reference: <http://home.att.net/~srschmitt/complexnumbers.html> ++ * Could also be calculated using: x^y = exp(ln(x)*y) ++ * ++ * Note: Defined here (and not in .c) so 'lmathlib.c' can share the ++ * implementation. ++ */ ++ static inline ++ lua_Complex luai_vectpow( lua_Complex a, lua_Complex b ) ++ { ++# if 1 ++ lua_Number ar= _LF(creal)(a), ai= _LF(cimag)(a); ++ lua_Number br= _LF(creal)(b), bi= _LF(cimag)(b); ++ ++ if (ai==0 && bi==0) { /* a^c (real) */ ++ return luai_numpow( ar, br ); ++ } ++ ++ int br_int= (int)br; ++ ++ if ( ai!=0 && bi==0 && br_int==br && br_int!=0 && br_int!=INT_MIN ) { ++ /* (a+bi)^N, N = { +-1,+-2, ... +-INT_MAX } ++ */ ++ lua_Number k= luai_numpow( _LF(sqrt) (ar*ar + ai*ai), br ); ++ lua_Number cos_z, sin_z; ++ ++ /* Situation depends upon c (N) in the following manner: ++ * ++ * N%4==0 => cos(c*t)=1, sin(c*t)=0 ++ * (N*sign(b))%4==1 or (N*sign(b))%4==-3 => cos(c*t)=0, sin(c*t)=1 ++ * N%4==2 or N%4==-2 => cos(c*t)=-1, sin(c*t)=0 ++ * (N*sign(b))%4==-1 or (N*sign(b))%4==3 => cos(c*t)=0, sin(c*t)=-1 ++ */ ++ int br_int_abs = br_int<0 ? -br_int:br_int; ++ ++ switch( (br_int_abs%4) * (br_int<0 ? -1:1) * (ai<0 ? -1:1) ) { ++ case 0: cos_z=1, sin_z=0; break; ++ case 2: case -2: cos_z=-1, sin_z=0; break; ++ case 1: case -3: cos_z=0, sin_z=1; break; ++ case 3: case -1: cos_z=0, sin_z=-1; break; ++ default: lua_assert(0); return 0; ++ } ++ return k*cos_z + (k*sin_z)*I; ++ } ++# endif ++ return _LF(cpow) ( a, b ); ++ } ++#endif ++ ++LUAI_FUNC int luaO_str2d (const char *s, lua_Number *res1, lua_Integer *res2); ++LUAI_FUNC void luaO_num2buf( char *s, const TValue *o ); ++ ++LUAI_FUNC int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref ); ++ ++#define luai_normalize(o) \ ++{ lua_Integer _i; if (tt_integer_valued(o,&_i)) setivalue(o,_i); } ++ ++#endif +--- /dev/null ++++ b/src/lnum_config.h +@@ -0,0 +1,221 @@ ++/* ++** $Id: lnum_config.h,v ... $ ++** Internal Number model ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lnum_config_h ++#define lnum_config_h ++ ++/* ++** Default number modes ++*/ ++#if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE) ++# define LNUM_FLOAT ++#endif ++#if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64) ++# define LNUM_INT32 ++#endif ++ ++/* ++** Require C99 mode for COMPLEX, FLOAT and LDOUBLE (only DOUBLE is ANSI C). ++*/ ++#if defined(LNUM_COMPLEX) && (__STDC_VERSION__ < 199901L) ++# error "Need C99 for complex (use '--std=c99' or similar)" ++#elif defined(LNUM_LDOUBLE) && (__STDC_VERSION__ < 199901L) && !defined(_MSC_VER) ++# error "Need C99 for 'long double' (use '--std=c99' or similar)" ++#elif defined(LNUM_FLOAT) && (__STDC_VERSION__ < 199901L) ++/* LNUM_FLOAT not supported on Windows */ ++# error "Need C99 for 'float' (use '--std=c99' or similar)" ++#endif ++ ++/* ++** Number mode identifier to accompany the version string. ++*/ ++#ifdef LNUM_COMPLEX ++# define _LNUM1 "complex " ++#else ++# define _LNUM1 "" ++#endif ++#ifdef LNUM_DOUBLE ++# define _LNUM2 "double" ++#elif defined(LNUM_FLOAT) ++# define _LNUM2 "float" ++#elif defined(LNUM_LDOUBLE) ++# define _LNUM2 "ldouble" ++#endif ++#ifdef LNUM_INT32 ++# define _LNUM3 "int32" ++#elif defined(LNUM_INT64) ++# define _LNUM3 "int64" ++#elif defined(LNUM_INT16) ++# define _LNUM3 "int16" ++#endif ++#define LUA_LNUM _LNUM1 _LNUM2 " " _LNUM3 ++ ++/* ++** LUA_NUMBER is the type of floating point number in Lua ++** LUA_NUMBER_SCAN is the format for reading numbers. ++** LUA_NUMBER_FMT is the format for writing numbers. ++*/ ++#ifdef LNUM_FLOAT ++# define LUA_NUMBER float ++# define LUA_NUMBER_SCAN "%f" ++# define LUA_NUMBER_FMT "%g" ++#elif (defined LNUM_DOUBLE) ++# define LUA_NUMBER double ++# define LUA_NUMBER_SCAN "%lf" ++# define LUA_NUMBER_FMT "%.14g" ++#elif (defined LNUM_LDOUBLE) ++# define LUA_NUMBER long double ++# define LUA_NUMBER_SCAN "%Lg" ++# define LUA_NUMBER_FMT "%.20Lg" ++#endif ++ ++ ++/* ++** LUAI_MAXNUMBER2STR: size of a buffer fitting any number->string result. ++** ++** double: 24 (sign, x.xxxxxxxxxxxxxxe+nnnn, and \0) ++** int64: 21 (19 digits, sign, and \0) ++** long double: 43 for 128-bit (sign, x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxe+nnnn, and \0) ++** 30 for 80-bit (sign, x.xxxxxxxxxxxxxxxxxxxxe+nnnn, and \0) ++*/ ++#ifdef LNUM_LDOUBLE ++# define _LUAI_MN2S 44 ++#else ++# define _LUAI_MN2S 24 ++#endif ++ ++#ifdef LNUM_COMPLEX ++# define LUAI_MAXNUMBER2STR (2*_LUAI_MN2S) ++#else ++# define LUAI_MAXNUMBER2STR _LUAI_MN2S ++#endif ++ ++/* ++** LUA_INTEGER is the integer type used by lua_pushinteger/lua_tointeger/lua_isinteger. ++** LUA_INTEGER_SCAN is the format for reading integers ++** LUA_INTEGER_FMT is the format for writing integers ++** ++** Note: Visual C++ 2005 does not have 'strtoull()', use '_strtoui64()' instead. ++*/ ++#ifdef LNUM_INT32 ++# if LUAI_BITSINT > 16 ++# define LUA_INTEGER int ++# define LUA_INTEGER_SCAN "%d" ++# define LUA_INTEGER_FMT "%d" ++# else ++/* Note: 'LUA_INTEGER' being 'ptrdiff_t' (as in Lua 5.1) causes problems with ++ * 'printf()' operations. Also 'unsigned ptrdiff_t' is invalid. ++ */ ++# define LUA_INTEGER long ++# define LUA_INTEGER_SCAN "%ld" ++# define LUA_INTEGER_FMT "%ld" ++# endif ++# define LUA_INTEGER_MAX 0x7FFFFFFF /* 2^31-1 */ ++/* */ ++#elif defined(LNUM_INT64) ++# define LUA_INTEGER long long ++# ifdef _MSC_VER ++# define lua_str2ul _strtoui64 ++# else ++# define lua_str2ul strtoull ++# endif ++# define LUA_INTEGER_SCAN "%lld" ++# define LUA_INTEGER_FMT "%lld" ++# define LUA_INTEGER_MAX 0x7fffffffffffffffLL /* 2^63-1 */ ++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX - 1LL) /* -2^63 */ ++/* */ ++#elif defined(LNUM_INT16) ++# if LUAI_BITSINT > 16 ++# define LUA_INTEGER short ++# define LUA_INTEGER_SCAN "%hd" ++# define LUA_INTEGER_FMT "%hd" ++# else ++# define LUA_INTEGER int ++# define LUA_INTEGER_SCAN "%d" ++# define LUA_INTEGER_FMT "%d" ++# endif ++# define LUA_INTEGER_MAX 0x7FFF /* 2^16-1 */ ++#endif ++ ++#ifndef lua_str2ul ++# define lua_str2ul (unsigned LUA_INTEGER)strtoul ++#endif ++#ifndef LUA_INTEGER_MIN ++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1) /* -2^16|32 */ ++#endif ++ ++/* ++@@ lua_number2int is a macro to convert lua_Number to int. ++@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. ++** CHANGE them if you know a faster way to convert a lua_Number to ++** int (with any rounding method and without throwing errors) in your ++** system. In Pentium machines, a naive typecast from double to int ++** in C is extremely slow, so any alternative is worth trying. ++*/ ++ ++/* On a Pentium, resort to a trick */ ++#if defined(LNUM_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ ++ (defined(__i386) || defined (_M_IX86) || defined(__i386__)) ++ ++/* On a Microsoft compiler, use assembler */ ++# if defined(_MSC_VER) ++# define lua_number2int(i,d) __asm fld d __asm fistp i ++# else ++ ++/* the next trick should work on any Pentium, but sometimes clashes ++ with a DirectX idiosyncrasy */ ++union luai_Cast { double l_d; long l_l; }; ++# define lua_number2int(i,d) \ ++ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } ++# endif ++ ++# ifndef LNUM_INT64 ++# define lua_number2integer lua_number2int ++# endif ++ ++/* this option always works, but may be slow */ ++#else ++# define lua_number2int(i,d) ((i)=(int)(d)) ++#endif ++ ++/* Note: Some compilers (OS X gcc 4.0?) may choke on double->long long conversion ++ * since it can lose precision. Others do require 'long long' there. ++ */ ++#ifndef lua_number2integer ++# define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) ++#endif ++ ++/* ++** 'luai_abs()' to give absolute value of 'lua_Integer' ++*/ ++#ifdef LNUM_INT32 ++# define luai_abs abs ++#elif defined(LNUM_INT64) && (__STDC_VERSION__ >= 199901L) ++# define luai_abs llabs ++#else ++# define luai_abs(v) ((v) >= 0 ? (v) : -(v)) ++#endif ++ ++/* ++** LUAI_UACNUMBER is the result of an 'usual argument conversion' over a number. ++** LUAI_UACINTEGER the same, over an integer. ++*/ ++#define LUAI_UACNUMBER double ++#define LUAI_UACINTEGER long ++ ++/* ANSI C only has math funcs for 'double. C99 required for float and long double ++ * variants. ++ */ ++#ifdef LNUM_DOUBLE ++# define _LF(name) name ++#elif defined(LNUM_FLOAT) ++# define _LF(name) name ## f ++#elif defined(LNUM_LDOUBLE) ++# define _LF(name) name ## l ++#endif ++ ++#endif ++ +--- a/src/lobject.c ++++ b/src/lobject.c +@@ -21,7 +21,8 @@ + #include "lstate.h" + #include "lstring.h" + #include "lvm.h" +- ++#include "llex.h" ++#include "lnum.h" + + + const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; +@@ -70,12 +71,31 @@ int luaO_log2 (unsigned int x) { + + + int luaO_rawequalObj (const TValue *t1, const TValue *t2) { +- if (ttype(t1) != ttype(t2)) return 0; ++ if (!ttype_ext_same(t1,t2)) return 0; + else switch (ttype(t1)) { + case LUA_TNIL: + return 1; ++ case LUA_TINT: ++ if (ttype(t2)==LUA_TINT) ++ return ivalue(t1) == ivalue(t2); ++ else { /* t1:int, t2:num */ ++#ifdef LNUM_COMPLEX ++ if (nvalue_img_fast(t2) != 0) return 0; ++#endif ++ /* Avoid doing accuracy losing cast, if possible. */ ++ lua_Integer tmp; ++ if (tt_integer_valued(t2,&tmp)) ++ return ivalue(t1) == tmp; ++ else ++ return luai_numeq( cast_num(ivalue(t1)), nvalue_fast(t2) ); ++ } + case LUA_TNUMBER: +- return luai_numeq(nvalue(t1), nvalue(t2)); ++ if (ttype(t2)==LUA_TINT) ++ return luaO_rawequalObj(t2, t1); /* swap LUA_TINT to left */ ++#ifdef LNUM_COMPLEX ++ if (!luai_numeq(nvalue_img_fast(t1), nvalue_img_fast(t2))) return 0; ++#endif ++ return luai_numeq(nvalue_fast(t1), nvalue_fast(t2)); + case LUA_TBOOLEAN: + return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ + case LUA_TLIGHTUSERDATA: +@@ -86,21 +106,6 @@ int luaO_rawequalObj (const TValue *t1, + } + } + +- +-int luaO_str2d (const char *s, lua_Number *result) { +- char *endptr; +- *result = lua_str2number(s, &endptr); +- if (endptr == s) return 0; /* conversion failed */ +- if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ +- *result = cast_num(strtoul(s, &endptr, 16)); +- if (*endptr == '\0') return 1; /* most common case */ +- while (isspace(cast(unsigned char, *endptr))) endptr++; +- if (*endptr != '\0') return 0; /* invalid trailing characters? */ +- return 1; +-} +- +- +- + static void pushstr (lua_State *L, const char *str) { + setsvalue2s(L, L->top, luaS_new(L, str)); + incr_top(L); +@@ -131,7 +136,11 @@ const char *luaO_pushvfstring (lua_State + break; + } + case 'd': { +- setnvalue(L->top, cast_num(va_arg(argp, int))); ++ /* This is tricky for 64-bit integers; maybe they even cannot be ++ * supported on all compilers; depends on the conversions applied to ++ * variable argument lists. TBD: test! ++ */ ++ setivalue(L->top, (lua_Integer) va_arg(argp, l_uacInteger)); + incr_top(L); + break; + } +@@ -212,3 +221,4 @@ void luaO_chunkid (char *out, const char + } + } + } ++ +--- a/src/lobject.h ++++ b/src/lobject.h +@@ -17,7 +17,11 @@ + + + /* tags for values visible from Lua */ +-#define LAST_TAG LUA_TTHREAD ++#if LUA_TINT > LUA_TTHREAD ++# define LAST_TAG LUA_TINT ++#else ++# define LAST_TAG LUA_TTHREAD ++#endif + + #define NUM_TAGS (LAST_TAG+1) + +@@ -59,7 +63,12 @@ typedef struct GCheader { + typedef union { + GCObject *gc; + void *p; ++#ifdef LNUM_COMPLEX ++ lua_Complex n; ++#else + lua_Number n; ++#endif ++ lua_Integer i; + int b; + } Value; + +@@ -77,7 +86,11 @@ typedef struct lua_TValue { + + /* Macros to test type */ + #define ttisnil(o) (ttype(o) == LUA_TNIL) +-#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) ++#define ttisint(o) (ttype(o) == LUA_TINT) ++#define ttisnumber(o) ((ttype(o) == LUA_TINT) || (ttype(o) == LUA_TNUMBER)) ++#ifdef LNUM_COMPLEX ++# define ttiscomplex(o) ((ttype(o) == LUA_TNUMBER) && (nvalue_img_fast(o)!=0)) ++#endif + #define ttisstring(o) (ttype(o) == LUA_TSTRING) + #define ttistable(o) (ttype(o) == LUA_TTABLE) + #define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) +@@ -90,7 +103,25 @@ typedef struct lua_TValue { + #define ttype(o) ((o)->tt) + #define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) + #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) +-#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) ++ ++#define ttype_ext(o) ( ttype(o) == LUA_TINT ? LUA_TNUMBER : ttype(o) ) ++#define ttype_ext_same(o1,o2) ( (ttype(o1)==ttype(o2)) || (ttisnumber(o1) && ttisnumber(o2)) ) ++ ++/* '_fast' variants are for cases where 'ttype(o)' is known to be LUA_TNUMBER. ++ */ ++#ifdef LNUM_COMPLEX ++# define nvalue_complex_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n ) ++# define nvalue_fast(o) ( _LF(creal) ( nvalue_complex_fast(o) ) ) ++# define nvalue_img_fast(o) ( _LF(cimag) ( nvalue_complex_fast(o) ) ) ++# define nvalue_complex(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? (o)->value.i : (o)->value.n ) ++# define nvalue_img(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? 0 : _LF(cimag)( (o)->value.n ) ) ++# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : _LF(creal)((o)->value.n) ) ++#else ++# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : (o)->value.n ) ++# define nvalue_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n ) ++#endif ++#define ivalue(o) check_exp( ttype(o)==LUA_TINT, (o)->value.i ) ++ + #define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) + #define tsvalue(o) (&rawtsvalue(o)->tsv) + #define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) +@@ -116,8 +147,27 @@ typedef struct lua_TValue { + /* Macros to set values */ + #define setnilvalue(obj) ((obj)->tt=LUA_TNIL) + +-#define setnvalue(obj,x) \ +- { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } ++/* Must not have side effects, 'x' may be expression. ++*/ ++#define setivalue(obj,x) \ ++ { TValue *i_o=(obj); i_o->value.i=(x); i_o->tt=LUA_TINT; } ++ ++# define setnvalue(obj,x) \ ++ { TValue *i_o=(obj); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; } ++ ++/* Note: Complex always has "inline", both are C99. ++*/ ++#ifdef LNUM_COMPLEX ++ static inline void setnvalue_complex_fast( TValue *obj, lua_Complex x ) { ++ lua_assert( _LF(cimag)(x) != 0 ); ++ obj->value.n= x; obj->tt= LUA_TNUMBER; ++ } ++ static inline void setnvalue_complex( TValue *obj, lua_Complex x ) { ++ if (_LF(cimag)(x) == 0) { setnvalue(obj, _LF(creal)(x)); } ++ else { obj->value.n= x; obj->tt= LUA_TNUMBER; } ++ } ++#endif ++ + + #define setpvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } +@@ -155,9 +205,6 @@ typedef struct lua_TValue { + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ + checkliveness(G(L),i_o); } + +- +- +- + #define setobj(L,obj1,obj2) \ + { const TValue *o2=(obj2); TValue *o1=(obj1); \ + o1->value = o2->value; o1->tt=o2->tt; \ +@@ -185,8 +232,11 @@ typedef struct lua_TValue { + + #define setttype(obj, tt) (ttype(obj) = (tt)) + +- +-#define iscollectable(o) (ttype(o) >= LUA_TSTRING) ++#if LUA_TINT >= LUA_TSTRING ++# define iscollectable(o) ((ttype(o) >= LUA_TSTRING) && (ttype(o) != LUA_TINT)) ++#else ++# define iscollectable(o) (ttype(o) >= LUA_TSTRING) ++#endif + + + +@@ -370,12 +420,10 @@ LUAI_FUNC int luaO_log2 (unsigned int x) + LUAI_FUNC int luaO_int2fb (unsigned int x); + LUAI_FUNC int luaO_fb2int (int x); + LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); +-LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); + LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, + va_list argp); + LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); + LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); + +- + #endif + +--- a/src/loslib.c ++++ b/src/loslib.c +@@ -186,15 +186,30 @@ static int os_time (lua_State *L) { + } + if (t == (time_t)(-1)) + lua_pushnil(L); +- else +- lua_pushnumber(L, (lua_Number)t); ++ else { ++ /* On float systems the pushed value must be an integer, NOT a number. ++ * Otherwise, accuracy is lost in the time_t->float conversion. ++ */ ++#ifdef LNUM_FLOAT ++ lua_pushinteger(L, (lua_Integer) t); ++#else ++ lua_pushnumber(L, (lua_Number) t); ++#endif ++ } + return 1; + } + + + static int os_difftime (lua_State *L) { ++#ifdef LNUM_FLOAT ++ lua_Integer i= (lua_Integer) ++ difftime( (time_t)(luaL_checkinteger(L, 1)), ++ (time_t)(luaL_optinteger(L, 2, 0))); ++ lua_pushinteger(L, i); ++#else + lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), + (time_t)(luaL_optnumber(L, 2, 0)))); ++#endif + return 1; + } + +--- a/src/lparser.c ++++ b/src/lparser.c +@@ -33,7 +33,6 @@ + + #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) + +- + /* + ** nodes for block list (list of active blocks) + */ +@@ -72,7 +71,7 @@ static void errorlimit (FuncState *fs, i + const char *msg = (fs->f->linedefined == 0) ? + luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : + luaO_pushfstring(fs->L, "function at line %d has more than %d %s", +- fs->f->linedefined, limit, what); ++ (fs->f->linedefined), limit, what); + luaX_lexerror(fs->ls, msg, 0); + } + +@@ -733,6 +732,18 @@ static void simpleexp (LexState *ls, exp + v->u.nval = ls->t.seminfo.r; + break; + } ++ case TK_INT: { ++ init_exp(v, VKINT, 0); ++ v->u.ival = ls->t.seminfo.i; ++ break; ++ } ++#ifdef LNUM_COMPLEX ++ case TK_NUMBER2: { ++ init_exp(v, VKNUM2, 0); ++ v->u.nval = ls->t.seminfo.r; ++ break; ++ } ++#endif + case TK_STRING: { + codestring(ls, v, ls->t.seminfo.ts); + break; +@@ -1079,7 +1090,7 @@ static void fornum (LexState *ls, TStrin + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else { /* default step = 1 */ +- luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); ++ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_integerK(fs, 1)); + luaK_reserveregs(fs, 1); + } + forbody(ls, base, line, 1, 1); +--- a/src/lparser.h ++++ b/src/lparser.h +@@ -31,7 +31,11 @@ typedef enum { + VRELOCABLE, /* info = instruction pc */ + VNONRELOC, /* info = result register */ + VCALL, /* info = instruction pc */ +- VVARARG /* info = instruction pc */ ++ VVARARG, /* info = instruction pc */ ++ VKINT /* ival = integer value */ ++#ifdef LNUM_COMPLEX ++ ,VKNUM2 /* nval = imaginary value */ ++#endif + } expkind; + + typedef struct expdesc { +@@ -39,6 +43,7 @@ typedef struct expdesc { + union { + struct { int info, aux; } s; + lua_Number nval; ++ lua_Integer ival; + } u; + int t; /* patch list of `exit when true' */ + int f; /* patch list of `exit when false' */ +--- a/src/lstrlib.c ++++ b/src/lstrlib.c +@@ -43,8 +43,8 @@ static ptrdiff_t posrelat (ptrdiff_t pos + static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); +- ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); +- ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); ++ ptrdiff_t start = posrelat(luaL_checkint32(L, 2), l); ++ ptrdiff_t end = posrelat(luaL_optint32(L, 3, -1), l); + if (start < 1) start = 1; + if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; + if (start <= end) +@@ -106,8 +106,8 @@ static int str_rep (lua_State *L) { + static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); +- ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); +- ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); ++ ptrdiff_t posi = posrelat(luaL_optint32(L, 2, 1), l); ++ ptrdiff_t pose = posrelat(luaL_optint32(L, 3, posi), l); + int n, i; + if (posi <= 0) posi = 1; + if ((size_t)pose > l) pose = l; +@@ -496,7 +496,7 @@ static int str_find_aux (lua_State *L, i + size_t l1, l2; + const char *s = luaL_checklstring(L, 1, &l1); + const char *p = luaL_checklstring(L, 2, &l2); +- ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; ++ ptrdiff_t init = posrelat(luaL_optint32(L, 3, 1), l1) - 1; + if (init < 0) init = 0; + else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; + if (find && (lua_toboolean(L, 4) || /* explicit request? */ +@@ -690,7 +690,7 @@ static int str_gsub (lua_State *L) { + ** maximum size of each format specification (such as '%-099.99d') + ** (+10 accounts for %99.99x plus margin of error) + */ +-#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) ++#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTEGER_FMT)-2 + 10) + + + static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { +@@ -747,9 +747,9 @@ static const char *scanformat (lua_State + static void addintlen (char *form) { + size_t l = strlen(form); + char spec = form[l - 1]; +- strcpy(form + l - 1, LUA_INTFRMLEN); +- form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; +- form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; ++ const char *tmp= LUA_INTEGER_FMT; /* "%lld" or "%ld" */ ++ strcpy(form + l - 1, tmp+1); ++ form[l + sizeof(LUA_INTEGER_FMT)-4] = spec; + } + + +@@ -779,12 +779,12 @@ static int str_format (lua_State *L) { + } + case 'd': case 'i': { + addintlen(form); +- sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); ++ sprintf(buff, form, luaL_checkinteger(L, arg)); + break; + } + case 'o': case 'u': case 'x': case 'X': { + addintlen(form); +- sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); ++ sprintf(buff, form, (unsigned LUA_INTEGER)luaL_checkinteger(L, arg)); + break; + } + case 'e': case 'E': case 'f': +--- a/src/ltable.c ++++ b/src/ltable.c +@@ -33,6 +33,7 @@ + #include "lobject.h" + #include "lstate.h" + #include "ltable.h" ++#include "lnum.h" + + + /* +@@ -51,25 +52,15 @@ + + #define hashstr(t,str) hashpow2(t, (str)->tsv.hash) + #define hashboolean(t,p) hashpow2(t, p) +- ++#define hashint(t,i) hashpow2(t,i) + + /* + ** for some types, it is better to avoid modulus by power of 2, as + ** they tend to have many 2 factors. + */ + #define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) +- +- + #define hashpointer(t,p) hashmod(t, IntPoint(p)) + +- +-/* +-** number of ints inside a lua_Number +-*/ +-#define numints cast_int(sizeof(lua_Number)/sizeof(int)) +- +- +- + #define dummynode (&dummynode_) + + static const Node dummynode_ = { +@@ -80,27 +71,46 @@ static const Node dummynode_ = { + + /* + ** hash for lua_Numbers ++** ++** for non-complex modes, never called with 'lua_Integer' value range (s.a. 0) + */ + static Node *hashnum (const Table *t, lua_Number n) { +- unsigned int a[numints]; +- int i; +- if (luai_numeq(n, 0)) /* avoid problems with -0 */ +- return gnode(t, 0); +- memcpy(a, &n, sizeof(a)); +- for (i = 1; i < numints; i++) a[0] += a[i]; +- return hashmod(t, a[0]); ++ const unsigned int *p= cast(const unsigned int *,&n); ++ unsigned int sum= *p; ++ unsigned int m= sizeof(lua_Number)/sizeof(int); ++ unsigned int i; ++ /* OS X Intel has 'm'==4 and gives "Bus error" if the last integer of ++ * 'n' is read; the actual size of long double is only 80 bits = 10 bytes. ++ * Linux x86 has 'm'==3, and does not require reduction. ++ */ ++#if defined(LNUM_LDOUBLE) && defined(__i386__) ++ if (m>3) m--; ++#endif ++ for (i = 1; i < m; i++) sum += p[i]; ++ return hashmod(t, sum); + } + + +- + /* + ** returns the `main' position of an element in a table (that is, the index + ** of its hash value) ++** ++** Floating point numbers with integer value give the hash position of the ++** integer (so they use the same table position). + */ + static Node *mainposition (const Table *t, const TValue *key) { ++ lua_Integer i; + switch (ttype(key)) { + case LUA_TNUMBER: +- return hashnum(t, nvalue(key)); ++ if (tt_integer_valued(key,&i)) ++ return hashint(t, i); ++#ifdef LNUM_COMPLEX ++ if (nvalue_img_fast(key)!=0 && luai_numeq(nvalue_fast(key),0)) ++ return gnode(t, 0); /* 0 and -0 to give same hash */ ++#endif ++ return hashnum(t, nvalue_fast(key)); ++ case LUA_TINT: ++ return hashint(t, ivalue(key)); + case LUA_TSTRING: + return hashstr(t, rawtsvalue(key)); + case LUA_TBOOLEAN: +@@ -116,16 +126,20 @@ static Node *mainposition (const Table * + /* + ** returns the index for `key' if `key' is an appropriate key to live in + ** the array part of the table, -1 otherwise. ++** ++** Anything <=0 is taken as not being in the array part. + */ +-static int arrayindex (const TValue *key) { +- if (ttisnumber(key)) { +- lua_Number n = nvalue(key); +- int k; +- lua_number2int(k, n); +- if (luai_numeq(cast_num(k), n)) +- return k; ++static int arrayindex (const TValue *key, int max) { ++ lua_Integer k; ++ switch( ttype(key) ) { ++ case LUA_TINT: ++ k= ivalue(key); break; ++ case LUA_TNUMBER: ++ if (tt_integer_valued(key,&k)) break; ++ default: ++ return -1; /* not to be used as array index */ + } +- return -1; /* `key' did not match some condition */ ++ return ((k>0) && (k <= max)) ? cast_int(k) : -1; + } + + +@@ -137,8 +151,8 @@ static int arrayindex (const TValue *key + static int findindex (lua_State *L, Table *t, StkId key) { + int i; + if (ttisnil(key)) return -1; /* first iteration */ +- i = arrayindex(key); +- if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ ++ i = arrayindex(key, t->sizearray); ++ if (i>0) /* inside array part? */ + return i-1; /* yes; that's the index (corrected to C) */ + else { + Node *n = mainposition(t, key); +@@ -163,7 +177,7 @@ int luaH_next (lua_State *L, Table *t, S + int i = findindex(L, t, key); /* find original element */ + for (i++; i < t->sizearray; i++) { /* try first array part */ + if (!ttisnil(&t->array[i])) { /* a non-nil value? */ +- setnvalue(key, cast_num(i+1)); ++ setivalue(key, i+1); + setobj2s(L, key+1, &t->array[i]); + return 1; + } +@@ -209,8 +223,8 @@ static int computesizes (int nums[], int + + + static int countint (const TValue *key, int *nums) { +- int k = arrayindex(key); +- if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ ++ int k = arrayindex(key,MAXASIZE); ++ if (k>0) { /* appropriate array index? */ + nums[ceillog2(k)]++; /* count as such */ + return 1; + } +@@ -308,7 +322,7 @@ static void resize (lua_State *L, Table + /* re-insert elements from vanishing slice */ + for (i=nasize; i<oldasize; i++) { + if (!ttisnil(&t->array[i])) +- setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); ++ setobjt2t(L, luaH_setint(L, t, i+1), &t->array[i]); + } + /* shrink array */ + luaM_reallocvector(L, t->array, oldasize, nasize, TValue); +@@ -409,7 +423,9 @@ static TValue *newkey (lua_State *L, Tab + othern = mainposition(t, key2tval(mp)); + if (othern != mp) { /* is colliding node out of its main position? */ + /* yes; move colliding node into free position */ +- while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ ++ while (gnext(othern) != mp) { ++ othern = gnext(othern); /* find previous */ ++ } + gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ + *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + gnext(mp) = NULL; /* now `mp' is free */ +@@ -432,17 +448,18 @@ static TValue *newkey (lua_State *L, Tab + /* + ** search function for integers + */ +-const TValue *luaH_getnum (Table *t, int key) { ++const TValue *luaH_getint (Table *t, lua_Integer key) { + /* (1 <= key && key <= t->sizearray) */ + if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) + return &t->array[key-1]; + else { +- lua_Number nk = cast_num(key); +- Node *n = hashnum(t, nk); ++ Node *n = hashint(t, key); + do { /* check whether `key' is somewhere in the chain */ +- if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) ++ if (ttisint(gkey(n)) && (ivalue(gkey(n)) == key)) { + return gval(n); /* that's it */ +- else n = gnext(n); ++ } else { ++ n = gnext(n); ++ } + } while (n); + return luaO_nilobject; + } +@@ -470,14 +487,12 @@ const TValue *luaH_get (Table *t, const + switch (ttype(key)) { + case LUA_TNIL: return luaO_nilobject; + case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); ++ case LUA_TINT: return luaH_getint(t, ivalue(key)); + case LUA_TNUMBER: { +- int k; +- lua_Number n = nvalue(key); +- lua_number2int(k, n); +- if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ +- return luaH_getnum(t, k); /* use specialized version */ +- /* else go through */ +- } ++ lua_Integer i; ++ if (tt_integer_valued(key,&i)) ++ return luaH_getint(t,i); ++ } /* pass through */ + default: { + Node *n = mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ +@@ -498,20 +513,25 @@ TValue *luaH_set (lua_State *L, Table *t + return cast(TValue *, p); + else { + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); +- else if (ttisnumber(key) && luai_numisnan(nvalue(key))) +- luaG_runerror(L, "table index is NaN"); ++ else if (ttype(key)==LUA_TNUMBER) { ++ lua_Integer k; ++ if (luai_numisnan(nvalue_fast(key))) ++ luaG_runerror(L, "table index is NaN"); ++ if (tt_integer_valued(key,&k)) ++ return luaH_setint(L, t, k); ++ } + return newkey(L, t, key); + } + } + + +-TValue *luaH_setnum (lua_State *L, Table *t, int key) { +- const TValue *p = luaH_getnum(t, key); ++TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key) { ++ const TValue *p = luaH_getint(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + TValue k; +- setnvalue(&k, cast_num(key)); ++ setivalue(&k, key); + return newkey(L, t, &k); + } + } +@@ -533,20 +553,21 @@ static int unbound_search (Table *t, uns + unsigned int i = j; /* i is zero or a present index */ + j++; + /* find `i' and `j' such that i is present and j is not */ +- while (!ttisnil(luaH_getnum(t, j))) { ++ while (!ttisnil(luaH_getint(t, j))) { + i = j; + j *= 2; + if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ + /* table was built with bad purposes: resort to linear search */ +- i = 1; +- while (!ttisnil(luaH_getnum(t, i))) i++; +- return i - 1; ++ for( i = 1; i<MAX_INT+1; i++ ) { ++ if (ttisnil(luaH_getint(t, i))) break; ++ } ++ return i - 1; /* up to MAX_INT */ + } + } + /* now do a binary search between them */ + while (j - i > 1) { + unsigned int m = (i+j)/2; +- if (ttisnil(luaH_getnum(t, m))) j = m; ++ if (ttisnil(luaH_getint(t, m))) j = m; + else i = m; + } + return i; +--- a/src/ltable.h ++++ b/src/ltable.h +@@ -18,8 +18,8 @@ + #define key2tval(n) (&(n)->i_key.tvk) + + +-LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); +-LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); ++LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); ++LUAI_FUNC TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key); + LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); + LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); + LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); +--- a/src/ltm.c ++++ b/src/ltm.c +@@ -19,7 +19,6 @@ + #include "ltm.h" + + +- + const char *const luaT_typenames[] = { + "nil", "boolean", "userdata", "number", + "string", "table", "function", "userdata", "thread", +@@ -67,6 +66,9 @@ const TValue *luaT_gettmbyobj (lua_State + case LUA_TUSERDATA: + mt = uvalue(o)->metatable; + break; ++ case LUA_TINT: ++ mt = G(L)->mt[LUA_TNUMBER]; ++ break; + default: + mt = G(L)->mt[ttype(o)]; + } +--- a/src/lua.c ++++ b/src/lua.c +@@ -16,7 +16,7 @@ + + #include "lauxlib.h" + #include "lualib.h" +- ++#include "llimits.h" + + + static lua_State *globalL = NULL; +@@ -382,6 +382,15 @@ int main (int argc, char **argv) { + l_message(argv[0], "cannot create state: not enough memory"); + return EXIT_FAILURE; + } ++ /* Checking 'sizeof(lua_Integer)' cannot be made in preprocessor on all compilers. ++ */ ++#ifdef LNUM_INT16 ++ lua_assert( sizeof(lua_Integer) == 2 ); ++#elif defined(LNUM_INT32) ++ lua_assert( sizeof(lua_Integer) == 4 ); ++#elif defined(LNUM_INT64) ++ lua_assert( sizeof(lua_Integer) == 8 ); ++#endif + s.argc = argc; + s.argv = argv; + status = lua_cpcall(L, &pmain, &s); +--- a/src/lua.h ++++ b/src/lua.h +@@ -19,7 +19,7 @@ + #define LUA_VERSION "Lua 5.1" + #define LUA_RELEASE "Lua 5.1.5" + #define LUA_VERSION_NUM 501 +-#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio" ++#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio" " (" LUA_LNUM ")" + #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" + + +@@ -71,6 +71,16 @@ typedef void * (*lua_Alloc) (void *ud, v + */ + #define LUA_TNONE (-1) + ++/* LUA_TINT is an internal type, not visible to applications. There are three ++ * potential values where it can be tweaked to (code autoadjusts to these): ++ * ++ * -2: not 'usual' type value; good since 'LUA_TINT' is not part of the API ++ * LUA_TNUMBER+1: shifts other type values upwards, breaking binary compatibility ++ * not acceptable for 5.1, maybe 5.2 onwards? ++ * 9: greater than existing (5.1) type values. ++*/ ++#define LUA_TINT (-2) ++ + #define LUA_TNIL 0 + #define LUA_TBOOLEAN 1 + #define LUA_TLIGHTUSERDATA 2 +@@ -139,6 +149,8 @@ LUA_API int (lua_isuserdata) + LUA_API int (lua_type) (lua_State *L, int idx); + LUA_API const char *(lua_typename) (lua_State *L, int tp); + ++LUA_API int (lua_isinteger) (lua_State *L, int idx); ++ + LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); + LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); + LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); +@@ -244,6 +256,19 @@ LUA_API lua_Alloc (lua_getallocf) (lua_S + LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); + + ++/* ++* It is unnecessary to break Lua C API 'lua_tonumber()' compatibility, just ++* because the Lua number type is complex. Most C modules would use scalars ++* only. We'll introduce new 'lua_tocomplex' and 'lua_pushcomplex' for when ++* the module really wants to use them. ++*/ ++#ifdef LNUM_COMPLEX ++ #include <complex.h> ++ typedef LUA_NUMBER complex lua_Complex; ++ LUA_API lua_Complex (lua_tocomplex) (lua_State *L, int idx); ++ LUA_API void (lua_pushcomplex) (lua_State *L, lua_Complex v); ++#endif ++ + + /* + ** =============================================================== +@@ -268,7 +293,12 @@ LUA_API void lua_setallocf (lua_State *L + #define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) + #define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) + #define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +-#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) ++ ++#if LUA_TINT < 0 ++# define lua_isnoneornil(L, n) ( (lua_type(L,(n)) <= 0) && (lua_type(L,(n)) != LUA_TINT) ) ++#else ++# define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) ++#endif + + #define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) +@@ -386,3 +416,4 @@ struct lua_Debug { + + + #endif ++ +--- a/src/luaconf.h ++++ b/src/luaconf.h +@@ -10,7 +10,9 @@ + + #include <limits.h> + #include <stddef.h> +- ++#ifdef lua_assert ++# include <assert.h> ++#endif + + /* + ** ================================================================== +@@ -136,14 +138,38 @@ + + + /* +-@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. +-** CHANGE that if ptrdiff_t is not adequate on your machine. (On most +-** machines, ptrdiff_t gives a good choice between int or long.) ++@@ LUAI_BITSINT defines the number of bits in an int. ++** CHANGE here if Lua cannot automatically detect the number of bits of ++** your machine. Probably you do not need to change this. + */ +-#define LUA_INTEGER ptrdiff_t ++/* avoid overflows in comparison */ ++#if INT_MAX-20 < 32760 ++#define LUAI_BITSINT 16 ++#elif INT_MAX > 2147483640L ++/* int has at least 32 bits */ ++#define LUAI_BITSINT 32 ++#else ++#error "you must define LUA_BITSINT with number of bits in an integer" ++#endif + + + /* ++@@ LNUM_DOUBLE | LNUM_FLOAT | LNUM_LDOUBLE: Generic Lua number mode ++@@ LNUM_INT32 | LNUM_INT64: Integer type ++@@ LNUM_COMPLEX: Define for using 'a+bi' numbers ++@@ ++@@ You can combine LNUM_xxx but only one of each group. I.e. '-DLNUM_FLOAT ++@@ -DLNUM_INT32 -DLNUM_COMPLEX' gives float range complex numbers, with ++@@ 32-bit scalar integer range optimized. ++** ++** These are kept in a separate configuration file mainly for ease of patching ++** (can be changed if integerated to Lua proper). ++*/ ++/*#define LNUM_DOUBLE*/ ++/*#define LNUM_INT32*/ ++#include "lnum_config.h" ++ ++/* + @@ LUA_API is a mark for all core API functions. + @@ LUALIB_API is a mark for all standard library functions. + ** CHANGE them if you need to define those functions in some special way. +@@ -383,22 +409,6 @@ + + + /* +-@@ LUAI_BITSINT defines the number of bits in an int. +-** CHANGE here if Lua cannot automatically detect the number of bits of +-** your machine. Probably you do not need to change this. +-*/ +-/* avoid overflows in comparison */ +-#if INT_MAX-20 < 32760 +-#define LUAI_BITSINT 16 +-#elif INT_MAX > 2147483640L +-/* int has at least 32 bits */ +-#define LUAI_BITSINT 32 +-#else +-#error "you must define LUA_BITSINT with number of bits in an integer" +-#endif +- +- +-/* + @@ LUAI_UINT32 is an unsigned integer with at least 32 bits. + @@ LUAI_INT32 is an signed integer with at least 32 bits. + @@ LUAI_UMEM is an unsigned integer big enough to count the total +@@ -425,6 +435,15 @@ + #define LUAI_MEM long + #endif + ++/* ++@@ LUAI_BOOL carries 0 and nonzero (normally 1). It may be defined as 'char' ++** (to save memory), 'int' (for speed), 'bool' (for C++) or '_Bool' (C99) ++*/ ++#ifdef __cplusplus ++# define LUAI_BOOL bool ++#else ++# define LUAI_BOOL int ++#endif + + /* + @@ LUAI_MAXCALLS limits the number of nested calls. +@@ -490,101 +509,6 @@ + /* }================================================================== */ + + +- +- +-/* +-** {================================================================== +-@@ LUA_NUMBER is the type of numbers in Lua. +-** CHANGE the following definitions only if you want to build Lua +-** with a number type different from double. You may also need to +-** change lua_number2int & lua_number2integer. +-** =================================================================== +-*/ +- +-#define LUA_NUMBER_DOUBLE +-#define LUA_NUMBER double +- +-/* +-@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' +-@* over a number. +-*/ +-#define LUAI_UACNUMBER double +- +- +-/* +-@@ LUA_NUMBER_SCAN is the format for reading numbers. +-@@ LUA_NUMBER_FMT is the format for writing numbers. +-@@ lua_number2str converts a number to a string. +-@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. +-@@ lua_str2number converts a string to a number. +-*/ +-#define LUA_NUMBER_SCAN "%lf" +-#define LUA_NUMBER_FMT "%.14g" +-#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +-#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ +-#define lua_str2number(s,p) strtod((s), (p)) +- +- +-/* +-@@ The luai_num* macros define the primitive operations over numbers. +-*/ +-#if defined(LUA_CORE) +-#include <math.h> +-#define luai_numadd(a,b) ((a)+(b)) +-#define luai_numsub(a,b) ((a)-(b)) +-#define luai_nummul(a,b) ((a)*(b)) +-#define luai_numdiv(a,b) ((a)/(b)) +-#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) +-#define luai_numpow(a,b) (pow(a,b)) +-#define luai_numunm(a) (-(a)) +-#define luai_numeq(a,b) ((a)==(b)) +-#define luai_numlt(a,b) ((a)<(b)) +-#define luai_numle(a,b) ((a)<=(b)) +-#define luai_numisnan(a) (!luai_numeq((a), (a))) +-#endif +- +- +-/* +-@@ lua_number2int is a macro to convert lua_Number to int. +-@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. +-** CHANGE them if you know a faster way to convert a lua_Number to +-** int (with any rounding method and without throwing errors) in your +-** system. In Pentium machines, a naive typecast from double to int +-** in C is extremely slow, so any alternative is worth trying. +-*/ +- +-/* On a Pentium, resort to a trick */ +-#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ +- (defined(__i386) || defined (_M_IX86) || defined(__i386__)) +- +-/* On a Microsoft compiler, use assembler */ +-#if defined(_MSC_VER) +- +-#define lua_number2int(i,d) __asm fld d __asm fistp i +-#define lua_number2integer(i,n) lua_number2int(i, n) +- +-/* the next trick should work on any Pentium, but sometimes clashes +- with a DirectX idiosyncrasy */ +-#else +- +-union luai_Cast { double l_d; long l_l; }; +-#define lua_number2int(i,d) \ +- { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } +-#define lua_number2integer(i,n) lua_number2int(i, n) +- +-#endif +- +- +-/* this option always works, but may be slow */ +-#else +-#define lua_number2int(i,d) ((i)=(int)(d)) +-#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) +- +-#endif +- +-/* }================================================================== */ +- +- + /* + @@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. + ** CHANGE it if your system requires alignments larger than double. (For +@@ -728,28 +652,6 @@ union luai_Cast { double l_d; long l_l; + #define luai_userstateyield(L,n) ((void)L) + + +-/* +-@@ LUA_INTFRMLEN is the length modifier for integer conversions +-@* in 'string.format'. +-@@ LUA_INTFRM_T is the integer type correspoding to the previous length +-@* modifier. +-** CHANGE them if your system supports long long or does not support long. +-*/ +- +-#if defined(LUA_USELONGLONG) +- +-#define LUA_INTFRMLEN "ll" +-#define LUA_INTFRM_T long long +- +-#else +- +-#define LUA_INTFRMLEN "l" +-#define LUA_INTFRM_T long +- +-#endif +- +- +- + /* =================================================================== */ + + /* +--- a/src/lundump.c ++++ b/src/lundump.c +@@ -73,6 +73,13 @@ static lua_Number LoadNumber(LoadState* + return x; + } + ++static lua_Integer LoadInteger(LoadState* S) ++{ ++ lua_Integer x; ++ LoadVar(S,x); ++ return x; ++} ++ + static TString* LoadString(LoadState* S) + { + size_t size; +@@ -119,6 +126,9 @@ static void LoadConstants(LoadState* S, + case LUA_TNUMBER: + setnvalue(o,LoadNumber(S)); + break; ++ case LUA_TINT: /* Integer type saved in bytecode (see lcode.c) */ ++ setivalue(o,LoadInteger(S)); ++ break; + case LUA_TSTRING: + setsvalue2n(S->L,o,LoadString(S)); + break; +@@ -223,5 +233,22 @@ void luaU_header (char* h) + *h++=(char)sizeof(size_t); + *h++=(char)sizeof(Instruction); + *h++=(char)sizeof(lua_Number); +- *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ ++ ++ /* ++ * Last byte of header (0/1 in unpatched Lua 5.1.3): ++ * ++ * 0: lua_Number is float or double, lua_Integer not used. (nonpatched only) ++ * 1: lua_Number is integer (nonpatched only) ++ * ++ * +2: LNUM_INT16: sizeof(lua_Integer) ++ * +4: LNUM_INT32: sizeof(lua_Integer) ++ * +8: LNUM_INT64: sizeof(lua_Integer) ++ * ++ * +0x80: LNUM_COMPLEX ++ */ ++ *h++ = (char)(sizeof(lua_Integer) ++#ifdef LNUM_COMPLEX ++ | 0x80 ++#endif ++ ); + } +--- a/src/lvm.c ++++ b/src/lvm.c +@@ -25,22 +25,35 @@ + #include "ltable.h" + #include "ltm.h" + #include "lvm.h" +- +- ++#include "llex.h" ++#include "lnum.h" + + /* limit for table tag-method chains (to avoid loops) */ + #define MAXTAGLOOP 100 + + +-const TValue *luaV_tonumber (const TValue *obj, TValue *n) { +- lua_Number num; ++/* ++ * If 'obj' is a string, it is tried to be interpreted as a number. ++ */ ++const TValue *luaV_tonumber ( const TValue *obj, TValue *n) { ++ lua_Number d; ++ lua_Integer i; ++ + if (ttisnumber(obj)) return obj; +- if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { +- setnvalue(n, num); +- return n; +- } +- else +- return NULL; ++ ++ if (ttisstring(obj)) { ++ switch( luaO_str2d( svalue(obj), &d, &i ) ) { ++ case TK_INT: ++ setivalue(n,i); return n; ++ case TK_NUMBER: ++ setnvalue(n,d); return n; ++#ifdef LNUM_COMPLEX ++ case TK_NUMBER2: /* "N.NNNi", != 0 */ ++ setnvalue_complex_fast(n, d*I); return n; ++#endif ++ } ++ } ++ return NULL; + } + + +@@ -49,8 +62,7 @@ int luaV_tostring (lua_State *L, StkId o + return 0; + else { + char s[LUAI_MAXNUMBER2STR]; +- lua_Number n = nvalue(obj); +- lua_number2str(s, n); ++ luaO_num2buf(s,obj); + setsvalue2s(L, obj, luaS_new(L, s)); + return 1; + } +@@ -222,59 +234,127 @@ static int l_strcmp (const TString *ls, + } + + ++#ifdef LNUM_COMPLEX ++void error_complex( lua_State *L, const TValue *l, const TValue *r ) ++{ ++ char buf1[ LUAI_MAXNUMBER2STR ]; ++ char buf2[ LUAI_MAXNUMBER2STR ]; ++ luaO_num2buf( buf1, l ); ++ luaO_num2buf( buf2, r ); ++ luaG_runerror( L, "unable to compare: %s with %s", buf1, buf2 ); ++ /* no return */ ++} ++#endif ++ ++ + int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { + int res; +- if (ttype(l) != ttype(r)) ++ int tl,tr; ++ lua_Integer tmp; ++ ++ if (!ttype_ext_same(l,r)) + return luaG_ordererror(L, l, r); +- else if (ttisnumber(l)) +- return luai_numlt(nvalue(l), nvalue(r)); +- else if (ttisstring(l)) +- return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; +- else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) ++#ifdef LNUM_COMPLEX ++ if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) ) ++ error_complex( L, l, r ); ++#endif ++ tl= ttype(l); tr= ttype(r); ++ if (tl==tr) { /* clear arithmetics */ ++ switch(tl) { ++ case LUA_TINT: return ivalue(l) < ivalue(r); ++ case LUA_TNUMBER: return luai_numlt(nvalue_fast(l), nvalue_fast(r)); ++ case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; ++ } ++ } else if (tl==LUA_TINT) { /* l:int, r:num */ ++ /* Avoid accuracy losing casts: if 'r' is integer by value, do comparisons ++ * in integer realm. Only otherwise cast 'l' to FP (which might change its ++ * value). ++ */ ++ if (tt_integer_valued(r,&tmp)) ++ return ivalue(l) < tmp; ++ else ++ return luai_numlt( cast_num(ivalue(l)), nvalue_fast(r) ); ++ ++ } else if (tl==LUA_TNUMBER) { /* l:num, r:int */ ++ if (tt_integer_valued(l,&tmp)) ++ return tmp < ivalue(r); ++ else ++ return luai_numlt( nvalue_fast(l), cast_num(ivalue(r)) ); ++ ++ } else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) + return res; ++ + return luaG_ordererror(L, l, r); + } + + + static int lessequal (lua_State *L, const TValue *l, const TValue *r) { + int res; +- if (ttype(l) != ttype(r)) ++ int tl, tr; ++ lua_Integer tmp; ++ ++ if (!ttype_ext_same(l,r)) + return luaG_ordererror(L, l, r); +- else if (ttisnumber(l)) +- return luai_numle(nvalue(l), nvalue(r)); +- else if (ttisstring(l)) +- return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; +- else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ ++#ifdef LNUM_COMPLEX ++ if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) ) ++ error_complex( L, l, r ); ++#endif ++ tl= ttype(l); tr= ttype(r); ++ if (tl==tr) { /* clear arithmetics */ ++ switch(tl) { ++ case LUA_TINT: return ivalue(l) <= ivalue(r); ++ case LUA_TNUMBER: return luai_numle(nvalue_fast(l), nvalue_fast(r)); ++ case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; ++ } ++ } ++ if (tl==LUA_TINT) { /* l:int, r:num */ ++ if (tt_integer_valued(r,&tmp)) ++ return ivalue(l) <= tmp; ++ else ++ return luai_numle( cast_num(ivalue(l)), nvalue_fast(r) ); ++ ++ } else if (tl==LUA_TNUMBER) { /* l:num, r:int */ ++ if (tt_integer_valued(l,&tmp)) ++ return tmp <= ivalue(r); ++ else ++ return luai_numle( nvalue_fast(l), cast_num(ivalue(r)) ); ++ ++ } else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ + return res; + else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ + return !res; ++ + return luaG_ordererror(L, l, r); + } + + +-int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { ++/* Note: 'luaV_equalval()' and 'luaO_rawequalObj()' have largely overlapping ++ * implementation. LUA_TNIL..LUA_TLIGHTUSERDATA cases could be handled ++ * simply by the 'default' case here. ++ */ ++int luaV_equalval (lua_State *L, const TValue *l, const TValue *r) { + const TValue *tm; +- lua_assert(ttype(t1) == ttype(t2)); +- switch (ttype(t1)) { ++ lua_assert(ttype_ext_same(l,r)); ++ switch (ttype(l)) { + case LUA_TNIL: return 1; +- case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); +- case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ +- case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); ++ case LUA_TINT: ++ case LUA_TNUMBER: return luaO_rawequalObj(l,r); ++ case LUA_TBOOLEAN: return bvalue(l) == bvalue(r); /* true must be 1 !! */ ++ case LUA_TLIGHTUSERDATA: return pvalue(l) == pvalue(r); + case LUA_TUSERDATA: { +- if (uvalue(t1) == uvalue(t2)) return 1; +- tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, +- TM_EQ); ++ if (uvalue(l) == uvalue(r)) return 1; ++ tm = get_compTM(L, uvalue(l)->metatable, uvalue(r)->metatable, TM_EQ); + break; /* will try TM */ + } + case LUA_TTABLE: { +- if (hvalue(t1) == hvalue(t2)) return 1; +- tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); ++ if (hvalue(l) == hvalue(r)) return 1; ++ tm = get_compTM(L, hvalue(l)->metatable, hvalue(r)->metatable, TM_EQ); + break; /* will try TM */ + } +- default: return gcvalue(t1) == gcvalue(t2); ++ default: return gcvalue(l) == gcvalue(r); + } + if (tm == NULL) return 0; /* no TM? */ +- callTMres(L, L->top, tm, t1, t2); /* call TM */ ++ callTMres(L, L->top, tm, l, r); /* call TM */ + return !l_isfalse(L->top); + } + +@@ -314,30 +394,6 @@ void luaV_concat (lua_State *L, int tota + } + + +-static void Arith (lua_State *L, StkId ra, const TValue *rb, +- const TValue *rc, TMS op) { +- TValue tempb, tempc; +- const TValue *b, *c; +- if ((b = luaV_tonumber(rb, &tempb)) != NULL && +- (c = luaV_tonumber(rc, &tempc)) != NULL) { +- lua_Number nb = nvalue(b), nc = nvalue(c); +- switch (op) { +- case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; +- case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; +- case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; +- case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; +- case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; +- case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; +- case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; +- default: lua_assert(0); break; +- } +- } +- else if (!call_binTM(L, rb, rc, ra, op)) +- luaG_aritherror(L, rb, rc); +-} +- +- +- + /* + ** some macros for common tasks in `luaV_execute' + */ +@@ -361,17 +417,154 @@ static void Arith (lua_State *L, StkId r + #define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } + + +-#define arith_op(op,tm) { \ +- TValue *rb = RKB(i); \ +- TValue *rc = RKC(i); \ +- if (ttisnumber(rb) && ttisnumber(rc)) { \ +- lua_Number nb = nvalue(rb), nc = nvalue(rc); \ +- setnvalue(ra, op(nb, nc)); \ +- } \ +- else \ +- Protect(Arith(L, ra, rb, rc, tm)); \ ++/* Note: if called for unary operations, 'rc'=='rb'. ++ */ ++static void Arith (lua_State *L, StkId ra, const TValue *rb, ++ const TValue *rc, TMS op) { ++ TValue tempb, tempc; ++ const TValue *b, *c; ++ lua_Number nb,nc; ++ ++ if ((b = luaV_tonumber(rb, &tempb)) != NULL && ++ (c = luaV_tonumber(rc, &tempc)) != NULL) { ++ ++ /* Keep integer arithmetics in the integer realm, if possible. ++ */ ++ if (ttisint(b) && ttisint(c)) { ++ lua_Integer ib = ivalue(b), ic = ivalue(c); ++ lua_Integer *ri = &ra->value.i; ++ ra->tt= LUA_TINT; /* part of 'setivalue(ra)' */ ++ switch (op) { ++ case TM_ADD: if (try_addint( ri, ib, ic)) return; break; ++ case TM_SUB: if (try_subint( ri, ib, ic)) return; break; ++ case TM_MUL: if (try_mulint( ri, ib, ic)) return; break; ++ case TM_DIV: if (try_divint( ri, ib, ic)) return; break; ++ case TM_MOD: if (try_modint( ri, ib, ic)) return; break; ++ case TM_POW: if (try_powint( ri, ib, ic)) return; break; ++ case TM_UNM: if (try_unmint( ri, ib)) return; break; ++ default: lua_assert(0); ++ } ++ } ++ /* Fallback to floating point, when leaving range. */ ++ ++#ifdef LNUM_COMPLEX ++ if ((nvalue_img(b)!=0) || (nvalue_img(c)!=0)) { ++ lua_Complex r; ++ if (op==TM_UNM) { ++ r= -nvalue_complex_fast(b); /* never an integer (or scalar) */ ++ setnvalue_complex_fast( ra, r ); ++ } else { ++ lua_Complex bb= nvalue_complex(b), cc= nvalue_complex(c); ++ switch (op) { ++ case TM_ADD: r= bb + cc; break; ++ case TM_SUB: r= bb - cc; break; ++ case TM_MUL: r= bb * cc; break; ++ case TM_DIV: r= bb / cc; break; ++ case TM_MOD: ++ luaG_runerror(L, "attempt to use %% on complex numbers"); /* no return */ ++ case TM_POW: r= luai_vectpow( bb, cc ); break; ++ default: lua_assert(0); r=0; ++ } ++ setnvalue_complex( ra, r ); + } ++ return; ++ } ++#endif ++ nb = nvalue(b); nc = nvalue(c); ++ switch (op) { ++ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); return; ++ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); return; ++ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); return; ++ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); return; ++ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); return; ++ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); return; ++ case TM_UNM: setnvalue(ra, luai_numunm(nb)); return; ++ default: lua_assert(0); ++ } ++ } ++ ++ /* Either operand not a number */ ++ if (!call_binTM(L, rb, rc, ra, op)) ++ luaG_aritherror(L, rb, rc); ++} + ++/* Helper macro to sort arithmetic operations into four categories: ++ * TK_INT: integer - integer operands ++ * TK_NUMBER: number - number (non complex, either may be integer) ++ * TK_NUMBER2: complex numbers (at least the other) ++ * 0: non-numeric (at least the other) ++*/ ++#ifdef LNUM_COMPLEX ++static inline int arith_mode( const TValue *rb, const TValue *rc ) { ++ if (ttisint(rb) && ttisint(rc)) return TK_INT; ++ if (ttiscomplex(rb) || ttiscomplex(rc)) return TK_NUMBER2; ++ if (ttisnumber(rb) && ttisnumber(rc)) return TK_NUMBER; ++ return 0; ++} ++#else ++# define arith_mode(rb,rc) \ ++ ( (ttisint(rb) && ttisint(rc)) ? TK_INT : \ ++ (ttisnumber(rb) && ttisnumber(rc)) ? TK_NUMBER : 0 ) ++#endif ++ ++/* arith_op macro for two operators: ++ * automatically chooses, which function (number, integer, complex) to use ++ */ ++#define ARITH_OP2_START( op_num, op_int ) \ ++ int failed= 0; \ ++ switch( arith_mode(rb,rc) ) { \ ++ case TK_INT: \ ++ if (op_int ( &(ra)->value.i, ivalue(rb), ivalue(rc) )) \ ++ { ra->tt= LUA_TINT; break; } /* else flow through */ \ ++ case TK_NUMBER: \ ++ setnvalue(ra, op_num ( nvalue(rb), nvalue(rc) )); break; ++ ++#define ARITH_OP2_END \ ++ default: \ ++ failed= 1; break; \ ++ } if (!failed) continue; ++ ++#define arith_op_continue_scalar( op_num, op_int ) \ ++ ARITH_OP2_START( op_num, op_int ) \ ++ ARITH_OP2_END ++ ++#ifdef LNUM_COMPLEX ++# define arith_op_continue( op_num, op_int, op_complex ) \ ++ ARITH_OP2_START( op_num, op_int ) \ ++ case TK_NUMBER2: \ ++ setnvalue_complex( ra, op_complex ( nvalue_complex(rb), nvalue_complex(rc) ) ); break; \ ++ ARITH_OP2_END ++#else ++# define arith_op_continue(op_num,op_int,_) arith_op_continue_scalar(op_num,op_int) ++#endif ++ ++/* arith_op macro for one operator: ++ */ ++#define ARITH_OP1_START( op_num, op_int ) \ ++ int failed= 0; \ ++ switch( arith_mode(rb,rb) ) { \ ++ case TK_INT: \ ++ if (op_int ( &(ra)->value.i, ivalue(rb) )) \ ++ { ra->tt= LUA_TINT; break; } /* else flow through */ \ ++ case TK_NUMBER: \ ++ setnvalue(ra, op_num (nvalue(rb))); break; \ ++ ++#define ARITH_OP1_END \ ++ default: \ ++ failed= 1; break; \ ++ } if (!failed) continue; ++ ++#ifdef LNUM_COMPLEX ++# define arith_op1_continue( op_num, op_int, op_complex ) \ ++ ARITH_OP1_START( op_num, op_int ) \ ++ case TK_NUMBER2: \ ++ setnvalue_complex( ra, op_complex ( nvalue_complex_fast(rb) )); break; \ ++ ARITH_OP1_END ++#else ++# define arith_op1_continue( op_num, op_int, _ ) \ ++ ARITH_OP1_START( op_num, op_int ) \ ++ ARITH_OP1_END ++#endif + + + void luaV_execute (lua_State *L, int nexeccalls) { +@@ -472,38 +665,45 @@ void luaV_execute (lua_State *L, int nex + continue; + } + case OP_ADD: { +- arith_op(luai_numadd, TM_ADD); ++ TValue *rb = RKB(i), *rc= RKC(i); ++ arith_op_continue( luai_numadd, try_addint, luai_vectadd ); ++ Protect(Arith(L, ra, rb, rc, TM_ADD)); \ + continue; + } + case OP_SUB: { +- arith_op(luai_numsub, TM_SUB); ++ TValue *rb = RKB(i), *rc= RKC(i); ++ arith_op_continue( luai_numsub, try_subint, luai_vectsub ); ++ Protect(Arith(L, ra, rb, rc, TM_SUB)); + continue; + } + case OP_MUL: { +- arith_op(luai_nummul, TM_MUL); ++ TValue *rb = RKB(i), *rc= RKC(i); ++ arith_op_continue(luai_nummul, try_mulint, luai_vectmul); ++ Protect(Arith(L, ra, rb, rc, TM_MUL)); + continue; + } + case OP_DIV: { +- arith_op(luai_numdiv, TM_DIV); ++ TValue *rb = RKB(i), *rc= RKC(i); ++ arith_op_continue(luai_numdiv, try_divint, luai_vectdiv); ++ Protect(Arith(L, ra, rb, rc, TM_DIV)); + continue; + } + case OP_MOD: { +- arith_op(luai_nummod, TM_MOD); ++ TValue *rb = RKB(i), *rc= RKC(i); ++ arith_op_continue_scalar(luai_nummod, try_modint); /* scalars only */ ++ Protect(Arith(L, ra, rb, rc, TM_MOD)); + continue; + } + case OP_POW: { +- arith_op(luai_numpow, TM_POW); ++ TValue *rb = RKB(i), *rc= RKC(i); ++ arith_op_continue(luai_numpow, try_powint, luai_vectpow); ++ Protect(Arith(L, ra, rb, rc, TM_POW)); + continue; + } + case OP_UNM: { + TValue *rb = RB(i); +- if (ttisnumber(rb)) { +- lua_Number nb = nvalue(rb); +- setnvalue(ra, luai_numunm(nb)); +- } +- else { +- Protect(Arith(L, ra, rb, rb, TM_UNM)); +- } ++ arith_op1_continue(luai_numunm, try_unmint, luai_vectunm); ++ Protect(Arith(L, ra, rb, rb, TM_UNM)); + continue; + } + case OP_NOT: { +@@ -515,11 +715,11 @@ void luaV_execute (lua_State *L, int nex + const TValue *rb = RB(i); + switch (ttype(rb)) { + case LUA_TTABLE: { +- setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); ++ setivalue(ra, luaH_getn(hvalue(rb))); + break; + } + case LUA_TSTRING: { +- setnvalue(ra, cast_num(tsvalue(rb)->len)); ++ setivalue(ra, tsvalue(rb)->len); + break; + } + default: { /* try metamethod */ +@@ -652,14 +852,30 @@ void luaV_execute (lua_State *L, int nex + } + } + case OP_FORLOOP: { +- lua_Number step = nvalue(ra+2); +- lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ +- lua_Number limit = nvalue(ra+1); +- if (luai_numlt(0, step) ? luai_numle(idx, limit) +- : luai_numle(limit, idx)) { +- dojump(L, pc, GETARG_sBx(i)); /* jump back */ +- setnvalue(ra, idx); /* update internal index... */ +- setnvalue(ra+3, idx); /* ...and external index */ ++ /* If start,step and limit are all integers, we don't need to check ++ * against overflow in the looping. ++ */ ++ if (ttisint(ra) && ttisint(ra+1) && ttisint(ra+2)) { ++ lua_Integer step = ivalue(ra+2); ++ lua_Integer idx = ivalue(ra) + step; /* increment index */ ++ lua_Integer limit = ivalue(ra+1); ++ if (step > 0 ? (idx <= limit) : (limit <= idx)) { ++ dojump(L, pc, GETARG_sBx(i)); /* jump back */ ++ setivalue(ra, idx); /* update internal index... */ ++ setivalue(ra+3, idx); /* ...and external index */ ++ } ++ } else { ++ /* non-integer looping (don't use 'nvalue_fast', some may be integer!) ++ */ ++ lua_Number step = nvalue(ra+2); ++ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ ++ lua_Number limit = nvalue(ra+1); ++ if (luai_numlt(0, step) ? luai_numle(idx, limit) ++ : luai_numle(limit, idx)) { ++ dojump(L, pc, GETARG_sBx(i)); /* jump back */ ++ setnvalue(ra, idx); /* update internal index... */ ++ setnvalue(ra+3, idx); /* ...and external index */ ++ } + } + continue; + } +@@ -668,13 +884,21 @@ void luaV_execute (lua_State *L, int nex + const TValue *plimit = ra+1; + const TValue *pstep = ra+2; + L->savedpc = pc; /* next steps may throw errors */ ++ /* Using same location for tonumber's both arguments, effectively does ++ * in-place modification (string->number). */ + if (!tonumber(init, ra)) + luaG_runerror(L, LUA_QL("for") " initial value must be a number"); + else if (!tonumber(plimit, ra+1)) + luaG_runerror(L, LUA_QL("for") " limit must be a number"); + else if (!tonumber(pstep, ra+2)) + luaG_runerror(L, LUA_QL("for") " step must be a number"); +- setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); ++ /* Step back one value (keep within integers if we can) ++ */ ++ if (!( ttisint(ra) && ttisint(pstep) && ++ try_subint( &ra->value.i, ivalue(ra), ivalue(pstep) ) )) { ++ /* don't use 'nvalue_fast()', values may be integer */ ++ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); ++ } + dojump(L, pc, GETARG_sBx(i)); + continue; + } +@@ -711,7 +935,7 @@ void luaV_execute (lua_State *L, int nex + luaH_resizearray(L, h, last); /* pre-alloc it at once */ + for (; n > 0; n--) { + TValue *val = ra+n; +- setobj2t(L, luaH_setnum(L, h, last--), val); ++ setobj2t(L, luaH_setint(L, h, last--), val); + luaC_barriert(L, h, val); + } + continue; +--- a/src/lvm.h ++++ b/src/lvm.h +@@ -15,11 +15,9 @@ + + #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) + +-#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ +- (((o) = luaV_tonumber(o,n)) != NULL)) ++#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) + +-#define equalobj(L,o1,o2) \ +- (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) ++#define equalobj(L,o1,o2) (ttype_ext_same(o1,o2) && luaV_equalval(L, o1, o2)) + + + LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); +--- a/src/print.c ++++ b/src/print.c +@@ -14,6 +14,7 @@ + #include "lobject.h" + #include "lopcodes.h" + #include "lundump.h" ++#include "lnum.h" + + #define PrintFunction luaU_print + +@@ -59,8 +60,16 @@ static void PrintConstant(const Proto* f + case LUA_TBOOLEAN: + printf(bvalue(o) ? "true" : "false"); + break; ++ case LUA_TINT: ++ printf(LUA_INTEGER_FMT,ivalue(o)); ++ break; + case LUA_TNUMBER: +- printf(LUA_NUMBER_FMT,nvalue(o)); ++#ifdef LNUM_COMPLEX ++ // TBD: Do we get complex values here? ++ { lua_Number b= nvalue_img_fast(o); ++ printf( LUA_NUMBER_FMT "%s" LUA_NUMBER_FMT "i", nvalue_fast(o), b>=0 ? "+":"", b ); } ++#endif ++ printf(LUA_NUMBER_FMT,nvalue_fast(o)); + break; + case LUA_TSTRING: + PrintString(rawtsvalue(o)); diff --git a/package/utils/lua/patches/011-lnum-use-double.patch b/package/utils/lua/patches/011-lnum-use-double.patch new file mode 100644 index 0000000..14c720b --- /dev/null +++ b/package/utils/lua/patches/011-lnum-use-double.patch @@ -0,0 +1,11 @@ +--- a/src/lnum_config.h ++++ b/src/lnum_config.h +@@ -11,7 +11,7 @@ + ** Default number modes + */ + #if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE) +-# define LNUM_FLOAT ++# define LNUM_DOUBLE + #endif + #if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64) + # define LNUM_INT32 diff --git a/package/utils/lua/patches/015-lnum-ppc-compat.patch b/package/utils/lua/patches/015-lnum-ppc-compat.patch new file mode 100644 index 0000000..2ea59f1 --- /dev/null +++ b/package/utils/lua/patches/015-lnum-ppc-compat.patch @@ -0,0 +1,11 @@ +--- a/src/lua.h ++++ b/src/lua.h +@@ -79,7 +79,7 @@ typedef void * (*lua_Alloc) (void *ud, v + * not acceptable for 5.1, maybe 5.2 onwards? + * 9: greater than existing (5.1) type values. + */ +-#define LUA_TINT (-2) ++#define LUA_TINT 9 + + #define LUA_TNIL 0 + #define LUA_TBOOLEAN 1 diff --git a/package/utils/lua/patches/020-shared_liblua.patch b/package/utils/lua/patches/020-shared_liblua.patch new file mode 100644 index 0000000..bcd410f --- /dev/null +++ b/package/utils/lua/patches/020-shared_liblua.patch @@ -0,0 +1,140 @@ +--- a/Makefile ++++ b/Makefile +@@ -42,8 +42,8 @@ PLATS= aix ansi bsd freebsd generic linu + + # What to install. + TO_BIN= lua luac +-TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp +-TO_LIB= liblua.a ++TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp lnum_config.h ++TO_LIB= liblua.a liblua.so.$R + TO_MAN= lua.1 luac.1 + + # Lua version and release. +@@ -63,6 +63,7 @@ install: dummy + cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN) + cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC) + cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB) ++ ln -s liblua.so.$R $(INSTALL_LIB)/liblua.so + cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) + + ranlib: +--- a/src/ldo.h ++++ b/src/ldo.h +@@ -46,7 +46,7 @@ LUAI_FUNC int luaD_pcall (lua_State *L, + LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); + LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); + LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); +-LUAI_FUNC void luaD_growstack (lua_State *L, int n); ++LUA_API void luaD_growstack (lua_State *L, int n); + + LUAI_FUNC void luaD_throw (lua_State *L, int errcode); + LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); +--- a/src/lfunc.h ++++ b/src/lfunc.h +@@ -18,7 +18,7 @@ + cast(int, sizeof(TValue *)*((n)-1))) + + +-LUAI_FUNC Proto *luaF_newproto (lua_State *L); ++LUA_API Proto *luaF_newproto (lua_State *L); + LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); + LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); + LUAI_FUNC UpVal *luaF_newupval (lua_State *L); +--- a/src/lmem.h ++++ b/src/lmem.h +@@ -38,9 +38,9 @@ + ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) + + +-LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, ++LUA_API void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, + size_t size); +-LUAI_FUNC void *luaM_toobig (lua_State *L); ++LUA_API void *luaM_toobig (lua_State *L); + LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, + size_t size_elem, int limit, + const char *errormsg); +--- a/src/lstring.h ++++ b/src/lstring.h +@@ -25,7 +25,7 @@ + + LUAI_FUNC void luaS_resize (lua_State *L, int newsize); + LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); +-LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); ++LUA_API TString *luaS_newlstr (lua_State *L, const char *str, size_t l); + + + #endif +--- a/src/lundump.h ++++ b/src/lundump.h +@@ -17,7 +17,7 @@ LUAI_FUNC Proto* luaU_undump (lua_State* + LUAI_FUNC void luaU_header (char* h); + + /* dump one chunk; from ldump.c */ +-LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); ++LUA_API int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); + + #ifdef luac_c + /* print one chunk; from print.c */ +--- a/src/Makefile ++++ b/src/Makefile +@@ -23,6 +23,7 @@ MYLIBS= + PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris + + LUA_A= liblua.a ++LUA_SO= liblua.so + CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ + lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \ + lundump.o lvm.o lzio.o lnum.o +@@ -33,11 +34,12 @@ LUA_T= lua + LUA_O= lua.o + + LUAC_T= luac +-LUAC_O= luac.o print.o ++LUAC_O= luac.o print.o lopcodes.o + + ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O) +-ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) ++ALL_T= $(LUA_A) $(LUA_SO) $(LUA_T) $(LUAC_T) + ALL_A= $(LUA_A) ++ALL_SO= $(LUA_SO) + + default: $(PLAT) + +@@ -47,14 +49,23 @@ o: $(ALL_O) + + a: $(ALL_A) + ++so: $(ALL_SO) ++ + $(LUA_A): $(CORE_O) $(LIB_O) + $(AR) $@ $(CORE_O) $(LIB_O) # DLL needs all object files + $(RANLIB) $@ + +-$(LUA_T): $(LUA_O) $(LUA_A) +- $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) ++$(LUA_SO): $(CORE_O) $(LIB_O) ++ $(CC) -o $@.$(PKG_VERSION) -shared -Wl,-soname="$@.$(PKG_VERSION)" $? ++ ln -fs $@.$(PKG_VERSION) $@ ++ ++$(LUA_T): $(LUA_O) $(LUA_SO) ++ $(CC) -o $@ -L. -llua $(MYLDFLAGS) $(LUA_O) $(LIBS) ++ ++$(LUAC_T): $(LUAC_O) $(LUA_SO) ++ $(CC) -o $@ -L. -llua $(MYLDFLAGS) $(LUAC_O) $(LIBS) + +-$(LUAC_T): $(LUAC_O) $(LUA_A) ++$(LUAC_T)-host: $(LUAC_O) $(LUA_A) + $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) + + clean: +@@ -96,7 +107,7 @@ generic: + $(MAKE) all MYCFLAGS= + + linux: +- $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses" ++ $(MAKE) all MYCFLAGS+=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses" + + macosx: + $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline" diff --git a/package/utils/lua/patches/030-archindependent-bytecode.patch b/package/utils/lua/patches/030-archindependent-bytecode.patch new file mode 100644 index 0000000..8dfef85 --- /dev/null +++ b/package/utils/lua/patches/030-archindependent-bytecode.patch @@ -0,0 +1,111 @@ +--- a/src/ldump.c ++++ b/src/ldump.c +@@ -67,12 +67,12 @@ static void DumpString(const TString* s, + { + if (s==NULL || getstr(s)==NULL) + { +- size_t size=0; ++ unsigned int size=0; + DumpVar(size,D); + } + else + { +- size_t size=s->tsv.len+1; /* include trailing '\0' */ ++ unsigned int size=s->tsv.len+1; /* include trailing '\0' */ + DumpVar(size,D); + DumpBlock(getstr(s),size,D); + } +--- a/src/lundump.c ++++ b/src/lundump.c +@@ -25,6 +25,7 @@ typedef struct { + ZIO* Z; + Mbuffer* b; + const char* name; ++ int swap; + } LoadState; + + #ifdef LUAC_TRUST_BINARIES +@@ -40,7 +41,6 @@ static void error(LoadState* S, const ch + } + #endif + +-#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) + #define LoadByte(S) (lu_byte)LoadChar(S) + #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) + #define LoadVector(S,b,n,size) LoadMem(S,b,n,size) +@@ -51,6 +51,49 @@ static void LoadBlock(LoadState* S, void + IF (r!=0, "unexpected end"); + } + ++static void LoadMem (LoadState* S, void* b, int n, size_t size) ++{ ++ LoadBlock(S,b,n*size); ++ if (S->swap) ++ { ++ char* p=(char*) b; ++ char c; ++ switch (size) ++ { ++ case 1: ++ break; ++ case 2: ++ while (n--) ++ { ++ c=p[0]; p[0]=p[1]; p[1]=c; ++ p+=2; ++ } ++ break; ++ case 4: ++ while (n--) ++ { ++ c=p[0]; p[0]=p[3]; p[3]=c; ++ c=p[1]; p[1]=p[2]; p[2]=c; ++ p+=4; ++ } ++ break; ++ case 8: ++ while (n--) ++ { ++ c=p[0]; p[0]=p[7]; p[7]=c; ++ c=p[1]; p[1]=p[6]; p[6]=c; ++ c=p[2]; p[2]=p[5]; p[5]=c; ++ c=p[3]; p[3]=p[4]; p[4]=c; ++ p+=8; ++ } ++ break; ++ default: ++ IF(1, "bad size"); ++ break; ++ } ++ } ++} ++ + static int LoadChar(LoadState* S) + { + char x; +@@ -82,7 +125,7 @@ static lua_Integer LoadInteger(LoadState + + static TString* LoadString(LoadState* S) + { +- size_t size; ++ unsigned int size; + LoadVar(S,size); + if (size==0) + return NULL; +@@ -196,6 +239,7 @@ static void LoadHeader(LoadState* S) + char s[LUAC_HEADERSIZE]; + luaU_header(h); + LoadBlock(S,s,LUAC_HEADERSIZE); ++ S->swap=(s[6]!=h[6]); s[6]=h[6]; + IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); + } + +@@ -230,7 +274,7 @@ void luaU_header (char* h) + *h++=(char)LUAC_FORMAT; + *h++=(char)*(char*)&x; /* endianness */ + *h++=(char)sizeof(int); +- *h++=(char)sizeof(size_t); ++ *h++=(char)sizeof(unsigned int); + *h++=(char)sizeof(Instruction); + *h++=(char)sizeof(lua_Number); + diff --git a/package/utils/lua/patches/040-use-symbolic-functions.patch b/package/utils/lua/patches/040-use-symbolic-functions.patch new file mode 100644 index 0000000..f590695 --- /dev/null +++ b/package/utils/lua/patches/040-use-symbolic-functions.patch @@ -0,0 +1,11 @@ +--- a/src/Makefile ++++ b/src/Makefile +@@ -56,7 +56,7 @@ $(LUA_A): $(CORE_O) $(LIB_O) + $(RANLIB) $@ + + $(LUA_SO): $(CORE_O) $(LIB_O) +- $(CC) -o $@.$(PKG_VERSION) -shared -Wl,-soname="$@.$(PKG_VERSION)" $? ++ $(CC) -o $@.$(PKG_VERSION) -Wl,-Bsymbolic-functions -shared -Wl,-soname="$@.$(PKG_VERSION)" $? + ln -fs $@.$(PKG_VERSION) $@ + + $(LUA_T): $(LUA_O) $(LUA_SO) diff --git a/package/utils/lua/patches/050-honor-cflags.patch b/package/utils/lua/patches/050-honor-cflags.patch new file mode 100644 index 0000000..dd65791 --- /dev/null +++ b/package/utils/lua/patches/050-honor-cflags.patch @@ -0,0 +1,11 @@ +--- a/src/Makefile ++++ b/src/Makefile +@@ -56,7 +56,7 @@ $(LUA_A): $(CORE_O) $(LIB_O) + $(RANLIB) $@ + + $(LUA_SO): $(CORE_O) $(LIB_O) +- $(CC) -o $@.$(PKG_VERSION) -Wl,-Bsymbolic-functions -shared -Wl,-soname="$@.$(PKG_VERSION)" $? ++ $(CC) -o $@.$(PKG_VERSION) -Wl,-Bsymbolic-functions $(MYLDFLAGS) -shared -Wl,-soname="$@.$(PKG_VERSION)" $? + ln -fs $@.$(PKG_VERSION) $@ + + diff --git a/package/utils/lua/patches/100-no_readline.patch b/package/utils/lua/patches/100-no_readline.patch new file mode 100644 index 0000000..0350e47 --- /dev/null +++ b/package/utils/lua/patches/100-no_readline.patch @@ -0,0 +1,49 @@ +--- a/src/luaconf.h ++++ b/src/luaconf.h +@@ -38,7 +38,6 @@ + #if defined(LUA_USE_LINUX) + #define LUA_USE_POSIX + #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +-#define LUA_USE_READLINE /* needs some extra libraries */ + #endif + + #if defined(LUA_USE_MACOSX) +--- a/src/Makefile ++++ b/src/Makefile +@@ -17,6 +17,7 @@ LIBS= -lm $(MYLIBS) + MYCFLAGS= + MYLDFLAGS= + MYLIBS= ++# USE_READLINE=1 + + # == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= + +@@ -86,7 +87,7 @@ echo: + @echo "MYLIBS = $(MYLIBS)" + + # convenience targets for popular platforms +- ++RFLAG=$(if $(USE_READLINE),-DLUA_USE_READLINE) + none: + @echo "Please choose a platform:" + @echo " $(PLATS)" +@@ -101,16 +102,16 @@ bsd: + $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E" + + freebsd: +- $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline" ++ $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX $(RFLAG)" MYLIBS="-Wl,-E$(if $(USE_READLINE), -lreadline)" + + generic: + $(MAKE) all MYCFLAGS= + + linux: +- $(MAKE) all MYCFLAGS+=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses" ++ $(MAKE) all MYCFLAGS+="-DLUA_USE_LINUX $(RFLAG)" MYLIBS="-Wl,-E -ldl $(if $(USE_READLINE), -lreadline -lhistory -lncurses)" + + macosx: +- $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline" ++ $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX $(if $(USE_READLINE), MYLIBS="-lreadline") + # use this on Mac OS X 10.3- + # $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX + diff --git a/package/utils/lua/patches/200-lua-path.patch b/package/utils/lua/patches/200-lua-path.patch new file mode 100644 index 0000000..0544577 --- /dev/null +++ b/package/utils/lua/patches/200-lua-path.patch @@ -0,0 +1,15 @@ +--- a/src/luaconf.h ++++ b/src/luaconf.h +@@ -95,9 +95,9 @@ + ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" + + #else +-#define LUA_ROOT "/usr/local/" +-#define LUA_LDIR LUA_ROOT "share/lua/5.1/" +-#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" ++#define LUA_ROOT "/usr/" ++#define LUA_LDIR LUA_ROOT "share/lua/" ++#define LUA_CDIR LUA_ROOT "lib/lua/" + #define LUA_PATH_DEFAULT \ + "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" diff --git a/package/utils/lua/patches/300-opcode_performance.patch b/package/utils/lua/patches/300-opcode_performance.patch new file mode 100644 index 0000000..5fbb873 --- /dev/null +++ b/package/utils/lua/patches/300-opcode_performance.patch @@ -0,0 +1,363 @@ +--- a/src/lvm.c ++++ b/src/lvm.c +@@ -31,6 +31,9 @@ + /* limit for table tag-method chains (to avoid loops) */ + #define MAXTAGLOOP 100 + ++#ifdef __GNUC__ ++#define COMPUTED_GOTO 1 ++#endif + + /* + * If 'obj' is a string, it is tried to be interpreted as a number. +@@ -566,12 +569,63 @@ static inline int arith_mode( const TVal + ARITH_OP1_END + #endif + ++#ifdef COMPUTED_GOTO ++#define OPCODE_TARGET(op) DO_OP_##op: ++#define CALL_OPCODE(op) goto *opcodes[op]; ++#define OPCODE_PTR(op) [OP_##op] = &&DO_OP_##op ++#else ++#define OPCODE_TARGET(op) case OP_##op: ++#define CALL_OPCODE(op) switch (op) ++#endif ++ + + void luaV_execute (lua_State *L, int nexeccalls) { + LClosure *cl; + StkId base; + TValue *k; + const Instruction *pc; ++#ifdef COMPUTED_GOTO ++ static const void *opcodes[] = { ++ OPCODE_PTR(MOVE), ++ OPCODE_PTR(LOADK), ++ OPCODE_PTR(LOADBOOL), ++ OPCODE_PTR(LOADNIL), ++ OPCODE_PTR(GETUPVAL), ++ OPCODE_PTR(GETGLOBAL), ++ OPCODE_PTR(GETTABLE), ++ OPCODE_PTR(SETGLOBAL), ++ OPCODE_PTR(SETUPVAL), ++ OPCODE_PTR(SETTABLE), ++ OPCODE_PTR(NEWTABLE), ++ OPCODE_PTR(SELF), ++ OPCODE_PTR(ADD), ++ OPCODE_PTR(SUB), ++ OPCODE_PTR(MUL), ++ OPCODE_PTR(DIV), ++ OPCODE_PTR(MOD), ++ OPCODE_PTR(POW), ++ OPCODE_PTR(UNM), ++ OPCODE_PTR(NOT), ++ OPCODE_PTR(LEN), ++ OPCODE_PTR(CONCAT), ++ OPCODE_PTR(JMP), ++ OPCODE_PTR(EQ), ++ OPCODE_PTR(LT), ++ OPCODE_PTR(LE), ++ OPCODE_PTR(TEST), ++ OPCODE_PTR(TESTSET), ++ OPCODE_PTR(CALL), ++ OPCODE_PTR(TAILCALL), ++ OPCODE_PTR(RETURN), ++ OPCODE_PTR(FORLOOP), ++ OPCODE_PTR(FORPREP), ++ OPCODE_PTR(TFORLOOP), ++ OPCODE_PTR(SETLIST), ++ OPCODE_PTR(CLOSE), ++ OPCODE_PTR(CLOSURE), ++ OPCODE_PTR(VARARG) ++ }; ++#endif + reentry: /* entry point */ + lua_assert(isLua(L->ci)); + pc = L->savedpc; +@@ -596,33 +650,33 @@ void luaV_execute (lua_State *L, int nex + lua_assert(base == L->base && L->base == L->ci->base); + lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); + lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); +- switch (GET_OPCODE(i)) { +- case OP_MOVE: { ++ CALL_OPCODE(GET_OPCODE(i)) { ++ OPCODE_TARGET(MOVE) { + setobjs2s(L, ra, RB(i)); + continue; + } +- case OP_LOADK: { ++ OPCODE_TARGET(LOADK) { + setobj2s(L, ra, KBx(i)); + continue; + } +- case OP_LOADBOOL: { ++ OPCODE_TARGET(LOADBOOL) { + setbvalue(ra, GETARG_B(i)); + if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ + continue; + } +- case OP_LOADNIL: { ++ OPCODE_TARGET(LOADNIL) { + TValue *rb = RB(i); + do { + setnilvalue(rb--); + } while (rb >= ra); + continue; + } +- case OP_GETUPVAL: { ++ OPCODE_TARGET(GETUPVAL) { + int b = GETARG_B(i); + setobj2s(L, ra, cl->upvals[b]->v); + continue; + } +- case OP_GETGLOBAL: { ++ OPCODE_TARGET(GETGLOBAL) { + TValue g; + TValue *rb = KBx(i); + sethvalue(L, &g, cl->env); +@@ -630,88 +684,88 @@ void luaV_execute (lua_State *L, int nex + Protect(luaV_gettable(L, &g, rb, ra)); + continue; + } +- case OP_GETTABLE: { ++ OPCODE_TARGET(GETTABLE) { + Protect(luaV_gettable(L, RB(i), RKC(i), ra)); + continue; + } +- case OP_SETGLOBAL: { ++ OPCODE_TARGET(SETGLOBAL) { + TValue g; + sethvalue(L, &g, cl->env); + lua_assert(ttisstring(KBx(i))); + Protect(luaV_settable(L, &g, KBx(i), ra)); + continue; + } +- case OP_SETUPVAL: { ++ OPCODE_TARGET(SETUPVAL) { + UpVal *uv = cl->upvals[GETARG_B(i)]; + setobj(L, uv->v, ra); + luaC_barrier(L, uv, ra); + continue; + } +- case OP_SETTABLE: { ++ OPCODE_TARGET(SETTABLE) { + Protect(luaV_settable(L, ra, RKB(i), RKC(i))); + continue; + } +- case OP_NEWTABLE: { ++ OPCODE_TARGET(NEWTABLE) { + int b = GETARG_B(i); + int c = GETARG_C(i); + sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); + Protect(luaC_checkGC(L)); + continue; + } +- case OP_SELF: { ++ OPCODE_TARGET(SELF) { + StkId rb = RB(i); + setobjs2s(L, ra+1, rb); + Protect(luaV_gettable(L, rb, RKC(i), ra)); + continue; + } +- case OP_ADD: { ++ OPCODE_TARGET(ADD) { + TValue *rb = RKB(i), *rc= RKC(i); + arith_op_continue( luai_numadd, try_addint, luai_vectadd ); + Protect(Arith(L, ra, rb, rc, TM_ADD)); \ + continue; + } +- case OP_SUB: { ++ OPCODE_TARGET(SUB) { + TValue *rb = RKB(i), *rc= RKC(i); + arith_op_continue( luai_numsub, try_subint, luai_vectsub ); + Protect(Arith(L, ra, rb, rc, TM_SUB)); + continue; + } +- case OP_MUL: { ++ OPCODE_TARGET(MUL) { + TValue *rb = RKB(i), *rc= RKC(i); + arith_op_continue(luai_nummul, try_mulint, luai_vectmul); + Protect(Arith(L, ra, rb, rc, TM_MUL)); + continue; + } +- case OP_DIV: { ++ OPCODE_TARGET(DIV) { + TValue *rb = RKB(i), *rc= RKC(i); + arith_op_continue(luai_numdiv, try_divint, luai_vectdiv); + Protect(Arith(L, ra, rb, rc, TM_DIV)); + continue; + } +- case OP_MOD: { ++ OPCODE_TARGET(MOD) { + TValue *rb = RKB(i), *rc= RKC(i); + arith_op_continue_scalar(luai_nummod, try_modint); /* scalars only */ + Protect(Arith(L, ra, rb, rc, TM_MOD)); + continue; + } +- case OP_POW: { ++ OPCODE_TARGET(POW) { + TValue *rb = RKB(i), *rc= RKC(i); + arith_op_continue(luai_numpow, try_powint, luai_vectpow); + Protect(Arith(L, ra, rb, rc, TM_POW)); + continue; + } +- case OP_UNM: { ++ OPCODE_TARGET(UNM) { + TValue *rb = RB(i); + arith_op1_continue(luai_numunm, try_unmint, luai_vectunm); + Protect(Arith(L, ra, rb, rb, TM_UNM)); + continue; + } +- case OP_NOT: { ++ OPCODE_TARGET(NOT) { + int res = l_isfalse(RB(i)); /* next assignment may change this value */ + setbvalue(ra, res); + continue; + } +- case OP_LEN: { ++ OPCODE_TARGET(LEN) { + const TValue *rb = RB(i); + switch (ttype(rb)) { + case LUA_TTABLE: { +@@ -731,18 +785,18 @@ void luaV_execute (lua_State *L, int nex + } + continue; + } +- case OP_CONCAT: { ++ OPCODE_TARGET(CONCAT) { + int b = GETARG_B(i); + int c = GETARG_C(i); + Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); + setobjs2s(L, RA(i), base+b); + continue; + } +- case OP_JMP: { ++ OPCODE_TARGET(JMP) { + dojump(L, pc, GETARG_sBx(i)); + continue; + } +- case OP_EQ: { ++ OPCODE_TARGET(EQ) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + Protect( +@@ -752,7 +806,7 @@ void luaV_execute (lua_State *L, int nex + pc++; + continue; + } +- case OP_LT: { ++ OPCODE_TARGET(LT) { + Protect( + if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); +@@ -760,7 +814,7 @@ void luaV_execute (lua_State *L, int nex + pc++; + continue; + } +- case OP_LE: { ++ OPCODE_TARGET(LE) { + Protect( + if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); +@@ -768,13 +822,13 @@ void luaV_execute (lua_State *L, int nex + pc++; + continue; + } +- case OP_TEST: { ++ OPCODE_TARGET(TEST) { + if (l_isfalse(ra) != GETARG_C(i)) + dojump(L, pc, GETARG_sBx(*pc)); + pc++; + continue; + } +- case OP_TESTSET: { ++ OPCODE_TARGET(TESTSET) { + TValue *rb = RB(i); + if (l_isfalse(rb) != GETARG_C(i)) { + setobjs2s(L, ra, rb); +@@ -783,7 +837,7 @@ void luaV_execute (lua_State *L, int nex + pc++; + continue; + } +- case OP_CALL: { ++ OPCODE_TARGET(CALL) { + int b = GETARG_B(i); + int nresults = GETARG_C(i) - 1; + if (b != 0) L->top = ra+b; /* else previous instruction set top */ +@@ -804,7 +858,7 @@ void luaV_execute (lua_State *L, int nex + } + } + } +- case OP_TAILCALL: { ++ OPCODE_TARGET(TAILCALL) { + int b = GETARG_B(i); + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + L->savedpc = pc; +@@ -836,7 +890,7 @@ void luaV_execute (lua_State *L, int nex + } + } + } +- case OP_RETURN: { ++ OPCODE_TARGET(RETURN) { + int b = GETARG_B(i); + if (b != 0) L->top = ra+b-1; + if (L->openupval) luaF_close(L, base); +@@ -851,7 +905,7 @@ void luaV_execute (lua_State *L, int nex + goto reentry; + } + } +- case OP_FORLOOP: { ++ OPCODE_TARGET(FORLOOP) { + /* If start,step and limit are all integers, we don't need to check + * against overflow in the looping. + */ +@@ -879,7 +933,7 @@ void luaV_execute (lua_State *L, int nex + } + continue; + } +- case OP_FORPREP: { ++ OPCODE_TARGET(FORPREP) { + const TValue *init = ra; + const TValue *plimit = ra+1; + const TValue *pstep = ra+2; +@@ -902,7 +956,7 @@ void luaV_execute (lua_State *L, int nex + dojump(L, pc, GETARG_sBx(i)); + continue; + } +- case OP_TFORLOOP: { ++ OPCODE_TARGET(TFORLOOP) { + StkId cb = ra + 3; /* call base */ + setobjs2s(L, cb+2, ra+2); + setobjs2s(L, cb+1, ra+1); +@@ -918,7 +972,7 @@ void luaV_execute (lua_State *L, int nex + pc++; + continue; + } +- case OP_SETLIST: { ++ OPCODE_TARGET(SETLIST) { + int n = GETARG_B(i); + int c = GETARG_C(i); + int last; +@@ -940,11 +994,11 @@ void luaV_execute (lua_State *L, int nex + } + continue; + } +- case OP_CLOSE: { ++ OPCODE_TARGET(CLOSE) { + luaF_close(L, ra); + continue; + } +- case OP_CLOSURE: { ++ OPCODE_TARGET(CLOSURE) { + Proto *p; + Closure *ncl; + int nup, j; +@@ -964,7 +1018,7 @@ void luaV_execute (lua_State *L, int nex + Protect(luaC_checkGC(L)); + continue; + } +- case OP_VARARG: { ++ OPCODE_TARGET(VARARG) { + int b = GETARG_B(i) - 1; + int j; + CallInfo *ci = L->ci; diff --git a/package/utils/mdadm/Makefile b/package/utils/mdadm/Makefile new file mode 100644 index 0000000..69eec5b --- /dev/null +++ b/package/utils/mdadm/Makefile @@ -0,0 +1,52 @@ +# +# Copyright (C) 2008-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:=mdadm +PKG_VERSION:=3.2.5 +PKG_RELEASE:=1 + +PKG_SOURCE_URL:=@KERNEL/linux/utils/raid/mdadm +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_MD5SUM:=2fd33dedcdb06f0d1461f50ddabb7e4a + +PKG_MAINTAINER:=Felix Fietkau <nbd@openwrt.org> + +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/mdadm + SECTION:=utils + CATEGORY:=Utilities + TITLE:=A tool for managing Soft RAID under Linux + URL:=http://www.kernel.org/pub/linux/utils/raid/mdadm/ + DEPENDS:=+@KERNEL_DIRECT_IO +endef + +define Package/mdadm/description + A tool for managing Linux Software RAID arrays. +endef + +TARGET_CFLAGS += -ffunction-sections -fdata-sections +TARGET_LDFLAGS += -Wl,--gc-sections + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + CC="$(TARGET_CC)" \ + CFLAGS="$(TARGET_CFLAGS) -DHAVE_STDINT_H" \ + LDFLAGS="$(TARGET_LDFLAGS)" \ + mdadm +endef + +define Package/mdadm/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/mdadm $(1)/sbin +endef + +$(eval $(call BuildPackage,mdadm)) diff --git a/package/utils/mdadm/patches/000-compile.patch b/package/utils/mdadm/patches/000-compile.patch new file mode 100644 index 0000000..6d47489 --- /dev/null +++ b/package/utils/mdadm/patches/000-compile.patch @@ -0,0 +1,11 @@ +--- a/sha1.h ++++ b/sha1.h +@@ -26,8 +26,6 @@ + # include <limits.h> + #endif + +-#include "ansidecl.h" +- + /* The following contortions are an attempt to use the C preprocessor + to determine an unsigned integral type that is 32 bits wide. An + alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but diff --git a/package/utils/mdadm/patches/100-cross_compile.patch b/package/utils/mdadm/patches/100-cross_compile.patch new file mode 100644 index 0000000..8709e57 --- /dev/null +++ b/package/utils/mdadm/patches/100-cross_compile.patch @@ -0,0 +1,19 @@ +--- a/Makefile ++++ b/Makefile +@@ -76,7 +76,6 @@ FAILED_SLOTS_DIR = /run/mdadm/failed-slo + DIRFLAGS = -DMAP_DIR=\"$(MAP_DIR)\" -DMAP_FILE=\"$(MAP_FILE)\" + DIRFLAGS += -DMDMON_DIR=\"$(MDMON_DIR)\" + DIRFLAGS += -DFAILED_SLOTS_DIR=\"$(FAILED_SLOTS_DIR)\" +-CFLAGS = $(CWFLAGS) $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\" $(CONFFILEFLAGS) $(DIRFLAGS) + + # The glibc TLS ABI requires applications that call clone(2) to set up + # TLS data structures, use pthreads until mdmon implements this support +@@ -183,7 +182,7 @@ raid6check : raid6check.o mdadm.h $(CHEC + + mdassemble : $(ASSEMBLE_SRCS) $(INCL) + rm -f $(OBJS) +- $(DIET_GCC) $(ASSEMBLE_FLAGS) -o mdassemble $(ASSEMBLE_SRCS) $(STATICSRC) ++ $(CC) $(ASSEMBLE_FLAGS) -o mdassemble $(ASSEMBLE_SRCS) $(STATICSRC) + + mdassemble.static : $(ASSEMBLE_SRCS) $(INCL) + rm -f $(OBJS) diff --git a/package/utils/mdadm/patches/200-reduce_size.patch b/package/utils/mdadm/patches/200-reduce_size.patch new file mode 100644 index 0000000..3d8c2f4 --- /dev/null +++ b/package/utils/mdadm/patches/200-reduce_size.patch @@ -0,0 +1,25 @@ +--- a/Incremental.c ++++ b/Incremental.c +@@ -1508,6 +1508,10 @@ static int Incremental_container(struct + if (ra_all == ra_blocked) + return 0; + ++#ifndef MDADM_FULL ++ return 0; ++#endif ++ + /* Now move all suitable spares from spare container */ + domains = domain_from_array(list, st->ss->name); + memcpy(suuid, uuid_zero, sizeof(int[4])); +--- a/util.c ++++ b/util.c +@@ -928,7 +928,9 @@ void wait_for(char *dev, int fd) + struct superswitch *superlist[] = + { + &super0, &super1, ++#ifdef MDADM_FULL + &super_ddf, &super_imsm, ++#endif + &mbr, &gpt, + NULL }; + diff --git a/package/utils/mkelfimage/Makefile b/package/utils/mkelfimage/Makefile new file mode 100644 index 0000000..3a52e71 --- /dev/null +++ b/package/utils/mkelfimage/Makefile @@ -0,0 +1,35 @@ +# +# Copyright (C) 2006 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:=mkelfimage +PKG_VERSION:=2.7 + +PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.gz +PKG_SOURCE_URL:=http://ftp.debian.org/debian/pool/main/m/mkelfimage/ +PKG_MD5SUM:=e505cb87e9c0cdc44cf03d2c4ea8c74b + +include $(INCLUDE_DIR)/package.mk + +define Package/mkelfimage + SECTION:=base + CATEGORY:=Base system + TITLE:=mkelfimage + HIDDEN:=1 + DEPENDS:=@i386 + DEFAULT:=y if TARGET_x86 +endef + +CONFIGURE_VARS += AS="$(TARGET_CROSS)as" +MAKE_FLAGS += HOST_CC="$(HOSTCC)" DEFS="-I$(STAGING_DIR_HOST)/include" + +define Build/InstallDev + $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/objdir/sbin/mkelfImage $(STAGING_DIR_HOST)/bin +endef + +$(eval $(call BuildPackage,mkelfimage)) diff --git a/package/utils/mkelfimage/patches/no-stack-protector.patch b/package/utils/mkelfimage/patches/no-stack-protector.patch new file mode 100644 index 0000000..108583a --- /dev/null +++ b/package/utils/mkelfimage/patches/no-stack-protector.patch @@ -0,0 +1,11 @@ +--- mkelfimage-2.7.old//Makefile 2006-03-28 02:44:59.000000000 +0300 ++++ mkelfimage-2.7/Makefile 2011-01-17 14:15:13.000000000 +0200 +@@ -14,7 +14,7 @@ + pkglibdir = $(libdir)/$(PACKAGE) + pkgincludedir = $(includedir)/$(PACKAGE) + +-CPPFLAGS=-DVERSION='"$(VERSION)"' -DRELEASE_DATE='"$(RELEASE_DATE)"' -I include ++CPPFLAGS=-DVERSION='"$(VERSION)"' -DRELEASE_DATE='"$(RELEASE_DATE)"' -I include -fno-stack-protector + HOST_CPPFLAGS=$(CPPFLAGS) + I386_CPPFLAGS=$(CPPFLAGS) -I arch/i386/include + IA64_CPPFLAGS=$(CPPFLAGS) -I arch/ia64/include diff --git a/package/utils/nvram/Makefile b/package/utils/nvram/Makefile new file mode 100644 index 0000000..992f336 --- /dev/null +++ b/package/utils/nvram/Makefile @@ -0,0 +1,52 @@ +# +# Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org> +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=nvram +PKG_RELEASE:=9 + +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/nvram + SECTION:=utils + CATEGORY:=Base system + TITLE:=Userspace port of the Broadcom NVRAM manipulation tool + MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org> + DEPENDS:=@TARGET_brcm47xx||@TARGET_bcm53xx||@TARGET_ar71xx +endef + +define Package/nvram/description + This package contains an utility to manipulate NVRAM on Broadcom based devices. + It works on bcm47xx (Linux 2.6) without using the kernel api. +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Configure +endef + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + CC="$(TARGET_CC)" \ + CFLAGS="$(TARGET_CFLAGS) -Wall" \ + LDFLAGS="$(TARGET_LDFLAGS)" +endef + +define Package/nvram/install + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/nvram.init $(1)/etc/init.d/nvram + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/nvram $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,nvram)) diff --git a/package/utils/nvram/files/nvram.init b/package/utils/nvram/files/nvram.init new file mode 100755 index 0000000..467ab28 --- /dev/null +++ b/package/utils/nvram/files/nvram.init @@ -0,0 +1,98 @@ +#!/bin/sh /etc/rc.common +# NVRAM setup +# +# This file handles the NVRAM quirks of various hardware. + +START=02 +alias debug=${DEBUG:-:} + +nvram_default() { + [ -z "$(nvram get $1)" ] && nvram set "$1=$2" +} + +nvram_set() { # for the linksys fixup part + [ "$(nvram get "$1")" = "$2" -a "$2" != "" ] || { + COMMIT=1 + /usr/sbin/nvram set "$1=$2" + } +} + +fixup_linksys() { + # work around braindead CFE defaults in linksys routers + boardtype=$(nvram get boardtype) + boardnum=$(nvram get boardnum) + boardflags=$(($(nvram get boardflags))) + adm_switch="$(( ($boardflags & 0x80) >> 7 ))" + + [ -n "$(nvram get vxkilled)" ] && boardtype=0 # don't mess with the ram settings on the hacked cfe + case "$(( $boardtype ))" in + "1800") #0x708 + if [ "$adm_switch" = 0 ]; then + nvram_set sdram_init "$(printf 0x%04x $(( $(/usr/sbin/nvram get sdram_init) | 0x0100 )))" + [ "$COMMIT" = 1 ] && { + nvram_set clkfreq 216 + nvram_set sdram_ncdl 0x0 + nvram_set pa0itssit 62 + nvram_set pa0b0 0x15eb + nvram_set pa0b1 0xfa82 + nvram_set pa0b2 0xfe66 + nvram_set pa0maxpwr 0x4e + } + fi + ;; + "1127") #0x467 + nvram_set sdram_init "$(printf 0x%04x $(( $(/usr/sbin/nvram get sdram_init) | 0x0100 )))" + [ "$COMMIT" = 1 ] && { + nvram_set sdram_ncdl 0x0 + nvram_set pa0itssit 62 + nvram_set pa0b0 0x168b + nvram_set pa0b1 0xfabf + nvram_set pa0b2 0xfeaf + nvram_set pa0maxpwr 0x4e + } + ;; + "1071") #0x042f + # do sanity check first! max 0x0011 = 128mb + SDRAM_INIT=$(printf %d $(/usr/sbin/nvram get sdram_init)) + [ "$SDRAM_INIT" -lt "9" -o "$SDRAM_INIT" -gt "17" ] && { + # set this to default: 0x09 only if value is invaild like 16MB on Asus WL-500GP + echo "sdram_init is invaild: $(printf 0x%04x $SDRAM_INIT), force to default!" + nvram_set sdram_init 0x0009 + } + # on WRT54G3GV2 set flag, so checksum errors of firmware image 2 don't stop the boot process + noset_try_flag=$(nvram get noset_try_flag) + [ "$noset_try_flag" = 0 ] && { + echo "setting noset_try_flag to 1." + nvram_set noset_try_flag 1 + } + [ "$COMMIT" = 1 ] && { + nvram_set sdram_ncdl 0x0 + } + esac +} + +start() { + # Don't do any fixups on the WGT634U + [ "$(cat /proc/diag/model)" = "Netgear WGT634U" ] && return + + fixup_linksys + + # OFDM Power Offset is set incorrectly on many boards. + # Setting it to 0 will increase the tx power to normal levels. + nvram_set opo 0x0 + + [ "$(nvram get il0macaddr)" = "00:90:4c:5f:00:2a" ] && { + # if default wifi mac, set two higher than the lan mac + nvram set il0macaddr=$(nvram get et0macaddr| + awk '{OFS=FS=":";for(x=7,y=2;--x;){$x=sprintf("%02x",(y+="0x"$x)%256);y/=256}print}') + } + + [ "$(nvram get et0macaddr)" = "00:90:4c:c0:00:08" ] && { + # OvisLink WL-1600GL mac workaround + nvram set et0macaddr=$(hexdump -n 6 -s 130976 -e '5/1 "%02x:" "%02x" ' /dev/mtd/0) + nvram set il0macaddr=$(nvram get et0macaddr| + awk '{OFS=FS=":";for(x=7,y=2;--x;){$x=sprintf("%02x",(y+="0x"$x)%256);y/=256}print}') + } + + [ "$COMMIT" = "1" ] && nvram commit +} diff --git a/package/utils/nvram/src/Makefile b/package/utils/nvram/src/Makefile new file mode 100644 index 0000000..68a6354 --- /dev/null +++ b/package/utils/nvram/src/Makefile @@ -0,0 +1,7 @@ +all: nvram + +nvram: + $(CC) $(CFLAGS) -o $@ cli.c crc.c nvram.c $(LDFLAGS) + +clean: + rm -f nvram diff --git a/package/utils/nvram/src/cli.c b/package/utils/nvram/src/cli.c new file mode 100644 index 0000000..488d641 --- /dev/null +++ b/package/utils/nvram/src/cli.c @@ -0,0 +1,246 @@ +/* + * Command line interface for libnvram + * + * Copyright 2009, Jo-Philipp Wich <xm@subsignal.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * The libnvram code is based on Broadcom code for Linux 2.4.x . + * + */ + +#include "nvram.h" + + +static nvram_handle_t * nvram_open_rdonly(void) +{ + const char *file = nvram_find_staging(); + + if( file == NULL ) + file = nvram_find_mtd(); + + if( file != NULL ) + return nvram_open(file, NVRAM_RO); + + return NULL; +} + +static nvram_handle_t * nvram_open_staging(void) +{ + if( nvram_find_staging() != NULL || nvram_to_staging() == 0 ) + return nvram_open(NVRAM_STAGING, NVRAM_RW); + + return NULL; +} + +static int do_show(nvram_handle_t *nvram) +{ + nvram_tuple_t *t; + int stat = 1; + + if( (t = nvram_getall(nvram)) != NULL ) + { + while( t ) + { + printf("%s=%s\n", t->name, t->value); + t = t->next; + } + + stat = 0; + } + + return stat; +} + +static int do_get(nvram_handle_t *nvram, const char *var) +{ + const char *val; + int stat = 1; + + if( (val = nvram_get(nvram, var)) != NULL ) + { + printf("%s\n", val); + stat = 0; + } + + return stat; +} + +static int do_unset(nvram_handle_t *nvram, const char *var) +{ + return nvram_unset(nvram, var); +} + +static int do_set(nvram_handle_t *nvram, const char *pair) +{ + char *val = strstr(pair, "="); + char var[strlen(pair)]; + int stat = 1; + + if( val != NULL ) + { + memset(var, 0, sizeof(var)); + strncpy(var, pair, (int)(val-pair)); + stat = nvram_set(nvram, var, (char *)(val + 1)); + } + + return stat; +} + +static int do_info(nvram_handle_t *nvram) +{ + nvram_header_t *hdr = nvram_header(nvram); + + /* CRC8 over the last 11 bytes of the header and data bytes */ + uint8_t crc = hndcrc8((unsigned char *) &hdr[0] + NVRAM_CRC_START_POSITION, + hdr->len - NVRAM_CRC_START_POSITION, 0xff); + + /* Show info */ + printf("Magic: 0x%08X\n", hdr->magic); + printf("Length: 0x%08X\n", hdr->len); + printf("Offset: 0x%08X\n", nvram->offset); + + printf("CRC8: 0x%02X (calculated: 0x%02X)\n", + hdr->crc_ver_init & 0xFF, crc); + + printf("Version: 0x%02X\n", (hdr->crc_ver_init >> 8) & 0xFF); + printf("SDRAM init: 0x%04X\n", (hdr->crc_ver_init >> 16) & 0xFFFF); + printf("SDRAM config: 0x%04X\n", hdr->config_refresh & 0xFFFF); + printf("SDRAM refresh: 0x%04X\n", (hdr->config_refresh >> 16) & 0xFFFF); + printf("NCDL values: 0x%08X\n\n", hdr->config_ncdl); + + printf("%i bytes used / %i bytes available (%.2f%%)\n", + hdr->len, nvram->length - nvram->offset - hdr->len, + (100.00 / (double)(nvram->length - nvram->offset)) * (double)hdr->len); + + return 0; +} + + +int main( int argc, const char *argv[] ) +{ + nvram_handle_t *nvram; + int commit = 0; + int write = 0; + int stat = 1; + int done = 0; + int i; + + /* Ugly... iterate over arguments to see whether we can expect a write */ + for( i = 1; i < argc; i++ ) + if( ( !strcmp(argv[i], "set") && ++i < argc ) || + ( !strcmp(argv[i], "unset") && ++i < argc ) || + !strcmp(argv[i], "commit") ) + { + write = 1; + break; + } + + + nvram = write ? nvram_open_staging() : nvram_open_rdonly(); + + if( nvram != NULL && argc > 1 ) + { + for( i = 1; i < argc; i++ ) + { + if( !strcmp(argv[i], "show") ) + { + stat = do_show(nvram); + done++; + } + else if( !strcmp(argv[i], "info") ) + { + stat = do_info(nvram); + done++; + } + else if( !strcmp(argv[i], "get") || !strcmp(argv[i], "unset") || !strcmp(argv[i], "set") ) + { + if( (i+1) < argc ) + { + switch(argv[i++][0]) + { + case 'g': + stat = do_get(nvram, argv[i]); + break; + + case 'u': + stat = do_unset(nvram, argv[i]); + break; + + case 's': + stat = do_set(nvram, argv[i]); + break; + } + done++; + } + else + { + fprintf(stderr, "Command '%s' requires an argument!\n", argv[i]); + done = 0; + break; + } + } + else if( !strcmp(argv[i], "commit") ) + { + commit = 1; + done++; + } + else + { + fprintf(stderr, "Unknown option '%s' !\n", argv[i]); + done = 0; + break; + } + } + + if( write ) + stat = nvram_commit(nvram); + + nvram_close(nvram); + + if( commit ) + stat = staging_to_nvram(); + } + + if( !nvram ) + { + fprintf(stderr, + "Could not open nvram! Possible reasons are:\n" + " - No device found (/proc not mounted or no nvram present)\n" + " - Insufficient permissions to open mtd device\n" + " - Insufficient memory to complete operation\n" + " - Memory mapping failed or not supported\n" + ); + + stat = 1; + } + else if( !done ) + { + fprintf(stderr, + "Usage:\n" + " nvram show\n" + " nvram info\n" + " nvram get variable\n" + " nvram set variable=value [set ...]\n" + " nvram unset variable [unset ...]\n" + " nvram commit\n" + ); + + stat = 1; + } + + return stat; +} diff --git a/package/utils/nvram/src/crc.c b/package/utils/nvram/src/crc.c new file mode 100644 index 0000000..22a3665 --- /dev/null +++ b/package/utils/nvram/src/crc.c @@ -0,0 +1,69 @@ +#include "nvram.h" + +/******************************************************************************* + * crc8 + * + * Computes a crc8 over the input data using the polynomial: + * + * x^8 + x^7 +x^6 + x^4 + x^2 + 1 + * + * The caller provides the initial value (either CRC8_INIT_VALUE + * or the previous returned value) to allow for processing of + * discontiguous blocks of data. When generating the CRC the + * caller is responsible for complementing the final return value + * and inserting it into the byte stream. When checking, a final + * return value of CRC8_GOOD_VALUE indicates a valid CRC. + * + * Reference: Dallas Semiconductor Application Note 27 + * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", + * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., + * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt + * + * **************************************************************************** + */ + +static const uint8_t crc8_table[256] = { + 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, + 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, + 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, + 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, + 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, + 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, + 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, + 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, + 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, + 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, + 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, + 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, + 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, + 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, + 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, + 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, + 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, + 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, + 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, + 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, + 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, + 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, + 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, + 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, + 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, + 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, + 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, + 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, + 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, + 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, + 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, + 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F +}; + +uint8_t hndcrc8 ( + uint8_t * pdata, /* pointer to array of data to process */ + uint32_t nbytes, /* number of input data bytes to process */ + uint8_t crc /* either CRC8_INIT_VALUE or previous return value */ +) { + while (nbytes-- > 0) + crc = crc8_table[(crc ^ *pdata++) & 0xff]; + + return crc; +} diff --git a/package/utils/nvram/src/nvram.c b/package/utils/nvram/src/nvram.c new file mode 100644 index 0000000..0e42943 --- /dev/null +++ b/package/utils/nvram/src/nvram.c @@ -0,0 +1,540 @@ +/* + * NVRAM variable manipulation (common) + * + * Copyright 2004, Broadcom Corporation + * Copyright 2009-2010, OpenWrt.org + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + */ + +#include "nvram.h" + +#define TRACE(msg) \ + printf("%s(%i) in %s(): %s\n", \ + __FILE__, __LINE__, __FUNCTION__, msg ? msg : "?") + +/* Size of "nvram" MTD partition */ +size_t nvram_part_size = 0; + + +/* + * -- Helper functions -- + */ + +/* String hash */ +static uint32_t hash(const char *s) +{ + uint32_t hash = 0; + + while (*s) + hash = 31 * hash + *s++; + + return hash; +} + +/* Free all tuples. */ +static void _nvram_free(nvram_handle_t *h) +{ + uint32_t i; + nvram_tuple_t *t, *next; + + /* Free hash table */ + for (i = 0; i < NVRAM_ARRAYSIZE(h->nvram_hash); i++) { + for (t = h->nvram_hash[i]; t; t = next) { + next = t->next; + free(t); + } + h->nvram_hash[i] = NULL; + } + + /* Free dead table */ + for (t = h->nvram_dead; t; t = next) { + next = t->next; + free(t); + } + + h->nvram_dead = NULL; +} + +/* (Re)allocate NVRAM tuples. */ +static nvram_tuple_t * _nvram_realloc( nvram_handle_t *h, nvram_tuple_t *t, + const char *name, const char *value ) +{ + if ((strlen(value) + 1) > h->length - h->offset) + return NULL; + + if (!t) { + if (!(t = malloc(sizeof(nvram_tuple_t) + strlen(name) + 1))) + return NULL; + + /* Copy name */ + t->name = (char *) &t[1]; + strcpy(t->name, name); + + t->value = NULL; + } + + /* Copy value */ + if (!t->value || strcmp(t->value, value)) + { + if(!(t->value = (char *) realloc(t->value, strlen(value)+1))) + return NULL; + + strcpy(t->value, value); + t->value[strlen(value)] = '\0'; + } + + return t; +} + +/* (Re)initialize the hash table. */ +static int _nvram_rehash(nvram_handle_t *h) +{ + nvram_header_t *header = nvram_header(h); + char buf[] = "0xXXXXXXXX", *name, *value, *eq; + + /* (Re)initialize hash table */ + _nvram_free(h); + + /* Parse and set "name=value\0 ... \0\0" */ + name = (char *) &header[1]; + + for (; *name; name = value + strlen(value) + 1) { + if (!(eq = strchr(name, '='))) + break; + *eq = '\0'; + value = eq + 1; + nvram_set(h, name, value); + *eq = '='; + } + + /* Set special SDRAM parameters */ + if (!nvram_get(h, "sdram_init")) { + sprintf(buf, "0x%04X", (uint16_t)(header->crc_ver_init >> 16)); + nvram_set(h, "sdram_init", buf); + } + if (!nvram_get(h, "sdram_config")) { + sprintf(buf, "0x%04X", (uint16_t)(header->config_refresh & 0xffff)); + nvram_set(h, "sdram_config", buf); + } + if (!nvram_get(h, "sdram_refresh")) { + sprintf(buf, "0x%04X", + (uint16_t)((header->config_refresh >> 16) & 0xffff)); + nvram_set(h, "sdram_refresh", buf); + } + if (!nvram_get(h, "sdram_ncdl")) { + sprintf(buf, "0x%08X", header->config_ncdl); + nvram_set(h, "sdram_ncdl", buf); + } + + return 0; +} + + +/* + * -- Public functions -- + */ + +/* Get nvram header. */ +nvram_header_t * nvram_header(nvram_handle_t *h) +{ + return (nvram_header_t *) &h->mmap[h->offset]; +} + +/* Get the value of an NVRAM variable. */ +char * nvram_get(nvram_handle_t *h, const char *name) +{ + uint32_t i; + nvram_tuple_t *t; + char *value; + + if (!name) + return NULL; + + /* Hash the name */ + i = hash(name) % NVRAM_ARRAYSIZE(h->nvram_hash); + + /* Find the associated tuple in the hash table */ + for (t = h->nvram_hash[i]; t && strcmp(t->name, name); t = t->next); + + value = t ? t->value : NULL; + + return value; +} + +/* Set the value of an NVRAM variable. */ +int nvram_set(nvram_handle_t *h, const char *name, const char *value) +{ + uint32_t i; + nvram_tuple_t *t, *u, **prev; + + /* Hash the name */ + i = hash(name) % NVRAM_ARRAYSIZE(h->nvram_hash); + + /* Find the associated tuple in the hash table */ + for (prev = &h->nvram_hash[i], t = *prev; + t && strcmp(t->name, name); prev = &t->next, t = *prev); + + /* (Re)allocate tuple */ + if (!(u = _nvram_realloc(h, t, name, value))) + return -12; /* -ENOMEM */ + + /* Value reallocated */ + if (t && t == u) + return 0; + + /* Move old tuple to the dead table */ + if (t) { + *prev = t->next; + t->next = h->nvram_dead; + h->nvram_dead = t; + } + + /* Add new tuple to the hash table */ + u->next = h->nvram_hash[i]; + h->nvram_hash[i] = u; + + return 0; +} + +/* Unset the value of an NVRAM variable. */ +int nvram_unset(nvram_handle_t *h, const char *name) +{ + uint32_t i; + nvram_tuple_t *t, **prev; + + if (!name) + return 0; + + /* Hash the name */ + i = hash(name) % NVRAM_ARRAYSIZE(h->nvram_hash); + + /* Find the associated tuple in the hash table */ + for (prev = &h->nvram_hash[i], t = *prev; + t && strcmp(t->name, name); prev = &t->next, t = *prev); + + /* Move it to the dead table */ + if (t) { + *prev = t->next; + t->next = h->nvram_dead; + h->nvram_dead = t; + } + + return 0; +} + +/* Get all NVRAM variables. */ +nvram_tuple_t * nvram_getall(nvram_handle_t *h) +{ + int i; + nvram_tuple_t *t, *l, *x; + + l = NULL; + + for (i = 0; i < NVRAM_ARRAYSIZE(h->nvram_hash); i++) { + for (t = h->nvram_hash[i]; t; t = t->next) { + if( (x = (nvram_tuple_t *) malloc(sizeof(nvram_tuple_t))) != NULL ) + { + x->name = t->name; + x->value = t->value; + x->next = l; + l = x; + } + else + { + break; + } + } + } + + return l; +} + +/* Regenerate NVRAM. */ +int nvram_commit(nvram_handle_t *h) +{ + nvram_header_t *header = nvram_header(h); + char *init, *config, *refresh, *ncdl; + char *ptr, *end; + int i; + nvram_tuple_t *t; + nvram_header_t tmp; + uint8_t crc; + + /* Regenerate header */ + header->magic = NVRAM_MAGIC; + header->crc_ver_init = (NVRAM_VERSION << 8); + if (!(init = nvram_get(h, "sdram_init")) || + !(config = nvram_get(h, "sdram_config")) || + !(refresh = nvram_get(h, "sdram_refresh")) || + !(ncdl = nvram_get(h, "sdram_ncdl"))) { + header->crc_ver_init |= SDRAM_INIT << 16; + header->config_refresh = SDRAM_CONFIG; + header->config_refresh |= SDRAM_REFRESH << 16; + header->config_ncdl = 0; + } else { + header->crc_ver_init |= (strtoul(init, NULL, 0) & 0xffff) << 16; + header->config_refresh = strtoul(config, NULL, 0) & 0xffff; + header->config_refresh |= (strtoul(refresh, NULL, 0) & 0xffff) << 16; + header->config_ncdl = strtoul(ncdl, NULL, 0); + } + + /* Clear data area */ + ptr = (char *) header + sizeof(nvram_header_t); + memset(ptr, 0xFF, nvram_part_size - h->offset - sizeof(nvram_header_t)); + memset(&tmp, 0, sizeof(nvram_header_t)); + + /* Leave space for a double NUL at the end */ + end = (char *) header + nvram_part_size - h->offset - 2; + + /* Write out all tuples */ + for (i = 0; i < NVRAM_ARRAYSIZE(h->nvram_hash); i++) { + for (t = h->nvram_hash[i]; t; t = t->next) { + if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end) + break; + ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1; + } + } + + /* End with a double NULL and pad to 4 bytes */ + *ptr = '\0'; + ptr++; + + if( (int)ptr % 4 ) + memset(ptr, 0, 4 - ((int)ptr % 4)); + + ptr++; + + /* Set new length */ + header->len = NVRAM_ROUNDUP(ptr - (char *) header, 4); + + /* Little-endian CRC8 over the last 11 bytes of the header */ + tmp.crc_ver_init = header->crc_ver_init; + tmp.config_refresh = header->config_refresh; + tmp.config_ncdl = header->config_ncdl; + crc = hndcrc8((unsigned char *) &tmp + NVRAM_CRC_START_POSITION, + sizeof(nvram_header_t) - NVRAM_CRC_START_POSITION, 0xff); + + /* Continue CRC8 over data bytes */ + crc = hndcrc8((unsigned char *) &header[0] + sizeof(nvram_header_t), + header->len - sizeof(nvram_header_t), crc); + + /* Set new CRC8 */ + header->crc_ver_init |= crc; + + /* Write out */ + msync(h->mmap, h->length, MS_SYNC); + fsync(h->fd); + + /* Reinitialize hash table */ + return _nvram_rehash(h); +} + +/* Open NVRAM and obtain a handle. */ +nvram_handle_t * nvram_open(const char *file, int rdonly) +{ + int i; + int fd; + char *mtd = NULL; + nvram_handle_t *h; + nvram_header_t *header; + int offset = -1; + + /* If erase size or file are undefined then try to define them */ + if( (nvram_part_size == 0) || (file == NULL) ) + { + /* Finding the mtd will set the appropriate erase size */ + if( (mtd = nvram_find_mtd()) == NULL || nvram_part_size == 0 ) + { + free(mtd); + return NULL; + } + } + + if( (fd = open(file ? file : mtd, O_RDWR)) > -1 ) + { + char *mmap_area = (char *) mmap( + NULL, nvram_part_size, PROT_READ | PROT_WRITE, + (( rdonly == NVRAM_RO ) ? MAP_PRIVATE : MAP_SHARED) | MAP_LOCKED, fd, 0); + + if( mmap_area != MAP_FAILED ) + { + /* + * Start looking for NVRAM_MAGIC at beginning of MTD + * partition. Stop if there is less than NVRAM_MIN_SPACE + * to check, that was the lowest used size. + */ + for( i = 0; i <= ((nvram_part_size - NVRAM_MIN_SPACE) / sizeof(uint32_t)); i++ ) + { + if( ((uint32_t *)mmap_area)[i] == NVRAM_MAGIC ) + { + offset = i * sizeof(uint32_t); + break; + } + } + + if( offset < 0 ) + { + free(mtd); + return NULL; + } + else if( (h = malloc(sizeof(nvram_handle_t))) != NULL ) + { + memset(h, 0, sizeof(nvram_handle_t)); + + h->fd = fd; + h->mmap = mmap_area; + h->length = nvram_part_size; + h->offset = offset; + + header = nvram_header(h); + + if (header->magic == NVRAM_MAGIC && + (rdonly || header->len < h->length - h->offset)) { + _nvram_rehash(h); + free(mtd); + return h; + } + else + { + munmap(h->mmap, h->length); + free(h); + } + } + } + } + + free(mtd); + return NULL; +} + +/* Close NVRAM and free memory. */ +int nvram_close(nvram_handle_t *h) +{ + _nvram_free(h); + munmap(h->mmap, h->length); + close(h->fd); + free(h); + + return 0; +} + +/* Determine NVRAM device node. */ +char * nvram_find_mtd(void) +{ + FILE *fp; + int i, part_size; + char dev[PATH_MAX]; + char *path = NULL; + struct stat s; + + if ((fp = fopen("/proc/mtd", "r"))) + { + while( fgets(dev, sizeof(dev), fp) ) + { + if( strstr(dev, "nvram") && sscanf(dev, "mtd%d: %08x", &i, &part_size) ) + { + nvram_part_size = part_size; + + sprintf(dev, "/dev/mtdblock%d", i); + if( stat(dev, &s) > -1 && (s.st_mode & S_IFBLK) ) + { + if( (path = (char *) malloc(strlen(dev)+1)) != NULL ) + { + strncpy(path, dev, strlen(dev)+1); + break; + } + } + } + } + fclose(fp); + } + + return path; +} + +/* Check NVRAM staging file. */ +char * nvram_find_staging(void) +{ + struct stat s; + + if( (stat(NVRAM_STAGING, &s) > -1) && (s.st_mode & S_IFREG) ) + { + return NVRAM_STAGING; + } + + return NULL; +} + +/* Copy NVRAM contents to staging file. */ +int nvram_to_staging(void) +{ + int fdmtd, fdstg, stat; + char *mtd = nvram_find_mtd(); + char buf[nvram_part_size]; + + stat = -1; + + if( (mtd != NULL) && (nvram_part_size > 0) ) + { + if( (fdmtd = open(mtd, O_RDONLY)) > -1 ) + { + if( read(fdmtd, buf, sizeof(buf)) == sizeof(buf) ) + { + if((fdstg = open(NVRAM_STAGING, O_WRONLY | O_CREAT, 0600)) > -1) + { + write(fdstg, buf, sizeof(buf)); + fsync(fdstg); + close(fdstg); + + stat = 0; + } + } + + close(fdmtd); + } + } + + free(mtd); + return stat; +} + +/* Copy staging file to NVRAM device. */ +int staging_to_nvram(void) +{ + int fdmtd, fdstg, stat; + char *mtd = nvram_find_mtd(); + char buf[nvram_part_size]; + + stat = -1; + + if( (mtd != NULL) && (nvram_part_size > 0) ) + { + if( (fdstg = open(NVRAM_STAGING, O_RDONLY)) > -1 ) + { + if( read(fdstg, buf, sizeof(buf)) == sizeof(buf) ) + { + if( (fdmtd = open(mtd, O_WRONLY | O_SYNC)) > -1 ) + { + write(fdmtd, buf, sizeof(buf)); + fsync(fdmtd); + close(fdmtd); + stat = 0; + } + } + + close(fdstg); + + if( !stat ) + stat = unlink(NVRAM_STAGING) ? 1 : 0; + } + } + + free(mtd); + return stat; +} diff --git a/package/utils/nvram/src/nvram.h b/package/utils/nvram/src/nvram.h new file mode 100644 index 0000000..724f33b --- /dev/null +++ b/package/utils/nvram/src/nvram.h @@ -0,0 +1,123 @@ +/* + * NVRAM variable manipulation + * + * Copyright 2007, Broadcom Corporation + * Copyright 2009, OpenWrt.org + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + */ + +#ifndef _nvram_h_ +#define _nvram_h_ + +#include <stdint.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <linux/limits.h> + +#include "sdinitvals.h" + + +struct nvram_header { + uint32_t magic; + uint32_t len; + uint32_t crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ + uint32_t config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ + uint32_t config_ncdl; /* ncdl values for memc */ +} __attribute__((__packed__)); + +struct nvram_tuple { + char *name; + char *value; + struct nvram_tuple *next; +}; + +struct nvram_handle { + int fd; + char *mmap; + unsigned int length; + unsigned int offset; + struct nvram_tuple *nvram_hash[257]; + struct nvram_tuple *nvram_dead; +}; + +typedef struct nvram_handle nvram_handle_t; +typedef struct nvram_header nvram_header_t; +typedef struct nvram_tuple nvram_tuple_t; + + +/* Get nvram header. */ +nvram_header_t * nvram_header(nvram_handle_t *h); + +/* Set the value of an NVRAM variable */ +int nvram_set(nvram_handle_t *h, const char *name, const char *value); + +/* Get the value of an NVRAM variable. */ +char * nvram_get(nvram_handle_t *h, const char *name); + +/* Unset the value of an NVRAM variable. */ +int nvram_unset(nvram_handle_t *h, const char *name); + +/* Get all NVRAM variables. */ +nvram_tuple_t * nvram_getall(nvram_handle_t *h); + +/* Regenerate NVRAM. */ +int nvram_commit(nvram_handle_t *h); + +/* Open NVRAM and obtain a handle. */ +nvram_handle_t * nvram_open(const char *file, int rdonly); + +/* Close NVRAM and free memory. */ +int nvram_close(nvram_handle_t *h); + +/* Get the value of an NVRAM variable in a safe way, use "" instead of NULL. */ +#define nvram_safe_get(h, name) (nvram_get(h, name) ? : "") + +/* Computes a crc8 over the input data. */ +uint8_t hndcrc8 (uint8_t * pdata, uint32_t nbytes, uint8_t crc); + +/* Returns the crc value of the nvram. */ +uint8_t nvram_calc_crc(nvram_header_t * nvh); + +/* Determine NVRAM device node. */ +char * nvram_find_mtd(void); + +/* Copy NVRAM contents to staging file. */ +int nvram_to_staging(void); + +/* Copy staging file to NVRAM device. */ +int staging_to_nvram(void); + +/* Check NVRAM staging file. */ +char * nvram_find_staging(void); + + +/* Staging file for NVRAM */ +#define NVRAM_STAGING "/tmp/.nvram" +#define NVRAM_RO 1 +#define NVRAM_RW 0 + +/* Helper macros */ +#define NVRAM_ARRAYSIZE(a) sizeof(a)/sizeof(a[0]) +#define NVRAM_ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) + +/* NVRAM constants */ +#define NVRAM_MIN_SPACE 0x8000 +#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ +#define NVRAM_VERSION 1 + +#define NVRAM_CRC_START_POSITION 9 /* magic, len, crc8 to be skipped */ + + +#endif /* _nvram_h_ */ diff --git a/package/utils/nvram/src/sdinitvals.h b/package/utils/nvram/src/sdinitvals.h new file mode 100644 index 0000000..5a289ad --- /dev/null +++ b/package/utils/nvram/src/sdinitvals.h @@ -0,0 +1,30 @@ +/* + * SDRAM init values + * + * Copyright 2007, Broadcom Corporation + * Copyright 2009, OpenWrt.org + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + */ + +#ifndef _sdinitvals_h_ +#define _sdinitvals_h_ + +/* SDRAM refresh control (refresh) register bits */ +#define SDRAM_REF(p) (((p)&0xff) | SDRAM_REF_EN) /* Refresh period */ +#define SDRAM_REF_EN 0x8000 /* Writing 1 enables periodic refresh */ + +/* SDRAM Core default Init values (OCP ID 0x803) */ +#define MEM4MX16X2 0x419 /* 16 MB */ + +#define SDRAM_INIT MEM4MX16X2 +#define SDRAM_BURSTFULL 0x0000 /* Use full page bursts */ +#define SDRAM_CONFIG SDRAM_BURSTFULL +#define SDRAM_REFRESH SDRAM_REF(0x40) + +#endif /* _sdinitvals_h_ */ diff --git a/package/utils/otrx/Makefile b/package/utils/otrx/Makefile new file mode 100644 index 0000000..360fb17 --- /dev/null +++ b/package/utils/otrx/Makefile @@ -0,0 +1,43 @@ +# +# Copyright (C) 2015 Rafał Miłecki <zajec5@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:=otrx +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/otrx + SECTION:=utils + CATEGORY:=Base system + TITLE:=Utility for opening (analyzing) TRX firmware images + MAINTAINER:=Rafał Miłecki <zajec5@gmail.com> + DEPENDS:=@TARGET_brcm47xx||@TARGET_bcm53xx +endef + +define Package/otrx/description + This package contains an utility that allows validating TRX images. +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + CC="$(TARGET_CC)" \ + CFLAGS="$(TARGET_CFLAGS) -Wall" +endef + +define Package/otrx/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/otrx $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,otrx)) diff --git a/package/utils/otrx/src/Makefile b/package/utils/otrx/src/Makefile new file mode 100644 index 0000000..df50ea4 --- /dev/null +++ b/package/utils/otrx/src/Makefile @@ -0,0 +1,7 @@ +all: otrx + +otrx: + $(CC) $(CFLAGS) -o $@ otrx.c -Wall + +clean: + rm -f otrx diff --git a/package/utils/otrx/src/otrx.c b/package/utils/otrx/src/otrx.c new file mode 100644 index 0000000..101a310 --- /dev/null +++ b/package/utils/otrx/src/otrx.c @@ -0,0 +1,577 @@ +/* + * otrx + * + * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include <byteswap.h> +#include <endian.h> +#include <errno.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#if !defined(__BYTE_ORDER) +#error "Unknown byte order" +#endif + +#if __BYTE_ORDER == __BIG_ENDIAN +#define cpu_to_le32(x) bswap_32(x) +#define le32_to_cpu(x) bswap_32(x) +#elif __BYTE_ORDER == __LITTLE_ENDIAN +#define cpu_to_le32(x) (x) +#define le32_to_cpu(x) (x) +#else +#error "Unsupported endianness" +#endif + +#define TRX_MAGIC 0x30524448 +#define TRX_FLAGS_OFFSET 12 +#define TRX_MAX_PARTS 3 + +struct trx_header { + uint32_t magic; + uint32_t length; + uint32_t crc32; + uint16_t flags; + uint16_t version; + uint32_t offset[3]; +}; + +char *trx_path; +size_t trx_offset = 0; +char *partition[TRX_MAX_PARTS] = {}; + +static inline size_t otrx_min(size_t x, size_t y) { + return x < y ? x : y; +} + +/************************************************** + * CRC32 + **************************************************/ + +static const uint32_t crc32_tbl[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, +}; + +uint32_t otrx_crc32(uint8_t *buf, size_t len) { + uint32_t crc = 0xffffffff; + + while (len) { + crc = crc32_tbl[(crc ^ *buf) & 0xff] ^ (crc >> 8); + buf++; + len--; + } + + return crc; +} + +/************************************************** + * Check + **************************************************/ + +static void otrx_check_parse_options(int argc, char **argv) { + int c; + + while ((c = getopt(argc, argv, "o:")) != -1) { + switch (c) { + case 'o': + trx_offset = atoi(optarg); + break; + } + } +} + +static int otrx_check(int argc, char **argv) { + FILE *trx; + struct trx_header hdr; + size_t bytes, length; + uint8_t buf[1024]; + uint32_t crc32; + int i; + int err = 0; + + if (argc < 3) { + fprintf(stderr, "No TRX file passed\n"); + err = -EINVAL; + goto out; + } + trx_path = argv[2]; + + optind = 3; + otrx_check_parse_options(argc, argv); + + trx = fopen(trx_path, "r"); + if (!trx) { + fprintf(stderr, "Couldn't open %s\n", trx_path); + err = -EACCES; + goto out; + } + + fseek(trx, trx_offset, SEEK_SET); + bytes = fread(&hdr, 1, sizeof(hdr), trx); + if (bytes != sizeof(hdr)) { + fprintf(stderr, "Couldn't read %s header\n", trx_path); + err = -EIO; + goto err_close; + } + + if (le32_to_cpu(hdr.magic) != TRX_MAGIC) { + fprintf(stderr, "Invalid TRX magic: 0x%08x\n", le32_to_cpu(hdr.magic)); + err = -EINVAL; + goto err_close; + } + + length = le32_to_cpu(hdr.length); + if (length < sizeof(hdr)) { + fprintf(stderr, "Length read from TRX too low (%zu B)\n", length); + err = -EINVAL; + goto err_close; + } + + crc32 = 0xffffffff; + fseek(trx, trx_offset + TRX_FLAGS_OFFSET, SEEK_SET); + length -= TRX_FLAGS_OFFSET; + while ((bytes = fread(buf, 1, otrx_min(sizeof(buf), length), trx)) > 0) { + for (i = 0; i < bytes; i++) + crc32 = crc32_tbl[(crc32 ^ buf[i]) & 0xff] ^ (crc32 >> 8); + length -= bytes; + } + + if (length) { + fprintf(stderr, "Couldn't read last %zd B of data from %s\n", length, trx_path); + err = -EIO; + goto err_close; + } + + if (crc32 != le32_to_cpu(hdr.crc32)) { + fprintf(stderr, "Invalid data crc32: 0x%08x instead of 0x%08x\n", crc32, le32_to_cpu(hdr.crc32)); + err = -EINVAL; + goto err_close; + } + + printf("Found a valid TRX version %d\n", le32_to_cpu(hdr.version)); + +err_close: + fclose(trx); +out: + return err; +} + +/************************************************** + * Create + **************************************************/ + +static void otrx_create_parse_options(int argc, char **argv) { +} + +static ssize_t otrx_create_append_file(FILE *trx, const char *in_path) { + FILE *in; + size_t bytes; + ssize_t length = 0; + uint8_t buf[128]; + + in = fopen(in_path, "r"); + if (!in) { + fprintf(stderr, "Couldn't open %s\n", in_path); + return -EACCES; + } + + while ((bytes = fread(buf, 1, sizeof(buf), in)) > 0) { + if (fwrite(buf, 1, bytes, trx) != bytes) { + fprintf(stderr, "Couldn't write %zu B to %s\n", bytes, trx_path); + length = -EIO; + break; + } + length += bytes; + } + + fclose(in); + + return length; +} + +static ssize_t otrx_create_append_zeros(FILE *trx, size_t length) { + uint8_t *buf; + + buf = malloc(length); + if (!buf) + return -ENOMEM; + memset(buf, 0, length); + + if (fwrite(buf, 1, length, trx) != length) { + fprintf(stderr, "Couldn't write %zu B to %s\n", length, trx_path); + return -EIO; + } + + return length; +} + +static ssize_t otrx_create_align(FILE *trx, size_t curr_offset, size_t alignment) { + if (curr_offset & (alignment - 1)) { + size_t length = alignment - (curr_offset % alignment); + return otrx_create_append_zeros(trx, length); + } + + return 0; +} + +static int otrx_create_write_hdr(FILE *trx, struct trx_header *hdr) { + size_t bytes, length; + uint8_t *buf; + uint32_t crc32; + + hdr->magic = cpu_to_le32(TRX_MAGIC); + hdr->version = 1; + + fseek(trx, 0, SEEK_SET); + bytes = fwrite(hdr, 1, sizeof(struct trx_header), trx); + if (bytes != sizeof(struct trx_header)) { + fprintf(stderr, "Couldn't write TRX header to %s\n", trx_path); + return -EIO; + } + + length = le32_to_cpu(hdr->length); + + buf = malloc(length); + if (!buf) { + fprintf(stderr, "Couldn't alloc %zu B buffer\n", length); + return -ENOMEM; + } + + fseek(trx, 0, SEEK_SET); + bytes = fread(buf, 1, length, trx); + if (bytes != length) { + fprintf(stderr, "Couldn't read %zu B of data from %s\n", length, trx_path); + return -ENOMEM; + } + + crc32 = otrx_crc32(buf + TRX_FLAGS_OFFSET, length - TRX_FLAGS_OFFSET); + hdr->crc32 = cpu_to_le32(crc32); + + fseek(trx, 0, SEEK_SET); + bytes = fwrite(hdr, 1, sizeof(struct trx_header), trx); + if (bytes != sizeof(struct trx_header)) { + fprintf(stderr, "Couldn't write TRX header to %s\n", trx_path); + return -EIO; + } + + return 0; +} + +static int otrx_create(int argc, char **argv) { + FILE *trx; + struct trx_header hdr = {}; + ssize_t sbytes; + size_t curr_idx = 0; + size_t curr_offset = sizeof(hdr); + int c; + int err = 0; + + if (argc < 3) { + fprintf(stderr, "No TRX file passed\n"); + err = -EINVAL; + goto out; + } + trx_path = argv[2]; + + optind = 3; + otrx_create_parse_options(argc, argv); + + trx = fopen(trx_path, "w+"); + if (!trx) { + fprintf(stderr, "Couldn't open %s\n", trx_path); + err = -EACCES; + goto out; + } + fseek(trx, curr_offset, SEEK_SET); + + optind = 3; + while ((c = getopt(argc, argv, "f:b:")) != -1) { + switch (c) { + case 'f': + if (curr_idx >= TRX_MAX_PARTS) { + err = -ENOSPC; + fprintf(stderr, "Reached TRX partitions limit, no place for %s\n", optarg); + goto err_close; + } + + sbytes = otrx_create_append_file(trx, optarg); + if (sbytes < 0) { + fprintf(stderr, "Failed to append file %s\n", optarg); + } else { + hdr.offset[curr_idx++] = curr_offset; + curr_offset += sbytes; + } + + sbytes = otrx_create_align(trx, curr_offset, 4); + if (sbytes < 0) + fprintf(stderr, "Failed to append zeros\n"); + else + curr_offset += sbytes; + + break; + case 'b': + sbytes = strtol(optarg, NULL, 0) - curr_offset; + if (sbytes < 0) { + fprintf(stderr, "Current TRX length is 0x%zx, can't pad it with zeros to 0x%lx\n", curr_offset, strtol(optarg, NULL, 0)); + } else { + sbytes = otrx_create_append_zeros(trx, sbytes); + if (sbytes < 0) + fprintf(stderr, "Failed to append zeros\n"); + else + curr_offset += sbytes; + } + break; + } + if (err) + break; + } + + hdr.length = curr_offset; + otrx_create_write_hdr(trx, &hdr); +err_close: + fclose(trx); +out: + return err; +} + +/************************************************** + * Extract + **************************************************/ + +static void otrx_extract_parse_options(int argc, char **argv) { + int c; + + while ((c = getopt(argc, argv, "c:e:o:1:2:3:")) != -1) { + switch (c) { + case 'o': + trx_offset = atoi(optarg); + break; + case '1': + partition[0] = optarg; + break; + case '2': + partition[1] = optarg; + break; + case '3': + partition[2] = optarg; + break; + } + } +} + +static int otrx_extract_copy(FILE *trx, size_t offset, size_t length, char *out_path) { + FILE *out; + size_t bytes; + uint8_t *buf; + int err = 0; + + out = fopen(out_path, "w"); + if (!out) { + fprintf(stderr, "Couldn't open %s\n", out_path); + err = -EACCES; + goto out; + } + + buf = malloc(length); + if (!buf) { + fprintf(stderr, "Couldn't alloc %zu B buffer\n", length); + err = -ENOMEM; + goto err_close; + } + + fseek(trx, offset, SEEK_SET); + bytes = fread(buf, 1, length, trx); + if (bytes != length) { + fprintf(stderr, "Couldn't read %zu B of data from %s\n", length, trx_path); + err = -ENOMEM; + goto err_free_buf; + }; + + bytes = fwrite(buf, 1, length, out); + if (bytes != length) { + fprintf(stderr, "Couldn't write %zu B to %s\n", length, out_path); + err = -ENOMEM; + goto err_free_buf; + } + + printf("Extracted 0x%zx bytes into %s\n", length, out_path); + +err_free_buf: + free(buf); +err_close: + fclose(out); +out: + return err; +} + +static int otrx_extract(int argc, char **argv) { + FILE *trx; + struct trx_header hdr; + size_t bytes; + int i; + int err = 0; + + if (argc < 3) { + fprintf(stderr, "No TRX file passed\n"); + err = -EINVAL; + goto out; + } + trx_path = argv[2]; + + optind = 3; + otrx_extract_parse_options(argc, argv); + + trx = fopen(trx_path, "r"); + if (!trx) { + fprintf(stderr, "Couldn't open %s\n", trx_path); + err = -EACCES; + goto out; + } + + fseek(trx, trx_offset, SEEK_SET); + bytes = fread(&hdr, 1, sizeof(hdr), trx); + if (bytes != sizeof(hdr)) { + fprintf(stderr, "Couldn't read %s header\n", trx_path); + err = -EIO; + goto err_close; + } + + if (le32_to_cpu(hdr.magic) != TRX_MAGIC) { + fprintf(stderr, "Invalid TRX magic: 0x%08x\n", le32_to_cpu(hdr.magic)); + err = -EINVAL; + goto err_close; + } + + for (i = 0; i < TRX_MAX_PARTS; i++) { + size_t length; + + if (!partition[i]) + continue; + if (!hdr.offset[i]) { + printf("TRX doesn't contain partition %d, can't extract %s\n", i + 1, partition[i]); + continue; + } + + if (i + 1 >= TRX_MAX_PARTS || !hdr.offset[i + 1]) + length = le32_to_cpu(hdr.length) - le32_to_cpu(hdr.offset[i]); + else + length = le32_to_cpu(hdr.offset[i + 1]) - le32_to_cpu(hdr.offset[i]); + + otrx_extract_copy(trx, trx_offset + le32_to_cpu(hdr.offset[i]), length, partition[i]); + } + +err_close: + fclose(trx); +out: + return err; +} + +/************************************************** + * Start + **************************************************/ + +static void usage() { + printf("Usage:\n"); + printf("\n"); + printf("Checking TRX file:\n"); + printf("\totrx check <file> [options]\tcheck if file is a valid TRX\n"); + printf("\t-o offset\t\t\toffset of TRX data in file (default: 0)\n"); + printf("\n"); + printf("Creating new TRX file:\n"); + printf("\totrx create <file> [options] [partitions]\n"); + printf("\t-f file\t\t\t\t[partition] start new partition with content copied from file\n"); + printf("\t-b offset\t\t\t[partition] append zeros to partition till reaching absolute offset\n"); + printf("\n"); + printf("Extracting from TRX file:\n"); + printf("\totrx extract <file> [options]\textract partitions from TRX file\n"); + printf("\t-o offset\t\t\toffset of TRX data in file (default: 0)\n"); + printf("\t-1 file\t\t\t\tfile to extract 1st partition to (optional)\n"); + printf("\t-2 file\t\t\t\tfile to extract 2nd partition to (optional)\n"); + printf("\t-3 file\t\t\t\tfile to extract 3rd partition to (optional)\n"); +} + +int main(int argc, char **argv) { + if (argc > 1) { + if (!strcmp(argv[1], "check")) + return otrx_check(argc, argv); + else if (!strcmp(argv[1], "create")) + return otrx_create(argc, argv); + else if (!strcmp(argv[1], "extract")) + return otrx_extract(argc, argv); + } + + usage(); + return 0; +} diff --git a/package/utils/px5g-standalone/Makefile b/package/utils/px5g-standalone/Makefile new file mode 100644 index 0000000..bd02676 --- /dev/null +++ b/package/utils/px5g-standalone/Makefile @@ -0,0 +1,41 @@ +# +# Copyright (C) 2010-2014 Jo-Philipp Wich <xm@subsignal.org> +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=px5g-standalone +PKG_RELEASE:=2 + +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) +PKG_CHECK_FORMAT_SECURITY:=0 + +include $(INCLUDE_DIR)/package.mk + +define Package/px5g-standalone + SECTION:=utils + CATEGORY:=Utilities + TITLE:=Standalone X.509 certificate generator (standalone version) + MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org> +endef + +define Package/px5g-standalone/description + Px5g is a tiny standalone X.509 certificate generator. + It suitable to create key files and certificates in DER + and PEM format for use with stunnel, uhttpd and others. +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Package/px5g-standalone/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/px5g $(1)/usr/sbin/px5g +endef + +$(eval $(call BuildPackage,px5g-standalone)) diff --git a/package/utils/px5g-standalone/src/Makefile b/package/utils/px5g-standalone/src/Makefile new file mode 100644 index 0000000..2bd9573 --- /dev/null +++ b/package/utils/px5g-standalone/src/Makefile @@ -0,0 +1,14 @@ +CFLAGS?=-O2 +CFLAGS+= +SFLAGS:=--std=gnu99 +WFLAGS:=-Wall -Werror -pedantic +LDFLAGS?= +BINARY:=px5g + +all: $(BINARY) + +$(BINARY): *.c library/*.c + $(CC) -I. $(CFLAGS) $(SFLAGS) $(WFLAGS) $(LDFLAGS) -o $@ $+ + +clean: + rm -f $(BINARY) diff --git a/package/utils/px5g-standalone/src/library/base64.c b/package/utils/px5g-standalone/src/library/base64.c new file mode 100644 index 0000000..b7cc5b8 --- /dev/null +++ b/package/utils/px5g-standalone/src/library/base64.c @@ -0,0 +1,264 @@ +/* + * RFC 1521 base64 encoding/decoding + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 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 + * OWNER 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 "polarssl/config.h" + +#if defined(POLARSSL_BASE64_C) + +#include "polarssl/base64.h" + +static const unsigned char base64_enc_map[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +static const unsigned char base64_dec_map[128] = +{ + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, + 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 127, 127, 127, 127, 127 +}; + +/* + * Encode a buffer into base64 format + */ +int base64_encode( unsigned char *dst, int *dlen, + unsigned char *src, int slen ) +{ + int i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + return( 0 ); + + n = (slen << 3) / 6; + + switch( (slen << 3) - (n * 6) ) + { + case 2: n += 3; break; + case 4: n += 2; break; + default: break; + } + + if( *dlen < n + 1 ) + { + *dlen = n + 1; + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = (slen / 3) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; + *p++ = base64_enc_map[C3 & 0x3F]; + } + + if( i < slen ) + { + C1 = *src++; + C2 = ((i + 1) < slen) ? *src++ : 0; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + + if( (i + 1) < slen ) + *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; + else *p++ = '='; + + *p++ = '='; + } + + *dlen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int base64_decode( unsigned char *dst, int *dlen, + unsigned char *src, int slen ) +{ + int i, j, n; + unsigned long x; + unsigned char *p; + + for( i = j = n = 0; i < slen; i++ ) + { + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + if( src[i] == '=' && ++j > 2 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + if( base64_dec_map[src[i]] < 64 && j != 0 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + n++; + } + + if( n == 0 ) + return( 0 ); + + n = ((n * 6) + 7) >> 3; + + if( *dlen < n ) + { + *dlen = n; + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) + { + if( *src == '\r' || *src == '\n' ) + continue; + + j -= ( base64_dec_map[*src] == 64 ); + x = (x << 6) | ( base64_dec_map[*src] & 0x3F ); + + if( ++n == 4 ) + { + n = 0; + if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); + if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); + if( j > 2 ) *p++ = (unsigned char)( x ); + } + } + + *dlen = p - dst; + + return( 0 ); +} + +#if defined(POLARSSL_SELF_TEST) + +#include <string.h> +#include <stdio.h> + +static const unsigned char base64_test_dec[64] = +{ + 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, + 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, + 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, + 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, + 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, + 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, + 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, + 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 +}; + +static const unsigned char base64_test_enc[] = + "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" + "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; + +/* + * Checkup routine + */ +int base64_self_test( int verbose ) +{ + int len; + unsigned char *src, buffer[128]; + + if( verbose != 0 ) + printf( " Base64 encoding test: " ); + + len = sizeof( buffer ); + src = (unsigned char *) base64_test_dec; + + if( base64_encode( buffer, &len, src, 64 ) != 0 || + memcmp( base64_test_enc, buffer, 88 ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n Base64 decoding test: " ); + + len = sizeof( buffer ); + src = (unsigned char *) base64_test_enc; + + if( base64_decode( buffer, &len, src, 88 ) != 0 || + memcmp( base64_test_dec, buffer, 64 ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n\n" ); + + return( 0 ); +} + +#endif + +#endif diff --git a/package/utils/px5g-standalone/src/library/bignum.c b/package/utils/px5g-standalone/src/library/bignum.c new file mode 100644 index 0000000..8b7c12f --- /dev/null +++ b/package/utils/px5g-standalone/src/library/bignum.c @@ -0,0 +1,2010 @@ +/* + * Multi-precision integer library + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 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 + * OWNER 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. + */ +/* + * This MPI implementation is based on: + * + * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf + * http://www.stillhq.com/extracted/gnupg-api/mpi/ + * http://math.libtomcrypt.com/files/tommath.pdf + */ + +#include "polarssl/config.h" + +#if defined(POLARSSL_BIGNUM_C) + +#include "polarssl/bignum.h" +#include "polarssl/bn_mul.h" + +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> + +#define ciL ((int) sizeof(t_int)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +/* + * Convert between bits/chars and number of limbs + */ +#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL) +#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL) + +/* + * Initialize one or more mpi + */ +void mpi_init( mpi *X, ... ) +{ + va_list args; + + va_start( args, X ); + + while( X != NULL ) + { + X->s = 1; + X->n = 0; + X->p = NULL; + + X = va_arg( args, mpi* ); + } + + va_end( args ); +} + +/* + * Unallocate one or more mpi + */ +void mpi_free( mpi *X, ... ) +{ + va_list args; + + va_start( args, X ); + + while( X != NULL ) + { + if( X->p != NULL ) + { + memset( X->p, 0, X->n * ciL ); + free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; + + X = va_arg( args, mpi* ); + } + + va_end( args ); +} + +/* + * Enlarge to the specified number of limbs + */ +int mpi_grow( mpi *X, int nblimbs ) +{ + t_int *p; + + if( X->n < nblimbs ) + { + if( ( p = (t_int *) malloc( nblimbs * ciL ) ) == NULL ) + return( 1 ); + + memset( p, 0, nblimbs * ciL ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + memset( X->p, 0, X->n * ciL ); + free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mpi_copy( mpi *X, mpi *Y ) +{ + int ret, i; + + if( X == Y ) + return( 0 ); + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + MPI_CHK( mpi_grow( X, i ) ); + + memset( X->p, 0, X->n * ciL ); + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mpi_swap( mpi *X, mpi *Y ) +{ + mpi T; + + memcpy( &T, X, sizeof( mpi ) ); + memcpy( X, Y, sizeof( mpi ) ); + memcpy( Y, &T, sizeof( mpi ) ); +} + +/* + * Set value from integer + */ +int mpi_lset( mpi *X, int z ) +{ + int ret; + + MPI_CHK( mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Return the number of least significant bits + */ +int mpi_lsb( mpi *X ) +{ + int i, j, count = 0; + + for( i = 0; i < X->n; i++ ) + for( j = 0; j < (int) biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Return the number of most significant bits + */ +int mpi_msb( mpi *X ) +{ + int i, j; + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + for( j = biL - 1; j >= 0; j-- ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + break; + + return( ( i * biL ) + j + 1 ); +} + +/* + * Return the total size in bytes + */ +int mpi_size( mpi *X ) +{ + return( ( mpi_msb( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( t_int *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (t_int) radix ) + return( POLARSSL_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mpi_read_string( mpi *X, int radix, char *s ) +{ + int ret, i, j, n; + t_int d; + mpi T; + + if( radix < 2 || radix > 16 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + mpi_init( &T, NULL ); + + if( radix == 16 ) + { + n = BITS_TO_LIMBS( strlen( s ) << 2 ); + + MPI_CHK( mpi_grow( X, n ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i = strlen( s ) - 1, j = 0; i >= 0; i--, j++ ) + { + if( i == 0 && s[i] == '-' ) + { + X->s = -1; + break; + } + + MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 ); + } + } + else + { + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i = 0; i < (int) strlen( s ); i++ ) + { + if( i == 0 && s[i] == '-' ) + { + X->s = -1; + continue; + } + + MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MPI_CHK( mpi_mul_int( &T, X, radix ) ); + MPI_CHK( mpi_add_int( X, &T, d ) ); + } + } + +cleanup: + + mpi_free( &T, NULL ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first + */ +static int mpi_write_hlp( mpi *X, int radix, char **p ) +{ + int ret; + t_int r; + + if( radix < 2 || radix > 16 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + MPI_CHK( mpi_mod_int( &r, X, radix ) ); + MPI_CHK( mpi_div_int( X, NULL, X, radix ) ); + + if( mpi_cmp_int( X, 0 ) != 0 ) + MPI_CHK( mpi_write_hlp( X, radix, p ) ); + + if( r < 10 ) + *(*p)++ = (char)( r + 0x30 ); + else + *(*p)++ = (char)( r + 0x37 ); + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mpi_write_string( mpi *X, int radix, char *s, int *slen ) +{ + int ret = 0, n; + char *p; + mpi T; + + if( radix < 2 || radix > 16 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + n = mpi_msb( X ); + if( radix >= 4 ) n >>= 1; + if( radix >= 16 ) n >>= 1; + n += 3; + + if( *slen < n ) + { + *slen = n; + return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = s; + mpi_init( &T, NULL ); + + if( X->s == -1 ) + *p++ = '-'; + + if( radix == 16 ) + { + int c, i, j, k; + + for( i = X->n - 1, k = 0; i >= 0; i-- ) + { + for( j = ciL - 1; j >= 0; j-- ) + { + c = ( X->p[i] >> (j << 3) ) & 0xFF; + + if( c == 0 && k == 0 && (i + j) != 0 ) + continue; + + p += sprintf( p, "%02X", c ); + k = 1; + } + } + } + else + { + MPI_CHK( mpi_copy( &T, X ) ); + MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); + } + + *p++ = '\0'; + *slen = p - s; + +cleanup: + + mpi_free( &T, NULL ); + + return( ret ); +} + +/* + * Read X from an opened file + */ +int mpi_read_file( mpi *X, int radix, FILE *fin ) +{ + t_int d; + int slen; + char *p; + char s[1024]; + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( POLARSSL_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while( --p >= s ) + if( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mpi_write_file( char *p, mpi *X, int radix, FILE *fout ) +{ + int n, ret; + size_t slen; + size_t plen; + char s[1024]; + + n = sizeof( s ); + memset( s, 0, n ); + n -= 2; + + MPI_CHK( mpi_write_string( X, radix, s, (int *) &n ) ); + + if( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if( fout != NULL ) + { + if( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( POLARSSL_ERR_MPI_FILE_IO_ERROR ); + } + else + printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} + +/* + * Import X from unsigned binary data, big endian + */ +int mpi_read_binary( mpi *X, unsigned char *buf, int buflen ) +{ + int ret, i, j, n; + + for( n = 0; n < buflen; n++ ) + if( buf[n] != 0 ) + break; + + MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i = buflen - 1, j = 0; i >= n; i--, j++ ) + X->p[j / ciL] |= ((t_int) buf[i]) << ((j % ciL) << 3); + +cleanup: + + return( ret ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mpi_write_binary( mpi *X, unsigned char *buf, int buflen ) +{ + int i, j, n; + + n = mpi_size( X ); + + if( buflen < n ) + return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); + + memset( buf, 0, buflen ); + + for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) + buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mpi_shift_l( mpi *X, int count ) +{ + int ret, i, v0, t1; + t_int r0 = 0, r1; + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mpi_msb( X ) + count; + + if( X->n * (int) biL < i ) + MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = X->n - 1; i >= v0; i-- ) + X->p[i] = X->p[i - v0]; + + for( ; i >= 0; i-- ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if( t1 > 0 ) + { + for( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mpi_shift_r( mpi *X, int count ) +{ + int i, v0, v1; + t_int r0 = 0, r1; + + v0 = count / biL; + v1 = count & (biL - 1); + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if( v1 > 0 ) + { + for( i = X->n - 1; i >= 0; i-- ) + { + r1 = X->p[i] << (biL - v1); + X->p[i] >>= v1; + X->p[i] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mpi_cmp_abs( mpi *X, mpi *Y ) +{ + int i, j; + + for( i = X->n - 1; i >= 0; i-- ) + if( X->p[i] != 0 ) + break; + + for( j = Y->n - 1; j >= 0; j-- ) + if( Y->p[j] != 0 ) + break; + + if( i < 0 && j < 0 ) + return( 0 ); + + if( i > j ) return( 1 ); + if( j > i ) return( -1 ); + + for( ; i >= 0; i-- ) + { + if( X->p[i] > Y->p[i] ) return( 1 ); + if( X->p[i] < Y->p[i] ) return( -1 ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mpi_cmp_mpi( mpi *X, mpi *Y ) +{ + int i, j; + + for( i = X->n - 1; i >= 0; i-- ) + if( X->p[i] != 0 ) + break; + + for( j = Y->n - 1; j >= 0; j-- ) + if( Y->p[j] != 0 ) + break; + + if( i < 0 && j < 0 ) + return( 0 ); + + if( i > j ) return( X->s ); + if( j > i ) return( -X->s ); + + if( X->s > 0 && Y->s < 0 ) return( 1 ); + if( Y->s > 0 && X->s < 0 ) return( -1 ); + + for( ; i >= 0; i-- ) + { + if( X->p[i] > Y->p[i] ) return( X->s ); + if( X->p[i] < Y->p[i] ) return( -X->s ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mpi_cmp_int( mpi *X, int z ) +{ + mpi Y; + t_int p[1]; + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mpi_add_abs( mpi *X, mpi *A, mpi *B ) +{ + int ret, i, j; + t_int *o, *p, c; + + if( X == B ) + { + mpi *T = A; A = X; B = T; + } + + if( X != A ) + MPI_CHK( mpi_copy( X, A ) ); + + for( j = B->n - 1; j >= 0; j-- ) + if( B->p[j] != 0 ) + break; + + MPI_CHK( mpi_grow( X, j + 1 ) ); + + o = B->p; p = X->p; c = 0; + + for( i = 0; i <= j; i++, o++, p++ ) + { + *p += c; c = ( *p < c ); + *p += *o; c += ( *p < *o ); + } + + while( c != 0 ) + { + if( i >= X->n ) + { + MPI_CHK( mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; + } + +cleanup: + + return( ret ); +} + +/* + * Helper for mpi substraction + */ +static void mpi_sub_hlp( int n, t_int *s, t_int *d ) +{ + int i; + t_int c, z; + + for( i = c = 0; i < n; i++, s++, d++ ) + { + z = ( *d < c ); *d -= c; + c = ( *d < *s ) + z; *d -= *s; + } + + while( c != 0 ) + { + z = ( *d < c ); *d -= c; + c = z; i++; d++; + } +} + +/* + * Unsigned substraction: X = |A| - |B| (HAC 14.9) + */ +int mpi_sub_abs( mpi *X, mpi *A, mpi *B ) +{ + mpi TB; + int ret, n; + + if( mpi_cmp_abs( A, B ) < 0 ) + return( POLARSSL_ERR_MPI_NEGATIVE_VALUE ); + + mpi_init( &TB, NULL ); + + if( X == B ) + { + MPI_CHK( mpi_copy( &TB, B ) ); + B = &TB; + } + + if( X != A ) + MPI_CHK( mpi_copy( X, A ) ); + + ret = 0; + + for( n = B->n - 1; n >= 0; n-- ) + if( B->p[n] != 0 ) + break; + + mpi_sub_hlp( n + 1, B->p, X->p ); + +cleanup: + + mpi_free( &TB, NULL ); + + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mpi_add_mpi( mpi *X, mpi *A, mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s < 0 ) + { + if( mpi_cmp_abs( A, B ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MPI_CHK( mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MPI_CHK( mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed substraction: X = A - B + */ +int mpi_sub_mpi( mpi *X, mpi *A, mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s > 0 ) + { + if( mpi_cmp_abs( A, B ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MPI_CHK( mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MPI_CHK( mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mpi_add_int( mpi *X, mpi *A, int b ) +{ + mpi _B; + t_int p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_add_mpi( X, A, &_B ) ); +} + +/* + * Signed substraction: X = A - b + */ +int mpi_sub_int( mpi *X, mpi *A, int b ) +{ + mpi _B; + t_int p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_sub_mpi( X, A, &_B ) ); +} + +/* + * Helper for mpi multiplication + */ +static void mpi_mul_hlp( int i, t_int *s, t_int *d, t_int b ) +{ + t_int c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif + + t++; + + do { + *d += c; c = ( *d < c ); d++; + } + while( c != 0 ); +} + +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mpi_mul_mpi( mpi *X, mpi *A, mpi *B ) +{ + int ret, i, j; + mpi TA, TB; + + mpi_init( &TA, &TB, NULL ); + + if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; } + + for( i = A->n - 1; i >= 0; i-- ) + if( A->p[i] != 0 ) + break; + + for( j = B->n - 1; j >= 0; j-- ) + if( B->p[j] != 0 ) + break; + + MPI_CHK( mpi_grow( X, i + j + 2 ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i++; j >= 0; j-- ) + mpi_mul_hlp( i, A->p, X->p + j, B->p[j] ); + + X->s = A->s * B->s; + +cleanup: + + mpi_free( &TB, &TA, NULL ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mpi_mul_int( mpi *X, mpi *A, t_int b ) +{ + mpi _B; + t_int p[1]; + + _B.s = 1; + _B.n = 1; + _B.p = p; + p[0] = b; + + return( mpi_mul_mpi( X, A, &_B ) ); +} + +/* + * Division by mpi: A = Q * B + R (HAC 14.20) + */ +int mpi_div_mpi( mpi *Q, mpi *R, mpi *A, mpi *B ) +{ + int ret, i, n, t, k; + mpi X, Y, Z, T1, T2; + + if( mpi_cmp_int( B, 0 ) == 0 ) + return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); + + mpi_init( &X, &Y, &Z, &T1, &T2, NULL ); + + if( mpi_cmp_abs( A, B ) < 0 ) + { + if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) ); + if( R != NULL ) MPI_CHK( mpi_copy( R, A ) ); + return( 0 ); + } + + MPI_CHK( mpi_copy( &X, A ) ); + MPI_CHK( mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MPI_CHK( mpi_grow( &Z, A->n + 2 ) ); + MPI_CHK( mpi_lset( &Z, 0 ) ); + MPI_CHK( mpi_grow( &T1, 2 ) ); + MPI_CHK( mpi_grow( &T2, 3 ) ); + + k = mpi_msb( &Y ) % biL; + if( k < (int) biL - 1 ) + { + k = biL - 1 - k; + MPI_CHK( mpi_shift_l( &X, k ) ); + MPI_CHK( mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + mpi_shift_l( &Y, biL * (n - t) ); + + while( mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + mpi_sub_mpi( &X, &X, &Y ); + } + mpi_shift_r( &Y, biL * (n - t) ); + + for( i = n; i > t ; i-- ) + { + if( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { +#if defined(POLARSSL_HAVE_LONGLONG) + t_dbl r; + + r = (t_dbl) X.p[i] << biL; + r |= (t_dbl) X.p[i - 1]; + r /= Y.p[t]; + if( r > ((t_dbl) 1 << biL) - 1) + r = ((t_dbl) 1 << biL) - 1; + + Z.p[i - t - 1] = (t_int) r; +#else + /* + * __udiv_qrnnd_c, from gmp/longlong.h + */ + t_int q0, q1, r0, r1; + t_int d0, d1, d, m; + + d = Y.p[t]; + d0 = ( d << biH ) >> biH; + d1 = ( d >> biH ); + + q1 = X.p[i] / d1; + r1 = X.p[i] - d1 * q1; + r1 <<= biH; + r1 |= ( X.p[i - 1] >> biH ); + + m = q1 * d0; + if( r1 < m ) + { + q1--, r1 += d; + while( r1 >= d && r1 < m ) + q1--, r1 += d; + } + r1 -= m; + + q0 = r1 / d1; + r0 = r1 - d1 * q0; + r0 <<= biH; + r0 |= ( X.p[i - 1] << biH ) >> biH; + + m = q0 * d0; + if( r0 < m ) + { + q0--, r0 += d; + while( r0 >= d && r0 < m ) + q0--, r0 += d; + } + r0 -= m; + + Z.p[i - t - 1] = ( q1 << biH ) | q0; +#endif + } + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MPI_CHK( mpi_lset( &T1, 0 ) ); + T1.p[0] = (t < 1) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + + MPI_CHK( mpi_lset( &T2, 0 ) ); + T2.p[0] = (i < 2) ? 0 : X.p[i - 2]; + T2.p[1] = (i < 1) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + } + while( mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); + + if( mpi_cmp_int( &X, 0 ) < 0 ) + { + MPI_CHK( mpi_copy( &T1, &Y ) ); + MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); + MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if( Q != NULL ) + { + mpi_copy( Q, &Z ); + Q->s = A->s * B->s; + } + + if( R != NULL ) + { + mpi_shift_r( &X, k ); + mpi_copy( R, &X ); + + R->s = A->s; + if( mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mpi_free( &X, &Y, &Z, &T1, &T2, NULL ); + + return( ret ); +} + +/* + * Division by int: A = Q * b + R + * + * Returns 0 if successful + * 1 if memory allocation failed + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 + */ +int mpi_div_int( mpi *Q, mpi *R, mpi *A, int b ) +{ + mpi _B; + t_int p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_div_mpi( Q, R, A, &_B ) ); +} + +/* + * Modulo: R = A mod B + */ +int mpi_mod_mpi( mpi *R, mpi *A, mpi *B ) +{ + int ret; + + MPI_CHK( mpi_div_mpi( NULL, R, A, B ) ); + + while( mpi_cmp_int( R, 0 ) < 0 ) + MPI_CHK( mpi_add_mpi( R, R, B ) ); + + while( mpi_cmp_mpi( R, B ) >= 0 ) + MPI_CHK( mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mpi_mod_int( t_int *r, mpi *A, int b ) +{ + int i; + t_int x, y, z; + + if( b == 0 ) + return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); + + if( b < 0 ) + b = -b; + + /* + * handle trivial cases + */ + if( b == 1 ) + { + *r = 0; + return( 0 ); + } + + if( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); + } + + /* + * general case + */ + for( i = A->n - 1, y = 0; i >= 0; i-- ) + { + x = A->p[i]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } + + *r = y; + + return( 0 ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( t_int *mm, mpi *N ) +{ + t_int x, m0 = N->p[0]; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + x *= ( 2 - ( m0 * x ) ); + + if( biL >= 16 ) x *= ( 2 - ( m0 * x ) ); + if( biL >= 32 ) x *= ( 2 - ( m0 * x ) ); + if( biL >= 64 ) x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +/* + * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + */ +static void mpi_montmul( mpi *A, mpi *B, mpi *N, t_int mm, mpi *T ) +{ + int i, n, m; + t_int u0, u1, *d; + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + memcpy( A->p, d, (n + 1) * ciL ); + + if( mpi_cmp_abs( A, N ) >= 0 ) + mpi_sub_hlp( n, N->p, A->p ); + else + /* prevent timing attacks */ + mpi_sub_hlp( n, A->p, T->p ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + */ +static void mpi_montred( mpi *A, mpi *N, t_int mm, mpi *T ) +{ + t_int z = 1; + mpi U; + + U.n = U.s = z; + U.p = &z; + + mpi_montmul( A, &U, N, mm, T ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mpi_exp_mod( mpi *X, mpi *A, mpi *E, mpi *N, mpi *_RR ) +{ + int ret, i, j, wsize, wbits; + int bufsize, nblimbs, nbits; + t_int ei, mm, state; + mpi RR, T, W[64]; + + if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mpi_init( &RR, &T, NULL ); + memset( W, 0, sizeof( W ) ); + + i = mpi_msb( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + + j = N->n + 1; + MPI_CHK( mpi_grow( X, j ) ); + MPI_CHK( mpi_grow( &W[1], j ) ); + MPI_CHK( mpi_grow( &T, j * 2 ) ); + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( _RR == NULL || _RR->p == NULL ) + { + MPI_CHK( mpi_lset( &RR, 1 ) ); + MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) ); + MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) ); + + if( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mpi ) ); + } + else + memcpy( &RR, _RR, sizeof( mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mpi_cmp_mpi( A, N ) >= 0 ) + mpi_mod_mpi( &W[1], A, N ); + else mpi_copy( &W[1], A ); + + mpi_montmul( &W[1], &RR, N, mm, &T ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MPI_CHK( mpi_copy( X, &RR ) ); + mpi_montred( X, N, mm, &T ); + + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = 1 << (wsize - 1); + + MPI_CHK( mpi_grow( &W[j], N->n + 1 ) ); + MPI_CHK( mpi_copy( &W[j], &W[1] ) ); + + for( i = 0; i < wsize - 1; i++ ) + mpi_montmul( &W[j], &W[j], N, mm, &T ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < (1 << wsize); i++ ) + { + MPI_CHK( mpi_grow( &W[i], N->n + 1 ) ); + MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) ); + + mpi_montmul( &W[i], &W[1], N, mm, &T ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs-- == 0 ) + break; + + bufsize = sizeof( t_int ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + mpi_montmul( X, X, N, mm, &T ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= (ei << (wsize - nbits)); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + mpi_montmul( X, X, N, mm, &T ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + mpi_montmul( X, &W[wbits], N, mm, &T ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + mpi_montmul( X, X, N, mm, &T ); + + wbits <<= 1; + + if( (wbits & (1 << wsize)) != 0 ) + mpi_montmul( X, &W[1], N, mm, &T ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + mpi_montred( X, N, mm, &T ); + +cleanup: + + for( i = (1 << (wsize - 1)); i < (1 << wsize); i++ ) + mpi_free( &W[i], NULL ); + + if( _RR != NULL ) + mpi_free( &W[1], &T, NULL ); + else mpi_free( &W[1], &T, &RR, NULL ); + + return( ret ); +} + +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mpi_gcd( mpi *G, mpi *A, mpi *B ) +{ + int ret, lz, lzt; + mpi TG, TA, TB; + + mpi_init( &TG, &TA, &TB, NULL ); + + MPI_CHK( mpi_copy( &TA, A ) ); + MPI_CHK( mpi_copy( &TB, B ) ); + + lz = mpi_lsb( &TA ); + lzt = mpi_lsb( &TB ); + + if ( lzt < lz ) + lz = lzt; + + MPI_CHK( mpi_shift_r( &TA, lz ) ); + MPI_CHK( mpi_shift_r( &TB, lz ) ); + + TA.s = TB.s = 1; + + while( mpi_cmp_int( &TA, 0 ) != 0 ) + { + MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) ); + MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) ); + + if( mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) ); + MPI_CHK( mpi_shift_r( &TA, 1 ) ); + } + else + { + MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) ); + MPI_CHK( mpi_shift_r( &TB, 1 ) ); + } + } + + MPI_CHK( mpi_shift_l( &TB, lz ) ); + MPI_CHK( mpi_copy( G, &TB ) ); + +cleanup: + + mpi_free( &TB, &TA, &TG, NULL ); + + return( ret ); +} + +#if defined(POLARSSL_GENPRIME) + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mpi_inv_mod( mpi *X, mpi *A, mpi *N ) +{ + int ret; + mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + + if( mpi_cmp_int( N, 0 ) <= 0 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + mpi_init( &TA, &TU, &U1, &U2, &G, + &TB, &TV, &V1, &V2, NULL ); + + MPI_CHK( mpi_gcd( &G, A, N ) ); + + if( mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MPI_CHK( mpi_mod_mpi( &TA, A, N ) ); + MPI_CHK( mpi_copy( &TU, &TA ) ); + MPI_CHK( mpi_copy( &TB, N ) ); + MPI_CHK( mpi_copy( &TV, N ) ); + + MPI_CHK( mpi_lset( &U1, 1 ) ); + MPI_CHK( mpi_lset( &U2, 0 ) ); + MPI_CHK( mpi_lset( &V1, 0 ) ); + MPI_CHK( mpi_lset( &V2, 1 ) ); + + do + { + while( ( TU.p[0] & 1 ) == 0 ) + { + MPI_CHK( mpi_shift_r( &TU, 1 ) ); + + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) ); + MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MPI_CHK( mpi_shift_r( &U1, 1 ) ); + MPI_CHK( mpi_shift_r( &U2, 1 ) ); + } + + while( ( TV.p[0] & 1 ) == 0 ) + { + MPI_CHK( mpi_shift_r( &TV, 1 ) ); + + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) ); + MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MPI_CHK( mpi_shift_r( &V1, 1 ) ); + MPI_CHK( mpi_shift_r( &V2, 1 ) ); + } + + if( mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) ); + MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) ); + MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) ); + MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) ); + MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mpi_cmp_int( &TU, 0 ) != 0 ); + + while( mpi_cmp_int( &V1, 0 ) < 0 ) + MPI_CHK( mpi_add_mpi( &V1, &V1, N ) ); + + while( mpi_cmp_mpi( &V1, N ) >= 0 ) + MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) ); + + MPI_CHK( mpi_copy( X, &V1 ) ); + +cleanup: + + mpi_free( &V2, &V1, &TV, &TB, &G, + &U2, &U1, &TU, &TA, NULL ); + + return( ret ); +} + +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; + +/* + * Miller-Rabin primality test (HAC 4.24) + */ +int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng ) +{ + int ret, i, j, n, s, xs; + mpi W, R, T, A, RR; + unsigned char *p; + + if( mpi_cmp_int( X, 0 ) == 0 ) + return( 0 ); + + mpi_init( &W, &R, &T, &A, &RR, NULL ); + + xs = X->s; X->s = 1; + + /* + * test trivial factors first + */ + if( ( X->p[0] & 1 ) == 0 ) + return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); + + for( i = 0; small_prime[i] > 0; i++ ) + { + t_int r; + + if( mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 0 ); + + MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) ); + + if( r == 0 ) + return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); + } + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + s = mpi_lsb( &W ); + MPI_CHK( mpi_sub_int( &W, X, 1 ) ); + MPI_CHK( mpi_copy( &R, &W ) ); + MPI_CHK( mpi_shift_r( &R, s ) ); + + i = mpi_msb( X ); + /* + * HAC, table 4.4 + */ + n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : + ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : + ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); + + for( i = 0; i < n; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + MPI_CHK( mpi_grow( &A, X->n ) ); + + p = (unsigned char *) A.p; + for( j = 0; j < A.n * ciL; j++ ) + *p++ = (unsigned char) f_rng( p_rng ); + + j = mpi_msb( &A ) - mpi_msb( &W ); + MPI_CHK( mpi_shift_r( &A, j + 1 ) ); + A.p[0] |= 3; + + /* + * A = A^R mod |X| + */ + MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if( mpi_cmp_mpi( &A, &W ) == 0 || + mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while( j < s && mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MPI_CHK( mpi_mul_mpi( &T, &A, &A ) ); + MPI_CHK( mpi_mod_mpi( &A, &T, X ) ); + + if( mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mpi_cmp_mpi( &A, &W ) != 0 || + mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + + X->s = xs; + + mpi_free( &RR, &A, &T, &R, &W, NULL ); + + return( ret ); +} + +/* + * Prime number generation + */ +int mpi_gen_prime( mpi *X, int nbits, int dh_flag, + int (*f_rng)(void *), void *p_rng ) +{ + int ret, k, n; + unsigned char *p; + mpi Y; + + if( nbits < 3 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + mpi_init( &Y, NULL ); + + n = BITS_TO_LIMBS( nbits ); + + MPI_CHK( mpi_grow( X, n ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + p = (unsigned char *) X->p; + for( k = 0; k < X->n * ciL; k++ ) + *p++ = (unsigned char) f_rng( p_rng ); + + k = mpi_msb( X ); + if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) ); + if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) ); + + X->p[0] |= 3; + + if( dh_flag == 0 ) + { + while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) + { + if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + MPI_CHK( mpi_add_int( X, X, 2 ) ); + } + } + else + { + MPI_CHK( mpi_sub_int( &Y, X, 1 ) ); + MPI_CHK( mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 ) + { + if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 ) + break; + + if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + } + + if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + MPI_CHK( mpi_add_int( &Y, X, 1 ) ); + MPI_CHK( mpi_add_int( X, X, 2 ) ); + MPI_CHK( mpi_shift_r( &Y, 1 ) ); + } + } + +cleanup: + + mpi_free( &Y, NULL ); + + return( ret ); +} + +#endif + +#if defined(POLARSSL_SELF_TEST) + +#define GCD_PAIR_COUNT 3 + +static const int gcd_pairs[GCD_PAIR_COUNT][3] = +{ + { 693, 609, 21 }, + { 1764, 868, 28 }, + { 768454923, 542167814, 1 } +}; + +/* + * Checkup routine + */ +int mpi_self_test( int verbose ) +{ + int ret, i; + mpi A, E, N, X, Y, U, V; + + mpi_init( &A, &E, &N, &X, &Y, &U, &V, NULL ); + + MPI_CHK( mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MPI_CHK( mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MPI_CHK( mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MPI_CHK( mpi_mul_mpi( &X, &A, &N ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if( verbose != 0 ) + printf( " MPI test #1 (mul_mpi): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + + MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); + + MPI_CHK( mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if( verbose != 0 ) + printf( " MPI test #2 (div_mpi): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 || + mpi_cmp_mpi( &Y, &V ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + + MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if( verbose != 0 ) + printf( " MPI test #3 (exp_mod): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + + MPI_CHK( mpi_inv_mod( &X, &A, &N ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if( verbose != 0 ) + printf( " MPI test #4 (inv_mod): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + + if( verbose != 0 ) + printf( " MPI test #5 (simple gcd): " ); + + for ( i = 0; i < GCD_PAIR_COUNT; i++) + { + MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) ); + MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) ); + + MPI_CHK( mpi_gcd( &A, &X, &Y ) ); + + if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if( verbose != 0 ) + printf( "failed at %d\n", i ); + + return( 1 ); + } + } + + if( verbose != 0 ) + printf( "passed\n" ); + +cleanup: + + if( ret != 0 && verbose != 0 ) + printf( "Unexpected error, return code = %08X\n", ret ); + + mpi_free( &V, &U, &Y, &X, &N, &E, &A, NULL ); + + if( verbose != 0 ) + printf( "\n" ); + + return( ret ); +} + +#endif + +#endif diff --git a/package/utils/px5g-standalone/src/library/rsa.c b/package/utils/px5g-standalone/src/library/rsa.c new file mode 100644 index 0000000..131b6c6 --- /dev/null +++ b/package/utils/px5g-standalone/src/library/rsa.c @@ -0,0 +1,750 @@ +/* + * The RSA public-key cryptosystem + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 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 + * OWNER 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. + */ +/* + * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman. + * + * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf + * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf + */ + +#include "polarssl/config.h" + +#if defined(POLARSSL_RSA_C) + +#include "polarssl/rsa.h" + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +/* + * Initialize an RSA context + */ +void rsa_init( rsa_context *ctx, + int padding, + int hash_id, + int (*f_rng)(void *), + void *p_rng ) +{ + memset( ctx, 0, sizeof( rsa_context ) ); + + ctx->padding = padding; + ctx->hash_id = hash_id; + + ctx->f_rng = f_rng; + ctx->p_rng = p_rng; +} + +#if defined(POLARSSL_GENPRIME) + +/* + * Generate an RSA keypair + */ +int rsa_gen_key( rsa_context *ctx, int nbits, int exponent ) +{ + int ret; + mpi P1, Q1, H, G; + + if( ctx->f_rng == NULL || nbits < 128 || exponent < 3 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + mpi_init( &P1, &Q1, &H, &G, NULL ); + + /* + * find primes P and Q with Q < P so that: + * GCD( E, (P-1)*(Q-1) ) == 1 + */ + MPI_CHK( mpi_lset( &ctx->E, exponent ) ); + + do + { + MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, + ctx->f_rng, ctx->p_rng ) ); + + MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0, + ctx->f_rng, ctx->p_rng ) ); + + if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) + mpi_swap( &ctx->P, &ctx->Q ); + + if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) + continue; + + MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + if( mpi_msb( &ctx->N ) != nbits ) + continue; + + MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); + MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); + MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); + } + while( mpi_cmp_int( &G, 1 ) != 0 ); + + /* + * D = E^-1 mod ((P-1)*(Q-1)) + * DP = D mod (P - 1) + * DQ = D mod (Q - 1) + * QP = Q^-1 mod P + */ + MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); + MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); + MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); + MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); + + ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3; + +cleanup: + + mpi_free( &G, &H, &Q1, &P1, NULL ); + + if( ret != 0 ) + { + rsa_free( ctx ); + return( POLARSSL_ERR_RSA_KEY_GEN_FAILED | ret ); + } + + return( 0 ); +} + +#endif + +/* + * Check a public RSA key + */ +int rsa_check_pubkey( rsa_context *ctx ) +{ + if( ( ctx->N.p[0] & 1 ) == 0 || + ( ctx->E.p[0] & 1 ) == 0 ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + if( mpi_msb( &ctx->N ) < 128 || + mpi_msb( &ctx->N ) > 4096 ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + if( mpi_msb( &ctx->E ) < 2 || + mpi_msb( &ctx->E ) > 64 ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + return( 0 ); +} + +/* + * Check a private RSA key + */ +int rsa_check_privkey( rsa_context *ctx ) +{ + int ret; + mpi PQ, DE, P1, Q1, H, I, G; + + if( ( ret = rsa_check_pubkey( ctx ) ) != 0 ) + return( ret ); + + mpi_init( &PQ, &DE, &P1, &Q1, &H, &I, &G, NULL ); + + MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); + MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); + MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); + MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); + MPI_CHK( mpi_mod_mpi( &I, &DE, &H ) ); + MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); + + if( mpi_cmp_mpi( &PQ, &ctx->N ) == 0 && + mpi_cmp_int( &I, 1 ) == 0 && + mpi_cmp_int( &G, 1 ) == 0 ) + { + mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, NULL ); + return( 0 ); + } + +cleanup: + + mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, NULL ); + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED | ret ); +} + +/* + * Do an RSA public key operation + */ +int rsa_public( rsa_context *ctx, + unsigned char *input, + unsigned char *output ) +{ + int ret, olen; + mpi T; + + mpi_init( &T, NULL ); + + MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); + + if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + mpi_free( &T, NULL ); + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + olen = ctx->len; + MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MPI_CHK( mpi_write_binary( &T, output, olen ) ); + +cleanup: + + mpi_free( &T, NULL ); + + if( ret != 0 ) + return( POLARSSL_ERR_RSA_PUBLIC_FAILED | ret ); + + return( 0 ); +} + +/* + * Do an RSA private key operation + */ +int rsa_private( rsa_context *ctx, + unsigned char *input, + unsigned char *output ) +{ + int ret, olen; + mpi T, T1, T2; + + mpi_init( &T, &T1, &T2, NULL ); + + MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); + + if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + mpi_free( &T, NULL ); + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + +#if 0 + MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); +#else + /* + * faster decryption using the CRT + * + * T1 = input ^ dP mod P + * T2 = input ^ dQ mod Q + */ + MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); + MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); + + /* + * T = (T1 - T2) * (Q^-1 mod P) mod P + */ + MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) ); + MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) ); + MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) ); + + /* + * output = T2 + T * Q + */ + MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) ); + MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) ); +#endif + + olen = ctx->len; + MPI_CHK( mpi_write_binary( &T, output, olen ) ); + +cleanup: + + mpi_free( &T, &T1, &T2, NULL ); + + if( ret != 0 ) + return( POLARSSL_ERR_RSA_PRIVATE_FAILED | ret ); + + return( 0 ); +} + +/* + * Add the message padding, then do an RSA operation + */ +int rsa_pkcs1_encrypt( rsa_context *ctx, + int mode, int ilen, + unsigned char *input, + unsigned char *output ) +{ + int nb_pad, olen; + unsigned char *p = output; + + olen = ctx->len; + + switch( ctx->padding ) + { + case RSA_PKCS_V15: + + if( ilen < 0 || olen < ilen + 11 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + *p++ = RSA_CRYPT; + + while( nb_pad-- > 0 ) + { + do { + *p = (unsigned char) rand(); + } while( *p == 0 ); + p++; + } + *p++ = 0; + memcpy( p, input, ilen ); + break; + + default: + + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, output, output ) + : rsa_private( ctx, output, output ) ); +} + +/* + * Do an RSA operation, then remove the message padding + */ +int rsa_pkcs1_decrypt( rsa_context *ctx, + int mode, int *olen, + unsigned char *input, + unsigned char *output, + int output_max_len) +{ + int ret, ilen; + unsigned char *p; + unsigned char buf[512]; + + ilen = ctx->len; + + if( ilen < 16 || ilen > (int) sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, input, buf ) + : rsa_private( ctx, input, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + switch( ctx->padding ) + { + case RSA_PKCS_V15: + + if( *p++ != 0 || *p++ != RSA_CRYPT ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + while( *p != 0 ) + { + if( p >= buf + ilen - 1 ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + p++; + } + p++; + break; + + default: + + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } + + if (ilen - (int)(p - buf) > output_max_len) + return( POLARSSL_ERR_RSA_OUTPUT_TO_LARGE ); + + *olen = ilen - (int)(p - buf); + memcpy( output, p, *olen ); + + return( 0 ); +} + +/* + * Do an RSA operation to sign the message digest + */ +int rsa_pkcs1_sign( rsa_context *ctx, + int mode, + int hash_id, + int hashlen, + unsigned char *hash, + unsigned char *sig ) +{ + int nb_pad, olen; + unsigned char *p = sig; + + olen = ctx->len; + + switch( ctx->padding ) + { + case RSA_PKCS_V15: + + switch( hash_id ) + { + case RSA_RAW: + nb_pad = olen - 3 - hashlen; + break; + + case RSA_MD2: + case RSA_MD4: + case RSA_MD5: + nb_pad = olen - 3 - 34; + break; + + case RSA_SHA1: + nb_pad = olen - 3 - 35; + break; + + default: + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + if( nb_pad < 8 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + *p++ = 0; + *p++ = RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + break; + + default: + + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } + + switch( hash_id ) + { + case RSA_RAW: + memcpy( p, hash, hashlen ); + break; + + case RSA_MD2: + memcpy( p, ASN1_HASH_MDX, 18 ); + memcpy( p + 18, hash, 16 ); + p[13] = 2; break; + + case RSA_MD4: + memcpy( p, ASN1_HASH_MDX, 18 ); + memcpy( p + 18, hash, 16 ); + p[13] = 4; break; + + case RSA_MD5: + memcpy( p, ASN1_HASH_MDX, 18 ); + memcpy( p + 18, hash, 16 ); + p[13] = 5; break; + + case RSA_SHA1: + memcpy( p, ASN1_HASH_SHA1, 15 ); + memcpy( p + 15, hash, 20 ); + break; + + default: + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, sig ) + : rsa_private( ctx, sig, sig ) ); +} + +/* + * Do an RSA operation and check the message digest + */ +int rsa_pkcs1_verify( rsa_context *ctx, + int mode, + int hash_id, + int hashlen, + unsigned char *hash, + unsigned char *sig ) +{ + int ret, len, siglen; + unsigned char *p, c; + unsigned char buf[512]; + + siglen = ctx->len; + + if( siglen < 16 || siglen > (int) sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, buf ) + : rsa_private( ctx, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + switch( ctx->padding ) + { + case RSA_PKCS_V15: + + if( *p++ != 0 || *p++ != RSA_SIGN ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + while( *p != 0 ) + { + if( p >= buf + siglen - 1 || *p != 0xFF ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + p++; + } + p++; + break; + + default: + + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } + + len = siglen - (int)( p - buf ); + + if( len == 34 ) + { + c = p[13]; + p[13] = 0; + + if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( ( c == 2 && hash_id == RSA_MD2 ) || + ( c == 4 && hash_id == RSA_MD4 ) || + ( c == 5 && hash_id == RSA_MD5 ) ) + { + if( memcmp( p + 18, hash, 16 ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + } + + if( len == 35 && hash_id == RSA_SHA1 ) + { + if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 && + memcmp( p + 15, hash, 20 ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + + if( len == hashlen && hash_id == RSA_RAW ) + { + if( memcmp( p, hash, hashlen ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + + return( POLARSSL_ERR_RSA_INVALID_PADDING ); +} + +/* + * Free the components of an RSA key + */ +void rsa_free( rsa_context *ctx ) +{ + mpi_free( &ctx->RQ, &ctx->RP, &ctx->RN, + &ctx->QP, &ctx->DQ, &ctx->DP, + &ctx->Q, &ctx->P, &ctx->D, + &ctx->E, &ctx->N, NULL ); +} + +#if defined(POLARSSL_SELF_TEST) + +#include "polarssl/sha1.h" + +/* + * Example RSA-1024 keypair, for test purposes + */ +#define KEY_LEN 128 + +#define RSA_N "9292758453063D803DD603D5E777D788" \ + "8ED1D5BF35786190FA2F23EBC0848AEA" \ + "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ + "7130B9CED7ACDF54CFC7555AC14EEBAB" \ + "93A89813FBF3C4F8066D2D800F7C38A8" \ + "1AE31942917403FF4946B0A83D3D3E05" \ + "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ + "5E94BB77B07507233A0BC7BAC8F90F79" + +#define RSA_E "10001" + +#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ + "66CA472BC44D253102F8B4A9D3BFA750" \ + "91386C0077937FE33FA3252D28855837" \ + "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ + "DF79C5CE07EE72C7F123142198164234" \ + "CABB724CF78B8173B9F880FC86322407" \ + "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ + "071513A1E85B5DFA031F21ECAE91A34D" + +#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ + "2C01CAD19EA484A87EA4377637E75500" \ + "FCB2005C5C7DD6EC4AC023CDA285D796" \ + "C3D9E75E1EFC42488BB4F1D13AC30A57" + +#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ + "E211C2B9E5DB1ED0BF61D0D9899620F4" \ + "910E4168387E3C30AA1E00C339A79508" \ + "8452DD96A9A5EA5D9DCA68DA636032AF" + +#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ + "3C94D22288ACD763FD8E5600ED4A702D" \ + "F84198A5F06C2E72236AE490C93F07F8" \ + "3CC559CD27BC2D1CA488811730BB5725" + +#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ + "D8AAEA56749EA28623272E4F7D0592AF" \ + "7C1F1313CAC9471B5C523BFE592F517B" \ + "407A1BD76C164B93DA2D32A383E58357" + +#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ + "F38D18D2B2F0E2DD275AA977E2BF4411" \ + "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ + "A74206CEC169D74BF5A8C50D6F48EA08" + +#define PT_LEN 24 +#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ + "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" + +/* + * Checkup routine + */ +int rsa_self_test( int verbose ) +{ + int len; + rsa_context rsa; + unsigned char sha1sum[20]; + unsigned char rsa_plaintext[PT_LEN]; + unsigned char rsa_decrypted[PT_LEN]; + unsigned char rsa_ciphertext[KEY_LEN]; + + memset( &rsa, 0, sizeof( rsa_context ) ); + + rsa.len = KEY_LEN; + mpi_read_string( &rsa.N , 16, RSA_N ); + mpi_read_string( &rsa.E , 16, RSA_E ); + mpi_read_string( &rsa.D , 16, RSA_D ); + mpi_read_string( &rsa.P , 16, RSA_P ); + mpi_read_string( &rsa.Q , 16, RSA_Q ); + mpi_read_string( &rsa.DP, 16, RSA_DP ); + mpi_read_string( &rsa.DQ, 16, RSA_DQ ); + mpi_read_string( &rsa.QP, 16, RSA_QP ); + + if( verbose != 0 ) + printf( " RSA key validation: " ); + + if( rsa_check_pubkey( &rsa ) != 0 || + rsa_check_privkey( &rsa ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n PKCS#1 encryption : " ); + + memcpy( rsa_plaintext, RSA_PT, PT_LEN ); + + if( rsa_pkcs1_encrypt( &rsa, RSA_PUBLIC, PT_LEN, + rsa_plaintext, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n PKCS#1 decryption : " ); + + if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len, + rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n PKCS#1 data sign : " ); + + sha1( rsa_plaintext, PT_LEN, sha1sum ); + + if( rsa_pkcs1_sign( &rsa, RSA_PRIVATE, RSA_SHA1, 20, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n PKCS#1 sig. verify: " ); + + if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, RSA_SHA1, 20, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n\n" ); + + rsa_free( &rsa ); + + return( 0 ); +} + +#endif + +#endif diff --git a/package/utils/px5g-standalone/src/library/sha1.c b/package/utils/px5g-standalone/src/library/sha1.c new file mode 100644 index 0000000..54a4416 --- /dev/null +++ b/package/utils/px5g-standalone/src/library/sha1.c @@ -0,0 +1,622 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 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 + * OWNER 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. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include "polarssl/config.h" + +#if defined(POLARSSL_SHA1_C) + +#include "polarssl/sha1.h" + +#include <string.h> +#include <stdio.h> + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_ULONG_BE +#define GET_ULONG_BE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ + | ( (unsigned long) (b)[(i) + 1] << 16 ) \ + | ( (unsigned long) (b)[(i) + 2] << 8 ) \ + | ( (unsigned long) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_ULONG_BE +#define PUT_ULONG_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * SHA-1 context setup + */ +void sha1_starts( sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +static void sha1_process( sha1_context *ctx, unsigned char data[64] ) +{ + unsigned long temp, W[16], A, B, C, D, E; + + GET_ULONG_BE( W[ 0], data, 0 ); + GET_ULONG_BE( W[ 1], data, 4 ); + GET_ULONG_BE( W[ 2], data, 8 ); + GET_ULONG_BE( W[ 3], data, 12 ); + GET_ULONG_BE( W[ 4], data, 16 ); + GET_ULONG_BE( W[ 5], data, 20 ); + GET_ULONG_BE( W[ 6], data, 24 ); + GET_ULONG_BE( W[ 7], data, 28 ); + GET_ULONG_BE( W[ 8], data, 32 ); + GET_ULONG_BE( W[ 9], data, 36 ); + GET_ULONG_BE( W[10], data, 40 ); + GET_ULONG_BE( W[11], data, 44 ); + GET_ULONG_BE( W[12], data, 48 ); + GET_ULONG_BE( W[13], data, 52 ); + GET_ULONG_BE( W[14], data, 56 ); + GET_ULONG_BE( W[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ + W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +/* + * SHA-1 process buffer + */ +void sha1_update( sha1_context *ctx, unsigned char *input, int ilen ) +{ + int fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, fill ); + sha1_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + sha1_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, ilen ); + } +} + +static const unsigned char sha1_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-1 final digest + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_BE( high, msglen, 0 ); + PUT_ULONG_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + sha1_update( ctx, (unsigned char *) sha1_padding, padn ); + sha1_update( ctx, msglen, 8 ); + + PUT_ULONG_BE( ctx->state[0], output, 0 ); + PUT_ULONG_BE( ctx->state[1], output, 4 ); + PUT_ULONG_BE( ctx->state[2], output, 8 ); + PUT_ULONG_BE( ctx->state[3], output, 12 ); + PUT_ULONG_BE( ctx->state[4], output, 16 ); +} + +/* + * output = SHA-1( input buffer ) + */ +void sha1( unsigned char *input, int ilen, unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_starts( &ctx ); + sha1_update( &ctx, input, ilen ); + sha1_finish( &ctx, output ); + + memset( &ctx, 0, sizeof( sha1_context ) ); +} + +/* + * output = SHA-1( file contents ) + */ +int sha1_file( char *path, unsigned char output[20] ) +{ + FILE *f; + size_t n; + sha1_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( 1 ); + + sha1_starts( &ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + sha1_update( &ctx, buf, (int) n ); + + sha1_finish( &ctx, output ); + + memset( &ctx, 0, sizeof( sha1_context ) ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( 2 ); + } + + fclose( f ); + return( 0 ); +} + +/* + * SHA-1 HMAC context setup + */ +void sha1_hmac_starts( sha1_context *ctx, unsigned char *key, int keylen ) +{ + int i; + unsigned char sum[20]; + + if( keylen > 64 ) + { + sha1( key, keylen, sum ); + keylen = 20; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + sha1_starts( ctx ); + sha1_update( ctx, ctx->ipad, 64 ); + + memset( sum, 0, sizeof( sum ) ); +} + +/* + * SHA-1 HMAC process buffer + */ +void sha1_hmac_update( sha1_context *ctx, unsigned char *input, int ilen ) +{ + sha1_update( ctx, input, ilen ); +} + +/* + * SHA-1 HMAC final digest + */ +void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ) +{ + unsigned char tmpbuf[20]; + + sha1_finish( ctx, tmpbuf ); + sha1_starts( ctx ); + sha1_update( ctx, ctx->opad, 64 ); + sha1_update( ctx, tmpbuf, 20 ); + sha1_finish( ctx, output ); + + memset( tmpbuf, 0, sizeof( tmpbuf ) ); +} + +/* + * output = HMAC-SHA-1( hmac key, input buffer ) + */ +void sha1_hmac( unsigned char *key, int keylen, + unsigned char *input, int ilen, + unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_hmac_starts( &ctx, key, keylen ); + sha1_hmac_update( &ctx, input, ilen ); + sha1_hmac_finish( &ctx, output ); + + memset( &ctx, 0, sizeof( sha1_context ) ); +} + +#if defined(POLARSSL_SELF_TEST) +/* + * FIPS-180-1 test vectors + */ +static unsigned char sha1_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const int sha1_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha1_test_sum[3][20] = +{ + { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, + { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } +}; + +/* + * RFC 2202 test vectors + */ +static unsigned char sha1_hmac_test_key[7][26] = +{ + { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" + "\x0B\x0B\x0B\x0B" }, + { "Jefe" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA" }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, + { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" + "\x0C\x0C\x0C\x0C" }, + { "" }, /* 0xAA 80 times */ + { "" } +}; + +static const int sha1_hmac_test_keylen[7] = +{ + 20, 4, 20, 25, 20, 80, 80 +}; + +static unsigned char sha1_hmac_test_buf[7][74] = +{ + { "Hi There" }, + { "what do ya want for nothing?" }, + { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, + { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, + { "Test With Truncation" }, + { "Test Using Larger Than Block-Size Key - Hash Key First" }, + { "Test Using Larger Than Block-Size Key and Larger" + " Than One Block-Size Data" } +}; + +static const int sha1_hmac_test_buflen[7] = +{ + 8, 28, 50, 50, 20, 54, 73 +}; + +static const unsigned char sha1_hmac_test_sum[7][20] = +{ + { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B, + 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 }, + { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74, + 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 }, + { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3, + 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 }, + { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84, + 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA }, + { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2, + 0x7B, 0xE1 }, + { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70, + 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 }, + { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B, + 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 } +}; + +/* + * Checkup routine + */ +int sha1_self_test( int verbose ) +{ + int i, j, buflen; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + sha1_context ctx; + + /* + * SHA-1 + */ + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + printf( " SHA-1 test #%d: ", i + 1 ); + + sha1_starts( &ctx ); + + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + sha1_update( &ctx, buf, buflen ); + } + else + sha1_update( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + + sha1_finish( &ctx, sha1sum ); + + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + } + + if( verbose != 0 ) + printf( "\n" ); + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + printf( " HMAC-SHA-1 test #%d: ", i + 1 ); + + if( i == 5 || i == 6 ) + { + memset( buf, '\xAA', buflen = 80 ); + sha1_hmac_starts( &ctx, buf, buflen ); + } + else + sha1_hmac_starts( &ctx, sha1_hmac_test_key[i], + sha1_hmac_test_keylen[i] ); + + sha1_hmac_update( &ctx, sha1_hmac_test_buf[i], + sha1_hmac_test_buflen[i] ); + + sha1_hmac_finish( &ctx, sha1sum ); + + buflen = ( i == 4 ) ? 12 : 20; + + if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + } + + if( verbose != 0 ) + printf( "\n" ); + + return( 0 ); +} + +#endif + +#endif diff --git a/package/utils/px5g-standalone/src/library/timing.c b/package/utils/px5g-standalone/src/library/timing.c new file mode 100644 index 0000000..6b7ab74 --- /dev/null +++ b/package/utils/px5g-standalone/src/library/timing.c @@ -0,0 +1,265 @@ +/* + * Portable interface to the CPU cycle counter + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 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 + * OWNER 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 "polarssl/config.h" + +#if defined(POLARSSL_TIMING_C) + +#include "polarssl/timing.h" + +#if defined(WIN32) + +#include <windows.h> +#include <winbase.h> + +struct _hr_time +{ + LARGE_INTEGER start; +}; + +#else + +#include <unistd.h> +#include <sys/types.h> +#include <sys/time.h> +#include <signal.h> +#include <time.h> + +struct _hr_time +{ + struct timeval start; +}; + +#endif + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +unsigned long hardclock( void ) +{ + unsigned long tsc; + __asm rdtsc + __asm mov [tsc], eax + return( tsc ); +} + +#else +#if defined(__GNUC__) && defined(__i386__) + +unsigned long hardclock( void ) +{ + unsigned long tsc; + asm( "rdtsc" : "=a" (tsc) ); + return( tsc ); +} + +#else +#if defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__)) + +unsigned long hardclock( void ) +{ + unsigned long lo, hi; + asm( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo | (hi << 32) ); +} + +#else +#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) + +unsigned long hardclock( void ) +{ + unsigned long tbl, tbu0, tbu1; + + do + { + asm( "mftbu %0" : "=r" (tbu0) ); + asm( "mftb %0" : "=r" (tbl ) ); + asm( "mftbu %0" : "=r" (tbu1) ); + } + while( tbu0 != tbu1 ); + + return( tbl ); +} + +#else +#if defined(__GNUC__) && defined(__sparc__) + +unsigned long hardclock( void ) +{ + unsigned long tick; + asm( ".byte 0x83, 0x41, 0x00, 0x00" ); + asm( "mov %%g1, %0" : "=r" (tick) ); + return( tick ); +} + +#else +#if defined(__GNUC__) && defined(__alpha__) + +unsigned long hardclock( void ) +{ + unsigned long cc; + asm( "rpcc %0" : "=r" (cc) ); + return( cc & 0xFFFFFFFF ); +} + +#else +#if defined(__GNUC__) && defined(__ia64__) + +unsigned long hardclock( void ) +{ + unsigned long itc; + asm( "mov %0 = ar.itc" : "=r" (itc) ); + return( itc ); +} + +#else + +static int hardclock_init = 0; +static struct timeval tv_init; + +unsigned long hardclock( void ) +{ + struct timeval tv_cur; + + if( hardclock_init == 0 ) + { + gettimeofday( &tv_init, NULL ); + hardclock_init = 1; + } + + gettimeofday( &tv_cur, NULL ); + return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 + + ( tv_cur.tv_usec - tv_init.tv_usec ) ); +} + +#endif /* generic */ +#endif /* IA-64 */ +#endif /* Alpha */ +#endif /* SPARC8 */ +#endif /* PowerPC */ +#endif /* AMD64 */ +#endif /* i586+ */ + +int alarmed = 0; + +#if defined(WIN32) + +unsigned long get_timer( struct hr_time *val, int reset ) +{ + unsigned long delta; + LARGE_INTEGER offset, hfreq; + struct _hr_time *t = (struct _hr_time *) val; + + QueryPerformanceCounter( &offset ); + QueryPerformanceFrequency( &hfreq ); + + delta = (unsigned long)( ( 1000 * + ( offset.QuadPart - t->start.QuadPart ) ) / + hfreq.QuadPart ); + + if( reset ) + QueryPerformanceCounter( &t->start ); + + return( delta ); +} + +DWORD WINAPI TimerProc( LPVOID uElapse ) +{ + Sleep( (DWORD) uElapse ); + alarmed = 1; + return( TRUE ); +} + +void set_alarm( int seconds ) +{ + DWORD ThreadId; + + alarmed = 0; + CloseHandle( CreateThread( NULL, 0, TimerProc, + (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) ); +} + +void m_sleep( int milliseconds ) +{ + Sleep( milliseconds ); +} + +#else + +unsigned long get_timer( struct hr_time *val, int reset ) +{ + unsigned long delta; + struct timeval offset; + struct _hr_time *t = (struct _hr_time *) val; + + gettimeofday( &offset, NULL ); + + delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 + + ( offset.tv_usec - t->start.tv_usec ) / 1000; + + if( reset ) + { + t->start.tv_sec = offset.tv_sec; + t->start.tv_usec = offset.tv_usec; + } + + return( delta ); +} + +static void sighandler( int signum ) +{ + alarmed = 1; + signal( signum, sighandler ); +} + +void set_alarm( int seconds ) +{ + alarmed = 0; + signal( SIGALRM, sighandler ); + alarm( seconds ); +} + +void m_sleep( int milliseconds ) +{ + struct timeval tv; + + tv.tv_sec = milliseconds / 1000; + tv.tv_usec = milliseconds * 1000; + + select( 0, NULL, NULL, NULL, &tv ); +} + +#endif + +#endif diff --git a/package/utils/px5g-standalone/src/library/x509write.c b/package/utils/px5g-standalone/src/library/x509write.c new file mode 100644 index 0000000..1091568 --- /dev/null +++ b/package/utils/px5g-standalone/src/library/x509write.c @@ -0,0 +1,1162 @@ +/* + * X.509 certificate and private key writing + * + * Copyright (C) 2006-2007 Pascal Vizeli <pvizeli@yahoo.de> + * Modifications (C) 2009 Steven Barth <steven@midlink.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License, version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +/* + * The ITU-T X.509 standard defines a certificat format for PKI. + * + * http://www.ietf.org/rfc/rfc2459.txt + * http://www.ietf.org/rfc/rfc3279.txt + * + * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + * + * For CRS: + * http://www.faqs.org/rfcs/rfc2314.html + */ +#include "polarssl/config.h" +#include "polarssl/x509.h" +#include "polarssl/base64.h" +#include "polarssl/sha1.h" + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <time.h> + +#define and && +#define or || + +#if defined _MSC_VER && !defined snprintf +#define snprintf _snprintf +#endif + +static int x509write_realloc_node(x509_node *node, size_t larger); +static int x509write_file(x509_node *node, char *path, int format, const char* pem_prolog, const char* pem_epilog); + +/* + * evaluate how mani octet have this integer + */ +static int asn1_eval_octet(unsigned int digit) +{ + int i, byte; + + for (byte = 4, i = 24; i >= 0; i -= 8, --byte) + if (((digit >> i) & 0xFF) != 0) + return byte; + + return 0; +} + +/* + * write the asn.1 lenght form into p + */ +static int asn1_add_len(unsigned int size, x509_node *node) +{ + if (size > 127) { + + /* long size */ + int byte = asn1_eval_octet(size); + int i = 0; + + *(node->p) = (0x80 | byte) & 0xFF; + ++node->p; + + for (i = byte; i > 0; --i) { + + *(node->p) = (size >> ((i - 1) * 8)) & 0xFF; + ++node->p; + } + + } else { + + /* short size */ + *(node->p) = size & 0xFF; + if (size != 0) + ++node->p; + } + + return 0; +} + +/* + * write a ans.1 object into p + */ +static int asn1_add_obj(unsigned char *value, unsigned int size, int tag, + x509_node *node) +{ + int tl = 2; + + if (tag == ASN1_BIT_STRING) + ++tl; + + if (size > 127) + x509write_realloc_node(node, (size_t) size + tl + + asn1_eval_octet(size)); + else + x509write_realloc_node(node, (size_t) size + tl); + + if (node->data == NULL) + return 1; + + /* tag */ + *(node->p) = tag & 0xFF; + ++node->p; + + /* len */ + if (tag == ASN1_BIT_STRING) { + asn1_add_len((unsigned int) size + 1, node); + *(node->p) = 0x00; + ++node->p; + } else { + asn1_add_len((unsigned int) size, node); + } + + /* value */ + if (size > 0) { + + memcpy(node->p, value, (size_t) size); + if ((node->p += size -1) != node->end) + return POLARSSL_ERR_X509_POINT_ERROR; + } else { + /* make nothing -> NULL */ + } + + return 0; +} + +/* + * write a asn.1 conform integer object + */ +static int asn1_add_int(signed int value, x509_node *node) +{ + signed int i = 0, neg = 1; + unsigned int byte, u_val = 0, tmp_val = 0; + + /* if negate? */ + if (value < 0) { + neg = -1; + u_val = ~value; + } else { + u_val = value; + } + + byte = asn1_eval_octet(u_val); + /* 0 isn't NULL */ + if (byte == 0) + byte = 1; + + /* ASN.1 integer is signed! */ + if (byte < 4 and ((u_val >> ((byte -1) * 8)) & 0xFF) == 0x80) + byte += 1; + + if (x509write_realloc_node(node, (size_t) byte + 2) != 0) + return 1; + + /* tag */ + *(node->p) = ASN1_INTEGER; + ++node->p; + + /* len */ + asn1_add_len(byte, node); + + /* value */ + for (i = byte; i > 0; --i) { + + tmp_val = (u_val >> ((i - 1) * 8)) & 0xFF; + if (neg == 1) + *(node->p) = tmp_val; + else + *(node->p) = ~tmp_val; + + if (i > 1) + ++node->p; + } + + if (node->p != node->end) + return POLARSSL_ERR_X509_POINT_ERROR; + + return 0; +} + +/* + * write a asn.1 conform mpi object + */ +static int asn1_add_mpi(mpi *value, int tag, x509_node *node) +{ + size_t size = (mpi_msb(value) / 8) + 1; + unsigned char *buf; + int buf_len = (int) size, tl = 2; + + if (tag == ASN1_BIT_STRING) + ++tl; + + if (size > 127) + x509write_realloc_node(node, size + (size_t) tl + + asn1_eval_octet((unsigned int)size)); + else + x509write_realloc_node(node, size + (size_t) tl); + + if (node->data == NULL) + return 1; + + buf = (unsigned char*) malloc(size); + if (mpi_write_binary(value, buf, buf_len) != 0) + return POLARSSL_ERR_MPI_BUFFER_TOO_SMALL; + + /* tag */ + *(node->p) = tag & 0xFF; + ++node->p; + + /* len */ + if (tag == ASN1_BIT_STRING) { + asn1_add_len((unsigned int) size + 1, node); + *(node->p) = 0x00; + ++node->p; + } else { + asn1_add_len((unsigned int) size, node); + } + + /* value */ + memcpy(node->p, buf, size); + free(buf); + + if ((node->p += (int) size -1) != node->end) + return POLARSSL_ERR_X509_POINT_ERROR; + + return 0; +} + +/* + * write a node into asn.1 conform object + */ +static int asn1_append_tag(x509_node *node, int tag) +{ + int tl = 2; + + x509_node tmp; + x509write_init_node(&tmp); + + if (tag == ASN1_BIT_STRING) + ++tl; + + if (node->len > 127) + x509write_realloc_node(&tmp, node->len + (size_t) tl + + asn1_eval_octet((unsigned int)node->len)); + else + x509write_realloc_node(&tmp, node->len + (size_t) tl); + + if (tmp.data == NULL) { + x509write_free_node(&tmp); + return 1; + } + + /* tag */ + *(tmp.p) = tag & 0xFF; + ++tmp.p; + + /* len */ + if (tag == ASN1_BIT_STRING) { + asn1_add_len((unsigned int) node->len + 1, &tmp); + *(tmp.p) = 0x00; + ++tmp.p; + } else { + asn1_add_len((unsigned int) node->len, &tmp); + } + + /* value */ + memcpy(tmp.p, node->data, node->len); + + /* good? */ + if ((tmp.p += (int) node->len -1) != tmp.end) { + x509write_free_node(&tmp); + return POLARSSL_ERR_X509_POINT_ERROR; + } + + free(node->data); + node->data = tmp.data; + node->p = tmp.p; + node->end = tmp.end; + node->len = tmp.len; + + return 0; +} + +/* + * write nodes into a asn.1 object + */ +static int asn1_append_nodes(x509_node *node, int tag, int anz, ...) +{ + va_list ap; + size_t size = 0; + x509_node *tmp; + int count; + + va_start(ap, anz); + count = anz; + + while (count--) { + + tmp = va_arg(ap, x509_node*); + if (tmp->data != NULL) + size += tmp->len; + } + + if ( size > 127) { + if (x509write_realloc_node(node, size + (size_t) 2 + + asn1_eval_octet(size)) != 0) + return 1; + } else { + if (x509write_realloc_node(node, size + (size_t) 2) != 0) + return 1; + } + + /* tag */ + *(node->p) = tag & 0xFF; + ++node->p; + + /* len */ + asn1_add_len(size, node); + + /* value */ + va_start(ap, anz); + count = anz; + + while (count--) { + + tmp = va_arg(ap, x509_node*); + if (tmp->data != NULL) { + + memcpy(node->p, tmp->data, tmp->len); + if ((node->p += (int) tmp->len -1) != node->end) + ++node->p; + } + } + + va_end(ap); + return 0; +} + +/* + * write a ASN.1 conform object identifiere include a "tag" + */ +static int asn1_add_oid(x509_node *node, unsigned char *oid, size_t len, + int tag, int tag_val, unsigned char *value, size_t val_len) +{ + int ret; + x509_node tmp; + + x509write_init_node(&tmp); + + /* OBJECT IDENTIFIER */ + if ((ret = asn1_add_obj(oid, len, ASN1_OID, &tmp)) != 0) { + x509write_free_node(&tmp); + return ret; + } + + /* value */ + if ((ret = asn1_add_obj(value, val_len, tag_val, &tmp)) != 0) { + x509write_free_node(&tmp); + return ret; + } + + /* SET/SEQUENCE */ + if ((ret = asn1_append_nodes(node, tag, 1, &tmp)) != 0) { + x509write_free_node(&tmp); + return ret; + } + + x509write_free_node(&tmp); + return 0; +} + +/* + * utcTime UTCTime + */ +static int asn1_add_date_utc(unsigned char *time, x509_node *node) +{ + unsigned char date[13], *sp; + x509_time xtime; + int ret; + + sscanf((char*)time, "%d-%d-%d %d:%d:%d", &xtime.year, &xtime.mon, + &xtime.day, &xtime.hour, &xtime.min, &xtime.sec); + + /* convert to YY */ + if (xtime.year > 2000) + xtime.year -= 2000; + else + xtime.year -= 1900; + + snprintf((char*)date, 13, "%2d%2d%2d%2d%2d%2d", xtime.year, xtime.mon, xtime.day, + xtime.hour, xtime.min, xtime.sec); + + /* replace ' ' to '0' */ + for (sp = date; *sp != '\0'; ++sp) + if (*sp == '\x20') + *sp = '\x30'; + + date[12] = 'Z'; + + if ((ret = asn1_add_obj(date, 13, ASN1_UTC_TIME, node)) != 0) + return ret; + + return 0; +} + +/* + * serialize an rsa key into DER + */ + +int x509write_serialize_key(rsa_context *rsa, x509_node *node) +{ + int ret = 0; + x509write_init_node(node); + + /* vers, n, e, d, p, q, dp, dq, pq */ + if ((ret = asn1_add_int(rsa->ver, node)) != 0) + return ret; + if ((ret = asn1_add_mpi(&rsa->N, ASN1_INTEGER, node)) != 0) + return ret; + if ((ret = asn1_add_mpi(&rsa->E, ASN1_INTEGER, node)) != 0) + return ret; + if ((ret = asn1_add_mpi(&rsa->D, ASN1_INTEGER, node)) != 0) + return ret; + if ((ret = asn1_add_mpi(&rsa->P, ASN1_INTEGER, node)) != 0) + return ret; + if ((ret = asn1_add_mpi(&rsa->Q, ASN1_INTEGER, node)) != 0) + return ret; + if ((ret = asn1_add_mpi(&rsa->DP, ASN1_INTEGER, node)) != 0) + return ret; + if ((ret = asn1_add_mpi(&rsa->DQ, ASN1_INTEGER, node)) != 0) + return ret; + if ((ret = asn1_add_mpi(&rsa->QP, ASN1_INTEGER, node)) != 0) + return ret; + if ((ret = asn1_append_tag(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0) + return ret; + + return 0; +} + +/* + * write a der/pem encoded rsa private key into a file + */ +int x509write_keyfile(rsa_context *rsa, char *path, int out_flag) +{ + int ret = 0; + const char key_beg[] = "-----BEGIN RSA PRIVATE KEY-----\n", + key_end[] = "-----END RSA PRIVATE KEY-----\n"; + x509_node node; + + x509write_init_node(&node); + if ((ret = x509write_serialize_key(rsa,&node)) != 0) { + x509write_free_node(&node); + return ret; + } + + ret = x509write_file(&node,path,out_flag,key_beg,key_end); + x509write_free_node(&node); + + return ret; +} + + +/* + * reasize the memory for node + */ +static int x509write_realloc_node(x509_node *node, size_t larger) +{ + /* init len */ + if (node->data == NULL) { + node->len = 0; + node->data = malloc(larger); + if(node->data == NULL) + return 1; + } else { + /* realloc memory */ + if ((node->data = realloc(node->data, node->len + larger)) == NULL) + return 1; + } + + /* init pointer */ + node->p = &node->data[node->len]; + node->len += larger; + node->end = &node->data[node->len -1]; + + return 0; +} + +/* + * init node + */ +void x509write_init_node(x509_node *node) +{ + memset(node, 0, sizeof(x509_node)); +} + +/* + * clean memory + */ +void x509write_free_node(x509_node *node) +{ + if (node->data != NULL) + free(node->data); + node->p = NULL; + node->end = NULL; + node->len = 0; +} + +/* + * write a x509 certificate into file + */ +int x509write_crtfile(x509_raw *chain, unsigned char *path, int out_flag) +{ + const char cer_beg[] = "-----BEGIN CERTIFICATE-----\n", + cer_end[] = "-----END CERTIFICATE-----\n"; + + return x509write_file(&chain->raw, (char*)path, out_flag, cer_beg, cer_end); +} + +/* + * write a x509 certificate into file + */ +int x509write_csrfile(x509_raw *chain, unsigned char *path, int out_flag) +{ + const char cer_beg[] = "-----BEGIN CERTIFICATE REQUEST-----\n", + cer_end[] = "-----END CERTIFICATE REQUEST-----\n"; + + return x509write_file(&chain->raw, (char*)path, out_flag, cer_beg, cer_end); +} + +/* + * write an x509 file + */ +static int x509write_file(x509_node *node, char *path, int format, + const char* pem_prolog, const char* pem_epilog) +{ + FILE *ofstream = stdout; + int is_err = 1, buf_len, i, n; + unsigned char* base_buf; + + if (path) { + if ((ofstream = fopen(path, "wb")) == NULL) + return 1; + } + + switch (format) { + case X509_OUTPUT_DER: + if (fwrite(node->data, 1, node->len, ofstream) + != node->len) + is_err = -1; + break; + + case X509_OUTPUT_PEM: + if (fprintf(ofstream,pem_prolog)<0) { + is_err = -1; + break; + } + + buf_len = node->len << 1; + base_buf = (unsigned char*) malloc((size_t)buf_len); + memset(base_buf,0,buf_len); + if (base64_encode(base_buf, &buf_len, node->data, + (int) node->len) != 0) { + is_err = -1; + break; + } + + n=strlen((char*)base_buf); + for(i=0;i<n;i+=64) { + fprintf(ofstream,"%.64s\n",&base_buf[i]); + } + + if (fprintf(ofstream, pem_epilog)<0) { + is_err = -1; + break; + } + + free(base_buf); + } + + fclose(ofstream); + + if (is_err == -1) + return 1; + + return 0; +} + + +/* + * add the owner public key to x509 certificate + */ +int x509write_add_pubkey(x509_raw *chain, rsa_context *pubkey) +{ + x509_node n_tmp, n_tmp2, *node; + int ret; + + node = &chain->subpubkey; + + x509write_init_node(&n_tmp); + x509write_init_node(&n_tmp2); + + /* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ + if ((ret = asn1_add_mpi(&pubkey->N, ASN1_INTEGER, &n_tmp)) != 0) { + x509write_free_node(&n_tmp); + x509write_free_node(&n_tmp2); + return ret; + } + if ((ret = asn1_add_mpi(&pubkey->E, ASN1_INTEGER, &n_tmp)) != 0) { + x509write_free_node(&n_tmp); + x509write_free_node(&n_tmp2); + return ret; + } + if ((ret = asn1_append_tag(&n_tmp, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) + != 0) { + x509write_free_node(&n_tmp); + x509write_free_node(&n_tmp2); + return ret; + } + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + if ((ret = asn1_append_tag(&n_tmp, ASN1_BIT_STRING)) != 0) { + x509write_free_node(&n_tmp); + x509write_free_node(&n_tmp2); + return ret; + } + if ((ret = asn1_add_oid(&n_tmp2, (unsigned char*)OID_PKCS1_RSA, 9, + ASN1_CONSTRUCTED | ASN1_SEQUENCE, ASN1_NULL, + (unsigned char *)"", 0)) != 0) { + x509write_free_node(&n_tmp); + x509write_free_node(&n_tmp2); + return ret; + } + + if ((ret = asn1_append_nodes(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE, 2, + &n_tmp2, &n_tmp))) { + x509write_free_node(&n_tmp); + x509write_free_node(&n_tmp2); + return ret; + } + + x509write_free_node(&n_tmp); + x509write_free_node(&n_tmp2); + return 0; +} + +/* + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + */ +static int x509write_add_name(x509_node *node, unsigned char *oid, + unsigned int oid_len, unsigned char *value, int len, int value_tag) +{ + int ret; + x509_node n_tmp; + + x509write_init_node(&n_tmp); + + if ((ret = asn1_add_oid(&n_tmp, oid, oid_len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE, value_tag, + value, len))) { + x509write_free_node(&n_tmp); + return ret; + } + + if ((asn1_append_nodes(node, ASN1_CONSTRUCTED | ASN1_SET, 1, &n_tmp)) + != 0) { + x509write_free_node(&n_tmp); + return ret; + } + + x509write_free_node(&n_tmp); + return 0; +} + +/* + * Parse the name string and add to node + */ +static int x509write_parse_names(x509_node *node, unsigned char *names) +{ + unsigned char *sp, *begin = NULL; + unsigned char oid[3] = OID_X520, tag[4], *tag_sp = tag; + unsigned char *C = NULL, *CN = NULL, *O = NULL, *OU = NULL, + *ST = NULL, *L = NULL, *R = NULL; + int C_len = 0, CN_len = 0, O_len = 0, OU_len = 0, ST_len = 0, + L_len = 0, R_len = 0; + int ret = 0, is_tag = 1, is_begin = -1, len = 0; + + + for (sp = names; ; ++sp) { + + /* filter tag */ + if (is_tag == 1) { + + if (tag_sp == &tag[3]) + return POLARSSL_ERR_X509_VALUE_TO_LENGTH; + + /* is tag end? */ + if (*sp == '=') { + is_tag = -1; + *tag_sp = '\0'; + is_begin = 1; + /* set len 0 (reset) */ + len = 0; + } else { + /* tag hasn't ' '! */ + if (*sp != ' ') { + *tag_sp = *sp; + ++tag_sp; + } + } + /* filter value */ + } else { + + /* set pointer of value begin */ + if (is_begin == 1) { + begin = sp; + is_begin = -1; + } + + /* is value at end? */ + if (*sp == ';' or *sp == '\0') { + is_tag = 1; + + /* common name */ + if (tag[0] == 'C' and tag[1] == 'N') { + CN = begin; + CN_len = len; + + /* organization */ + } else if (tag[0] == 'O' and tag[1] == '\0') { + O = begin; + O_len = len; + + /* country */ + } else if (tag[0] == 'C' and tag[1] == '\0') { + C = begin; + C_len = len; + + /* organisation unit */ + } else if (tag[0] == 'O' and tag[1] == 'U') { + OU = begin; + OU_len = len; + + /* state */ + } else if (tag[0] == 'S' and tag[1] == 'T') { + ST = begin; + ST_len = len; + + /* locality */ + } else if (tag[0] == 'L' and tag[1] == '\0') { + L = begin; + L_len = len; + + /* email */ + } else if (tag[0] == 'R' and tag[1] == '\0') { + R = begin; + R_len = len; + } + + /* set tag poiner to begin */ + tag_sp = tag; + + /* is at end? */ + if (*sp == '\0' or *(sp +1) == '\0') + break; + } else { + ++len; + } + } + + /* make saver */ + if (*sp == '\0') + break; + } /* end for */ + + /* country */ + if (C != NULL) { + oid[2] = X520_COUNTRY; + if ((ret = x509write_add_name(node, oid, 3, C, C_len, + ASN1_PRINTABLE_STRING)) != 0) + return ret; + } + + /* state */ + if (ST != NULL) { + oid[2] = X520_STATE; + if ((ret = x509write_add_name(node, oid, 3, ST, ST_len, + ASN1_PRINTABLE_STRING)) != 0) + return ret; + } + + /* locality */ + if (L != NULL) { + oid[2] = X520_LOCALITY; + if ((ret = x509write_add_name(node, oid, 3, L, L_len, + ASN1_PRINTABLE_STRING)) != 0) + return ret; + } + + /* organization */ + if (O != NULL) { + oid[2] = X520_ORGANIZATION; + if ((ret = x509write_add_name(node, oid, 3, O, O_len, + ASN1_PRINTABLE_STRING)) != 0) + return ret; + } + + /* organisation unit */ + if (OU != NULL) { + oid[2] = X520_ORG_UNIT; + if ((ret = x509write_add_name(node, oid, 3, OU, OU_len, + ASN1_PRINTABLE_STRING)) != 0) + return ret; + } + + /* common name */ + if (CN != NULL) { + oid[2] = X520_COMMON_NAME; + if ((ret = x509write_add_name(node, oid, 3, CN, CN_len, + ASN1_PRINTABLE_STRING)) != 0) + return ret; + } + + /* email */ + if (R != NULL) { + if ((ret = x509write_add_name(node, (unsigned char*)OID_PKCS9_EMAIL, + 9, R, R_len, ASN1_IA5_STRING)) != 0) + return ret; + } + + if ((asn1_append_tag(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0) + return ret; + + return 0; +} + +/* + * Copy raw data from orginal ca to node + */ +static int x509write_copy_from_raw(x509_node *node, x509_buf *raw) +{ + if (x509write_realloc_node(node, raw->len) != 0) + return 1; + + memcpy(node->p, raw->p, (size_t)raw->len); + if ((node->p += raw->len -1) != node->end) + return POLARSSL_ERR_X509_POINT_ERROR; + + return 0; +} + +/* + * Add the issuer + */ + +int x509write_add_issuer(x509_raw *crt, unsigned char *issuer) +{ + return x509write_parse_names(&crt->issuer, issuer); +} + +/* + * Add the subject + */ +int x509write_add_subject(x509_raw *crt, unsigned char *subject) +{ + return x509write_parse_names(&crt->subject, subject); +} + +/* + * Copy issuer line from another cert to issuer + */ +int x509write_copy_issuer(x509_raw *crt, x509_cert *from_crt) +{ + return x509write_copy_from_raw(&crt->issuer, &from_crt->issuer_raw); +} + +/* + * Copy subject line from another cert + */ +int x509write_copy_subject(x509_raw *crt, x509_cert *from_crt) +{ + return x509write_copy_from_raw(&crt->subject, &from_crt->subject_raw); +} + +/* + * Copy subject line form antoher cert into issuer + */ +int x509write_copy_issuer_form_subject(x509_raw *crt, + x509_cert *from_crt) +{ + return x509write_copy_from_raw(&crt->issuer, &from_crt->subject_raw); +} + +/* + * Copy issuer line from another cert into subject + */ +int x509write_copy_subject_from_issuer(x509_raw *crt, + x509_cert * from_crt) +{ + return x509write_copy_from_raw(&crt->subject, &from_crt->issuer_raw); +} + +/* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + */ +/* TODO: No handle GeneralizedTime! */ +int x509write_add_validity(x509_raw *chain, unsigned char *befor, + unsigned char *after) +{ + int ret; + + x509_node *node = &chain->validity; + + /* notBefore */ + if ((ret = asn1_add_date_utc(befor, node)) != 0) + return ret; + + /* notAfter */ + if ((ret = asn1_add_date_utc(after, node)) != 0) + return ret; + + if ((ret = asn1_append_tag(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0) + return ret; + + return 0; +} + +/* + * make hash from tbs and sign that with private key + */ +static int x509write_make_sign(x509_raw *chain, rsa_context *privkey) +{ + int ret; + unsigned char hash[20], *sign; + size_t sign_len = (size_t) mpi_size(&privkey->N); + + /* make hash */ + sha1(chain->tbs.data, chain->tbs.len, hash); + + /* create sign */ + sign = (unsigned char *) malloc(sign_len); + if (sign == NULL) + return 1; + + if ((ret = rsa_pkcs1_sign(privkey, RSA_PRIVATE, RSA_SHA1, 20, hash, + sign)) != 0) + return ret; + + if ((ret = asn1_add_obj(sign, sign_len, ASN1_BIT_STRING, + &chain->sign)) != 0) + return ret; + + /* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ + return asn1_add_oid(&chain->signalg, (unsigned char*)OID_PKCS1_RSA_SHA, 9, + ASN1_CONSTRUCTED | ASN1_SEQUENCE, ASN1_NULL, + (unsigned char*)"", 0); +} + +/* + * Create a random serial + */ +static int get_random_serial(void) +{ + int random = 0; + FILE *fd; + + fd = fopen("/dev/urandom", "r"); + + if (fd) { + if (fread(&random, 1, sizeof(random), fd) != sizeof(random)) + random = 0; + + fclose(fd); + } + + return random; +} + +/* + * Create a self signed certificate + */ +int x509write_create_sign(x509_raw *chain, rsa_context *privkey) +{ + int ret, serial; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + if ((ret = asn1_add_int(2, &chain->version)) != 0) + return ret; + + if ((ret = asn1_append_tag(&chain->version, ASN1_CONTEXT_SPECIFIC | + ASN1_CONSTRUCTED)) != 0) + return ret; + + + /* + * CertificateSerialNumber ::= INTEGER + */ + serial = get_random_serial(); + + if (serial == 0) + return 1; + + if ((ret = asn1_add_int(serial, &chain->serial)) != 0) + return ret; + + /* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ + if ((ret = asn1_add_oid(&chain->tbs_signalg, + (unsigned char*)OID_PKCS1_RSA_SHA, 9, ASN1_CONSTRUCTED | + ASN1_SEQUENCE, ASN1_NULL, (unsigned char*)"", 0)) != 0) + return ret; + + /* + * Create the tbs + */ + if ((ret = asn1_append_nodes(&chain->tbs, ASN1_CONSTRUCTED | + ASN1_SEQUENCE, 7, &chain->version, &chain->serial, + &chain->tbs_signalg, &chain->issuer, &chain->validity, + &chain->subject, &chain->subpubkey)) != 0) + return ret; + + /* make signing */ + if ((ret = x509write_make_sign(chain, privkey)) != 0) + return ret; + + /* finishing */ + if ((ret = asn1_append_nodes(&chain->raw, ASN1_CONSTRUCTED | + ASN1_SEQUENCE, 3, &chain->tbs, &chain->signalg, + &chain->sign)) != 0) + return ret; + + return 0; +} + +int x509write_create_selfsign(x509_raw *chain, rsa_context *privkey) +{ + /* + * On self signed certificate are subject and issuer the same + */ + x509write_free_node(&chain->issuer); + chain->issuer = chain->subject; + return x509write_create_sign(chain, privkey); +} + +/* + * CertificationRequestInfo ::= SEQUENCE { + * version Version, + * subject Name, + * subjectPublicKeyInfo SubjectPublicKeyInfo, + * attributes [0] IMPLICIT Attributes } + * + * CertificationRequest ::= SEQUENCE { + * certificationRequestInfo CertificationRequestInfo, + * signatureAlgorithm SignatureAlgorithmIdentifier, + * signature Signature } + * + * It use chain.serail for attributes! + * + */ +int x509write_create_csr(x509_raw *chain, rsa_context *privkey) +{ + int ret; + + /* version ::= INTEGER */ + if ((ret = asn1_add_int(0, &chain->version)) != 0) + return ret; + + /* write attributes */ + if ((ret = asn1_add_obj((unsigned char*)"", 0, ASN1_CONTEXT_SPECIFIC | + ASN1_CONSTRUCTED, &chain->serial)) != 0) + return ret; + + /* create CertificationRequestInfo */ + if ((ret = asn1_append_nodes(&chain->tbs, ASN1_CONSTRUCTED | + ASN1_SEQUENCE, 4, &chain->version, &chain->subject, + &chain->subpubkey, &chain->serial)) != 0) + return ret; + + /* make signing */ + if ((ret = x509write_make_sign(chain, privkey)) != 0) + return ret; + + /* finish */ + if ((ret = asn1_append_nodes(&chain->raw, ASN1_CONSTRUCTED | ASN1_SEQUENCE, + 3, &chain->tbs, &chain->signalg, &chain->sign)) != 0) + return ret; + + return ret; +} + +/* + * Free memory + */ +void x509write_free_raw(x509_raw *chain) +{ + x509write_free_node(&chain->raw); + x509write_free_node(&chain->tbs); + x509write_free_node(&chain->version); + x509write_free_node(&chain->serial); + x509write_free_node(&chain->tbs_signalg); + x509write_free_node(&chain->issuer); + x509write_free_node(&chain->validity); + if (chain->subject.data != chain->issuer.data) + x509write_free_node(&chain->subject); + x509write_free_node(&chain->subpubkey); + x509write_free_node(&chain->signalg); + x509write_free_node(&chain->sign); +} + +void x509write_init_raw(x509_raw *chain) +{ + memset((void *) chain, 0, sizeof(x509_raw)); +} + diff --git a/package/utils/px5g-standalone/src/polarssl/base64.h b/package/utils/px5g-standalone/src/polarssl/base64.h new file mode 100644 index 0000000..c48267b --- /dev/null +++ b/package/utils/px5g-standalone/src/polarssl/base64.h @@ -0,0 +1,93 @@ +/** + * \file base64.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 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 + * OWNER 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. + */ +#ifndef POLARSSL_BASE64_H +#define POLARSSL_BASE64_H + +#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x0010 +#define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x0012 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the buffer + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL. + * *dlen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dlen = 0 to obtain the + * required buffer size in *dlen + */ +int base64_encode( unsigned char *dst, int *dlen, + unsigned char *src, int slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer + * \param dlen size of the buffer + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or + * POLARSSL_ERR_BASE64_INVALID_DATA if the input data is not + * correct. *dlen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dlen = 0 to obtain the + * required buffer size in *dlen + */ +int base64_decode( unsigned char *dst, int *dlen, + unsigned char *src, int slen ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int base64_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ diff --git a/package/utils/px5g-standalone/src/polarssl/bignum.h b/package/utils/px5g-standalone/src/polarssl/bignum.h new file mode 100644 index 0000000..c667303 --- /dev/null +++ b/package/utils/px5g-standalone/src/polarssl/bignum.h @@ -0,0 +1,437 @@ +/** + * \file bignum.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 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 + * OWNER 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. + */ +#ifndef POLARSSL_BIGNUM_H +#define POLARSSL_BIGNUM_H + +#include <stdio.h> + +#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002 +#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004 +#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006 +#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008 +#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A +#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C +#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E + +#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup + +/* + * Define the base integer type, architecture-wise + */ +#if defined(POLARSSL_HAVE_INT8) +typedef unsigned char t_int; +typedef unsigned short t_dbl; +#else +#if defined(POLARSSL_HAVE_INT16) +typedef unsigned short t_int; +typedef unsigned long t_dbl; +#else + typedef unsigned long t_int; + #if defined(_MSC_VER) && defined(_M_IX86) + typedef unsigned __int64 t_dbl; + #else + #if defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) + typedef unsigned int t_dbl __attribute__((mode(TI))); + #else + typedef unsigned long long t_dbl; + #endif + #endif +#endif +#endif + +/** + * \brief MPI structure + */ +typedef struct +{ + int s; /*!< integer sign */ + int n; /*!< total # of limbs */ + t_int *p; /*!< pointer to limbs */ +} +mpi; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize one or more mpi + */ +void mpi_init( mpi *X, ... ); + +/** + * \brief Unallocate one or more mpi + */ +void mpi_free( mpi *X, ... ); + +/** + * \brief Enlarge to the specified number of limbs + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_grow( mpi *X, int nblimbs ); + +/** + * \brief Copy the contents of Y into X + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_copy( mpi *X, mpi *Y ); + +/** + * \brief Swap the contents of X and Y + */ +void mpi_swap( mpi *X, mpi *Y ); + +/** + * \brief Set value from integer + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_lset( mpi *X, int z ); + +/** + * \brief Return the number of least significant bits + */ +int mpi_lsb( mpi *X ); + +/** + * \brief Return the number of most significant bits + */ +int mpi_msb( mpi *X ); + +/** + * \brief Return the total size in bytes + */ +int mpi_size( mpi *X ); + +/** + * \brief Import from an ASCII string + * + * \param X destination mpi + * \param radix input numeric base + * \param s null-terminated string buffer + * + * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code + */ +int mpi_read_string( mpi *X, int radix, char *s ); + +/** + * \brief Export into an ASCII string + * + * \param X source mpi + * \param radix output numeric base + * \param s string buffer + * \param slen string buffer size + * + * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code + * + * \note Call this function with *slen = 0 to obtain the + * minimum required buffer size in *slen. + */ +int mpi_write_string( mpi *X, int radix, char *s, int *slen ); + +/** + * \brief Read X from an opened file + * + * \param X destination mpi + * \param radix input numeric base + * \param fin input file handle + * + * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code + */ +int mpi_read_file( mpi *X, int radix, FILE *fin ); + +/** + * \brief Write X into an opened file, or stdout + * + * \param p prefix, can be NULL + * \param X source mpi + * \param radix output numeric base + * \param fout output file handle + * + * \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code + * + * \note Set fout == NULL to print X on the console. + */ +int mpi_write_file( char *p, mpi *X, int radix, FILE *fout ); + +/** + * \brief Import X from unsigned binary data, big endian + * + * \param X destination mpi + * \param buf input buffer + * \param buflen input buffer size + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_read_binary( mpi *X, unsigned char *buf, int buflen ); + +/** + * \brief Export X into unsigned binary data, big endian + * + * \param X source mpi + * \param buf output buffer + * \param buflen output buffer size + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough + * + * \note Call this function with *buflen = 0 to obtain the + * minimum required buffer size in *buflen. + */ +int mpi_write_binary( mpi *X, unsigned char *buf, int buflen ); + +/** + * \brief Left-shift: X <<= count + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_shift_l( mpi *X, int count ); + +/** + * \brief Right-shift: X >>= count + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_shift_r( mpi *X, int count ); + +/** + * \brief Compare unsigned values + * + * \return 1 if |X| is greater than |Y|, + * -1 if |X| is lesser than |Y| or + * 0 if |X| is equal to |Y| + */ +int mpi_cmp_abs( mpi *X, mpi *Y ); + +/** + * \brief Compare signed values + * + * \return 1 if X is greater than Y, + * -1 if X is lesser than Y or + * 0 if X is equal to Y + */ +int mpi_cmp_mpi( mpi *X, mpi *Y ); + +/** + * \brief Compare signed values + * + * \return 1 if X is greater than z, + * -1 if X is lesser than z or + * 0 if X is equal to z + */ +int mpi_cmp_int( mpi *X, int z ); + +/** + * \brief Unsigned addition: X = |A| + |B| + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_add_abs( mpi *X, mpi *A, mpi *B ); + +/** + * \brief Unsigned substraction: X = |A| - |B| + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A + */ +int mpi_sub_abs( mpi *X, mpi *A, mpi *B ); + +/** + * \brief Signed addition: X = A + B + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_add_mpi( mpi *X, mpi *A, mpi *B ); + +/** + * \brief Signed substraction: X = A - B + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_sub_mpi( mpi *X, mpi *A, mpi *B ); + +/** + * \brief Signed addition: X = A + b + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_add_int( mpi *X, mpi *A, int b ); + +/** + * \brief Signed substraction: X = A - b + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_sub_int( mpi *X, mpi *A, int b ); + +/** + * \brief Baseline multiplication: X = A * B + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_mul_mpi( mpi *X, mpi *A, mpi *B ); + +/** + * \brief Baseline multiplication: X = A * b + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_mul_int( mpi *X, mpi *A, t_int b ); + +/** + * \brief Division by mpi: A = Q * B + R + * + * \return 0 if successful, + * 1 if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0 + * + * \note Either Q or R can be NULL. + */ +int mpi_div_mpi( mpi *Q, mpi *R, mpi *A, mpi *B ); + +/** + * \brief Division by int: A = Q * b + R + * + * \return 0 if successful, + * 1 if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 + * + * \note Either Q or R can be NULL. + */ +int mpi_div_int( mpi *Q, mpi *R, mpi *A, int b ); + +/** + * \brief Modulo: R = A mod B + * + * \return 0 if successful, + * 1 if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0 + */ +int mpi_mod_mpi( mpi *R, mpi *A, mpi *B ); + +/** + * \brief Modulo: r = A mod b + * + * \return 0 if successful, + * 1 if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 + */ +int mpi_mod_int( t_int *r, mpi *A, int b ); + +/** + * \brief Sliding-window exponentiation: X = A^E mod N + * + * \return 0 if successful, + * 1 if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even + * + * \note _RR is used to avoid re-computing R*R mod N across + * multiple calls, which speeds up things a bit. It can + * be set to NULL if the extra performance is unneeded. + */ +int mpi_exp_mod( mpi *X, mpi *A, mpi *E, mpi *N, mpi *_RR ); + +/** + * \brief Greatest common divisor: G = gcd(A, B) + * + * \return 0 if successful, + * 1 if memory allocation failed + */ +int mpi_gcd( mpi *G, mpi *A, mpi *B ); + +/** + * \brief Modular inverse: X = A^-1 mod N + * + * \return 0 if successful, + * 1 if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil + * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N + */ +int mpi_inv_mod( mpi *X, mpi *A, mpi *N ); + +/** + * \brief Miller-Rabin primality test + * + * \return 0 if successful (probably prime), + * 1 if memory allocation failed, + * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime + */ +int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng ); + +/** + * \brief Prime number generation + * + * \param X destination mpi + * \param nbits required size of X in bits + * \param dh_flag if 1, then (X-1)/2 will be prime too + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * 1 if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 + */ +int mpi_gen_prime( mpi *X, int nbits, int dh_flag, + int (*f_rng)(void *), void *p_rng ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mpi_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ diff --git a/package/utils/px5g-standalone/src/polarssl/bn_mul.h b/package/utils/px5g-standalone/src/polarssl/bn_mul.h new file mode 100644 index 0000000..f6d34da --- /dev/null +++ b/package/utils/px5g-standalone/src/polarssl/bn_mul.h @@ -0,0 +1,731 @@ +/** + * \file bn_mul.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 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 + * OWNER 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. + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef POLARSSL_BN_MUL_H +#define POLARSSL_BN_MUL_H + +#include "polarssl/config.h" + +#if defined(POLARSSL_HAVE_ASM) + +#if defined(__GNUC__) +#if defined(__i386__) + +#define MULADDC_INIT \ + asm( "movl %%ebx, %0 " : "=m" (t)); \ + asm( "movl %0, %%esi " :: "m" (s)); \ + asm( "movl %0, %%edi " :: "m" (d)); \ + asm( "movl %0, %%ecx " :: "m" (c)); \ + asm( "movl %0, %%ebx " :: "m" (b)); + +#define MULADDC_CORE \ + asm( "lodsl " ); \ + asm( "mull %ebx " ); \ + asm( "addl %ecx, %eax " ); \ + asm( "adcl $0, %edx " ); \ + asm( "addl (%edi), %eax " ); \ + asm( "adcl $0, %edx " ); \ + asm( "movl %edx, %ecx " ); \ + asm( "stosl " ); + +#if defined(POLARSSL_HAVE_SSE2) + +#define MULADDC_HUIT \ + asm( "movd %ecx, %mm1 " ); \ + asm( "movd %ebx, %mm0 " ); \ + asm( "movd (%edi), %mm3 " ); \ + asm( "paddq %mm3, %mm1 " ); \ + asm( "movd (%esi), %mm2 " ); \ + asm( "pmuludq %mm0, %mm2 " ); \ + asm( "movd 4(%esi), %mm4 " ); \ + asm( "pmuludq %mm0, %mm4 " ); \ + asm( "movd 8(%esi), %mm6 " ); \ + asm( "pmuludq %mm0, %mm6 " ); \ + asm( "movd 12(%esi), %mm7 " ); \ + asm( "pmuludq %mm0, %mm7 " ); \ + asm( "paddq %mm2, %mm1 " ); \ + asm( "movd 4(%edi), %mm3 " ); \ + asm( "paddq %mm4, %mm3 " ); \ + asm( "movd 8(%edi), %mm5 " ); \ + asm( "paddq %mm6, %mm5 " ); \ + asm( "movd 12(%edi), %mm4 " ); \ + asm( "paddq %mm4, %mm7 " ); \ + asm( "movd %mm1, (%edi) " ); \ + asm( "movd 16(%esi), %mm2 " ); \ + asm( "pmuludq %mm0, %mm2 " ); \ + asm( "psrlq $32, %mm1 " ); \ + asm( "movd 20(%esi), %mm4 " ); \ + asm( "pmuludq %mm0, %mm4 " ); \ + asm( "paddq %mm3, %mm1 " ); \ + asm( "movd 24(%esi), %mm6 " ); \ + asm( "pmuludq %mm0, %mm6 " ); \ + asm( "movd %mm1, 4(%edi) " ); \ + asm( "psrlq $32, %mm1 " ); \ + asm( "movd 28(%esi), %mm3 " ); \ + asm( "pmuludq %mm0, %mm3 " ); \ + asm( "paddq %mm5, %mm1 " ); \ + asm( "movd 16(%edi), %mm5 " ); \ + asm( "paddq %mm5, %mm2 " ); \ + asm( "movd %mm1, 8(%edi) " ); \ + asm( "psrlq $32, %mm1 " ); \ + asm( "paddq %mm7, %mm1 " ); \ + asm( "movd 20(%edi), %mm5 " ); \ + asm( "paddq %mm5, %mm4 " ); \ + asm( "movd %mm1, 12(%edi) " ); \ + asm( "psrlq $32, %mm1 " ); \ + asm( "paddq %mm2, %mm1 " ); \ + asm( "movd 24(%edi), %mm5 " ); \ + asm( "paddq %mm5, %mm6 " ); \ + asm( "movd %mm1, 16(%edi) " ); \ + asm( "psrlq $32, %mm1 " ); \ + asm( "paddq %mm4, %mm1 " ); \ + asm( "movd 28(%edi), %mm5 " ); \ + asm( "paddq %mm5, %mm3 " ); \ + asm( "movd %mm1, 20(%edi) " ); \ + asm( "psrlq $32, %mm1 " ); \ + asm( "paddq %mm6, %mm1 " ); \ + asm( "movd %mm1, 24(%edi) " ); \ + asm( "psrlq $32, %mm1 " ); \ + asm( "paddq %mm3, %mm1 " ); \ + asm( "movd %mm1, 28(%edi) " ); \ + asm( "addl $32, %edi " ); \ + asm( "addl $32, %esi " ); \ + asm( "psrlq $32, %mm1 " ); \ + asm( "movd %mm1, %ecx " ); + +#define MULADDC_STOP \ + asm( "emms " ); \ + asm( "movl %0, %%ebx " :: "m" (t)); \ + asm( "movl %%ecx, %0 " : "=m" (c)); \ + asm( "movl %%edi, %0 " : "=m" (d)); \ + asm( "movl %%esi, %0 " : "=m" (s) :: \ + "eax", "ecx", "edx", "esi", "edi" ); + +#else + +#define MULADDC_STOP \ + asm( "movl %0, %%ebx " :: "m" (t)); \ + asm( "movl %%ecx, %0 " : "=m" (c)); \ + asm( "movl %%edi, %0 " : "=m" (d)); \ + asm( "movl %%esi, %0 " : "=m" (s) :: \ + "eax", "ecx", "edx", "esi", "edi" ); + +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( "movq %0, %%rsi " :: "m" (s)); \ + asm( "movq %0, %%rdi " :: "m" (d)); \ + asm( "movq %0, %%rcx " :: "m" (c)); \ + asm( "movq %0, %%rbx " :: "m" (b)); \ + asm( "xorq %r8, %r8 " ); + +#define MULADDC_CORE \ + asm( "movq (%rsi),%rax " ); \ + asm( "mulq %rbx " ); \ + asm( "addq $8, %rsi " ); \ + asm( "addq %rcx, %rax " ); \ + asm( "movq %r8, %rcx " ); \ + asm( "adcq $0, %rdx " ); \ + asm( "nop " ); \ + asm( "addq %rax, (%rdi) " ); \ + asm( "adcq %rdx, %rcx " ); \ + asm( "addq $8, %rdi " ); + +#define MULADDC_STOP \ + asm( "movq %%rcx, %0 " : "=m" (c)); \ + asm( "movq %%rdi, %0 " : "=m" (d)); \ + asm( "movq %%rsi, %0 " : "=m" (s) :: \ + "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" ); + +#endif /* AMD64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( "movl %0, %%a2 " :: "m" (s)); \ + asm( "movl %0, %%a3 " :: "m" (d)); \ + asm( "movl %0, %%d3 " :: "m" (c)); \ + asm( "movl %0, %%d2 " :: "m" (b)); \ + asm( "moveq #0, %d0 " ); + +#define MULADDC_CORE \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d4:%d1 " ); \ + asm( "addl %d3, %d1 " ); \ + asm( "addxl %d0, %d4 " ); \ + asm( "moveq #0, %d3 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "addxl %d4, %d3 " ); + +#define MULADDC_STOP \ + asm( "movl %%d3, %0 " : "=m" (c)); \ + asm( "movl %%a3, %0 " : "=m" (d)); \ + asm( "movl %%a2, %0 " : "=m" (s) :: \ + "d0", "d1", "d2", "d3", "d4", "a2", "a3" ); + +#define MULADDC_HUIT \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d4:%d1 " ); \ + asm( "addxl %d3, %d1 " ); \ + asm( "addxl %d0, %d4 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d3:%d1 " ); \ + asm( "addxl %d4, %d1 " ); \ + asm( "addxl %d0, %d3 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d4:%d1 " ); \ + asm( "addxl %d3, %d1 " ); \ + asm( "addxl %d0, %d4 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d3:%d1 " ); \ + asm( "addxl %d4, %d1 " ); \ + asm( "addxl %d0, %d3 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d4:%d1 " ); \ + asm( "addxl %d3, %d1 " ); \ + asm( "addxl %d0, %d4 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d3:%d1 " ); \ + asm( "addxl %d4, %d1 " ); \ + asm( "addxl %d0, %d3 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d4:%d1 " ); \ + asm( "addxl %d3, %d1 " ); \ + asm( "addxl %d0, %d4 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "movel %a2@+, %d1 " ); \ + asm( "mulul %d2, %d3:%d1 " ); \ + asm( "addxl %d4, %d1 " ); \ + asm( "addxl %d0, %d3 " ); \ + asm( "addl %d1, %a3@+ " ); \ + asm( "addxl %d0, %d3 " ); + +#endif /* MC68000 */ + +#if defined(__powerpc__) || defined(__ppc__) +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( "ld r3, %0 " :: "m" (s)); \ + asm( "ld r4, %0 " :: "m" (d)); \ + asm( "ld r5, %0 " :: "m" (c)); \ + asm( "ld r6, %0 " :: "m" (b)); \ + asm( "addi r3, r3, -8 " ); \ + asm( "addi r4, r4, -8 " ); \ + asm( "addic r5, r5, 0 " ); + +#define MULADDC_CORE \ + asm( "ldu r7, 8(r3) " ); \ + asm( "mulld r8, r7, r6 " ); \ + asm( "mulhdu r9, r7, r6 " ); \ + asm( "adde r8, r8, r5 " ); \ + asm( "ld r7, 8(r4) " ); \ + asm( "addze r5, r9 " ); \ + asm( "addc r8, r8, r7 " ); \ + asm( "stdu r8, 8(r4) " ); + +#define MULADDC_STOP \ + asm( "addze r5, r5 " ); \ + asm( "addi r4, r4, 8 " ); \ + asm( "addi r3, r3, 8 " ); \ + asm( "std r5, %0 " : "=m" (c)); \ + asm( "std r4, %0 " : "=m" (d)); \ + asm( "std r3, %0 " : "=m" (s) :: \ + "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + +#else + +#define MULADDC_INIT \ + asm( "ld %%r3, %0 " :: "m" (s)); \ + asm( "ld %%r4, %0 " :: "m" (d)); \ + asm( "ld %%r5, %0 " :: "m" (c)); \ + asm( "ld %%r6, %0 " :: "m" (b)); \ + asm( "addi %r3, %r3, -8 " ); \ + asm( "addi %r4, %r4, -8 " ); \ + asm( "addic %r5, %r5, 0 " ); + +#define MULADDC_CORE \ + asm( "ldu %r7, 8(%r3) " ); \ + asm( "mulld %r8, %r7, %r6 " ); \ + asm( "mulhdu %r9, %r7, %r6 " ); \ + asm( "adde %r8, %r8, %r5 " ); \ + asm( "ld %r7, 8(%r4) " ); \ + asm( "addze %r5, %r9 " ); \ + asm( "addc %r8, %r8, %r7 " ); \ + asm( "stdu %r8, 8(%r4) " ); + +#define MULADDC_STOP \ + asm( "addze %r5, %r5 " ); \ + asm( "addi %r4, %r4, 8 " ); \ + asm( "addi %r3, %r3, 8 " ); \ + asm( "std %%r5, %0 " : "=m" (c)); \ + asm( "std %%r4, %0 " : "=m" (d)); \ + asm( "std %%r3, %0 " : "=m" (s) :: \ + "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + +#endif + +#else /* PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( "lwz r3, %0 " :: "m" (s)); \ + asm( "lwz r4, %0 " :: "m" (d)); \ + asm( "lwz r5, %0 " :: "m" (c)); \ + asm( "lwz r6, %0 " :: "m" (b)); \ + asm( "addi r3, r3, -4 " ); \ + asm( "addi r4, r4, -4 " ); \ + asm( "addic r5, r5, 0 " ); + +#define MULADDC_CORE \ + asm( "lwzu r7, 4(r3) " ); \ + asm( "mullw r8, r7, r6 " ); \ + asm( "mulhwu r9, r7, r6 " ); \ + asm( "adde r8, r8, r5 " ); \ + asm( "lwz r7, 4(r4) " ); \ + asm( "addze r5, r9 " ); \ + asm( "addc r8, r8, r7 " ); \ + asm( "stwu r8, 4(r4) " ); + +#define MULADDC_STOP \ + asm( "addze r5, r5 " ); \ + asm( "addi r4, r4, 4 " ); \ + asm( "addi r3, r3, 4 " ); \ + asm( "stw r5, %0 " : "=m" (c)); \ + asm( "stw r4, %0 " : "=m" (d)); \ + asm( "stw r3, %0 " : "=m" (s) :: \ + "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + +#else + +#define MULADDC_INIT \ + asm( "lwz %%r3, %0 " :: "m" (s)); \ + asm( "lwz %%r4, %0 " :: "m" (d)); \ + asm( "lwz %%r5, %0 " :: "m" (c)); \ + asm( "lwz %%r6, %0 " :: "m" (b)); \ + asm( "addi %r3, %r3, -4 " ); \ + asm( "addi %r4, %r4, -4 " ); \ + asm( "addic %r5, %r5, 0 " ); + +#define MULADDC_CORE \ + asm( "lwzu %r7, 4(%r3) " ); \ + asm( "mullw %r8, %r7, %r6 " ); \ + asm( "mulhwu %r9, %r7, %r6 " ); \ + asm( "adde %r8, %r8, %r5 " ); \ + asm( "lwz %r7, 4(%r4) " ); \ + asm( "addze %r5, %r9 " ); \ + asm( "addc %r8, %r8, %r7 " ); \ + asm( "stwu %r8, 4(%r4) " ); + +#define MULADDC_STOP \ + asm( "addze %r5, %r5 " ); \ + asm( "addi %r4, %r4, 4 " ); \ + asm( "addi %r3, %r3, 4 " ); \ + asm( "stw %%r5, %0 " : "=m" (c)); \ + asm( "stw %%r4, %0 " : "=m" (d)); \ + asm( "stw %%r3, %0 " : "=m" (s) :: \ + "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + +#endif + +#endif /* PPC32 */ +#endif /* PPC64 */ + +#if defined(__sparc__) + +#define MULADDC_INIT \ + asm( "ld %0, %%o0 " :: "m" (s)); \ + asm( "ld %0, %%o1 " :: "m" (d)); \ + asm( "ld %0, %%o2 " :: "m" (c)); \ + asm( "ld %0, %%o3 " :: "m" (b)); + +#define MULADDC_CORE \ + asm( "ld [%o0], %o4 " ); \ + asm( "inc 4, %o0 " ); \ + asm( "ld [%o1], %o5 " ); \ + asm( "umul %o3, %o4, %o4 " ); \ + asm( "addcc %o4, %o2, %o4 " ); \ + asm( "rd %y, %g1 " ); \ + asm( "addx %g1, 0, %g1 " ); \ + asm( "addcc %o4, %o5, %o4 " ); \ + asm( "st %o4, [%o1] " ); \ + asm( "addx %g1, 0, %o2 " ); \ + asm( "inc 4, %o1 " ); + +#define MULADDC_STOP \ + asm( "st %%o2, %0 " : "=m" (c)); \ + asm( "st %%o1, %0 " : "=m" (d)); \ + asm( "st %%o0, %0 " : "=m" (s) :: \ + "g1", "o0", "o1", "o2", "o3", "o4", "o5" ); + +#endif /* SPARCv8 */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( "lwi r3, %0 " :: "m" (s)); \ + asm( "lwi r4, %0 " :: "m" (d)); \ + asm( "lwi r5, %0 " :: "m" (c)); \ + asm( "lwi r6, %0 " :: "m" (b)); \ + asm( "andi r7, r6, 0xffff" ); \ + asm( "bsrli r6, r6, 16 " ); + +#define MULADDC_CORE \ + asm( "lhui r8, r3, 0 " ); \ + asm( "addi r3, r3, 2 " ); \ + asm( "lhui r9, r3, 0 " ); \ + asm( "addi r3, r3, 2 " ); \ + asm( "mul r10, r9, r6 " ); \ + asm( "mul r11, r8, r7 " ); \ + asm( "mul r12, r9, r7 " ); \ + asm( "mul r13, r8, r6 " ); \ + asm( "bsrli r8, r10, 16 " ); \ + asm( "bsrli r9, r11, 16 " ); \ + asm( "add r13, r13, r8 " ); \ + asm( "add r13, r13, r9 " ); \ + asm( "bslli r10, r10, 16 " ); \ + asm( "bslli r11, r11, 16 " ); \ + asm( "add r12, r12, r10 " ); \ + asm( "addc r13, r13, r0 " ); \ + asm( "add r12, r12, r11 " ); \ + asm( "addc r13, r13, r0 " ); \ + asm( "lwi r10, r4, 0 " ); \ + asm( "add r12, r12, r10 " ); \ + asm( "addc r13, r13, r0 " ); \ + asm( "add r12, r12, r5 " ); \ + asm( "addc r5, r13, r0 " ); \ + asm( "swi r12, r4, 0 " ); \ + asm( "addi r4, r4, 4 " ); + +#define MULADDC_STOP \ + asm( "swi r5, %0 " : "=m" (c)); \ + asm( "swi r4, %0 " : "=m" (d)); \ + asm( "swi r3, %0 " : "=m" (s) :: \ + "r3", "r4" , "r5" , "r6" , "r7" , "r8" , \ + "r9", "r10", "r11", "r12", "r13" ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( "ld.a %%a2, %0 " :: "m" (s)); \ + asm( "ld.a %%a3, %0 " :: "m" (d)); \ + asm( "ld.w %%d4, %0 " :: "m" (c)); \ + asm( "ld.w %%d1, %0 " :: "m" (b)); \ + asm( "xor %d5, %d5 " ); + +#define MULADDC_CORE \ + asm( "ld.w %d0, [%a2+] " ); \ + asm( "madd.u %e2, %e4, %d0, %d1 " ); \ + asm( "ld.w %d0, [%a3] " ); \ + asm( "addx %d2, %d2, %d0 " ); \ + asm( "addc %d3, %d3, 0 " ); \ + asm( "mov %d4, %d3 " ); \ + asm( "st.w [%a3+], %d2 " ); + +#define MULADDC_STOP \ + asm( "st.w %0, %%d4 " : "=m" (c)); \ + asm( "st.a %0, %%a3 " : "=m" (d)); \ + asm( "st.a %0, %%a2 " : "=m" (s) :: \ + "d0", "d1", "e2", "d4", "a2", "a3" ); + +#endif /* TriCore */ + +#if defined(__arm__) + +#define MULADDC_INIT \ + asm( "ldr r0, %0 " :: "m" (s)); \ + asm( "ldr r1, %0 " :: "m" (d)); \ + asm( "ldr r2, %0 " :: "m" (c)); \ + asm( "ldr r3, %0 " :: "m" (b)); + +#define MULADDC_CORE \ + asm( "ldr r4, [r0], #4 " ); \ + asm( "mov r5, #0 " ); \ + asm( "ldr r6, [r1] " ); \ + asm( "umlal r2, r5, r3, r4 " ); \ + asm( "adds r7, r6, r2 " ); \ + asm( "adc r2, r5, #0 " ); \ + asm( "str r7, [r1], #4 " ); + +#define MULADDC_STOP \ + asm( "str r2, %0 " : "=m" (c)); \ + asm( "str r1, %0 " : "=m" (d)); \ + asm( "str r0, %0 " : "=m" (s) :: \ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" ); + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( "ldq $1, %0 " :: "m" (s)); \ + asm( "ldq $2, %0 " :: "m" (d)); \ + asm( "ldq $3, %0 " :: "m" (c)); \ + asm( "ldq $4, %0 " :: "m" (b)); + +#define MULADDC_CORE \ + asm( "ldq $6, 0($1) " ); \ + asm( "addq $1, 8, $1 " ); \ + asm( "mulq $6, $4, $7 " ); \ + asm( "umulh $6, $4, $6 " ); \ + asm( "addq $7, $3, $7 " ); \ + asm( "cmpult $7, $3, $3 " ); \ + asm( "ldq $5, 0($2) " ); \ + asm( "addq $7, $5, $7 " ); \ + asm( "cmpult $7, $5, $5 " ); \ + asm( "stq $7, 0($2) " ); \ + asm( "addq $2, 8, $2 " ); \ + asm( "addq $6, $3, $3 " ); \ + asm( "addq $5, $3, $3 " ); + +#define MULADDC_STOP \ + asm( "stq $3, %0 " : "=m" (c)); \ + asm( "stq $2, %0 " : "=m" (d)); \ + asm( "stq $1, %0 " : "=m" (s) :: \ + "$1", "$2", "$3", "$4", "$5", "$6", "$7" ); + +#endif /* Alpha */ + +#if defined(__mips__) + +#define MULADDC_INIT \ + asm( "lw $10, %0 " :: "m" (s)); \ + asm( "lw $11, %0 " :: "m" (d)); \ + asm( "lw $12, %0 " :: "m" (c)); \ + asm( "lw $13, %0 " :: "m" (b)); + +#define MULADDC_CORE \ + asm( "lw $14, 0($10) " ); \ + asm( "multu $13, $14 " ); \ + asm( "addi $10, $10, 4 " ); \ + asm( "mflo $14 " ); \ + asm( "mfhi $9 " ); \ + asm( "addu $14, $12, $14 " ); \ + asm( "lw $15, 0($11) " ); \ + asm( "sltu $12, $14, $12 " ); \ + asm( "addu $15, $14, $15 " ); \ + asm( "sltu $14, $15, $14 " ); \ + asm( "addu $12, $12, $9 " ); \ + asm( "sw $15, 0($11) " ); \ + asm( "addu $12, $12, $14 " ); \ + asm( "addi $11, $11, 4 " ); + +#define MULADDC_STOP \ + asm( "sw $12, %0 " : "=m" (c)); \ + asm( "sw $11, %0 " : "=m" (d)); \ + asm( "sw $10, %0 " : "=m" (s) :: \ + "$9", "$10", "$11", "$12", "$13", "$14", "$15" ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(POLARSSL_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* POLARSSL_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(POLARSSL_HAVE_LONGLONG) + +#define MULADDC_INIT \ +{ \ + t_dbl r; \ + t_int r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (t_dbl) b; \ + r0 = r; \ + r1 = r >> biL; \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + t_int s0, s1, b0, b1; \ + t_int r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ diff --git a/package/utils/px5g-standalone/src/polarssl/config.h b/package/utils/px5g-standalone/src/polarssl/config.h new file mode 100644 index 0000000..79cd3db --- /dev/null +++ b/package/utils/px5g-standalone/src/polarssl/config.h @@ -0,0 +1,329 @@ +/** + * \file config.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 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 + * OWNER 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. + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/* + * Uncomment if native integers are 8-bit wide. + * +#define POLARSSL_HAVE_INT8 + */ + +/* + * Uncomment if native integers are 16-bit wide. + * +#define POLARSSL_HAVE_INT16 + */ + +/* + * Uncomment if the compiler supports long long. +#define POLARSSL_HAVE_LONGLONG + */ + + +/* + * Uncomment to enable the use of assembly code. + */ +/* #define POLARSSL_HAVE_ASM */ + +/* + * Uncomment if the CPU supports SSE2 (IA-32 specific). + * +#define POLARSSL_HAVE_SSE2 + */ + +/* + * Enable all SSL/TLS debugging messages. + */ +#define POLARSSL_DEBUG_MSG + +/* + * Enable the checkup functions (*_self_test). + */ +#define POLARSSL_SELF_TEST + +/* + * Enable the prime-number generation code. + */ +#define POLARSSL_GENPRIME + +/* + * Uncomment this macro to store the AES tables in ROM. + * +#define POLARSSL_AES_ROM_TABLES + */ + +/* + * Module: library/aes.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites: + * SSL_RSA_AES_128_SHA + * SSL_RSA_AES_256_SHA + * SSL_EDH_RSA_AES_256_SHA + */ +#define POLARSSL_AES_C + +/* + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites: + * SSL_RSA_RC4_128_MD5 + * SSL_RSA_RC4_128_SHA + */ +#define POLARSSL_ARC4_C + +/* + * Module: library/base64.c + * Caller: library/x509parse.c + * + * This module is required for X.509 support. + */ +#define POLARSSL_BASE64_C + +/* + * Module: library/bignum.c + * Caller: library/dhm.c + * library/rsa.c + * library/ssl_tls.c + * library/x509parse.c + * + * This module is required for RSA and DHM support. + */ +#define POLARSSL_BIGNUM_C + +/* + * Module: library/camellia.c + * Caller: + * + * This module enabled the following cipher suites: + */ +#define POLARSSL_CAMELLIA_C + +/* + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +#define POLARSSL_CERTS_C + +/* + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +#define POLARSSL_DEBUG_C + +/* + * Module: library/des.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites: + * SSL_RSA_DES_168_SHA + * SSL_EDH_RSA_DES_168_SHA + */ +#define POLARSSL_DES_C + +/* + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module enables the following ciphersuites: + * SSL_EDH_RSA_DES_168_SHA + * SSL_EDH_RSA_AES_256_SHA + */ +#define POLARSSL_DHM_C + +/* + * Module: library/havege.c + * Caller: + * + * This module enables the HAVEGE random number generator. + */ +#define POLARSSL_HAVEGE_C + +/* + * Module: library/md2.c + * Caller: library/x509parse.c + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * +#define POLARSSL_MD2_C + */ + +/* + * Module: library/md4.c + * Caller: library/x509parse.c + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * +#define POLARSSL_MD4_C + */ + +/* + * Module: library/md5.c + * Caller: library/ssl_tls.c + * library/x509parse.c + * + * This module is required for SSL/TLS and X.509. + */ +#define POLARSSL_MD5_C + +/* + * Module: library/net.c + * Caller: + * + * This module provides TCP/IP networking routines. + */ +#define POLARSSL_NET_C + +/* + * Module: library/padlock.c + * Caller: library/aes.c + * + * This modules adds support for the VIA PadLock on x86. + */ +#define POLARSSL_PADLOCK_C + +/* + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is required for SSL/TLS and MD5-signed certificates. + */ +#define POLARSSL_RSA_C + +/* + * Module: library/sha1.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509parse.c + * + * This module is required for SSL/TLS and SHA1-signed certificates. + */ +#define POLARSSL_SHA1_C + +/* + * Module: library/sha2.c + * Caller: + * + * This module adds support for SHA-224 and SHA-256. + */ +#define POLARSSL_SHA2_C + +/* + * Module: library/sha4.c + * Caller: + * + * This module adds support for SHA-384 and SHA-512. + */ +#define POLARSSL_SHA4_C + +/* + * Module: library/ssl_cli.c + * Caller: + * + * This module is required for SSL/TLS client support. + */ +#define POLARSSL_SSL_CLI_C + +/* + * Module: library/ssl_srv.c + * Caller: + * + * This module is required for SSL/TLS server support. + */ +#define POLARSSL_SSL_SRV_C + +/* + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is required for SSL/TLS. + */ +#define POLARSSL_SSL_TLS_C + +/* + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +#define POLARSSL_TIMING_C + +/* + * Module: library/x509parse.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module is required for X.509 certificate parsing. + */ +#define POLARSSL_X509_PARSE_C + +/* + * Module: library/x509_write.c + * Caller: + * + * This module is required for X.509 certificate writing. + */ +#define POLARSSL_X509_WRITE_C + +/* + * Module: library/xtea.c + * Caller: + */ +#define POLARSSL_XTEA_C + +#endif /* config.h */ diff --git a/package/utils/px5g-standalone/src/polarssl/rsa.h b/package/utils/px5g-standalone/src/polarssl/rsa.h new file mode 100644 index 0000000..b31dc2f --- /dev/null +++ b/package/utils/px5g-standalone/src/polarssl/rsa.h @@ -0,0 +1,309 @@ +/** + * \file rsa.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 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 + * OWNER 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. + */ +#ifndef POLARSSL_RSA_H +#define POLARSSL_RSA_H + +#include "polarssl/bignum.h" + +#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x0400 +#define POLARSSL_ERR_RSA_INVALID_PADDING -0x0410 +#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x0420 +#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x0430 +#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x0440 +#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x0450 +#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x0460 +#define POLARSSL_ERR_RSA_OUTPUT_TO_LARGE -0x0470 + +/* + * PKCS#1 constants + */ +#define RSA_RAW 0 +#define RSA_MD2 2 +#define RSA_MD4 3 +#define RSA_MD5 4 +#define RSA_SHA1 5 +#define RSA_SHA256 6 + +#define RSA_PUBLIC 0 +#define RSA_PRIVATE 1 + +#define RSA_PKCS_V15 0 +#define RSA_PKCS_V21 1 + +#define RSA_SIGN 1 +#define RSA_CRYPT 2 + +/* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ +#define ASN1_HASH_MDX \ + "\x30\x20\x30\x0C\x06\x08\x2A\x86\x48" \ + "\x86\xF7\x0D\x02\x00\x05\x00\x04\x10" + +#define ASN1_HASH_SHA1 \ + "\x30\x21\x30\x09\x06\x05\x2B\x0E\x03" \ + "\x02\x1A\x05\x00\x04\x14" + +/** + * \brief RSA context structure + */ +typedef struct +{ + int ver; /*!< always 0 */ + int len; /*!< size(N) in chars */ + + mpi N; /*!< public modulus */ + mpi E; /*!< public exponent */ + + mpi D; /*!< private exponent */ + mpi P; /*!< 1st prime factor */ + mpi Q; /*!< 2nd prime factor */ + mpi DP; /*!< D % (P - 1) */ + mpi DQ; /*!< D % (Q - 1) */ + mpi QP; /*!< 1 / (Q % P) */ + + mpi RN; /*!< cached R^2 mod N */ + mpi RP; /*!< cached R^2 mod P */ + mpi RQ; /*!< cached R^2 mod Q */ + + int padding; /*!< 1.5 or OAEP/PSS */ + int hash_id; /*!< hash identifier */ + int (*f_rng)(void *); /*!< RNG function */ + void *p_rng; /*!< RNG parameter */ +} +rsa_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize an RSA context + * + * \param ctx RSA context to be initialized + * \param padding RSA_PKCS_V15 or RSA_PKCS_V21 + * \param hash_id RSA_PKCS_V21 hash identifier + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note The hash_id parameter is actually ignored + * when using RSA_PKCS_V15 padding. + * + * \note Currently (xyssl-0.8), RSA_PKCS_V21 padding + * is not supported. + */ +void rsa_init( rsa_context *ctx, + int padding, + int hash_id, + int (*f_rng)(void *), + void *p_rng ); + +/** + * \brief Generate an RSA keypair + * + * \param ctx RSA context that will hold the key + * \param nbits size of the public key in bits + * \param exponent public exponent (e.g., 65537) + * + * \note rsa_init() must be called beforehand to setup + * the RSA context (especially f_rng and p_rng). + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_gen_key( rsa_context *ctx, int nbits, int exponent ); + +/** + * \brief Check a public RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_check_pubkey( rsa_context *ctx ); + +/** + * \brief Check a private RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_check_privkey( rsa_context *ctx ); + +/** + * \brief Do an RSA public key operation + * + * \param ctx RSA context + * \param input input buffer + * \param output output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note This function does NOT take care of message + * padding. Also, be sure to set input[0] = 0. + * + * \note The input and output buffers must be large + * enough (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_public( rsa_context *ctx, + unsigned char *input, + unsigned char *output ); + +/** + * \brief Do an RSA private key operation + * + * \param ctx RSA context + * \param input input buffer + * \param output output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The input and output buffers must be large + * enough (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_private( rsa_context *ctx, + unsigned char *input, + unsigned char *output ); + +/** + * \brief Add the message padding, then do an RSA operation + * + * \param ctx RSA context + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param ilen contains the the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_pkcs1_encrypt( rsa_context *ctx, + int mode, int ilen, + unsigned char *input, + unsigned char *output ); + +/** + * \brief Do an RSA operation, then remove the message padding + * + * \param ctx RSA context + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param olen will contain the plaintext length + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int rsa_pkcs1_decrypt( rsa_context *ctx, + int mode, int *olen, + unsigned char *input, + unsigned char *output, + int output_max_len); + +/** + * \brief Do a private RSA to sign a message digest + * + * \param ctx RSA context + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id RSA_RAW, RSA_MD{2,4,5} or RSA_SHA{1,256} + * \param hashlen message digest length (for RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_pkcs1_sign( rsa_context *ctx, + int mode, + int hash_id, + int hashlen, + unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Do a public RSA and check the message digest + * + * \param ctx points to an RSA public key + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param hash_id RSA_RAW, RSA_MD{2,4,5} or RSA_SHA{1,256} + * \param hashlen message digest length (for RSA_RAW only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_pkcs1_verify( rsa_context *ctx, + int mode, + int hash_id, + int hashlen, + unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Free the components of an RSA key + */ +void rsa_free( rsa_context *ctx ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int rsa_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa.h */ diff --git a/package/utils/px5g-standalone/src/polarssl/sha1.h b/package/utils/px5g-standalone/src/polarssl/sha1.h new file mode 100644 index 0000000..3ca7dc3 --- /dev/null +++ b/package/utils/px5g-standalone/src/polarssl/sha1.h @@ -0,0 +1,150 @@ +/** + * \file sha1.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 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 + * OWNER 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. + */ +#ifndef POLARSSL_SHA1_H +#define POLARSSL_SHA1_H + +/** + * \brief SHA-1 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ +} +sha1_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void sha1_starts( sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_update( sha1_context *ctx, unsigned char *input, int ilen ); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ); + +/** + * \brief Output = SHA-1( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-1 checksum result + */ +void sha1( unsigned char *input, int ilen, unsigned char output[20] ); + +/** + * \brief Output = SHA-1( file contents ) + * + * \param path input file name + * \param output SHA-1 checksum result + * + * \return 0 if successful, 1 if fopen failed, + * or 2 if fread failed + */ +int sha1_file( char *path, unsigned char output[20] ); + +/** + * \brief SHA-1 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void sha1_hmac_starts( sha1_context *ctx, unsigned char *key, int keylen ); + +/** + * \brief SHA-1 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_hmac_update( sha1_context *ctx, unsigned char *input, int ilen ); + +/** + * \brief SHA-1 HMAC final digest + * + * \param ctx HMAC context + * \param output SHA-1 HMAC checksum result + */ +void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ); + +/** + * \brief Output = HMAC-SHA-1( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-SHA-1 result + */ +void sha1_hmac( unsigned char *key, int keylen, + unsigned char *input, int ilen, + unsigned char output[20] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int sha1_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* sha1.h */ diff --git a/package/utils/px5g-standalone/src/polarssl/timing.h b/package/utils/px5g-standalone/src/polarssl/timing.h new file mode 100644 index 0000000..62d627f --- /dev/null +++ b/package/utils/px5g-standalone/src/polarssl/timing.h @@ -0,0 +1,81 @@ +/** + * \file timing.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 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 + * OWNER 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. + */ +#ifndef POLARSSL_TIMING_H +#define POLARSSL_TIMING_H + +/** + * \brief timer structure + */ +struct hr_time +{ + unsigned char opaque[32]; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +extern int alarmed; + +/** + * \brief Return the CPU cycle counter value + */ +unsigned long hardclock( void ); + +/** + * \brief Return the elapsed time in milliseconds + * + * \param val points to a timer structure + * \param reset if set to 1, the timer is restarted + */ +unsigned long get_timer( struct hr_time *val, int reset ); + +/** + * \brief Setup an alarm clock + * + * \param seconds delay before the "alarmed" flag is set + */ +void set_alarm( int seconds ); + +/** + * \brief Sleep for a certain amount of time + */ +void m_sleep( int milliseconds ); + +#ifdef __cplusplus +} +#endif + +#endif /* timing.h */ diff --git a/package/utils/px5g-standalone/src/polarssl/x509.h b/package/utils/px5g-standalone/src/polarssl/x509.h new file mode 100644 index 0000000..908a1db --- /dev/null +++ b/package/utils/px5g-standalone/src/polarssl/x509.h @@ -0,0 +1,549 @@ +/** + * \file x509.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 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 + * OWNER 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. + */ +#ifndef POLARSSL_X509_H +#define POLARSSL_X509_H + +#include "polarssl/rsa.h" + +#define POLARSSL_ERR_ASN1_OUT_OF_DATA -0x0014 +#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG -0x0016 +#define POLARSSL_ERR_ASN1_INVALID_LENGTH -0x0018 +#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH -0x001A +#define POLARSSL_ERR_ASN1_INVALID_DATA -0x001C + +#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE -0x0020 +#define POLARSSL_ERR_X509_CERT_INVALID_PEM -0x0040 +#define POLARSSL_ERR_X509_CERT_INVALID_FORMAT -0x0060 +#define POLARSSL_ERR_X509_CERT_INVALID_VERSION -0x0080 +#define POLARSSL_ERR_X509_CERT_INVALID_SERIAL -0x00A0 +#define POLARSSL_ERR_X509_CERT_INVALID_ALG -0x00C0 +#define POLARSSL_ERR_X509_CERT_INVALID_NAME -0x00E0 +#define POLARSSL_ERR_X509_CERT_INVALID_DATE -0x0100 +#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY -0x0120 +#define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE -0x0140 +#define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS -0x0160 +#define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION -0x0180 +#define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG -0x01A0 +#define POLARSSL_ERR_X509_CERT_UNKNOWN_PK_ALG -0x01C0 +#define POLARSSL_ERR_X509_CERT_SIG_MISMATCH -0x01E0 +#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED -0x0200 +#define POLARSSL_ERR_X509_KEY_INVALID_PEM -0x0220 +#define POLARSSL_ERR_X509_KEY_INVALID_VERSION -0x0240 +#define POLARSSL_ERR_X509_KEY_INVALID_FORMAT -0x0260 +#define POLARSSL_ERR_X509_KEY_INVALID_ENC_IV -0x0280 +#define POLARSSL_ERR_X509_KEY_UNKNOWN_ENC_ALG -0x02A0 +#define POLARSSL_ERR_X509_KEY_PASSWORD_REQUIRED -0x02C0 +#define POLARSSL_ERR_X509_KEY_PASSWORD_MISMATCH -0x02E0 +#define POLARSSL_ERR_X509_POINT_ERROR -0x0300 +#define POLARSSL_ERR_X509_VALUE_TO_LENGTH -0x0320 + +#define BADCERT_EXPIRED 1 +#define BADCERT_REVOKED 2 +#define BADCERT_CN_MISMATCH 4 +#define BADCERT_NOT_TRUSTED 8 + +/* + * DER constants + */ +#define ASN1_BOOLEAN 0x01 +#define ASN1_INTEGER 0x02 +#define ASN1_BIT_STRING 0x03 +#define ASN1_OCTET_STRING 0x04 +#define ASN1_NULL 0x05 +#define ASN1_OID 0x06 +#define ASN1_UTF8_STRING 0x0C +#define ASN1_SEQUENCE 0x10 +#define ASN1_SET 0x11 +#define ASN1_PRINTABLE_STRING 0x13 +#define ASN1_T61_STRING 0x14 +#define ASN1_IA5_STRING 0x16 +#define ASN1_UTC_TIME 0x17 +#define ASN1_UNIVERSAL_STRING 0x1C +#define ASN1_BMP_STRING 0x1E +#define ASN1_PRIMITIVE 0x00 +#define ASN1_CONSTRUCTED 0x20 +#define ASN1_CONTEXT_SPECIFIC 0x80 + +/* + * various object identifiers + */ +#define X520_COMMON_NAME 3 +#define X520_COUNTRY 6 +#define X520_LOCALITY 7 +#define X520_STATE 8 +#define X520_ORGANIZATION 10 +#define X520_ORG_UNIT 11 +#define PKCS9_EMAIL 1 + +#define X509_OUTPUT_DER 0x01 +#define X509_OUTPUT_PEM 0x02 +#define PEM_LINE_LENGTH 72 +#define X509_ISSUER 0x01 +#define X509_SUBJECT 0x02 + +#define OID_X520 "\x55\x04" +#define OID_CN "\x55\x04\x03" +#define OID_PKCS1 "\x2A\x86\x48\x86\xF7\x0D\x01\x01" +#define OID_PKCS1_RSA "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01" +#define OID_PKCS1_RSA_SHA "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05" +#define OID_PKCS9 "\x2A\x86\x48\x86\xF7\x0D\x01\x09" +#define OID_PKCS9_EMAIL "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01" + +/* + * Structures for parsing X.509 certificates + */ +typedef struct _x509_buf +{ + int tag; + int len; + unsigned char *p; +} +x509_buf; + +typedef struct _x509_name +{ + x509_buf oid; + x509_buf val; + struct _x509_name *next; +} +x509_name; + +typedef struct _x509_time +{ + int year, mon, day; + int hour, min, sec; +} +x509_time; + +typedef struct _x509_cert +{ + x509_buf raw; + x509_buf tbs; + + int version; + x509_buf serial; + x509_buf sig_oid1; + + x509_buf issuer_raw; + x509_buf subject_raw; + + x509_name issuer; + x509_name subject; + + x509_time valid_from; + x509_time valid_to; + + x509_buf pk_oid; + rsa_context rsa; + + x509_buf issuer_id; + x509_buf subject_id; + x509_buf v3_ext; + + int ca_istrue; + int max_pathlen; + + x509_buf sig_oid2; + x509_buf sig; + + struct _x509_cert *next; +} +x509_cert; + +/* + * Structures for writing X.509 certificates + */ +typedef struct _x509_node +{ + unsigned char *data; + unsigned char *p; + unsigned char *end; + + size_t len; +} +x509_node; + +typedef struct _x509_raw +{ + x509_node raw; + x509_node tbs; + + x509_node version; + x509_node serial; + x509_node tbs_signalg; + x509_node issuer; + x509_node validity; + x509_node subject; + x509_node subpubkey; + + x509_node signalg; + x509_node sign; +} +x509_raw; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Parse one or more certificates and add them + * to the chained list + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 error code + */ +int x509parse_crt( x509_cert *crt, unsigned char *buf, int buflen ); + +/** + * \brief Load one or more certificates and add them + * to the chained list + * + * \param chain points to the start of the chain + * \param path filename to read the certificates from + * + * \return 0 if successful, or a specific X509 error code + */ +int x509parse_crtfile( x509_cert *crt, char *path ); + +/** + * \brief Parse a private RSA key + * + * \param rsa RSA context to be initialized + * \param buf input buffer + * \param buflen size of the buffer + * \param pwd password for decryption (optional) + * \param pwdlen size of the password + * + * \return 0 if successful, or a specific X509 error code + */ +int x509parse_key( rsa_context *rsa, + unsigned char *buf, int buflen, + unsigned char *pwd, int pwdlen ); + +/** + * \brief Load and parse a private RSA key + * + * \param rsa RSA context to be initialized + * \param path filename to read the private key from + * \param pwd password to decrypt the file (can be NULL) + * + * \return 0 if successful, or a specific X509 error code + */ +int x509parse_keyfile( rsa_context *rsa, char *path, char *password ); + +/** + * \brief Store the certificate DN in printable form into buf; + * no more than (end - buf) characters will be written. + */ +int x509parse_dn_gets( char *buf, char *end, x509_name *dn ); + +/** + * \brief Returns an informational string about the + * certificate. + */ +char *x509parse_cert_info( char *prefix, x509_cert *crt ); + +/** + * \brief Return 0 if the certificate is still valid, + * or BADCERT_EXPIRED + */ +int x509parse_expired( x509_cert *crt ); + +/** + * \brief Verify the certificate signature + * + * \param crt a certificate to be verified + * \param trust_ca the trusted CA chain + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * + * \return 0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED, + * in which case *flags will have one or more of + * the following values set: + * BADCERT_EXPIRED -- + * BADCERT_REVOKED -- + * BADCERT_CN_MISMATCH -- + * BADCERT_NOT_TRUSTED + * + * \note TODO: add two arguments, depth and crl + */ +int x509parse_verify( x509_cert *crt, + x509_cert *trust_ca, + char *cn, int *flags ); + +/** + * \brief Unallocate all certificate data + */ +void x509_free( x509_cert *crt ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int x509_self_test( int verbose ); + +/** + * \brief Write a certificate info file + * + * \param chain points to the raw certificate data + * \param path filename to write the certificate to + * \param format X509_OUTPUT_DER or X509_OUTPUT_PEM + * + * \return 0 if successful, or a specific X509 error code + */ +int x509write_crtfile( x509_raw *chain, + unsigned char *path, + int format ); + +/** + * \brief Write a certificate signing request message format file + * + * \param chain points to the raw certificate (with x509write_create_csr) data + * \param path filename to write the certificate to + * \param format X509_OUTPUT_DER or X509_OUTPUT_PEM + * + * \return 0 if successful, or a specific X509 error code + */ +int x509write_csrfile( x509_raw *chain, + unsigned char *path, + int format ); + +/* + * \brief Write a private RSA key into a file + * + * \param rsa points to an RSA key + * \param path filename to write the key to + * \param format X509_OUTPUT_DER or X509_OUTPUT_PEM + * + * \return 0 if successful, or a specific X509 error code + */ +int x509write_keyfile( rsa_context *rsa, + char *path, + int format ); + +/** + * \brief Add a public key to certificate + * + * \param chain points to the raw certificate data + * \param pubkey points to an RSA key + * + * \return 0 if successful, or a specific X509 error code + */ +int x509write_add_pubkey( x509_raw *chain, rsa_context *pubkey ); + +/** + * \brief Create x509 subject/issuer field to raw certificate + * from string or CA cert. Make string NULL if you will + * use the CA copy function or make CA NULL then used + * the string parse. + * + * \param chain points to the raw certificate data + * \param names a string that can hold (separete with ";"): + * CN=CommonName + * -- O=Organization + * -- OU=OrgUnit + * -- ST=State + * -- L=Locality + * -- R=Email + * -- C=Country + * . Make that NULL if you didn't need that. + * \param flag flag is X509_ISSUER or X509_SUBJECT that defined + * where change + * \param ca the certificate for copy data. Make that NULL if you + * didn't need that. + * \param ca_flag set the ca field from copy to crt + * + * \return 0 if successful, or a specific X509 error code + */ +int x509write_add_customize ( x509_raw *crt, + unsigned char *names, + int flag, + x509_cert *ca, + int ca_flag ); + +/** +* \brief Add x509 issuer field +* +* \param chain points to the raw certificate data +* \param issuer a string holding (separete with ";"): +* CN=CommonName +* -- O=Organization +* -- OU=OrgUnit +* -- ST=State +* -- L=Locality +* -- R=Email +* -- C=Country +* . Set this to NULL if not needed. +* \return 0 if successful, or a specific X509 error code +*/ +int x509write_add_issuer( x509_raw *crt, unsigned char *issuer); + +/** + * \brief Add x509 subject field + * + * \param chain points to the raw certificate data + * \param subject a string holding (separete with ";"): + * CN=CommonName + * -- O=Organization + * -- OU=OrgUnit + * -- ST=State + * -- L=Locality + * -- R=Email + * -- C=Country + * . Set this to NULL if not needed. + * \return 0 if successful, or a specific X509 error code + */ +int x509write_add_subject( x509_raw *crt, unsigned char *subject); + +/** +* \brief Copy x509 issuer field from another certificate +* +* \param chain points to the raw certificate data +* \param from_crt the certificate whose issuer is to be copied. +* \return 0 if successful, or a specific X509 error code +*/ +int x509write_copy_issuer(x509_raw *crt, x509_cert *from_crt); + +/** +* \brief Copy x509 subject field from another certificate +* +* \param chain points to the raw certificate data +* \param from_crt the certificate whose subject is to be copied. +* \return 0 if successful, or a specific X509 error code +*/ +int x509write_copy_subject(x509_raw *crt, x509_cert *from_crt); + +/** +* \brief Copy x509 issuer field from the subject of another certificate +* +* \param chain points to the raw certificate data +* \param from_crt the certificate whose subject is to be copied. +* \return 0 if successful, or a specific X509 error code +*/ +int x509write_copy_issuer_from_subject(x509_raw *crt, x509_cert *from_crt); + +/** +* \brief Copy x509 subject field from the issuer of another certificate +* +* \param chain points to the raw certificate data +* \param from_crt the certificate whose issuer is to be copied. +* \return 0 if successful, or a specific X509 error code +*/ +int x509write_copy_subject_from_issuer(x509_raw *crt, x509_cert *from_crt); + +/** + * \brief Create x509 validity time in UTC + * + * \param chain points to the raw certificate data + * \param before valid not before in format YYYY-MM-DD hh:mm:ss + * \param after valid not after in format YYYY-MM-DD hh:mm:ss + * + * \return 0 if successful, or a specific X509 error code + */ +int x509write_add_validity( x509_raw *crt, + unsigned char *before, + unsigned char *after ); + +/** + * \brief Create a self-signed certificate + * + * \param chain points to the raw certificate data + * \param rsa a private key to sign the certificate + * + * \return 0 if successful, or a specific X509 error code + */ +int x509write_create_selfsign( x509_raw *crt, rsa_context *raw ); + +/** + * \brief Create a certificate + * + * \param chain points to the raw certificate data + * \param rsa a private key to sign the certificate + * + * \return 0 if successful, or a specific X509 error code + */ +int x509write_create_sign( x509_raw *crt, rsa_context *raw ); + +/** + * \brief Create a certificate signing request + * + * \param chain points to the raw certificate data. Didn't use the + * same chain that u have use for certificate. + * \param privkey a rsa private key + * + * \return 0 if successful, or a specific X509 error code + */ +int x509write_create_csr( x509_raw *chain, rsa_context *privkey ); + +/** + * \brief Serialize an rsa key into DER + * + * \param rsa a rsa key for output + * \param node a x509 node for write into + * + * \return 0 if successful, or a specific X509 error code + */ +int x509write_serialize_key( rsa_context *rsa, x509_node *node ); + +/** + * \brief Unallocate all raw certificate data + */ +void x509write_free_raw( x509_raw *crt ); + +/** + * \brief Allocate all raw certificate data + */ +void x509write_init_raw( x509_raw *crt ); + +/** + * \brief Unallocate all node certificate data + */ +void x509write_free_node( x509_node *crt_node ); + +/** + * \brief Allocate all node certificate data + */ +void x509write_init_node( x509_node *crt_node ); + +#ifdef __cplusplus +} +#endif + +#endif /* x509.h */ diff --git a/package/utils/px5g-standalone/src/px5g.c b/package/utils/px5g-standalone/src/px5g.c new file mode 100644 index 0000000..34ab34f --- /dev/null +++ b/package/utils/px5g-standalone/src/px5g.c @@ -0,0 +1,213 @@ +/* + * px5g - Embedded x509 key and certificate generator based on PolarSSL + * + * Copyright (C) 2009 Steven Barth <steven@midlink.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License, version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <limits.h> +#include <fcntl.h> +#include <unistd.h> +#include "polarssl/bignum.h" +#include "polarssl/x509.h" +#include "polarssl/rsa.h" + +#define PX5G_VERSION "0.1" +#define PX5G_COPY "Copyright (c) 2009 Steven Barth <steven@midlink.org>" +#define PX5G_LICENSE "Licensed under the GNU Lesser General Public License v2.1" + +static int urandom_fd; + +static int _urandom(void *ctx) +{ + int ret; + read(urandom_fd, &ret, sizeof(ret)); + return ret; +} + + +int rsakey(char **arg) { + rsa_context rsa; + + unsigned int ksize = 512; + int exp = 65537; + char *path = NULL; + int flag = X509_OUTPUT_PEM; + + while (*arg && **arg == '-') { + if (!strcmp(*arg, "-out") && arg[1]) { + path = arg[1]; + arg++; + } else if (!strcmp(*arg, "-3")) { + exp = 3; + } else if (!strcmp(*arg, "-der")) { + flag = X509_OUTPUT_DER; + } + arg++; + } + + if (*arg) { + ksize = (unsigned int)atoi(*arg); + } + + rsa_init(&rsa, RSA_PKCS_V15, 0, _urandom, NULL); + + fprintf(stderr, "Generating RSA private key, %i bit long modulus\n", ksize); + if (rsa_gen_key(&rsa, ksize, exp)) { + fprintf(stderr, "error: key generation failed\n"); + return 1; + } + + if (x509write_keyfile(&rsa, path, flag)) { + fprintf(stderr, "error: I/O error\n"); + return 1; + } + + rsa_free(&rsa); + return 0; +} + +int selfsigned(char **arg) { + rsa_context rsa; + x509_node node; + + char *subject = ""; + unsigned int ksize = 512; + int exp = 65537; + unsigned int days = 30; + char *keypath = NULL, *certpath = NULL; + int flag = X509_OUTPUT_PEM; + time_t from = time(NULL), to; + char fstr[20], tstr[20]; + + while (*arg && **arg == '-') { + if (!strcmp(*arg, "-der")) { + flag = X509_OUTPUT_DER; + } else if (!strcmp(*arg, "-newkey") && arg[1]) { + if (strncmp(arg[1], "rsa:", 4)) { + fprintf(stderr, "error: invalid algorithm"); + return 1; + } + ksize = (unsigned int)atoi(arg[1] + 4); + arg++; + } else if (!strcmp(*arg, "-days") && arg[1]) { + days = (unsigned int)atoi(arg[1]); + arg++; + } else if (!strcmp(*arg, "-keyout") && arg[1]) { + keypath = arg[1]; + arg++; + } else if (!strcmp(*arg, "-out") && arg[1]) { + certpath = arg[1]; + arg++; + } else if (!strcmp(*arg, "-subj") && arg[1]) { + if (arg[1][0] != '/' || strchr(arg[1], ';')) { + fprintf(stderr, "error: invalid subject"); + return 1; + } + subject = calloc(strlen(arg[1]) + 1, 1); + char *oldc = arg[1] + 1, *newc = subject, *delim; + do { + delim = strchr(oldc, '='); + if (!delim) { + fprintf(stderr, "error: invalid subject"); + return 1; + } + memcpy(newc, oldc, delim - oldc + 1); + newc += delim - oldc + 1; + oldc = delim + 1; + + delim = strchr(oldc, '/'); + if (!delim) { + delim = arg[1] + strlen(arg[1]); + } + memcpy(newc, oldc, delim - oldc); + newc += delim - oldc; + *newc++ = ';'; + oldc = delim + 1; + } while(*delim); + arg++; + } + arg++; + } + + rsa_init(&rsa, RSA_PKCS_V15, 0, _urandom, NULL); + x509write_init_node(&node); + fprintf(stderr, "Generating RSA private key, %i bit long modulus\n", ksize); + if (rsa_gen_key(&rsa, ksize, exp)) { + fprintf(stderr, "error: key generation failed\n"); + return 1; + } + + if (keypath) { + if (x509write_keyfile(&rsa, keypath, flag)) { + fprintf(stderr, "error: I/O error\n"); + return 1; + } + } + + from = (from < 1000000000) ? 1000000000 : from; + strftime(fstr, sizeof(fstr), "%F %H:%M:%S", gmtime(&from)); + to = from + 60 * 60 * 24 * days; + if (to < from) + to = INT_MAX; + strftime(tstr, sizeof(tstr), "%F %H:%M:%S", gmtime(&to)); + + x509_raw cert; + x509write_init_raw(&cert); + x509write_add_pubkey(&cert, &rsa); + x509write_add_subject(&cert, (unsigned char*)subject); + x509write_add_validity(&cert, (unsigned char*)fstr, (unsigned char*)tstr); + fprintf(stderr, "Generating selfsigned certificate with subject '%s'" + " and validity %s-%s\n", subject, fstr, tstr); + if (x509write_create_selfsign(&cert, &rsa)) { + fprintf(stderr, "error: certificate generation failed\n"); + } + + if (x509write_crtfile(&cert, (unsigned char*)certpath, flag)) { + fprintf(stderr, "error: I/O error\n"); + return 1; + } + + x509write_free_raw(&cert); + rsa_free(&rsa); + return 0; +} + +int main(int argc, char *argv[]) { + urandom_fd = open("/dev/urandom", O_RDONLY); + if (urandom_fd < 0) { + perror("open(/dev/urandom)"); + return 1; + } + + if (!argv[1]) { + //Usage + } else if (!strcmp(argv[1], "rsakey")) { + return rsakey(argv+2); + } else if (!strcmp(argv[1], "selfsigned")) { + return selfsigned(argv+2); + } + + fprintf(stderr, + "PX5G X.509 Certificate Generator Utility v" PX5G_VERSION "\n" PX5G_COPY + "\nbased on PolarSSL by Christophe Devine and Paul Bakker\n\n"); + fprintf(stderr, "Usage: %s [rsakey|selfsigned]\n", *argv); + return 1; +} diff --git a/package/utils/px5g/Makefile b/package/utils/px5g/Makefile new file mode 100644 index 0000000..8677a8b --- /dev/null +++ b/package/utils/px5g/Makefile @@ -0,0 +1,44 @@ +# +# Copyright (C) 2010-2015 Jo-Philipp Wich <jow@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:=px5g +PKG_RELEASE:=3 + +PKG_USE_MIPS16:=0 + +include $(INCLUDE_DIR)/package.mk + +define Package/px5g + SECTION:=utils + CATEGORY:=Utilities + TITLE:=X.509 certificate generator (using PolarSSL) + MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org> + DEPENDS:=+libpolarssl +endef + +define Package/px5g/description + Px5g is a tiny standalone X.509 certificate generator. + It suitable to create key files and certificates in DER + and PEM format for use with stunnel, uhttpd and others. +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) +endef + +define Build/Compile + $(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/px5g px5g.c -lpolarssl +endef + +define Package/px5g/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/px5g $(1)/usr/sbin/px5g +endef + +$(eval $(call BuildPackage,px5g)) diff --git a/package/utils/px5g/px5g.c b/package/utils/px5g/px5g.c new file mode 100644 index 0000000..eec8fd3 --- /dev/null +++ b/package/utils/px5g/px5g.c @@ -0,0 +1,273 @@ +/* + * px5g - Embedded x509 key and certificate generator based on PolarSSL + * + * Copyright (C) 2009 Steven Barth <steven@midlink.org> + * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License, version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <sys/types.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <limits.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdbool.h> + +#include <polarssl/bignum.h> +#include <polarssl/x509_crt.h> +#include <polarssl/rsa.h> + +#define PX5G_VERSION "0.2" +#define PX5G_COPY "Copyright (c) 2009 Steven Barth <steven@midlink.org>" +#define PX5G_LICENSE "Licensed under the GNU Lesser General Public License v2.1" + +static int urandom_fd; +static char buf[16384]; + +static int _urandom(void *ctx, unsigned char *out, size_t len) +{ + read(urandom_fd, out, len); + return 0; +} + +static void write_file(const char *path, int len, bool pem) +{ + FILE *f = stdout; + const char *buf_start = buf; + + if (!pem) + buf_start += sizeof(buf) - len; + + if (!len) { + fprintf(stderr, "No data to write\n"); + exit(1); + } + + if (!f) { + fprintf(stderr, "error: I/O error\n"); + exit(1); + } + + if (path) + f = fopen(path, "w"); + + fwrite(buf_start, 1, len, f); + fclose(f); +} + +static void write_key(pk_context *key, const char *path, bool pem) +{ + int len = 0; + + if (pem) { + if (pk_write_key_pem(key, (void *) buf, sizeof(buf)) == 0) + len = strlen(buf); + } else { + len = pk_write_key_der(key, (void *) buf, sizeof(buf)); + if (len < 0) + len = 0; + } + + write_file(path, len, pem); +} + +static void gen_key(pk_context *key, int ksize, int exp, bool pem) +{ + pk_init(key); + pk_init_ctx(key, pk_info_from_type(POLARSSL_PK_RSA)); + fprintf(stderr, "Generating RSA private key, %i bit long modulus\n", ksize); + if (rsa_gen_key(pk_rsa(*key), _urandom, NULL, ksize, exp)) { + fprintf(stderr, "error: key generation failed\n"); + exit(1); + } +} + +int rsakey(char **arg) +{ + pk_context key; + unsigned int ksize = 512; + int exp = 65537; + char *path = NULL; + bool pem = true; + + while (*arg && **arg == '-') { + if (!strcmp(*arg, "-out") && arg[1]) { + path = arg[1]; + arg++; + } else if (!strcmp(*arg, "-3")) { + exp = 3; + } else if (!strcmp(*arg, "-der")) { + pem = false; + } + arg++; + } + + if (*arg) + ksize = (unsigned int)atoi(*arg); + + gen_key(&key, ksize, exp, pem); + write_key(&key, path, pem); + + pk_free(&key); + + return 0; +} + +int selfsigned(char **arg) +{ + pk_context key; + x509write_cert cert; + mpi serial; + + char *subject = ""; + unsigned int ksize = 512; + int exp = 65537; + unsigned int days = 30; + char *keypath = NULL, *certpath = NULL; + bool pem = true; + time_t from = time(NULL), to; + char fstr[20], tstr[20], sstr[17]; + int len; + + while (*arg && **arg == '-') { + if (!strcmp(*arg, "-der")) { + pem = false; + } else if (!strcmp(*arg, "-newkey") && arg[1]) { + if (strncmp(arg[1], "rsa:", 4)) { + fprintf(stderr, "error: invalid algorithm"); + return 1; + } + ksize = (unsigned int)atoi(arg[1] + 4); + arg++; + } else if (!strcmp(*arg, "-days") && arg[1]) { + days = (unsigned int)atoi(arg[1]); + arg++; + } else if (!strcmp(*arg, "-keyout") && arg[1]) { + keypath = arg[1]; + arg++; + } else if (!strcmp(*arg, "-out") && arg[1]) { + certpath = arg[1]; + arg++; + } else if (!strcmp(*arg, "-subj") && arg[1]) { + if (arg[1][0] != '/' || strchr(arg[1], ';')) { + fprintf(stderr, "error: invalid subject"); + return 1; + } + subject = calloc(strlen(arg[1]) + 1, 1); + char *oldc = arg[1] + 1, *newc = subject, *delim; + do { + delim = strchr(oldc, '='); + if (!delim) { + fprintf(stderr, "error: invalid subject"); + return 1; + } + memcpy(newc, oldc, delim - oldc + 1); + newc += delim - oldc + 1; + oldc = delim + 1; + + delim = strchr(oldc, '/'); + if (!delim) { + delim = arg[1] + strlen(arg[1]); + } + memcpy(newc, oldc, delim - oldc); + newc += delim - oldc; + *newc++ = ','; + oldc = delim + 1; + } while(*delim); + arg++; + } + arg++; + } + + gen_key(&key, ksize, exp, pem); + + if (keypath) + write_key(&key, keypath, pem); + + from = (from < 1000000000) ? 1000000000 : from; + strftime(fstr, sizeof(fstr), "%Y%m%d%H%M%S", gmtime(&from)); + to = from + 60 * 60 * 24 * days; + if (to < from) + to = INT_MAX; + strftime(tstr, sizeof(tstr), "%Y%m%d%H%M%S", gmtime(&to)); + + fprintf(stderr, "Generating selfsigned certificate with subject '%s'" + " and validity %s-%s\n", subject, fstr, tstr); + + x509write_crt_init(&cert); + x509write_crt_set_md_alg(&cert, POLARSSL_MD_SHA1); + x509write_crt_set_issuer_key(&cert, &key); + x509write_crt_set_subject_key(&cert, &key); + x509write_crt_set_subject_name(&cert, subject); + x509write_crt_set_issuer_name(&cert, subject); + x509write_crt_set_validity(&cert, fstr, tstr); + x509write_crt_set_basic_constraints(&cert, 0, -1); + x509write_crt_set_subject_key_identifier(&cert); + x509write_crt_set_authority_key_identifier(&cert); + + _urandom(NULL, buf, 8); + for (len = 0; len < 8; len++) + sprintf(sstr + len*2, "%02x", (unsigned char) buf[len]); + + mpi_init(&serial); + mpi_read_string(&serial, 16, sstr); + x509write_crt_set_serial(&cert, &serial); + + if (pem) { + if (x509write_crt_pem(&cert, (void *) buf, sizeof(buf), _urandom, NULL) < 0) { + fprintf(stderr, "Failed to generate certificate\n"); + return 1; + } + + len = strlen(buf); + } else { + len = x509write_crt_der(&cert, (void *) buf, sizeof(buf), _urandom, NULL); + if (len < 0) { + fprintf(stderr, "Failed to generate certificate: %d\n", len); + return 1; + } + } + write_file(certpath, len, pem); + + x509write_crt_free(&cert); + mpi_free(&serial); + pk_free(&key); + + return 0; +} + +int main(int argc, char *argv[]) +{ + urandom_fd = open("/dev/urandom", O_RDONLY); + + if (!argv[1]) { + //Usage + } else if (!strcmp(argv[1], "rsakey")) { + return rsakey(argv+2); + } else if (!strcmp(argv[1], "selfsigned")) { + return selfsigned(argv+2); + } + + fprintf(stderr, + "PX5G X.509 Certificate Generator Utility v" PX5G_VERSION "\n" PX5G_COPY + "\nbased on PolarSSL by Christophe Devine and Paul Bakker\n\n"); + fprintf(stderr, "Usage: %s [rsakey|selfsigned]\n", *argv); + return 1; +} diff --git a/package/utils/spidev_test/Makefile b/package/utils/spidev_test/Makefile new file mode 100644 index 0000000..807039a --- /dev/null +++ b/package/utils/spidev_test/Makefile @@ -0,0 +1,43 @@ +# +# Copyright (C) 2009 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:=spidev-test +PKG_RELEASE:=$(LINUX_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define Package/spidev-test + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=+kmod-spi-dev + TITLE:=SPI testing utility + VERSION:=$(LINUX_VERSION)-$(PKG_RELEASE) + URL:=http://www.kernel.org + MAINTAINER:=Florian Fainelli <florian@openwrt.org> +endef + +define Package/spidev-test/description + SPI testing utility. +endef + +define Build/Prepare +endef + +define Build/Compile + $(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/spidev_test \ + $(LINUX_DIR)/Documentation/spi/spidev_test.c +endef + +define Package/spidev-test/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/spidev_test $(1)/sbin/ +endef + +$(eval $(call BuildPackage,spidev-test)) diff --git a/package/utils/ubi-utils/Makefile b/package/utils/ubi-utils/Makefile new file mode 100644 index 0000000..b89a5d2 --- /dev/null +++ b/package/utils/ubi-utils/Makefile @@ -0,0 +1,61 @@ +# +# Copyright (C) 2009-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:=ubi-utils +PKG_REV:=7d2839b8dede3ae368780364b4a07473d2303219 +PKG_VERSION:=1.5.1 +PKG_RELEASE:=2 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=git://git.infradead.org/mtd-utils.git +PKG_SOURCE_PROTO:=git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=$(PKG_REV) +PKG_MIRROR_MD5SUM:=69b68adcfcbe786584771e5978534ab4 + +PKG_INSTALL:=1 + +PKG_BUILD_DEPENDS:=util-linux liblzo zlib + +PKG_LICENSE:=GPLv2 +PKG_LICENSE_FILES:= + +PKG_MAINTAINER:=John Crispin <blogic@openwrt.org> + +include $(INCLUDE_DIR)/package.mk + +define Package/ubi-utils + TITLE:=Utilities for ubi info/debug + SECTION:=utils + CATEGORY:=Utilities + URL:=http://www.linux-mtd.infradead.org/ + DEPENDS:=@NAND_SUPPORT +endef + +define Package/ubi-utils/description + Utilities for manipulating memory technology devices. +endef + +MAKE_FLAGS += \ + DESTDIR="$(PKG_INSTALL_DIR)" \ + BUILDDIR="$(PKG_BUILD_DIR)" \ + LDLIBS+="$(LIBGCC_S)" \ + WITHOUT_XATTR=1 \ + WITHOUT_LZO=1 + +define Package/ubi-utils/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) \ + $(PKG_INSTALL_DIR)/usr/sbin/{ubiattach,ubicrc32,ubiblock,ubidetach,ubiformat,ubimkvol} $(1)/usr/sbin/ + $(INSTALL_BIN) \ + $(PKG_INSTALL_DIR)/usr/sbin/{ubinfo,ubinize,ubirename,ubirmvol,ubirsvol,ubiupdatevol} $(1)/usr/sbin/ +endef + + +$(eval $(call BuildPackage,ubi-utils)) diff --git a/package/utils/ubi-utils/patches/010-fix-rpmatch.patch b/package/utils/ubi-utils/patches/010-fix-rpmatch.patch new file mode 100644 index 0000000..9d0de7f --- /dev/null +++ b/package/utils/ubi-utils/patches/010-fix-rpmatch.patch @@ -0,0 +1,19 @@ +--- a/include/common.h ++++ b/include/common.h +@@ -137,10 +137,12 @@ static inline bool prompt(const char *ms + } + + if (strcmp("\n", line) != 0) { +- switch (rpmatch(line)) { +- case 0: ret = false; break; +- case 1: ret = true; break; +- case -1: ++ switch (line[0]) { ++ case 'N': ++ case 'n': ret = false; break; ++ case 'Y': ++ case 'y': ret = true; break; ++ default: + puts("unknown response; please try again"); + continue; + } diff --git a/package/utils/ubi-utils/patches/100-fix_includes.patch b/package/utils/ubi-utils/patches/100-fix_includes.patch new file mode 100644 index 0000000..44421d0 --- /dev/null +++ b/package/utils/ubi-utils/patches/100-fix_includes.patch @@ -0,0 +1,30 @@ +--- a/lib/libfec.c ++++ b/lib/libfec.c +@@ -45,6 +45,7 @@ + #include <stdio.h> + #include <stdlib.h> + #include <string.h> ++#include <sys/types.h> + + /* + * stuff used for testing purposes only +--- a/serve_image.c ++++ b/serve_image.c +@@ -3,7 +3,6 @@ + + #include <time.h> + #include <errno.h> +-#include <error.h> + #include <netdb.h> + #include <stdio.h> + #include <stdlib.h> +--- a/recv_image.c ++++ b/recv_image.c +@@ -4,7 +4,6 @@ + #define _BSD_SOURCE /* struct ip_mreq */ + + #include <errno.h> +-#include <error.h> + #include <stdio.h> + #include <netdb.h> + #include <stdlib.h> diff --git a/package/utils/ubi-utils/patches/110-gcc5-fix.patch b/package/utils/ubi-utils/patches/110-gcc5-fix.patch new file mode 100644 index 0000000..d871d67 --- /dev/null +++ b/package/utils/ubi-utils/patches/110-gcc5-fix.patch @@ -0,0 +1,41 @@ +--- a/mkfs.ubifs/hashtable/hashtable_itr.c ++++ b/mkfs.ubifs/hashtable/hashtable_itr.c +@@ -35,18 +35,6 @@ hashtable_iterator(struct hashtable *h) + } + + /*****************************************************************************/ +-/* key - return the key of the (key,value) pair at the current position */ +-/* value - return the value of the (key,value) pair at the current position */ +- +-void * +-hashtable_iterator_key(struct hashtable_itr *i) +-{ return i->e->k; } +- +-void * +-hashtable_iterator_value(struct hashtable_itr *i) +-{ return i->e->v; } +- +-/*****************************************************************************/ + /* advance - advance the iterator to the next element + * returns zero if advanced to end of table */ + +--- a/mkfs.ubifs/hashtable/hashtable_itr.h ++++ b/mkfs.ubifs/hashtable/hashtable_itr.h +@@ -28,7 +28,7 @@ hashtable_iterator(struct hashtable *h); + /* hashtable_iterator_key + * - return the value of the (key,value) pair at the current position */ + +-extern inline void * ++static inline void * + hashtable_iterator_key(struct hashtable_itr *i) + { + return i->e->k; +@@ -37,7 +37,7 @@ hashtable_iterator_key(struct hashtable_ + /*****************************************************************************/ + /* value - return the value of the (key,value) pair at the current position */ + +-extern inline void * ++static inline void * + hashtable_iterator_value(struct hashtable_itr *i) + { + return i->e->v; diff --git a/package/utils/ubi-utils/patches/130-lzma_jffs2.patch b/package/utils/ubi-utils/patches/130-lzma_jffs2.patch new file mode 100644 index 0000000..8c3794d --- /dev/null +++ b/package/utils/ubi-utils/patches/130-lzma_jffs2.patch @@ -0,0 +1,5029 @@ +--- a/Makefile ++++ b/Makefile +@@ -3,7 +3,7 @@ + + VERSION = 1.5.1 + +-CPPFLAGS += -D_GNU_SOURCE -I./include -I$(BUILDDIR)/include -I./ubi-utils/include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS) $(UUIDCPPFLAGS) ++CPPFLAGS += -D_GNU_SOURCE -I./include -I$(BUILDDIR)/include -I./ubi-utils/include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS) $(UUIDCPPFLAGS) -I./include/linux/lzma + + ifeq ($(WITHOUT_XATTR), 1) + CPPFLAGS += -DWITHOUT_XATTR +@@ -84,7 +84,7 @@ $(BUILDDIR)/include/version.h.tmp: + # + # Utils in top level + # +-obj-mkfs.jffs2 = compr_rtime.o compr_zlib.o compr_lzo.o compr.o rbtree.o ++obj-mkfs.jffs2 = compr_rtime.o compr_zlib.o $(if $(WITHOUT_LZO),,compr_lzo.o) compr_lzma.o lzma/LzFind.o lzma/LzmaEnc.o lzma/LzmaDec.o compr.o rbtree.o + LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS) + LDLIBS_mkfs.jffs2 = -lz $(LZOLDLIBS) + +--- a/compr.c ++++ b/compr.c +@@ -520,6 +520,9 @@ int jffs2_compressors_init(void) + #ifdef CONFIG_JFFS2_LZO + jffs2_lzo_init(); + #endif ++#ifdef CONFIG_JFFS2_LZMA ++ jffs2_lzma_init(); ++#endif + return 0; + } + +@@ -534,5 +537,8 @@ int jffs2_compressors_exit(void) + #ifdef CONFIG_JFFS2_LZO + jffs2_lzo_exit(); + #endif ++#ifdef CONFIG_JFFS2_LZMA ++ jffs2_lzma_exit(); ++#endif + return 0; + } +--- a/compr.h ++++ b/compr.h +@@ -18,13 +18,14 @@ + + #define CONFIG_JFFS2_ZLIB + #define CONFIG_JFFS2_RTIME +-#define CONFIG_JFFS2_LZO ++#define CONFIG_JFFS2_LZMA + + #define JFFS2_RUBINMIPS_PRIORITY 10 + #define JFFS2_DYNRUBIN_PRIORITY 20 + #define JFFS2_RTIME_PRIORITY 50 +-#define JFFS2_ZLIB_PRIORITY 60 +-#define JFFS2_LZO_PRIORITY 80 ++#define JFFS2_LZMA_PRIORITY 70 ++#define JFFS2_ZLIB_PRIORITY 80 ++#define JFFS2_LZO_PRIORITY 90 + + #define JFFS2_COMPR_MODE_NONE 0 + #define JFFS2_COMPR_MODE_PRIORITY 1 +@@ -115,5 +116,10 @@ void jffs2_rtime_exit(void); + int jffs2_lzo_init(void); + void jffs2_lzo_exit(void); + #endif ++#ifdef CONFIG_JFFS2_LZMA ++int jffs2_lzma_init(void); ++void jffs2_lzma_exit(void); ++#endif ++ + + #endif /* __JFFS2_COMPR_H__ */ +--- /dev/null ++++ b/compr_lzma.c +@@ -0,0 +1,128 @@ ++/* ++ * JFFS2 -- Journalling Flash File System, Version 2. ++ * ++ * For licensing information, see the file 'LICENCE' in this directory. ++ * ++ * JFFS2 wrapper to the LZMA C SDK ++ * ++ */ ++ ++#include <linux/lzma.h> ++#include "compr.h" ++ ++#ifdef __KERNEL__ ++ static DEFINE_MUTEX(deflate_mutex); ++#endif ++ ++CLzmaEncHandle *p; ++Byte propsEncoded[LZMA_PROPS_SIZE]; ++SizeT propsSize = sizeof(propsEncoded); ++ ++STATIC void lzma_free_workspace(void) ++{ ++ LzmaEnc_Destroy(p, &lzma_alloc, &lzma_alloc); ++} ++ ++STATIC int INIT lzma_alloc_workspace(CLzmaEncProps *props) ++{ ++ if ((p = (CLzmaEncHandle *)LzmaEnc_Create(&lzma_alloc)) == NULL) ++ { ++ PRINT_ERROR("Failed to allocate lzma deflate workspace\n"); ++ return -ENOMEM; ++ } ++ ++ if (LzmaEnc_SetProps(p, props) != SZ_OK) ++ { ++ lzma_free_workspace(); ++ return -1; ++ } ++ ++ if (LzmaEnc_WriteProperties(p, propsEncoded, &propsSize) != SZ_OK) ++ { ++ lzma_free_workspace(); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++STATIC int jffs2_lzma_compress(unsigned char *data_in, unsigned char *cpage_out, ++ uint32_t *sourcelen, uint32_t *dstlen, void *model) ++{ ++ SizeT compress_size = (SizeT)(*dstlen); ++ int ret; ++ ++ #ifdef __KERNEL__ ++ mutex_lock(&deflate_mutex); ++ #endif ++ ++ ret = LzmaEnc_MemEncode(p, cpage_out, &compress_size, data_in, *sourcelen, ++ 0, NULL, &lzma_alloc, &lzma_alloc); ++ ++ #ifdef __KERNEL__ ++ mutex_unlock(&deflate_mutex); ++ #endif ++ ++ if (ret != SZ_OK) ++ return -1; ++ ++ *dstlen = (uint32_t)compress_size; ++ ++ return 0; ++} ++ ++STATIC int jffs2_lzma_decompress(unsigned char *data_in, unsigned char *cpage_out, ++ uint32_t srclen, uint32_t destlen, void *model) ++{ ++ int ret; ++ SizeT dl = (SizeT)destlen; ++ SizeT sl = (SizeT)srclen; ++ ELzmaStatus status; ++ ++ ret = LzmaDecode(cpage_out, &dl, data_in, &sl, propsEncoded, ++ propsSize, LZMA_FINISH_ANY, &status, &lzma_alloc); ++ ++ if (ret != SZ_OK || status == LZMA_STATUS_NOT_FINISHED || dl != (SizeT)destlen) ++ return -1; ++ ++ return 0; ++} ++ ++static struct jffs2_compressor jffs2_lzma_comp = { ++ .priority = JFFS2_LZMA_PRIORITY, ++ .name = "lzma", ++ .compr = JFFS2_COMPR_LZMA, ++ .compress = &jffs2_lzma_compress, ++ .decompress = &jffs2_lzma_decompress, ++ .disabled = 0, ++}; ++ ++int INIT jffs2_lzma_init(void) ++{ ++ int ret; ++ CLzmaEncProps props; ++ LzmaEncProps_Init(&props); ++ ++ props.dictSize = LZMA_BEST_DICT(0x2000); ++ props.level = LZMA_BEST_LEVEL; ++ props.lc = LZMA_BEST_LC; ++ props.lp = LZMA_BEST_LP; ++ props.pb = LZMA_BEST_PB; ++ props.fb = LZMA_BEST_FB; ++ ++ ret = lzma_alloc_workspace(&props); ++ if (ret < 0) ++ return ret; ++ ++ ret = jffs2_register_compressor(&jffs2_lzma_comp); ++ if (ret) ++ lzma_free_workspace(); ++ ++ return ret; ++} ++ ++void jffs2_lzma_exit(void) ++{ ++ jffs2_unregister_compressor(&jffs2_lzma_comp); ++ lzma_free_workspace(); ++} +--- a/include/linux/jffs2.h ++++ b/include/linux/jffs2.h +@@ -47,6 +47,7 @@ + #define JFFS2_COMPR_DYNRUBIN 0x05 + #define JFFS2_COMPR_ZLIB 0x06 + #define JFFS2_COMPR_LZO 0x07 ++#define JFFS2_COMPR_LZMA 0x08 + /* Compatibility flags. */ + #define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */ + #define JFFS2_NODE_ACCURATE 0x2000 +--- /dev/null ++++ b/include/linux/lzma.h +@@ -0,0 +1,61 @@ ++#ifndef __LZMA_H__ ++#define __LZMA_H__ ++ ++#ifdef __KERNEL__ ++ #include <linux/kernel.h> ++ #include <linux/sched.h> ++ #include <linux/slab.h> ++ #include <linux/vmalloc.h> ++ #include <linux/init.h> ++ #define LZMA_MALLOC vmalloc ++ #define LZMA_FREE vfree ++ #define PRINT_ERROR(msg) printk(KERN_WARNING #msg) ++ #define INIT __init ++ #define STATIC static ++#else ++ #include <stdint.h> ++ #include <stdlib.h> ++ #include <stdio.h> ++ #include <unistd.h> ++ #include <string.h> ++ #include <errno.h> ++ #include <linux/jffs2.h> ++ #ifndef PAGE_SIZE ++ extern int page_size; ++ #define PAGE_SIZE page_size ++ #endif ++ #define LZMA_MALLOC malloc ++ #define LZMA_FREE free ++ #define PRINT_ERROR(msg) fprintf(stderr, msg) ++ #define INIT ++ #define STATIC ++#endif ++ ++#include "lzma/LzmaDec.h" ++#include "lzma/LzmaEnc.h" ++ ++#define LZMA_BEST_LEVEL (9) ++#define LZMA_BEST_LC (0) ++#define LZMA_BEST_LP (0) ++#define LZMA_BEST_PB (0) ++#define LZMA_BEST_FB (273) ++ ++#define LZMA_BEST_DICT(n) (((int)((n) / 2)) * 2) ++ ++static void *p_lzma_malloc(void *p, size_t size) ++{ ++ if (size == 0) ++ return NULL; ++ ++ return LZMA_MALLOC(size); ++} ++ ++static void p_lzma_free(void *p, void *address) ++{ ++ if (address != NULL) ++ LZMA_FREE(address); ++} ++ ++static ISzAlloc lzma_alloc = {p_lzma_malloc, p_lzma_free}; ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzFind.h +@@ -0,0 +1,116 @@ ++/* LzFind.h -- Match finder for LZ algorithms ++2008-04-04 ++Copyright (c) 1999-2008 Igor Pavlov ++You can use any of the following license options: ++ 1) GNU Lesser General Public License (GNU LGPL) ++ 2) Common Public License (CPL) ++ 3) Common Development and Distribution License (CDDL) Version 1.0 ++ 4) Igor Pavlov, as the author of this code, expressly permits you to ++ statically or dynamically link your code (or bind by name) to this file, ++ while you keep this file unmodified. ++*/ ++ ++#ifndef __LZFIND_H ++#define __LZFIND_H ++ ++#include "Types.h" ++ ++typedef UInt32 CLzRef; ++ ++typedef struct _CMatchFinder ++{ ++ Byte *buffer; ++ UInt32 pos; ++ UInt32 posLimit; ++ UInt32 streamPos; ++ UInt32 lenLimit; ++ ++ UInt32 cyclicBufferPos; ++ UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ ++ ++ UInt32 matchMaxLen; ++ CLzRef *hash; ++ CLzRef *son; ++ UInt32 hashMask; ++ UInt32 cutValue; ++ ++ Byte *bufferBase; ++ ISeqInStream *stream; ++ int streamEndWasReached; ++ ++ UInt32 blockSize; ++ UInt32 keepSizeBefore; ++ UInt32 keepSizeAfter; ++ ++ UInt32 numHashBytes; ++ int directInput; ++ int btMode; ++ /* int skipModeBits; */ ++ int bigHash; ++ UInt32 historySize; ++ UInt32 fixedHashSize; ++ UInt32 hashSizeSum; ++ UInt32 numSons; ++ SRes result; ++ UInt32 crc[256]; ++} CMatchFinder; ++ ++#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) ++#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) ++ ++#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) ++ ++int MatchFinder_NeedMove(CMatchFinder *p); ++Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); ++void MatchFinder_MoveBlock(CMatchFinder *p); ++void MatchFinder_ReadIfRequired(CMatchFinder *p); ++ ++void MatchFinder_Construct(CMatchFinder *p); ++ ++/* Conditions: ++ historySize <= 3 GB ++ keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB ++*/ ++int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, ++ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ++ ISzAlloc *alloc); ++void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); ++void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); ++void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); ++ ++UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, ++ UInt32 *distances, UInt32 maxLen); ++ ++/* ++Conditions: ++ Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. ++ Mf_GetPointerToCurrentPos_Func's result must be used only before any other function ++*/ ++ ++typedef void (*Mf_Init_Func)(void *object); ++typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); ++typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); ++typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); ++typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); ++typedef void (*Mf_Skip_Func)(void *object, UInt32); ++ ++typedef struct _IMatchFinder ++{ ++ Mf_Init_Func Init; ++ Mf_GetIndexByte_Func GetIndexByte; ++ Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; ++ Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; ++ Mf_GetMatches_Func GetMatches; ++ Mf_Skip_Func Skip; ++} IMatchFinder; ++ ++void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); ++ ++void MatchFinder_Init(CMatchFinder *p); ++UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); ++UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); ++void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); ++void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzHash.h +@@ -0,0 +1,56 @@ ++/* LzHash.h -- HASH functions for LZ algorithms ++2008-03-26 ++Copyright (c) 1999-2008 Igor Pavlov ++Read LzFind.h for license options */ ++ ++#ifndef __LZHASH_H ++#define __LZHASH_H ++ ++#define kHash2Size (1 << 10) ++#define kHash3Size (1 << 16) ++#define kHash4Size (1 << 20) ++ ++#define kFix3HashSize (kHash2Size) ++#define kFix4HashSize (kHash2Size + kHash3Size) ++#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) ++ ++#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); ++ ++#define HASH3_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } ++ ++#define HASH4_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ ++ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } ++ ++#define HASH5_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ ++ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ ++ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ ++ hash4Value &= (kHash4Size - 1); } ++ ++/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ ++#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; ++ ++ ++#define MT_HASH2_CALC \ ++ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); ++ ++#define MT_HASH3_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } ++ ++#define MT_HASH4_CALC { \ ++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ ++ hash2Value = temp & (kHash2Size - 1); \ ++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ ++ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzmaDec.h +@@ -0,0 +1,232 @@ ++/* LzmaDec.h -- LZMA Decoder ++2008-04-29 ++Copyright (c) 1999-2008 Igor Pavlov ++You can use any of the following license options: ++ 1) GNU Lesser General Public License (GNU LGPL) ++ 2) Common Public License (CPL) ++ 3) Common Development and Distribution License (CDDL) Version 1.0 ++ 4) Igor Pavlov, as the author of this code, expressly permits you to ++ statically or dynamically link your code (or bind by name) to this file, ++ while you keep this file unmodified. ++*/ ++ ++#ifndef __LZMADEC_H ++#define __LZMADEC_H ++ ++#include "Types.h" ++ ++/* #define _LZMA_PROB32 */ ++/* _LZMA_PROB32 can increase the speed on some CPUs, ++ but memory usage for CLzmaDec::probs will be doubled in that case */ ++ ++#ifdef _LZMA_PROB32 ++#define CLzmaProb UInt32 ++#else ++#define CLzmaProb UInt16 ++#endif ++ ++ ++/* ---------- LZMA Properties ---------- */ ++ ++#define LZMA_PROPS_SIZE 5 ++ ++typedef struct _CLzmaProps ++{ ++ unsigned lc, lp, pb; ++ UInt32 dicSize; ++} CLzmaProps; ++ ++/* LzmaProps_Decode - decodes properties ++Returns: ++ SZ_OK ++ SZ_ERROR_UNSUPPORTED - Unsupported properties ++*/ ++ ++SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); ++ ++ ++/* ---------- LZMA Decoder state ---------- */ ++ ++/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. ++ Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ ++ ++#define LZMA_REQUIRED_INPUT_MAX 20 ++ ++typedef struct ++{ ++ CLzmaProps prop; ++ CLzmaProb *probs; ++ Byte *dic; ++ const Byte *buf; ++ UInt32 range, code; ++ SizeT dicPos; ++ SizeT dicBufSize; ++ UInt32 processedPos; ++ UInt32 checkDicSize; ++ unsigned state; ++ UInt32 reps[4]; ++ unsigned remainLen; ++ int needFlush; ++ int needInitState; ++ UInt32 numProbs; ++ unsigned tempBufSize; ++ Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; ++} CLzmaDec; ++ ++#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } ++ ++void LzmaDec_Init(CLzmaDec *p); ++ ++/* There are two types of LZMA streams: ++ 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. ++ 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ ++ ++typedef enum ++{ ++ LZMA_FINISH_ANY, /* finish at any point */ ++ LZMA_FINISH_END /* block must be finished at the end */ ++} ELzmaFinishMode; ++ ++/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! ++ ++ You must use LZMA_FINISH_END, when you know that current output buffer ++ covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. ++ ++ If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, ++ and output value of destLen will be less than output buffer size limit. ++ You can check status result also. ++ ++ You can use multiple checks to test data integrity after full decompression: ++ 1) Check Result and "status" variable. ++ 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. ++ 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. ++ You must use correct finish mode in that case. */ ++ ++typedef enum ++{ ++ LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ ++ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ ++ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ ++ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ ++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ ++} ELzmaStatus; ++ ++/* ELzmaStatus is used only as output value for function call */ ++ ++ ++/* ---------- Interfaces ---------- */ ++ ++/* There are 3 levels of interfaces: ++ 1) Dictionary Interface ++ 2) Buffer Interface ++ 3) One Call Interface ++ You can select any of these interfaces, but don't mix functions from different ++ groups for same object. */ ++ ++ ++/* There are two variants to allocate state for Dictionary Interface: ++ 1) LzmaDec_Allocate / LzmaDec_Free ++ 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs ++ You can use variant 2, if you set dictionary buffer manually. ++ For Buffer Interface you must always use variant 1. ++ ++LzmaDec_Allocate* can return: ++ SZ_OK ++ SZ_ERROR_MEM - Memory allocation error ++ SZ_ERROR_UNSUPPORTED - Unsupported properties ++*/ ++ ++SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); ++void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); ++ ++SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); ++void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); ++ ++/* ---------- Dictionary Interface ---------- */ ++ ++/* You can use it, if you want to eliminate the overhead for data copying from ++ dictionary to some other external buffer. ++ You must work with CLzmaDec variables directly in this interface. ++ ++ STEPS: ++ LzmaDec_Constr() ++ LzmaDec_Allocate() ++ for (each new stream) ++ { ++ LzmaDec_Init() ++ while (it needs more decompression) ++ { ++ LzmaDec_DecodeToDic() ++ use data from CLzmaDec::dic and update CLzmaDec::dicPos ++ } ++ } ++ LzmaDec_Free() ++*/ ++ ++/* LzmaDec_DecodeToDic ++ ++ The decoding to internal dictionary buffer (CLzmaDec::dic). ++ You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! ++ ++finishMode: ++ It has meaning only if the decoding reaches output limit (dicLimit). ++ LZMA_FINISH_ANY - Decode just dicLimit bytes. ++ LZMA_FINISH_END - Stream must be finished after dicLimit. ++ ++Returns: ++ SZ_OK ++ status: ++ LZMA_STATUS_FINISHED_WITH_MARK ++ LZMA_STATUS_NOT_FINISHED ++ LZMA_STATUS_NEEDS_MORE_INPUT ++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ++ SZ_ERROR_DATA - Data error ++*/ ++ ++SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, ++ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); ++ ++ ++/* ---------- Buffer Interface ---------- */ ++ ++/* It's zlib-like interface. ++ See LzmaDec_DecodeToDic description for information about STEPS and return results, ++ but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need ++ to work with CLzmaDec variables manually. ++ ++finishMode: ++ It has meaning only if the decoding reaches output limit (*destLen). ++ LZMA_FINISH_ANY - Decode just destLen bytes. ++ LZMA_FINISH_END - Stream must be finished after (*destLen). ++*/ ++ ++SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, ++ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); ++ ++ ++/* ---------- One Call Interface ---------- */ ++ ++/* LzmaDecode ++ ++finishMode: ++ It has meaning only if the decoding reaches output limit (*destLen). ++ LZMA_FINISH_ANY - Decode just destLen bytes. ++ LZMA_FINISH_END - Stream must be finished after (*destLen). ++ ++Returns: ++ SZ_OK ++ status: ++ LZMA_STATUS_FINISHED_WITH_MARK ++ LZMA_STATUS_NOT_FINISHED ++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ++ SZ_ERROR_DATA - Data error ++ SZ_ERROR_MEM - Memory allocation error ++ SZ_ERROR_UNSUPPORTED - Unsupported properties ++ SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). ++*/ ++ ++SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ++ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ++ ELzmaStatus *status, ISzAlloc *alloc); ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/LzmaEnc.h +@@ -0,0 +1,74 @@ ++/* LzmaEnc.h -- LZMA Encoder ++2008-04-27 ++Copyright (c) 1999-2008 Igor Pavlov ++Read LzFind.h for license options */ ++ ++#ifndef __LZMAENC_H ++#define __LZMAENC_H ++ ++#include "Types.h" ++ ++#define LZMA_PROPS_SIZE 5 ++ ++typedef struct _CLzmaEncProps ++{ ++ int level; /* 0 <= level <= 9 */ ++ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version ++ (1 << 12) <= dictSize <= (1 << 30) for 64-bit version ++ default = (1 << 24) */ ++ int lc; /* 0 <= lc <= 8, default = 3 */ ++ int lp; /* 0 <= lp <= 4, default = 0 */ ++ int pb; /* 0 <= pb <= 4, default = 2 */ ++ int algo; /* 0 - fast, 1 - normal, default = 1 */ ++ int fb; /* 5 <= fb <= 273, default = 32 */ ++ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ ++ int numHashBytes; /* 2, 3 or 4, default = 4 */ ++ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ ++ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ ++ int numThreads; /* 1 or 2, default = 2 */ ++} CLzmaEncProps; ++ ++void LzmaEncProps_Init(CLzmaEncProps *p); ++void LzmaEncProps_Normalize(CLzmaEncProps *p); ++UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); ++ ++ ++/* ---------- CLzmaEncHandle Interface ---------- */ ++ ++/* LzmaEnc_* functions can return the following exit codes: ++Returns: ++ SZ_OK - OK ++ SZ_ERROR_MEM - Memory allocation error ++ SZ_ERROR_PARAM - Incorrect paramater in props ++ SZ_ERROR_WRITE - Write callback error. ++ SZ_ERROR_PROGRESS - some break from progress callback ++ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) ++*/ ++ ++typedef void * CLzmaEncHandle; ++ ++CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); ++void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); ++SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); ++SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); ++SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++ ++/* ---------- One Call Interface ---------- */ ++ ++/* LzmaEncode ++Return code: ++ SZ_OK - OK ++ SZ_ERROR_MEM - Memory allocation error ++ SZ_ERROR_PARAM - Incorrect paramater ++ SZ_ERROR_OUTPUT_EOF - output buffer overflow ++ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) ++*/ ++ ++SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ++ ++#endif +--- /dev/null ++++ b/include/linux/lzma/Types.h +@@ -0,0 +1,130 @@ ++/* Types.h -- Basic types ++2008-04-11 ++Igor Pavlov ++Public domain */ ++ ++#ifndef __7Z_TYPES_H ++#define __7Z_TYPES_H ++ ++#define SZ_OK 0 ++ ++#define SZ_ERROR_DATA 1 ++#define SZ_ERROR_MEM 2 ++#define SZ_ERROR_CRC 3 ++#define SZ_ERROR_UNSUPPORTED 4 ++#define SZ_ERROR_PARAM 5 ++#define SZ_ERROR_INPUT_EOF 6 ++#define SZ_ERROR_OUTPUT_EOF 7 ++#define SZ_ERROR_READ 8 ++#define SZ_ERROR_WRITE 9 ++#define SZ_ERROR_PROGRESS 10 ++#define SZ_ERROR_FAIL 11 ++#define SZ_ERROR_THREAD 12 ++ ++#define SZ_ERROR_ARCHIVE 16 ++#define SZ_ERROR_NO_ARCHIVE 17 ++ ++typedef int SRes; ++ ++#ifndef RINOK ++#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } ++#endif ++ ++typedef unsigned char Byte; ++typedef short Int16; ++typedef unsigned short UInt16; ++ ++#ifdef _LZMA_UINT32_IS_ULONG ++typedef long Int32; ++typedef unsigned long UInt32; ++#else ++typedef int Int32; ++typedef unsigned int UInt32; ++#endif ++ ++/* #define _SZ_NO_INT_64 */ ++/* define it if your compiler doesn't support 64-bit integers */ ++ ++#ifdef _SZ_NO_INT_64 ++ ++typedef long Int64; ++typedef unsigned long UInt64; ++ ++#else ++ ++#if defined(_MSC_VER) || defined(__BORLANDC__) ++typedef __int64 Int64; ++typedef unsigned __int64 UInt64; ++#else ++typedef long long int Int64; ++typedef unsigned long long int UInt64; ++#endif ++ ++#endif ++ ++#ifdef _LZMA_NO_SYSTEM_SIZE_T ++typedef UInt32 SizeT; ++#else ++#include <stddef.h> ++typedef size_t SizeT; ++#endif ++ ++typedef int Bool; ++#define True 1 ++#define False 0 ++ ++ ++#ifdef _MSC_VER ++ ++#if _MSC_VER >= 1300 ++#define MY_NO_INLINE __declspec(noinline) ++#else ++#define MY_NO_INLINE ++#endif ++ ++#define MY_CDECL __cdecl ++#define MY_STD_CALL __stdcall ++#define MY_FAST_CALL MY_NO_INLINE __fastcall ++ ++#else ++ ++#define MY_CDECL ++#define MY_STD_CALL ++#define MY_FAST_CALL ++ ++#endif ++ ++ ++/* The following interfaces use first parameter as pointer to structure */ ++ ++typedef struct ++{ ++ SRes (*Read)(void *p, void *buf, size_t *size); ++ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. ++ (output(*size) < input(*size)) is allowed */ ++} ISeqInStream; ++ ++typedef struct ++{ ++ size_t (*Write)(void *p, const void *buf, size_t size); ++ /* Returns: result - the number of actually written bytes. ++ (result < size) means error */ ++} ISeqOutStream; ++ ++typedef struct ++{ ++ SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); ++ /* Returns: result. (result != SZ_OK) means break. ++ Value (UInt64)(Int64)-1 for size means unknown value. */ ++} ICompressProgress; ++ ++typedef struct ++{ ++ void *(*Alloc)(void *p, size_t size); ++ void (*Free)(void *p, void *address); /* address can be 0 */ ++} ISzAlloc; ++ ++#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) ++#define IAlloc_Free(p, a) (p)->Free((p), a) ++ ++#endif +--- /dev/null ++++ b/lzma/LzFind.c +@@ -0,0 +1,753 @@ ++/* LzFind.c -- Match finder for LZ algorithms ++2008-04-04 ++Copyright (c) 1999-2008 Igor Pavlov ++Read LzFind.h for license options */ ++ ++#include <string.h> ++ ++#include "LzFind.h" ++#include "LzHash.h" ++ ++#define kEmptyHashValue 0 ++#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) ++#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ ++#define kNormalizeMask (~(kNormalizeStepMin - 1)) ++#define kMaxHistorySize ((UInt32)3 << 30) ++ ++#define kStartMaxLen 3 ++ ++static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) ++{ ++ if (!p->directInput) ++ { ++ alloc->Free(alloc, p->bufferBase); ++ p->bufferBase = 0; ++ } ++} ++ ++/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ ++ ++static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) ++{ ++ UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; ++ if (p->directInput) ++ { ++ p->blockSize = blockSize; ++ return 1; ++ } ++ if (p->bufferBase == 0 || p->blockSize != blockSize) ++ { ++ LzInWindow_Free(p, alloc); ++ p->blockSize = blockSize; ++ p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); ++ } ++ return (p->bufferBase != 0); ++} ++ ++Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } ++Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } ++ ++UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } ++ ++void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) ++{ ++ p->posLimit -= subValue; ++ p->pos -= subValue; ++ p->streamPos -= subValue; ++} ++ ++static void MatchFinder_ReadBlock(CMatchFinder *p) ++{ ++ if (p->streamEndWasReached || p->result != SZ_OK) ++ return; ++ for (;;) ++ { ++ Byte *dest = p->buffer + (p->streamPos - p->pos); ++ size_t size = (p->bufferBase + p->blockSize - dest); ++ if (size == 0) ++ return; ++ p->result = p->stream->Read(p->stream, dest, &size); ++ if (p->result != SZ_OK) ++ return; ++ if (size == 0) ++ { ++ p->streamEndWasReached = 1; ++ return; ++ } ++ p->streamPos += (UInt32)size; ++ if (p->streamPos - p->pos > p->keepSizeAfter) ++ return; ++ } ++} ++ ++void MatchFinder_MoveBlock(CMatchFinder *p) ++{ ++ memmove(p->bufferBase, ++ p->buffer - p->keepSizeBefore, ++ (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); ++ p->buffer = p->bufferBase + p->keepSizeBefore; ++} ++ ++int MatchFinder_NeedMove(CMatchFinder *p) ++{ ++ /* if (p->streamEndWasReached) return 0; */ ++ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); ++} ++ ++void MatchFinder_ReadIfRequired(CMatchFinder *p) ++{ ++ if (p->streamEndWasReached) ++ return; ++ if (p->keepSizeAfter >= p->streamPos - p->pos) ++ MatchFinder_ReadBlock(p); ++} ++ ++static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) ++{ ++ if (MatchFinder_NeedMove(p)) ++ MatchFinder_MoveBlock(p); ++ MatchFinder_ReadBlock(p); ++} ++ ++static void MatchFinder_SetDefaultSettings(CMatchFinder *p) ++{ ++ p->cutValue = 32; ++ p->btMode = 1; ++ p->numHashBytes = 4; ++ /* p->skipModeBits = 0; */ ++ p->directInput = 0; ++ p->bigHash = 0; ++} ++ ++#define kCrcPoly 0xEDB88320 ++ ++void MatchFinder_Construct(CMatchFinder *p) ++{ ++ UInt32 i; ++ p->bufferBase = 0; ++ p->directInput = 0; ++ p->hash = 0; ++ MatchFinder_SetDefaultSettings(p); ++ ++ for (i = 0; i < 256; i++) ++ { ++ UInt32 r = i; ++ int j; ++ for (j = 0; j < 8; j++) ++ r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); ++ p->crc[i] = r; ++ } ++} ++ ++static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->hash); ++ p->hash = 0; ++} ++ ++void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) ++{ ++ MatchFinder_FreeThisClassMemory(p, alloc); ++ LzInWindow_Free(p, alloc); ++} ++ ++static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) ++{ ++ size_t sizeInBytes = (size_t)num * sizeof(CLzRef); ++ if (sizeInBytes / sizeof(CLzRef) != num) ++ return 0; ++ return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); ++} ++ ++int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, ++ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ++ ISzAlloc *alloc) ++{ ++ UInt32 sizeReserv; ++ if (historySize > kMaxHistorySize) ++ { ++ MatchFinder_Free(p, alloc); ++ return 0; ++ } ++ sizeReserv = historySize >> 1; ++ if (historySize > ((UInt32)2 << 30)) ++ sizeReserv = historySize >> 2; ++ sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); ++ ++ p->keepSizeBefore = historySize + keepAddBufferBefore + 1; ++ p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; ++ /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ ++ if (LzInWindow_Create(p, sizeReserv, alloc)) ++ { ++ UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; ++ UInt32 hs; ++ p->matchMaxLen = matchMaxLen; ++ { ++ p->fixedHashSize = 0; ++ if (p->numHashBytes == 2) ++ hs = (1 << 16) - 1; ++ else ++ { ++ hs = historySize - 1; ++ hs |= (hs >> 1); ++ hs |= (hs >> 2); ++ hs |= (hs >> 4); ++ hs |= (hs >> 8); ++ hs >>= 1; ++ /* hs >>= p->skipModeBits; */ ++ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ ++ if (hs > (1 << 24)) ++ { ++ if (p->numHashBytes == 3) ++ hs = (1 << 24) - 1; ++ else ++ hs >>= 1; ++ } ++ } ++ p->hashMask = hs; ++ hs++; ++ if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; ++ if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; ++ if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; ++ hs += p->fixedHashSize; ++ } ++ ++ { ++ UInt32 prevSize = p->hashSizeSum + p->numSons; ++ UInt32 newSize; ++ p->historySize = historySize; ++ p->hashSizeSum = hs; ++ p->cyclicBufferSize = newCyclicBufferSize; ++ p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); ++ newSize = p->hashSizeSum + p->numSons; ++ if (p->hash != 0 && prevSize == newSize) ++ return 1; ++ MatchFinder_FreeThisClassMemory(p, alloc); ++ p->hash = AllocRefs(newSize, alloc); ++ if (p->hash != 0) ++ { ++ p->son = p->hash + p->hashSizeSum; ++ return 1; ++ } ++ } ++ } ++ MatchFinder_Free(p, alloc); ++ return 0; ++} ++ ++static void MatchFinder_SetLimits(CMatchFinder *p) ++{ ++ UInt32 limit = kMaxValForNormalize - p->pos; ++ UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; ++ if (limit2 < limit) ++ limit = limit2; ++ limit2 = p->streamPos - p->pos; ++ if (limit2 <= p->keepSizeAfter) ++ { ++ if (limit2 > 0) ++ limit2 = 1; ++ } ++ else ++ limit2 -= p->keepSizeAfter; ++ if (limit2 < limit) ++ limit = limit2; ++ { ++ UInt32 lenLimit = p->streamPos - p->pos; ++ if (lenLimit > p->matchMaxLen) ++ lenLimit = p->matchMaxLen; ++ p->lenLimit = lenLimit; ++ } ++ p->posLimit = p->pos + limit; ++} ++ ++void MatchFinder_Init(CMatchFinder *p) ++{ ++ UInt32 i; ++ for(i = 0; i < p->hashSizeSum; i++) ++ p->hash[i] = kEmptyHashValue; ++ p->cyclicBufferPos = 0; ++ p->buffer = p->bufferBase; ++ p->pos = p->streamPos = p->cyclicBufferSize; ++ p->result = SZ_OK; ++ p->streamEndWasReached = 0; ++ MatchFinder_ReadBlock(p); ++ MatchFinder_SetLimits(p); ++} ++ ++static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) ++{ ++ return (p->pos - p->historySize - 1) & kNormalizeMask; ++} ++ ++void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) ++{ ++ UInt32 i; ++ for (i = 0; i < numItems; i++) ++ { ++ UInt32 value = items[i]; ++ if (value <= subValue) ++ value = kEmptyHashValue; ++ else ++ value -= subValue; ++ items[i] = value; ++ } ++} ++ ++static void MatchFinder_Normalize(CMatchFinder *p) ++{ ++ UInt32 subValue = MatchFinder_GetSubValue(p); ++ MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); ++ MatchFinder_ReduceOffsets(p, subValue); ++} ++ ++static void MatchFinder_CheckLimits(CMatchFinder *p) ++{ ++ if (p->pos == kMaxValForNormalize) ++ MatchFinder_Normalize(p); ++ if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) ++ MatchFinder_CheckAndMoveAndRead(p); ++ if (p->cyclicBufferPos == p->cyclicBufferSize) ++ p->cyclicBufferPos = 0; ++ MatchFinder_SetLimits(p); ++} ++ ++static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, ++ UInt32 *distances, UInt32 maxLen) ++{ ++ son[_cyclicBufferPos] = curMatch; ++ for (;;) ++ { ++ UInt32 delta = pos - curMatch; ++ if (cutValue-- == 0 || delta >= _cyclicBufferSize) ++ return distances; ++ { ++ const Byte *pb = cur - delta; ++ curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; ++ if (pb[maxLen] == cur[maxLen] && *pb == *cur) ++ { ++ UInt32 len = 0; ++ while(++len != lenLimit) ++ if (pb[len] != cur[len]) ++ break; ++ if (maxLen < len) ++ { ++ *distances++ = maxLen = len; ++ *distances++ = delta - 1; ++ if (len == lenLimit) ++ return distances; ++ } ++ } ++ } ++ } ++} ++ ++UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, ++ UInt32 *distances, UInt32 maxLen) ++{ ++ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; ++ CLzRef *ptr1 = son + (_cyclicBufferPos << 1); ++ UInt32 len0 = 0, len1 = 0; ++ for (;;) ++ { ++ UInt32 delta = pos - curMatch; ++ if (cutValue-- == 0 || delta >= _cyclicBufferSize) ++ { ++ *ptr0 = *ptr1 = kEmptyHashValue; ++ return distances; ++ } ++ { ++ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); ++ const Byte *pb = cur - delta; ++ UInt32 len = (len0 < len1 ? len0 : len1); ++ if (pb[len] == cur[len]) ++ { ++ if (++len != lenLimit && pb[len] == cur[len]) ++ while(++len != lenLimit) ++ if (pb[len] != cur[len]) ++ break; ++ if (maxLen < len) ++ { ++ *distances++ = maxLen = len; ++ *distances++ = delta - 1; ++ if (len == lenLimit) ++ { ++ *ptr1 = pair[0]; ++ *ptr0 = pair[1]; ++ return distances; ++ } ++ } ++ } ++ if (pb[len] < cur[len]) ++ { ++ *ptr1 = curMatch; ++ ptr1 = pair + 1; ++ curMatch = *ptr1; ++ len1 = len; ++ } ++ else ++ { ++ *ptr0 = curMatch; ++ ptr0 = pair; ++ curMatch = *ptr0; ++ len0 = len; ++ } ++ } ++ } ++} ++ ++static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, ++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) ++{ ++ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; ++ CLzRef *ptr1 = son + (_cyclicBufferPos << 1); ++ UInt32 len0 = 0, len1 = 0; ++ for (;;) ++ { ++ UInt32 delta = pos - curMatch; ++ if (cutValue-- == 0 || delta >= _cyclicBufferSize) ++ { ++ *ptr0 = *ptr1 = kEmptyHashValue; ++ return; ++ } ++ { ++ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); ++ const Byte *pb = cur - delta; ++ UInt32 len = (len0 < len1 ? len0 : len1); ++ if (pb[len] == cur[len]) ++ { ++ while(++len != lenLimit) ++ if (pb[len] != cur[len]) ++ break; ++ { ++ if (len == lenLimit) ++ { ++ *ptr1 = pair[0]; ++ *ptr0 = pair[1]; ++ return; ++ } ++ } ++ } ++ if (pb[len] < cur[len]) ++ { ++ *ptr1 = curMatch; ++ ptr1 = pair + 1; ++ curMatch = *ptr1; ++ len1 = len; ++ } ++ else ++ { ++ *ptr0 = curMatch; ++ ptr0 = pair; ++ curMatch = *ptr0; ++ len0 = len; ++ } ++ } ++ } ++} ++ ++#define MOVE_POS \ ++ ++p->cyclicBufferPos; \ ++ p->buffer++; \ ++ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); ++ ++#define MOVE_POS_RET MOVE_POS return offset; ++ ++static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } ++ ++#define GET_MATCHES_HEADER2(minLen, ret_op) \ ++ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ ++ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ ++ cur = p->buffer; ++ ++#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) ++#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) ++ ++#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue ++ ++#define GET_MATCHES_FOOTER(offset, maxLen) \ ++ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ ++ distances + offset, maxLen) - distances); MOVE_POS_RET; ++ ++#define SKIP_FOOTER \ ++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; ++ ++static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 offset; ++ GET_MATCHES_HEADER(2) ++ HASH2_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ offset = 0; ++ GET_MATCHES_FOOTER(offset, 1) ++} ++ ++UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 offset; ++ GET_MATCHES_HEADER(3) ++ HASH_ZIP_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ offset = 0; ++ GET_MATCHES_FOOTER(offset, 2) ++} ++ ++static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 hash2Value, delta2, maxLen, offset; ++ GET_MATCHES_HEADER(3) ++ ++ HASH3_CALC; ++ ++ delta2 = p->pos - p->hash[hash2Value]; ++ curMatch = p->hash[kFix3HashSize + hashValue]; ++ ++ p->hash[hash2Value] = ++ p->hash[kFix3HashSize + hashValue] = p->pos; ++ ++ ++ maxLen = 2; ++ offset = 0; ++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) ++ { ++ for (; maxLen != lenLimit; maxLen++) ++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) ++ break; ++ distances[0] = maxLen; ++ distances[1] = delta2 - 1; ++ offset = 2; ++ if (maxLen == lenLimit) ++ { ++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); ++ MOVE_POS_RET; ++ } ++ } ++ GET_MATCHES_FOOTER(offset, maxLen) ++} ++ ++static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; ++ GET_MATCHES_HEADER(4) ++ ++ HASH4_CALC; ++ ++ delta2 = p->pos - p->hash[ hash2Value]; ++ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; ++ curMatch = p->hash[kFix4HashSize + hashValue]; ++ ++ p->hash[ hash2Value] = ++ p->hash[kFix3HashSize + hash3Value] = ++ p->hash[kFix4HashSize + hashValue] = p->pos; ++ ++ maxLen = 1; ++ offset = 0; ++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) ++ { ++ distances[0] = maxLen = 2; ++ distances[1] = delta2 - 1; ++ offset = 2; ++ } ++ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) ++ { ++ maxLen = 3; ++ distances[offset + 1] = delta3 - 1; ++ offset += 2; ++ delta2 = delta3; ++ } ++ if (offset != 0) ++ { ++ for (; maxLen != lenLimit; maxLen++) ++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) ++ break; ++ distances[offset - 2] = maxLen; ++ if (maxLen == lenLimit) ++ { ++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); ++ MOVE_POS_RET; ++ } ++ } ++ if (maxLen < 3) ++ maxLen = 3; ++ GET_MATCHES_FOOTER(offset, maxLen) ++} ++ ++static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; ++ GET_MATCHES_HEADER(4) ++ ++ HASH4_CALC; ++ ++ delta2 = p->pos - p->hash[ hash2Value]; ++ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; ++ curMatch = p->hash[kFix4HashSize + hashValue]; ++ ++ p->hash[ hash2Value] = ++ p->hash[kFix3HashSize + hash3Value] = ++ p->hash[kFix4HashSize + hashValue] = p->pos; ++ ++ maxLen = 1; ++ offset = 0; ++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) ++ { ++ distances[0] = maxLen = 2; ++ distances[1] = delta2 - 1; ++ offset = 2; ++ } ++ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) ++ { ++ maxLen = 3; ++ distances[offset + 1] = delta3 - 1; ++ offset += 2; ++ delta2 = delta3; ++ } ++ if (offset != 0) ++ { ++ for (; maxLen != lenLimit; maxLen++) ++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) ++ break; ++ distances[offset - 2] = maxLen; ++ if (maxLen == lenLimit) ++ { ++ p->son[p->cyclicBufferPos] = curMatch; ++ MOVE_POS_RET; ++ } ++ } ++ if (maxLen < 3) ++ maxLen = 3; ++ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), ++ distances + offset, maxLen) - (distances)); ++ MOVE_POS_RET ++} ++ ++UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) ++{ ++ UInt32 offset; ++ GET_MATCHES_HEADER(3) ++ HASH_ZIP_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), ++ distances, 2) - (distances)); ++ MOVE_POS_RET ++} ++ ++static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ SKIP_HEADER(2) ++ HASH2_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ SKIP_FOOTER ++ } ++ while (--num != 0); ++} ++ ++void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ SKIP_HEADER(3) ++ HASH_ZIP_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ SKIP_FOOTER ++ } ++ while (--num != 0); ++} ++ ++static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ UInt32 hash2Value; ++ SKIP_HEADER(3) ++ HASH3_CALC; ++ curMatch = p->hash[kFix3HashSize + hashValue]; ++ p->hash[hash2Value] = ++ p->hash[kFix3HashSize + hashValue] = p->pos; ++ SKIP_FOOTER ++ } ++ while (--num != 0); ++} ++ ++static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ UInt32 hash2Value, hash3Value; ++ SKIP_HEADER(4) ++ HASH4_CALC; ++ curMatch = p->hash[kFix4HashSize + hashValue]; ++ p->hash[ hash2Value] = ++ p->hash[kFix3HashSize + hash3Value] = p->pos; ++ p->hash[kFix4HashSize + hashValue] = p->pos; ++ SKIP_FOOTER ++ } ++ while (--num != 0); ++} ++ ++static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ UInt32 hash2Value, hash3Value; ++ SKIP_HEADER(4) ++ HASH4_CALC; ++ curMatch = p->hash[kFix4HashSize + hashValue]; ++ p->hash[ hash2Value] = ++ p->hash[kFix3HashSize + hash3Value] = ++ p->hash[kFix4HashSize + hashValue] = p->pos; ++ p->son[p->cyclicBufferPos] = curMatch; ++ MOVE_POS ++ } ++ while (--num != 0); ++} ++ ++void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) ++{ ++ do ++ { ++ SKIP_HEADER(3) ++ HASH_ZIP_CALC; ++ curMatch = p->hash[hashValue]; ++ p->hash[hashValue] = p->pos; ++ p->son[p->cyclicBufferPos] = curMatch; ++ MOVE_POS ++ } ++ while (--num != 0); ++} ++ ++void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) ++{ ++ vTable->Init = (Mf_Init_Func)MatchFinder_Init; ++ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; ++ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; ++ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; ++ if (!p->btMode) ++ { ++ vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; ++ vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; ++ } ++ else if (p->numHashBytes == 2) ++ { ++ vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; ++ vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; ++ } ++ else if (p->numHashBytes == 3) ++ { ++ vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; ++ vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; ++ } ++ else ++ { ++ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; ++ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; ++ } ++} +--- /dev/null ++++ b/lzma/LzmaDec.c +@@ -0,0 +1,1014 @@ ++/* LzmaDec.c -- LZMA Decoder ++2008-04-29 ++Copyright (c) 1999-2008 Igor Pavlov ++Read LzmaDec.h for license options */ ++ ++#include "LzmaDec.h" ++ ++#include <string.h> ++ ++#define kNumTopBits 24 ++#define kTopValue ((UInt32)1 << kNumTopBits) ++ ++#define kNumBitModelTotalBits 11 ++#define kBitModelTotal (1 << kNumBitModelTotalBits) ++#define kNumMoveBits 5 ++ ++#define RC_INIT_SIZE 5 ++ ++#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } ++ ++#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) ++#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); ++#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); ++#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ ++ { UPDATE_0(p); i = (i + i); A0; } else \ ++ { UPDATE_1(p); i = (i + i) + 1; A1; } ++#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) ++ ++#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } ++#define TREE_DECODE(probs, limit, i) \ ++ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } ++ ++/* #define _LZMA_SIZE_OPT */ ++ ++#ifdef _LZMA_SIZE_OPT ++#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) ++#else ++#define TREE_6_DECODE(probs, i) \ ++ { i = 1; \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ TREE_GET_BIT(probs, i); \ ++ i -= 0x40; } ++#endif ++ ++#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } ++ ++#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) ++#define UPDATE_0_CHECK range = bound; ++#define UPDATE_1_CHECK range -= bound; code -= bound; ++#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ ++ { UPDATE_0_CHECK; i = (i + i); A0; } else \ ++ { UPDATE_1_CHECK; i = (i + i) + 1; A1; } ++#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) ++#define TREE_DECODE_CHECK(probs, limit, i) \ ++ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while(i < limit); i -= limit; } ++ ++ ++#define kNumPosBitsMax 4 ++#define kNumPosStatesMax (1 << kNumPosBitsMax) ++ ++#define kLenNumLowBits 3 ++#define kLenNumLowSymbols (1 << kLenNumLowBits) ++#define kLenNumMidBits 3 ++#define kLenNumMidSymbols (1 << kLenNumMidBits) ++#define kLenNumHighBits 8 ++#define kLenNumHighSymbols (1 << kLenNumHighBits) ++ ++#define LenChoice 0 ++#define LenChoice2 (LenChoice + 1) ++#define LenLow (LenChoice2 + 1) ++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) ++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) ++#define kNumLenProbs (LenHigh + kLenNumHighSymbols) ++ ++ ++#define kNumStates 12 ++#define kNumLitStates 7 ++ ++#define kStartPosModelIndex 4 ++#define kEndPosModelIndex 14 ++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) ++ ++#define kNumPosSlotBits 6 ++#define kNumLenToPosStates 4 ++ ++#define kNumAlignBits 4 ++#define kAlignTableSize (1 << kNumAlignBits) ++ ++#define kMatchMinLen 2 ++#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) ++ ++#define IsMatch 0 ++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) ++#define IsRepG0 (IsRep + kNumStates) ++#define IsRepG1 (IsRepG0 + kNumStates) ++#define IsRepG2 (IsRepG1 + kNumStates) ++#define IsRep0Long (IsRepG2 + kNumStates) ++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) ++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) ++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) ++#define LenCoder (Align + kAlignTableSize) ++#define RepLenCoder (LenCoder + kNumLenProbs) ++#define Literal (RepLenCoder + kNumLenProbs) ++ ++#define LZMA_BASE_SIZE 1846 ++#define LZMA_LIT_SIZE 768 ++ ++#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) ++ ++#if Literal != LZMA_BASE_SIZE ++StopCompilingDueBUG ++#endif ++ ++/* ++#define LZMA_STREAM_WAS_FINISHED_ID (-1) ++#define LZMA_SPEC_LEN_OFFSET (-3) ++*/ ++ ++Byte kLiteralNextStates[kNumStates * 2] = ++{ ++ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, ++ 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 ++}; ++ ++#define LZMA_DIC_MIN (1 << 12) ++ ++/* First LZMA-symbol is always decoded. ++And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization ++Out: ++ Result: ++ 0 - OK ++ 1 - Error ++ p->remainLen: ++ < kMatchSpecLenStart : normal remain ++ = kMatchSpecLenStart : finished ++ = kMatchSpecLenStart + 1 : Flush marker ++ = kMatchSpecLenStart + 2 : State Init Marker ++*/ ++ ++static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) ++{ ++ CLzmaProb *probs = p->probs; ++ ++ unsigned state = p->state; ++ UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; ++ unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; ++ unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; ++ unsigned lc = p->prop.lc; ++ ++ Byte *dic = p->dic; ++ SizeT dicBufSize = p->dicBufSize; ++ SizeT dicPos = p->dicPos; ++ ++ UInt32 processedPos = p->processedPos; ++ UInt32 checkDicSize = p->checkDicSize; ++ unsigned len = 0; ++ ++ const Byte *buf = p->buf; ++ UInt32 range = p->range; ++ UInt32 code = p->code; ++ ++ do ++ { ++ CLzmaProb *prob; ++ UInt32 bound; ++ unsigned ttt; ++ unsigned posState = processedPos & pbMask; ++ ++ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; ++ IF_BIT_0(prob) ++ { ++ unsigned symbol; ++ UPDATE_0(prob); ++ prob = probs + Literal; ++ if (checkDicSize != 0 || processedPos != 0) ++ prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + ++ (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); ++ ++ if (state < kNumLitStates) ++ { ++ symbol = 1; ++ do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); ++ } ++ else ++ { ++ unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; ++ unsigned offs = 0x100; ++ symbol = 1; ++ do ++ { ++ unsigned bit; ++ CLzmaProb *probLit; ++ matchByte <<= 1; ++ bit = (matchByte & offs); ++ probLit = prob + offs + bit + symbol; ++ GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) ++ } ++ while (symbol < 0x100); ++ } ++ dic[dicPos++] = (Byte)symbol; ++ processedPos++; ++ ++ state = kLiteralNextStates[state]; ++ /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ ++ continue; ++ } ++ else ++ { ++ UPDATE_1(prob); ++ prob = probs + IsRep + state; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ state += kNumStates; ++ prob = probs + LenCoder; ++ } ++ else ++ { ++ UPDATE_1(prob); ++ if (checkDicSize == 0 && processedPos == 0) ++ return SZ_ERROR_DATA; ++ prob = probs + IsRepG0 + state; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; ++ dicPos++; ++ processedPos++; ++ state = state < kNumLitStates ? 9 : 11; ++ continue; ++ } ++ UPDATE_1(prob); ++ } ++ else ++ { ++ UInt32 distance; ++ UPDATE_1(prob); ++ prob = probs + IsRepG1 + state; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ distance = rep1; ++ } ++ else ++ { ++ UPDATE_1(prob); ++ prob = probs + IsRepG2 + state; ++ IF_BIT_0(prob) ++ { ++ UPDATE_0(prob); ++ distance = rep2; ++ } ++ else ++ { ++ UPDATE_1(prob); ++ distance = rep3; ++ rep3 = rep2; ++ } ++ rep2 = rep1; ++ } ++ rep1 = rep0; ++ rep0 = distance; ++ } ++ state = state < kNumLitStates ? 8 : 11; ++ prob = probs + RepLenCoder; ++ } ++ { ++ unsigned limit, offset; ++ CLzmaProb *probLen = prob + LenChoice; ++ IF_BIT_0(probLen) ++ { ++ UPDATE_0(probLen); ++ probLen = prob + LenLow + (posState << kLenNumLowBits); ++ offset = 0; ++ limit = (1 << kLenNumLowBits); ++ } ++ else ++ { ++ UPDATE_1(probLen); ++ probLen = prob + LenChoice2; ++ IF_BIT_0(probLen) ++ { ++ UPDATE_0(probLen); ++ probLen = prob + LenMid + (posState << kLenNumMidBits); ++ offset = kLenNumLowSymbols; ++ limit = (1 << kLenNumMidBits); ++ } ++ else ++ { ++ UPDATE_1(probLen); ++ probLen = prob + LenHigh; ++ offset = kLenNumLowSymbols + kLenNumMidSymbols; ++ limit = (1 << kLenNumHighBits); ++ } ++ } ++ TREE_DECODE(probLen, limit, len); ++ len += offset; ++ } ++ ++ if (state >= kNumStates) ++ { ++ UInt32 distance; ++ prob = probs + PosSlot + ++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); ++ TREE_6_DECODE(prob, distance); ++ if (distance >= kStartPosModelIndex) ++ { ++ unsigned posSlot = (unsigned)distance; ++ int numDirectBits = (int)(((distance >> 1) - 1)); ++ distance = (2 | (distance & 1)); ++ if (posSlot < kEndPosModelIndex) ++ { ++ distance <<= numDirectBits; ++ prob = probs + SpecPos + distance - posSlot - 1; ++ { ++ UInt32 mask = 1; ++ unsigned i = 1; ++ do ++ { ++ GET_BIT2(prob + i, i, ; , distance |= mask); ++ mask <<= 1; ++ } ++ while(--numDirectBits != 0); ++ } ++ } ++ else ++ { ++ numDirectBits -= kNumAlignBits; ++ do ++ { ++ NORMALIZE ++ range >>= 1; ++ ++ { ++ UInt32 t; ++ code -= range; ++ t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ ++ distance = (distance << 1) + (t + 1); ++ code += range & t; ++ } ++ /* ++ distance <<= 1; ++ if (code >= range) ++ { ++ code -= range; ++ distance |= 1; ++ } ++ */ ++ } ++ while (--numDirectBits != 0); ++ prob = probs + Align; ++ distance <<= kNumAlignBits; ++ { ++ unsigned i = 1; ++ GET_BIT2(prob + i, i, ; , distance |= 1); ++ GET_BIT2(prob + i, i, ; , distance |= 2); ++ GET_BIT2(prob + i, i, ; , distance |= 4); ++ GET_BIT2(prob + i, i, ; , distance |= 8); ++ } ++ if (distance == (UInt32)0xFFFFFFFF) ++ { ++ len += kMatchSpecLenStart; ++ state -= kNumStates; ++ break; ++ } ++ } ++ } ++ rep3 = rep2; ++ rep2 = rep1; ++ rep1 = rep0; ++ rep0 = distance + 1; ++ if (checkDicSize == 0) ++ { ++ if (distance >= processedPos) ++ return SZ_ERROR_DATA; ++ } ++ else if (distance >= checkDicSize) ++ return SZ_ERROR_DATA; ++ state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; ++ /* state = kLiteralNextStates[state]; */ ++ } ++ ++ len += kMatchMinLen; ++ ++ { ++ SizeT rem = limit - dicPos; ++ unsigned curLen = ((rem < len) ? (unsigned)rem : len); ++ SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); ++ ++ processedPos += curLen; ++ ++ len -= curLen; ++ if (pos + curLen <= dicBufSize) ++ { ++ Byte *dest = dic + dicPos; ++ ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; ++ const Byte *lim = dest + curLen; ++ dicPos += curLen; ++ do ++ *(dest) = (Byte)*(dest + src); ++ while (++dest != lim); ++ } ++ else ++ { ++ do ++ { ++ dic[dicPos++] = dic[pos]; ++ if (++pos == dicBufSize) ++ pos = 0; ++ } ++ while (--curLen != 0); ++ } ++ } ++ } ++ } ++ while (dicPos < limit && buf < bufLimit); ++ NORMALIZE; ++ p->buf = buf; ++ p->range = range; ++ p->code = code; ++ p->remainLen = len; ++ p->dicPos = dicPos; ++ p->processedPos = processedPos; ++ p->reps[0] = rep0; ++ p->reps[1] = rep1; ++ p->reps[2] = rep2; ++ p->reps[3] = rep3; ++ p->state = state; ++ ++ return SZ_OK; ++} ++ ++static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) ++{ ++ if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) ++ { ++ Byte *dic = p->dic; ++ SizeT dicPos = p->dicPos; ++ SizeT dicBufSize = p->dicBufSize; ++ unsigned len = p->remainLen; ++ UInt32 rep0 = p->reps[0]; ++ if (limit - dicPos < len) ++ len = (unsigned)(limit - dicPos); ++ ++ if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) ++ p->checkDicSize = p->prop.dicSize; ++ ++ p->processedPos += len; ++ p->remainLen -= len; ++ while (len-- != 0) ++ { ++ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; ++ dicPos++; ++ } ++ p->dicPos = dicPos; ++ } ++} ++ ++/* LzmaDec_DecodeReal2 decodes LZMA-symbols and sets p->needFlush and p->needInit, if required. */ ++ ++static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) ++{ ++ do ++ { ++ SizeT limit2 = limit; ++ if (p->checkDicSize == 0) ++ { ++ UInt32 rem = p->prop.dicSize - p->processedPos; ++ if (limit - p->dicPos > rem) ++ limit2 = p->dicPos + rem; ++ } ++ RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); ++ if (p->processedPos >= p->prop.dicSize) ++ p->checkDicSize = p->prop.dicSize; ++ LzmaDec_WriteRem(p, limit); ++ } ++ while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); ++ ++ if (p->remainLen > kMatchSpecLenStart) ++ { ++ p->remainLen = kMatchSpecLenStart; ++ } ++ return 0; ++} ++ ++typedef enum ++{ ++ DUMMY_ERROR, /* unexpected end of input stream */ ++ DUMMY_LIT, ++ DUMMY_MATCH, ++ DUMMY_REP ++} ELzmaDummy; ++ ++static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) ++{ ++ UInt32 range = p->range; ++ UInt32 code = p->code; ++ const Byte *bufLimit = buf + inSize; ++ CLzmaProb *probs = p->probs; ++ unsigned state = p->state; ++ ELzmaDummy res; ++ ++ { ++ CLzmaProb *prob; ++ UInt32 bound; ++ unsigned ttt; ++ unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); ++ ++ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK ++ ++ /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ ++ ++ prob = probs + Literal; ++ if (p->checkDicSize != 0 || p->processedPos != 0) ++ prob += (LZMA_LIT_SIZE * ++ ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + ++ (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); ++ ++ if (state < kNumLitStates) ++ { ++ unsigned symbol = 1; ++ do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); ++ } ++ else ++ { ++ unsigned matchByte = p->dic[p->dicPos - p->reps[0] + ++ ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; ++ unsigned offs = 0x100; ++ unsigned symbol = 1; ++ do ++ { ++ unsigned bit; ++ CLzmaProb *probLit; ++ matchByte <<= 1; ++ bit = (matchByte & offs); ++ probLit = prob + offs + bit + symbol; ++ GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) ++ } ++ while (symbol < 0x100); ++ } ++ res = DUMMY_LIT; ++ } ++ else ++ { ++ unsigned len; ++ UPDATE_1_CHECK; ++ ++ prob = probs + IsRep + state; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ state = 0; ++ prob = probs + LenCoder; ++ res = DUMMY_MATCH; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ res = DUMMY_REP; ++ prob = probs + IsRepG0 + state; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ NORMALIZE_CHECK; ++ return DUMMY_REP; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ } ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ prob = probs + IsRepG1 + state; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ prob = probs + IsRepG2 + state; ++ IF_BIT_0_CHECK(prob) ++ { ++ UPDATE_0_CHECK; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ } ++ } ++ } ++ state = kNumStates; ++ prob = probs + RepLenCoder; ++ } ++ { ++ unsigned limit, offset; ++ CLzmaProb *probLen = prob + LenChoice; ++ IF_BIT_0_CHECK(probLen) ++ { ++ UPDATE_0_CHECK; ++ probLen = prob + LenLow + (posState << kLenNumLowBits); ++ offset = 0; ++ limit = 1 << kLenNumLowBits; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ probLen = prob + LenChoice2; ++ IF_BIT_0_CHECK(probLen) ++ { ++ UPDATE_0_CHECK; ++ probLen = prob + LenMid + (posState << kLenNumMidBits); ++ offset = kLenNumLowSymbols; ++ limit = 1 << kLenNumMidBits; ++ } ++ else ++ { ++ UPDATE_1_CHECK; ++ probLen = prob + LenHigh; ++ offset = kLenNumLowSymbols + kLenNumMidSymbols; ++ limit = 1 << kLenNumHighBits; ++ } ++ } ++ TREE_DECODE_CHECK(probLen, limit, len); ++ len += offset; ++ } ++ ++ if (state < 4) ++ { ++ unsigned posSlot; ++ prob = probs + PosSlot + ++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << ++ kNumPosSlotBits); ++ TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); ++ if (posSlot >= kStartPosModelIndex) ++ { ++ int numDirectBits = ((posSlot >> 1) - 1); ++ ++ /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ ++ ++ if (posSlot < kEndPosModelIndex) ++ { ++ prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; ++ } ++ else ++ { ++ numDirectBits -= kNumAlignBits; ++ do ++ { ++ NORMALIZE_CHECK ++ range >>= 1; ++ code -= range & (((code - range) >> 31) - 1); ++ /* if (code >= range) code -= range; */ ++ } ++ while (--numDirectBits != 0); ++ prob = probs + Align; ++ numDirectBits = kNumAlignBits; ++ } ++ { ++ unsigned i = 1; ++ do ++ { ++ GET_BIT_CHECK(prob + i, i); ++ } ++ while(--numDirectBits != 0); ++ } ++ } ++ } ++ } ++ } ++ NORMALIZE_CHECK; ++ return res; ++} ++ ++ ++static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) ++{ ++ p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); ++ p->range = 0xFFFFFFFF; ++ p->needFlush = 0; ++} ++ ++void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) ++{ ++ p->needFlush = 1; ++ p->remainLen = 0; ++ p->tempBufSize = 0; ++ ++ if (initDic) ++ { ++ p->processedPos = 0; ++ p->checkDicSize = 0; ++ p->needInitState = 1; ++ } ++ if (initState) ++ p->needInitState = 1; ++} ++ ++void LzmaDec_Init(CLzmaDec *p) ++{ ++ p->dicPos = 0; ++ LzmaDec_InitDicAndState(p, True, True); ++} ++ ++static void LzmaDec_InitStateReal(CLzmaDec *p) ++{ ++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); ++ UInt32 i; ++ CLzmaProb *probs = p->probs; ++ for (i = 0; i < numProbs; i++) ++ probs[i] = kBitModelTotal >> 1; ++ p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; ++ p->state = 0; ++ p->needInitState = 0; ++} ++ ++SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ++ ELzmaFinishMode finishMode, ELzmaStatus *status) ++{ ++ SizeT inSize = *srcLen; ++ (*srcLen) = 0; ++ LzmaDec_WriteRem(p, dicLimit); ++ ++ *status = LZMA_STATUS_NOT_SPECIFIED; ++ ++ while (p->remainLen != kMatchSpecLenStart) ++ { ++ int checkEndMarkNow; ++ ++ if (p->needFlush != 0) ++ { ++ for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) ++ p->tempBuf[p->tempBufSize++] = *src++; ++ if (p->tempBufSize < RC_INIT_SIZE) ++ { ++ *status = LZMA_STATUS_NEEDS_MORE_INPUT; ++ return SZ_OK; ++ } ++ if (p->tempBuf[0] != 0) ++ return SZ_ERROR_DATA; ++ ++ LzmaDec_InitRc(p, p->tempBuf); ++ p->tempBufSize = 0; ++ } ++ ++ checkEndMarkNow = 0; ++ if (p->dicPos >= dicLimit) ++ { ++ if (p->remainLen == 0 && p->code == 0) ++ { ++ *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; ++ return SZ_OK; ++ } ++ if (finishMode == LZMA_FINISH_ANY) ++ { ++ *status = LZMA_STATUS_NOT_FINISHED; ++ return SZ_OK; ++ } ++ if (p->remainLen != 0) ++ { ++ *status = LZMA_STATUS_NOT_FINISHED; ++ return SZ_ERROR_DATA; ++ } ++ checkEndMarkNow = 1; ++ } ++ ++ if (p->needInitState) ++ LzmaDec_InitStateReal(p); ++ ++ if (p->tempBufSize == 0) ++ { ++ SizeT processed; ++ const Byte *bufLimit; ++ if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) ++ { ++ int dummyRes = LzmaDec_TryDummy(p, src, inSize); ++ if (dummyRes == DUMMY_ERROR) ++ { ++ memcpy(p->tempBuf, src, inSize); ++ p->tempBufSize = (unsigned)inSize; ++ (*srcLen) += inSize; ++ *status = LZMA_STATUS_NEEDS_MORE_INPUT; ++ return SZ_OK; ++ } ++ if (checkEndMarkNow && dummyRes != DUMMY_MATCH) ++ { ++ *status = LZMA_STATUS_NOT_FINISHED; ++ return SZ_ERROR_DATA; ++ } ++ bufLimit = src; ++ } ++ else ++ bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; ++ p->buf = src; ++ if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) ++ return SZ_ERROR_DATA; ++ processed = p->buf - src; ++ (*srcLen) += processed; ++ src += processed; ++ inSize -= processed; ++ } ++ else ++ { ++ unsigned rem = p->tempBufSize, lookAhead = 0; ++ while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) ++ p->tempBuf[rem++] = src[lookAhead++]; ++ p->tempBufSize = rem; ++ if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) ++ { ++ int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); ++ if (dummyRes == DUMMY_ERROR) ++ { ++ (*srcLen) += lookAhead; ++ *status = LZMA_STATUS_NEEDS_MORE_INPUT; ++ return SZ_OK; ++ } ++ if (checkEndMarkNow && dummyRes != DUMMY_MATCH) ++ { ++ *status = LZMA_STATUS_NOT_FINISHED; ++ return SZ_ERROR_DATA; ++ } ++ } ++ p->buf = p->tempBuf; ++ if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) ++ return SZ_ERROR_DATA; ++ lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); ++ (*srcLen) += lookAhead; ++ src += lookAhead; ++ inSize -= lookAhead; ++ p->tempBufSize = 0; ++ } ++ } ++ if (p->code == 0) ++ *status = LZMA_STATUS_FINISHED_WITH_MARK; ++ return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; ++} ++ ++SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) ++{ ++ SizeT outSize = *destLen; ++ SizeT inSize = *srcLen; ++ *srcLen = *destLen = 0; ++ for (;;) ++ { ++ SizeT inSizeCur = inSize, outSizeCur, dicPos; ++ ELzmaFinishMode curFinishMode; ++ SRes res; ++ if (p->dicPos == p->dicBufSize) ++ p->dicPos = 0; ++ dicPos = p->dicPos; ++ if (outSize > p->dicBufSize - dicPos) ++ { ++ outSizeCur = p->dicBufSize; ++ curFinishMode = LZMA_FINISH_ANY; ++ } ++ else ++ { ++ outSizeCur = dicPos + outSize; ++ curFinishMode = finishMode; ++ } ++ ++ res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); ++ src += inSizeCur; ++ inSize -= inSizeCur; ++ *srcLen += inSizeCur; ++ outSizeCur = p->dicPos - dicPos; ++ memcpy(dest, p->dic + dicPos, outSizeCur); ++ dest += outSizeCur; ++ outSize -= outSizeCur; ++ *destLen += outSizeCur; ++ if (res != 0) ++ return res; ++ if (outSizeCur == 0 || outSize == 0) ++ return SZ_OK; ++ } ++} ++ ++void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->probs); ++ p->probs = 0; ++} ++ ++static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->dic); ++ p->dic = 0; ++} ++ ++void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) ++{ ++ LzmaDec_FreeProbs(p, alloc); ++ LzmaDec_FreeDict(p, alloc); ++} ++ ++SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) ++{ ++ UInt32 dicSize; ++ Byte d; ++ ++ if (size < LZMA_PROPS_SIZE) ++ return SZ_ERROR_UNSUPPORTED; ++ else ++ dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); ++ ++ if (dicSize < LZMA_DIC_MIN) ++ dicSize = LZMA_DIC_MIN; ++ p->dicSize = dicSize; ++ ++ d = data[0]; ++ if (d >= (9 * 5 * 5)) ++ return SZ_ERROR_UNSUPPORTED; ++ ++ p->lc = d % 9; ++ d /= 9; ++ p->pb = d / 5; ++ p->lp = d % 5; ++ ++ return SZ_OK; ++} ++ ++static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) ++{ ++ UInt32 numProbs = LzmaProps_GetNumProbs(propNew); ++ if (p->probs == 0 || numProbs != p->numProbs) ++ { ++ LzmaDec_FreeProbs(p, alloc); ++ p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); ++ p->numProbs = numProbs; ++ if (p->probs == 0) ++ return SZ_ERROR_MEM; ++ } ++ return SZ_OK; ++} ++ ++SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) ++{ ++ CLzmaProps propNew; ++ RINOK(LzmaProps_Decode(&propNew, props, propsSize)); ++ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); ++ p->prop = propNew; ++ return SZ_OK; ++} ++ ++SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) ++{ ++ CLzmaProps propNew; ++ SizeT dicBufSize; ++ RINOK(LzmaProps_Decode(&propNew, props, propsSize)); ++ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); ++ dicBufSize = propNew.dicSize; ++ if (p->dic == 0 || dicBufSize != p->dicBufSize) ++ { ++ LzmaDec_FreeDict(p, alloc); ++ p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); ++ if (p->dic == 0) ++ { ++ LzmaDec_FreeProbs(p, alloc); ++ return SZ_ERROR_MEM; ++ } ++ } ++ p->dicBufSize = dicBufSize; ++ p->prop = propNew; ++ return SZ_OK; ++} ++ ++SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ++ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ++ ELzmaStatus *status, ISzAlloc *alloc) ++{ ++ CLzmaDec p; ++ SRes res; ++ SizeT inSize = *srcLen; ++ SizeT outSize = *destLen; ++ *srcLen = *destLen = 0; ++ if (inSize < RC_INIT_SIZE) ++ return SZ_ERROR_INPUT_EOF; ++ ++ LzmaDec_Construct(&p); ++ res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); ++ if (res != 0) ++ return res; ++ p.dic = dest; ++ p.dicBufSize = outSize; ++ ++ LzmaDec_Init(&p); ++ ++ *srcLen = inSize; ++ res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); ++ ++ if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) ++ res = SZ_ERROR_INPUT_EOF; ++ ++ (*destLen) = p.dicPos; ++ LzmaDec_FreeProbs(&p, alloc); ++ return res; ++} +--- /dev/null ++++ b/lzma/LzmaEnc.c +@@ -0,0 +1,2335 @@ ++/* LzmaEnc.c -- LZMA Encoder ++2008-04-28 ++Copyright (c) 1999-2008 Igor Pavlov ++Read LzmaEnc.h for license options */ ++ ++#if defined(SHOW_STAT) || defined(SHOW_STAT2) ++#include <stdio.h> ++#endif ++ ++#include <string.h> ++ ++#include "LzmaEnc.h" ++ ++#include "LzFind.h" ++#ifdef COMPRESS_MF_MT ++#include "LzFindMt.h" ++#endif ++ ++/* #define SHOW_STAT */ ++/* #define SHOW_STAT2 */ ++ ++#ifdef SHOW_STAT ++static int ttt = 0; ++#endif ++ ++#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) ++ ++#define kBlockSize (9 << 10) ++#define kUnpackBlockSize (1 << 18) ++#define kMatchArraySize (1 << 21) ++#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) ++ ++#define kNumMaxDirectBits (31) ++ ++#define kNumTopBits 24 ++#define kTopValue ((UInt32)1 << kNumTopBits) ++ ++#define kNumBitModelTotalBits 11 ++#define kBitModelTotal (1 << kNumBitModelTotalBits) ++#define kNumMoveBits 5 ++#define kProbInitValue (kBitModelTotal >> 1) ++ ++#define kNumMoveReducingBits 4 ++#define kNumBitPriceShiftBits 4 ++#define kBitPrice (1 << kNumBitPriceShiftBits) ++ ++void LzmaEncProps_Init(CLzmaEncProps *p) ++{ ++ p->level = 5; ++ p->dictSize = p->mc = 0; ++ p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; ++ p->writeEndMark = 0; ++} ++ ++void LzmaEncProps_Normalize(CLzmaEncProps *p) ++{ ++ int level = p->level; ++ if (level < 0) level = 5; ++ p->level = level; ++ if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); ++ if (p->lc < 0) p->lc = 3; ++ if (p->lp < 0) p->lp = 0; ++ if (p->pb < 0) p->pb = 2; ++ if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); ++ if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); ++ if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); ++ if (p->numHashBytes < 0) p->numHashBytes = 4; ++ if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); ++ if (p->numThreads < 0) p->numThreads = ((p->btMode && p->algo) ? 2 : 1); ++} ++ ++UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) ++{ ++ CLzmaEncProps props = *props2; ++ LzmaEncProps_Normalize(&props); ++ return props.dictSize; ++} ++ ++/* #define LZMA_LOG_BSR */ ++/* Define it for Intel's CPU */ ++ ++ ++#ifdef LZMA_LOG_BSR ++ ++#define kDicLogSizeMaxCompress 30 ++ ++#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } ++ ++UInt32 GetPosSlot1(UInt32 pos) ++{ ++ UInt32 res; ++ BSR2_RET(pos, res); ++ return res; ++} ++#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } ++#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } ++ ++#else ++ ++#define kNumLogBits (9 + (int)sizeof(size_t) / 2) ++#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) ++ ++void LzmaEnc_FastPosInit(Byte *g_FastPos) ++{ ++ int c = 2, slotFast; ++ g_FastPos[0] = 0; ++ g_FastPos[1] = 1; ++ ++ for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) ++ { ++ UInt32 k = (1 << ((slotFast >> 1) - 1)); ++ UInt32 j; ++ for (j = 0; j < k; j++, c++) ++ g_FastPos[c] = (Byte)slotFast; ++ } ++} ++ ++#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ ++ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ ++ res = p->g_FastPos[pos >> i] + (i * 2); } ++/* ++#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ ++ p->g_FastPos[pos >> 6] + 12 : \ ++ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } ++*/ ++ ++#define GetPosSlot1(pos) p->g_FastPos[pos] ++#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } ++#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } ++ ++#endif ++ ++ ++#define LZMA_NUM_REPS 4 ++ ++typedef unsigned CState; ++ ++typedef struct _COptimal ++{ ++ UInt32 price; ++ ++ CState state; ++ int prev1IsChar; ++ int prev2; ++ ++ UInt32 posPrev2; ++ UInt32 backPrev2; ++ ++ UInt32 posPrev; ++ UInt32 backPrev; ++ UInt32 backs[LZMA_NUM_REPS]; ++} COptimal; ++ ++#define kNumOpts (1 << 12) ++ ++#define kNumLenToPosStates 4 ++#define kNumPosSlotBits 6 ++#define kDicLogSizeMin 0 ++#define kDicLogSizeMax 32 ++#define kDistTableSizeMax (kDicLogSizeMax * 2) ++ ++ ++#define kNumAlignBits 4 ++#define kAlignTableSize (1 << kNumAlignBits) ++#define kAlignMask (kAlignTableSize - 1) ++ ++#define kStartPosModelIndex 4 ++#define kEndPosModelIndex 14 ++#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) ++ ++#define kNumFullDistances (1 << (kEndPosModelIndex / 2)) ++ ++#ifdef _LZMA_PROB32 ++#define CLzmaProb UInt32 ++#else ++#define CLzmaProb UInt16 ++#endif ++ ++#define LZMA_PB_MAX 4 ++#define LZMA_LC_MAX 8 ++#define LZMA_LP_MAX 4 ++ ++#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) ++ ++ ++#define kLenNumLowBits 3 ++#define kLenNumLowSymbols (1 << kLenNumLowBits) ++#define kLenNumMidBits 3 ++#define kLenNumMidSymbols (1 << kLenNumMidBits) ++#define kLenNumHighBits 8 ++#define kLenNumHighSymbols (1 << kLenNumHighBits) ++ ++#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) ++ ++#define LZMA_MATCH_LEN_MIN 2 ++#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) ++ ++#define kNumStates 12 ++ ++typedef struct ++{ ++ CLzmaProb choice; ++ CLzmaProb choice2; ++ CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; ++ CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; ++ CLzmaProb high[kLenNumHighSymbols]; ++} CLenEnc; ++ ++typedef struct ++{ ++ CLenEnc p; ++ UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; ++ UInt32 tableSize; ++ UInt32 counters[LZMA_NUM_PB_STATES_MAX]; ++} CLenPriceEnc; ++ ++typedef struct _CRangeEnc ++{ ++ UInt32 range; ++ Byte cache; ++ UInt64 low; ++ UInt64 cacheSize; ++ Byte *buf; ++ Byte *bufLim; ++ Byte *bufBase; ++ ISeqOutStream *outStream; ++ UInt64 processed; ++ SRes res; ++} CRangeEnc; ++ ++typedef struct _CSeqInStreamBuf ++{ ++ ISeqInStream funcTable; ++ const Byte *data; ++ SizeT rem; ++} CSeqInStreamBuf; ++ ++static SRes MyRead(void *pp, void *data, size_t *size) ++{ ++ size_t curSize = *size; ++ CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; ++ if (p->rem < curSize) ++ curSize = p->rem; ++ memcpy(data, p->data, curSize); ++ p->rem -= curSize; ++ p->data += curSize; ++ *size = curSize; ++ return SZ_OK; ++} ++ ++typedef struct ++{ ++ CLzmaProb *litProbs; ++ ++ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; ++ CLzmaProb isRep[kNumStates]; ++ CLzmaProb isRepG0[kNumStates]; ++ CLzmaProb isRepG1[kNumStates]; ++ CLzmaProb isRepG2[kNumStates]; ++ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; ++ ++ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; ++ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; ++ CLzmaProb posAlignEncoder[1 << kNumAlignBits]; ++ ++ CLenPriceEnc lenEnc; ++ CLenPriceEnc repLenEnc; ++ ++ UInt32 reps[LZMA_NUM_REPS]; ++ UInt32 state; ++} CSaveState; ++ ++typedef struct _CLzmaEnc ++{ ++ IMatchFinder matchFinder; ++ void *matchFinderObj; ++ ++ #ifdef COMPRESS_MF_MT ++ Bool mtMode; ++ CMatchFinderMt matchFinderMt; ++ #endif ++ ++ CMatchFinder matchFinderBase; ++ ++ #ifdef COMPRESS_MF_MT ++ Byte pad[128]; ++ #endif ++ ++ UInt32 optimumEndIndex; ++ UInt32 optimumCurrentIndex; ++ ++ Bool longestMatchWasFound; ++ UInt32 longestMatchLength; ++ UInt32 numDistancePairs; ++ ++ COptimal opt[kNumOpts]; ++ ++ #ifndef LZMA_LOG_BSR ++ Byte g_FastPos[1 << kNumLogBits]; ++ #endif ++ ++ UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; ++ UInt32 matchDistances[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; ++ UInt32 numFastBytes; ++ UInt32 additionalOffset; ++ UInt32 reps[LZMA_NUM_REPS]; ++ UInt32 state; ++ ++ UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; ++ UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; ++ UInt32 alignPrices[kAlignTableSize]; ++ UInt32 alignPriceCount; ++ ++ UInt32 distTableSize; ++ ++ unsigned lc, lp, pb; ++ unsigned lpMask, pbMask; ++ ++ CLzmaProb *litProbs; ++ ++ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; ++ CLzmaProb isRep[kNumStates]; ++ CLzmaProb isRepG0[kNumStates]; ++ CLzmaProb isRepG1[kNumStates]; ++ CLzmaProb isRepG2[kNumStates]; ++ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; ++ ++ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; ++ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; ++ CLzmaProb posAlignEncoder[1 << kNumAlignBits]; ++ ++ CLenPriceEnc lenEnc; ++ CLenPriceEnc repLenEnc; ++ ++ unsigned lclp; ++ ++ Bool fastMode; ++ ++ CRangeEnc rc; ++ ++ Bool writeEndMark; ++ UInt64 nowPos64; ++ UInt32 matchPriceCount; ++ Bool finished; ++ Bool multiThread; ++ ++ SRes result; ++ UInt32 dictSize; ++ UInt32 matchFinderCycles; ++ ++ ISeqInStream *inStream; ++ CSeqInStreamBuf seqBufInStream; ++ ++ CSaveState saveState; ++} CLzmaEnc; ++ ++void LzmaEnc_SaveState(CLzmaEncHandle pp) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ CSaveState *dest = &p->saveState; ++ int i; ++ dest->lenEnc = p->lenEnc; ++ dest->repLenEnc = p->repLenEnc; ++ dest->state = p->state; ++ ++ for (i = 0; i < kNumStates; i++) ++ { ++ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); ++ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); ++ } ++ for (i = 0; i < kNumLenToPosStates; i++) ++ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); ++ memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); ++ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); ++ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); ++ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); ++ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); ++ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); ++ memcpy(dest->reps, p->reps, sizeof(p->reps)); ++ memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); ++} ++ ++void LzmaEnc_RestoreState(CLzmaEncHandle pp) ++{ ++ CLzmaEnc *dest = (CLzmaEnc *)pp; ++ const CSaveState *p = &dest->saveState; ++ int i; ++ dest->lenEnc = p->lenEnc; ++ dest->repLenEnc = p->repLenEnc; ++ dest->state = p->state; ++ ++ for (i = 0; i < kNumStates; i++) ++ { ++ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); ++ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); ++ } ++ for (i = 0; i < kNumLenToPosStates; i++) ++ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); ++ memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); ++ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); ++ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); ++ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); ++ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); ++ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); ++ memcpy(dest->reps, p->reps, sizeof(p->reps)); ++ memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); ++} ++ ++SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ CLzmaEncProps props = *props2; ++ LzmaEncProps_Normalize(&props); ++ ++ if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || ++ props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) ++ return SZ_ERROR_PARAM; ++ p->dictSize = props.dictSize; ++ p->matchFinderCycles = props.mc; ++ { ++ unsigned fb = props.fb; ++ if (fb < 5) ++ fb = 5; ++ if (fb > LZMA_MATCH_LEN_MAX) ++ fb = LZMA_MATCH_LEN_MAX; ++ p->numFastBytes = fb; ++ } ++ p->lc = props.lc; ++ p->lp = props.lp; ++ p->pb = props.pb; ++ p->fastMode = (props.algo == 0); ++ p->matchFinderBase.btMode = props.btMode; ++ { ++ UInt32 numHashBytes = 4; ++ if (props.btMode) ++ { ++ if (props.numHashBytes < 2) ++ numHashBytes = 2; ++ else if (props.numHashBytes < 4) ++ numHashBytes = props.numHashBytes; ++ } ++ p->matchFinderBase.numHashBytes = numHashBytes; ++ } ++ ++ p->matchFinderBase.cutValue = props.mc; ++ ++ p->writeEndMark = props.writeEndMark; ++ ++ #ifdef COMPRESS_MF_MT ++ /* ++ if (newMultiThread != _multiThread) ++ { ++ ReleaseMatchFinder(); ++ _multiThread = newMultiThread; ++ } ++ */ ++ p->multiThread = (props.numThreads > 1); ++ #endif ++ ++ return SZ_OK; ++} ++ ++static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; ++static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; ++static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; ++static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; ++ ++/* ++ void UpdateChar() { Index = kLiteralNextStates[Index]; } ++ void UpdateMatch() { Index = kMatchNextStates[Index]; } ++ void UpdateRep() { Index = kRepNextStates[Index]; } ++ void UpdateShortRep() { Index = kShortRepNextStates[Index]; } ++*/ ++ ++#define IsCharState(s) ((s) < 7) ++ ++ ++#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) ++ ++#define kInfinityPrice (1 << 30) ++ ++static void RangeEnc_Construct(CRangeEnc *p) ++{ ++ p->outStream = 0; ++ p->bufBase = 0; ++} ++ ++#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) ++ ++#define RC_BUF_SIZE (1 << 16) ++static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) ++{ ++ if (p->bufBase == 0) ++ { ++ p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); ++ if (p->bufBase == 0) ++ return 0; ++ p->bufLim = p->bufBase + RC_BUF_SIZE; ++ } ++ return 1; ++} ++ ++static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->bufBase); ++ p->bufBase = 0; ++} ++ ++static void RangeEnc_Init(CRangeEnc *p) ++{ ++ /* Stream.Init(); */ ++ p->low = 0; ++ p->range = 0xFFFFFFFF; ++ p->cacheSize = 1; ++ p->cache = 0; ++ ++ p->buf = p->bufBase; ++ ++ p->processed = 0; ++ p->res = SZ_OK; ++} ++ ++static void RangeEnc_FlushStream(CRangeEnc *p) ++{ ++ size_t num; ++ if (p->res != SZ_OK) ++ return; ++ num = p->buf - p->bufBase; ++ if (num != p->outStream->Write(p->outStream, p->bufBase, num)) ++ p->res = SZ_ERROR_WRITE; ++ p->processed += num; ++ p->buf = p->bufBase; ++} ++ ++static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) ++{ ++ if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) ++ { ++ Byte temp = p->cache; ++ do ++ { ++ Byte *buf = p->buf; ++ *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); ++ p->buf = buf; ++ if (buf == p->bufLim) ++ RangeEnc_FlushStream(p); ++ temp = 0xFF; ++ } ++ while (--p->cacheSize != 0); ++ p->cache = (Byte)((UInt32)p->low >> 24); ++ } ++ p->cacheSize++; ++ p->low = (UInt32)p->low << 8; ++} ++ ++static void RangeEnc_FlushData(CRangeEnc *p) ++{ ++ int i; ++ for (i = 0; i < 5; i++) ++ RangeEnc_ShiftLow(p); ++} ++ ++static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) ++{ ++ do ++ { ++ p->range >>= 1; ++ p->low += p->range & (0 - ((value >> --numBits) & 1)); ++ if (p->range < kTopValue) ++ { ++ p->range <<= 8; ++ RangeEnc_ShiftLow(p); ++ } ++ } ++ while (numBits != 0); ++} ++ ++static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) ++{ ++ UInt32 ttt = *prob; ++ UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; ++ if (symbol == 0) ++ { ++ p->range = newBound; ++ ttt += (kBitModelTotal - ttt) >> kNumMoveBits; ++ } ++ else ++ { ++ p->low += newBound; ++ p->range -= newBound; ++ ttt -= ttt >> kNumMoveBits; ++ } ++ *prob = (CLzmaProb)ttt; ++ if (p->range < kTopValue) ++ { ++ p->range <<= 8; ++ RangeEnc_ShiftLow(p); ++ } ++} ++ ++static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) ++{ ++ symbol |= 0x100; ++ do ++ { ++ RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); ++ symbol <<= 1; ++ } ++ while (symbol < 0x10000); ++} ++ ++static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) ++{ ++ UInt32 offs = 0x100; ++ symbol |= 0x100; ++ do ++ { ++ matchByte <<= 1; ++ RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); ++ symbol <<= 1; ++ offs &= ~(matchByte ^ symbol); ++ } ++ while (symbol < 0x10000); ++} ++ ++void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) ++{ ++ UInt32 i; ++ for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) ++ { ++ const int kCyclesBits = kNumBitPriceShiftBits; ++ UInt32 w = i; ++ UInt32 bitCount = 0; ++ int j; ++ for (j = 0; j < kCyclesBits; j++) ++ { ++ w = w * w; ++ bitCount <<= 1; ++ while (w >= ((UInt32)1 << 16)) ++ { ++ w >>= 1; ++ bitCount++; ++ } ++ } ++ ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); ++ } ++} ++ ++ ++#define GET_PRICE(prob, symbol) \ ++ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; ++ ++#define GET_PRICEa(prob, symbol) \ ++ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; ++ ++#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] ++#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] ++ ++#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] ++#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] ++ ++static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) ++{ ++ UInt32 price = 0; ++ symbol |= 0x100; ++ do ++ { ++ price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); ++ symbol <<= 1; ++ } ++ while (symbol < 0x10000); ++ return price; ++}; ++ ++static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) ++{ ++ UInt32 price = 0; ++ UInt32 offs = 0x100; ++ symbol |= 0x100; ++ do ++ { ++ matchByte <<= 1; ++ price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); ++ symbol <<= 1; ++ offs &= ~(matchByte ^ symbol); ++ } ++ while (symbol < 0x10000); ++ return price; ++}; ++ ++ ++static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) ++{ ++ UInt32 m = 1; ++ int i; ++ for (i = numBitLevels; i != 0 ;) ++ { ++ UInt32 bit; ++ i--; ++ bit = (symbol >> i) & 1; ++ RangeEnc_EncodeBit(rc, probs + m, bit); ++ m = (m << 1) | bit; ++ } ++}; ++ ++static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) ++{ ++ UInt32 m = 1; ++ int i; ++ for (i = 0; i < numBitLevels; i++) ++ { ++ UInt32 bit = symbol & 1; ++ RangeEnc_EncodeBit(rc, probs + m, bit); ++ m = (m << 1) | bit; ++ symbol >>= 1; ++ } ++} ++ ++static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) ++{ ++ UInt32 price = 0; ++ symbol |= (1 << numBitLevels); ++ while (symbol != 1) ++ { ++ price += GET_PRICEa(probs[symbol >> 1], symbol & 1); ++ symbol >>= 1; ++ } ++ return price; ++} ++ ++static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) ++{ ++ UInt32 price = 0; ++ UInt32 m = 1; ++ int i; ++ for (i = numBitLevels; i != 0; i--) ++ { ++ UInt32 bit = symbol & 1; ++ symbol >>= 1; ++ price += GET_PRICEa(probs[m], bit); ++ m = (m << 1) | bit; ++ } ++ return price; ++} ++ ++ ++static void LenEnc_Init(CLenEnc *p) ++{ ++ unsigned i; ++ p->choice = p->choice2 = kProbInitValue; ++ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) ++ p->low[i] = kProbInitValue; ++ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) ++ p->mid[i] = kProbInitValue; ++ for (i = 0; i < kLenNumHighSymbols; i++) ++ p->high[i] = kProbInitValue; ++} ++ ++static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) ++{ ++ if (symbol < kLenNumLowSymbols) ++ { ++ RangeEnc_EncodeBit(rc, &p->choice, 0); ++ RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); ++ } ++ else ++ { ++ RangeEnc_EncodeBit(rc, &p->choice, 1); ++ if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) ++ { ++ RangeEnc_EncodeBit(rc, &p->choice2, 0); ++ RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); ++ } ++ else ++ { ++ RangeEnc_EncodeBit(rc, &p->choice2, 1); ++ RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); ++ } ++ } ++} ++ ++static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) ++{ ++ UInt32 a0 = GET_PRICE_0a(p->choice); ++ UInt32 a1 = GET_PRICE_1a(p->choice); ++ UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); ++ UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); ++ UInt32 i = 0; ++ for (i = 0; i < kLenNumLowSymbols; i++) ++ { ++ if (i >= numSymbols) ++ return; ++ prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); ++ } ++ for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) ++ { ++ if (i >= numSymbols) ++ return; ++ prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); ++ } ++ for (; i < numSymbols; i++) ++ prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); ++} ++ ++static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) ++{ ++ LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); ++ p->counters[posState] = p->tableSize; ++} ++ ++static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) ++{ ++ UInt32 posState; ++ for (posState = 0; posState < numPosStates; posState++) ++ LenPriceEnc_UpdateTable(p, posState, ProbPrices); ++} ++ ++static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) ++{ ++ LenEnc_Encode(&p->p, rc, symbol, posState); ++ if (updatePrice) ++ if (--p->counters[posState] == 0) ++ LenPriceEnc_UpdateTable(p, posState, ProbPrices); ++} ++ ++ ++ ++ ++static void MovePos(CLzmaEnc *p, UInt32 num) ++{ ++ #ifdef SHOW_STAT ++ ttt += num; ++ printf("\n MovePos %d", num); ++ #endif ++ if (num != 0) ++ { ++ p->additionalOffset += num; ++ p->matchFinder.Skip(p->matchFinderObj, num); ++ } ++} ++ ++static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) ++{ ++ UInt32 lenRes = 0, numDistancePairs; ++ numDistancePairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matchDistances); ++ #ifdef SHOW_STAT ++ printf("\n i = %d numPairs = %d ", ttt, numDistancePairs / 2); ++ if (ttt >= 61994) ++ ttt = ttt; ++ ++ ttt++; ++ { ++ UInt32 i; ++ for (i = 0; i < numDistancePairs; i += 2) ++ printf("%2d %6d | ", p->matchDistances[i], p->matchDistances[i + 1]); ++ } ++ #endif ++ if (numDistancePairs > 0) ++ { ++ lenRes = p->matchDistances[numDistancePairs - 2]; ++ if (lenRes == p->numFastBytes) ++ { ++ UInt32 numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) + 1; ++ const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ UInt32 distance = p->matchDistances[numDistancePairs - 1] + 1; ++ if (numAvail > LZMA_MATCH_LEN_MAX) ++ numAvail = LZMA_MATCH_LEN_MAX; ++ ++ { ++ const Byte *pby2 = pby - distance; ++ for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); ++ } ++ } ++ } ++ p->additionalOffset++; ++ *numDistancePairsRes = numDistancePairs; ++ return lenRes; ++} ++ ++ ++#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; ++#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; ++#define IsShortRep(p) ((p)->backPrev == 0) ++ ++static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) ++{ ++ return ++ GET_PRICE_0(p->isRepG0[state]) + ++ GET_PRICE_0(p->isRep0Long[state][posState]); ++} ++ ++static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) ++{ ++ UInt32 price; ++ if (repIndex == 0) ++ { ++ price = GET_PRICE_0(p->isRepG0[state]); ++ price += GET_PRICE_1(p->isRep0Long[state][posState]); ++ } ++ else ++ { ++ price = GET_PRICE_1(p->isRepG0[state]); ++ if (repIndex == 1) ++ price += GET_PRICE_0(p->isRepG1[state]); ++ else ++ { ++ price += GET_PRICE_1(p->isRepG1[state]); ++ price += GET_PRICE(p->isRepG2[state], repIndex - 2); ++ } ++ } ++ return price; ++} ++ ++static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) ++{ ++ return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + ++ GetPureRepPrice(p, repIndex, state, posState); ++} ++ ++static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) ++{ ++ UInt32 posMem = p->opt[cur].posPrev; ++ UInt32 backMem = p->opt[cur].backPrev; ++ p->optimumEndIndex = cur; ++ do ++ { ++ if (p->opt[cur].prev1IsChar) ++ { ++ MakeAsChar(&p->opt[posMem]) ++ p->opt[posMem].posPrev = posMem - 1; ++ if (p->opt[cur].prev2) ++ { ++ p->opt[posMem - 1].prev1IsChar = False; ++ p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; ++ p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; ++ } ++ } ++ { ++ UInt32 posPrev = posMem; ++ UInt32 backCur = backMem; ++ ++ backMem = p->opt[posPrev].backPrev; ++ posMem = p->opt[posPrev].posPrev; ++ ++ p->opt[posPrev].backPrev = backCur; ++ p->opt[posPrev].posPrev = cur; ++ cur = posPrev; ++ } ++ } ++ while (cur != 0); ++ *backRes = p->opt[0].backPrev; ++ p->optimumCurrentIndex = p->opt[0].posPrev; ++ return p->optimumCurrentIndex; ++} ++ ++#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) ++ ++static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) ++{ ++ UInt32 numAvailableBytes, lenMain, numDistancePairs; ++ const Byte *data; ++ UInt32 reps[LZMA_NUM_REPS]; ++ UInt32 repLens[LZMA_NUM_REPS]; ++ UInt32 repMaxIndex, i; ++ UInt32 *matchDistances; ++ Byte currentByte, matchByte; ++ UInt32 posState; ++ UInt32 matchPrice, repMatchPrice; ++ UInt32 lenEnd; ++ UInt32 len; ++ UInt32 normalMatchPrice; ++ UInt32 cur; ++ if (p->optimumEndIndex != p->optimumCurrentIndex) ++ { ++ const COptimal *opt = &p->opt[p->optimumCurrentIndex]; ++ UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; ++ *backRes = opt->backPrev; ++ p->optimumCurrentIndex = opt->posPrev; ++ return lenRes; ++ } ++ p->optimumCurrentIndex = p->optimumEndIndex = 0; ++ ++ numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); ++ ++ if (!p->longestMatchWasFound) ++ { ++ lenMain = ReadMatchDistances(p, &numDistancePairs); ++ } ++ else ++ { ++ lenMain = p->longestMatchLength; ++ numDistancePairs = p->numDistancePairs; ++ p->longestMatchWasFound = False; ++ } ++ ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ if (numAvailableBytes < 2) ++ { ++ *backRes = (UInt32)(-1); ++ return 1; ++ } ++ if (numAvailableBytes > LZMA_MATCH_LEN_MAX) ++ numAvailableBytes = LZMA_MATCH_LEN_MAX; ++ ++ repMaxIndex = 0; ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ { ++ UInt32 lenTest; ++ const Byte *data2; ++ reps[i] = p->reps[i]; ++ data2 = data - (reps[i] + 1); ++ if (data[0] != data2[0] || data[1] != data2[1]) ++ { ++ repLens[i] = 0; ++ continue; ++ } ++ for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++); ++ repLens[i] = lenTest; ++ if (lenTest > repLens[repMaxIndex]) ++ repMaxIndex = i; ++ } ++ if (repLens[repMaxIndex] >= p->numFastBytes) ++ { ++ UInt32 lenRes; ++ *backRes = repMaxIndex; ++ lenRes = repLens[repMaxIndex]; ++ MovePos(p, lenRes - 1); ++ return lenRes; ++ } ++ ++ matchDistances = p->matchDistances; ++ if (lenMain >= p->numFastBytes) ++ { ++ *backRes = matchDistances[numDistancePairs - 1] + LZMA_NUM_REPS; ++ MovePos(p, lenMain - 1); ++ return lenMain; ++ } ++ currentByte = *data; ++ matchByte = *(data - (reps[0] + 1)); ++ ++ if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) ++ { ++ *backRes = (UInt32)-1; ++ return 1; ++ } ++ ++ p->opt[0].state = (CState)p->state; ++ ++ posState = (position & p->pbMask); ++ ++ { ++ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); ++ p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + ++ (!IsCharState(p->state) ? ++ LitEnc_GetPriceMatched(probs, currentByte, matchByte, p->ProbPrices) : ++ LitEnc_GetPrice(probs, currentByte, p->ProbPrices)); ++ } ++ ++ MakeAsChar(&p->opt[1]); ++ ++ matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); ++ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); ++ ++ if (matchByte == currentByte) ++ { ++ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); ++ if (shortRepPrice < p->opt[1].price) ++ { ++ p->opt[1].price = shortRepPrice; ++ MakeAsShortRep(&p->opt[1]); ++ } ++ } ++ lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); ++ ++ if (lenEnd < 2) ++ { ++ *backRes = p->opt[1].backPrev; ++ return 1; ++ } ++ ++ p->opt[1].posPrev = 0; ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ p->opt[0].backs[i] = reps[i]; ++ ++ len = lenEnd; ++ do ++ p->opt[len--].price = kInfinityPrice; ++ while (len >= 2); ++ ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ { ++ UInt32 repLen = repLens[i]; ++ UInt32 price; ++ if (repLen < 2) ++ continue; ++ price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); ++ do ++ { ++ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; ++ COptimal *opt = &p->opt[repLen]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = 0; ++ opt->backPrev = i; ++ opt->prev1IsChar = False; ++ } ++ } ++ while (--repLen >= 2); ++ } ++ ++ normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); ++ ++ len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); ++ if (len <= lenMain) ++ { ++ UInt32 offs = 0; ++ while (len > matchDistances[offs]) ++ offs += 2; ++ for (; ; len++) ++ { ++ COptimal *opt; ++ UInt32 distance = matchDistances[offs + 1]; ++ ++ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; ++ UInt32 lenToPosState = GetLenToPosState(len); ++ if (distance < kNumFullDistances) ++ curAndLenPrice += p->distancesPrices[lenToPosState][distance]; ++ else ++ { ++ UInt32 slot; ++ GetPosSlot2(distance, slot); ++ curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; ++ } ++ opt = &p->opt[len]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = 0; ++ opt->backPrev = distance + LZMA_NUM_REPS; ++ opt->prev1IsChar = False; ++ } ++ if (len == matchDistances[offs]) ++ { ++ offs += 2; ++ if (offs == numDistancePairs) ++ break; ++ } ++ } ++ } ++ ++ cur = 0; ++ ++ #ifdef SHOW_STAT2 ++ if (position >= 0) ++ { ++ unsigned i; ++ printf("\n pos = %4X", position); ++ for (i = cur; i <= lenEnd; i++) ++ printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); ++ } ++ #endif ++ ++ for (;;) ++ { ++ UInt32 numAvailableBytesFull, newLen, numDistancePairs; ++ COptimal *curOpt; ++ UInt32 posPrev; ++ UInt32 state; ++ UInt32 curPrice; ++ Bool nextIsChar; ++ const Byte *data; ++ Byte currentByte, matchByte; ++ UInt32 posState; ++ UInt32 curAnd1Price; ++ COptimal *nextOpt; ++ UInt32 matchPrice, repMatchPrice; ++ UInt32 numAvailableBytes; ++ UInt32 startLen; ++ ++ cur++; ++ if (cur == lenEnd) ++ return Backward(p, backRes, cur); ++ ++ numAvailableBytesFull = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); ++ newLen = ReadMatchDistances(p, &numDistancePairs); ++ if (newLen >= p->numFastBytes) ++ { ++ p->numDistancePairs = numDistancePairs; ++ p->longestMatchLength = newLen; ++ p->longestMatchWasFound = True; ++ return Backward(p, backRes, cur); ++ } ++ position++; ++ curOpt = &p->opt[cur]; ++ posPrev = curOpt->posPrev; ++ if (curOpt->prev1IsChar) ++ { ++ posPrev--; ++ if (curOpt->prev2) ++ { ++ state = p->opt[curOpt->posPrev2].state; ++ if (curOpt->backPrev2 < LZMA_NUM_REPS) ++ state = kRepNextStates[state]; ++ else ++ state = kMatchNextStates[state]; ++ } ++ else ++ state = p->opt[posPrev].state; ++ state = kLiteralNextStates[state]; ++ } ++ else ++ state = p->opt[posPrev].state; ++ if (posPrev == cur - 1) ++ { ++ if (IsShortRep(curOpt)) ++ state = kShortRepNextStates[state]; ++ else ++ state = kLiteralNextStates[state]; ++ } ++ else ++ { ++ UInt32 pos; ++ const COptimal *prevOpt; ++ if (curOpt->prev1IsChar && curOpt->prev2) ++ { ++ posPrev = curOpt->posPrev2; ++ pos = curOpt->backPrev2; ++ state = kRepNextStates[state]; ++ } ++ else ++ { ++ pos = curOpt->backPrev; ++ if (pos < LZMA_NUM_REPS) ++ state = kRepNextStates[state]; ++ else ++ state = kMatchNextStates[state]; ++ } ++ prevOpt = &p->opt[posPrev]; ++ if (pos < LZMA_NUM_REPS) ++ { ++ UInt32 i; ++ reps[0] = prevOpt->backs[pos]; ++ for (i = 1; i <= pos; i++) ++ reps[i] = prevOpt->backs[i - 1]; ++ for (; i < LZMA_NUM_REPS; i++) ++ reps[i] = prevOpt->backs[i]; ++ } ++ else ++ { ++ UInt32 i; ++ reps[0] = (pos - LZMA_NUM_REPS); ++ for (i = 1; i < LZMA_NUM_REPS; i++) ++ reps[i] = prevOpt->backs[i - 1]; ++ } ++ } ++ curOpt->state = (CState)state; ++ ++ curOpt->backs[0] = reps[0]; ++ curOpt->backs[1] = reps[1]; ++ curOpt->backs[2] = reps[2]; ++ curOpt->backs[3] = reps[3]; ++ ++ curPrice = curOpt->price; ++ nextIsChar = False; ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ currentByte = *data; ++ matchByte = *(data - (reps[0] + 1)); ++ ++ posState = (position & p->pbMask); ++ ++ curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); ++ { ++ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); ++ curAnd1Price += ++ (!IsCharState(state) ? ++ LitEnc_GetPriceMatched(probs, currentByte, matchByte, p->ProbPrices) : ++ LitEnc_GetPrice(probs, currentByte, p->ProbPrices)); ++ } ++ ++ nextOpt = &p->opt[cur + 1]; ++ ++ if (curAnd1Price < nextOpt->price) ++ { ++ nextOpt->price = curAnd1Price; ++ nextOpt->posPrev = cur; ++ MakeAsChar(nextOpt); ++ nextIsChar = True; ++ } ++ ++ matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); ++ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); ++ ++ if (matchByte == currentByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) ++ { ++ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); ++ if (shortRepPrice <= nextOpt->price) ++ { ++ nextOpt->price = shortRepPrice; ++ nextOpt->posPrev = cur; ++ MakeAsShortRep(nextOpt); ++ nextIsChar = True; ++ } ++ } ++ ++ { ++ UInt32 temp = kNumOpts - 1 - cur; ++ if (temp < numAvailableBytesFull) ++ numAvailableBytesFull = temp; ++ } ++ numAvailableBytes = numAvailableBytesFull; ++ ++ if (numAvailableBytes < 2) ++ continue; ++ if (numAvailableBytes > p->numFastBytes) ++ numAvailableBytes = p->numFastBytes; ++ if (!nextIsChar && matchByte != currentByte) /* speed optimization */ ++ { ++ /* try Literal + rep0 */ ++ UInt32 temp; ++ UInt32 lenTest2; ++ const Byte *data2 = data - (reps[0] + 1); ++ UInt32 limit = p->numFastBytes + 1; ++ if (limit > numAvailableBytesFull) ++ limit = numAvailableBytesFull; ++ ++ for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); ++ lenTest2 = temp - 1; ++ if (lenTest2 >= 2) ++ { ++ UInt32 state2 = kLiteralNextStates[state]; ++ UInt32 posStateNext = (position + 1) & p->pbMask; ++ UInt32 nextRepMatchPrice = curAnd1Price + ++ GET_PRICE_1(p->isMatch[state2][posStateNext]) + ++ GET_PRICE_1(p->isRep[state2]); ++ /* for (; lenTest2 >= 2; lenTest2--) */ ++ { ++ UInt32 curAndLenPrice; ++ COptimal *opt; ++ UInt32 offset = cur + 1 + lenTest2; ++ while (lenEnd < offset) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); ++ opt = &p->opt[offset]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur + 1; ++ opt->backPrev = 0; ++ opt->prev1IsChar = True; ++ opt->prev2 = False; ++ } ++ } ++ } ++ } ++ ++ startLen = 2; /* speed optimization */ ++ { ++ UInt32 repIndex; ++ for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) ++ { ++ UInt32 lenTest; ++ UInt32 lenTestTemp; ++ UInt32 price; ++ const Byte *data2 = data - (reps[repIndex] + 1); ++ if (data[0] != data2[0] || data[1] != data2[1]) ++ continue; ++ for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++); ++ while (lenEnd < cur + lenTest) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ lenTestTemp = lenTest; ++ price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); ++ do ++ { ++ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; ++ COptimal *opt = &p->opt[cur + lenTest]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur; ++ opt->backPrev = repIndex; ++ opt->prev1IsChar = False; ++ } ++ } ++ while (--lenTest >= 2); ++ lenTest = lenTestTemp; ++ ++ if (repIndex == 0) ++ startLen = lenTest + 1; ++ ++ /* if (_maxMode) */ ++ { ++ UInt32 lenTest2 = lenTest + 1; ++ UInt32 limit = lenTest2 + p->numFastBytes; ++ UInt32 nextRepMatchPrice; ++ if (limit > numAvailableBytesFull) ++ limit = numAvailableBytesFull; ++ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); ++ lenTest2 -= lenTest + 1; ++ if (lenTest2 >= 2) ++ { ++ UInt32 state2 = kRepNextStates[state]; ++ UInt32 posStateNext = (position + lenTest) & p->pbMask; ++ UInt32 curAndLenCharPrice = ++ price + p->repLenEnc.prices[posState][lenTest - 2] + ++ GET_PRICE_0(p->isMatch[state2][posStateNext]) + ++ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), ++ data[lenTest], data2[lenTest], p->ProbPrices); ++ state2 = kLiteralNextStates[state2]; ++ posStateNext = (position + lenTest + 1) & p->pbMask; ++ nextRepMatchPrice = curAndLenCharPrice + ++ GET_PRICE_1(p->isMatch[state2][posStateNext]) + ++ GET_PRICE_1(p->isRep[state2]); ++ ++ /* for (; lenTest2 >= 2; lenTest2--) */ ++ { ++ UInt32 curAndLenPrice; ++ COptimal *opt; ++ UInt32 offset = cur + lenTest + 1 + lenTest2; ++ while (lenEnd < offset) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); ++ opt = &p->opt[offset]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur + lenTest + 1; ++ opt->backPrev = 0; ++ opt->prev1IsChar = True; ++ opt->prev2 = True; ++ opt->posPrev2 = cur; ++ opt->backPrev2 = repIndex; ++ } ++ } ++ } ++ } ++ } ++ } ++ /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ ++ if (newLen > numAvailableBytes) ++ { ++ newLen = numAvailableBytes; ++ for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2); ++ matchDistances[numDistancePairs] = newLen; ++ numDistancePairs += 2; ++ } ++ if (newLen >= startLen) ++ { ++ UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); ++ UInt32 offs, curBack, posSlot; ++ UInt32 lenTest; ++ while (lenEnd < cur + newLen) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ ++ offs = 0; ++ while (startLen > matchDistances[offs]) ++ offs += 2; ++ curBack = matchDistances[offs + 1]; ++ GetPosSlot2(curBack, posSlot); ++ for (lenTest = /*2*/ startLen; ; lenTest++) ++ { ++ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; ++ UInt32 lenToPosState = GetLenToPosState(lenTest); ++ COptimal *opt; ++ if (curBack < kNumFullDistances) ++ curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; ++ else ++ curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; ++ ++ opt = &p->opt[cur + lenTest]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur; ++ opt->backPrev = curBack + LZMA_NUM_REPS; ++ opt->prev1IsChar = False; ++ } ++ ++ if (/*_maxMode && */lenTest == matchDistances[offs]) ++ { ++ /* Try Match + Literal + Rep0 */ ++ const Byte *data2 = data - (curBack + 1); ++ UInt32 lenTest2 = lenTest + 1; ++ UInt32 limit = lenTest2 + p->numFastBytes; ++ UInt32 nextRepMatchPrice; ++ if (limit > numAvailableBytesFull) ++ limit = numAvailableBytesFull; ++ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); ++ lenTest2 -= lenTest + 1; ++ if (lenTest2 >= 2) ++ { ++ UInt32 state2 = kMatchNextStates[state]; ++ UInt32 posStateNext = (position + lenTest) & p->pbMask; ++ UInt32 curAndLenCharPrice = curAndLenPrice + ++ GET_PRICE_0(p->isMatch[state2][posStateNext]) + ++ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), ++ data[lenTest], data2[lenTest], p->ProbPrices); ++ state2 = kLiteralNextStates[state2]; ++ posStateNext = (posStateNext + 1) & p->pbMask; ++ nextRepMatchPrice = curAndLenCharPrice + ++ GET_PRICE_1(p->isMatch[state2][posStateNext]) + ++ GET_PRICE_1(p->isRep[state2]); ++ ++ /* for (; lenTest2 >= 2; lenTest2--) */ ++ { ++ UInt32 offset = cur + lenTest + 1 + lenTest2; ++ UInt32 curAndLenPrice; ++ COptimal *opt; ++ while (lenEnd < offset) ++ p->opt[++lenEnd].price = kInfinityPrice; ++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); ++ opt = &p->opt[offset]; ++ if (curAndLenPrice < opt->price) ++ { ++ opt->price = curAndLenPrice; ++ opt->posPrev = cur + lenTest + 1; ++ opt->backPrev = 0; ++ opt->prev1IsChar = True; ++ opt->prev2 = True; ++ opt->posPrev2 = cur; ++ opt->backPrev2 = curBack + LZMA_NUM_REPS; ++ } ++ } ++ } ++ offs += 2; ++ if (offs == numDistancePairs) ++ break; ++ curBack = matchDistances[offs + 1]; ++ if (curBack >= kNumFullDistances) ++ GetPosSlot2(curBack, posSlot); ++ } ++ } ++ } ++ } ++} ++ ++#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) ++ ++static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) ++{ ++ UInt32 numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); ++ UInt32 lenMain, numDistancePairs; ++ const Byte *data; ++ UInt32 repLens[LZMA_NUM_REPS]; ++ UInt32 repMaxIndex, i; ++ UInt32 *matchDistances; ++ UInt32 backMain; ++ ++ if (!p->longestMatchWasFound) ++ { ++ lenMain = ReadMatchDistances(p, &numDistancePairs); ++ } ++ else ++ { ++ lenMain = p->longestMatchLength; ++ numDistancePairs = p->numDistancePairs; ++ p->longestMatchWasFound = False; ++ } ++ ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ if (numAvailableBytes > LZMA_MATCH_LEN_MAX) ++ numAvailableBytes = LZMA_MATCH_LEN_MAX; ++ if (numAvailableBytes < 2) ++ { ++ *backRes = (UInt32)(-1); ++ return 1; ++ } ++ ++ repMaxIndex = 0; ++ ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ { ++ const Byte *data2 = data - (p->reps[i] + 1); ++ UInt32 len; ++ if (data[0] != data2[0] || data[1] != data2[1]) ++ { ++ repLens[i] = 0; ++ continue; ++ } ++ for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++); ++ if (len >= p->numFastBytes) ++ { ++ *backRes = i; ++ MovePos(p, len - 1); ++ return len; ++ } ++ repLens[i] = len; ++ if (len > repLens[repMaxIndex]) ++ repMaxIndex = i; ++ } ++ matchDistances = p->matchDistances; ++ if (lenMain >= p->numFastBytes) ++ { ++ *backRes = matchDistances[numDistancePairs - 1] + LZMA_NUM_REPS; ++ MovePos(p, lenMain - 1); ++ return lenMain; ++ } ++ ++ backMain = 0; /* for GCC */ ++ if (lenMain >= 2) ++ { ++ backMain = matchDistances[numDistancePairs - 1]; ++ while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1) ++ { ++ if (!ChangePair(matchDistances[numDistancePairs - 3], backMain)) ++ break; ++ numDistancePairs -= 2; ++ lenMain = matchDistances[numDistancePairs - 2]; ++ backMain = matchDistances[numDistancePairs - 1]; ++ } ++ if (lenMain == 2 && backMain >= 0x80) ++ lenMain = 1; ++ } ++ ++ if (repLens[repMaxIndex] >= 2) ++ { ++ if (repLens[repMaxIndex] + 1 >= lenMain || ++ (repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9))) || ++ (repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15)))) ++ { ++ UInt32 lenRes; ++ *backRes = repMaxIndex; ++ lenRes = repLens[repMaxIndex]; ++ MovePos(p, lenRes - 1); ++ return lenRes; ++ } ++ } ++ ++ if (lenMain >= 2 && numAvailableBytes > 2) ++ { ++ UInt32 i; ++ numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); ++ p->longestMatchLength = ReadMatchDistances(p, &p->numDistancePairs); ++ if (p->longestMatchLength >= 2) ++ { ++ UInt32 newDistance = matchDistances[p->numDistancePairs - 1]; ++ if ((p->longestMatchLength >= lenMain && newDistance < backMain) || ++ (p->longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance)) || ++ (p->longestMatchLength > lenMain + 1) || ++ (p->longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain))) ++ { ++ p->longestMatchWasFound = True; ++ *backRes = (UInt32)(-1); ++ return 1; ++ } ++ } ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; ++ for (i = 0; i < LZMA_NUM_REPS; i++) ++ { ++ UInt32 len; ++ const Byte *data2 = data - (p->reps[i] + 1); ++ if (data[1] != data2[1] || data[2] != data2[2]) ++ { ++ repLens[i] = 0; ++ continue; ++ } ++ for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++); ++ if (len + 1 >= lenMain) ++ { ++ p->longestMatchWasFound = True; ++ *backRes = (UInt32)(-1); ++ return 1; ++ } ++ } ++ *backRes = backMain + LZMA_NUM_REPS; ++ MovePos(p, lenMain - 2); ++ return lenMain; ++ } ++ *backRes = (UInt32)(-1); ++ return 1; ++} ++ ++static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) ++{ ++ UInt32 len; ++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); ++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); ++ p->state = kMatchNextStates[p->state]; ++ len = LZMA_MATCH_LEN_MIN; ++ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); ++ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); ++ RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); ++ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); ++} ++ ++static SRes CheckErrors(CLzmaEnc *p) ++{ ++ if (p->result != SZ_OK) ++ return p->result; ++ if (p->rc.res != SZ_OK) ++ p->result = SZ_ERROR_WRITE; ++ if (p->matchFinderBase.result != SZ_OK) ++ p->result = SZ_ERROR_READ; ++ if (p->result != SZ_OK) ++ p->finished = True; ++ return p->result; ++} ++ ++static SRes Flush(CLzmaEnc *p, UInt32 nowPos) ++{ ++ /* ReleaseMFStream(); */ ++ p->finished = True; ++ if (p->writeEndMark) ++ WriteEndMarker(p, nowPos & p->pbMask); ++ RangeEnc_FlushData(&p->rc); ++ RangeEnc_FlushStream(&p->rc); ++ return CheckErrors(p); ++} ++ ++static void FillAlignPrices(CLzmaEnc *p) ++{ ++ UInt32 i; ++ for (i = 0; i < kAlignTableSize; i++) ++ p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); ++ p->alignPriceCount = 0; ++} ++ ++static void FillDistancesPrices(CLzmaEnc *p) ++{ ++ UInt32 tempPrices[kNumFullDistances]; ++ UInt32 i, lenToPosState; ++ for (i = kStartPosModelIndex; i < kNumFullDistances; i++) ++ { ++ UInt32 posSlot = GetPosSlot1(i); ++ UInt32 footerBits = ((posSlot >> 1) - 1); ++ UInt32 base = ((2 | (posSlot & 1)) << footerBits); ++ tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); ++ } ++ ++ for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) ++ { ++ UInt32 posSlot; ++ const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; ++ UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; ++ for (posSlot = 0; posSlot < p->distTableSize; posSlot++) ++ posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); ++ for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) ++ posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); ++ ++ { ++ UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; ++ UInt32 i; ++ for (i = 0; i < kStartPosModelIndex; i++) ++ distancesPrices[i] = posSlotPrices[i]; ++ for (; i < kNumFullDistances; i++) ++ distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; ++ } ++ } ++ p->matchPriceCount = 0; ++} ++ ++void LzmaEnc_Construct(CLzmaEnc *p) ++{ ++ RangeEnc_Construct(&p->rc); ++ MatchFinder_Construct(&p->matchFinderBase); ++ #ifdef COMPRESS_MF_MT ++ MatchFinderMt_Construct(&p->matchFinderMt); ++ p->matchFinderMt.MatchFinder = &p->matchFinderBase; ++ #endif ++ ++ { ++ CLzmaEncProps props; ++ LzmaEncProps_Init(&props); ++ LzmaEnc_SetProps(p, &props); ++ } ++ ++ #ifndef LZMA_LOG_BSR ++ LzmaEnc_FastPosInit(p->g_FastPos); ++ #endif ++ ++ LzmaEnc_InitPriceTables(p->ProbPrices); ++ p->litProbs = 0; ++ p->saveState.litProbs = 0; ++} ++ ++CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) ++{ ++ void *p; ++ p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); ++ if (p != 0) ++ LzmaEnc_Construct((CLzmaEnc *)p); ++ return p; ++} ++ ++void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) ++{ ++ alloc->Free(alloc, p->litProbs); ++ alloc->Free(alloc, p->saveState.litProbs); ++ p->litProbs = 0; ++ p->saveState.litProbs = 0; ++} ++ ++void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ #ifdef COMPRESS_MF_MT ++ MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); ++ #endif ++ MatchFinder_Free(&p->matchFinderBase, allocBig); ++ LzmaEnc_FreeLits(p, alloc); ++ RangeEnc_Free(&p->rc, alloc); ++} ++ ++void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); ++ alloc->Free(alloc, p); ++} ++ ++static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) ++{ ++ UInt32 nowPos32, startPos32; ++ if (p->inStream != 0) ++ { ++ p->matchFinderBase.stream = p->inStream; ++ p->matchFinder.Init(p->matchFinderObj); ++ p->inStream = 0; ++ } ++ ++ if (p->finished) ++ return p->result; ++ RINOK(CheckErrors(p)); ++ ++ nowPos32 = (UInt32)p->nowPos64; ++ startPos32 = nowPos32; ++ ++ if (p->nowPos64 == 0) ++ { ++ UInt32 numDistancePairs; ++ Byte curByte; ++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) ++ return Flush(p, nowPos32); ++ ReadMatchDistances(p, &numDistancePairs); ++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); ++ p->state = kLiteralNextStates[p->state]; ++ curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); ++ LitEnc_Encode(&p->rc, p->litProbs, curByte); ++ p->additionalOffset--; ++ nowPos32++; ++ } ++ ++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) ++ for (;;) ++ { ++ UInt32 pos, len, posState; ++ ++ if (p->fastMode) ++ len = GetOptimumFast(p, &pos); ++ else ++ len = GetOptimum(p, nowPos32, &pos); ++ ++ #ifdef SHOW_STAT2 ++ printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); ++ #endif ++ ++ posState = nowPos32 & p->pbMask; ++ if (len == 1 && pos == 0xFFFFFFFF) ++ { ++ Byte curByte; ++ CLzmaProb *probs; ++ const Byte *data; ++ ++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); ++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; ++ curByte = *data; ++ probs = LIT_PROBS(nowPos32, *(data - 1)); ++ if (IsCharState(p->state)) ++ LitEnc_Encode(&p->rc, probs, curByte); ++ else ++ LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); ++ p->state = kLiteralNextStates[p->state]; ++ } ++ else ++ { ++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); ++ if (pos < LZMA_NUM_REPS) ++ { ++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); ++ if (pos == 0) ++ { ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); ++ RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); ++ } ++ else ++ { ++ UInt32 distance = p->reps[pos]; ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); ++ if (pos == 1) ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); ++ else ++ { ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); ++ RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); ++ if (pos == 3) ++ p->reps[3] = p->reps[2]; ++ p->reps[2] = p->reps[1]; ++ } ++ p->reps[1] = p->reps[0]; ++ p->reps[0] = distance; ++ } ++ if (len == 1) ++ p->state = kShortRepNextStates[p->state]; ++ else ++ { ++ LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); ++ p->state = kRepNextStates[p->state]; ++ } ++ } ++ else ++ { ++ UInt32 posSlot; ++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); ++ p->state = kMatchNextStates[p->state]; ++ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); ++ pos -= LZMA_NUM_REPS; ++ GetPosSlot(pos, posSlot); ++ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); ++ ++ if (posSlot >= kStartPosModelIndex) ++ { ++ UInt32 footerBits = ((posSlot >> 1) - 1); ++ UInt32 base = ((2 | (posSlot & 1)) << footerBits); ++ UInt32 posReduced = pos - base; ++ ++ if (posSlot < kEndPosModelIndex) ++ RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); ++ else ++ { ++ RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); ++ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); ++ p->alignPriceCount++; ++ } ++ } ++ p->reps[3] = p->reps[2]; ++ p->reps[2] = p->reps[1]; ++ p->reps[1] = p->reps[0]; ++ p->reps[0] = pos; ++ p->matchPriceCount++; ++ } ++ } ++ p->additionalOffset -= len; ++ nowPos32 += len; ++ if (p->additionalOffset == 0) ++ { ++ UInt32 processed; ++ if (!p->fastMode) ++ { ++ if (p->matchPriceCount >= (1 << 7)) ++ FillDistancesPrices(p); ++ if (p->alignPriceCount >= kAlignTableSize) ++ FillAlignPrices(p); ++ } ++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) ++ break; ++ processed = nowPos32 - startPos32; ++ if (useLimits) ++ { ++ if (processed + kNumOpts + 300 >= maxUnpackSize || ++ RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) ++ break; ++ } ++ else if (processed >= (1 << 15)) ++ { ++ p->nowPos64 += nowPos32 - startPos32; ++ return CheckErrors(p); ++ } ++ } ++ } ++ p->nowPos64 += nowPos32 - startPos32; ++ return Flush(p, nowPos32); ++} ++ ++#define kBigHashDicLimit ((UInt32)1 << 24) ++ ++static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ UInt32 beforeSize = kNumOpts; ++ Bool btMode; ++ if (!RangeEnc_Alloc(&p->rc, alloc)) ++ return SZ_ERROR_MEM; ++ btMode = (p->matchFinderBase.btMode != 0); ++ #ifdef COMPRESS_MF_MT ++ p->mtMode = (p->multiThread && !p->fastMode && btMode); ++ #endif ++ ++ { ++ unsigned lclp = p->lc + p->lp; ++ if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) ++ { ++ LzmaEnc_FreeLits(p, alloc); ++ p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); ++ p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); ++ if (p->litProbs == 0 || p->saveState.litProbs == 0) ++ { ++ LzmaEnc_FreeLits(p, alloc); ++ return SZ_ERROR_MEM; ++ } ++ p->lclp = lclp; ++ } ++ } ++ ++ p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); ++ ++ if (beforeSize + p->dictSize < keepWindowSize) ++ beforeSize = keepWindowSize - p->dictSize; ++ ++ #ifdef COMPRESS_MF_MT ++ if (p->mtMode) ++ { ++ RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); ++ p->matchFinderObj = &p->matchFinderMt; ++ MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); ++ } ++ else ++ #endif ++ { ++ if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) ++ return SZ_ERROR_MEM; ++ p->matchFinderObj = &p->matchFinderBase; ++ MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); ++ } ++ return SZ_OK; ++} ++ ++void LzmaEnc_Init(CLzmaEnc *p) ++{ ++ UInt32 i; ++ p->state = 0; ++ for(i = 0 ; i < LZMA_NUM_REPS; i++) ++ p->reps[i] = 0; ++ ++ RangeEnc_Init(&p->rc); ++ ++ ++ for (i = 0; i < kNumStates; i++) ++ { ++ UInt32 j; ++ for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) ++ { ++ p->isMatch[i][j] = kProbInitValue; ++ p->isRep0Long[i][j] = kProbInitValue; ++ } ++ p->isRep[i] = kProbInitValue; ++ p->isRepG0[i] = kProbInitValue; ++ p->isRepG1[i] = kProbInitValue; ++ p->isRepG2[i] = kProbInitValue; ++ } ++ ++ { ++ UInt32 num = 0x300 << (p->lp + p->lc); ++ for (i = 0; i < num; i++) ++ p->litProbs[i] = kProbInitValue; ++ } ++ ++ { ++ for (i = 0; i < kNumLenToPosStates; i++) ++ { ++ CLzmaProb *probs = p->posSlotEncoder[i]; ++ UInt32 j; ++ for (j = 0; j < (1 << kNumPosSlotBits); j++) ++ probs[j] = kProbInitValue; ++ } ++ } ++ { ++ for(i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) ++ p->posEncoders[i] = kProbInitValue; ++ } ++ ++ LenEnc_Init(&p->lenEnc.p); ++ LenEnc_Init(&p->repLenEnc.p); ++ ++ for (i = 0; i < (1 << kNumAlignBits); i++) ++ p->posAlignEncoder[i] = kProbInitValue; ++ ++ p->longestMatchWasFound = False; ++ p->optimumEndIndex = 0; ++ p->optimumCurrentIndex = 0; ++ p->additionalOffset = 0; ++ ++ p->pbMask = (1 << p->pb) - 1; ++ p->lpMask = (1 << p->lp) - 1; ++} ++ ++void LzmaEnc_InitPrices(CLzmaEnc *p) ++{ ++ if (!p->fastMode) ++ { ++ FillDistancesPrices(p); ++ FillAlignPrices(p); ++ } ++ ++ p->lenEnc.tableSize = ++ p->repLenEnc.tableSize = ++ p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; ++ LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); ++ LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); ++} ++ ++static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ UInt32 i; ++ for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) ++ if (p->dictSize <= ((UInt32)1 << i)) ++ break; ++ p->distTableSize = i * 2; ++ ++ p->finished = False; ++ p->result = SZ_OK; ++ RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); ++ LzmaEnc_Init(p); ++ LzmaEnc_InitPrices(p); ++ p->nowPos64 = 0; ++ return SZ_OK; ++} ++ ++static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, ++ ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ p->inStream = inStream; ++ p->rc.outStream = outStream; ++ return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); ++} ++ ++SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ++ ISeqInStream *inStream, UInt32 keepWindowSize, ++ ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ p->inStream = inStream; ++ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); ++} ++ ++static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) ++{ ++ p->seqBufInStream.funcTable.Read = MyRead; ++ p->seqBufInStream.data = src; ++ p->seqBufInStream.rem = srcLen; ++} ++ ++SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, ++ UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ LzmaEnc_SetInputBuf(p, src, srcLen); ++ p->inStream = &p->seqBufInStream.funcTable; ++ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); ++} ++ ++void LzmaEnc_Finish(CLzmaEncHandle pp) ++{ ++ #ifdef COMPRESS_MF_MT ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ if (p->mtMode) ++ MatchFinderMt_ReleaseStream(&p->matchFinderMt); ++ #endif ++} ++ ++typedef struct _CSeqOutStreamBuf ++{ ++ ISeqOutStream funcTable; ++ Byte *data; ++ SizeT rem; ++ Bool overflow; ++} CSeqOutStreamBuf; ++ ++static size_t MyWrite(void *pp, const void *data, size_t size) ++{ ++ CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; ++ if (p->rem < size) ++ { ++ size = p->rem; ++ p->overflow = True; ++ } ++ memcpy(p->data, data, size); ++ p->rem -= size; ++ p->data += size; ++ return size; ++} ++ ++ ++UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) ++{ ++ const CLzmaEnc *p = (CLzmaEnc *)pp; ++ return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); ++} ++ ++const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) ++{ ++ const CLzmaEnc *p = (CLzmaEnc *)pp; ++ return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; ++} ++ ++SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, ++ Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ UInt64 nowPos64; ++ SRes res; ++ CSeqOutStreamBuf outStream; ++ ++ outStream.funcTable.Write = MyWrite; ++ outStream.data = dest; ++ outStream.rem = *destLen; ++ outStream.overflow = False; ++ ++ p->writeEndMark = False; ++ p->finished = False; ++ p->result = SZ_OK; ++ ++ if (reInit) ++ LzmaEnc_Init(p); ++ LzmaEnc_InitPrices(p); ++ nowPos64 = p->nowPos64; ++ RangeEnc_Init(&p->rc); ++ p->rc.outStream = &outStream.funcTable; ++ ++ res = LzmaEnc_CodeOneBlock(pp, True, desiredPackSize, *unpackSize); ++ ++ *unpackSize = (UInt32)(p->nowPos64 - nowPos64); ++ *destLen -= outStream.rem; ++ if (outStream.overflow) ++ return SZ_ERROR_OUTPUT_EOF; ++ ++ return res; ++} ++ ++SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ++ ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ SRes res = SZ_OK; ++ ++ #ifdef COMPRESS_MF_MT ++ Byte allocaDummy[0x300]; ++ int i = 0; ++ for (i = 0; i < 16; i++) ++ allocaDummy[i] = (Byte)i; ++ #endif ++ ++ RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); ++ ++ for (;;) ++ { ++ res = LzmaEnc_CodeOneBlock(pp, False, 0, 0); ++ if (res != SZ_OK || p->finished != 0) ++ break; ++ if (progress != 0) ++ { ++ res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); ++ if (res != SZ_OK) ++ { ++ res = SZ_ERROR_PROGRESS; ++ break; ++ } ++ } ++ } ++ LzmaEnc_Finish(pp); ++ return res; ++} ++ ++SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ int i; ++ UInt32 dictSize = p->dictSize; ++ if (*size < LZMA_PROPS_SIZE) ++ return SZ_ERROR_PARAM; ++ *size = LZMA_PROPS_SIZE; ++ props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); ++ ++ for (i = 11; i <= 30; i++) ++ { ++ if (dictSize <= ((UInt32)2 << i)) ++ { ++ dictSize = (2 << i); ++ break; ++ } ++ if (dictSize <= ((UInt32)3 << i)) ++ { ++ dictSize = (3 << i); ++ break; ++ } ++ } ++ ++ for (i = 0; i < 4; i++) ++ props[1 + i] = (Byte)(dictSize >> (8 * i)); ++ return SZ_OK; ++} ++ ++SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ SRes res; ++ CLzmaEnc *p = (CLzmaEnc *)pp; ++ ++ CSeqOutStreamBuf outStream; ++ ++ LzmaEnc_SetInputBuf(p, src, srcLen); ++ ++ outStream.funcTable.Write = MyWrite; ++ outStream.data = dest; ++ outStream.rem = *destLen; ++ outStream.overflow = False; ++ ++ p->writeEndMark = writeEndMark; ++ res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, ++ progress, alloc, allocBig); ++ ++ *destLen -= outStream.rem; ++ if (outStream.overflow) ++ return SZ_ERROR_OUTPUT_EOF; ++ return res; ++} ++ ++SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, ++ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) ++{ ++ CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); ++ SRes res; ++ if (p == 0) ++ return SZ_ERROR_MEM; ++ ++ res = LzmaEnc_SetProps(p, props); ++ if (res == SZ_OK) ++ { ++ res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); ++ if (res == SZ_OK) ++ res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, ++ writeEndMark, progress, alloc, allocBig); ++ } ++ ++ LzmaEnc_Destroy(p, alloc, allocBig); ++ return res; ++} +--- a/mkfs.jffs2.c ++++ b/mkfs.jffs2.c +@@ -1659,11 +1659,11 @@ int main(int argc, char **argv) + } + erase_block_size *= units; + +- /* If it's less than 8KiB, they're not allowed */ +- if (erase_block_size < 0x2000) { +- fprintf(stderr, "Erase size 0x%x too small. Increasing to 8KiB minimum\n", ++ /* If it's less than 4KiB, they're not allowed */ ++ if (erase_block_size < 0x1000) { ++ fprintf(stderr, "Erase size 0x%x too small. Increasing to 4KiB minimum\n", + erase_block_size); +- erase_block_size = 0x2000; ++ erase_block_size = 0x1000; + } + break; + } diff --git a/package/utils/ugps/Makefile b/package/utils/ugps/Makefile new file mode 100644 index 0000000..e30578f --- /dev/null +++ b/package/utils/ugps/Makefile @@ -0,0 +1,50 @@ +# +# 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:=ugps +PKG_VERSION:=2015-08-17 +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_URL:=git://git.openwrt.org/project/ugps.git +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=971e6703eb9bed936cc62cd335105bd2acca14ef +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.bz2 + +PKG_MAINTAINER:=John Crispin <blogic@openwrt.org> +PKG_LICENSE:=GPL-2.0+ + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/ugps + SECTION:=utils + CATEGORY:=Utilities + TITLE:=OpenWrt GPS Daemon + DEPENDS:=+libubox +libubus +endef + +TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include + +ifneq ($(CONFIG_USE_GLIBC),) + TARGET_CFLAGS += -D_DEFAULT_SOURCE +endif + +define Package/ugps/conffiles +/etc/config/gps +endef + +define Package/ugps/install + $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d $(1)/etc/config + $(INSTALL_BIN) $(PKG_BUILD_DIR)/ugps $(1)/usr/sbin/ + $(INSTALL_BIN) ./files/ugps.init $(1)/etc/init.d/ugps + $(INSTALL_CONF) ./files/gps.config $(1)/etc/config/gps +endef + +$(eval $(call BuildPackage,ugps)) diff --git a/package/utils/ugps/files/gps.config b/package/utils/ugps/files/gps.config new file mode 100644 index 0000000..d997a59 --- /dev/null +++ b/package/utils/ugps/files/gps.config @@ -0,0 +1,2 @@ +config gps + option 'tty' 'ttyACM0' diff --git a/package/utils/ugps/files/ugps.init b/package/utils/ugps/files/ugps.init new file mode 100644 index 0000000..621d017 --- /dev/null +++ b/package/utils/ugps/files/ugps.init @@ -0,0 +1,22 @@ +#!/bin/sh /etc/rc.common +# Copyright (c) 2014 OpenWrt.org + +START=80 + +USE_PROCD=1 +PROG=/usr/sbin/ugps + +service_triggers() { + procd_add_reload_trigger gps +} + +start_service() { + local tty="$(uci get gps.@gps[-1].tty)" + + [ -d "/sys/class/tty/$tty/" ] || return + + procd_open_instance + procd_set_param command "$PROG" "/dev/$tty" + procd_set_param respawn + procd_close_instance +} diff --git a/package/utils/usbmode/Makefile b/package/utils/usbmode/Makefile new file mode 100644 index 0000000..8319d3e --- /dev/null +++ b/package/utils/usbmode/Makefile @@ -0,0 +1,59 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=usbmode +PKG_VERSION:=2014-08-26 +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=http://git.openwrt.org/project/usbmode.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=993a9a542791953c4804f7ddbb3a07756738e37a +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +CMAKE_INSTALL:=1 + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:= + +PKG_MAINTAINER:=Felix Fietkau <nbd@openwrt.org> + +PKG_DATA_VERSION:=20150115 +PKG_DATA_URL:=http://www.draisberghof.de/usb_modeswitch +PKG_DATA_PATH:=usb-modeswitch-data-$(PKG_DATA_VERSION) +PKG_DATA_FILENAME:=$(PKG_DATA_PATH).tar.bz2 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Download/data + FILE:=$(PKG_DATA_FILENAME) + URL:=$(PKG_DATA_URL) + MD5SUM:=662bcd56a97e560ea974bc710822de51 +endef +$(eval $(call Download,data)) + +define Package/usb-modeswitch + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=+libubox +libblobmsg-json +libusb-1.0 + TITLE:=USB mode switching utility +endef + +define Build/Prepare + $(Build/Prepare/Default) + tar xvfj $(DL_DIR)/$(PKG_DATA_FILENAME) -C $(PKG_BUILD_DIR) + rm -f \ + $(PKG_BUILD_DIR)/$(PKG_DATA_PATH)/usb_modeswitch.d/05c6:1000:sVe=GT + cp ./data/* $(PKG_BUILD_DIR)/$(PKG_DATA_PATH)/usb_modeswitch.d/ +endef + +define Package/usb-modeswitch/install + $(INSTALL_DIR) $(1)/etc/hotplug.d/usb $(1)/etc/init.d $(1)/sbin + perl $(PKG_BUILD_DIR)/convert-modeswitch.pl \ + $(PKG_BUILD_DIR)/$(PKG_DATA_PATH)/usb_modeswitch.d/* \ + > $(1)/etc/usb-mode.json + $(INSTALL_DATA) ./files/usbmode.hotplug $(1)/etc/hotplug.d/usb/20-usb_mode + $(INSTALL_BIN) ./files/usbmode.init $(1)/etc/init.d/usbmode + $(CP) $(PKG_INSTALL_DIR)/usr/sbin/usbmode $(1)/sbin/ +endef + +$(eval $(call BuildPackage,usb-modeswitch)) diff --git a/package/utils/usbmode/data/12d1:1f16 b/package/utils/usbmode/data/12d1:1f16 new file mode 100644 index 0000000..beda01f --- /dev/null +++ b/package/utils/usbmode/data/12d1:1f16 @@ -0,0 +1,2 @@ +# Vodafone K5150 +MBIM=1 diff --git a/package/utils/usbmode/files/usbmode.hotplug b/package/utils/usbmode/files/usbmode.hotplug new file mode 100644 index 0000000..b238894 --- /dev/null +++ b/package/utils/usbmode/files/usbmode.hotplug @@ -0,0 +1 @@ +/etc/init.d/usbmode start diff --git a/package/utils/usbmode/files/usbmode.init b/package/utils/usbmode/files/usbmode.init new file mode 100755 index 0000000..43e8ec5 --- /dev/null +++ b/package/utils/usbmode/files/usbmode.init @@ -0,0 +1,12 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org + +START=20 +USE_PROCD=1 + +start_service() +{ + procd_open_instance + procd_set_param command "/sbin/usbmode" -s + procd_close_instance +} diff --git a/package/utils/usbreset/Makefile b/package/utils/usbreset/Makefile new file mode 100644 index 0000000..d8efa54 --- /dev/null +++ b/package/utils/usbreset/Makefile @@ -0,0 +1,44 @@ +# +# 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:=usbreset +PKG_RELEASE:=4 + +include $(INCLUDE_DIR)/package.mk + +define Package/usbreset + SECTION:=utils + CATEGORY:=Utilities + TITLE:=Utility to send a USB port reset to a USB device + MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org> +endef + +define Package/usbreset/description + This package contains the small usbreset utility which + can be used to send a USB port reset to a USB device - + useful for debugging or to force re-detection of particular + devices. +endef + +define Build/Prepare + $(INSTALL_DIR) $(PKG_BUILD_DIR) + $(INSTALL_DATA) ./src/usbreset.c $(PKG_BUILD_DIR)/ +endef + +define Build/Compile + $(TARGET_CC) $(TARGET_CFLAGS) -Wall \ + -o $(PKG_BUILD_DIR)/usbreset $(PKG_BUILD_DIR)/usbreset.c +endef + +define Package/usbreset/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/usbreset $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,usbreset)) diff --git a/package/utils/usbreset/src/usbreset.c b/package/utils/usbreset/src/usbreset.c new file mode 100644 index 0000000..ead30b1 --- /dev/null +++ b/package/utils/usbreset/src/usbreset.c @@ -0,0 +1,235 @@ +/* usbreset -- send a USB port reset to a USB device */ + +/* + +http://marc.info/?l=linux-usb-users&m=116827193506484&w=2 + +and needs mounted usbfs filesystem + + sudo mount -t usbfs none /proc/bus/usb + +There is a way to suspend a USB device. In order to use it, +you must have a kernel with CONFIG_PM_SYSFS_DEPRECATED turned on. To +suspend a device, do (as root): + + echo -n 2 >/sys/bus/usb/devices/.../power/state + +where the "..." is the ID for your device. To unsuspend, do the same +thing but with a "0" instead of the "2" above. + +Note that this mechanism is slated to be removed from the kernel within +the next year. Hopefully some other mechanism will take its place. + +> To reset a +> device? + +Here's a program to do it. You invoke it as either + + usbreset /proc/bus/usb/BBB/DDD +or + usbreset /dev/usbB.D + +depending on how your system is set up, where BBB and DDD are the bus and +device address numbers. + +Alan Stern + +*/ + +#include <stdio.h> +#include <stdbool.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <ctype.h> +#include <limits.h> +#include <dirent.h> +#include <sys/ioctl.h> +#include <sys/types.h> + +#include <linux/usbdevice_fs.h> + + +static char *usbfs = NULL; + +struct usbentry { + int bus_num; + int dev_num; + int vendor_id; + int product_id; + char vendor_name[128]; + char product_name[128]; +}; + + +static char *sysfs_attr(const char *dev, const char *attr) +{ + int fd, len = 0; + char path[PATH_MAX]; + static char buf[129]; + + memset(buf, 0, sizeof(buf)); + snprintf(path, sizeof(path) - 1, "/sys/bus/usb/devices/%s/%s", dev, attr); + + if ((fd = open(path, O_RDONLY)) >= 0) + { + len = read(fd, buf, sizeof(buf) - 1); + close(fd); + } + + while (--len > 0 && isspace(buf[len])) + buf[len] = 0; + + return (len >= 0) ? buf : NULL; +} + +static struct usbentry * parse_devlist(DIR *d) +{ + char *attr; + struct dirent *e; + static struct usbentry dev; + + do { + e = readdir(d); + + if (!e) + return NULL; + } + while(!isdigit(e->d_name[0]) || strchr(e->d_name, ':')); + + memset(&dev, 0, sizeof(dev)); + + if ((attr = sysfs_attr(e->d_name, "busnum")) != NULL) + dev.bus_num = strtoul(attr, NULL, 10); + + if ((attr = sysfs_attr(e->d_name, "devnum")) != NULL) + dev.dev_num = strtoul(attr, NULL, 10); + + if ((attr = sysfs_attr(e->d_name, "idVendor")) != NULL) + dev.vendor_id = strtoul(attr, NULL, 16); + + if ((attr = sysfs_attr(e->d_name, "idProduct")) != NULL) + dev.product_id = strtoul(attr, NULL, 16); + + if ((attr = sysfs_attr(e->d_name, "manufacturer")) != NULL) + strcpy(dev.vendor_name, attr); + + if ((attr = sysfs_attr(e->d_name, "product")) != NULL) + strcpy(dev.product_name, attr); + + if (dev.bus_num && dev.dev_num && dev.vendor_id && dev.product_id) + return &dev; + + return NULL; +} + +static void list_devices(void) +{ + DIR *devs = opendir("/sys/bus/usb/devices"); + struct usbentry *dev; + + if (!devs) + return; + + while ((dev = parse_devlist(devs)) != NULL) + { + printf(" Number %03d/%03d ID %04x:%04x %s\n", + dev->bus_num, dev->dev_num, + dev->vendor_id, dev->product_id, + dev->product_name); + } + + closedir(devs); +} + +struct usbentry * find_device(int *bus, int *dev, + int *vid, int *pid, + const char *product) +{ + DIR *devs = opendir("/sys/bus/usb/devices"); + + struct usbentry *e, *match = NULL; + + if (!devs) + return NULL; + + while ((e = parse_devlist(devs)) != NULL) + { + if ((bus && (e->bus_num == *bus) && (e->dev_num == *dev)) || + (vid && (e->vendor_id == *vid) && (e->product_id == *pid)) || + (product && !strcasecmp(e->product_name, product))) + { + match = e; + break; + } + } + + closedir(devs); + + return match; +} + +static void reset_device(struct usbentry *dev) +{ + int fd; + char path[PATH_MAX]; + + snprintf(path, sizeof(path) - 1, "/dev/bus/usb/%03d/%03d", + dev->bus_num, dev->dev_num); + + printf("Resetting %s ... ", dev->product_name); + + if ((fd = open(path, O_WRONLY)) > -1) + { + if (ioctl(fd, USBDEVFS_RESET, 0) < 0) + printf("failed [%s]\n", strerror(errno)); + else + printf("ok\n"); + + close(fd); + } + else + { + printf("can't open [%s]\n", strerror(errno)); + } +} + + +int main(int argc, char **argv) +{ + int id1, id2; + struct usbentry *dev; + + if ((argc == 2) && (sscanf(argv[1], "%3d/%3d", &id1, &id2) == 2)) + { + dev = find_device(&id1, &id2, NULL, NULL, NULL); + } + else if ((argc == 2) && (sscanf(argv[1], "%4x:%4x", &id1, &id2) == 2)) + { + dev = find_device(NULL, NULL, &id1, &id2, NULL); + } + else if ((argc == 2) && strlen(argv[1]) < 128) + { + dev = find_device(NULL, NULL, NULL, NULL, argv[1]); + } + else + { + printf("Usage:\n" + " usbreset PPPP:VVVV - reset by product and vendor id\n" + " usbreset BBB/DDD - reset by bus and device number\n" + " usbreset \"Product\" - reset by product name\n\n" + "Devices:\n"); + list_devices(); + return 1; + } + + if (!dev) + { + fprintf(stderr, "No such device found\n"); + return 1; + } + + reset_device(dev); + return 0; +} diff --git a/package/utils/usbutils/Makefile b/package/utils/usbutils/Makefile new file mode 100644 index 0000000..b1c058b --- /dev/null +++ b/package/utils/usbutils/Makefile @@ -0,0 +1,57 @@ +# +# Copyright (C) 2007-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:=usbutils +PKG_VERSION:=007 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=@KERNEL/linux/utils/usb/usbutils +PKG_MD5SUM:=a6bd63d5c44cebb717a960eae22a3ca9 + +USB_IDS_VERSION:=2013-01-16 +USB_IDS_MD5SUM:=2a2344907b6344f0935c86efaf9de620 +USB_IDS_FILE:=usb.ids.$(USB_IDS_VERSION).gz + +PKG_BUILD_PARALLEL:=1 +PKG_INSTALL:=1 + +PKG_MAINTAINER := Felix Fietkau <nbd@openwrt.org> + +include $(INCLUDE_DIR)/package.mk + +define Package/usbutils + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=+libusb-1.0 +zlib +librt +libpthread + TITLE:=USB devices listing utilities + URL:=http://www.linux-usb.org/ +endef + +define Download/usb_ids + FILE:=$(USB_IDS_FILE) + URL:=http://mirror2.openwrt.org/sources + MD5SUM:=$(USB_IDS_MD5SUM) +endef +$(eval $(call Download,usb_ids)) + +define Build/Prepare + $(Build/Prepare/Default) + echo '#!/bin/sh' > $(PKG_BUILD_DIR)/update-usbids.sh.in + echo 'cp $(DL_DIR)/$(USB_IDS_FILE) usb.ids.gz' >> $(PKG_BUILD_DIR)/update-usbids.sh.in +endef + +define Package/usbutils/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lsusb $(1)/usr/bin/ + $(INSTALL_DIR) $(1)/usr/share + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/usb.ids.gz $(1)/usr/share/ +endef + +$(eval $(call BuildPackage,usbutils)) diff --git a/package/utils/util-linux/Makefile b/package/utils/util-linux/Makefile new file mode 100644 index 0000000..f037e6a --- /dev/null +++ b/package/utils/util-linux/Makefile @@ -0,0 +1,644 @@ +# +# 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:=util-linux +PKG_VERSION:=2.25.2 +PKG_RELEASE:=4 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=@KERNEL/linux/utils/$(PKG_NAME)/v2.25 +PKG_MD5SUM:=cab3d7be354000f629bc601238b629b3 + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=COPYING getopt/COPYING libblkid/COPYING libmount/COPYING Documentation/licenses/COPYING.GPLv2 Documentation/licenses/COPYING.LGPLv2.1 libuuid/COPYING Documentation/licenses/COPYING.BSD-3 + +PKG_BUILD_PARALLEL:=1 + +PKG_CONFIG_DEPENDS:= \ + CONFIG_PACKAGE_cal \ + CONFIG_PACKAGE_cfdisk \ + CONFIG_PACKAGE_setterm + +PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk + +define Package/util-linux/Default + SECTION:=utils + CATEGORY:=Utilities + URL:=http://www.kernel.org/pub/linux/utils/util-linux/ +endef + +CONFIGURE_ARGS += \ + --disable-rpath \ + --enable-new-mount \ + --disable-tls \ + --disable-sulogin \ + --without-python \ + --without-udev \ + $(if $(CONFIG_PACKAGE_cal)$(CONFIG_PACKAGE_cfdisk)$(CONFIG_PACKAGE_setterm),--with-ncurses,--without-ncurses) + +TARGET_CFLAGS += $(FPIC) -std=gnu99 + +define Build/InstallDev + $(MAKE) -C $(PKG_BUILD_DIR) \ + BUILDCC="$(HOSTCC)" \ + DESTDIR="$(1)" \ + installdirs install-data + + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) $(PKG_BUILD_DIR)/libblkid/blkid.pc $(1)/usr/lib/pkgconfig + $(CP) $(PKG_BUILD_DIR)/libmount/mount.pc $(1)/usr/lib/pkgconfig + $(CP) $(PKG_BUILD_DIR)/libsmartcols/smartcols.pc $(1)/usr/lib/pkgconfig + $(CP) $(PKG_BUILD_DIR)/libuuid/uuid.pc $(1)/usr/lib/pkgconfig + + $(INSTALL_DIR) $(1)/usr/include/blkid + $(CP) $(PKG_BUILD_DIR)/libblkid/src/blkid.h $(1)/usr/include/blkid + $(INSTALL_DIR) $(1)/usr/include/libmount + $(CP) $(PKG_BUILD_DIR)/libmount/src/libmount.h $(1)/usr/include/libmount + $(INSTALL_DIR) $(1)/usr/include/uuid + $(CP) $(PKG_BUILD_DIR)/libuuid/src/uuid.h $(1)/usr/include/uuid + $(INSTALL_DIR) $(1)/usr/include/smartcols + $(CP) $(PKG_BUILD_DIR)/libsmartcols/src/libsmartcols.h $(1)/usr/include/smartcols + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/.libs/libblkid.{a,so*} $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/.libs/libmount.{a,so*} $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/.libs/libuuid.{a,so*} $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/.libs/libsmartcols.{a,so*} $(1)/usr/lib +endef + +define Package/libblkid +$(call Package/util-linux/Default) + DEPENDS:=+libuuid + TITLE:=block device id library + SECTION:=libs + CATEGORY:=Libraries +endef + +define Package/libblkid/description + The libblkid library is used to identify block devices (disks) as to their + content (e.g. filesystem type, partitions) as well as extracting additional + information such as filesystem labels/volume names, partitions, unique + identifiers/serial numbers... +endef + +define Package/libmount +$(call Package/util-linux/Default) + DEPENDS:=+libblkid + TITLE:=mount library + SECTION:=libs + CATEGORY:=Libraries +endef + +define Package/libmount/description + The libmount library is used to parse /etc/fstab, /etc/mtab and + /proc/self/mountinfo files, manage the mtab file, evaluate mount options... +endef + +define Package/libuuid +$(call Package/util-linux/Default) + TITLE:=DCE compatible Universally Unique Identifier library + SECTION:=libs + CATEGORY:=Libraries +endef + +define Package/libuuid/description + The UUID library is used to generate unique identifiers for objects + that may be accessible beyond the local system. This library + generates UUIDs compatible with those created by the Open Software + Foundation (OSF) Distributed Computing Environment (DCE) utility. +endef + +define Package/libsmartcols +$(call Package/util-linux/Default) + TITLE:=table or tree library + SECTION:=libs + CATEGORY:=Libraries +endef + +define Package/libsmartcols/description + The smartcols library is used to print tables and trees in a pretty way. +endef + +define Package/agetty +$(call Package/util-linux/Default) + TITLE:=alternative Linux getty + SUBMENU=Terminal +endef + +define Package/agetty/description + agetty opens a tty port, prompts for a login name and invokes the + /bin/login command +endef + +define Package/blkid +$(call Package/util-linux/Default) + TITLE:=locate/print block device attributes + DEPENDS:= +libblkid +libuuid + SUBMENU=disc +endef + +define Package/blkid/description + The blkid program is the command-line interface to working with the libblkid + library. +endef + +define Package/cal +$(call Package/util-linux/Default) + TITLE:=display a calendar + DEPENDS:= +libncurses +endef + +define Package/cal/description + cal displays a simple calendar +endef + +define Package/cfdisk +$(call Package/util-linux/Default) + TITLE:=display or manipulate disk partition table + DEPENDS:= +libblkid +libncurses +libsmartcols + SUBMENU:=disc +endef + +define Package/cfdisk/description + cfdisk is a curses-based program for partitioning any hard disk drive +endef + +define Package/dmesg +$(call Package/util-linux/Default) + TITLE:=print or control the kernel ring buffer + DEPENDS:= +librt +endef + +define Package/dmesg/description + dmesg is used to examine or control the kernel ring buffer +endef + +define Package/fdisk +$(call Package/util-linux/Default) + TITLE:=manipulate disk partition table + DEPENDS:= +libblkid +libsmartcols + SUBMENU=disc +endef + +define Package/fdisk/description + a menu-driven program for creation and manipulation of partition tables +endef + +define Package/findfs +$(call Package/util-linux/Default) + TITLE:=find a filesystem by label or UUID + DEPENDS:= +libblkid + SUBMENU=disc +endef + +define Package/findfs/description + findfs will search the disks in the system looking for a filesystem which has + a label matching label or a UUID equal to uuid +endef + +define Package/flock +$(call Package/util-linux/Default) + TITLE:=manage locks from shell scripts +endef + +define Package/flock/description + manages flock locks from within shell scripts or the command line +endef + +define Package/getopt +$(call Package/util-linux/Default) + TITLE:=parse command options (enhanced) +endef + +define Package/getopt/description + getopt is used to break up (parse) options in command lines for easy parsing + by shell procedures, and to check for legal options +endef + +define Package/hwclock +$(call Package/util-linux/Default) + TITLE:=query or set the hardware clock +endef + +define Package/hwclock/description + hwclock is a tool for accessing the Hardware Clock +endef + +define Package/logger +$(call Package/util-linux/Default) + TITLE:=a shell command interface to the syslog system log module +endef + +define Package/logger/description + logger makes entries in the system log, it provides a shell command interface + to the syslog system log module +endef + +define Package/look +$(call Package/util-linux/Default) + TITLE:=display lines beginning with a given string +endef + +define Package/look/description + look utility displays any lines in file which contain string +endef + +define Package/losetup +$(call Package/util-linux/Default) + TITLE:=set up and control loop devices + DEPENDS:= +libsmartcols +endef + +define Package/losetup/description + losetup is used to associate loop devices with regular files or block devices, + to detach loop devices and to query the status of a loop device +endef + +define Package/lsblk +$(call Package/util-linux/Default) + TITLE:=list block devices + DEPENDS:= +libblkid +libmount +libsmartcols + SUBMENU=disc +endef + +define Package/lsblk/description + lsblk lists information about all or the specified block devices +endef + +define Package/mcookie +$(call Package/util-linux/Default) + TITLE:=generate magic cookies for xauth +endef + +define Package/mcookie/description + mcookie generates a 128-bit random hexadecimal number for use with the X + authority system +endef + +define Package/mount-utils +$(call Package/util-linux/Default) + TITLE:=related (u)mount utilities + DEPENDS+= +libmount +libsmartcols +endef + +define Package/mount-utils/description + contains: mount, umount, findmnt +endef + +define Package/namei +$(call Package/util-linux/Default) + TITLE:=follow a pathname until a terminal point is found +endef + +define Package/namei/description + namei uses its arguments as pathnames to any type of Unix file (symlinks, + files, directories, and so forth) +endef + +define Package/prlimit +$(call Package/util-linux/Default) + TITLE:=get and set process resource limits + DEPENDS:= +libsmartcols +endef + +define Package/prlimit/description + Given a process id and one or more resources, prlimit tries to retrieve + and/or modify the limits. +endef + +define Package/rename +$(call Package/util-linux/Default) + TITLE:=rename files +endef + +define Package/rename/description + rename will rename the specified files by replacing the first occurrence of + expression in their name by replacement +endef + +define Package/partx-utils +$(call Package/util-linux/Default) + TITLE:=inform kernel about the presence and numbering of on-disk partitions + DEPENDS:= +libblkid +libsmartcols + SUBMENU=disc +endef + +define Package/partx-utils/description + contains partx, addpart, delpart +endef + +define Package/script-utils +$(call Package/util-linux/Default) + TITLE:=make and replay typescript of terminal session + SUBMENU=Terminal +endef + +define Package/script-utils/description + contains: script, scriptreplay +endef + +define Package/setterm +$(call Package/util-linux/Default) + TITLE:=set terminal attributes + DEPENDS:= +libncurses + SUBMENU:=Terminal +endef + +define Package/setterm/description + setterm writes to standard output a character string that will invoke the + specified terminal capabilities +endef + +define Package/sfdisk +$(call Package/util-linux/Default) + TITLE:=partition table manipulator for Linux + SUBMENU=disc +endef + +define Package/sfdisk/description + list the size of a partition, list the partitions on a device, check the + partitions on a device and repartition a device +endef + +define Package/swap-utils +$(call Package/util-linux/Default) + TITLE:=swap space management utilities + DEPENDS+= +libblkid + SUBMENU:=disc +endef + +define Package/swap-utils/description + contains: mkswap, swaplabel +endef + +define Package/uuidd +$(call Package/util-linux/Default) + TITLE:=UUID generation daemon + DEPENDS:= +libuuid +endef + +define Package/uuidd/description + The uuidd daemon is used by the UUID library to generate universally unique + identifiers (UUIDs), especially time-based UUIDs, in a secure and + guaranteed-unique fashion, even in the face of large numbers of threads + running on different CPUs trying to grab UUIDs. +endef + +define Package/uuidgen +$(call Package/util-linux/Default) + TITLE:=create a new UUID value + DEPENDS:= +libuuid +endef + +define Package/uuidgen/description + The uuidgen program creates (and prints) a new universally unique identifier + (UUID) using the libuuid library. The new UUID can reasonably be considered + unique among all UUIDs created on the local system, and among UUIDs created on + other systems in the past and in the future. +endef + +define Package/wall +$(call Package/util-linux/Default) + TITLE:=send a message to everybody's terminal + SUBMENU=Terminal +endef + +define Package/wall/description + wall sends a message to everybody logged in with their mesg permission + set to yes +endef + +define Package/whereis +$(call Package/util-linux/Default) + TITLE:=locate the binary, source, and manual page files for a command +endef + +define Package/whereis/description + whereis locates source/binary and manuals sections for specified files +endef + +define Package/wipefs +$(call Package/util-linux/Default) + TITLE:=wipe a signature from a device + DEPENDS:= +libblkid + SUBMENU:=disc +endef + +define Package/wipefs/description + wipefs can erase filesystem, raid or partition table signatures (magic + strings) from the specified device to make the signature invisible for + libblkid. +endef + +define Package/libblkid/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/.libs/libblkid.so* $(1)/usr/lib/ +endef + +define Package/libmount/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/.libs/libmount.so* $(1)/usr/lib/ +endef + +define Package/libsmartcols/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/.libs/libsmartcols.so* $(1)/usr/lib/ +endef + +define Package/libuuid/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/.libs/libuuid.so* $(1)/usr/lib/ +endef + +define Package/agetty/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/agetty $(1)/usr/sbin/ +endef + +define Package/blkid/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/blkid $(1)/usr/sbin/ +endef + +define Package/cal/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/cal $(1)/usr/bin/ +endef + +define Package/cfdisk/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/cfdisk $(1)/usr/sbin/ +endef + +define Package/dmesg/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/dmesg $(1)/usr/sbin/ +endef + +define Package/fdisk/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/fdisk $(1)/usr/sbin/ +endef + +define Package/findfs/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/findfs $(1)/usr/sbin/ +endef + +define Package/flock/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/flock $(1)/usr/bin/ +endef + +define Package/getopt/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/getopt $(1)/usr/bin/ +endef + +define Package/hwclock/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/hwclock $(1)/usr/sbin/ +endef + +define Package/logger/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/logger $(1)/usr/bin/ +endef + +define Package/look/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/look $(1)/usr/bin/ +endef + +define Package/losetup/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/losetup $(1)/usr/sbin/ +endef + +define Package/lsblk/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/lsblk $(1)/usr/bin/ +endef + +define Package/mcookie/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/mcookie $(1)/usr/bin/ +endef + +define Package/mount-utils/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/{u,}mount $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/mountpoint $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/findmnt $(1)/usr/bin/ +endef + +define Package/namei/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/namei $(1)/usr/bin/ +endef + +define Package/prlimit/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/prlimit $(1)/usr/bin/ +endef + +define Package/rename/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/rename $(1)/usr/bin/ +endef + +define Package/partx-utils/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/partx $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/addpart $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/delpart $(1)/usr/sbin/ +endef + +define Package/script-utils/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/script $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/scriptreplay $(1)/usr/bin/ +endef + +define Package/setterm/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/setterm $(1)/usr/bin/ +endef + +define Package/sfdisk/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/sfdisk $(1)/usr/sbin/ +endef + +define Package/swap-utils/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/mkswap $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/swaplabel $(1)/usr/sbin/ +endef + +define Package/uuidd/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/uuidd $(1)/usr/sbin/ +endef + +define Package/uuidgen/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/uuidgen $(1)/usr/bin/ +endef + +define Package/wall/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/wall $(1)/usr/bin/ +endef + +define Package/whereis/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/whereis $(1)/usr/bin/ +endef + +define Package/wipefs/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/.libs/wipefs $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,libblkid)) +$(eval $(call BuildPackage,libmount)) +$(eval $(call BuildPackage,libsmartcols)) +$(eval $(call BuildPackage,libuuid)) +$(eval $(call BuildPackage,agetty)) +$(eval $(call BuildPackage,blkid)) +$(eval $(call BuildPackage,cal)) +$(eval $(call BuildPackage,cfdisk)) +$(eval $(call BuildPackage,dmesg)) +$(eval $(call BuildPackage,fdisk)) +$(eval $(call BuildPackage,findfs)) +$(eval $(call BuildPackage,flock)) +$(eval $(call BuildPackage,getopt)) +$(eval $(call BuildPackage,hwclock)) +$(eval $(call BuildPackage,logger)) +$(eval $(call BuildPackage,look)) +$(eval $(call BuildPackage,losetup)) +$(eval $(call BuildPackage,lsblk)) +$(eval $(call BuildPackage,mcookie)) +$(eval $(call BuildPackage,mount-utils)) +$(eval $(call BuildPackage,namei)) +$(eval $(call BuildPackage,prlimit)) +$(eval $(call BuildPackage,rename)) +$(eval $(call BuildPackage,partx-utils)) +$(eval $(call BuildPackage,script-utils)) +$(eval $(call BuildPackage,setterm)) +$(eval $(call BuildPackage,sfdisk)) +$(eval $(call BuildPackage,swap-utils)) +$(eval $(call BuildPackage,uuidd)) +$(eval $(call BuildPackage,uuidgen)) +$(eval $(call BuildPackage,wall)) +$(eval $(call BuildPackage,whereis)) +$(eval $(call BuildPackage,wipefs)) diff --git a/package/utils/util-linux/patches/0001-switch_root-improve-statfs-f_type-portability.patch b/package/utils/util-linux/patches/0001-switch_root-improve-statfs-f_type-portability.patch new file mode 100644 index 0000000..761ace7 --- /dev/null +++ b/package/utils/util-linux/patches/0001-switch_root-improve-statfs-f_type-portability.patch @@ -0,0 +1,49 @@ +From 8f806bb1ea30f15db7ca36d1cfa79349f8115302 Mon Sep 17 00:00:00 2001 +From: Karel Zak <kzak@redhat.com> +Date: Thu, 6 Nov 2014 12:50:27 +0100 +Subject: [PATCH] switch_root: improve statfs->f_type portability + +__SWORD_TYPE is not available everywhere, for example it's not defined +by musl libc. It also seems that __SWORD_TYPE is not used for f_type +on some architectures (s390x). + +Reported-by: Natanael Copa <ncopa@alpinelinux.org> +Signed-off-by: Karel Zak <kzak@redhat.com> +--- + include/statfs_magic.h | 11 +++++++++++ + sys-utils/switch_root.c | 4 ++-- + 2 files changed, 13 insertions(+), 2 deletions(-) + +--- a/include/statfs_magic.h ++++ b/include/statfs_magic.h +@@ -1,6 +1,17 @@ + #ifndef UTIL_LINUX_STATFS_MAGIC_H + #define UTIL_LINUX_STATFS_MAGIC_H + ++#include <sys/statfs.h> ++ ++/* ++ * If possible then don't depend on internal libc __SWORD_TYPE type. ++ */ ++#ifdef __GNUC__ ++typedef __typeof__( ((struct statfs *)0)->f_type ) ul_statfs_ftype_t; ++#else ++typedef __SWORD_TYPE ul_statfs_ftype_t; ++#endif ++ + /* + * Unfortunately, Linux kernel hedeader file <linux/magic.h> is incomplete + * mess and kernel returns by statfs f_type many numbers that are nowhere +--- a/sys-utils/switch_root.c ++++ b/sys-utils/switch_root.c +@@ -181,8 +181,8 @@ static int switchroot(const char *newroo + if (pid <= 0) { + struct statfs stfs; + if (fstatfs(cfd, &stfs) == 0 && +- (stfs.f_type == (__SWORD_TYPE)STATFS_RAMFS_MAGIC || +- stfs.f_type == (__SWORD_TYPE)STATFS_TMPFS_MAGIC)) ++ (stfs.f_type == (ul_statfs_ftype_t) STATFS_RAMFS_MAGIC || ++ stfs.f_type == (ul_statfs_ftype_t) STATFS_TMPFS_MAGIC)) + recursiveRemove(cfd); + else + warn(_("old root filesystem is not an initramfs")); diff --git a/package/utils/util-linux/patches/0002-lib-colors-use-static-buffers-when-parse-scheme.patch b/package/utils/util-linux/patches/0002-lib-colors-use-static-buffers-when-parse-scheme.patch new file mode 100644 index 0000000..ccd82fd --- /dev/null +++ b/package/utils/util-linux/patches/0002-lib-colors-use-static-buffers-when-parse-scheme.patch @@ -0,0 +1,126 @@ +From 6508db29ded734ac4ff5e5e19486c143c9eb3d89 Mon Sep 17 00:00:00 2001 +From: Karel Zak <kzak@redhat.com> +Date: Fri, 21 Nov 2014 12:23:47 +0100 +Subject: [PATCH] lib/colors: use static buffers when parse scheme + +* use static buffers when parse scheme colors +* cleanup deallocation on error in sequence parser + +Signed-off-by: Karel Zak <kzak@redhat.com> +--- + +This is modified upstream patch. + +--- a/lib/colors.c ++++ b/lib/colors.c +@@ -416,28 +416,31 @@ static int colors_add_scheme(struct ul_c + char *name, + char *seq0) + { +- struct ul_color_scheme *cs; +- char *seq; ++ struct ul_color_scheme *cs = NULL; ++ char *seq = NULL; + int rc; + + if (!cc || !name || !*name || !seq0 || !*seq0) + return -EINVAL; + + rc = cn_sequence(seq0, &seq); +- free(seq0); + if (rc) + return rc; + ++ rc = -ENOMEM; ++ + /* convert logical name (e.g. "red") to real ESC code */ + if (isalpha(*seq)) { + const char *s = color_sequence_from_colorname(seq); + char *p; + +- if (!s) +- return -EINVAL; ++ if (!s) { ++ rc = -EINVAL; ++ goto err; ++ } + p = strdup(s); + if (!p) +- return -ENOMEM; ++ goto err; + free(seq); + seq = p; + } +@@ -447,17 +450,28 @@ static int colors_add_scheme(struct ul_c + void *tmp = realloc(cc->schemes, (cc->nschemes + 10) + * sizeof(struct ul_color_scheme)); + if (!tmp) +- return -ENOMEM; ++ goto err; + cc->schemes = tmp; + cc->schemes_sz = cc->nschemes + 10; + } + + /* add a new item */ +- cs = &cc->schemes[cc->nschemes++]; +- cs->name = name; ++ cs = &cc->schemes[cc->nschemes]; + cs->seq = seq; ++ cs->name = strdup(name); ++ if (!cs->name) ++ goto err; + ++ cc->nschemes++; + return 0; ++err: ++ if (cs) { ++ free(cs->seq); ++ free(cs->name); ++ cs->seq = cs->name = NULL; ++ } else ++ free(seq); ++ return rc; + } + + /* +@@ -543,7 +557,8 @@ static int colors_read_schemes(struct ul + { + int rc = 0; + FILE *f = NULL; +- char buf[BUFSIZ]; ++ char buf[BUFSIZ], ++ cn[129], seq[129]; + + if (!cc->configured) + rc = colors_read_configuration(cc); +@@ -560,7 +575,6 @@ static int colors_read_schemes(struct ul + } + + while (fgets(buf, sizeof(buf), f)) { +- char *cn = NULL, *seq = NULL; + char *p = strchr(buf, '\n'); + + if (!p) { +@@ -576,17 +590,14 @@ static int colors_read_schemes(struct ul + if (*p == '\0' || *p == '#') + continue; + +- rc = sscanf(p, UL_SCNsA" " /* name */ +- UL_SCNsA, /* color */ +- &cn, &seq); +- if (rc == 2 && cn && seq) ++ rc = sscanf(p, "%128[^ ] %128[^\n ]", cn, seq); ++ if (rc == 2 && *cn && *seq) { + rc = colors_add_scheme(cc, cn, seq); /* set rc=0 on success */ +- if (rc) { +- free(cn); +- free(seq); ++ if (rc) ++ goto done; + } +- rc = 0; + } ++ rc = 0; + + done: + if (f) diff --git a/package/utils/util-linux/patches/001-no-printf-alloc.patch b/package/utils/util-linux/patches/001-no-printf-alloc.patch new file mode 100644 index 0000000..ad9eef0 --- /dev/null +++ b/package/utils/util-linux/patches/001-no-printf-alloc.patch @@ -0,0 +1,104 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -798,7 +798,6 @@ AC_ARG_ENABLE([libmount], + ) + UL_BUILD_INIT([libmount]) + UL_REQUIRES_BUILD([libmount], [libblkid]) +-UL_REQUIRES_HAVE([libmount], [scanf_alloc_modifier], [scanf string alloc modifier]) + AM_CONDITIONAL([BUILD_LIBMOUNT], [test "x$build_libmount" = xyes]) + AM_CONDITIONAL([BUILD_LIBMOUNT_TESTS], [test "x$build_libmount" = xyes -a "x$enable_static" = xyes]) + +--- a/libmount/src/tab_parse.c ++++ b/libmount/src/tab_parse.c +@@ -22,6 +22,10 @@ + #include "pathnames.h" + #include "strutils.h" + ++#ifndef HAVE_SCANF_MS_MODIFIER ++# define UL_SCNsA "%s" ++#endif ++ + static int next_number(char **s, int *num) + { + char *end = NULL; +@@ -52,16 +56,31 @@ static int mnt_parse_table_line(struct l + int rc, n = 0, xrc; + char *src = NULL, *fstype = NULL, *optstr = NULL; + ++#ifndef HAVE_SCANF_MS_MODIFIER ++ size_t len = strlen(s) + 1; ++ src = malloc(len); ++ fstype = malloc(len); ++ fs->target = malloc(len); ++ optstr = malloc(len); ++#endif ++ + rc = sscanf(s, UL_SCNsA" " /* (1) source */ + UL_SCNsA" " /* (2) target */ + UL_SCNsA" " /* (3) FS type */ + UL_SCNsA" " /* (4) options */ + "%n", /* byte count */ + ++#ifdef HAVE_SCANF_MS_MODIFIER + &src, + &fs->target, + &fstype, + &optstr, ++#else ++ src, ++ fs->target, ++ fstype, ++ optstr, ++#endif + &n); + xrc = rc; + +@@ -127,6 +146,16 @@ static int mnt_parse_mountinfo_line(stru + unsigned int maj, min; + char *fstype = NULL, *src = NULL, *p; + ++#ifndef HAVE_SCANF_MS_MODIFIER ++ size_t len = strlen(s) + 1; ++ fs->root = malloc(len); ++ fs->target = malloc(len); ++ fs->vfs_optstr = malloc(len); ++ fs->fs_optstr = malloc(len); ++ fstype = malloc(len); ++ src = malloc(len); ++#endif ++ + rc = sscanf(s, "%d " /* (1) id */ + "%d " /* (2) parent */ + "%u:%u " /* (3) maj:min */ +@@ -138,9 +167,15 @@ static int mnt_parse_mountinfo_line(stru + &fs->id, + &fs->parent, + &maj, &min, ++#ifdef HAVE_SCANF_MS_MODIFIER + &fs->root, + &fs->target, + &fs->vfs_optstr, ++#else ++ fs->root, ++ fs->target, ++ fs->vfs_optstr, ++#endif + &end); + + if (rc >= 7 && end > 0) +@@ -160,9 +195,15 @@ static int mnt_parse_mountinfo_line(stru + UL_SCNsA" " /* (9) source */ + UL_SCNsA, /* (10) fs options (fs specific) */ + ++#ifdef HAVE_SCANF_MS_MODIFIER + &fstype, + &src, + &fs->fs_optstr); ++#else ++ fstype, ++ src, ++ fs->fs_optstr); ++#endif + + if (rc >= 10) { + size_t sz; diff --git a/package/utils/util-linux/patches/002-mkostemp.patch b/package/utils/util-linux/patches/002-mkostemp.patch new file mode 100644 index 0000000..0281842 --- /dev/null +++ b/package/utils/util-linux/patches/002-mkostemp.patch @@ -0,0 +1,46 @@ +Support older hosts with latest util-linux-native + +mkostemp is not defined on older machines. So we detect this and +provide a define that uses mkstemp instead. + +O_CLOEXEC is not defined on older machines. It is however defined +in the 'c.h' header. Fix up the users to include 'c.h'. + +fdisks/fdisksunlabel.c was modified to use qsort_r, however +this is not defined on older hosts. Revert: + commit c69bbca9c1f6645097bd20fe3a21f5a99a2a0698 + fdisk: (sun): use ask API, remove global variable + +Upstream-Status: Inappropriate [other] +Patches revert upstream changes in order to support older +machines. + +Signed-off-by: Mark Hatle <mark.hatle@windriver.com> +--- + +--- a/configure.ac ++++ b/configure.ac +@@ -315,6 +315,7 @@ AC_CHECK_FUNCS([ \ + llseek \ + lseek64 \ + mempcpy \ ++ mkostemp \ + nanosleep \ + open_memstream \ + personality \ +--- a/include/c.h ++++ b/include/c.h +@@ -233,6 +233,13 @@ static inline int dirfd(DIR *d) + #endif + + /* ++ * mkostemp replacement ++ */ ++#ifndef HAVE_MKOSTEMP ++#define mkostemp(template, flags) mkstemp(template) ++#endif ++ ++/* + * MAXHOSTNAMELEN replacement + */ + static inline size_t get_hostname_max(void) diff --git a/package/utils/util-linux/patches/003-fix_pkgconfig_files.patch b/package/utils/util-linux/patches/003-fix_pkgconfig_files.patch new file mode 100644 index 0000000..ac590a0 --- /dev/null +++ b/package/utils/util-linux/patches/003-fix_pkgconfig_files.patch @@ -0,0 +1,62 @@ +--- a/libuuid/Makemodule.am ++++ b/libuuid/Makemodule.am +@@ -4,7 +4,6 @@ include libuuid/man/Makemodule.am + include libuuid/src/Makemodule.am + + pkgconfig_DATA += libuuid/uuid.pc +-PATHFILES += libuuid/uuid.pc + EXTRA_DIST += libuuid/COPYING + + endif # BUILD_LIBUUID +--- a/configure.ac ++++ b/configure.ac +@@ -1802,15 +1802,19 @@ AC_CONFIG_HEADERS([config.h]) + # + AC_CONFIG_FILES([ + Makefile ++libblkid/blkid.pc + libblkid/docs/Makefile + libblkid/docs/version.xml + libblkid/src/blkid.h ++libmount/mount.pc + libmount/docs/Makefile + libmount/docs/version.xml + libmount/src/libmount.h ++libsmartcols/smartcols.pc + libsmartcols/docs/Makefile + libsmartcols/docs/version.xml + libsmartcols/src/libsmartcols.h ++libuuid/uuid.pc + po/Makefile.in + ]) + +--- a/libblkid/Makemodule.am ++++ b/libblkid/Makemodule.am +@@ -9,7 +9,6 @@ SUBDIRS += libblkid/docs + endif + + pkgconfig_DATA += libblkid/blkid.pc +-PATHFILES += libblkid/blkid.pc + dist_man_MANS += libblkid/libblkid.3 + EXTRA_DIST += libblkid/libblkid.3 libblkid/COPYING + +--- a/libmount/Makemodule.am ++++ b/libmount/Makemodule.am +@@ -9,7 +9,6 @@ SUBDIRS += libmount/docs + endif + + pkgconfig_DATA += libmount/mount.pc +-PATHFILES += libmount/mount.pc + EXTRA_DIST += libmount/COPYING + + endif # BUILD_LIBMOUNT +--- a/libsmartcols/Makemodule.am ++++ b/libsmartcols/Makemodule.am +@@ -8,7 +8,6 @@ SUBDIRS += libsmartcols/docs + endif + + pkgconfig_DATA += libsmartcols/smartcols.pc +-PATHFILES += libsmartcols/smartcols.pc + EXTRA_DIST += libsmartcols/COPYING + + endif # BUILD_LIBSMARTCOLS diff --git a/package/utils/xfsprogs/Makefile b/package/utils/xfsprogs/Makefile new file mode 100644 index 0000000..6333077 --- /dev/null +++ b/package/utils/xfsprogs/Makefile @@ -0,0 +1,90 @@ +# +# 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_RELEASE:=1 +PKG_VERSION:=3.1.7 +PKG_SOURCE_URL:=ftp://oss.sgi.com/projects/xfs/previous/ +PKG_MD5SUM:=049cf9873794ea49d0bb3f12d45748a4 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_INSTALL:=1 +PKG_FIXUP:=autoreconf +PKG_CHECK_FORMAT_SECURITY:=0 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/xfsprogs/default + SECTION:=utils + CATEGORY:=Utilities + SUBMENU:=Filesystem + DEPENDS:=+libuuid +libpthread +librt + URL:=http://oss.sgi.com/projects/xfs +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 += \ + --enable-gettext=no \ + --enable-lib64=no \ + --enable-blkid=no + +TARGET_CFLAGS += \ + -I$(STAGING_DIR)/usr/include \ + -D_LARGEFILE64_SOURCE \ + -D_FILE_OFFSET_BITS=64 \ + -D_GNU_SOURCE + +MAKE_FLAGS += \ + DEBUG= Q= \ + PCFLAGS="-Wall" \ + PKG_PLATFORM=linux \ + ENABLE_GETTEXT=no \ + prefix=$(PKG_INSTALL_DIR)/usr \ + exec_prefix=$(PKG_INSTALL_DIR)/usr \ + PKG_SBIN_DIR=$(PKG_INSTALL_DIR)/usr/sbin \ + PKG_ROOT_SBIN_DIR=$(PKG_INSTALL_DIR)/sbin \ + PKG_MAN_DIR=$(PKG_INSTALL_DIR)/usr/man \ + PKG_LOCALE_DIR=$(PKG_INSTALL_DIR)/usr/share/locale \ + PKG_ROOT_LIB_DIR=$(PKG_INSTALL_DIR)/lib \ + PKG_DOC_DIR=$(PKG_INSTALL_DIR)/usr/share/doc/xfsprogs + +define Package/xfs-mkfs/install + mkdir -p $(1)/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/mkfs.xfs $(1)/sbin +endef + +define Package/xfs-fsck/install + mkdir -p $(1)/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/xfs_repair $(1)/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/xfs_db $(1)/sbin +endef + +define Package/xfs-growfs/install + mkdir -p $(1)/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/xfs_growfs $(1)/sbin +endef + +$(eval $(call BuildPackage,xfs-mkfs)) +$(eval $(call BuildPackage,xfs-fsck)) +$(eval $(call BuildPackage,xfs-growfs)) diff --git a/package/utils/xfsprogs/patches/001-automake-compat.patch b/package/utils/xfsprogs/patches/001-automake-compat.patch new file mode 100644 index 0000000..3003d6d --- /dev/null +++ b/package/utils/xfsprogs/patches/001-automake-compat.patch @@ -0,0 +1,84 @@ +commit 2222aa77e11b959e0e5a0ded3482e56799593bc2 +Author: Jens Muecke <jens@nons.de> +Date: Thu Jan 26 00:34:15 2012 +0100 + + 001-automake-compat + +diff --git a/configure.in b/configure.in +index 664c0e9..d91b6ec 100644 +--- a/configure.in ++++ b/configure.in +@@ -2,7 +2,8 @@ AC_INIT(include/libxfs.h) + AC_PREREQ(2.50) + AC_CONFIG_AUX_DIR([.]) + AC_CONFIG_MACRO_DIR([m4]) +-AC_CONFIG_HEADER(include/platform_defs.h) ++# Put a dummy here (http://www.mail-archive.com/automake@gnu.org/msg09241.html) ++AC_CONFIG_HEADERS([doesnotexist.h include/platform_defs.h]) + AC_PREFIX_DEFAULT(/usr) + + AC_PROG_LIBTOOL +diff --git a/include/builddefs.in b/include/builddefs.in +index 81ebfcd..5a4a0e8 100644 +--- a/include/builddefs.in ++++ b/include/builddefs.in +@@ -20,6 +20,8 @@ + ifndef _BUILDDEFS_INCLUDED_ + _BUILDDEFS_INCLUDED_ = 1 + ++SHELL = @SHELL@ ++ + DEBUG = @debug_build@ + OPTIMIZER = @opt_build@ + MALLOCLIB = @malloc_lib@ +diff --git a/m4/package_types.m4 b/m4/package_types.m4 +index 0a0e087..66a136a 100644 +--- a/m4/package_types.m4 ++++ b/m4/package_types.m4 +@@ -9,7 +9,7 @@ AC_DEFUN([AC_TYPE_PSINT], + #include <stddef.h> + ], [ + __psint_t psint; +- ], AC_DEFINE(HAVE___PSINT_T) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no)) ++ ], AC_DEFINE([HAVE___PSINT_T], [1], [Define if __psint_t exists]) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no)) + ]) + + # +@@ -23,7 +23,7 @@ AC_DEFUN([AC_TYPE_PSUNSIGNED], + #include <stddef.h> + ], [ + __psunsigned_t psuint; +- ], AC_DEFINE(HAVE___PSUNSIGNED_T) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no)) ++ ], AC_DEFINE([HAVE___PSUNSIGNED_T], [1], [Define if __psunsigned_t exists]) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no)) + ]) + + # +@@ -37,7 +37,7 @@ AC_DEFUN([AC_TYPE_U32], + #include <stddef.h> + ], [ + __u32 u32; +- ], AC_DEFINE(HAVE___U32) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no)) ++ ], AC_DEFINE([HAVE___U32], [1], [Define if __u32 exists]) AC_MSG_RESULT(yes) , AC_MSG_RESULT(no)) + ]) + + # +@@ -50,15 +50,15 @@ AC_DEFUN([AC_SIZEOF_POINTERS_AND_LONG], + AC_CHECK_SIZEOF(long, 4) + AC_CHECK_SIZEOF(char *, 4) + if test $ac_cv_sizeof_long -eq 4 -o $ac_cv_sizeof_long -eq 0; then +- AC_DEFINE(HAVE_32BIT_LONG) ++ AC_DEFINE([HAVE_32BIT_LONG], [1], [Define if long is 32bit]) + fi + if test $ac_cv_sizeof_long -eq 8; then +- AC_DEFINE(HAVE_64BIT_LONG) ++ AC_DEFINE([HAVE_64BIT_LONG], [1], [Define if long is 64bit]) + fi + if test $ac_cv_sizeof_char_p -eq 4 -o $ac_cv_sizeof_char_p -eq 0; then +- AC_DEFINE(HAVE_32BIT_PTR) ++ AC_DEFINE([HAVE_32BIT_PTR], [1], [Define if char* is 32bit]) + fi + if test $ac_cv_sizeof_char_p -eq 8; then +- AC_DEFINE(HAVE_64BIT_PTR) ++ AC_DEFINE([HAVE_64BIT_PTR], [1], [Define if char* is 64bit]) + fi + ]) diff --git a/package/utils/xfsprogs/patches/100-no_aio.patch b/package/utils/xfsprogs/patches/100-no_aio.patch new file mode 100644 index 0000000..30d36b4 --- /dev/null +++ b/package/utils/xfsprogs/patches/100-no_aio.patch @@ -0,0 +1,21 @@ +commit e72b7bd12fdef06c3494b919376bfe886aa8bb4d +Author: Jens Muecke <jens@nons.de> +Date: Thu Jan 26 00:35:43 2012 +0100 + + 100-no_aio + +diff --git a/configure.in b/configure.in +index d91b6ec..8dc8b4a 100644 +--- a/configure.in ++++ b/configure.in +@@ -92,8 +92,8 @@ AC_PACKAGE_GLOBALS(xfsprogs) + AC_PACKAGE_UTILITIES(xfsprogs) + AC_MULTILIB($enable_lib64) + +-AC_PACKAGE_NEED_AIO_H +-AC_PACKAGE_NEED_LIO_LISTIO ++librt="-lrt" ++AC_SUBST(librt) + + AC_PACKAGE_NEED_UUID_H + AC_PACKAGE_NEED_UUIDCOMPARE diff --git a/package/utils/xfsprogs/patches/110-uclibc_no_ustat.patch b/package/utils/xfsprogs/patches/110-uclibc_no_ustat.patch new file mode 100644 index 0000000..071dfc1 --- /dev/null +++ b/package/utils/xfsprogs/patches/110-uclibc_no_ustat.patch @@ -0,0 +1,34 @@ +commit 7b1d0a98e779170232c0a81b4749ab934ec67a7e +Author: Jens Muecke <jens@nons.de> +Date: Thu Jan 26 00:36:42 2012 +0100 + + 110-uclibc_no_ustat + +diff --git a/libxfs/linux.c b/libxfs/linux.c +index 2e07d54..6a6c905 100644 +--- a/libxfs/linux.c ++++ b/libxfs/linux.c +@@ -21,7 +21,6 @@ + #include <mntent.h> + #include <sys/stat.h> + #undef ustat +-#include <sys/ustat.h> + #include <sys/mount.h> + #include <sys/ioctl.h> + #include <sys/sysinfo.h> +@@ -49,6 +51,7 @@ static int max_block_alignment; + int + platform_check_ismounted(char *name, char *block, struct stat64 *s, int verbose) + { ++#if 0 + /* Pad ust; pre-2.6.28 linux copies out too much in 32bit compat mode */ + struct ustat ust[2]; + struct stat64 st; +@@ -68,6 +71,7 @@ platform_check_ismounted(char *name, char *block, struct stat64 *s, int verbose) + progname, name); + return 1; + } ++#endif + return 0; + } + diff --git a/package/utils/xfsprogs/patches/120-portability.patch b/package/utils/xfsprogs/patches/120-portability.patch new file mode 100644 index 0000000..1e9b533 --- /dev/null +++ b/package/utils/xfsprogs/patches/120-portability.patch @@ -0,0 +1,47 @@ +commit d2aef8b3967e53fe58178f5af50fef488ee0faed +Author: Jens Muecke <jens@nons.de> +Date: Thu Jan 26 00:37:52 2012 +0100 + + 120-portability + +diff --git a/copy/xfs_copy.c b/copy/xfs_copy.c +index c01e0b9..2e2f320 100644 +--- a/copy/xfs_copy.c ++++ b/copy/xfs_copy.c +@@ -463,6 +463,15 @@ read_ag_header(int fd, xfs_agnumber_t agno, wbuf *buf, ag_header_t *ag, + } + + ++static void sig_mask(int type) ++{ ++ sigset_t mask; ++ sigemptyset(&mask); ++ sigaddset(&mask, SIGCHLD); ++ sigprocmask(type, &mask, NULL); ++} ++ ++ + void + write_wbuf(void) + { +@@ -478,9 +487,9 @@ write_wbuf(void) + if (target[i].state != INACTIVE) + pthread_mutex_unlock(&targ[i].wait); /* wake up */ + +- sigrelse(SIGCHLD); ++ sig_mask(SIG_UNBLOCK); + pthread_mutex_lock(&mainwait); +- sighold(SIGCHLD); ++ sig_mask(SIG_BLOCK); + } + + +@@ -847,7 +856,7 @@ main(int argc, char **argv) + /* set up sigchild signal handler */ + + signal(SIGCHLD, handler); +- sighold(SIGCHLD); ++ sig_mask(SIG_BLOCK); + + /* make children */ + diff --git a/package/utils/xfsprogs/patches/130-uclibc_no_xattr.patch b/package/utils/xfsprogs/patches/130-uclibc_no_xattr.patch new file mode 100644 index 0000000..a9b5a6f --- /dev/null +++ b/package/utils/xfsprogs/patches/130-uclibc_no_xattr.patch @@ -0,0 +1,34 @@ +commit 10d6058b24f18cb31889154f830b191849f45106 +Author: Jens Muecke <jens@nons.de> +Date: Thu Jan 26 00:38:27 2012 +0100 + + 130-uclibc_no_xattr + +diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c +index 40c2e6f..4f54059 100644 +--- a/fsr/xfs_fsr.c ++++ b/fsr/xfs_fsr.c +@@ -35,7 +35,6 @@ + #include <sys/wait.h> + #include <sys/vfs.h> + #include <sys/statvfs.h> +-#include <sys/xattr.h> + + + #ifndef XFS_XFLAG_NODEFRAG +@@ -990,6 +992,7 @@ fsr_setup_attr_fork( + int tfd, + xfs_bstat_t *bstatp) + { ++#if 0 + struct stat64 tstatbuf; + int i; + int last_forkoff = 0; +@@ -1108,6 +1111,7 @@ fsr_setup_attr_fork( + out: + if (dflag) + fsrprintf(_("set temp attr\n")); ++#endif + return 0; + } + diff --git a/package/utils/xfsprogs/patches/140-no_po.patch b/package/utils/xfsprogs/patches/140-no_po.patch new file mode 100644 index 0000000..f915a9c --- /dev/null +++ b/package/utils/xfsprogs/patches/140-no_po.patch @@ -0,0 +1,20 @@ +diff -urN xfsprogs-3.1.7/Makefile xfsprogs-3.1.7.new/Makefile +--- xfsprogs-3.1.7/Makefile 2011-11-18 00:30:24.000000000 +0100 ++++ xfsprogs-3.1.7.new/Makefile 2012-04-20 14:15:48.641722955 +0200 +@@ -41,7 +41,7 @@ + + LIB_SUBDIRS = libxfs libxlog libxcmd libhandle libdisk + TOOL_SUBDIRS = copy db estimate fsck fsr growfs io logprint mkfs quota \ +- mdrestore repair rtcp m4 man doc po debian ++ mdrestore repair rtcp m4 man doc debian + + SUBDIRS = include $(LIB_SUBDIRS) $(TOOL_SUBDIRS) + +@@ -135,7 +135,6 @@ + $(Q)$(MAKE) $(MAKEOPTS) -C . $@ + else + $(Q)$(MAKE) $(MAKEOPTS) $(SRCDIR) +- $(Q)$(MAKE) $(MAKEOPTS) -C po + $(Q)$(MAKE) $(MAKEOPTS) source-link + $(Q)cd $(SRCDIR) && dpkg-buildpackage + endif diff --git a/package/utils/xfsprogs/patches/150-include_fixes.patch b/package/utils/xfsprogs/patches/150-include_fixes.patch new file mode 100644 index 0000000..793622a --- /dev/null +++ b/package/utils/xfsprogs/patches/150-include_fixes.patch @@ -0,0 +1,72 @@ +--- a/libhandle/handle.c ++++ b/libhandle/handle.c +@@ -20,6 +20,7 @@ + #include <xfs/xfs.h> + #include <xfs/handle.h> + #include <xfs/parent.h> ++#include <linux/limits.h> + + /* just pick a value we know is more than big enough */ + #define MAXHANSIZ 64 +--- a/libhandle/jdm.c ++++ b/libhandle/jdm.c +@@ -20,6 +20,7 @@ + #include <xfs/handle.h> + #include <xfs/jdm.h> + #include <xfs/parent.h> ++#include <linux/limits.h> + + /* internal fshandle - typecast to a void for external use */ + #define FSHANDLE_SZ 8 +--- a/libdisk/evms.c ++++ b/libdisk/evms.c +@@ -22,6 +22,7 @@ + #include <fcntl.h> + #include <sys/ioctl.h> + #include <sys/sysmacros.h> ++#include <sys/stat.h> + #include <disk/volume.h> + #include "evms.h" + +--- a/libdisk/evms.h ++++ b/libdisk/evms.h +@@ -16,6 +16,8 @@ + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + ++#include <sys/types.h> ++ + #define EVMS_MAJOR 117 + #define EVMS_GET_VOL_STRIPE_INFO \ + _IOR(EVMS_MAJOR, 0xF0, struct evms_vol_stripe_info_s) +--- a/libdisk/fstype.h ++++ b/libdisk/fstype.h +@@ -192,7 +192,7 @@ struct adfs_super_block { + char s_dummy2[62]; + char s_checksum[1]; + }; +-#define adfsblksize(s) ((uint) s.s_blksize[0]) ++#define adfsblksize(s) ((unsigned int) s.s_blksize[0]) + + /* found in first 4 bytes of block 1 */ + struct vxfs_super_block { +--- a/fsr/xfs_fsr.c ++++ b/fsr/xfs_fsr.c +@@ -25,6 +25,7 @@ + #include <xfs/xfs_dinode.h> + #include <xfs/xfs_attr_sf.h> + ++#include <paths.h> + #include <fcntl.h> + #include <errno.h> + #include <malloc.h> +--- a/libdisk/xvm.c ++++ b/libdisk/xvm.c +@@ -22,6 +22,7 @@ + #include <unistd.h> + #include <sys/stat.h> + #include <sys/ioctl.h> ++#include <sys/types.h> + #include <disk/volume.h> + #include "xvm.h" + |