diff options
author | John Crispin <blogic@openwrt.org> | 2013-06-21 16:54:37 +0000 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2013-06-21 16:54:37 +0000 |
commit | f1b4824c865b228039d84b2605b2e7e4f34cddeb (patch) | |
tree | 37c9cbe251e4fb790aaa72e862c35822be30b491 /package/utils | |
parent | d2642de7494bba312bbb22cfeb3ad77130a10047 (diff) | |
download | master-187ad058-f1b4824c865b228039d84b2605b2e7e4f34cddeb.tar.gz master-187ad058-f1b4824c865b228039d84b2605b2e7e4f34cddeb.tar.bz2 master-187ad058-f1b4824c865b228039d84b2605b2e7e4f34cddeb.zip |
packages: clean up the package folder
Signed-off-by: John Crispin <blogic@openwrt.org>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@37007 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/utils')
149 files changed, 33942 insertions, 0 deletions
diff --git a/package/utils/admswconfig/Makefile b/package/utils/admswconfig/Makefile new file mode 100644 index 0000000000..e16258f4b1 --- /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 0000000000..7231030650 --- /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 0000000000..984d7eea79 --- /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` + ifconfig eth$1 down + admswconfig eth$1 ${ports}c + ifconfig 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 0000000000..e50d515757 --- /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/busybox/Config.in b/package/utils/busybox/Config.in new file mode 100644 index 0000000000..5e3a8406be --- /dev/null +++ b/package/utils/busybox/Config.in @@ -0,0 +1,6 @@ + +if PACKAGE_busybox + +source "package/utils/busybox/config/Config.in" + +endif diff --git a/package/utils/busybox/Makefile b/package/utils/busybox/Makefile new file mode 100644 index 0000000000..aed6ddea6b --- /dev/null +++ b/package/utils/busybox/Makefile @@ -0,0 +1,117 @@ +# +# Copyright (C) 2006-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=busybox +PKG_VERSION:=1.19.4 +PKG_RELEASE:=6 +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:=9c0cae5a0379228e7b55e5b29528df8e + +PKG_BUILD_DEPENDS:=BUSYBOX_CONFIG_FEATURE_HAVE_RPC:librpc +PKG_BUILD_PARALLEL:=1 + +PKG_LICENSE:=GPLv2 BSD-4c +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 + +init-y := +init-$(CONFIG_BUSYBOX_CONFIG_CROND) += cron +init-$(CONFIG_BUSYBOX_CONFIG_TELNETD) += telnet + +define Package/busybox + SECTION:=base + CATEGORY:=Base system + MAINTAINER:=Nicolas Thill <nico@openwrt.org> + TITLE:=Core utilities for embedded Linux + URL:=http://busybox.net/ + DEPENDS:=+BUSYBOX_CONFIG_FEATURE_HAVE_RPC:librpc + 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 + +define Build/Configure + rm -f $(PKG_BUILD_DIR)/.configured* + grep 'CONFIG_BUSYBOX_' $(TOPDIR)/.config | sed -e "s,\\(# \)\\?CONFIG_BUSYBOX_\\(.*\\),\\1\\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 + +ifdef CONFIG_GCC_VERSION_LLVM + TARGET_CFLAGS += -fnested-functions +endif + +LDLIBS:=m crypt +ifdef CONFIG_BUSYBOX_CONFIG_FEATURE_HAVE_RPC + TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include + export LDFLAGS=$(TARGET_LDFLAGS) + LDLIBS += rpc +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)/ + for tmp in $(init-y); do \ + $(INSTALL_BIN) ./files/$$$$tmp $(1)/etc/init.d/$$$$tmp; \ + done + -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 0000000000..f9521de320 --- /dev/null +++ b/package/utils/busybox/config/Config.in @@ -0,0 +1,778 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + + +config BUSYBOX_CONFIG_HAVE_DOT_CONFIG + bool + default y + +menu "Busybox Settings" + +menu "General Configuration" + +config BUSYBOX_CONFIG_DESKTOP + bool "Enable options for full-blown desktop systems" + default n + 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 n + 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 y + 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 n + 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 y + 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 terse applet usage messages" + default y + help + All BusyBox applets will show help messages when invoked with + wrong arguments. You can turn off printing these terse usage + messages if you say no here. + This will save you up to 7k. + +config BUSYBOX_CONFIG_FEATURE_VERBOSE_USAGE + bool "Show verbose applet usage messages" + default y + depends on BUSYBOX_CONFIG_SHOW_USAGE + help + All BusyBox applets will show more 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 y + depends on BUSYBOX_CONFIG_SHOW_USAGE + help + Store usage messages in 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 n + 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 n + 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 n + 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 n + 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 n + 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 $LANG environment variable" + default n + depends on BUSYBOX_CONFIG_UNICODE_SUPPORT && !BUSYBOX_CONFIG_UNICODE_USING_LOCALE + help + With this option on, Unicode support is activated + only if LANG variable has 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 63 + 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 767 + 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 n + 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 n + 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 n + 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 n + 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 n + 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_LONG_OPTS + bool "Support for --long-options" + default y + 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 y + 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 n + 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 n + 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 n + 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 y + help + This option makes some applets (e.g. crond, syslogd, inetd) write + a pidfile in /var/run. Some applications rely on them. + +config BUSYBOX_CONFIG_FEATURE_SUID + bool "Support for SUID/SGID handling" + default y + 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 priviledges 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 n + 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 n + 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 n + 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. Go visit + http://www.nsa.gov/selinux/index.html + to download the necessary stuff to allow busybox to compile with + this option enabled. 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 y + 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 "/proc/self/exe" + 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 y + #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 n + #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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 y + 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 "" + 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_EXTRA_CFLAGS + string "Additional CFLAGS" + default "" + help + Additional CFLAGS to pass to the compiler verbatim. + +endmenu + +menu 'Debugging Options' + +config BUSYBOX_CONFIG_DEBUG + bool "Build BusyBox with extra Debugging symbols" + default n + 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 n + 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_WERROR + bool "Abort compilation on any warning" + default n + 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 "./_install" + 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 0000000000..d2bfa4848b --- /dev/null +++ b/package/utils/busybox/config/archival/Config.in @@ -0,0 +1,380 @@ +# 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 n + 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 n + 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 n + 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 y + help + Make tar, rpm, modprobe etc understand .gz data. + +config BUSYBOX_CONFIG_FEATURE_SEAMLESS_Z + bool "Make tar and gunzip understand .Z data" + default n + help + Make tar and gunzip understand .Z data. + +config BUSYBOX_CONFIG_AR + bool "ar" + default n # 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 n + 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 n + depends on BUSYBOX_CONFIG_AR + help + This enables archive creation (-c and -r) with busybox ar. + +config BUSYBOX_CONFIG_BUNZIP2 + bool "bunzip2" + default y + 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_BZIP2 + bool "bzip2" + default n + 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 n + 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 n + 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 n + depends on BUSYBOX_CONFIG_FEATURE_CPIO_O + help + Passthrough mode. Rarely used. + +config BUSYBOX_CONFIG_DPKG + bool "dpkg" + default n + 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 n + 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 n + 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_GUNZIP + bool "gunzip" + default y + 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_GZIP + bool "gzip" + default y + 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 n + depends on BUSYBOX_CONFIG_GZIP && BUSYBOX_CONFIG_LONG_OPTS + help + Enable use of long options, increases size by about 106 Bytes + +config BUSYBOX_CONFIG_LZOP + bool "lzop" + default n + help + Lzop compression/decompresion. + +config BUSYBOX_CONFIG_LZOP_COMPR_HIGH + bool "lzop compression levels 7,8,9 (not very useful)" + default n + 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_RPM2CPIO + bool "rpm2cpio" + default n + help + Converts a RPM file into a CPIO archive. + +config BUSYBOX_CONFIG_RPM + bool "rpm" + default n + help + Mini RPM applet - queries and extracts RPM packages. + +config BUSYBOX_CONFIG_TAR + bool "tar" + default y + 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 y + 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 n + 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 y + 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 n + 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 n + 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 y + 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 n + 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 n + 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 n + 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 n + 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 n + 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_UNCOMPRESS + bool "uncompress" + default n + help + uncompress is used to decompress archives created by compress. + Not much used anymore, replaced by gzip/gunzip. + +config BUSYBOX_CONFIG_UNLZMA + bool "unlzma" + default n + 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 de-compression only. + On an x86 system, this applet adds about 4K. + + Unless you have a specific application which requires unlzma, you + should probably say N here. + +config BUSYBOX_CONFIG_FEATURE_LZMA_FAST + bool "Optimize unlzma for speed" + default n + 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 n + 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 n + help + unxz is a unlzma successor. + +config BUSYBOX_CONFIG_XZ + bool "Provide xz alias which supports only unpacking" + default n + 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_UNZIP + bool "unzip" + default n + 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 0000000000..9069b0f1a1 --- /dev/null +++ b/package/utils/busybox/config/console-tools/Config.in @@ -0,0 +1,177 @@ +# 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 n + 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 n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program prints active (foreground) console number. + +config BUSYBOX_CONFIG_CLEAR + bool "clear" + default y + help + This program clears the terminal screen. + +config BUSYBOX_CONFIG_DEALLOCVT + bool "deallocvt" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program deallocates unused virtual consoles. + +config BUSYBOX_CONFIG_DUMPKMAP + bool "dumpkmap" + default n + 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 n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program reports and sets keyboard mode. + +config BUSYBOX_CONFIG_LOADFONT + bool "loadfont" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program loads a console font from standard input. + +config BUSYBOX_CONFIG_LOADKMAP + bool "loadkmap" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program loads a keyboard translation table from + standard input. + +config BUSYBOX_CONFIG_OPENVT + bool "openvt" + default n + 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 y + help + This program is used to reset the terminal screen, if it + gets messed up. + +config BUSYBOX_CONFIG_RESIZE + bool "resize" + default n + 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 n + 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 n + 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 n + depends on BUSYBOX_CONFIG_SETCONSOLE && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the setconsole applet. + +config BUSYBOX_CONFIG_SETFONT + bool "setfont" + default n + 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 n + 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 "" + 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 n + 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 n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + This program redirects the output console of kernel messages. + +config BUSYBOX_CONFIG_SHOWKEY + bool "showkey" + default n + 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 n + 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 n + 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 0000000000..33a5e25e62 --- /dev/null +++ b/package/utils/busybox/config/coreutils/Config.in @@ -0,0 +1,913 @@ +# 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 y + 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 y + 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 y + 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 y + 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 n + 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 n + 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_ID + bool "id" + default y + help + id displays the current user and group ID names. +config BUSYBOX_CONFIG_GROUPS + bool "groups" + default n + help + Print the group names associated with current user id. +config BUSYBOX_CONFIG_TEST + bool "test" + default y + 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 y + 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 y + help + touch is used to create or change the access and/or + modification timestamp of specified files. +config BUSYBOX_CONFIG_TR + bool "tr" + default y + 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 n + 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 n + 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_BASE64 + bool "base64" + default n + help + Base64 encode and decode +config BUSYBOX_CONFIG_WHO + bool "who" + default n + depends on BUSYBOX_CONFIG_FEATURE_UTMP + help + who is used to show who is logged on. +config BUSYBOX_CONFIG_USERS + bool "users" + default n + depends on BUSYBOX_CONFIG_FEATURE_UTMP + help + Print users currently logged on. + +config BUSYBOX_CONFIG_CAL + bool "cal" + default n + help + cal is used to display a monthly calender. + +config BUSYBOX_CONFIG_CATV + bool "catv" + default n + help + Display nonprinting characters as escape sequences (like some + implementations' cat -v option). + +config BUSYBOX_CONFIG_CHGRP + bool "chgrp" + default y + help + chgrp is used to change the group ownership of files. + +config BUSYBOX_CONFIG_CHMOD + bool "chmod" + default y + help + chmod is used to change the access permission of files. + +config BUSYBOX_CONFIG_CHOWN + bool "chown" + default y + 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 n + depends on BUSYBOX_CONFIG_CHOWN && BUSYBOX_CONFIG_LONG_OPTS + help + Enable use of long options + +config BUSYBOX_CONFIG_CHROOT + bool "chroot" + default y + 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 n + help + cksum is used to calculate the CRC32 checksum of a file. + +config BUSYBOX_CONFIG_COMM + bool "comm" + default n + help + comm is used to compare two files line by line and return + a three-column output. + +config BUSYBOX_CONFIG_CP + bool "cp" + default y + help + cp is used to copy files and directories. + +config BUSYBOX_CONFIG_FEATURE_CP_LONG_OPTIONS + bool "Enable long options for cp" + default n + 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 y + help + cut is used to print selected parts of lines from + each file to stdout. + +config BUSYBOX_CONFIG_DD + bool "dd" + default y + 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 y + 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 n + 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 y + 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 y + 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 n + 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 y + help + dirname is used to strip a non-directory suffix from + a file name. + +config BUSYBOX_CONFIG_DOS2UNIX + bool "dos2unix/unix2dos" + default n + help + dos2unix is used to convert a text file from DOS format to + UNIX format, and vice versa. + +config BUSYBOX_CONFIG_UNIX2DOS + bool + default n + 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 y + 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 y + 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 y + 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 y + 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 y + 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 n + depends on BUSYBOX_CONFIG_ENV && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the env applet. + +config BUSYBOX_CONFIG_EXPAND + bool "expand" + default n + help + By default, convert all tabs to spaces. + +config BUSYBOX_CONFIG_FEATURE_EXPAND_LONG_OPTIONS + bool "Enable long options" + default n + depends on BUSYBOX_CONFIG_EXPAND && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the expand applet. + +config BUSYBOX_CONFIG_EXPR + bool "expr" + default y + 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 y + 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 y + help + false returns an exit code of FALSE (1). + +config BUSYBOX_CONFIG_FOLD + bool "fold" + default n + help + Wrap text to fit a specific width. + +config BUSYBOX_CONFIG_FSYNC + bool "fsync" + default y + help + fsync is used to flush file-related cached blocks to disk. + +config BUSYBOX_CONFIG_HEAD + bool "head" + default y + 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 y + depends on BUSYBOX_CONFIG_HEAD + help + This enables the head options (-c, -q, and -v). + +config BUSYBOX_CONFIG_HOSTID + bool "hostid" + default y + help + hostid prints the numeric identifier (in hexadecimal) for + the current host. + +config BUSYBOX_CONFIG_INSTALL + bool "install" + default n + help + Copy files and set attributes. + +config BUSYBOX_CONFIG_FEATURE_INSTALL_LONG_OPTIONS + bool "Enable long options" + default n + 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 y + help + ln is used to create hard or soft links between files. + +config BUSYBOX_CONFIG_LOGNAME + bool "logname" + default n + help + logname is used to print the current user's login name. + +config BUSYBOX_CONFIG_LS + bool "ls" + default y + help + ls is used to list the contents of directories. + +config BUSYBOX_CONFIG_FEATURE_LS_FILETYPES + bool "Enable filetyping options (-p and -F)" + default y + 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 y + depends on BUSYBOX_CONFIG_LS + help + Enable the ls option (-L). + +config BUSYBOX_CONFIG_FEATURE_LS_RECURSIVE + bool "Enable recursion (-R)" + default y + depends on BUSYBOX_CONFIG_LS + help + Enable the ls option (-R). + +config BUSYBOX_CONFIG_FEATURE_LS_SORTFILES + bool "Sort the file names" + default y + depends on BUSYBOX_CONFIG_LS + help + Allow ls to sort file names alphabetically. + +config BUSYBOX_CONFIG_FEATURE_LS_TIMESTAMPS + bool "Show file timestamps" + default y + depends on BUSYBOX_CONFIG_LS + help + Allow ls to display timestamps for files. + +config BUSYBOX_CONFIG_FEATURE_LS_USERNAME + bool "Show username/groupnames" + default y + 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 y + 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 y + 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 y + help + md5sum is used to print or check MD5 checksums. + +config BUSYBOX_CONFIG_MKDIR + bool "mkdir" + default y + help + mkdir is used to create directories with the specified names. + +config BUSYBOX_CONFIG_FEATURE_MKDIR_LONG_OPTIONS + bool "Enable long options" + default n + depends on BUSYBOX_CONFIG_MKDIR && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the mkdir applet. + +config BUSYBOX_CONFIG_MKFIFO + bool "mkfifo" + default y + help + mkfifo is used to create FIFOs (named pipes). + The `mknod' program can also create FIFOs. + +config BUSYBOX_CONFIG_MKNOD + bool "mknod" + default y + help + mknod is used to create FIFOs or block/character special + files with the specified names. + +config BUSYBOX_CONFIG_MV + bool "mv" + default y + help + mv is used to move or rename files or directories. + +config BUSYBOX_CONFIG_FEATURE_MV_LONG_OPTIONS + bool "Enable long options" + default n + depends on BUSYBOX_CONFIG_MV && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the mv applet. + +config BUSYBOX_CONFIG_NICE + bool "nice" + default y + help + nice runs a program with modified scheduling priority. + +config BUSYBOX_CONFIG_NOHUP + bool "nohup" + default n + help + run a command immune to hangups, with output to a non-tty. + +config BUSYBOX_CONFIG_OD + bool "od" + default n + help + od is used to dump binary files in octal and other formats. + +config BUSYBOX_CONFIG_PRINTENV + bool "printenv" + default n + help + printenv is used to print all or part of environment. + +config BUSYBOX_CONFIG_PRINTF + bool "printf" + default y + 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 y + help + pwd is used to print the current directory. + +config BUSYBOX_CONFIG_READLINK + bool "readlink" + default y + 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 y + depends on BUSYBOX_CONFIG_READLINK + help + Enable the readlink option (-f). + +config BUSYBOX_CONFIG_REALPATH + bool "realpath" + default n + 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 y + help + rm is used to remove files or directories. + +config BUSYBOX_CONFIG_RMDIR + bool "rmdir" + default y + help + rmdir is used to remove empty directories. + +config BUSYBOX_CONFIG_FEATURE_RMDIR_LONG_OPTIONS + bool "Enable long options" + default n + 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 y + help + print a sequence of numbers + +config BUSYBOX_CONFIG_SHA1SUM + bool "sha1sum" + default n + help + Compute and check SHA1 message digest + +config BUSYBOX_CONFIG_SHA256SUM + bool "sha256sum" + default n + help + Compute and check SHA256 message digest + +config BUSYBOX_CONFIG_SHA512SUM + bool "sha512sum" + default n + help + Compute and check SHA512 message digest + +config BUSYBOX_CONFIG_SLEEP + bool "sleep" + default y + 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 y + 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 n + depends on BUSYBOX_CONFIG_FEATURE_FANCY_SLEEP + help + Allow for fractional numeric parameters. + +config BUSYBOX_CONFIG_SORT + bool "sort" + default y + 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 n + 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 n + help + split a file into pieces. + +config BUSYBOX_CONFIG_FEATURE_SPLIT_FANCY + bool "Fancy extensions" + default n + 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 n + select BUSYBOX_CONFIG_PLATFORM_LINUX # statfs() + help + display file or filesystem status. + +config BUSYBOX_CONFIG_FEATURE_STAT_FORMAT + bool "Enable custom formats (-c)" + default n + 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 n + help + stty is used to change and print terminal line settings. + +config BUSYBOX_CONFIG_SUM + bool "sum" + default n + help + checksum and count the blocks in a file + +config BUSYBOX_CONFIG_SYNC + bool "sync" + default y + help + sync is used to flush filesystem buffers. + +config BUSYBOX_CONFIG_TAC + bool "tac" + default n + help + tac is used to concatenate and print files in reverse. + +config BUSYBOX_CONFIG_TAIL + bool "tail" + default y + 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 y + depends on BUSYBOX_CONFIG_TAIL + help + The options (-q, -s, and -v) 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 + +config BUSYBOX_CONFIG_TEE + bool "tee" + default y + 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 y + depends on BUSYBOX_CONFIG_TEE + help + Enable this option for a faster tee, at expense of size. + +config BUSYBOX_CONFIG_TRUE + bool "true" + default y + help + true returns an exit code of TRUE (0). + +config BUSYBOX_CONFIG_TTY + bool "tty" + default n + help + tty is used to print the name of the current terminal to + standard output. + +config BUSYBOX_CONFIG_UNAME + bool "uname" + default y + help + uname is used to print system information. + +config BUSYBOX_CONFIG_UNEXPAND + bool "unexpand" + default n + help + By default, convert only leading sequences of blanks to tabs. + +config BUSYBOX_CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS + bool "Enable long options" + default n + depends on BUSYBOX_CONFIG_UNEXPAND && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the unexpand applet. + +config BUSYBOX_CONFIG_UNIQ + bool "uniq" + default y + help + uniq is used to remove duplicate lines from a sorted file. + +config BUSYBOX_CONFIG_USLEEP + bool "usleep" + default n + help + usleep is used to pause for a specified number of microseconds. + +config BUSYBOX_CONFIG_UUDECODE + bool "uudecode" + default n + help + uudecode is used to decode a uuencoded file. + +config BUSYBOX_CONFIG_UUENCODE + bool "uuencode" + default n + help + uuencode is used to uuencode a file. + +config BUSYBOX_CONFIG_WC + bool "wc" + default y + 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 n + depends on BUSYBOX_CONFIG_WC + help + Use "unsigned long long" in wc for counter variables. + +config BUSYBOX_CONFIG_WHOAMI + bool "whoami" + default n + help + whoami is used to print the username of the current + user id (same as id -un). + +config BUSYBOX_CONFIG_YES + bool "yes" + default y + help + yes is used to repeatedly output a specific string, or + the default string `y'. + +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 y + 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 y + 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 y + 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" + depends on BUSYBOX_CONFIG_MD5SUM || BUSYBOX_CONFIG_SHA1SUM || BUSYBOX_CONFIG_SHA256SUM || BUSYBOX_CONFIG_SHA512SUM + +config BUSYBOX_CONFIG_FEATURE_MD5_SHA1_SUM_CHECK + bool "Enable -c, -s and -w options" + default y + depends on BUSYBOX_CONFIG_MD5SUM || BUSYBOX_CONFIG_SHA1SUM || BUSYBOX_CONFIG_SHA256SUM || BUSYBOX_CONFIG_SHA512SUM + 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 0000000000..be69666fff --- /dev/null +++ b/package/utils/busybox/config/debianutils/Config.in @@ -0,0 +1,86 @@ +# 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 y + help + mktemp is used to create unique temporary files + +config BUSYBOX_CONFIG_PIPE_PROGRESS + bool "pipe_progress" + default n + help + Display a dot to indicate pipe activity. + +config BUSYBOX_CONFIG_RUN_PARTS + bool "run-parts" + default n + 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 n + 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 n + 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 y + 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 n + 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 n + 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 y + 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 0000000000..282681db0c --- /dev/null +++ b/package/utils/busybox/config/e2fsprogs/Config.in @@ -0,0 +1,72 @@ +# 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 n + 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 n + 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 n + 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 n # 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 0000000000..105c93a562 --- /dev/null +++ b/package/utils/busybox/config/e2fsprogs/old_e2fsprogs/Config.in @@ -0,0 +1,70 @@ +# 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 n + help + chattr changes the file attributes on a second extended file system. + +config BUSYBOX_CONFIG_E2FSCK + bool "e2fsck" + default n + 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 n + 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 n + help + lsattr lists the file attributes on a second extended file system. + +config BUSYBOX_CONFIG_MKE2FS + bool "mke2fs" + default n + 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 n + help + tune2fs allows the system administrator to adjust various tunable + filesystem parameters on Linux ext2/ext3 filesystems. + +config BUSYBOX_CONFIG_E2LABEL + bool "e2label" + default n + 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 n + 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 0000000000..21321dbb08 --- /dev/null +++ b/package/utils/busybox/config/editors/Config.in @@ -0,0 +1,206 @@ +# 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_PATCH + bool "patch" + default n + help + Apply a unified diff formatted patch. +config BUSYBOX_CONFIG_VI + bool "vi" + default y + 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 1024 + 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 n + 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 y + 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 y + 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 y + 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 n # 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 y + 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 y + 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 y + 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 y + 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 y + depends on BUSYBOX_CONFIG_VI + help + Support for ":set". + +config BUSYBOX_CONFIG_FEATURE_VI_WIN_RESIZE + bool "Handle window resize" + default y + 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 y + 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_OPTIMIZE_CURSOR + bool "Optimize cursor movement" + default y + depends on BUSYBOX_CONFIG_VI + help + This will make the cursor movement faster, but requires more memory + and it makes the applet a tiny bit larger. + +config BUSYBOX_CONFIG_AWK + bool "awk" + default y + 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 y + 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_CMP + bool "cmp" + default y + help + cmp is used to compare two files and returns the result + to standard output. + +config BUSYBOX_CONFIG_DIFF + bool "diff" + default n + 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 n + 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 n + depends on BUSYBOX_CONFIG_DIFF + help + This option enables support for directory and subdirectory + comparison. + +config BUSYBOX_CONFIG_ED + bool "ed" + default n + 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_SED + bool "sed" + default y + help + sed is used to perform text transformations on a file + or input from a pipeline. + +config BUSYBOX_CONFIG_FEATURE_ALLOW_EXEC + bool "Allow vi and awk to execute shell commands" + default y + 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 0000000000..8db1fdef91 --- /dev/null +++ b/package/utils/busybox/config/findutils/Config.in @@ -0,0 +1,252 @@ +# 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 y + 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 y + 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 n + 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 n + 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 y + 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 y + 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 y + 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 y + 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 n + 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 n + 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 y + depends on BUSYBOX_CONFIG_FIND + help + Support the 'find -exec' option for executing commands based upon + the files matched. + +config BUSYBOX_CONFIG_FEATURE_FIND_USER + bool "Enable -user: username/uid matching" + default y + 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 y + 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 y + 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 y + 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 y + 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 y + 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 y + 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 n + 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 y + 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 y + 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 n + 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 n + depends on BUSYBOX_CONFIG_FIND + help + Support the 'find -links' option for matching number of links. +config BUSYBOX_CONFIG_GREP + bool "grep" + default y + 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 y + 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 y + 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 y + 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 y + 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 y + 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 y + 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 y + 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 y + 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. + +endmenu diff --git a/package/utils/busybox/config/init/Config.in b/package/utils/busybox/config/init/Config.in new file mode 100644 index 0000000000..07d94a2056 --- /dev/null +++ b/package/utils/busybox/config/init/Config.in @@ -0,0 +1,185 @@ +# 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 n + 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 n + 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 n + 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 y + 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 n + 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 "/sbin/telinit" + 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 y + select BUSYBOX_CONFIG_FEATURE_SYSLOG + depends on BROKEN + help + init is the first program run when the system boots. + +config BUSYBOX_CONFIG_FEATURE_USE_INITTAB + bool "Support reading an inittab file" + default y + 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 n + 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 0 + 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 n + 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 y + depends on BUSYBOX_CONFIG_INIT + +config BUSYBOX_CONFIG_FEATURE_EXTRA_QUIET + bool "Be _extra_ quiet on boot" + default n + 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 n + 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 n + 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 "linux" + 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 n + 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 n + 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 0000000000..6475403b53 --- /dev/null +++ b/package/utils/busybox/config/libbb/Config.in @@ -0,0 +1,232 @@ +# 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 n + 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 n + 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 6 + range 5 32 + help + Minimum allowable password length. + +config BUSYBOX_CONFIG_MD5_SIZE_VS_SPEED + int "MD5: Trade bytes for speed (0:fast, 3:slow)" + default 2 + 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_FEATURE_FAST_TOP + bool "Faster /proc scanning code (+100 bytes)" + default y + 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 n + 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 n + 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 y + 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 512 + 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 n + 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 256 + depends on BUSYBOX_CONFIG_FEATURE_EDITING + help + Specify command history size (0 - disable). + +config BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY + bool "History saving" + default n + depends on BUSYBOX_CONFIG_FEATURE_EDITING + help + Enable history saving in shells. + +config BUSYBOX_CONFIG_FEATURE_REVERSE_SEARCH + bool "Reverse history search" + default n + 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 y + depends on BUSYBOX_CONFIG_FEATURE_EDITING + help + Enable tab completion. + +config BUSYBOX_CONFIG_FEATURE_USERNAME_COMPLETION + bool "Username completion" + default n + depends on BUSYBOX_CONFIG_FEATURE_TAB_COMPLETION + help + Enable username completion. + +config BUSYBOX_CONFIG_FEATURE_EDITING_FANCY_PROMPT + bool "Fancy shell prompts" + default y + 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 n + 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 y + 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 n + 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 4 + 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 n + 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 useful to turn this option off to make df show + initramfs statistic. + + Otherwise, choose Y. + +config BUSYBOX_CONFIG_MONOTONIC_SYSCALL + bool "Use clock_gettime(CLOCK_MONOTONIC) syscall" + default n + 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 y + 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 n + 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 0000000000..8c32851a2b --- /dev/null +++ b/package/utils/busybox/config/loginutils/Config.in @@ -0,0 +1,329 @@ +# 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 n if BUSYBOX_CONFIG_DESKTOP + help + Add shells to /etc/shells. + +config BUSYBOX_CONFIG_REMOVE_SHELL + bool "remove-shell" + default n if BUSYBOX_CONFIG_DESKTOP + help + Remove shells from /etc/shells. + +config BUSYBOX_CONFIG_FEATURE_SHADOWPASSWDS + bool "Support for shadow passwords" + default y + 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 n + 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 n + 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 n + 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 n + 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 n + help + Utility for creating a new user account. + +config BUSYBOX_CONFIG_FEATURE_ADDUSER_LONG_OPTIONS + bool "Enable long options" + default n + 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 n + 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_FIRST_SYSTEM_ID + int "First valid system uid or gid for adduser and addgroup" + depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP + range 0 64900 + default 100 + 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 0 64900 + default 999 + help + Last valid system uid or gid for adduser and addgroup + +config BUSYBOX_CONFIG_ADDGROUP + bool "addgroup" + default n + help + Utility for creating a new group account. + +config BUSYBOX_CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS + bool "Enable long options" + default n + 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 n + 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 n + help + Utility for deleting a user account. + +config BUSYBOX_CONFIG_DELGROUP + bool "delgroup" + default n + help + Utility for deleting a group account. + +config BUSYBOX_CONFIG_FEATURE_DEL_USER_FROM_GROUP + bool "Support for removing users from groups" + default n + 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 n + 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 n + 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_PAM + bool "Support for PAM (Pluggable Authentication Modules)" + default n + depends on DEVEL + depends on BUSYBOX_CONFIG_LOGIN + help + Use PAM in login(1) instead of direct access to password database. + + OpenWrt specific: + You should install libpam from the packages feed and compile it + before trying to build busysbox. + +config BUSYBOX_CONFIG_LOGIN_SCRIPTS + bool "Support for login scripts" + depends on BUSYBOX_CONFIG_LOGIN + default n + 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 n + 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 n + 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 y + 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 y + depends on BUSYBOX_CONFIG_PASSWD + help + With this option passwd will refuse new passwords which are "weak". + +config BUSYBOX_CONFIG_CRYPTPW + bool "cryptpw" + default n + 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 n + 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_SU + bool "su" + default n + 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 n + 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 n + +config BUSYBOX_CONFIG_SULOGIN + bool "sulogin" + default n + 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 n + 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 0000000000..8db30310be --- /dev/null +++ b/package/utils/busybox/config/mailutils/Config.in @@ -0,0 +1,56 @@ +# DO NOT EDIT. This file is generated from Config.src +menu "Mail Utilities" + + + +config BUSYBOX_CONFIG_MAKEMIME + bool "makemime" + default n + help + Create MIME-formatted messages. + +config BUSYBOX_CONFIG_FEATURE_MIME_CHARSET + string "Default charset" + default n + depends on BUSYBOX_CONFIG_MAKEMIME || BUSYBOX_CONFIG_REFORMIME || BUSYBOX_CONFIG_SENDMAIL + help + Default charset of the message. + +config BUSYBOX_CONFIG_POPMAILDIR + bool "popmaildir" + default n + 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 n + 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 n + help + Parse MIME-formatted messages. + +config BUSYBOX_CONFIG_FEATURE_REFORMIME_COMPAT + bool "Accept and ignore options other than -x and -X" + default n + 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 n + 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 0000000000..e69d6847ec --- /dev/null +++ b/package/utils/busybox/config/miscutils/Config.in @@ -0,0 +1,766 @@ +# 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 n + 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_LESS + bool "less" + default y + 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 9999999 + depends on BUSYBOX_CONFIG_LESS + +config BUSYBOX_CONFIG_FEATURE_LESS_BRACKETS + bool "Enable bracket searching" + default n + 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 extra flags" + default n + depends on BUSYBOX_CONFIG_LESS + help + The extra flags provided do the following: + + The -M flag enables a more sophisticated status line. + The -m flag enables a simpler status line with a percentage. + +config BUSYBOX_CONFIG_FEATURE_LESS_MARKS + bool "Enable marks" + default n + 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 n + 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 n + 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 n + 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 n + 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 n + depends on BUSYBOX_CONFIG_FEATURE_LESS_DASHCMD + help + Enables "-N" command. +config BUSYBOX_CONFIG_NANDWRITE + bool "nandwrite" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Write to the specified MTD device, with bad blocks awareness + +config BUSYBOX_CONFIG_NANDDUMP + bool "nanddump" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Dump the content of raw NAND chip +config BUSYBOX_CONFIG_SETSERIAL + bool "setserial" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Retrieve or set Linux serial port. +config BUSYBOX_CONFIG_UBIATTACH + bool "ubiattach" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Attach MTD device to an UBI device. + +config BUSYBOX_CONFIG_UBIDETACH + bool "ubidetach" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Detach MTD device from an UBI device. + +config BUSYBOX_CONFIG_UBIMKVOL + bool "ubimkvol" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Create a UBI volume. + +config BUSYBOX_CONFIG_UBIRMVOL + bool "ubirmvol" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Delete a UBI volume. + +config BUSYBOX_CONFIG_UBIRSVOL + bool "ubirsvol" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Resize a UBI volume. + +config BUSYBOX_CONFIG_UBIUPDATEVOL + bool "ubiupdatevol" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Update a UBI volume. + +config BUSYBOX_CONFIG_ADJTIMEX + bool "adjtimex" + default n + 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 n + 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 n + 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 n + 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 4000 + depends on BUSYBOX_CONFIG_BEEP + help + Frequency for default beep. + +config BUSYBOX_CONFIG_FEATURE_BEEP_LENGTH_MS + int "default length" + range 0 2147483647 + default 30 + depends on BUSYBOX_CONFIG_BEEP + help + Length in ms for default beep. + +config BUSYBOX_CONFIG_CHAT + bool "chat" + default n + help + Simple chat utility. + +config BUSYBOX_CONFIG_FEATURE_CHAT_NOFAIL + bool "Enable NOFAIL expect strings" + depends on BUSYBOX_CONFIG_CHAT + default n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + help + Support CLR_ABORT directive. + +config BUSYBOX_CONFIG_CHRT + bool "chrt" + default n + help + manipulate real-time attributes of a process. + This requires sched_{g,s}etparam support in your libc. + +config BUSYBOX_CONFIG_CROND + bool "crond" + default y + 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 n + help + -d sets loglevel to 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 n + 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 "/var/spool/cron" + depends on BUSYBOX_CONFIG_CROND || BUSYBOX_CONFIG_CRONTAB + help + Location of crond spool. + +config BUSYBOX_CONFIG_CRONTAB + bool "crontab" + default y + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + help + devmem is a small program that reads and writes from physical + memory using /dev/mem. + +config BUSYBOX_CONFIG_EJECT + bool "eject" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Used to eject cdroms. (defaults to /dev/cdrom) + +config BUSYBOX_CONFIG_FEATURE_EJECT_SCSI + bool "SCSI support" + default n + 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 n + 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 n # 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 n # 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 n # 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 n # 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 n + 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 n # 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + depends on BUSYBOX_CONFIG_HDPARM + help + Enables the 'hdparm -d' option to get/set using_dma flag. + +config BUSYBOX_CONFIG_LOCK + bool "lock" + default y + help + Small utility for using locks in scripts + +config BUSYBOX_CONFIG_MAKEDEVS + bool "makedevs" + default n + 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 n + help + Format and display manual pages. + +config BUSYBOX_CONFIG_MICROCOM + bool "microcom" + default n + help + The poor man's minicom utility for chatting with serial port devices. + +config BUSYBOX_CONFIG_MOUNTPOINT + bool "mountpoint" + default n + help + mountpoint checks if the directory is a mountpoint. + +config BUSYBOX_CONFIG_MT + bool "mt" + default n + 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 n + 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 n + 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_RFKILL + bool "rfkill" + default n # 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_RUNLEVEL + bool "runlevel" + default n + 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 n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Receive files using the Xmodem protocol. + +config BUSYBOX_CONFIG_SETSID + bool "setsid" + default n + help + setsid runs a program in a new session + +config BUSYBOX_CONFIG_STRINGS + bool "strings" + default y + help + strings prints the printable character sequences for each file + specified. + +config BUSYBOX_CONFIG_TASKSET + bool "taskset" + default n # 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 n + 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_TIME + bool "time" + default y + 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 n + 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 n + 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 n + help + Prints a CD-ROM volume name. + +config BUSYBOX_CONFIG_WALL + bool "wall" + default n + depends on BUSYBOX_CONFIG_FEATURE_UTMP + help + Write a message to all users that are logged in. + +config BUSYBOX_CONFIG_WATCHDOG + bool "watchdog" + default y + 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 0000000000..77f98581fd --- /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 n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Show information about a Linux Kernel module + +config BUSYBOX_CONFIG_MODPROBE_SMALL + bool "Simplified modutils" + default n + 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 n + 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 n + depends on BUSYBOX_CONFIG_MODPROBE_SMALL + help + Check if the module is already loaded. + +config BUSYBOX_CONFIG_INSMOD + bool "insmod" + default y + 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 y + 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 y + 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 y + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 y + 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 n + 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 n + 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 "/lib/modules" + depends on BUSYBOX_CONFIG_DEPMOD || BUSYBOX_CONFIG_INSMOD || 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 "modules.dep" + 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 0000000000..442eb03428 --- /dev/null +++ b/package/utils/busybox/config/networking/Config.in @@ -0,0 +1,1088 @@ +# 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 n + 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 n + 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 n + help + Network block device client +config BUSYBOX_CONFIG_NC + bool "nc" + default y + help + A simple Unix utility which reads and writes data across network + connections. + +config BUSYBOX_CONFIG_NC_SERVER + bool "Netcat server options (-l)" + default n + depends on BUSYBOX_CONFIG_NC + help + Allow netcat to act as a server. + +config BUSYBOX_CONFIG_NC_EXTRA + bool "Netcat extensions (-eiw and filename)" + default n + 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 n # 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 and -ll. +config BUSYBOX_CONFIG_PING + bool "ping" + default y + 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 y + 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 y + 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 n + help + whois is a client for the whois directory service + +config BUSYBOX_CONFIG_FEATURE_IPV6 + bool "Enable IPv6 support" + default 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 n + 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 y + 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 y + 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 n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Manipulate the system ARP cache. + +config BUSYBOX_CONFIG_ARPING + bool "arping" + default y + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Ping hosts by ARP packets. + +config BUSYBOX_CONFIG_BRCTL + bool "brctl" + default y + 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 y + 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 y + 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 n + help + Small and static DNS server daemon. + +config BUSYBOX_CONFIG_ETHER_WAKE + bool "ether-wake" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Send a magic packet to wake up sleeping machines. + +config BUSYBOX_CONFIG_FAKEIDENTD + bool "fakeidentd" + default n + 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 n + help + simple FTP daemon. You have to run it via inetd. + +config BUSYBOX_CONFIG_FEATURE_FTP_WRITE + bool "Enable upload commands" + default n + 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 n + 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_FTPGET + bool "ftpget" + default n + help + Retrieve a remote file via FTP. + +config BUSYBOX_CONFIG_FTPPUT + bool "ftpput" + default n + help + Store a remote file via FTP. + +config BUSYBOX_CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS + bool "Enable long options in ftpget/ftpput" + default n + 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 n + help + Show or set the system's host name. + +config BUSYBOX_CONFIG_HTTPD + bool "httpd" + default n + help + Serve web pages via an HTTP server. + +config BUSYBOX_CONFIG_FEATURE_HTTPD_RANGES + bool "Support 'Ranges:' header" + default n + 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_USE_SENDFILE + bool "Use sendfile system call" + default n + depends on BUSYBOX_CONFIG_HTTPD + help + When enabled, httpd will use the kernel sendfile() function + instead of read/write loop. + +config BUSYBOX_CONFIG_FEATURE_HTTPD_SETUID + bool "Enable -u <user> option" + default n + 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 n + depends on BUSYBOX_CONFIG_HTTPD + help + Utilizes password settings from /etc/httpd.conf for basic + authentication on a per url basis. + +config BUSYBOX_CONFIG_FEATURE_HTTPD_AUTH_MD5 + bool "Support MD5 crypted passwords for http Authentication" + default n + depends on BUSYBOX_CONFIG_FEATURE_HTTPD_BASIC_AUTH + help + Enables basic per URL authentication from /etc/httpd.conf + using md5 passwords. + +config BUSYBOX_CONFIG_FEATURE_HTTPD_CGI + bool "Support Common Gateway Interface (CGI)" + default n + 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 n + 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 + config 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 n + 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 n + 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 n + 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 n + 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 n + 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 y + 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 y + 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 n + 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 n + 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 y + 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 y + 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 n + 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 n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Network interface plug detection daemon. + +config BUSYBOX_CONFIG_IFUPDOWN + bool "ifupdown" + default n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + Internet superserver daemon + +config BUSYBOX_CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO + bool "Support echo service" + default n + 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 n + 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 n + 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 n + 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 n + depends on BUSYBOX_CONFIG_INETD + help + Familiar character generator internal inetd service + +config BUSYBOX_CONFIG_FEATURE_INETD_RPC + bool "Support RPC services" + default n + depends on BUSYBOX_CONFIG_INETD + select BUSYBOX_CONFIG_FEATURE_HAVE_RPC + help + Support Sun-RPC based services + +config BUSYBOX_CONFIG_IP + bool "ip" + default n + 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 n + depends on BUSYBOX_CONFIG_IP + help + Address manipulation support for the "ip" applet. + +config BUSYBOX_CONFIG_FEATURE_IP_LINK + bool "ip link" + default n + depends on BUSYBOX_CONFIG_IP + help + Configure network devices with "ip". + +config BUSYBOX_CONFIG_FEATURE_IP_ROUTE + bool "ip route" + default n + depends on BUSYBOX_CONFIG_IP + help + Add support for routing table management to "ip". + +config BUSYBOX_CONFIG_FEATURE_IP_TUNNEL + bool "ip tunnel" + default n + depends on BUSYBOX_CONFIG_IP + help + Add support for tunneling commands to "ip". + +config BUSYBOX_CONFIG_FEATURE_IP_RULE + bool "ip rule" + default n + 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 n + 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 n + 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 n + depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_ADDRESS + +config BUSYBOX_CONFIG_IPLINK + bool + default n + depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_LINK + +config BUSYBOX_CONFIG_IPROUTE + bool + default n + depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_ROUTE + +config BUSYBOX_CONFIG_IPTUNNEL + bool + default n + depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_TUNNEL + +config BUSYBOX_CONFIG_IPRULE + bool + default n + depends on BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS && BUSYBOX_CONFIG_FEATURE_IP_RULE + +config BUSYBOX_CONFIG_IPCALC + bool "ipcalc" + default n + 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 n + 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 n + depends on BUSYBOX_CONFIG_IPCALC && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the ipcalc applet. + +config BUSYBOX_CONFIG_NETMSG + bool "netmsg" + default y + help + simple program for sending udp broadcast messages + +config BUSYBOX_CONFIG_NETSTAT + bool "netstat" + default y + 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 y + 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 y + 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 y + help + nslookup is a tool to query Internet name servers. + +config BUSYBOX_CONFIG_NTPD + bool "ntpd" + default y + 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 y + 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_PSCAN + bool "pscan" + default n + help + Simple network port scanner. + +config BUSYBOX_CONFIG_ROUTE + bool "route" + default y + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Route displays or manipulates the kernel's IP routing tables. + +config BUSYBOX_CONFIG_SLATTACH + bool "slattach" + default n + 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 n + help + tcpsvd listens on a TCP port and runs a program for each new + connection. + +config BUSYBOX_CONFIG_TELNET + bool "telnet" + default y + 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 y + 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 n + 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 y + 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 y + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + depends on BUSYBOX_CONFIG_TFTP && BUSYBOX_CONFIG_FEATURE_TFTP_BLOCKSIZE + help + Show progress bar. + +config BUSYBOX_CONFIG_TFTP_DEBUG + bool "Enable debug" + default n + 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 y + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Utility to trace the route of IP packets. + +config BUSYBOX_CONFIG_TRACEROUTE6 + bool "traceroute6" + default n + 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 y + 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 n + 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 n + depends on BUSYBOX_CONFIG_TRACEROUTE + help + Add option -I to use ICMP ECHO instead of UDP datagrams. + +config BUSYBOX_CONFIG_TUNCTL + bool "tunctl" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + tunctl creates or deletes tun devices. + +config BUSYBOX_CONFIG_FEATURE_TUNCTL_UG + bool "Support owner:group assignment" + default n + 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 "-R -n" + 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 n + help + udpsvd listens on an UDP port and runs a program for each new + connection. + +config BUSYBOX_CONFIG_VCONFIG + bool "vconfig" + default y + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Creates, removes, and configures VLAN interfaces + +config BUSYBOX_CONFIG_WGET + bool "wget" + default y + help + wget is a utility for non-interactive download of files from HTTP, + HTTPS, and FTP servers. + +config BUSYBOX_CONFIG_FEATURE_WGET_STATUSBAR + bool "Enable a nifty process meter (+2k)" + default y + 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 y + depends on BUSYBOX_CONFIG_WGET + help + Support authenticated HTTP transfers. + +config BUSYBOX_CONFIG_FEATURE_WGET_LONG_OPTIONS + bool "Enable long options" + default y + 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 read timeout option -T SEC" + default n + depends on BUSYBOX_CONFIG_WGET + help + Supports network read timeout for wget, so that wget will give + up and timeout when reading network data, through the -T command + line option. Currently only network data read timeout is + supported (i.e., timeout is not applied to the DNS nor TCP + connection initialization). When FEATURE_WGET_LONG_OPTIONS is + also enabled, the --timeout option will work in addition to -T. + +config BUSYBOX_CONFIG_ZCIP + bool "zcip" + default n + 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 0000000000..f4d26ec9c8 --- /dev/null +++ b/package/utils/busybox/config/networking/udhcp/Config.in @@ -0,0 +1,155 @@ +# 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_UDHCPD + bool "udhcp server (udhcpd)" + default n + 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 n + 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 n + 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 n + 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 n + 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 "/var/run/udhcpd.leases" + 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 y + 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 n + 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_UDHCP_PORT + bool "Enable '-P port' option for udhcpd and udhcpc" + default n + 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 0 + 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 y + 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 n + 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 "/usr/share/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 80 + 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 0000000000..ca2ea9f56c --- /dev/null +++ b/package/utils/busybox/config/printutils/Config.in @@ -0,0 +1,29 @@ +# 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 n + help + lpd is a print spooling daemon. + +config BUSYBOX_CONFIG_LPR + bool "lpr" + default n + help + lpr sends files (or standard input) to a print spooling daemon. + +config BUSYBOX_CONFIG_LPQ + bool "lpq" + default n + 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 0000000000..d8d72a75e7 --- /dev/null +++ b/package/utils/busybox/config/procps/Config.in @@ -0,0 +1,260 @@ +# 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 n + help + Report CPU and I/O statistics +config BUSYBOX_CONFIG_MPSTAT + bool "mpstat" + default n + help + Per-processor statistics +config BUSYBOX_CONFIG_NMETER + bool "nmeter" + default n + help + Prints selected system stats continuously, one line per update. +config BUSYBOX_CONFIG_PMAP + bool "pmap" + default n + help + Display processes' memory mappings. +config BUSYBOX_CONFIG_POWERTOP + bool "powertop" + default n + help + Analyze power consumption on Intel-based laptops +config BUSYBOX_CONFIG_PSTREE + bool "pstree" + default n + help + Display a tree of processes. +config BUSYBOX_CONFIG_PWDX + bool "pwdx" + default n + help + Report current working directory of a process +config BUSYBOX_CONFIG_SMEMCAP + bool "smemcap" + default n + help + smemcap is a tool for capturing process data for smem, + a memory usage statistic tool. +config BUSYBOX_CONFIG_UPTIME + bool "uptime" + default y + 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 n + 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 y + 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 n + 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 y + 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 y + 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 n + depends on BUSYBOX_CONFIG_KILL + +config BUSYBOX_CONFIG_PGREP + bool "pgrep" + default y + help + Look for processes by name. + +config BUSYBOX_CONFIG_PIDOF + bool "pidof" + default y + 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 n + 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 n + 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 n + help + Send signals to processes by name. + +config BUSYBOX_CONFIG_PS + bool "ps" + default y + help + ps gives a snapshot of the current processes. + +config BUSYBOX_CONFIG_FEATURE_PS_WIDE + bool "Enable wide output option (-w)" + default y + depends on BUSYBOX_CONFIG_PS + 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_TIME + bool "Enable time and elapsed time output" + default n + 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 n + 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 n + 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 n + help + Renice alters the scheduling priority of one or more running + processes. + +config BUSYBOX_CONFIG_BB_SYSCTL + bool "sysctl" + default y + help + Configure kernel parameters at runtime. + +config BUSYBOX_CONFIG_TOP + bool "top" + default y + 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 y + 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 y + 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 n + 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 n + 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 n + 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 n + depends on BUSYBOX_CONFIG_TOP + help + Enable 's' in top (gives lots of memory info). + +config BUSYBOX_CONFIG_FEATURE_SHOW_THREADS + bool "Support for showing threads in ps/pstree/top" + default n + 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 n + 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 0000000000..9d7c5970a9 --- /dev/null +++ b/package/utils/busybox/config/runit/Config.in @@ -0,0 +1,90 @@ +# 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 n + help + runsv starts and monitors a service and optionally an appendant log + service. + +config BUSYBOX_CONFIG_RUNSVDIR + bool "runsvdir" + default n + 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 n + 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 n + 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 "/var/service" + depends on BUSYBOX_CONFIG_SV + help + Default directory for services. + Defaults to "/var/service" + +config BUSYBOX_CONFIG_SVLOGD + bool "svlogd" + default n + 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 n + help + chpst changes the process state according to the given options, and + execs specified program. + +config BUSYBOX_CONFIG_SETUIDGID + bool "setuidgid" + default n + help + Sets soft resource limits as specified by options + +config BUSYBOX_CONFIG_ENVUIDGID + bool "envuidgid" + default n + help + Sets $UID to account's uid and $GID to account's gid + +config BUSYBOX_CONFIG_ENVDIR + bool "envdir" + default n + help + Sets various environment variables as specified by files + in the given directory + +config BUSYBOX_CONFIG_SOFTLIMIT + bool "softlimit" + default n + 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 0000000000..e7317ca810 --- /dev/null +++ b/package/utils/busybox/config/selinux/Config.in @@ -0,0 +1,125 @@ +# 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 n + 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 n + depends on BUSYBOX_CONFIG_CHCON && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the chcon applet. + +config BUSYBOX_CONFIG_GETENFORCE + bool "getenforce" + default n + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support to get the current mode of SELinux. + +config BUSYBOX_CONFIG_GETSEBOOL + bool "getsebool" + default n + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support to get SELinux boolean values. + +config BUSYBOX_CONFIG_LOAD_POLICY + bool "load_policy" + default n + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support to load SELinux policy. + +config BUSYBOX_CONFIG_MATCHPATHCON + bool "matchpathcon" + default n + 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 n + 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 n + 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 n + depends on BUSYBOX_CONFIG_RUNCON && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the runcon applet. + +config BUSYBOX_CONFIG_SELINUXENABLED + bool "selinuxenabled" + default n + 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 n + depends on BUSYBOX_CONFIG_SELINUX + help + Enable support to modify the mode SELinux is running in. + +config BUSYBOX_CONFIG_SETFILES + bool "setfiles" + default n + 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 n + 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 n + 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 n + 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 0000000000..a271a386d6 --- /dev/null +++ b/package/utils/busybox/config/shell/Config.in @@ -0,0 +1,433 @@ +# 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 y + 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 y + depends on BUSYBOX_CONFIG_ASH + help + Enable bash-compatible extensions. + +config BUSYBOX_CONFIG_ASH_IDLE_TIMEOUT + bool "Idle timeout variable" + default n + 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 y + depends on BUSYBOX_CONFIG_ASH + help + Enable job control in the ash shell. + +config BUSYBOX_CONFIG_ASH_ALIAS + bool "Alias support" + default y + 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 y + 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 y + 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 y + 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 y + depends on BUSYBOX_CONFIG_ASH + help + Enable support for test builtin in ash. + +config BUSYBOX_CONFIG_ASH_CMDCMD + bool "'command' command to override shell builtins" + default y + 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 n + 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 n + 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 n + 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 y + 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 n + 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' + +config BUSYBOX_CONFIG_HUSH + bool "hush" + default n + 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 y + depends on BUSYBOX_CONFIG_HUSH + help + Enable bash-compatible extensions. + +config BUSYBOX_CONFIG_HUSH_BRACE_EXPANSION + bool "Brace expansion" + default n + depends on BUSYBOX_CONFIG_HUSH_BASH_COMPAT + help + Enable {abc,def} extension. + +config BUSYBOX_CONFIG_HUSH_HELP + bool "help builtin" + default y + depends on BUSYBOX_CONFIG_HUSH + help + Enable help builtin in hush. Code size + ~1 kbyte. + +config BUSYBOX_CONFIG_HUSH_INTERACTIVE + bool "Interactive mode" + default y + 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 n + 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 y + 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 y + 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 y + 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 y + 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 y + 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 y + 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 y + 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 n + 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 y + 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 n + 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 n + 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 y + 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 y + 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 n + 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 n + 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 n + 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 n + 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 0000000000..f403a684bb --- /dev/null +++ b/package/utils/busybox/config/sysklogd/Config.in @@ -0,0 +1,154 @@ +# 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 y + 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 y + 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 y + 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 n + 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 n + 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 256 + 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 y + 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 16 + 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 y + depends on BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG && BROKEN + 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 n + 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_KLOGD + bool "klogd" + default y + 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. + +config BUSYBOX_CONFIG_FEATURE_KLOGD_KLOGCTL + bool "Use the klogctl() interface" + default y + 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 y + 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 0000000000..d60b139a8b --- /dev/null +++ b/package/utils/busybox/config/util-linux/Config.in @@ -0,0 +1,985 @@ +# 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 n + help + Performs some ioctls with block devices. +config BUSYBOX_CONFIG_REV + bool "rev" + default n + help + Reverse lines of a file or files. + +config BUSYBOX_CONFIG_ACPID + bool "acpid" + default n + 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 n + depends on BUSYBOX_CONFIG_ACPID + help + Accept and ignore compatibility options -g -m -s -S -v. + +config BUSYBOX_CONFIG_BLKID + bool "blkid" + default n + 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 n + depends on BUSYBOX_CONFIG_BLKID + help + Show TYPE="filesystem type" + +config BUSYBOX_CONFIG_DMESG + bool "dmesg" + default y + 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 y + 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 n + 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 n + 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 n + depends on BUSYBOX_CONFIG_FBSET + help + This option allows fbset to read the video mode database stored by + default n /etc/fb.modes, which can be used to set frame buffer + device to pre-defined video modes. + +config BUSYBOX_CONFIG_FDFLUSH + bool "fdflush" + default n + 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 n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + fdformat is used to low-level format a floppy disk. + +config BUSYBOX_CONFIG_FDISK + bool "fdisk" + default n + 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 y + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + 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 n + help + Manage locks from shell scripts + +config BUSYBOX_CONFIG_FREERAMDISK + bool "freeramdisk" + default n + 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 n + 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 n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Utility to create EXT2 filesystems. + +config BUSYBOX_CONFIG_MKFS_MINIX + bool "mkfs_minix" + default n + 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 n + 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 n + 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 n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Utility to create FAT32 filesystems. + +config BUSYBOX_CONFIG_GETOPT + bool "getopt" + default n + 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 n 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 y + 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 n + 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 n + depends on BUSYBOX_CONFIG_HEXDUMP + help + hd is an alias to hexdump -C. + +config BUSYBOX_CONFIG_HWCLOCK + bool "hwclock" + default y + 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 n + 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 n # 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 n + 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 n + 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 n + 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 n + #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 n + #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_MDEV + bool "mdev" + default n + 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 n + 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 n + 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 n + 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 n + 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 n + 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_MKSWAP + bool "mkswap" + default y + 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 n + depends on BUSYBOX_CONFIG_MKSWAP + help + Generate swap spaces with universally unique identifiers. + +config BUSYBOX_CONFIG_MORE + bool "more" + default n + 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 y + 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 n + 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 n + 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 y + 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 n + 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" + default n + depends on BUSYBOX_CONFIG_MOUNT + select BUSYBOX_CONFIG_FEATURE_HAVE_RPC + select BUSYBOX_CONFIG_FEATURE_SYSLOG + help + Enable mounting of NFS file systems. + +config BUSYBOX_CONFIG_FEATURE_MOUNT_CIFS + bool "Support mounting CIFS/SMB file systems" + default y + 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 y + 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 y + help + Support mount all and looking for files in /etc/fstab. + +config BUSYBOX_CONFIG_PIVOT_ROOT + bool "pivot_root" + default y + 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 n + 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 n + help + Print the device node associated with the filesystem mounted at '/'. + +config BUSYBOX_CONFIG_READPROFILE + bool "readprofile" + default n + #select PLATFORM_LINUX + help + This allows you to parse /proc/profile for basic profiling. + +config BUSYBOX_CONFIG_RTCWAKE + bool "rtcwake" + default n + select BUSYBOX_CONFIG_PLATFORM_LINUX + help + Enter a system sleep state until specified wakeup time. + +config BUSYBOX_CONFIG_SCRIPT + bool "script" + default n + help + The script makes typescript of terminal session. + +config BUSYBOX_CONFIG_SCRIPTREPLAY + bool "scriptreplay" + default n + help + This program replays a typescript, using timing information + given by script -t. + +config BUSYBOX_CONFIG_SETARCH + bool "setarch" + default n + 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 y + 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_PRI + bool "Support priority option -p" + default n + depends on BUSYBOX_CONFIG_SWAPONOFF + help + Enable support for setting swap device priority in swapon. + +config BUSYBOX_CONFIG_SWITCH_ROOT + bool "switch_root" + default y + 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 y + 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 y + 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 y + 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 n + 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 n + 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. + +config BUSYBOX_CONFIG_VOLUMEID + bool #No description makes it a hidden option + default n + +menu "Filesystem/Volume identification" + depends on BUSYBOX_CONFIG_VOLUMEID + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_EXT + bool "Ext filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_BTRFS + bool "btrfs filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_REISERFS + bool "Reiser filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_FAT + bool "fat filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_HFS + bool "hfs filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_JFS + bool "jfs filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +### config FEATURE_VOLUMEID_UFS +### bool "ufs filesystem" +### default y +### depends on VOLUMEID +### help +### TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_XFS + bool "xfs filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_NTFS + bool "ntfs filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_ISO9660 + bool "iso9660 filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_UDF + bool "udf filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_LUKS + bool "luks filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_LINUXSWAP + bool "linux swap filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +### config FEATURE_VOLUMEID_LVM +### bool "lvm" +### default y +### depends on VOLUMEID +### help +### TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_CRAMFS + bool "cramfs filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +### config FEATURE_VOLUMEID_HPFS +### bool "hpfs filesystem" +### default y +### depends on VOLUMEID +### help +### TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_ROMFS + bool "romfs filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_SYSV + bool "sysv filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +### config FEATURE_VOLUMEID_MINIX +### bool "minix filesystem" +### default y +### depends on VOLUMEID +### help +### TODO + +### These only detect partition tables - not used (yet?) +### config FEATURE_VOLUMEID_MAC +### bool "mac filesystem" +### default y +### depends on VOLUMEID +### help +### TODO +### +### config FEATURE_VOLUMEID_MSDOS +### bool "msdos filesystem" +### default y +### depends on VOLUMEID +### help +### TODO + +config BUSYBOX_CONFIG_FEATURE_VOLUMEID_OCFS2 + bool "ocfs2 filesystem" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +### config FEATURE_VOLUMEID_HIGHPOINTRAID +### bool "highpoint raid" +### 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_VIARAID +### bool "via 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_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 BUSYBOX_CONFIG_FEATURE_VOLUMEID_LINUXRAID + bool "linuxraid" + default n + depends on BUSYBOX_CONFIG_VOLUMEID + help + TODO + +endmenu + +endmenu diff --git a/package/utils/busybox/convert_menuconfig.pl b/package/utils/busybox/convert_menuconfig.pl new file mode 100755 index 0000000000..0128bf78d7 --- /dev/null +++ b/package/utils/busybox/convert_menuconfig.pl @@ -0,0 +1,78 @@ +#!/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 $DEFCONFIG = $ARGV[1]; +($DEFCONFIG and -f $DEFCONFIG) or die 'invalid config file'; + +my %config; + +open CONFIG, $DEFCONFIG or die 'cannot open config file'; +while (<CONFIG>) { + /^CONFIG_([\w_]+)=([ym])/ and $config{$1} = $2; + /^CONFIG_([\w_]+)=(\d+)/ and $config{$1} = $2; + /^CONFIG_([\w_]+)=(".+")/ and $config{$1} = $2; +} +close 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\/busybox\/config\//; + + $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 = $config{$cur} or $c = 'n'; + + $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 0000000000..465b1ab45b --- /dev/null +++ b/package/utils/busybox/files/cron @@ -0,0 +1,18 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006-2011 OpenWrt.org + +START=50 + +SERVICE_USE_PID=1 + +start () { + loglevel=$(uci_get "system.@system[0].cronloglevel") + [ -z "$(ls /etc/crontabs/)" ] && exit 1 + mkdir -p /var/spool/cron + ln -s /etc/crontabs /var/spool/cron/ 2>/dev/null + service_start /usr/sbin/crond -c /etc/crontabs -l ${loglevel:-5} +} + +stop() { + service_stop /usr/sbin/crond +} diff --git a/package/utils/busybox/files/telnet b/package/utils/busybox/files/telnet new file mode 100755 index 0000000000..994e713e70 --- /dev/null +++ b/package/utils/busybox/files/telnet @@ -0,0 +1,37 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006-2011 OpenWrt.org + +START=50 + +has_root_pwd() { + local pwd=$([ -f "$1" ] && cat "$1") + pwd="${pwd#*root:}" + pwd="${pwd%%:*}" + + test -n "${pwd#[\!x]}" +} + +get_root_home() { + local homedir=$([ -f "$1" ] && cat "$1") + homedir="${homedir#*:*:0:0:*:}" + + echo "${homedir%%:*}" +} + +has_ssh_pubkey() { + ( /etc/init.d/dropbear enabled 2> /dev/null && grep -qs "^ssh-" /etc/dropbear/authorized_keys ) || \ + ( /etc/init.d/sshd enabled 2> /dev/null && grep -qs "^ssh-" "$(get_root_home /etc/passwd)"/.ssh/authorized_keys ) +} + +start() { + if ( ! has_ssh_pubkey && \ + ! has_root_pwd /etc/passwd && ! has_root_pwd /etc/shadow ) || \ + ( ! /etc/init.d/dropbear enabled 2> /dev/null && ! /etc/init.d/sshd enabled 2> /dev/null ); + then + service_start /usr/sbin/telnetd -l /bin/login.sh + fi +} + +stop() { + service_stop /usr/sbin/telnetd +} diff --git a/package/utils/busybox/patches/001-init_avoid_loop_opening_tty.patch b/package/utils/busybox/patches/001-init_avoid_loop_opening_tty.patch new file mode 100644 index 0000000000..4db64c34be --- /dev/null +++ b/package/utils/busybox/patches/001-init_avoid_loop_opening_tty.patch @@ -0,0 +1,15 @@ +--- a/init/init.c ++++ b/init/init.c +@@ -573,8 +573,11 @@ static void run_actions(int action_type) + /* Only run stuff with pid == 0. If pid != 0, + * it is already running + */ +- if (a->pid == 0) ++ if (a->pid == 0) { ++ if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) ++ continue; + a->pid = run(a); ++ } + } + } + } diff --git a/package/utils/busybox/patches/002-passwd_use_md5_hash_by_default_like_it_used_to_be.patch b/package/utils/busybox/patches/002-passwd_use_md5_hash_by_default_like_it_used_to_be.patch new file mode 100644 index 0000000000..ff79f3ee9c --- /dev/null +++ b/package/utils/busybox/patches/002-passwd_use_md5_hash_by_default_like_it_used_to_be.patch @@ -0,0 +1,20 @@ +From eb80c2a5315ed08bd329448217695375d89732c9 Mon Sep 17 00:00:00 2001 +From: Nicolas Thill <nico@openwrt.org> +Date: Wed, 9 Nov 2011 18:17:20 +0100 +Subject: [PATCH] passwd: use MD5 hash by default (like it used to be) + +--- + loginutils/passwd.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +--- a/loginutils/passwd.c ++++ b/loginutils/passwd.c +@@ -94,7 +94,7 @@ int passwd_main(int argc UNUSED_PARAM, c + }; + unsigned opt; + int rc; +- const char *opt_a = "d"; /* des */ ++ const char *opt_a = "m"; /* md5 */ + const char *filename; + char *myname; + char *name; diff --git a/package/utils/busybox/patches/003-brctl_show_fix.patch b/package/utils/busybox/patches/003-brctl_show_fix.patch new file mode 100644 index 0000000000..8177fb01c6 --- /dev/null +++ b/package/utils/busybox/patches/003-brctl_show_fix.patch @@ -0,0 +1,37 @@ +--- a/networking/brctl.c ++++ b/networking/brctl.c +@@ -129,7 +129,7 @@ int brctl_main(int argc UNUSED_PARAM, ch + "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" + "setpathcost\0" "setportprio\0" "setbridgeprio\0" + ) +- IF_FEATURE_BRCTL_SHOW("showmacs\0" "show\0"); ++ IF_FEATURE_BRCTL_SHOW("show\0"); + + enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif + IF_FEATURE_BRCTL_FANCY(, +@@ -137,7 +137,7 @@ int brctl_main(int argc UNUSED_PARAM, ch + ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, + ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio + ) +- IF_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show) ++ IF_FEATURE_BRCTL_SHOW(, ARG_show) + }; + + int fd; +--- a/networking/Config.src ++++ b/networking/Config.src +@@ -82,12 +82,12 @@ config FEATURE_BRCTL_FANCY + This adds about 600 bytes. + + config FEATURE_BRCTL_SHOW +- bool "Support show, showmac and showstp" ++ bool "Support show" + default y + depends on BRCTL && FEATURE_BRCTL_FANCY + help + Add support for option which prints the current config: +- showmacs, showstp, show ++ show + + config DNSD + bool "dnsd" diff --git a/package/utils/busybox/patches/004-upstream-percent_decode_in_place.patch b/package/utils/busybox/patches/004-upstream-percent_decode_in_place.patch new file mode 100644 index 0000000000..d94ee47900 --- /dev/null +++ b/package/utils/busybox/patches/004-upstream-percent_decode_in_place.patch @@ -0,0 +1,237 @@ +http://git.busybox.net/busybox/commit/?id=dd1061b6a79b0161597799e825bfefc27993ace5 + +From dd1061b6a79b0161597799e825bfefc27993ace5 Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko <vda.linux@googlemail.com> +Date: Sun, 11 Sep 2011 21:04:02 +0200 +Subject: [PATCH] wget: URL-decode user:password before base64-encoding it into auth hdr. Closes 3625. + +function old new delta +percent_decode_in_place - 152 +152 +parse_url 304 317 +13 +handle_incoming_and_exit 2795 2798 +3 +httpd_main 763 760 -3 +decodeString 152 - -152 +------------------------------------------------------------------------------ +(add/remove: 2/1 grow/shrink: 2/1 up/down: 168/-155) Total: 13 bytes + +Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> + +--- a/include/libbb.h ++++ b/include/libbb.h +@@ -1570,6 +1570,15 @@ int starts_with_cpu(const char *str) FAS + unsigned get_cpu_count(void) FAST_FUNC; + + ++/* Use strict=1 if you process input from untrusted source: ++ * it will return NULL on invalid %xx (bad hex chars) ++ * and str + 1 if decoded char is / or NUL. ++ * In non-strict mode, it always succeeds (returns str), ++ * and also it additionally decoded '+' to space. ++ */ ++char *percent_decode_in_place(char *str, int strict) FAST_FUNC; ++ ++ + extern const char bb_uuenc_tbl_base64[]; + extern const char bb_uuenc_tbl_std[]; + void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC; +--- /dev/null ++++ b/libbb/percent_decode.c +@@ -0,0 +1,69 @@ ++/* vi: set sw=4 ts=4: */ ++/* ++ * Licensed under GPLv2 or later, see file LICENSE in this source tree. ++ */ ++ ++//kbuild:lib-y += percent_decode.o ++ ++#include "libbb.h" ++ ++static unsigned hex_to_bin(unsigned char c) ++{ ++ unsigned v; ++ ++ v = c - '0'; ++ if (v <= 9) ++ return v; ++ /* c | 0x20: letters to lower case, non-letters ++ * to (potentially different) non-letters */ ++ v = (unsigned)(c | 0x20) - 'a'; ++ if (v <= 5) ++ return v + 10; ++ return ~0; ++/* For testing: ++void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); } ++int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f'); ++t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; } ++*/ ++} ++ ++char* FAST_FUNC percent_decode_in_place(char *str, int strict) ++{ ++ /* note that decoded string is always shorter than original */ ++ char *src = str; ++ char *dst = str; ++ char c; ++ ++ while ((c = *src++) != '\0') { ++ unsigned v; ++ ++ if (!strict && c == '+') { ++ *dst++ = ' '; ++ continue; ++ } ++ if (c != '%') { ++ *dst++ = c; ++ continue; ++ } ++ v = hex_to_bin(src[0]); ++ if (v > 15) { ++ bad_hex: ++ if (strict) ++ return NULL; ++ *dst++ = '%'; ++ continue; ++ } ++ v = (v * 16) | hex_to_bin(src[1]); ++ if (v > 255) ++ goto bad_hex; ++ if (strict && (v == '/' || v == '\0')) { ++ /* caller takes it as indication of invalid ++ * (dangerous wrt exploits) chars */ ++ return str + 1; ++ } ++ *dst++ = v; ++ src += 2; ++ } ++ *dst = '\0'; ++ return str; ++} +--- a/networking/httpd.c ++++ b/networking/httpd.c +@@ -820,78 +820,6 @@ static char *encodeString(const char *st + } + #endif + +-/* +- * Given a URL encoded string, convert it to plain ascii. +- * Since decoding always makes strings smaller, the decode is done in-place. +- * Thus, callers should xstrdup() the argument if they do not want the +- * argument modified. The return is the original pointer, allowing this +- * function to be easily used as arguments to other functions. +- * +- * string The first string to decode. +- * option_d 1 if called for httpd -d +- * +- * Returns a pointer to the decoded string (same as input). +- */ +-static unsigned hex_to_bin(unsigned char c) +-{ +- unsigned v; +- +- v = c - '0'; +- if (v <= 9) +- return v; +- /* c | 0x20: letters to lower case, non-letters +- * to (potentially different) non-letters */ +- v = (unsigned)(c | 0x20) - 'a'; +- if (v <= 5) +- return v + 10; +- return ~0; +-/* For testing: +-void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); } +-int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f'); +-t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; } +-*/ +-} +-static char *decodeString(char *orig, int option_d) +-{ +- /* note that decoded string is always shorter than original */ +- char *string = orig; +- char *ptr = string; +- char c; +- +- while ((c = *ptr++) != '\0') { +- unsigned v; +- +- if (option_d && c == '+') { +- *string++ = ' '; +- continue; +- } +- if (c != '%') { +- *string++ = c; +- continue; +- } +- v = hex_to_bin(ptr[0]); +- if (v > 15) { +- bad_hex: +- if (!option_d) +- return NULL; +- *string++ = '%'; +- continue; +- } +- v = (v * 16) | hex_to_bin(ptr[1]); +- if (v > 255) +- goto bad_hex; +- if (!option_d && (v == '/' || v == '\0')) { +- /* caller takes it as indication of invalid +- * (dangerous wrt exploits) chars */ +- return orig + 1; +- } +- *string++ = v; +- ptr += 2; +- } +- *string = '\0'; +- return orig; +-} +- + #if ENABLE_FEATURE_HTTPD_BASIC_AUTH + /* + * Decode a base64 data stream as per rfc1521. +@@ -1949,7 +1877,7 @@ static void handle_incoming_and_exit(con + } + + /* Decode URL escape sequences */ +- tptr = decodeString(urlcopy, 0); ++ tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1); + if (tptr == NULL) + send_headers_and_exit(HTTP_BAD_REQUEST); + if (tptr == urlcopy + 1) { +@@ -2408,7 +2336,7 @@ int httpd_main(int argc UNUSED_PARAM, ch + , &verbose + ); + if (opt & OPT_DECODE_URL) { +- fputs(decodeString(url_for_decode, 1), stdout); ++ fputs(percent_decode_in_place(url_for_decode, /*strict:*/ 0), stdout); + return 0; + } + #if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR +--- a/networking/wget.c ++++ b/networking/wget.c +@@ -298,8 +298,13 @@ static void parse_url(const char *src_ur + + sp = strrchr(h->host, '@'); + if (sp != NULL) { +- h->user = h->host; ++ // URL-decode "user:password" string before base64-encoding: ++ // wget http://test:my%20pass@example.com should send ++ // Authorization: Basic dGVzdDpteSBwYXNz ++ // which decodes to "test:my pass". ++ // Standard wget and curl do this too. + *sp = '\0'; ++ h->user = percent_decode_in_place(h->host, /*strict:*/ 0); + h->host = sp + 1; + } + +@@ -661,12 +666,6 @@ static void download_one_url(const char + + #if ENABLE_FEATURE_WGET_AUTHENTICATION + if (target.user) { +-//TODO: URL-decode "user:password" string before base64-encoding: +-//wget http://test:my%20pass@example.com should send +-// Authorization: Basic dGVzdDpteSBwYXNz +-//which decodes to "test:my pass", instead of what we send now: +-// Authorization: Basic dGVzdDpteSUyMHBhc3M= +-//Can reuse decodeString() from httpd.c + fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6, + base64enc(target.user)); + } diff --git a/package/utils/busybox/patches/005-resource_h_include.patch b/package/utils/busybox/patches/005-resource_h_include.patch new file mode 100644 index 0000000000..d66d66d67e --- /dev/null +++ b/package/utils/busybox/patches/005-resource_h_include.patch @@ -0,0 +1,10 @@ +--- a/include/libbb.h ++++ b/include/libbb.h +@@ -35,6 +35,7 @@ + #include <sys/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/006-upstream_CVE-2011-2716_fixes.patch b/package/utils/busybox/patches/006-upstream_CVE-2011-2716_fixes.patch new file mode 100644 index 0000000000..532fcee0fb --- /dev/null +++ b/package/utils/busybox/patches/006-upstream_CVE-2011-2716_fixes.patch @@ -0,0 +1,164 @@ +--- a/networking/udhcp/common.c ++++ b/networking/udhcp/common.c +@@ -29,16 +29,16 @@ const struct dhcp_optflag dhcp_optflags[ + // { OPTION_IP | OPTION_LIST , 0x07 }, /* DHCP_LOG_SERVER */ + // { OPTION_IP | OPTION_LIST , 0x08 }, /* DHCP_COOKIE_SERVER */ + { OPTION_IP | OPTION_LIST , 0x09 }, /* DHCP_LPR_SERVER */ +- { OPTION_STRING | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME */ ++ { OPTION_STRING_HOST | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME */ + { OPTION_U16 , 0x0d }, /* DHCP_BOOT_SIZE */ +- { OPTION_STRING | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME */ ++ { OPTION_STRING_HOST | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME */ + { OPTION_IP , 0x10 }, /* DHCP_SWAP_SERVER */ + { OPTION_STRING , 0x11 }, /* DHCP_ROOT_PATH */ + { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */ + { OPTION_U16 , 0x1a }, /* DHCP_MTU */ + { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */ + { OPTION_IP_PAIR | OPTION_LIST , 0x21 }, /* DHCP_ROUTES */ +- { OPTION_STRING , 0x28 }, /* DHCP_NIS_DOMAIN */ ++ { OPTION_STRING_HOST , 0x28 }, /* DHCP_NIS_DOMAIN */ + { OPTION_IP | OPTION_LIST , 0x29 }, /* DHCP_NIS_SERVER */ + { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a }, /* DHCP_NTP_SERVER */ + { OPTION_IP | OPTION_LIST , 0x2c }, /* DHCP_WINS_SERVER */ +@@ -46,7 +46,7 @@ const struct dhcp_optflag dhcp_optflags[ + { OPTION_IP , 0x36 }, /* DHCP_SERVER_ID */ + { OPTION_STRING , 0x38 }, /* DHCP_ERR_MESSAGE */ + //TODO: must be combined with 'sname' and 'file' handling: +- { OPTION_STRING , 0x42 }, /* DHCP_TFTP_SERVER_NAME */ ++ { OPTION_STRING_HOST , 0x42 }, /* DHCP_TFTP_SERVER_NAME */ + { OPTION_STRING , 0x43 }, /* DHCP_BOOT_FILE */ + //TODO: not a string, but a set of LASCII strings: + // { OPTION_STRING , 0x4D }, /* DHCP_USER_CLASS */ +@@ -143,6 +143,7 @@ const uint8_t dhcp_option_lengths[] ALIG + [OPTION_IP_PAIR] = 8, + // [OPTION_BOOLEAN] = 1, + [OPTION_STRING] = 1, /* ignored by udhcp_str2optset */ ++ [OPTION_STRING_HOST] = 1, /* ignored by udhcp_str2optset */ + #if ENABLE_FEATURE_UDHCP_RFC3397 + [OPTION_DNS_STRING] = 1, /* ignored by both udhcp_str2optset and xmalloc_optname_optval */ + [OPTION_SIP_SERVERS] = 1, +@@ -411,7 +412,9 @@ static NOINLINE void attach_option( + /* actually 255 is ok too, but adding a space can overlow it */ + + existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length); +- if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING) { ++ if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING ++ || (optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING_HOST ++ ) { + /* add space separator between STRING options in a list */ + existing->data[OPT_DATA + old_len] = ' '; + old_len++; +@@ -475,6 +478,7 @@ int FAST_FUNC udhcp_str2optset(const cha + retval = udhcp_str2nip(val, buffer + 4); + break; + case OPTION_STRING: ++ case OPTION_STRING_HOST: + #if ENABLE_FEATURE_UDHCP_RFC3397 + case OPTION_DNS_STRING: + #endif +--- a/networking/udhcp/common.h ++++ b/networking/udhcp/common.h +@@ -80,6 +80,9 @@ enum { + OPTION_IP = 1, + OPTION_IP_PAIR, + OPTION_STRING, ++ /* Opts of STRING_HOST type will be sanitized before they are passed ++ * to udhcpc script's environment: */ ++ OPTION_STRING_HOST, + // OPTION_BOOLEAN, + OPTION_U8, + OPTION_U16, +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -101,6 +101,7 @@ static const uint8_t len_of_option_as_st + [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2, + [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "), + [OPTION_STRING ] = 1, ++ [OPTION_STRING_HOST ] = 1, + #if ENABLE_FEATURE_UDHCP_RFC3397 + [OPTION_DNS_STRING ] = 1, /* unused */ + /* Hmmm, this severely overestimates size if SIP_SERVERS option +@@ -135,6 +136,63 @@ static int mton(uint32_t mask) + return i; + } + ++/* Check if a given label represents a valid DNS label ++ * Return pointer to the first character after the label upon success, ++ * NULL otherwise. ++ * See RFC1035, 2.3.1 ++ */ ++/* We don't need to be particularly anal. For example, allowing _, hyphen ++ * at the end, or leading and trailing dots would be ok, since it ++ * can't be used for attacks. (Leading hyphen can be, if someone uses ++ * cmd "$hostname" ++ * in the script: then hostname may be treated as an option) ++ */ ++static const char *valid_domain_label(const char *label) ++{ ++ unsigned char ch; ++ unsigned pos = 0; ++ ++ for (;;) { ++ ch = *label; ++ if ((ch|0x20) < 'a' || (ch|0x20) > 'z') { ++ if (pos == 0) { ++ /* label must begin with letter */ ++ return NULL; ++ } ++ if (ch < '0' || ch > '9') { ++ if (ch == '\0' || ch == '.') ++ return label; ++ /* DNS allows only '-', but we are more permissive */ ++ if (ch != '-' && ch != '_') ++ return NULL; ++ } ++ } ++ label++; ++ pos++; ++ //Do we want this? ++ //if (pos > 63) /* NS_MAXLABEL; labels must be 63 chars or less */ ++ // return NULL; ++ } ++} ++ ++/* Check if a given name represents a valid DNS name */ ++/* See RFC1035, 2.3.1 */ ++static int good_hostname(const char *name) ++{ ++ //const char *start = name; ++ ++ for (;;) { ++ name = valid_domain_label(name); ++ if (!name) ++ return 0; ++ if (!name[0]) ++ return 1; ++ //Do we want this? ++ //return ((name - start) < 1025); /* NS_MAXDNAME */ ++ name++; ++ } ++} ++ + /* Create "opt_name=opt_value" string */ + static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_optflag *optflag, const char *opt_name) + { +@@ -185,8 +243,11 @@ static NOINLINE char *xmalloc_optname_op + break; + } + case OPTION_STRING: ++ case OPTION_STRING_HOST: + memcpy(dest, option, len); + dest[len] = '\0'; ++ if (type == OPTION_STRING_HOST && !good_hostname(dest)) ++ safe_strncpy(dest, "bad", len); + return ret; /* Short circuit this case */ + case OPTION_STATIC_ROUTES: { + /* Option binary format: +@@ -314,6 +375,7 @@ static char **fill_envp(struct dhcp_pack + /* +1 element for each option, +2 for subnet option: */ + if (packet) { + /* note: do not search for "pad" (0) and "end" (255) options */ ++//TODO: change logic to scan packet _once_ + for (i = 1; i < 255; i++) { + temp = udhcp_get_option(packet, i); + if (temp) { diff --git a/package/utils/busybox/patches/007-upstream_mkfs_ext2_fixes.patch b/package/utils/busybox/patches/007-upstream_mkfs_ext2_fixes.patch new file mode 100644 index 0000000000..8528ee87f9 --- /dev/null +++ b/package/utils/busybox/patches/007-upstream_mkfs_ext2_fixes.patch @@ -0,0 +1,1441 @@ +--- a/e2fsprogs/e2fs_defs.h ++++ /dev/null +@@ -1,561 +0,0 @@ +-/* vi: set sw=4 ts=4: */ +-/* +- * linux/include/linux/ext2_fs.h +- * +- * Copyright (C) 1992, 1993, 1994, 1995 +- * Remy Card (card@masi.ibp.fr) +- * Laboratoire MASI - Institut Blaise Pascal +- * Universite Pierre et Marie Curie (Paris VI) +- * +- * Copyright (C) 1991, 1992 Linus Torvalds +- */ +- +-#ifndef LINUX_EXT2_FS_H +-#define LINUX_EXT2_FS_H 1 +- +-/* +- * Special inode numbers +- */ +-#define EXT2_BAD_INO 1 /* Bad blocks inode */ +-#define EXT2_ROOT_INO 2 /* Root inode */ +-#define EXT2_ACL_IDX_INO 3 /* ACL inode */ +-#define EXT2_ACL_DATA_INO 4 /* ACL inode */ +-#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ +-#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ +-#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */ +-#define EXT2_JOURNAL_INO 8 /* Journal inode */ +- +-/* First non-reserved inode for old ext2 filesystems */ +-#define EXT2_GOOD_OLD_FIRST_INO 11 +- +-/* +- * The second extended file system magic number +- */ +-#define EXT2_SUPER_MAGIC 0xEF53 +- +-/* Assume that user mode programs are passing in an ext2fs superblock, not +- * a kernel struct super_block. This will allow us to call the feature-test +- * macros from user land. */ +-#define EXT2_SB(sb) (sb) +- +-/* +- * Maximal count of links to a file +- */ +-#define EXT2_LINK_MAX 32000 +- +-/* +- * Macro-instructions used to manage several block sizes +- */ +-#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */ +-#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */ +-#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE) +-#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE) +-#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) +-#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) +-#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ +- EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size) +-#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ +- EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino) +-#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(uint32_t)) +- +-/* +- * Macro-instructions used to manage fragments +- */ +-#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE +-#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE +-#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE +-#define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size) +-#define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s)) +- +-/* +- * ACL structures +- */ +-struct ext2_acl_header { /* Header of Access Control Lists */ +- uint32_t aclh_size; +- uint32_t aclh_file_count; +- uint32_t aclh_acle_count; +- uint32_t aclh_first_acle; +-}; +- +-struct ext2_acl_entry { /* Access Control List Entry */ +- uint32_t acle_size; +- uint16_t acle_perms; /* Access permissions */ +- uint16_t acle_type; /* Type of entry */ +- uint16_t acle_tag; /* User or group identity */ +- uint16_t acle_pad1; +- uint32_t acle_next; /* Pointer on next entry for the */ +- /* same inode or on next free entry */ +-}; +- +-/* +- * Structure of a blocks group descriptor +- */ +-struct ext2_group_desc { +- uint32_t bg_block_bitmap; /* Blocks bitmap block */ +- uint32_t bg_inode_bitmap; /* Inodes bitmap block */ +- uint32_t bg_inode_table; /* Inodes table block */ +- uint16_t bg_free_blocks_count; /* Free blocks count */ +- uint16_t bg_free_inodes_count; /* Free inodes count */ +- uint16_t bg_used_dirs_count; /* Directories count */ +- uint16_t bg_pad; +- uint32_t bg_reserved[3]; +-}; +- +-/* +- * Data structures used by the directory indexing feature +- * +- * Note: all of the multibyte integer fields are little endian. +- */ +- +-/* +- * Note: dx_root_info is laid out so that if it should somehow get +- * overlaid by a dirent the two low bits of the hash version will be +- * zero. Therefore, the hash version mod 4 should never be 0. +- * Sincerely, the paranoia department. +- */ +-struct ext2_dx_root_info { +- uint32_t reserved_zero; +- uint8_t hash_version; /* 0 now, 1 at release */ +- uint8_t info_length; /* 8 */ +- uint8_t indirect_levels; +- uint8_t unused_flags; +-}; +- +-#define EXT2_HASH_LEGACY 0 +-#define EXT2_HASH_HALF_MD4 1 +-#define EXT2_HASH_TEA 2 +- +-#define EXT2_HASH_FLAG_INCOMPAT 0x1 +- +-struct ext2_dx_entry { +- uint32_t hash; +- uint32_t block; +-}; +- +-struct ext2_dx_countlimit { +- uint16_t limit; +- uint16_t count; +-}; +- +- +-/* +- * Macro-instructions used to manage group descriptors +- */ +-#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group) +-#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group) +-#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s)) +-/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */ +-#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8) +-#define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s)) +-#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc)) +- +-/* +- * Constants relative to the data blocks +- */ +-#define EXT2_NDIR_BLOCKS 12 +-#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS +-#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) +-#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) +-#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) +- +-/* +- * Inode flags +- */ +-#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */ +-#define EXT2_UNRM_FL 0x00000002 /* Undelete */ +-#define EXT2_COMPR_FL 0x00000004 /* Compress file */ +-#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */ +-#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ +-#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ +-#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ +-#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */ +-/* Reserved for compression usage... */ +-#define EXT2_DIRTY_FL 0x00000100 +-#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */ +-#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */ +-#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */ +-/* End compression flags --- maybe not all used */ +-#define EXT2_BTREE_FL 0x00001000 /* btree format dir */ +-#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */ +-#define EXT2_IMAGIC_FL 0x00002000 +-#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ +-#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */ +-#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */ +-#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ +-#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */ +-#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ +- +-#define EXT2_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */ +-#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */ +- +-/* +- * ioctl commands +- */ +-#define EXT2_IOC_GETFLAGS _IOR('f', 1, long) +-#define EXT2_IOC_SETFLAGS _IOW('f', 2, long) +-#define EXT2_IOC_GETVERSION _IOR('v', 1, long) +-#define EXT2_IOC_SETVERSION _IOW('v', 2, long) +- +-/* +- * Structure of an inode on the disk +- */ +-struct ext2_inode { +- uint16_t i_mode; /* File mode */ +- uint16_t i_uid; /* Low 16 bits of Owner Uid */ +- uint32_t i_size; /* Size in bytes */ +- uint32_t i_atime; /* Access time */ +- uint32_t i_ctime; /* Creation time */ +- uint32_t i_mtime; /* Modification time */ +- uint32_t i_dtime; /* Deletion Time */ +- uint16_t i_gid; /* Low 16 bits of Group Id */ +- uint16_t i_links_count; /* Links count */ +- uint32_t i_blocks; /* Blocks count */ +- uint32_t i_flags; /* File flags */ +- union { +- struct { +- uint32_t l_i_reserved1; +- } linux1; +- struct { +- uint32_t h_i_translator; +- } hurd1; +- struct { +- uint32_t m_i_reserved1; +- } masix1; +- } osd1; /* OS dependent 1 */ +- uint32_t i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ +- uint32_t i_generation; /* File version (for NFS) */ +- uint32_t i_file_acl; /* File ACL */ +- uint32_t i_dir_acl; /* Directory ACL */ +- uint32_t i_faddr; /* Fragment address */ +- union { +- struct { +- uint8_t l_i_frag; /* Fragment number */ +- uint8_t l_i_fsize; /* Fragment size */ +- uint16_t i_pad1; +- uint16_t l_i_uid_high; /* these 2 fields */ +- uint16_t l_i_gid_high; /* were reserved2[0] */ +- uint32_t l_i_reserved2; +- } linux2; +- struct { +- uint8_t h_i_frag; /* Fragment number */ +- uint8_t h_i_fsize; /* Fragment size */ +- uint16_t h_i_mode_high; +- uint16_t h_i_uid_high; +- uint16_t h_i_gid_high; +- uint32_t h_i_author; +- } hurd2; +- struct { +- uint8_t m_i_frag; /* Fragment number */ +- uint8_t m_i_fsize; /* Fragment size */ +- uint16_t m_pad1; +- uint32_t m_i_reserved2[2]; +- } masix2; +- } osd2; /* OS dependent 2 */ +-}; +- +-/* +- * Permanent part of an large inode on the disk +- */ +-struct ext2_inode_large { +- uint16_t i_mode; /* File mode */ +- uint16_t i_uid; /* Low 16 bits of Owner Uid */ +- uint32_t i_size; /* Size in bytes */ +- uint32_t i_atime; /* Access time */ +- uint32_t i_ctime; /* Creation time */ +- uint32_t i_mtime; /* Modification time */ +- uint32_t i_dtime; /* Deletion Time */ +- uint16_t i_gid; /* Low 16 bits of Group Id */ +- uint16_t i_links_count; /* Links count */ +- uint32_t i_blocks; /* Blocks count */ +- uint32_t i_flags; /* File flags */ +- union { +- struct { +- uint32_t l_i_reserved1; +- } linux1; +- struct { +- uint32_t h_i_translator; +- } hurd1; +- struct { +- uint32_t m_i_reserved1; +- } masix1; +- } osd1; /* OS dependent 1 */ +- uint32_t i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ +- uint32_t i_generation; /* File version (for NFS) */ +- uint32_t i_file_acl; /* File ACL */ +- uint32_t i_dir_acl; /* Directory ACL */ +- uint32_t i_faddr; /* Fragment address */ +- union { +- struct { +- uint8_t l_i_frag; /* Fragment number */ +- uint8_t l_i_fsize; /* Fragment size */ +- uint16_t i_pad1; +- uint16_t l_i_uid_high; /* these 2 fields */ +- uint16_t l_i_gid_high; /* were reserved2[0] */ +- uint32_t l_i_reserved2; +- } linux2; +- struct { +- uint8_t h_i_frag; /* Fragment number */ +- uint8_t h_i_fsize; /* Fragment size */ +- uint16_t h_i_mode_high; +- uint16_t h_i_uid_high; +- uint16_t h_i_gid_high; +- uint32_t h_i_author; +- } hurd2; +- struct { +- uint8_t m_i_frag; /* Fragment number */ +- uint8_t m_i_fsize; /* Fragment size */ +- uint16_t m_pad1; +- uint32_t m_i_reserved2[2]; +- } masix2; +- } osd2; /* OS dependent 2 */ +- uint16_t i_extra_isize; +- uint16_t i_pad1; +-}; +- +-#define i_size_high i_dir_acl +- +-/* +- * File system states +- */ +-#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */ +-#define EXT2_ERROR_FS 0x0002 /* Errors detected */ +- +-/* +- * Mount flags +- */ +-#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */ +-#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */ +-#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */ +-#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */ +-#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ +-#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ +-#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ +-#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ +- +-#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt +-#define set_opt(o, opt) o |= EXT2_MOUNT_##opt +-#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \ +- EXT2_MOUNT_##opt) +-/* +- * Maximal mount counts between two filesystem checks +- */ +-#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */ +-#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */ +- +-/* +- * Behaviour when detecting errors +- */ +-#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */ +-#define EXT2_ERRORS_RO 2 /* Remount fs read-only */ +-#define EXT2_ERRORS_PANIC 3 /* Panic */ +-#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE +- +-/* +- * Structure of the super block +- */ +-struct ext2_super_block { +- uint32_t s_inodes_count; /* Inodes count */ +- uint32_t s_blocks_count; /* Blocks count */ +- uint32_t s_r_blocks_count; /* Reserved blocks count */ +- uint32_t s_free_blocks_count; /* Free blocks count */ +- uint32_t s_free_inodes_count; /* Free inodes count */ +- uint32_t s_first_data_block; /* First Data Block */ +- uint32_t s_log_block_size; /* Block size */ +- int32_t s_log_frag_size; /* Fragment size */ +- uint32_t s_blocks_per_group; /* # Blocks per group */ +- uint32_t s_frags_per_group; /* # Fragments per group */ +- uint32_t s_inodes_per_group; /* # Inodes per group */ +- uint32_t s_mtime; /* Mount time */ +- uint32_t s_wtime; /* Write time */ +- uint16_t s_mnt_count; /* Mount count */ +- int16_t s_max_mnt_count; /* Maximal mount count */ +- uint16_t s_magic; /* Magic signature */ +- uint16_t s_state; /* File system state */ +- uint16_t s_errors; /* Behaviour when detecting errors */ +- uint16_t s_minor_rev_level; /* minor revision level */ +- uint32_t s_lastcheck; /* time of last check */ +- uint32_t s_checkinterval; /* max. time between checks */ +- uint32_t s_creator_os; /* OS */ +- uint32_t s_rev_level; /* Revision level */ +- uint16_t s_def_resuid; /* Default uid for reserved blocks */ +- uint16_t s_def_resgid; /* Default gid for reserved blocks */ +- /* +- * These fields are for EXT2_DYNAMIC_REV superblocks only. +- * +- * Note: the difference between the compatible feature set and +- * the incompatible feature set is that if there is a bit set +- * in the incompatible feature set that the kernel doesn't +- * know about, it should refuse to mount the filesystem. +- * +- * e2fsck's requirements are more strict; if it doesn't know +- * about a feature in either the compatible or incompatible +- * feature set, it must abort and not try to meddle with +- * things it doesn't understand... +- */ +- uint32_t s_first_ino; /* First non-reserved inode */ +- uint16_t s_inode_size; /* size of inode structure */ +- uint16_t s_block_group_nr; /* block group # of this superblock */ +- uint32_t s_feature_compat; /* compatible feature set */ +- uint32_t s_feature_incompat; /* incompatible feature set */ +- uint32_t s_feature_ro_compat; /* readonly-compatible feature set */ +- uint8_t s_uuid[16]; /* 128-bit uuid for volume */ +- char s_volume_name[16]; /* volume name */ +- char s_last_mounted[64]; /* directory where last mounted */ +- uint32_t s_algorithm_usage_bitmap; /* For compression */ +- /* +- * Performance hints. Directory preallocation should only +- * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on. +- */ +- uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ +- uint8_t s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ +- uint16_t s_reserved_gdt_blocks; /* Per group table for online growth */ +- /* +- * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set. +- */ +- uint8_t s_journal_uuid[16]; /* uuid of journal superblock */ +- uint32_t s_journal_inum; /* inode number of journal file */ +- uint32_t s_journal_dev; /* device number of journal file */ +- uint32_t s_last_orphan; /* start of list of inodes to delete */ +- uint32_t s_hash_seed[4]; /* HTREE hash seed */ +- uint8_t s_def_hash_version; /* Default hash version to use */ +- uint8_t s_jnl_backup_type; /* Default type of journal backup */ +- uint16_t s_reserved_word_pad; +- uint32_t s_default_mount_opts; +- uint32_t s_first_meta_bg; /* First metablock group */ +- uint32_t s_mkfs_time; /* When the filesystem was created */ +- uint32_t s_jnl_blocks[17]; /* Backup of the journal inode */ +- uint32_t s_reserved[172]; /* Padding to the end of the block */ +-}; +- +-/* +- * Codes for operating systems +- */ +-#define EXT2_OS_LINUX 0 +-#define EXT2_OS_HURD 1 +-#define EXT2_OS_MASIX 2 +-#define EXT2_OS_FREEBSD 3 +-#define EXT2_OS_LITES 4 +- +-/* +- * Revision levels +- */ +-#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ +-#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ +- +-#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV +-#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV +- +-#define EXT2_GOOD_OLD_INODE_SIZE 128 +- +-/* +- * Journal inode backup types +- */ +-#define EXT3_JNL_BACKUP_BLOCKS 1 +- +-/* +- * Feature set definitions +- */ +- +-#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \ +- ( EXT2_SB(sb)->s_feature_compat & (mask) ) +-#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \ +- ( EXT2_SB(sb)->s_feature_ro_compat & (mask) ) +-#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ +- ( EXT2_SB(sb)->s_feature_incompat & (mask) ) +- +-#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 +-#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002 +-#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 +-#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008 +-#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010 +-#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020 +- +-#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 +-#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 +-/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */ +- +-#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 +-#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +-#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ +-#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ +-#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 +-#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 +- +- +-#define EXT2_FEATURE_COMPAT_SUPP 0 +-#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE) +-#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ +- EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ +- EXT2_FEATURE_RO_COMPAT_BTREE_DIR) +- +-/* +- * Default values for user and/or group using reserved blocks +- */ +-#define EXT2_DEF_RESUID 0 +-#define EXT2_DEF_RESGID 0 +- +-/* +- * Default mount options +- */ +-#define EXT2_DEFM_DEBUG 0x0001 +-#define EXT2_DEFM_BSDGROUPS 0x0002 +-#define EXT2_DEFM_XATTR_USER 0x0004 +-#define EXT2_DEFM_ACL 0x0008 +-#define EXT2_DEFM_UID16 0x0010 +-#define EXT3_DEFM_JMODE 0x0060 +-#define EXT3_DEFM_JMODE_DATA 0x0020 +-#define EXT3_DEFM_JMODE_ORDERED 0x0040 +-#define EXT3_DEFM_JMODE_WBACK 0x0060 +- +-/* +- * Structure of a directory entry +- */ +-#define EXT2_NAME_LEN 255 +- +-struct ext2_dir_entry { +- uint32_t inode; /* Inode number */ +- uint16_t rec_len; /* Directory entry length */ +- uint16_t name_len; /* Name length */ +- char name[EXT2_NAME_LEN]; /* File name */ +-}; +- +-/* +- * The new version of the directory entry. Since EXT2 structures are +- * stored in intel byte order, and the name_len field could never be +- * bigger than 255 chars, it's safe to reclaim the extra byte for the +- * file_type field. +- */ +-struct ext2_dir_entry_2 { +- uint32_t inode; /* Inode number */ +- uint16_t rec_len; /* Directory entry length */ +- uint8_t name_len; /* Name length */ +- uint8_t file_type; +- char name[EXT2_NAME_LEN]; /* File name */ +-}; +- +-/* +- * Ext2 directory file types. Only the low 3 bits are used. The +- * other bits are reserved for now. +- */ +-#define EXT2_FT_UNKNOWN 0 +-#define EXT2_FT_REG_FILE 1 +-#define EXT2_FT_DIR 2 +-#define EXT2_FT_CHRDEV 3 +-#define EXT2_FT_BLKDEV 4 +-#define EXT2_FT_FIFO 5 +-#define EXT2_FT_SOCK 6 +-#define EXT2_FT_SYMLINK 7 +- +-#define EXT2_FT_MAX 8 +- +-/* +- * EXT2_DIR_PAD defines the directory entries boundaries +- * +- * NOTE: It must be a multiple of 4 +- */ +-#define EXT2_DIR_PAD 4 +-#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) +-#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ +- ~EXT2_DIR_ROUND) +- +-#endif +--- a/e2fsprogs/e2fs_lib.h ++++ b/e2fsprogs/e2fs_lib.h +@@ -7,7 +7,7 @@ + */ + + /* Constants and structures */ +-#include "e2fs_defs.h" ++#include "bb_e2fs_defs.h" + + PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN + +--- a/e2fsprogs/old_e2fsprogs/e2fsck.c ++++ b/e2fsprogs/old_e2fsprogs/e2fsck.c +@@ -11577,7 +11577,7 @@ static void check_resize_inode(e2fsck_t + * s_reserved_gdt_blocks must be zero. + */ + if (!(fs->super->s_feature_compat & +- EXT2_FEATURE_COMPAT_RESIZE_INODE)) { ++ EXT2_FEATURE_COMPAT_RESIZE_INO)) { + if (fs->super->s_reserved_gdt_blocks) { + pctx.num = fs->super->s_reserved_gdt_blocks; + if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS, +@@ -11593,7 +11593,7 @@ static void check_resize_inode(e2fsck_t + retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode); + if (retval) { + if (fs->super->s_feature_compat & +- EXT2_FEATURE_COMPAT_RESIZE_INODE) ++ EXT2_FEATURE_COMPAT_RESIZE_INO) + ctx->flags |= E2F_FLAG_RESIZE_INODE; + return; + } +@@ -11603,7 +11603,7 @@ static void check_resize_inode(e2fsck_t + * the resize inode is cleared; then we're done. + */ + if (!(fs->super->s_feature_compat & +- EXT2_FEATURE_COMPAT_RESIZE_INODE)) { ++ EXT2_FEATURE_COMPAT_RESIZE_INO)) { + for (i=0; i < EXT2_N_BLOCKS; i++) { + if (inode.i_block[i]) + break; +--- a/e2fsprogs/old_e2fsprogs/e2p/feature.c ++++ b/e2fsprogs/old_e2fsprogs/e2p/feature.c +@@ -34,7 +34,7 @@ static const struct feature feature_list + "ext_attr" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX, + "dir_index" }, +- { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INODE, ++ { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INO, + "resize_inode" }, + { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER, + "sparse_super" }, +--- a/e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h ++++ b/e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h +@@ -475,7 +475,7 @@ struct ext2_super_block { + #define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002 + #define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 + #define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008 +-#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010 ++#define EXT2_FEATURE_COMPAT_RESIZE_INO 0x0010 + #define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020 + + #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 +--- a/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h ++++ b/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h +@@ -383,7 +383,7 @@ typedef struct ext2_icount *ext2_icount_ + #define EXT2_LIB_FEATURE_COMPAT_SUPP (EXT2_FEATURE_COMPAT_DIR_PREALLOC|\ + EXT2_FEATURE_COMPAT_IMAGIC_INODES|\ + EXT3_FEATURE_COMPAT_HAS_JOURNAL|\ +- EXT2_FEATURE_COMPAT_RESIZE_INODE|\ ++ EXT2_FEATURE_COMPAT_RESIZE_INO|\ + EXT2_FEATURE_COMPAT_DIR_INDEX|\ + EXT2_FEATURE_COMPAT_EXT_ATTR) + +--- a/e2fsprogs/old_e2fsprogs/ext2fs/initialize.c ++++ b/e2fsprogs/old_e2fsprogs/ext2fs/initialize.c +@@ -284,7 +284,7 @@ retry: + /* + * check the number of reserved group descriptor table blocks + */ +- if (super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE) ++ if (super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INO) + rsv_gdt = calc_reserved_gdt_blocks(fs); + else + rsv_gdt = 0; +--- a/e2fsprogs/old_e2fsprogs/mke2fs.c ++++ b/e2fsprogs/old_e2fsprogs/mke2fs.c +@@ -757,7 +757,7 @@ static void parse_extended_opts(struct e + + if (rsv_gdb > 0) { + sb_param->s_feature_compat |= +- EXT2_FEATURE_COMPAT_RESIZE_INODE; ++ EXT2_FEATURE_COMPAT_RESIZE_INO; + + sb_param->s_reserved_gdt_blocks = rsv_gdb; + } +@@ -778,7 +778,7 @@ static void parse_extended_opts(struct e + + static __u32 ok_features[3] = { + EXT3_FEATURE_COMPAT_HAS_JOURNAL | +- EXT2_FEATURE_COMPAT_RESIZE_INODE | ++ EXT2_FEATURE_COMPAT_RESIZE_INO | + EXT2_FEATURE_COMPAT_DIR_INDEX, /* Compat */ + EXT2_FEATURE_INCOMPAT_FILETYPE| /* Incompat */ + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV| +@@ -1123,7 +1123,7 @@ static int PRS(int argc, char **argv) + /* Since sparse_super is the default, we would only have a problem + * here if it was explicitly disabled. + */ +- if ((param.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE) && ++ if ((param.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INO) && + !(param.s_feature_ro_compat&EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) { + bb_error_msg_and_die("reserved online resize blocks not supported " + "on non-sparse filesystem"); +@@ -1312,7 +1312,7 @@ int mke2fs_main (int argc, char **argv) + reserve_inodes(fs); + create_bad_block_inode(fs, bb_list); + if (fs->super->s_feature_compat & +- EXT2_FEATURE_COMPAT_RESIZE_INODE) { ++ EXT2_FEATURE_COMPAT_RESIZE_INO) { + retval = ext2fs_create_resize_inode(fs); + mke2fs_error_msg_and_die(retval, "reserve blocks for online resize"); + } +--- a/e2fsprogs/tune2fs.c ++++ b/e2fsprogs/tune2fs.c +@@ -8,7 +8,7 @@ + */ + #include "libbb.h" + #include <linux/fs.h> +-#include <linux/ext2_fs.h> ++#include "bb_e2fs_defs.h" + + // storage helpers + char BUG_wrong_field_size(void); +--- /dev/null ++++ b/include/bb_e2fs_defs.h +@@ -0,0 +1,602 @@ ++/* vi: set sw=4 ts=4: */ ++/* ++ * linux/include/linux/ext2_fs.h ++ * ++ * Copyright (C) 1992, 1993, 1994, 1995 ++ * Remy Card (card@masi.ibp.fr) ++ * Laboratoire MASI - Institut Blaise Pascal ++ * Universite Pierre et Marie Curie (Paris VI) ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ */ ++ ++#ifndef LINUX_EXT2_FS_H ++#define LINUX_EXT2_FS_H 1 ++ ++/* ++ * Special inode numbers ++ */ ++#define EXT2_BAD_INO 1 /* Bad blocks inode */ ++#define EXT2_ROOT_INO 2 /* Root inode */ ++#define EXT2_ACL_IDX_INO 3 /* ACL inode */ ++#define EXT2_ACL_DATA_INO 4 /* ACL inode */ ++#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ ++#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ ++#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */ ++#define EXT2_JOURNAL_INO 8 /* Journal inode */ ++ ++/* First non-reserved inode for old ext2 filesystems */ ++#define EXT2_GOOD_OLD_FIRST_INO 11 ++ ++/* ++ * The second extended file system magic number ++ */ ++#define EXT2_SUPER_MAGIC 0xEF53 ++ ++/* Assume that user mode programs are passing in an ext2fs superblock, not ++ * a kernel struct super_block. This will allow us to call the feature-test ++ * macros from user land. */ ++#define EXT2_SB(sb) (sb) ++ ++/* ++ * Maximal count of links to a file ++ */ ++#define EXT2_LINK_MAX 32000 ++ ++/* ++ * Macro-instructions used to manage several block sizes ++ */ ++#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */ ++#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */ ++#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE) ++#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE) ++#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) ++#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) ++#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ ++ EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size) ++#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ ++ EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino) ++#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(uint32_t)) ++ ++/* ++ * Macro-instructions used to manage fragments ++ */ ++#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE ++#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE ++#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE ++#define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size) ++#define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s)) ++ ++/* ++ * ACL structures ++ */ ++struct ext2_acl_header { /* Header of Access Control Lists */ ++ uint32_t aclh_size; ++ uint32_t aclh_file_count; ++ uint32_t aclh_acle_count; ++ uint32_t aclh_first_acle; ++}; ++ ++struct ext2_acl_entry { /* Access Control List Entry */ ++ uint32_t acle_size; ++ uint16_t acle_perms; /* Access permissions */ ++ uint16_t acle_type; /* Type of entry */ ++ uint16_t acle_tag; /* User or group identity */ ++ uint16_t acle_pad1; ++ uint32_t acle_next; /* Pointer on next entry for the */ ++ /* same inode or on next free entry */ ++}; ++ ++/* ++ * Structure of a blocks group descriptor ++ */ ++struct ext2_group_desc { ++ uint32_t bg_block_bitmap; /* Blocks bitmap block */ ++ uint32_t bg_inode_bitmap; /* Inodes bitmap block */ ++ uint32_t bg_inode_table; /* Inodes table block */ ++ uint16_t bg_free_blocks_count; /* Free blocks count */ ++ uint16_t bg_free_inodes_count; /* Free inodes count */ ++ uint16_t bg_used_dirs_count; /* Directories count */ ++ uint16_t bg_pad; ++ uint32_t bg_reserved[3]; ++}; ++ ++/* ++ * Data structures used by the directory indexing feature ++ * ++ * Note: all of the multibyte integer fields are little endian. ++ */ ++ ++/* ++ * Note: dx_root_info is laid out so that if it should somehow get ++ * overlaid by a dirent the two low bits of the hash version will be ++ * zero. Therefore, the hash version mod 4 should never be 0. ++ * Sincerely, the paranoia department. ++ */ ++struct ext2_dx_root_info { ++ uint32_t reserved_zero; ++ uint8_t hash_version; /* 0 now, 1 at release */ ++ uint8_t info_length; /* 8 */ ++ uint8_t indirect_levels; ++ uint8_t unused_flags; ++}; ++ ++#define EXT2_HASH_LEGACY 0 ++#define EXT2_HASH_HALF_MD4 1 ++#define EXT2_HASH_TEA 2 ++ ++#define EXT2_HASH_FLAG_INCOMPAT 0x1 ++ ++struct ext2_dx_entry { ++ uint32_t hash; ++ uint32_t block; ++}; ++ ++struct ext2_dx_countlimit { ++ uint16_t limit; ++ uint16_t count; ++}; ++ ++ ++/* ++ * Macro-instructions used to manage group descriptors ++ */ ++#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group) ++#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group) ++#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s)) ++/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */ ++#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8) ++#define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s)) ++#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc)) ++ ++/* ++ * Constants relative to the data blocks ++ */ ++#define EXT2_NDIR_BLOCKS 12 ++#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS ++#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) ++#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) ++#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) ++ ++/* ++ * Inode flags ++ */ ++#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */ ++#define EXT2_UNRM_FL 0x00000002 /* Undelete */ ++#define EXT2_COMPR_FL 0x00000004 /* Compress file */ ++#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */ ++#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ ++#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ ++#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ ++#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */ ++/* Reserved for compression usage... */ ++#define EXT2_DIRTY_FL 0x00000100 ++#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */ ++#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */ ++#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */ ++/* End compression flags --- maybe not all used */ ++#define EXT2_BTREE_FL 0x00001000 /* btree format dir */ ++#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */ ++#define EXT2_IMAGIC_FL 0x00002000 ++#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ ++#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */ ++#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */ ++#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ ++#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */ ++#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ ++ ++#define EXT2_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */ ++#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */ ++ ++/* ++ * ioctl commands ++ */ ++#define EXT2_IOC_GETFLAGS _IOR('f', 1, long) ++#define EXT2_IOC_SETFLAGS _IOW('f', 2, long) ++#define EXT2_IOC_GETVERSION _IOR('v', 1, long) ++#define EXT2_IOC_SETVERSION _IOW('v', 2, long) ++ ++/* ++ * Structure of an inode on the disk ++ */ ++struct ext2_inode { ++ uint16_t i_mode; /* File mode */ ++ uint16_t i_uid; /* Low 16 bits of Owner Uid */ ++ uint32_t i_size; /* Size in bytes */ ++ uint32_t i_atime; /* Access time */ ++ uint32_t i_ctime; /* Creation time */ ++ uint32_t i_mtime; /* Modification time */ ++ uint32_t i_dtime; /* Deletion Time */ ++ uint16_t i_gid; /* Low 16 bits of Group Id */ ++ uint16_t i_links_count; /* Links count */ ++ uint32_t i_blocks; /* Blocks count */ ++ uint32_t i_flags; /* File flags */ ++ union { ++ struct { ++ uint32_t l_i_reserved1; ++ } linux1; ++ struct { ++ uint32_t h_i_translator; ++ } hurd1; ++ struct { ++ uint32_t m_i_reserved1; ++ } masix1; ++ } osd1; /* OS dependent 1 */ ++ uint32_t i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ ++ uint32_t i_generation; /* File version (for NFS) */ ++ uint32_t i_file_acl; /* File ACL */ ++ uint32_t i_dir_acl; /* Directory ACL */ ++ uint32_t i_faddr; /* Fragment address */ ++ union { ++ struct { ++ uint8_t l_i_frag; /* Fragment number */ ++ uint8_t l_i_fsize; /* Fragment size */ ++ uint16_t i_pad1; ++ uint16_t l_i_uid_high; /* these 2 fields */ ++ uint16_t l_i_gid_high; /* were reserved2[0] */ ++ uint32_t l_i_reserved2; ++ } linux2; ++ struct { ++ uint8_t h_i_frag; /* Fragment number */ ++ uint8_t h_i_fsize; /* Fragment size */ ++ uint16_t h_i_mode_high; ++ uint16_t h_i_uid_high; ++ uint16_t h_i_gid_high; ++ uint32_t h_i_author; ++ } hurd2; ++ struct { ++ uint8_t m_i_frag; /* Fragment number */ ++ uint8_t m_i_fsize; /* Fragment size */ ++ uint16_t m_pad1; ++ uint32_t m_i_reserved2[2]; ++ } masix2; ++ } osd2; /* OS dependent 2 */ ++}; ++ ++/* ++ * Permanent part of an large inode on the disk ++ */ ++struct ext2_inode_large { ++ uint16_t i_mode; /* File mode */ ++ uint16_t i_uid; /* Low 16 bits of Owner Uid */ ++ uint32_t i_size; /* Size in bytes */ ++ uint32_t i_atime; /* Access time */ ++ uint32_t i_ctime; /* Creation time */ ++ uint32_t i_mtime; /* Modification time */ ++ uint32_t i_dtime; /* Deletion Time */ ++ uint16_t i_gid; /* Low 16 bits of Group Id */ ++ uint16_t i_links_count; /* Links count */ ++ uint32_t i_blocks; /* Blocks count */ ++ uint32_t i_flags; /* File flags */ ++ union { ++ struct { ++ uint32_t l_i_reserved1; ++ } linux1; ++ struct { ++ uint32_t h_i_translator; ++ } hurd1; ++ struct { ++ uint32_t m_i_reserved1; ++ } masix1; ++ } osd1; /* OS dependent 1 */ ++ uint32_t i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ ++ uint32_t i_generation; /* File version (for NFS) */ ++ uint32_t i_file_acl; /* File ACL */ ++ uint32_t i_dir_acl; /* Directory ACL */ ++ uint32_t i_faddr; /* Fragment address */ ++ union { ++ struct { ++ uint8_t l_i_frag; /* Fragment number */ ++ uint8_t l_i_fsize; /* Fragment size */ ++ uint16_t i_pad1; ++ uint16_t l_i_uid_high; /* these 2 fields */ ++ uint16_t l_i_gid_high; /* were reserved2[0] */ ++ uint32_t l_i_reserved2; ++ } linux2; ++ struct { ++ uint8_t h_i_frag; /* Fragment number */ ++ uint8_t h_i_fsize; /* Fragment size */ ++ uint16_t h_i_mode_high; ++ uint16_t h_i_uid_high; ++ uint16_t h_i_gid_high; ++ uint32_t h_i_author; ++ } hurd2; ++ struct { ++ uint8_t m_i_frag; /* Fragment number */ ++ uint8_t m_i_fsize; /* Fragment size */ ++ uint16_t m_pad1; ++ uint32_t m_i_reserved2[2]; ++ } masix2; ++ } osd2; /* OS dependent 2 */ ++ uint16_t i_extra_isize; ++ uint16_t i_pad1; ++}; ++ ++#define i_size_high i_dir_acl ++ ++/* ++ * File system states ++ */ ++#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */ ++#define EXT2_ERROR_FS 0x0002 /* Errors detected */ ++ ++/* ++ * Mount flags ++ */ ++#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */ ++#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */ ++#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */ ++#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */ ++#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ ++#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ ++#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ ++#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ ++ ++#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt ++#define set_opt(o, opt) o |= EXT2_MOUNT_##opt ++#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \ ++ EXT2_MOUNT_##opt) ++/* ++ * Maximal mount counts between two filesystem checks ++ */ ++#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */ ++#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */ ++ ++/* ++ * Behaviour when detecting errors ++ */ ++#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */ ++#define EXT2_ERRORS_RO 2 /* Remount fs read-only */ ++#define EXT2_ERRORS_PANIC 3 /* Panic */ ++#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE ++ ++/* ++ * Structure of the super block ++ */ ++struct ext2_super_block { ++ uint32_t s_inodes_count; /* Inodes count */ ++ uint32_t s_blocks_count; /* Blocks count */ ++ uint32_t s_r_blocks_count; /* Reserved blocks count */ ++ uint32_t s_free_blocks_count; /* Free blocks count */ ++ uint32_t s_free_inodes_count; /* Free inodes count */ ++ uint32_t s_first_data_block; /* First Data Block */ ++ uint32_t s_log_block_size; /* Block size */ ++ int32_t s_log_frag_size; /* Fragment size */ ++ uint32_t s_blocks_per_group; /* # Blocks per group */ ++ uint32_t s_frags_per_group; /* # Fragments per group */ ++ uint32_t s_inodes_per_group; /* # Inodes per group */ ++ uint32_t s_mtime; /* Mount time */ ++ uint32_t s_wtime; /* Write time */ ++ uint16_t s_mnt_count; /* Mount count */ ++ int16_t s_max_mnt_count; /* Maximal mount count */ ++ uint16_t s_magic; /* Magic signature */ ++ uint16_t s_state; /* File system state */ ++ uint16_t s_errors; /* Behaviour when detecting errors */ ++ uint16_t s_minor_rev_level; /* minor revision level */ ++ uint32_t s_lastcheck; /* time of last check */ ++ uint32_t s_checkinterval; /* max. time between checks */ ++ uint32_t s_creator_os; /* OS */ ++ uint32_t s_rev_level; /* Revision level */ ++ uint16_t s_def_resuid; /* Default uid for reserved blocks */ ++ uint16_t s_def_resgid; /* Default gid for reserved blocks */ ++ /* ++ * These fields are for EXT2_DYNAMIC_REV superblocks only. ++ * ++ * Note: the difference between the compatible feature set and ++ * the incompatible feature set is that if there is a bit set ++ * in the incompatible feature set that the kernel doesn't ++ * know about, it should refuse to mount the filesystem. ++ * ++ * e2fsck's requirements are more strict; if it doesn't know ++ * about a feature in either the compatible or incompatible ++ * feature set, it must abort and not try to meddle with ++ * things it doesn't understand... ++ */ ++ uint32_t s_first_ino; /* First non-reserved inode */ ++ uint16_t s_inode_size; /* size of inode structure */ ++ uint16_t s_block_group_nr; /* block group # of this superblock */ ++ uint32_t s_feature_compat; /* compatible feature set */ ++ uint32_t s_feature_incompat; /* incompatible feature set */ ++ uint32_t s_feature_ro_compat; /* readonly-compatible feature set */ ++ uint8_t s_uuid[16]; /* 128-bit uuid for volume */ ++ char s_volume_name[16]; /* volume name */ ++ char s_last_mounted[64]; /* directory where last mounted */ ++ uint32_t s_algorithm_usage_bitmap; /* For compression */ ++ /* ++ * Performance hints. Directory preallocation should only ++ * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on. ++ */ ++ uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ ++ uint8_t s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ ++ uint16_t s_reserved_gdt_blocks; /* Per group table for online growth */ ++ /* ++ * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set. ++ */ ++/*D0*/ uint8_t s_journal_uuid[16]; /* uuid of journal superblock */ ++/*E0*/ uint32_t s_journal_inum; /* inode number of journal file */ ++ uint32_t s_journal_dev; /* device number of journal file */ ++ uint32_t s_last_orphan; /* start of list of inodes to delete */ ++ uint32_t s_hash_seed[4]; /* HTREE hash seed */ ++ uint8_t s_def_hash_version; /* Default hash version to use */ ++ uint8_t s_jnl_backup_type; /* Default type of journal backup */ ++ uint16_t s_reserved_word_pad; ++/*100*/ uint32_t s_default_mount_opts; ++ uint32_t s_first_meta_bg; /* First metablock group */ ++ /* ext3 additions */ ++ uint32_t s_mkfs_time; /* When the filesystem was created */ ++ uint32_t s_jnl_blocks[17]; /* Backup of the journal inode */ ++ /* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */ ++/*150*/ uint32_t s_blocks_count_hi; /* Blocks count */ ++ uint32_t s_r_blocks_count_hi; /* Reserved blocks count */ ++ uint32_t s_free_blocks_count_hi; /* Free blocks count */ ++ uint16_t s_min_extra_isize; /* All inodes have at least # bytes */ ++ uint16_t s_want_extra_isize; /* New inodes should reserve # bytes */ ++ uint32_t s_flags; /* Miscellaneous flags */ ++ uint16_t s_raid_stride; /* RAID stride */ ++ uint16_t s_mmp_interval; /* # seconds to wait in MMP checking */ ++ uint64_t s_mmp_block; /* Block for multi-mount protection */ ++ uint32_t s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ ++ uint8_t s_log_groups_per_flex; /* FLEX_BG group size */ ++ uint8_t s_reserved_char_pad2; ++ uint16_t s_reserved_pad; ++ uint32_t s_reserved[162]; /* Padding to the end of the block */ ++}; ++struct BUG_ext2_super_block { ++ char bug[sizeof(struct ext2_super_block) == 1024 ? 1 : -1]; ++}; ++ ++/* ++ * Codes for operating systems ++ */ ++#define EXT2_OS_LINUX 0 ++#define EXT2_OS_HURD 1 ++#define EXT2_OS_MASIX 2 ++#define EXT2_OS_FREEBSD 3 ++#define EXT2_OS_LITES 4 ++ ++/* ++ * Revision levels ++ */ ++#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ ++#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ ++ ++#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV ++#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV ++ ++#define EXT2_GOOD_OLD_INODE_SIZE 128 ++ ++/* ++ * Journal inode backup types ++ */ ++#define EXT3_JNL_BACKUP_BLOCKS 1 ++ ++/* ++ * Feature set definitions ++ */ ++ ++#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \ ++ ( EXT2_SB(sb)->s_feature_compat & (mask) ) ++#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \ ++ ( EXT2_SB(sb)->s_feature_ro_compat & (mask) ) ++#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ ++ ( EXT2_SB(sb)->s_feature_incompat & (mask) ) ++ ++/* for s_feature_compat */ ++#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 ++#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002 ++#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 ++#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008 ++#define EXT2_FEATURE_COMPAT_RESIZE_INO 0x0010 ++#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020 ++ ++/* for s_feature_ro_compat */ ++#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 ++#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 ++#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 /* not used */ ++#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008 ++#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 ++#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 ++#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 ++ ++/* for s_feature_incompat */ ++#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 ++#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 ++#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 ++#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 ++#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 ++#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 ++#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 ++#define EXT4_FEATURE_INCOMPAT_MMP 0x0100 ++#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 ++ ++ ++#define EXT2_FEATURE_COMPAT_SUPP 0 ++#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ ++ EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ ++ EXT2_FEATURE_RO_COMPAT_BTREE_DIR) ++#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ ++ EXT2_FEATURE_INCOMPAT_META_BG) ++#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED (~EXT2_FEATURE_INCOMPAT_SUPP) ++#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED (~EXT2_FEATURE_RO_COMPAT_SUPP) ++ ++#define EXT3_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ ++ EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ ++ EXT2_FEATURE_RO_COMPAT_BTREE_DIR) ++#define EXT3_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ ++ EXT3_FEATURE_INCOMPAT_RECOVER| \ ++ EXT2_FEATURE_INCOMPAT_META_BG) ++#define EXT3_FEATURE_INCOMPAT_UNSUPPORTED (~EXT3_FEATURE_INCOMPAT_SUPP) ++#define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED (~EXT3_FEATURE_RO_COMPAT_SUPP) ++ ++ ++/* ++ * Default values for user and/or group using reserved blocks ++ */ ++#define EXT2_DEF_RESUID 0 ++#define EXT2_DEF_RESGID 0 ++ ++/* ++ * Default mount options ++ */ ++#define EXT2_DEFM_DEBUG 0x0001 ++#define EXT2_DEFM_BSDGROUPS 0x0002 ++#define EXT2_DEFM_XATTR_USER 0x0004 ++#define EXT2_DEFM_ACL 0x0008 ++#define EXT2_DEFM_UID16 0x0010 ++#define EXT3_DEFM_JMODE 0x0060 ++#define EXT3_DEFM_JMODE_DATA 0x0020 ++#define EXT3_DEFM_JMODE_ORDERED 0x0040 ++#define EXT3_DEFM_JMODE_WBACK 0x0060 ++ ++/* ++ * Structure of a directory entry ++ */ ++#define EXT2_NAME_LEN 255 ++ ++struct ext2_dir_entry { ++ uint32_t inode; /* Inode number */ ++ uint16_t rec_len; /* Directory entry length */ ++ uint16_t name_len; /* Name length */ ++ char name[EXT2_NAME_LEN]; /* File name */ ++}; ++ ++/* ++ * The new version of the directory entry. Since EXT2 structures are ++ * stored in intel byte order, and the name_len field could never be ++ * bigger than 255 chars, it's safe to reclaim the extra byte for the ++ * file_type field. ++ */ ++struct ext2_dir_entry_2 { ++ uint32_t inode; /* Inode number */ ++ uint16_t rec_len; /* Directory entry length */ ++ uint8_t name_len; /* Name length */ ++ uint8_t file_type; ++ char name[EXT2_NAME_LEN]; /* File name */ ++}; ++ ++/* ++ * Ext2 directory file types. Only the low 3 bits are used. The ++ * other bits are reserved for now. ++ */ ++#define EXT2_FT_UNKNOWN 0 ++#define EXT2_FT_REG_FILE 1 ++#define EXT2_FT_DIR 2 ++#define EXT2_FT_CHRDEV 3 ++#define EXT2_FT_BLKDEV 4 ++#define EXT2_FT_FIFO 5 ++#define EXT2_FT_SOCK 6 ++#define EXT2_FT_SYMLINK 7 ++ ++#define EXT2_FT_MAX 8 ++ ++/* ++ * EXT2_DIR_PAD defines the directory entries boundaries ++ * ++ * NOTE: It must be a multiple of 4 ++ */ ++#define EXT2_DIR_PAD 4 ++#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) ++#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ ++ ~EXT2_DIR_ROUND) ++ ++#endif +--- a/testsuite/mount.tests ++++ b/testsuite/mount.tests +@@ -36,7 +36,8 @@ testing "mount -o remount,mand" \ + "mount -o loop mount.image1m $testdir "\ + "&& grep -Fc $testdir </proc/mounts "\ + "&& mount -o remount,mand $testdir "\ +-"&& grep -F $testdir </proc/mounts | grep -c '[, ]mand[, ]'" \ ++"&& grep -F $testdir </proc/mounts | grep -c '[, ]mand[, ]'"\ ++"|| grep -F $testdir </proc/mounts" \ + "1\n""1\n" \ + "" "" + +@@ -83,4 +84,28 @@ b + "" "" + SKIP= + ++ ++testing "mount RO loop" "\ ++exec 2>&1 ++umount -d mount.dir 2>/dev/null ++rmdir mount.dir 2>/dev/null ++mkdir -p mount.dir ++( ++cd mount.dir || { echo 'cd error'; exit 1; } ++mkdir z1 z2 || { echo 'mkdir error'; exit 1; } ++mount -t tmpfs tmpfs z1 || { echo 'mount tmpfs error'; exit 1; } ++dd if=/dev/zero of=z1/e2img count=10 bs=1M 2>/dev/null || { echo 'dd error'; exit 1; } ++mke2fs -F z1/e2img 2>/dev/null >&2 || { echo 'mke2fs error'; exit 1; } ++mount -r -o loop -t ext2 z1/e2img z2 || { echo 'mount -r -o loop error'; exit 1; } ++mount -o remount,ro z1 || { echo 'mount -o remount,ro error'; exit 1; } ++) ++umount -d mount.dir/z2 ++##losetup -d /dev/loop* ++umount -d mount.dir/z1 ++rm -rf mount.dir ++echo DONE ++" \ ++"DONE\n" "" "" ++ ++ + exit $FAILCOUNT +--- a/util-linux/mkfs_ext2.c ++++ b/util-linux/mkfs_ext2.c +@@ -48,16 +48,11 @@ + + #include "libbb.h" + #include <linux/fs.h> +-#include <linux/ext2_fs.h> ++#include "bb_e2fs_defs.h" + + #define ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT 0 + #define ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX 1 + +-// from e2fsprogs +-#define s_reserved_gdt_blocks s_padding1 +-#define s_mkfs_time s_reserved[0] +-#define s_flags s_reserved[22] +- + #define EXT2_HASH_HALF_MD4 1 + #define EXT2_FLAGS_SIGNED_HASH 0x0001 + #define EXT2_FLAGS_UNSIGNED_HASH 0x0002 +@@ -482,8 +477,10 @@ int mkfs_ext2_main(int argc UNUSED_PARAM + STORE_LE(sb->s_magic, EXT2_SUPER_MAGIC); + STORE_LE(sb->s_inode_size, inodesize); + // set "Required extra isize" and "Desired extra isize" fields to 28 +- if (inodesize != sizeof(*inode)) +- STORE_LE(sb->s_reserved[21], 0x001C001C); ++ if (inodesize != sizeof(*inode)) { ++ STORE_LE(sb->s_min_extra_isize, 0x001c); ++ STORE_LE(sb->s_want_extra_isize, 0x001c); ++ } + STORE_LE(sb->s_first_ino, EXT2_GOOD_OLD_FIRST_INO); + STORE_LE(sb->s_log_block_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE); + STORE_LE(sb->s_log_frag_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE); +--- a/util-linux/volume_id/ext.c ++++ b/util-linux/volume_id/ext.c +@@ -19,28 +19,8 @@ + */ + + #include "volume_id_internal.h" ++#include "bb_e2fs_defs.h" + +-struct ext2_super_block { +- uint32_t inodes_count; +- uint32_t blocks_count; +- uint32_t r_blocks_count; +- uint32_t free_blocks_count; +- uint32_t free_inodes_count; +- uint32_t first_data_block; +- uint32_t log_block_size; +- uint32_t dummy3[7]; +- uint8_t magic[2]; +- uint16_t state; +- uint32_t dummy5[8]; +- uint32_t feature_compat; +- uint32_t feature_incompat; +- uint32_t feature_ro_compat; +- uint8_t uuid[16]; +- uint8_t volume_name[16]; +-} PACKED; +- +-#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004 +-#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008 + #define EXT_SUPERBLOCK_OFFSET 0x400 + + int FAST_FUNC volume_id_probe_ext(struct volume_id *id /*,uint64_t off*/) +@@ -54,23 +34,27 @@ int FAST_FUNC volume_id_probe_ext(struct + if (es == NULL) + return -1; + +- if (es->magic[0] != 0123 || es->magic[1] != 0357) { ++ if (es->s_magic != cpu_to_le16(EXT2_SUPER_MAGIC)) { + dbg("ext: no magic found"); + return -1; + } + + // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); + // volume_id_set_label_raw(id, es->volume_name, 16); +- volume_id_set_label_string(id, es->volume_name, 16); +- volume_id_set_uuid(id, es->uuid, UUID_DCE); ++ volume_id_set_label_string(id, (void*)es->s_volume_name, 16); ++ volume_id_set_uuid(id, es->s_uuid, UUID_DCE); + dbg("ext: label '%s' uuid '%s'", id->label, id->uuid); + + #if ENABLE_FEATURE_BLKID_TYPE +- if ((le32_to_cpu(es->feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0) ++ if ((es->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_HUGE_FILE | EXT4_FEATURE_RO_COMPAT_DIR_NLINK)) ++ || (es->s_feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_EXTENTS | EXT4_FEATURE_INCOMPAT_64BIT)) ++ ) { ++ id->type = "ext4"; ++ } ++ else if (es->s_feature_compat & cpu_to_le32(EXT3_FEATURE_COMPAT_HAS_JOURNAL)) + id->type = "ext3"; + else + id->type = "ext2"; + #endif +- + return 0; + } diff --git a/package/utils/busybox/patches/110-wget_getopt_fix.patch b/package/utils/busybox/patches/110-wget_getopt_fix.patch new file mode 100644 index 0000000000..1003231462 --- /dev/null +++ b/package/utils/busybox/patches/110-wget_getopt_fix.patch @@ -0,0 +1,11 @@ +--- a/networking/wget.c ++++ b/networking/wget.c +@@ -873,7 +873,7 @@ int wget_main(int argc UNUSED_PARAM, cha + /* Ignored: */ + // "tries\0" Required_argument "t" + /* Ignored (we always use PASV): */ +- "passive-ftp\0" No_argument "\xff" ++ "passive-ftp\0" No_argument "\xfd" + "header\0" Required_argument "\xfe" + "post-data\0" Required_argument "\xfd" + /* Ignored (we don't do ssl) */ diff --git a/package/utils/busybox/patches/140-trylink_bash.patch b/package/utils/busybox/patches/140-trylink_bash.patch new file mode 100644 index 0000000000..f9571fcbc8 --- /dev/null +++ b/package/utils/busybox/patches/140-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/141-gen_build_files_bash.patch b/package/utils/busybox/patches/141-gen_build_files_bash.patch new file mode 100644 index 0000000000..d258fb8bc4 --- /dev/null +++ b/package/utils/busybox/patches/141-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/150-no_static_libgcc.patch b/package/utils/busybox/patches/150-no_static_libgcc.patch new file mode 100644 index 0000000000..fde6fbb869 --- /dev/null +++ b/package/utils/busybox/patches/150-no_static_libgcc.patch @@ -0,0 +1,11 @@ +--- a/Makefile.flags ++++ b/Makefile.flags +@@ -50,7 +50,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,) + + # FIXME: These warnings are at least partially to be concerned about and should diff --git a/package/utils/busybox/patches/200-etc_crontabs.patch b/package/utils/busybox/patches/200-etc_crontabs.patch new file mode 100644 index 0000000000..ebf2990502 --- /dev/null +++ b/package/utils/busybox/patches/200-etc_crontabs.patch @@ -0,0 +1,22 @@ +--- a/miscutils/crond.c ++++ b/miscutils/crond.c +@@ -37,7 +37,7 @@ + + + #define TMPDIR CONFIG_FEATURE_CROND_DIR +-#define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs" ++#define CRONTABS "/etc/crontabs" + #ifndef SENDMAIL + # define SENDMAIL "sendmail" + #endif +--- a/miscutils/crontab.c ++++ b/miscutils/crontab.c +@@ -22,7 +22,7 @@ + + #include "libbb.h" + +-#define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs" ++#define CRONTABS "/etc/crontabs" + #ifndef CRONUPDATE + #define CRONUPDATE "cron.update" + #endif diff --git a/package/utils/busybox/patches/240-udhcpc_retries.patch b/package/utils/busybox/patches/240-udhcpc_retries.patch new file mode 100644 index 0000000000..0e26864e8d --- /dev/null +++ b/package/utils/busybox/patches/240-udhcpc_retries.patch @@ -0,0 +1,20 @@ +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -1319,7 +1319,7 @@ int udhcpc_main(int argc UNUSED_PARAM, c + + switch (state) { + case INIT_SELECTING: +- if (packet_num < discover_retries) { ++ if (!discover_retries || packet_num < discover_retries) { + if (packet_num == 0) + xid = random_xid(); + /* broadcast */ +@@ -1348,7 +1348,7 @@ int udhcpc_main(int argc UNUSED_PARAM, c + packet_num = 0; + continue; + case REQUESTING: +- if (packet_num < discover_retries) { ++ if (!discover_retries || packet_num < discover_retries) { + /* send broadcast select packet */ + send_select(xid, server_addr, requested_ip); + timeout = discover_timeout; diff --git a/package/utils/busybox/patches/241-udhcpc-oversized_packets.patch b/package/utils/busybox/patches/241-udhcpc-oversized_packets.patch new file mode 100644 index 0000000000..471d704a71 --- /dev/null +++ b/package/utils/busybox/patches/241-udhcpc-oversized_packets.patch @@ -0,0 +1,99 @@ +--- a/networking/udhcp/packet.c ++++ b/networking/udhcp/packet.c +@@ -158,6 +158,11 @@ uint16_t FAST_FUNC udhcp_checksum(void * + return ~sum; + } + ++int udhcp_get_payload_len(struct dhcp_packet *dhcp_pkt) ++{ ++ return sizeof(struct dhcp_packet) - DHCP_OPTIONS_BUFSIZE + udhcp_end_option(dhcp_pkt->options) + sizeof(dhcp_pkt->options[0]); ++} ++ + /* Construct a ip/udp header for a packet, send packet */ + int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, + uint32_t source_nip, int source_port, +@@ -166,10 +171,10 @@ int FAST_FUNC udhcp_send_raw_packet(stru + { + struct sockaddr_ll dest_sll; + struct ip_udp_dhcp_packet packet; +- unsigned padding; + int fd; + int result = -1; + const char *msg; ++ int p_len = udhcp_get_payload_len(dhcp_pkt); + + fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); + if (fd < 0) { +@@ -178,8 +183,8 @@ int FAST_FUNC udhcp_send_raw_packet(stru + } + + memset(&dest_sll, 0, sizeof(dest_sll)); +- memset(&packet, 0, offsetof(struct ip_udp_dhcp_packet, data)); +- packet.data = *dhcp_pkt; /* struct copy */ ++ memset(&packet, 0, sizeof(packet)); ++ memcpy(&(packet.data), dhcp_pkt, p_len); + + dest_sll.sll_family = AF_PACKET; + dest_sll.sll_protocol = htons(ETH_P_IP); +@@ -192,36 +197,24 @@ int FAST_FUNC udhcp_send_raw_packet(stru + goto ret_close; + } + +- /* We were sending full-sized DHCP packets (zero padded), +- * but some badly configured servers were seen dropping them. +- * Apparently they drop all DHCP packets >576 *ethernet* octets big, +- * whereas they may only drop packets >576 *IP* octets big +- * (which for typical Ethernet II means 590 octets: 6+6+2 + 576). +- * +- * In order to work with those buggy servers, +- * we truncate packets after end option byte. +- */ +- padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(packet.data.options); +- + packet.ip.protocol = IPPROTO_UDP; + packet.ip.saddr = source_nip; + packet.ip.daddr = dest_nip; + packet.udp.source = htons(source_port); + packet.udp.dest = htons(dest_port); +- /* size, excluding IP header: */ +- packet.udp.len = htons(UDP_DHCP_SIZE - padding); +- /* for UDP checksumming, ip.len is set to UDP packet len */ ++ p_len += sizeof(packet.udp); ++ packet.udp.len = htons(p_len); + packet.ip.tot_len = packet.udp.len; +- packet.udp.check = udhcp_checksum(&packet, IP_UDP_DHCP_SIZE - padding); +- /* but for sending, it is set to IP packet len */ +- packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding); ++ p_len += sizeof(packet.ip); ++ packet.udp.check = udhcp_checksum(&packet, p_len); ++ packet.ip.tot_len = htons(p_len); + packet.ip.ihl = sizeof(packet.ip) >> 2; + packet.ip.version = IPVERSION; + packet.ip.ttl = IPDEFTTL; + packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip)); + + udhcp_dump_packet(dhcp_pkt); +- result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, /*flags:*/ 0, ++ result = sendto(fd, &packet, p_len, /*flags:*/ 0, + (struct sockaddr *) &dest_sll, sizeof(dest_sll)); + msg = "sendto"; + ret_close: +@@ -239,7 +232,6 @@ int FAST_FUNC udhcp_send_kernel_packet(s + uint32_t dest_nip, int dest_port) + { + struct sockaddr_in client; +- unsigned padding; + int fd; + int result = -1; + const char *msg; +@@ -270,9 +262,7 @@ int FAST_FUNC udhcp_send_kernel_packet(s + } + + udhcp_dump_packet(dhcp_pkt); +- +- padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options); +- result = safe_write(fd, dhcp_pkt, DHCP_SIZE - padding); ++ result = safe_write(fd, dhcp_pkt, udhcp_get_payload_len(dhcp_pkt)); + msg = "write"; + ret_close: + close(fd); diff --git a/package/utils/busybox/patches/242-udhcpc_msgs.patch b/package/utils/busybox/patches/242-udhcpc_msgs.patch new file mode 100644 index 0000000000..c1c6096697 --- /dev/null +++ b/package/utils/busybox/patches/242-udhcpc_msgs.patch @@ -0,0 +1,18 @@ +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -602,6 +602,7 @@ static int raw_bcast_from_client_config_ + 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), +@@ -619,6 +620,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/243-udhcpc_changed_ifindex.patch b/package/utils/busybox/patches/243-udhcpc_changed_ifindex.patch new file mode 100644 index 0000000000..cb0df224cc --- /dev/null +++ b/package/utils/busybox/patches/243-udhcpc_changed_ifindex.patch @@ -0,0 +1,15 @@ +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -1267,6 +1267,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/244-udhcpc_add_6rd_option.patch b/package/utils/busybox/patches/244-udhcpc_add_6rd_option.patch new file mode 100644 index 0000000000..2f0eadb160 --- /dev/null +++ b/package/utils/busybox/patches/244-udhcpc_add_6rd_option.patch @@ -0,0 +1,143 @@ +--- a/networking/udhcp/common.c ++++ b/networking/udhcp/common.c +@@ -60,6 +60,8 @@ const struct dhcp_optflag dhcp_optflags[ + { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */ + #endif + { OPTION_STATIC_ROUTES , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ ++ { OPTION_6RD , 0xd4 }, /* DHCP_6RD (RFC) */ ++ { OPTION_6RD , 0x96 }, /* DHCP_6RD (Comcast) */ + { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ + + /* Options below have no match in dhcp_option_strings[], +@@ -127,6 +129,8 @@ const char dhcp_option_strings[] ALIGN1 + "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */ + #endif + "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ ++ "ip6rd" "\0" /* DHCP_6RD (RFC) */ ++ "ip6rd" "\0" /* DHCP_6RD (Comcast) */ + "wpad" "\0" /* DHCP_WPAD */ + ; + +@@ -155,6 +159,7 @@ const uint8_t dhcp_option_lengths[] ALIG + [OPTION_S32] = 4, + /* Just like OPTION_STRING, we use minimum length here */ + [OPTION_STATIC_ROUTES] = 5, ++ [OPTION_6RD] = 22, + }; + + +--- a/networking/udhcp/common.h ++++ b/networking/udhcp/common.h +@@ -91,6 +91,7 @@ enum { + OPTION_S32, + OPTION_BIN, + OPTION_STATIC_ROUTES, ++ OPTION_6RD, + #if ENABLE_FEATURE_UDHCP_RFC3397 + OPTION_DNS_STRING, /* RFC1035 compressed domain name list */ + OPTION_SIP_SERVERS, +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -100,6 +100,7 @@ static const uint8_t len_of_option_as_st + [OPTION_IP ] = sizeof("255.255.255.255 "), + [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2, + [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "), ++ [OPTION_6RD ] = sizeof("32 128 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF 255.255.255.255 "), + [OPTION_STRING ] = 1, + [OPTION_STRING_HOST ] = 1, + #if ENABLE_FEATURE_UDHCP_RFC3397 +@@ -124,6 +125,23 @@ static int sprint_nip(char *dest, const + return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); + } + ++static int sprint_nip6(char *dest, const char *pre, const uint8_t *ip) ++{ ++ int len = 0; ++ int off; ++ uint16_t word; ++ ++ len += sprintf(dest, "%s", pre); ++ ++ for (off = 0; off < 16; off += 2) ++ { ++ move_from_unaligned16(word, &ip[off]); ++ len += sprintf(dest+len, "%s%04X", off ? ":" : "", htons(word)); ++ } ++ ++ return len; ++} ++ + /* really simple implementation, just count the bits */ + static int mton(uint32_t mask) + { +@@ -292,6 +310,70 @@ static NOINLINE char *xmalloc_optname_op + } + + return ret; ++ } ++ case OPTION_6RD: { ++ /* Option binary format: ++ * 0 1 2 3 ++ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | OPTION_6RD | option-length | IPv4MaskLen | 6rdPrefixLen | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | | ++ * | 6rdPrefix | ++ * | (16 octets) | ++ * | | ++ * | | ++ * | | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | 6rdBRIPv4Address(es) | ++ * . . ++ * . . ++ * . . ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * ++ * We convert it to a string "IPv4MaskLen 6rdPrefixLen 6rdPrefix 6rdBRIPv4Address" ++ */ ++ ++ /* Sanity check: ensure that our length is at least 22 bytes, that ++ * IPv4MaskLen is <= 32, 6rdPrefixLen <= 128 and that the sum of ++ * (32 - IPv4MaskLen) + 6rdPrefixLen is less than or equal to 128. ++ * If any of these requirements is not fulfilled, return with empty ++ * value. ++ */ ++ if ((len >= 22) && (*option <= 32) && (*(option+1) <= 128) && ++ (((32 - *option) + *(option+1)) <= 128)) ++ { ++ /* IPv4MaskLen */ ++ dest += sprintf(dest, "%u ", *option++); ++ len--; ++ ++ /* 6rdPrefixLen */ ++ dest += sprintf(dest, "%u ", *option++); ++ len--; ++ ++ /* 6rdPrefix */ ++ dest += sprint_nip6(dest, "", option); ++ option += 16; ++ len -= 16; ++ ++ /* 6rdBRIPv4Addresses */ ++ while (len >= 4) ++ { ++ dest += sprint_nip(dest, " ", option); ++ option += 4; ++ len -= 4; ++ ++ /* the code to determine the option size fails to work with ++ * lengths that are not a multiple of the minimum length, ++ * adding all advertised 6rdBRIPv4Addresses here would ++ * overflow the destination buffer, therefore skip the rest ++ * for now ++ */ ++ break; ++ } ++ } ++ ++ return ret; + } + #if ENABLE_FEATURE_UDHCP_RFC3397 + case OPTION_DNS_STRING: diff --git a/package/utils/busybox/patches/250-ash_export-n.patch b/package/utils/busybox/patches/250-ash_export-n.patch new file mode 100644 index 0000000000..048c236b85 --- /dev/null +++ b/package/utils/busybox/patches/250-ash_export-n.patch @@ -0,0 +1,34 @@ +--- a/shell/ash.c ++++ b/shell/ash.c +@@ -12611,8 +12611,17 @@ exportcmd(int argc UNUSED_PARAM, char ** + const char *p; + char **aptr; + int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT; ++ int mask = ~0; ++ int nopt; ++ while ((nopt = nextopt("np"))) { ++ if (nopt == 'n') { ++ mask = ~flag; ++ } else { /* p */ ++ break; ++ } ++ } + +- if (nextopt("p") != 'p') { ++ if (nopt != 'p') { + aptr = argptr; + name = *aptr; + if (name) { +@@ -12624,10 +12633,12 @@ exportcmd(int argc UNUSED_PARAM, char ** + vp = *findvar(hashvar(name), name); + if (vp) { + vp->flags |= flag; ++ vp->flags &= mask; + continue; + } + } + setvar(name, p, flag); ++ setvar(name, p, flag & mask); + } while ((name = *++aptr) != NULL); + return 0; + } diff --git a/package/utils/busybox/patches/251-ash_fix-redir-substitution.patch b/package/utils/busybox/patches/251-ash_fix-redir-substitution.patch new file mode 100644 index 0000000000..cb2ae94e04 --- /dev/null +++ b/package/utils/busybox/patches/251-ash_fix-redir-substitution.patch @@ -0,0 +1,12 @@ +--- a/shell/ash.c ++++ b/shell/ash.c +@@ -6846,8 +6846,7 @@ evalvar(char *p, int flags, struct strli + patloc = expdest - (char *)stackblock(); + if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype, + startloc, varflags, +-//TODO: | EXP_REDIR too? All other such places do it too +- /* quotes: */ flags & (EXP_FULL | EXP_CASE), ++ /* quotes: */ flags & (EXP_FULL | EXP_CASE | EXP_REDIR), + var_str_list) + ) { + int amount = expdest - ( diff --git a/package/utils/busybox/patches/260-vconfig_proc.patch b/package/utils/busybox/patches/260-vconfig_proc.patch new file mode 100644 index 0000000000..7ac52abbfe --- /dev/null +++ b/package/utils/busybox/patches/260-vconfig_proc.patch @@ -0,0 +1,22 @@ +--- a/networking/vconfig.c ++++ b/networking/vconfig.c +@@ -116,8 +116,6 @@ static const char name_types[] ALIGN1 = + '_', 'N', 'O', '_', 'P', 'A', 'D', 0, + }; + +-static const char conf_file_name[] ALIGN1 = "/proc/net/vlan/config"; +- + int vconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; + int vconfig_main(int argc, char **argv) + { +@@ -129,10 +127,6 @@ int vconfig_main(int argc, char **argv) + bb_show_usage(); + } + +- /* Don't bother closing the filedes. It will be closed on cleanup. */ +- /* Will die if 802.1q is not present */ +- xopen(conf_file_name, O_RDONLY); +- + memset(&ifr, 0, sizeof(ifr)); + + ++argv; diff --git a/package/utils/busybox/patches/300-netmsg.patch b/package/utils/busybox/patches/300-netmsg.patch new file mode 100644 index 0000000000..e8b2513eb3 --- /dev/null +++ b/package/utils/busybox/patches/300-netmsg.patch @@ -0,0 +1,103 @@ +--- a/include/applets.src.h ++++ b/include/applets.src.h +@@ -266,6 +266,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 +@@ -612,6 +612,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/310-passwd_access.patch b/package/utils/busybox/patches/310-passwd_access.patch new file mode 100644 index 0000000000..daa1b99983 --- /dev/null +++ b/package/utils/busybox/patches/310-passwd_access.patch @@ -0,0 +1,41 @@ + + Copyright (C) 2006 OpenWrt.org + +--- a/networking/httpd.c ++++ b/networking/httpd.c +@@ -1700,21 +1700,32 @@ static int check_user_passwd(const char + + if (ENABLE_FEATURE_HTTPD_AUTH_MD5) { + char *md5_passwd; ++ int user_len_p1; + + md5_passwd = strchr(cur->after_colon, ':'); +- if (md5_passwd && md5_passwd[1] == '$' && md5_passwd[2] == '1' ++ user_len_p1 = md5_passwd + 1 - cur->after_colon; ++ if (md5_passwd && !strncmp(md5_passwd + 1, "$p$", 3)) { ++ struct passwd *pwd = NULL; ++ ++ pwd = getpwnam(&md5_passwd[4]); ++ if(!pwd->pw_passwd || !pwd->pw_passwd[0] || pwd->pw_passwd[0] == '!') ++ return 1; ++ ++ md5_passwd = pwd->pw_passwd; ++ goto check_md5_pw; ++ } else if (md5_passwd && md5_passwd[1] == '$' && md5_passwd[2] == '1' + && md5_passwd[3] == '$' && md5_passwd[4] + ) { + char *encrypted; +- int r, user_len_p1; ++ int r; + + md5_passwd++; +- user_len_p1 = md5_passwd - cur->after_colon; + /* comparing "user:" */ + if (strncmp(cur->after_colon, user_and_passwd, user_len_p1) != 0) { + continue; + } + ++check_md5_pw: + encrypted = pw_encrypt( + user_and_passwd + user_len_p1 /* cleartext pwd from user */, + md5_passwd /*salt */, 1 /* cleanup */); diff --git a/package/utils/busybox/patches/340-lock_util.patch b/package/utils/busybox/patches/340-lock_util.patch new file mode 100644 index 0000000000..eb346421a4 --- /dev/null +++ b/package/utils/busybox/patches/340-lock_util.patch @@ -0,0 +1,172 @@ +--- a/include/applets.src.h ++++ b/include/applets.src.h +@@ -218,6 +218,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 +@@ -419,6 +419,11 @@ config FEATURE_HDPARM_HDIO_GETSET_DMA + help + Enables the 'hdparm -d' option to get/set using_dma flag. + ++config LOCK ++ bool "lock" ++ help ++ Small utility for using locks in scripts ++ + config MAKEDEVS + bool "makedevs" + default y +--- a/miscutils/Kbuild.src ++++ b/miscutils/Kbuild.src +@@ -29,6 +29,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,135 @@ ++/* ++ * 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 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", 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; ++ 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; ++ } ++ } ++ ++ if (flock(fd, (shared ? LOCK_SH : LOCK_EX)) < 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; ++ } ++ } ++ 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/350-httpd_redir.patch b/package/utils/busybox/patches/350-httpd_redir.patch new file mode 100644 index 0000000000..11125e71f1 --- /dev/null +++ b/package/utils/busybox/patches/350-httpd_redir.patch @@ -0,0 +1,90 @@ +--- a/networking/httpd.c ++++ b/networking/httpd.c +@@ -105,6 +105,7 @@ + //usage: IF_FEATURE_HTTPD_BASIC_AUTH(" [-r REALM]") + //usage: " [-h HOME]\n" + //usage: "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING" ++//usage: " [-R <path> [-H <host>]]" + //usage:#define httpd_full_usage "\n\n" + //usage: "Listen for incoming HTTP requests\n" + //usage: "\n -i Inetd mode" +@@ -121,6 +122,8 @@ + //usage: "\n -m STRING MD5 crypt STRING") + //usage: "\n -e STRING HTML encode STRING" + //usage: "\n -d STRING URL decode STRING" ++//usage: "\n -R PATH Redirect target path" ++//usage: "\n -H HOST Redirect target host" + + #include "libbb.h" + #if ENABLE_FEATURE_HTTPD_USE_SENDFILE +@@ -272,6 +275,8 @@ struct globals { + + const char *found_mime_type; + const char *found_moved_temporarily; ++ const char *redirect_path; ++ const char *redirect_host; + Htaccess_IP *ip_a_d; /* config allow/deny lines */ + + IF_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) +@@ -322,6 +327,8 @@ struct globals { + #define index_page (G.index_page ) + #define found_mime_type (G.found_mime_type ) + #define found_moved_temporarily (G.found_moved_temporarily) ++#define redirect_path (G.redirect_path ) ++#define redirect_host (G.redirect_host ) + #define last_mod (G.last_mod ) + #define ip_a_d (G.ip_a_d ) + #define g_realm (G.g_realm ) +@@ -956,8 +963,11 @@ static void send_headers(int responseNum + } + #endif + if (responseNum == HTTP_MOVED_TEMPORARILY) { +- len += sprintf(iobuf + len, "Location: %s/%s%s\r\n", ++ len += sprintf(iobuf + len, "Location: %s%s%s%s%s%s\r\n", ++ (redirect_host ? "http://" : ""), ++ (redirect_host ? redirect_host : ""), + found_moved_temporarily, ++ (redirect_host ? "" : "/"), + (g_query ? "?" : ""), + (g_query ? g_query : "")); + } +@@ -1925,8 +1935,12 @@ static void handle_incoming_and_exit(con + } while (*++tptr); + *++urlp = '\0'; /* terminate after last character */ + ++ /* redirect active */ ++ if (redirect_path && (strncmp(urlcopy, redirect_path, strlen(redirect_path)) != 0)) ++ found_moved_temporarily = redirect_path; ++ + /* If URL is a directory, add '/' */ +- if (urlp[-1] != '/') { ++ if (!redirect_path && (urlp[-1] != '/')) { + if (is_directory(urlcopy + 1, 1, NULL)) { + found_moved_temporarily = urlcopy; + } +@@ -2283,7 +2297,9 @@ static void sighup_handler(int sig UNUSE + } + + enum { +- c_opt_config_file = 0, ++ R_opt_redirect_path = 0, ++ H_opt_redirect_host, ++ c_opt_config_file, + d_opt_decode_url, + h_opt_home_httpd, + IF_FEATURE_HTTPD_ENCODE_URL_STR(e_opt_encode_url,) +@@ -2332,12 +2348,13 @@ int httpd_main(int argc UNUSED_PARAM, ch + /* We do not "absolutize" path given by -h (home) opt. + * If user gives relative path in -h, + * $SCRIPT_FILENAME will not be set. */ +- opt = getopt32(argv, "c:d:h:" ++ opt = getopt32(argv, "R:H:c:d:h:" + IF_FEATURE_HTTPD_ENCODE_URL_STR("e:") + IF_FEATURE_HTTPD_BASIC_AUTH("r:") + IF_FEATURE_HTTPD_AUTH_MD5("m:") + IF_FEATURE_HTTPD_SETUID("u:") + "p:ifv", ++ &redirect_path, &redirect_host, + &opt_c_configFile, &url_for_decode, &home_httpd + IF_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) + IF_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) diff --git a/package/utils/busybox/patches/410-httpd_cgi_headers.patch b/package/utils/busybox/patches/410-httpd_cgi_headers.patch new file mode 100644 index 0000000000..b02a5b9d71 --- /dev/null +++ b/package/utils/busybox/patches/410-httpd_cgi_headers.patch @@ -0,0 +1,16 @@ +--- a/networking/httpd.c ++++ b/networking/httpd.c +@@ -1222,10 +1222,10 @@ static NOINLINE void cgi_io_loop_and_exi + if (full_write(STDOUT_FILENO, HTTP_200, sizeof(HTTP_200)-1) != sizeof(HTTP_200)-1) + break; + } +- /* Commented out: +- if (!strstr(rbuf, "ontent-")) { +- full_write(s, "Content-type: text/plain\r\n\r\n", 28); ++ if (!strstr(rbuf, "ontent-") && !strstr(rbuf, "ocation:")) { ++ full_write(1, "Content-type: text/plain\r\n\r\n", 28); + } ++ /* Previously commented out: + * Counter-example of valid CGI without Content-type: + * echo -en "HTTP/1.0 302 Found\r\n" + * echo -en "Location: http://www.busybox.net\r\n" diff --git a/package/utils/busybox/patches/440-httpd_chdir.patch b/package/utils/busybox/patches/440-httpd_chdir.patch new file mode 100644 index 0000000000..401c6eb5d0 --- /dev/null +++ b/package/utils/busybox/patches/440-httpd_chdir.patch @@ -0,0 +1,10 @@ +--- a/networking/httpd.c ++++ b/networking/httpd.c +@@ -1814,6 +1814,7 @@ static void handle_incoming_and_exit(con + char *header_ptr = header_ptr; + Htaccess_Proxy *proxy_entry; + #endif ++ xchdir(home_httpd); + + /* Allocation of iobuf is postponed until now + * (IOW, server process doesn't need to waste 8k) */ diff --git a/package/utils/busybox/patches/470-insmod_search.patch b/package/utils/busybox/patches/470-insmod_search.patch new file mode 100644 index 0000000000..7f0188fc82 --- /dev/null +++ b/package/utils/busybox/patches/470-insmod_search.patch @@ -0,0 +1,137 @@ +--- a/modutils/Config.src ++++ b/modutils/Config.src +@@ -247,7 +247,7 @@ config FEATURE_MODUTILS_SYMBOLS + config DEFAULT_MODULES_DIR + string "Default directory containing modules" + default "/lib/modules" +- depends on DEPMOD || MODPROBE || MODPROBE_SMALL || MODINFO ++ depends on DEPMOD || INSMOD || MODPROBE || MODPROBE_SMALL || MODINFO + help + Directory that contains kernel modules. + Defaults to "/lib/modules" +--- a/modutils/insmod.c ++++ b/modutils/insmod.c +@@ -11,6 +11,106 @@ + + #include "libbb.h" + #include "modutils.h" ++#include <sys/utsname.h> ++#ifndef CONFIG_FEATURE_2_4_MODULES ++#include <sys/mman.h> ++#include <asm/unistd.h> ++#include <sys/syscall.h> ++#endif ++ ++static char *g_filename = NULL; ++ ++static int FAST_FUNC check_module_name_match(const char *filename, struct stat *statbuf, ++ void *userdata, int depth) ++{ ++ char *fullname = (char *) userdata; ++ char *tmp; ++ ++ if (fullname[0] == '\0') ++ return FALSE; ++ ++ tmp = bb_get_last_path_component_nostrip(filename); ++ if (strcmp(tmp, fullname) == 0) { ++ /* Stop searching if we find a match */ ++ g_filename = xstrdup(filename); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++static int find_module(char *filename) ++{ ++ char *module_dir, real_module_dir[FILENAME_MAX]; ++ int len, slen, ret = ENOENT, k_version; ++ struct utsname myuname; ++ const char *suffix = ".ko"; ++ struct stat st; ++ ++ /* check the kernel version */ ++ if (uname(&myuname) != 0) ++ return EINVAL; ++ ++ k_version = myuname.release[0] - '0'; ++ ++ if (k_version < 2 || k_version > 9) ++ return EINVAL; ++ ++ if (k_version == 2) { ++ int k_patchlevel = myuname.release[2] - '0'; ++ if (k_patchlevel <= 4) ++#if ENABLE_FEATURE_2_4_MODULES ++ suffix = ".o"; ++#else ++ return EINVAL; ++#endif ++ } ++ ++ len = strlen(filename); ++ slen = strlen(suffix); ++ ++ /* check for suffix and absolute path first */ ++ if ((len < slen + 2) || (strcmp(filename + len - slen, suffix) != 0)) { ++ filename = xasprintf("%s%s", filename, suffix); ++ } else { ++ filename = strdup(filename); ++ if ((stat(filename, &st) == 0) && S_ISREG(st.st_mode)) { ++ g_filename = filename; ++ return 0; ++ } ++ free(filename); ++ return ENOENT; ++ } ++ ++ /* next: scan /lib/modules/<release> */ ++ /* Jump through hoops in case /lib/modules/`uname -r` ++ * is a symlink. We do not want recursive_action to ++ * follow symlinks, but we do want to follow the ++ * /lib/modules/`uname -r` dir, So resolve it ourselves ++ * if it is a link... */ ++ module_dir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, myuname.release); ++ if (realpath(module_dir, real_module_dir) != NULL) { ++ free(module_dir); ++ module_dir = real_module_dir; ++ } ++ ++ recursive_action(module_dir, ACTION_RECURSE, ++ check_module_name_match, 0, filename, 0); ++ ++ /* Check if we have a complete path */ ++ if (g_filename == NULL) ++ goto done; ++ ++ if ((stat(g_filename, &st) == 0) && S_ISREG(st.st_mode)) ++ ret = 0; ++ else ++ free(g_filename); ++ ++done: ++ free(filename); ++ ++ return ret; ++} + + /* 2.6 style insmod has no options and required filename + * (not module name - .ko can't be omitted) */ +@@ -58,9 +158,15 @@ int insmod_main(int argc UNUSED_PARAM, c + if (!filename) + bb_show_usage(); + +- rc = bb_init_module(filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0)); ++ rc = find_module(filename); ++ if (rc || (g_filename == NULL)) ++ goto done; ++ ++ rc = bb_init_module(g_filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0)); + if (rc) + bb_error_msg("can't insert '%s': %s", filename, moderror(rc)); ++ free (g_filename); + ++done: + return rc; + } diff --git a/package/utils/busybox/patches/490-mount_disable_check.patch b/package/utils/busybox/patches/490-mount_disable_check.patch new file mode 100644 index 0000000000..2fcb7f7fc2 --- /dev/null +++ b/package/utils/busybox/patches/490-mount_disable_check.patch @@ -0,0 +1,12 @@ +--- a/util-linux/mount.c ++++ b/util-linux/mount.c +@@ -128,9 +128,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/510-awk_include.patch b/package/utils/busybox/patches/510-awk_include.patch new file mode 100644 index 0000000000..9f525acf86 --- /dev/null +++ b/package/utils/busybox/patches/510-awk_include.patch @@ -0,0 +1,217 @@ +--- a/editors/awk.c ++++ b/editors/awk.c +@@ -1,3 +1,4 @@ ++ + /* vi: set sw=4 ts=4: */ + /* + * awk implementation for busybox +@@ -81,9 +82,14 @@ typedef struct chain_s { + } chain; + + /* Function */ ++typedef var *(*awk_cfunc)(var *res, var *args, int nargs); + typedef struct func_s { + unsigned nargs; ++ enum { AWKFUNC, CFUNC } type; ++ union { ++ awk_cfunc cfunc; + struct chain_s body; ++ } x; + } func; + + /* I/O stream */ +@@ -1473,7 +1479,8 @@ static void parse_program(char *p) + next_token(TC_FUNCTION); + g_pos++; + f = newfunc(t_string); +- f->body.first = NULL; ++ f->type = AWKFUNC; ++ f->x.body.first = NULL; + f->nargs = 0; + while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) { + v = findvar(ahash, t_string); +@@ -1482,7 +1489,7 @@ static void parse_program(char *p) + if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM) + break; + } +- seq = &f->body; ++ seq = &f->x.body; + chain_group(); + clear_array(ahash); + +@@ -2580,7 +2587,8 @@ static var *evaluate(node *op, var *res) + var *vbeg, *v; + const char *sv_progname; + +- if (!op->r.f->body.first) ++ if ((op->r.f->type == AWKFUNC) && ++ !op->r.f->x.body.first) + syntax_error(EMSG_UNDEF_FUNC); + + vbeg = v = nvalloc(op->r.f->nargs + 1); +@@ -2597,7 +2605,10 @@ static var *evaluate(node *op, var *res) + fnargs = vbeg; + sv_progname = g_progname; + +- res = evaluate(op->r.f->body.first, res); ++ if (op->r.f->type == AWKFUNC) ++ res = evaluate(op->r.f->x.body.first, res); ++ else if (op->r.f->type == CFUNC) ++ res = op->r.f->x.cfunc(res, fnargs, op->r.f->nargs); + + g_progname = sv_progname; + nvfree(fnargs); +@@ -2991,6 +3002,143 @@ static rstream *next_input_file(void) + #undef files_happen + } + ++/* read the contents of an entire file */ ++static char *get_file(const char *fname) ++{ ++ FILE *F; ++ char *s = NULL; ++ int i, j, flen; ++ ++ F = fopen(fname, "r"); ++ if (!F) { ++ return NULL; ++ } ++ ++ if (fseek(F, 0, SEEK_END) == 0) { ++ flen = ftell(F); ++ s = (char *)xmalloc(flen+4); ++ fseek(F, 0, SEEK_SET); ++ i = 1 + fread(s+1, 1, flen, F); ++ } else { ++ for (i=j=1; j>0; i+=j) { ++ s = (char *)xrealloc(s, i+4096); ++ j = fread(s+i, 1, 4094, F); ++ } ++ } ++ ++ s[i] = '\0'; ++ fclose(F); ++ return s; ++} ++ ++ ++/* parse_include(): ++ * ++ * taken from parse_program from awk.c ++ * END{} is not parsed here, and BEGIN{} is executed immediately ++ */ ++static void parse_include(char *p) ++{ ++ uint32_t tclass; ++ chain *initseq = NULL; ++ chain tmp; ++ func *f; ++ var *v, *tv; ++ ++ tv = nvalloc(1); ++ memset(&tmp, 0, sizeof(tmp)); ++ g_pos = p; ++ t_lineno = 1; ++ while ((tclass = next_token(TC_EOF | TC_OPSEQ | ++ TC_OPTERM | TC_BEGIN | TC_FUNCDECL)) != TC_EOF) { ++ if (tclass & TC_OPTERM) ++ continue; ++ ++ seq = &tmp; ++ if (tclass & TC_BEGIN) { ++ initseq = xzalloc(sizeof(chain)); ++ seq = initseq; ++ chain_group(); ++ } else if (tclass & TC_FUNCDECL) { ++ next_token(TC_FUNCTION); ++ g_pos++; ++ f = newfunc(t_string); ++ f->type = AWKFUNC; ++ f->x.body.first = NULL; ++ f->nargs = 0; ++ while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) { ++ v = findvar(ahash, t_string); ++ v->x.aidx = (f->nargs)++; ++ ++ if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM) ++ break; ++ } ++ seq = &(f->x.body); ++ chain_group(); ++ clear_array(ahash); ++ } ++ } ++ if (initseq && initseq->first) ++ tv = evaluate(initseq->first, tv); ++ nvfree(tv); ++} ++ ++ ++/* include an awk file and run its BEGIN{} section */ ++static xhash *includes = NULL; ++static void include_file(const char *filename) ++{ ++ char *s; ++ var *v; ++ int oldlnr = g_lineno; ++ const char *oldprg = g_progname; ++ ++ if (!includes) ++ includes = hash_init(); ++ ++ /* find out if the file has been included already */ ++ v = findvar(includes, filename); ++ if (istrue(v)) ++ return; ++ setvar_s(v, "1"); ++ ++ /* read include file */ ++ s = get_file(filename); ++ if (!s) { ++ fprintf(stderr, "Could not open file.\n"); ++ return; ++ } ++ g_lineno = 1; ++ g_progname = xstrdup(filename); ++ parse_include(s+1); ++ free(s); ++ g_lineno = oldlnr; ++ g_progname = oldprg; ++} ++ ++static var *include(var *res, var *args, int nargs) ++{ ++ const char *s; ++ ++ nargs = nargs; /* shut up, gcc */ ++ s = getvar_s(args); ++ if (s && (strlen(s) > 0)) ++ include_file(s); ++ ++ return res; ++} ++ ++/* registers a global c function for the awk interpreter */ ++static void register_cfunc(const char *name, awk_cfunc cfunc, int nargs) ++{ ++ func *f; ++ ++ f = newfunc(name); ++ f->type = CFUNC; ++ f->x.cfunc = cfunc; ++ f->nargs = nargs; ++} ++ + int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; + int awk_main(int argc, char **argv) + { +@@ -3056,6 +3204,9 @@ int awk_main(int argc, char **argv) + *s1 = '='; + } + } ++ ++ register_cfunc("include", include, 1); ++ + opt_complementary = "v::f::"; /* -v and -f can occur multiple times */ + opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, &opt_W); + argv += optind; diff --git a/package/utils/busybox/patches/524-udhcpc_renew.patch b/package/utils/busybox/patches/524-udhcpc_renew.patch new file mode 100644 index 0000000000..c22fa52ea2 --- /dev/null +++ b/package/utils/busybox/patches/524-udhcpc_renew.patch @@ -0,0 +1,10 @@ +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -1045,7 +1045,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/610-ntpd_delayed_resolve.patch b/package/utils/busybox/patches/610-ntpd_delayed_resolve.patch new file mode 100644 index 0000000000..5e17ae16c2 --- /dev/null +++ b/package/utils/busybox/patches/610-ntpd_delayed_resolve.patch @@ -0,0 +1,48 @@ +--- a/networking/ntpd.c ++++ b/networking/ntpd.c +@@ -216,6 +216,7 @@ typedef struct { + typedef struct { + len_and_sockaddr *p_lsa; + char *p_dotted; ++ char *p_hostname; + /* when to send new query (if p_fd == -1) + * or when receive times out (if p_fd >= 0): */ + int p_fd; +@@ -646,8 +647,9 @@ add_peers(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); */ +@@ -696,6 +698,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/611-upstream_ntpd_version_fix.patch b/package/utils/busybox/patches/611-upstream_ntpd_version_fix.patch new file mode 100644 index 0000000000..7bcb8475d7 --- /dev/null +++ b/package/utils/busybox/patches/611-upstream_ntpd_version_fix.patch @@ -0,0 +1,29 @@ +From b7841cf7b919b16d1bd4619154bf7cb4c22b4ccd Mon Sep 17 00:00:00 2001 +From: Paul Marks <paul@pmarks.net> +Date: Mon, 14 Jan 2013 01:39:10 +0000 +Subject: ntpd: fix incorrect m_status field in outgoing packets. Closes 5120 + +When using busybox ntpd with an NTPv3 client and NTPv4 server (or vice +versa), the version numbers can be incorrectly ORed together, yielding +the bogus value of "NTPv7". This makes ntpd unusable with clients +such as Chrony and Windows "Internet Time". + +This patch avoids the version mangling, by copying only the Leap +Indicator bits from the server's status field. + +Signed-off-by: Paul Marks <paul@pmarks.net> +Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> +--- +(limited to 'networking/ntpd.c') + +--- a/networking/ntpd.c ++++ b/networking/ntpd.c +@@ -1794,7 +1794,7 @@ recv_and_process_client_pkt(void /*int f + + /* Build a reply packet */ + memset(&msg, 0, sizeof(msg)); +- msg.m_status = G.stratum < MAXSTRAT ? G.ntp_status : LI_ALARM; ++ msg.m_status = G.stratum < MAXSTRAT ? (G.ntp_status & LI_MASK) : LI_ALARM; + msg.m_status |= (query_status & VERSION_MASK); + msg.m_status |= ((query_status & MODE_MASK) == MODE_CLIENT) ? + MODE_SERVER : MODE_SYM_PAS; diff --git a/package/utils/busybox/patches/700-hexdump_segfault_fix.patch b/package/utils/busybox/patches/700-hexdump_segfault_fix.patch new file mode 100644 index 0000000000..ab09fb3e42 --- /dev/null +++ b/package/utils/busybox/patches/700-hexdump_segfault_fix.patch @@ -0,0 +1,11 @@ +--- a/libbb/dump.c ++++ b/libbb/dump.c +@@ -301,7 +301,7 @@ static NOINLINE void rewrite(priv_dumper + ) { + fu->reps += (dumper->blocksize - fs->bcnt) / fu->bcnt; + } +- if (fu->reps > 1) { ++ if (fu->reps > 1 && fu->nextpr) { + for (pr = fu->nextpr;; pr = pr->nextpr) + if (!pr->nextpr) + break; diff --git a/package/utils/busybox/patches/802-brctl_linux24.patch b/package/utils/busybox/patches/802-brctl_linux24.patch new file mode 100644 index 0000000000..8cc19779a2 --- /dev/null +++ b/package/utils/busybox/patches/802-brctl_linux24.patch @@ -0,0 +1,74 @@ +--- a/networking/brctl.c ++++ b/networking/brctl.c +@@ -56,7 +56,7 @@ + + /* Maximum number of ports supported per bridge interface. */ + #ifndef MAX_PORTS +-# define MAX_PORTS 32 ++# define MAX_PORTS 1024 + #endif + + /* Use internal number parsing and not the "exact" conversion. */ +@@ -193,6 +193,7 @@ int brctl_main(int argc UNUSED_PARAM, ch + printf(bi.stp_enabled ? "\tyes" : "\tno"); + + /* print interface list */ ++ memset(ifidx, 0, sizeof ifidx); + arm_ioctl(args, BRCTL_GET_PORT_LIST, + (unsigned long) ifidx, MAX_PORTS); + xioctl(fd, SIOCDEVPRIVATE, &ifr); +@@ -221,9 +222,19 @@ int brctl_main(int argc UNUSED_PARAM, ch + br = *argv++; + + if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */ +- ioctl_or_perror_and_die(fd, +- key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, +- br, "bridge %s", br); ++ int ret; ++ ret = ioctl(fd, ++ key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, ++ br); ++ if (ret < 0) { ++ arm_ioctl(args, ++ key == ARG_addbr ? BRCTL_ADD_BRIDGE : BRCTL_DEL_BRIDGE, ++ (unsigned long) br, 0); ++ ret = ioctl(fd, SIOCSIFBR, args); ++ } ++ if (ret < 0) { ++ bb_perror_msg_and_die("bridge %s", br); ++ } + goto done; + } + +@@ -232,14 +243,27 @@ int brctl_main(int argc UNUSED_PARAM, ch + + strncpy_IFNAMSIZ(ifr.ifr_name, br); + if (key == ARG_addif || key == ARG_delif) { /* addif or delif */ ++ int ret; ++ int if_index; + brif = *argv; +- ifr.ifr_ifindex = if_nametoindex(brif); +- if (!ifr.ifr_ifindex) { ++ if_index = if_nametoindex(brif); ++ if (!if_index) { + bb_perror_msg_and_die("iface %s", brif); + } +- ioctl_or_perror_and_die(fd, ++ ifr.ifr_ifindex = if_index; ++ ret = ioctl(fd, + key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF, +- &ifr, "bridge %s", br); ++ &ifr); ++ if (ret < 0) { ++ arm_ioctl(args, ++ key == ARG_addif ? BRCTL_ADD_IF : BRCTL_DEL_IF, ++ if_index, 0); ++ ifr.ifr_data = (char *) &args; ++ ret = ioctl(fd, SIOCDEVPRIVATE, &ifr); ++ } ++ if (ret < 0) { ++ bb_perror_msg_and_die("bridge %s", br); ++ } + goto done_next_argv; + } + #if ENABLE_FEATURE_BRCTL_FANCY diff --git a/package/utils/busybox/patches/902-telnetd_intr.patch b/package/utils/busybox/patches/902-telnetd_intr.patch new file mode 100644 index 0000000000..862ece055d --- /dev/null +++ b/package/utils/busybox/patches/902-telnetd_intr.patch @@ -0,0 +1,10 @@ +--- a/networking/telnetd.c ++++ b/networking/telnetd.c +@@ -330,6 +330,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/910-insmod-q-flag.patch b/package/utils/busybox/patches/910-insmod-q-flag.patch new file mode 100644 index 0000000000..6002f20f1b --- /dev/null +++ b/package/utils/busybox/patches/910-insmod-q-flag.patch @@ -0,0 +1,33 @@ +--- a/modutils/insmod.c ++++ b/modutils/insmod.c +@@ -139,7 +139,7 @@ int insmod_main(int argc, char **argv) M + int insmod_main(int argc UNUSED_PARAM, char **argv) + { + char *filename; +- int rc; ++ int rc, opt; + + /* Compat note: + * 2.6 style insmod has no options and required filename +@@ -149,10 +149,8 @@ int insmod_main(int argc UNUSED_PARAM, c + * or in $MODPATH. + */ + +- IF_FEATURE_2_4_MODULES( +- getopt32(argv, INSMOD_OPTS INSMOD_ARGS); +- argv += optind - 1; +- ); ++ opt = getopt32(argv, INSMOD_OPTS, NULL, NULL); ++ argv += optind - 1; + + filename = *++argv; + if (!filename) +@@ -163,7 +161,7 @@ int insmod_main(int argc UNUSED_PARAM, c + goto done; + + rc = bb_init_module(g_filename, parse_cmdline_module_options(argv, /*quote_spaces:*/ 0)); +- if (rc) ++ if (rc && !(opt & INSMOD_OPT_SILENT)) + bb_error_msg("can't insert '%s': %s", filename, moderror(rc)); + free (g_filename); + diff --git a/package/utils/busybox/patches/911-date-k-flag.patch b/package/utils/busybox/patches/911-date-k-flag.patch new file mode 100644 index 0000000000..c55ee23369 --- /dev/null +++ b/package/utils/busybox/patches/911-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]" +@@ -135,6 +136,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 +@@ -145,8 +147,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) +@@ -164,12 +167,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]; +@@ -184,7 +190,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)); +@@ -241,6 +247,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_BSD ++ 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/920-portability.patch b/package/utils/busybox/patches/920-portability.patch new file mode 100644 index 0000000000..4e5b9a0576 --- /dev/null +++ b/package/utils/busybox/patches/920-portability.patch @@ -0,0 +1,13 @@ +--- a/scripts/kconfig/mconf.c ++++ b/scripts/kconfig/mconf.c +@@ -25,6 +25,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/950-partial-checksum.patch b/package/utils/busybox/patches/950-partial-checksum.patch new file mode 100644 index 0000000000..6e8a69e9a6 --- /dev/null +++ b/package/utils/busybox/patches/950-partial-checksum.patch @@ -0,0 +1,86 @@ +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -26,8 +26,8 @@ + #include "dhcpc.h" + + #include <netinet/if_ether.h> +-#include <netpacket/packet.h> + #include <linux/filter.h> ++#include <linux/if_packet.h> + + /* struct client_config_t client_config is in bb_common_bufsiz1 */ + +@@ -846,17 +846,41 @@ static int send_release(uint32_t server, + static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) + { + int bytes; ++ int nocsum = 0; + struct ip_udp_dhcp_packet packet; + uint16_t check; ++ unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; ++ struct iovec iov = { ++ .iov_base = &packet, ++ .iov_len = sizeof(packet), ++ }; ++ struct msghdr msg = { ++ .msg_iov = &iov, ++ .msg_iovlen = 1, ++ .msg_control = cmsgbuf, ++ .msg_controllen = sizeof(cmsgbuf), ++ }; ++ struct cmsghdr *cmsg; + + memset(&packet, 0, sizeof(packet)); +- bytes = safe_read(fd, &packet, sizeof(packet)); ++ do { ++ bytes = recvmsg(fd, &msg, 0); ++ } while (bytes < 0 && errno == EINTR); ++ + if (bytes < 0) { + log1("Packet read error, ignoring"); + /* NB: possible down interface, etc. Caller should pause. */ + return bytes; /* returns -1 */ + } + ++ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { ++ if (cmsg->cmsg_level == SOL_PACKET && ++ cmsg->cmsg_type == PACKET_AUXDATA) { ++ struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg); ++ nocsum = aux->tp_status & TP_STATUS_CSUMNOTREADY; ++ } ++ } ++ + if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) { + log1("Packet is too short, ignoring"); + return -2; +@@ -896,7 +920,7 @@ static NOINLINE int udhcp_recv_raw_packe + packet.ip.tot_len = packet.udp.len; /* yes, this is needed */ + check = packet.udp.check; + packet.udp.check = 0; +- if (check && check != udhcp_checksum(&packet, bytes)) { ++ if (!nocsum && check && check != udhcp_checksum(&packet, bytes)) { + log1("Packet with bad UDP checksum received, ignoring"); + return -2; + } +@@ -942,6 +966,7 @@ static int udhcp_raw_socket(int ifindex) + { + int fd; + struct sockaddr_ll sock; ++ int val; + + /* + * Comment: +@@ -1008,6 +1033,13 @@ static int udhcp_raw_socket(int ifindex) + log1("Attached filter to raw socket fd %d", fd); // log? + } + ++ val = 1; ++ if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, &val, ++ sizeof(val)) < 0) { ++ if (errno != ENOPROTOOPT) ++ log1("Failed to set auxiliary packet data for socket fd %d", fd); ++ } ++ + log1("Created raw socket"); + + return fd; diff --git a/package/utils/busybox/patches/998-arping_missing_includes.patch b/package/utils/busybox/patches/998-arping_missing_includes.patch new file mode 100644 index 0000000000..a9d4a62af3 --- /dev/null +++ b/package/utils/busybox/patches/998-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/999-musl-fixes.patch b/package/utils/busybox/patches/999-musl-fixes.patch new file mode 100644 index 0000000000..b528b3e81b --- /dev/null +++ b/package/utils/busybox/patches/999-musl-fixes.patch @@ -0,0 +1,16 @@ +--- a/include/platform.h ++++ b/include/platform.h +@@ -443,6 +443,13 @@ typedef unsigned smalluint; + # undef HAVE_NET_ETHERNET_H + #endif + ++#if defined(__musl__) ++# undef HAVE_SETBIT ++# include <stddef.h> ++# include <termios.h> ++# include <sys/ioctl.h> ++#endif ++ + /* + * Now, define prototypes for all the functions defined in platform.c + * These must come after all the HAVE_* macros are defined (or not) diff --git a/package/utils/e2fsprogs/Makefile b/package/utils/e2fsprogs/Makefile new file mode 100644 index 0000000000..ebc21c9067 --- /dev/null +++ b/package/utils/e2fsprogs/Makefile @@ -0,0 +1,169 @@ +# +# Copyright (C) 2006-2012 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.4 +PKG_MD5SUM:=b6e296f210d642361b7394437ff0f318 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=@SF/e2fsprogs + +PKG_BUILD_DEPENDS:=util-linux +PKG_INSTALL:=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:=+libblkid +libuuid +libext2fs +endef + +define Package/e2fsprogs/description + This package contains essential ext2 filesystem utilities which consists of + e2fsck, mke2fs, tune2fs, and most of the other core ext2 + filesystem utilities. +endef + +define Package/libext2fs +$(call Package/e2fsprogs/Default) + DEPENDS:=+libcom_err + 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/libcom_err +$(call Package/e2fsprogs/Default) + DEPENDS:=+libpthread + SECTION:=libs + CATEGORY:=Libraries + TITLE:=Common error description library +endef + +define Package/libcom_err/description + libcom_err is a library providing common error descriptions +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 + +TARGET_CFLAGS += $(FPIC) + +CONFIGURE_ARGS += \ + --enable-elf-shlibs \ + --disable-libuuid \ + --disable-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) -C $(PKG_BUILD_DIR)/util \ + BUILDCC="$(HOSTCC)" \ + CFLAGS="" \ + CPPFLAGS="" \ + LDFLAGS="" \ + subst + $(MAKE) -C $(PKG_BUILD_DIR) \ + BUILDCC="$(HOSTCC)" \ + DESTDIR="$(PKG_INSTALL_DIR)" \ + all +endef + +define Build/InstallDev + $(MAKE) -C $(PKG_BUILD_DIR) \ + BUILDCC="$(HOSTCC)" \ + DESTDIR="$(1)" \ + install-libs + $(MAKE) -C $(PKG_BUILD_DIR)/lib/ext2fs \ + BUILDCC="$(HOSTCC)" \ + DESTDIR="$(1)" \ + install +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 -sf mke2fs $(1)/usr/sbin/mkfs.ext2 + ln -sf mke2fs $(1)/usr/sbin/mkfs.ext3 + ln -sf mke2fs $(1)/usr/sbin/mkfs.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 + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libcom_err.so.* $(1)/usr/lib/ +endef + +define Package/libext2fs/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libext2fs.so.* $(1)/usr/lib/ +endef + +define Package/tune2fs/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/tune2fs $(1)/usr/sbin/ +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 + +$(eval $(call BuildPackage,e2fsprogs)) +$(eval $(call BuildPackage,libext2fs)) +$(eval $(call BuildPackage,libcom_err)) +$(eval $(call BuildPackage,tune2fs)) +$(eval $(call BuildPackage,resize2fs)) +$(eval $(call BuildPackage,badblocks)) diff --git a/package/utils/e2fsprogs/files/e2fsck.conf b/package/utils/e2fsprogs/files/e2fsck.conf new file mode 100644 index 0000000000..9c96b49585 --- /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 0000000000..22031edb67 --- /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-link-against-libuuid.patch b/package/utils/e2fsprogs/patches/001-link-against-libuuid.patch new file mode 100644 index 0000000000..e0564dc355 --- /dev/null +++ b/package/utils/e2fsprogs/patches/001-link-against-libuuid.patch @@ -0,0 +1,38 @@ +--- a/configure ++++ b/configure +@@ -5038,7 +5038,7 @@ if test "${ac_cv_lib_blkid_blkid_get_cac + $as_echo_n "(cached) " >&6 + else + ac_check_lib_save_LIBS=$LIBS +-LIBS="-lblkid $LIBBLKID $LIBS" ++LIBS="-lblkid $LIBBLKID $LIBUUID $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + +--- a/misc/Makefile.in ++++ b/misc/Makefile.in +@@ -146,10 +146,10 @@ partinfo: partinfo.o + $(E) " LD $@" + $(Q) $(CC) $(ALL_LDFLAGS) -o partinfo partinfo.o + +-e2initrd_helper: e2initrd_helper.o $(DEPLIBS) $(DEPLIBBLKID) $(LIBEXT2FS) ++e2initrd_helper: e2initrd_helper.o $(DEPLIBS) $(DEPLIBBLKID) $(DEPLIBUUID) $(LIBEXT2FS) + $(E) " LD $@" + $(Q) $(CC) $(ALL_LDFLAGS) -o e2initrd_helper e2initrd_helper.o $(LIBS) \ +- $(LIBBLKID) $(LIBEXT2FS) $(LIBINTL) ++ $(LIBBLKID) $(LIBUUID) $(LIBEXT2FS) $(LIBINTL) + + tune2fs: $(TUNE2FS_OBJS) $(DEPLIBS) $(DEPLIBS_E2P) $(DEPLIBBLKID) \ + $(DEPLIBUUID) $(DEPLIBQUOTA) $(LIBEXT2FS) +@@ -289,9 +289,9 @@ dumpe2fs.profiled: $(PROFILED_DUMPE2FS_O + $(PROFILED_DUMPE2FS_OBJS) $(PROFILED_LIBS) \ + $(PROFILED_LIBE2P) $(PROFILED_LIBUUID) $(LIBINTL) + +-fsck: $(FSCK_OBJS) $(DEPLIBBLKID) ++fsck: $(FSCK_OBJS) $(DEPLIBBLKID) $(DEPLIBUUID) + $(E) " LD $@" +- $(Q) $(CC) $(ALL_LDFLAGS) -o fsck $(FSCK_OBJS) $(LIBBLKID) $(LIBINTL) ++ $(Q) $(CC) $(ALL_LDFLAGS) -o fsck $(FSCK_OBJS) $(LIBBLKID) $(LIBUUID) $(LIBINTL) + + fsck.profiled: $(PROFILED_FSCK_OBJS) $(PROFILED_DEPLIBBLKID) + $(E) " LD $@" diff --git a/package/utils/e2fsprogs/patches/002-no_malloc_h.patch b/package/utils/e2fsprogs/patches/002-no_malloc_h.patch new file mode 100644 index 0000000000..209b47c1cc --- /dev/null +++ b/package/utils/e2fsprogs/patches/002-no_malloc_h.patch @@ -0,0 +1,10 @@ +--- a/util/symlinks.c ++++ b/util/symlinks.c +@@ -8,7 +8,6 @@ + #endif + #include <stdio.h> + #include <stdlib.h> +-#include <malloc.h> + #include <string.h> + #include <fcntl.h> + #include <sys/param.h> diff --git a/package/utils/fbtest/Makefile b/package/utils/fbtest/Makefile new file mode 100644 index 0000000000..05e67cb63a --- /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 0000000000..075bc0ecbf --- /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 0000000000..6e9c2f85fa --- /dev/null +++ b/package/utils/fbtest/src/fbtest.c @@ -0,0 +1,448 @@ +/****************************************************************************** + * 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> + +#include <error.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 0000000000..0620b6cf9b --- /dev/null +++ b/package/utils/fuse/Makefile @@ -0,0 +1,111 @@ +# +# Copyright (C) 2006-2010 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.0 +PKG_RELEASE:=2 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=@SF/$(PKG_NAME) +PKG_MD5SUM:=894ee11674f89a915ae87524aed55bc4 + +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 \ + --disable-rpath \ + --disable-example \ + --disable-mtab + +# generic package uses lib & utils +CONFIGURE_ARGS += --enable-lib --enable-util + +define Build/InstallDev + @echo "--> Build/InstallDev enter" + mkdir -p $(1)/usr/include + $(CP) $(PKG_INSTALL_DIR)/usr/include/{fuse,*.h} $(1)/usr/include/ + mkdir -p $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.{a,so*} $(1)/usr/lib/ + mkdir -p $(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 + @echo "--> Build/InstallDev leave" +endef + +define Package/fuse-utils/install + @echo "--> Package/fuse-utils/install enter" + $(INSTALL_DIR) $(1)/usr/bin + # use cp and keep fusermount sticky bit + $(FIND) $(PKG_INSTALL_DIR)/usr/bin/ -type f -exec $(CP) -a {} $(1)/usr/bin/ \; + @echo "--> Package/fuse-utils/install leave" +endef + +define Package/libfuse/install + @echo "--> Package/libfuse/install enter" + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so.* $(1)/usr/lib/ + @echo "--> Package/libfuse/install leave" +endef + +define Package/kmod-fuse/install + @echo "--> Package/kmod-fuse/install enter/leave" +endef + +$(eval $(call BuildPackage,fuse-utils)) +$(eval $(call BuildPackage,libfuse)) 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 0000000000..5f913df6d6 --- /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 +@@ -641,7 +641,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/hostap-utils/Makefile b/package/utils/hostap-utils/Makefile new file mode 100644 index 0000000000..1d7b22122e --- /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/lua/Makefile b/package/utils/lua/Makefile new file mode 100644 index 0000000000..e7e011a405 --- /dev/null +++ b/package/utils/lua/Makefile @@ -0,0 +1,183 @@ +# +# 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:=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_EGLIBC),) + 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 -sf 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 0000000000..74b8c6f8f0 --- /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 0000000000..14c720bf19 --- /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 0000000000..2ea59f1769 --- /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 0000000000..8dfef85d0d --- /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 0000000000..209c302bb7 --- /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 0000000000..74b8c6f8f0 --- /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 0000000000..14c720bf19 --- /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 0000000000..2ea59f1769 --- /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 0000000000..bcd410f690 --- /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 0000000000..8dfef85d0d --- /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/100-no_readline.patch b/package/utils/lua/patches/100-no_readline.patch new file mode 100644 index 0000000000..0350e470ad --- /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 0000000000..054457744a --- /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 0000000000..5fbb87388a --- /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/mkelfimage/Makefile b/package/utils/mkelfimage/Makefile new file mode 100644 index 0000000000..2433c72038 --- /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 0000000000..108583aedd --- /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 0000000000..81cff034c4 --- /dev/null +++ b/package/utils/nvram/Makefile @@ -0,0 +1,60 @@ +# +# 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_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 Build/InstallDev + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/libnvram.so.0.1 $(1)/usr/lib/ + ln -s libnvram.so.0.1 $(1)/usr/lib/libnvram.so +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/ + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/libnvram.so.0.1 $(1)/usr/lib/ +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 0000000000..467ab28195 --- /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 0000000000..4872728baf --- /dev/null +++ b/package/utils/nvram/src/Makefile @@ -0,0 +1,33 @@ +CLI_FILENAME = nvram + +LIB_VERMAJOR = 0 +LIB_VERMINOR = 1 +LIB_FILENAME = libnvram.so + +LIB_CFLAGS = $(CFLAGS) -shared -fPIC +LIB_LDFLAGS = $(LDFLAGS) -Wl,-soname,$(LIB_FILENAME).$(LIB_VERMAJOR).$(LIB_VERMINOR) + +CLI_CFLAGS = $(CFLAGS) +CLI_LDFLAGS = $(LDFLAGS) + +CLI_OBJ = cli.o +LIB_OBJ = crc.o nvram.o + +all: cli libnvram + +cli: libnvram + $(CC) $(CLI_CFLAGS) -c -o cli.o cli.c + $(CC) -o $(CLI_FILENAME) $(CLI_LDFLAGS) $(CLI_OBJ) \ + $(LIB_FILENAME).$(LIB_VERMAJOR).$(LIB_VERMINOR) + +cli.o: cli.c + $(CC) $(CLI_CFLAGS) -c -o $@ $< + +libnvram: + $(CC) $(LIB_CFLAGS) -c -o crc.o crc.c + $(CC) $(LIB_CFLAGS) -c -o nvram.o nvram.c + $(CC) $(LIB_CFLAGS) $(LIB_LDFLAGS) \ + -o $(LIB_FILENAME).$(LIB_VERMAJOR).$(LIB_VERMINOR) $(LIB_OBJ) + +clean: + rm -f $(CLI_FILENAME) $(LIB_FILENAME)* *.o diff --git a/package/utils/nvram/src/cli.c b/package/utils/nvram/src/cli.c new file mode 100644 index 0000000000..66ef904885 --- /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_SPACE - hdr->len, + (100.00 / (double)NVRAM_SPACE) * (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 0000000000..22a36652aa --- /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 0000000000..a0bc006d15 --- /dev/null +++ b/package/utils/nvram/src/nvram.c @@ -0,0 +1,556 @@ +/* + * 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_t nvram_erase_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) > NVRAM_SPACE) + 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_SPACE - sizeof(nvram_header_t)); + memset(&tmp, 0, sizeof(nvram_header_t)); + + /* Leave space for a double NUL at the end */ + end = (char *) header + NVRAM_SPACE - 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_erase_size == 0) || (file == NULL) ) + { + /* Finding the mtd will set the appropriate erase size */ + if( (mtd = nvram_find_mtd()) == NULL || nvram_erase_size == 0 ) + { + free(mtd); + return NULL; + } + } + + if( (fd = open(file ? file : mtd, O_RDWR)) > -1 ) + { + char *mmap_area = (char *) mmap( + NULL, nvram_erase_size, PROT_READ | PROT_WRITE, + (( rdonly == NVRAM_RO ) ? MAP_PRIVATE : MAP_SHARED) | MAP_LOCKED, fd, 0); + + if( mmap_area != MAP_FAILED ) + { + for( i = 0; i <= ((nvram_erase_size - NVRAM_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_erase_size; + h->offset = offset; + + header = nvram_header(h); + + if( header->magic == NVRAM_MAGIC ) + { + _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, esz; + char dev[PATH_MAX]; + char *path = NULL; + struct stat s; + int supported = 1; + + /* Refuse any operation on the WGT634U */ + if( (fp = fopen("/proc/diag/model", "r")) ) + { + if( fgets(dev, sizeof(dev), fp) && !strncmp(dev, "Netgear WGT634U", 15) ) + supported = 0; + + fclose(fp); + } + + if( supported && (fp = fopen("/proc/mtd", "r")) ) + { + while( fgets(dev, sizeof(dev), fp) ) + { + if( strstr(dev, "nvram") && sscanf(dev, "mtd%d: %08x", &i, &esz) ) + { + nvram_erase_size = esz; + + 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; + } + } + else + { + 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_erase_size]; + + stat = -1; + + if( (mtd != NULL) && (nvram_erase_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_erase_size]; + + stat = -1; + + if( (mtd != NULL) && (nvram_erase_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 0000000000..c72f67e9a8 --- /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_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 0000000000..5a289adece --- /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/px5g/Makefile b/package/utils/px5g/Makefile new file mode 100644 index 0000000000..ad4ec40580 --- /dev/null +++ b/package/utils/px5g/Makefile @@ -0,0 +1,40 @@ +# +# Copyright (C) 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:=px5g +PKG_RELEASE:=1 + +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/px5g + SECTION:=utils + CATEGORY:=Utilities + TITLE:=Standalone X.509 certificate generator + MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org> +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) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +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/src/Makefile b/package/utils/px5g/src/Makefile new file mode 100644 index 0000000000..2bd95739cb --- /dev/null +++ b/package/utils/px5g/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/src/library/base64.c b/package/utils/px5g/src/library/base64.c new file mode 100644 index 0000000000..b7cc5b84ea --- /dev/null +++ b/package/utils/px5g/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/src/library/bignum.c b/package/utils/px5g/src/library/bignum.c new file mode 100644 index 0000000000..8b7c12ff00 --- /dev/null +++ b/package/utils/px5g/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/src/library/havege.c b/package/utils/px5g/src/library/havege.c new file mode 100644 index 0000000000..266299d3bb --- /dev/null +++ b/package/utils/px5g/src/library/havege.c @@ -0,0 +1,276 @@ +/* + * HAVEGE: HArdware Volatile Entropy Gathering and Expansion + * + * 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 HAVEGE RNG was designed by Andre Seznec in 2002. + * + * http://www.irisa.fr/caps/projects/hipsor/publi.php + * + * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr + */ + +#include <string.h> +#include <time.h> + +#include "polarssl/config.h" + +#if defined(POLARSSL_HAVEGE_C) + +#include "polarssl/havege.h" +#include "polarssl/timing.h" + +/* ------------------------------------------------------------------------ + * On average, one iteration accesses two 8-word blocks in the havege WALK + * table, and generates 16 words in the RES array. + * + * The data read in the WALK table is updated and permuted after each use. + * The result of the hardware clock counter read is used for this update. + * + * 25 conditional tests are present. The conditional tests are grouped in + * two nested groups of 12 conditional tests and 1 test that controls the + * permutation; on average, there should be 6 tests executed and 3 of them + * should be mispredicted. + * ------------------------------------------------------------------------ + */ + +#define SWAP(X,Y) { int *T = X; X = Y; Y = T; } + +#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; +#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; + +#define TST1_LEAVE U1++; } +#define TST2_LEAVE U2++; } + +#define ONE_ITERATION \ + \ + PTEST = PT1 >> 20; \ + \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + \ + PTX = (PT1 >> 18) & 7; \ + PT1 &= 0x1FFF; \ + PT2 &= 0x1FFF; \ + CLK = (int) hardclock(); \ + \ + i = 0; \ + A = &WALK[PT1 ]; RES[i++] ^= *A; \ + B = &WALK[PT2 ]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ + \ + IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ + *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ + *B = IN ^ U1; \ + *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ + *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ + \ + if( PTEST & 1 ) SWAP( A, C ); \ + \ + IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ + *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ + *B = IN; CLK = (int) hardclock(); \ + *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ + *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 4]; \ + B = &WALK[PT2 ^ 1]; \ + \ + PTEST = PT2 >> 1; \ + \ + PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ + PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ + PTY = (PT2 >> 10) & 7; \ + \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + \ + C = &WALK[PT1 ^ 5]; \ + D = &WALK[PT2 ^ 5]; \ + \ + RES[i++] ^= *A; \ + RES[i++] ^= *B; \ + RES[i++] ^= *C; \ + RES[i++] ^= *D; \ + \ + IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ + *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ + *B = IN ^ U2; \ + *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ + *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ + \ + IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ + *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ + *B = IN; \ + *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ + *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ + \ + PT1 = ( RES[(i - 8) ^ PTX] ^ \ + WALK[PT1 ^ PTX ^ 7] ) & (~1); \ + PT1 ^= (PT2 ^ 0x10) & 0x10; \ + \ + for( n++, i = 0; i < 16; i++ ) \ + hs->pool[n % COLLECT_SIZE] ^= RES[i]; + +/* + * Entropy gathering function + */ +static void havege_fill( havege_state *hs ) +{ + int i, n = 0; + int U1, U2, *A, *B, *C, *D; + int PT1, PT2, *WALK, RES[16]; + int PTX, PTY, CLK, PTEST, IN; + + WALK = hs->WALK; + PT1 = hs->PT1; + PT2 = hs->PT2; + + PTX = U1 = 0; + PTY = U2 = 0; + + memset( RES, 0, sizeof( RES ) ); + + while( n < COLLECT_SIZE * 4 ) + { + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + } + + hs->PT1 = PT1; + hs->PT2 = PT2; + + hs->offset[0] = 0; + hs->offset[1] = COLLECT_SIZE / 2; +} + +/* + * HAVEGE initialization + */ +void havege_init( havege_state *hs ) +{ + memset( hs, 0, sizeof( havege_state ) ); + + havege_fill( hs ); +} + +/* + * HAVEGE rand function + */ +int havege_rand( void *p_rng ) +{ + int ret; + havege_state *hs = (havege_state *) p_rng; + + if( hs->offset[1] >= COLLECT_SIZE ) + havege_fill( hs ); + + ret = hs->pool[hs->offset[0]++]; + ret ^= hs->pool[hs->offset[1]++]; + + return( ret ); +} + +#if defined(POLARSSL_RAND_TEST) + +#include <stdio.h> + +int main( int argc, char *argv[] ) +{ + FILE *f; + time_t t; + int i, j, k; + havege_state hs; + unsigned char buf[1024]; + + if( argc < 2 ) + { + fprintf( stderr, "usage: %s <output filename>\n", argv[0] ); + return( 1 ); + } + + if( ( f = fopen( argv[1], "wb+" ) ) == NULL ) + { + printf( "failed to open '%s' for writing.\n", argv[0] ); + return( 1 ); + } + + havege_init( &hs ); + + t = time( NULL ); + + for( i = 0, k = 32768; i < k; i++ ) + { + for( j = 0; j < sizeof( buf ); j++ ) + buf[j] = havege_rand( &hs ); + + fwrite( buf, sizeof( buf ), 1, f ); + + printf( "Generating 32Mb of data in file '%s'... %04.1f" \ + "%% done\r", argv[1], (100 * (float) (i + 1)) / k ); + fflush( stdout ); + } + + if( t == time( NULL ) ) + t--; + + fclose( f ); + return( 0 ); +} + +#endif + +#endif diff --git a/package/utils/px5g/src/library/rsa.c b/package/utils/px5g/src/library/rsa.c new file mode 100644 index 0000000000..131b6c6c9c --- /dev/null +++ b/package/utils/px5g/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/src/library/sha1.c b/package/utils/px5g/src/library/sha1.c new file mode 100644 index 0000000000..54a4416f31 --- /dev/null +++ b/package/utils/px5g/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/src/library/timing.c b/package/utils/px5g/src/library/timing.c new file mode 100644 index 0000000000..6b7ab740e1 --- /dev/null +++ b/package/utils/px5g/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/src/library/x509write.c b/package/utils/px5g/src/library/x509write.c new file mode 100644 index 0000000000..fabee20ea6 --- /dev/null +++ b/package/utils/px5g/src/library/x509write.c @@ -0,0 +1,1139 @@ +/* + * 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 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 + */ + srand((unsigned int) time(NULL)); + serial = rand(); + 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/src/polarssl/base64.h b/package/utils/px5g/src/polarssl/base64.h new file mode 100644 index 0000000000..c48267b1b5 --- /dev/null +++ b/package/utils/px5g/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/src/polarssl/bignum.h b/package/utils/px5g/src/polarssl/bignum.h new file mode 100644 index 0000000000..c667303329 --- /dev/null +++ b/package/utils/px5g/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/src/polarssl/bn_mul.h b/package/utils/px5g/src/polarssl/bn_mul.h new file mode 100644 index 0000000000..f6d34da58a --- /dev/null +++ b/package/utils/px5g/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/src/polarssl/config.h b/package/utils/px5g/src/polarssl/config.h new file mode 100644 index 0000000000..ad3f9a7f39 --- /dev/null +++ b/package/utils/px5g/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/src/polarssl/havege.h b/package/utils/px5g/src/polarssl/havege.h new file mode 100644 index 0000000000..c27cecac0f --- /dev/null +++ b/package/utils/px5g/src/polarssl/havege.h @@ -0,0 +1,75 @@ +/** + * \file havege.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_HAVEGE_H +#define POLARSSL_HAVEGE_H + +#define COLLECT_SIZE 1024 + +/** + * \brief HAVEGE state structure + */ +typedef struct +{ + int PT1, PT2, offset[2]; + int pool[COLLECT_SIZE]; + int WALK[8192]; +} +havege_state; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief HAVEGE initialization + * + * \param hs HAVEGE state to be initialized + */ +void havege_init( havege_state *hs ); + +/** + * \brief HAVEGE rand function + * + * \param rng_st points to an HAVEGE state + * + * \return A random int + */ +int havege_rand( void *p_rng ); + +#ifdef __cplusplus +} +#endif + +#endif /* havege.h */ diff --git a/package/utils/px5g/src/polarssl/rsa.h b/package/utils/px5g/src/polarssl/rsa.h new file mode 100644 index 0000000000..b31dc2f144 --- /dev/null +++ b/package/utils/px5g/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/src/polarssl/sha1.h b/package/utils/px5g/src/polarssl/sha1.h new file mode 100644 index 0000000000..3ca7dc3195 --- /dev/null +++ b/package/utils/px5g/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/src/polarssl/timing.h b/package/utils/px5g/src/polarssl/timing.h new file mode 100644 index 0000000000..62d627f61b --- /dev/null +++ b/package/utils/px5g/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/src/polarssl/x509.h b/package/utils/px5g/src/polarssl/x509.h new file mode 100644 index 0000000000..908a1dbf51 --- /dev/null +++ b/package/utils/px5g/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/src/px5g.c b/package/utils/px5g/src/px5g.c new file mode 100644 index 0000000000..2b3e78585c --- /dev/null +++ b/package/utils/px5g/src/px5g.c @@ -0,0 +1,197 @@ +/* + * 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 "polarssl/havege.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" + +int rsakey(char **arg) { + havege_state hs; + 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); + } + + havege_init(&hs); + rsa_init(&rsa, RSA_PKCS_V15, 0, havege_rand, &hs); + + 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) { + havege_state hs; + 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++; + } + + havege_init(&hs); + rsa_init(&rsa, RSA_PKCS_V15, 0, havege_rand, &hs); + 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; + 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[]) { + 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/robocfg/Makefile b/package/utils/robocfg/Makefile new file mode 100644 index 0000000000..4bc72f51db --- /dev/null +++ b/package/utils/robocfg/Makefile @@ -0,0 +1,39 @@ +# +# 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:=robocfg +PKG_VERSION:=0.01 +PKG_RELEASE:=1 + +PKG_BUILD_DIR:=$(BUILD_DIR)/robocfg + +include $(INCLUDE_DIR)/package.mk + +define Package/robocfg + SECTION:=utils + CATEGORY:=Utilities + TITLE:=BCM5325E/536x switch configuration utility +endef + +define Package/robocfg/description + This package contains an utility for configuring the Broadcom BCM5325E/536x + based switches. +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Package/robocfg/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/robocfg $(1)/sbin/ +endef + +$(eval $(call BuildPackage,robocfg)) diff --git a/package/utils/robocfg/src/Makefile b/package/utils/robocfg/src/Makefile new file mode 100644 index 0000000000..e11acb020a --- /dev/null +++ b/package/utils/robocfg/src/Makefile @@ -0,0 +1,11 @@ + +all: robocfg + +%.o: %.c + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $^ + +robocfg: robocfg.o + $(CC) -o $@ $^ + +clean: + rm -f *.o robocfg diff --git a/package/utils/robocfg/src/etc53xx.h b/package/utils/robocfg/src/etc53xx.h new file mode 100644 index 0000000000..d5b1310cb6 --- /dev/null +++ b/package/utils/robocfg/src/etc53xx.h @@ -0,0 +1,619 @@ +/* + * Broadcom Home Gateway Reference Design + * BCM53xx Register definitions + * + * Copyright 2004, Broadcom Corporation + * 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 __BCM535M_H_ +#define __BCM535M_H_ + +/* ROBO embedded device type */ +#define ROBO_DEV_5380 1 +#define ROBO_DEV_5365 2 +#define ROBO_DEV_5350 3 + +/* BCM5325m GLOBAL PAGE REGISTER MAP */ +#ifndef _CFE_ +#pragma pack(1) +#endif + +/* BCM5325m Serial Management Port (SMP) Page offsets */ +#define ROBO_CTRL_PAGE 0x00 /* Control registers */ +#define ROBO_STAT_PAGE 0x01 /* Status register */ +#define ROBO_MGMT_PAGE 0x02 /* Management Mode registers */ +#define ROBO_MIB_AC_PAGE 0x03 /* MIB Autocast registers */ +#define ROBO_ARLCTRL_PAGE 0x04 /* ARL Control Registers */ +#define ROBO_ARLIO_PAGE 0x05 /* ARL Access Registers */ +#define ROBO_FRAMEBUF_PAGE 0x06 /* Management frame access registers */ +#define ROBO_MEM_ACCESS_PAGE 0x08 /* Memory access registers */ + +/* PHY Registers */ +#define ROBO_PORT0_MII_PAGE 0x10 /* Port 0 MII Registers */ +#define ROBO_PORT1_MII_PAGE 0x11 /* Port 1 MII Registers */ +#define ROBO_PORT2_MII_PAGE 0x12 /* Port 2 MII Registers */ +#define ROBO_PORT3_MII_PAGE 0x13 /* Port 3 MII Registers */ +#define ROBO_PORT4_MII_PAGE 0x14 /* Port 4 MII Registers */ +/* (start) registers only for BCM5380 */ +#define ROBO_PORT5_MII_PAGE 0x15 /* Port 5 MII Registers */ +#define ROBO_PORT6_MII_PAGE 0x16 /* Port 6 MII Registers */ +#define ROBO_PORT7_MII_PAGE 0x17 /* Port 7 MII Registers */ +/* (end) registers only for BCM5380 */ +#define ROBO_IM_PORT_PAGE 0x18 /* Inverse MII Port (to EMAC) */ +#define ROBO_ALL_PORT_PAGE 0x19 /* All ports MII Registers (broadcast)*/ + +/* MAC Statistics registers */ +#define ROBO_PORT0_MIB_PAGE 0x20 /* Port 0 10/100 MIB Statistics */ +#define ROBO_PORT1_MIB_PAGE 0x21 /* Port 1 10/100 MIB Statistics */ +#define ROBO_PORT2_MIB_PAGE 0x22 /* Port 2 10/100 MIB Statistics */ +#define ROBO_PORT3_MIB_PAGE 0x23 /* Port 3 10/100 MIB Statistics */ +#define ROBO_PORT4_MIB_PAGE 0x24 /* Port 4 10/100 MIB Statistics */ +/* (start) registers only for BCM5380 */ +#define ROBO_PORT5_MIB_PAGE 0x25 /* Port 5 10/100 MIB Statistics */ +#define ROBO_PORT6_MIB_PAGE 0x26 /* Port 6 10/100 MIB Statistics */ +#define ROBO_PORT7_MIB_PAGE 0x27 /* Port 7 10/100 MIB Statistics */ +/* (end) registers only for BCM5380 */ +#define ROBO_IM_PORT_MIB_PAGE 0x28 /* Inverse MII Port MIB Statistics */ + +/* Quality of Service (QoS) Registers */ +#define ROBO_QOS_PAGE 0x30 /* QoS Registers */ + +/* VLAN Registers */ +#define ROBO_VLAN_PAGE 0x34 /* VLAN Registers */ + +/* Note SPI Data/IO Registers not used */ +#define ROBO_SPI_DATA_IO_0_PAGE 0xf0 /* SPI Data I/O 0 */ +#define ROBO_SPI_DATA_IO_1_PAGE 0xf1 /* SPI Data I/O 1 */ +#define ROBO_SPI_DATA_IO_2_PAGE 0xf2 /* SPI Data I/O 2 */ +#define ROBO_SPI_DATA_IO_3_PAGE 0xf3 /* SPI Data I/O 3 */ +#define ROBO_SPI_DATA_IO_4_PAGE 0xf4 /* SPI Data I/O 4 */ +#define ROBO_SPI_DATA_IO_5_PAGE 0xf5 /* SPI Data I/O 5 */ +#define ROBO_SPI_DATA_IO_6_PAGE 0xf6 /* SPI Data I/O 6 */ +#define ROBO_SPI_DATA_IO_7_PAGE 0xf7 /* SPI Data I/O 7 */ + +#define ROBO_SPI_STATUS_PAGE 0xfe /* SPI Status Registers */ +#define ROBO_PAGE_PAGE 0xff /* Page Registers */ + + +/* BCM5325m CONTROL PAGE (0x00) REGISTER MAP : 8bit (byte) registers */ +typedef struct _ROBO_PORT_CTRL_STRUC +{ + unsigned char rx_disable:1; /* rx disable */ + unsigned char tx_disable:1; /* tx disable */ + unsigned char rsvd:3; /* reserved */ + unsigned char stp_state:3; /* spanning tree state */ +} ROBO_PORT_CTRL_STRUC; + +#define ROBO_PORT0_CTRL 0x00 /* 10/100 Port 0 Control */ +#define ROBO_PORT1_CTRL 0x01 /* 10/100 Port 1 Control */ +#define ROBO_PORT2_CTRL 0x02 /* 10/100 Port 2 Control */ +#define ROBO_PORT3_CTRL 0x03 /* 10/100 Port 3 Control */ +#define ROBO_PORT4_CTRL 0x04 /* 10/100 Port 4 Control */ +/* (start) registers only for BCM5380 */ +#define ROBO_PORT5_CTRL 0x05 /* 10/100 Port 5 Control */ +#define ROBO_PORT6_CTRL 0x06 /* 10/100 Port 6 Control */ +#define ROBO_PORT7_CTRL 0x07 /* 10/100 Port 7 Control */ +/* (end) registers only for BCM5380 */ +#define ROBO_IM_PORT_CTRL 0x08 /* 10/100 Port 8 Control */ +#define ROBO_SMP_CTRL 0x0a /* SMP Control register */ +#define ROBO_SWITCH_MODE 0x0b /* Switch Mode Control */ +#define ROBO_PORT_OVERRIDE_CTRL 0x0e /* Port state override */ +#define ROBO_PORT_OVERRIDE_RVMII (1<<4) /* Bit 4 enables RvMII */ +#define ROBO_PD_MODE_CTRL 0x0f /* Power-down mode control */ +#define ROBO_IP_MULTICAST_CTRL 0x21 /* IP Multicast control */ + +/* BCM5325m STATUS PAGE (0x01) REGISTER MAP : 16bit/48bit registers */ +#define ROBO_HALF_DUPLEX 0 +#define ROBO_FULL_DUPLEX 1 + +#define ROBO_LINK_STAT_SUMMARY 0x00 /* Link Status Summary: 16bit */ +#define ROBO_LINK_STAT_CHANGE 0x02 /* Link Status Change: 16bit */ +#define ROBO_SPEED_STAT_SUMMARY 0x04 /* Port Speed Summary: 16bit*/ +#define ROBO_DUPLEX_STAT_SUMMARY 0x06 /* Duplex Status Summary: 16bit */ +#define ROBO_PAUSE_STAT_SUMMARY 0x08 /* PAUSE Status Summary: 16bit */ +#define ROBO_SOURCE_ADDR_CHANGE 0x0C /* Source Address Change: 16bit */ +#define ROBO_LSA_PORT0 0x10 /* Last Source Addr, Port 0: 48bits*/ +#define ROBO_LSA_PORT1 0x16 /* Last Source Addr, Port 1: 48bits*/ +#define ROBO_LSA_PORT2 0x1c /* Last Source Addr, Port 2: 48bits*/ +#define ROBO_LSA_PORT3 0x22 /* Last Source Addr, Port 3: 48bits*/ +#define ROBO_LSA_PORT4 0x28 /* Last Source Addr, Port 4: 48bits*/ +#define ROBO_LSA_IM_PORT 0x40 /* Last Source Addr, IM Port: 48bits*/ + +/* BCM5325m MANAGEMENT MODE REGISTERS (0x02) REGISTER MAP: 8/48 bit regs*/ +typedef struct _ROBO_GLOBAL_CONFIG_STRUC +{ + unsigned char resetMIB:1; /* reset MIB counters */ + unsigned char rxBPDU:1; /* receive BDPU enable */ + unsigned char rsvd1:2; /* reserved */ + unsigned char MIBacHdrCtrl:1; /* MIB autocast header control */ + unsigned char MIBac:1; /* MIB autocast enable */ + unsigned char frameMgmtPort:2; /* frame management port */ +} ROBO_GLOBAL_CONFIG_STRUC; +#define ROBO_GLOBAL_CONFIG 0x00 /* Global Management Config: 8bit*/ +#define ROBO_MGMT_PORT_ID 0x02 /* Management Port ID: 8bit*/ +#define ROBO_RMON_MIB_STEER 0x04 /* RMON Mib Steering: 16bit */ +#define ROBO_MIB_MODE_SELECT 0x04 /* MIB Mode select: 16bit (BCM5350) */ +#define ROBO_AGE_TIMER_CTRL 0x06 /* Age time control: 32bit */ +#define ROBO_MIRROR_CAP_CTRL 0x10 /* Mirror Capture : 16bit */ +#define ROBO_MIRROR_ING_CTRL 0x12 /* Mirror Ingress Control: 16bit */ +#define ROBO_MIRROR_ING_DIV_CTRL 0x14 /* Mirror Ingress Divider: 16bit */ +#define ROBO_MIRROR_ING_MAC_ADDR 0x16 /* Ingress Mirror MAC Addr: 48bit*/ +#define ROBO_MIRROR_EGR_CTRL 0x1c /* Mirror Egress Control: 16bit */ +#define ROBO_MIRROR_EGR_DIV_CTRL 0x1e /* Mirror Egress Divider: 16bit */ +#define ROBO_MIRROR_EGR_MAC_ADDR 0x20 /* Egress Mirror MAC Addr: 48bit*/ + +/* BCM5325m MIB AUTOCAST REGISTERS (0x03) REGISTER MAP: 8/16/48 bit regs */ +#define ROBO_MIB_AC_PORT 0x00 /* MIB Autocast Port: 16bit */ +#define ROBO_MIB_AC_HDR_PTR 0x02 /* MIB Autocast Header pointer:16bit*/ +#define ROBO_MIB_AC_HDR_LEN 0x04 /* MIB Autocast Header Len: 16bit */ +#define ROBO_MIB_AC_DA 0x06 /* MIB Autocast DA: 48bit */ +#define ROBO_MIB_AC_SA 0x0c /* MIB Autocast SA: 48bit */ +#define ROBO_MIB_AC_TYPE 0x12 /* MIB Autocast Type: 16bit */ +#define ROBO_MIB_AC_RATE 0x14 /* MIB Autocast Rate: 8bit */ +#define ROBO_GET_AC_RATE(secs) ((secs)*10) +#define ROBO_AC_RATE_MAX 0xff +#define ROBO_AC_RATE_DEFAULT 0x64 /* 10 secs */ +typedef struct _ROBO_MIB_AC_STRUCT +{ + unsigned char opcode:4; /* Tx MIB Autocast opcode */ + unsigned char portno:4; /* zero-based port no. */ + unsigned char portstate:8; /* port state */ + unsigned long long TxOctets; + unsigned int TxDropPkts; + unsigned int rsvd; + unsigned int TxBroadcastPkts; + unsigned int TxMulticastPkts; + unsigned int TxUnicastPkts; + unsigned int TxCollisions; + unsigned int TxSingleCollision; + unsigned int TxMultiCollision; + unsigned int TxDeferredTransmit; + unsigned int TxLateCollision; + unsigned int TxExcessiveCollision; + unsigned int TxFrameInDiscards; + unsigned int TxPausePkts; + unsigned int rsvd1[2]; + unsigned long long RxOctets; + unsigned int RxUndersizePkts; + unsigned int RxPausePkts; + unsigned int RxPkts64Octets; + unsigned int RxPkts64to127Octets; + unsigned int RxPkts128to255Octets; + unsigned int RxPkts256to511Octets; + unsigned int RxPkts512to1023Octets; + unsigned int RxPkts1024to1522Octets; + unsigned int RxOversizePkts; + unsigned int RxJabbers; + unsigned int RxAlignmentErrors; + unsigned int RxFCSErrors; + unsigned long long RxGoodOctets; + unsigned int RxDropPkts; + unsigned int RxUnicastPkts; + unsigned int RxMulticastPkts; + unsigned int RxBroadcastPkts; + unsigned int RxSAChanges; + unsigned int RxFragments; + unsigned int RxExcessSizeDisc; + unsigned int RxSymbolError; +} ROBO_MIB_AC_STRUCT; + +/* BCM5325m ARL CONTROL REGISTERS (0x04) REGISTER MAP: 8/16/48/64 bit regs */ +#define ROBO_ARL_CONFIG 0x00 /* ARL Global Configuration: 8bit*/ +#define ROBO_BPDU_MC_ADDR_REG 0x04 /* BPDU Multicast Address Reg:64bit*/ +#define ROBO_MULTIPORT_ADDR_1 0x10 /* Multiport Address 1: 48 bits*/ +#define ROBO_MULTIPORT_VECTOR_1 0x16 /* Multiport Vector 1: 16 bits */ +#define ROBO_MULTIPORT_ADDR_2 0x20 /* Multiport Address 2: 48 bits*/ +#define ROBO_MULTIPORT_VECTOR_2 0x26 /* Multiport Vector 2: 16 bits */ +#define ROBO_SECURE_SRC_PORT_MASK 0x30 /* Secure Source Port Mask: 16 bits*/ +#define ROBO_SECURE_DST_PORT_MASK 0x32 /* Secure Dest Port Mask: 16 bits */ + + +/* BCM5325m ARL IO REGISTERS (0x05) REGISTER MAP: 8/16/48/64 bit regs */ +#define ARL_TABLE_WRITE 0 /* for read/write state in control reg */ +#define ARL_TABLE_READ 1 /* for read/write state in control reg */ +#ifdef BCM5380 +#define ARL_VID_BYTES 2 /* number of bytes for VID */ +#else +#define ARL_VID_BYTES 1 /* number of bytes for VID */ +#endif +typedef struct _ROBO_ARL_RW_CTRL_STRUC +{ + unsigned char ARLrw:1; /* ARL read/write (1=read) */ + unsigned char rsvd:6; /* reserved */ + unsigned char ARLStart:1; /* ARL start/done (1=start) */ +} ROBO_ARL_RW_CTRL_STRUC; +typedef struct _ROBO_ARL_SEARCH_CTRL_STRUC +{ + unsigned char valid:1; /* ARL search result valid */ + unsigned char rsvd:6; /* reserved */ + unsigned char ARLStart:1; /* ARL start/done (1=start) */ +} ROBO_ARL_SEARCH_CTRL_STRUC; +typedef struct _ROBO_ARL_ENTRY_CTRL_STRUC +{ + unsigned char portID:4; /* port id */ + unsigned char chipID:2; /* chip id */ + unsigned char rsvd:5; /* reserved */ + unsigned char prio:2; /* priority */ + unsigned char age:1; /* age */ + unsigned char staticEn:1; /* static */ + unsigned char valid:1; /* valid */ +} ROBO_ARL_ENTRY_CTRL_STRUC; +typedef struct _ROBO_ARL_SEARCH_RESULT_CTRL_STRUC +{ + unsigned char portID:4; /* port id */ + unsigned char rsvd:1; /* reserved */ + unsigned char vid:8; /* vlan id */ + unsigned char age:1; /* age */ + unsigned char staticEn:1; /* static */ + unsigned char valid:1; /* valid */ +} ROBO_ARL_SEARCH_RESULT_CTRL_STRUC; +typedef struct _ROBO_ARL_ENTRY_MAC_STRUC +{ + unsigned char macBytes[6]; /* MAC address */ +} ROBO_ARL_ENTRY_MAC_STRUC; + +typedef struct _ROBO_ARL_ENTRY_STRUC +{ + ROBO_ARL_ENTRY_MAC_STRUC mac; /* MAC address */ + ROBO_ARL_ENTRY_CTRL_STRUC ctrl; /* control bits */ +} ROBO_ARL_ENTRY_STRUC; + +typedef struct _ROBO_ARL_SEARCH_RESULT_STRUC +{ + ROBO_ARL_ENTRY_MAC_STRUC mac; /* MAC address */ + ROBO_ARL_SEARCH_RESULT_CTRL_STRUC ctrl; /* control bits */ +} ROBO_ARL_SEARCH_RESULT_STRUC; + +/* multicast versions of ARL entry structs */ +typedef struct _ROBO_ARL_ENTRY_MCAST_CTRL_STRUC +{ + unsigned int portMask:12;/* multicast port mask */ + unsigned char prio:1; /* priority */ + unsigned char gigPort:1; /* gigabit port 1 mask */ + unsigned char staticEn:1; /* static */ + unsigned char valid:1; /* valid */ +} ROBO_ARL_ENTRY_MCAST_CTRL_STRUC; +typedef struct _ROBO_ARL_SEARCH_RESULT_MCAST_CTRL_STRUC +{ + unsigned int portMask:13; /* multicast port mask */ + unsigned char age:1; /* age */ + unsigned char staticEn:1; /* static */ + unsigned char valid:1; /* valid */ +} ROBO_ARL_SEARCH_RESULT_MCAST_CTRL_STRUC; +/* BCM5350 extension register */ +typedef struct _ROBO_ARL_SEARCH_RESULT_EXTENSION +{ + unsigned int prio:2; /* priority */ + unsigned int portMask:1; /* MSB (MII) of port mask for multicast */ + unsigned int reserved:5; +} ROBO_ARL_SEARCH_RESULT_EXTENSION; + +typedef struct _ROBO_ARL_ENTRY_MCAST_STRUC +{ + ROBO_ARL_ENTRY_MAC_STRUC mac; /* MAC address */ + ROBO_ARL_ENTRY_MCAST_CTRL_STRUC ctrl; /* control bits */ +} ROBO_ARL_ENTRY_MCAST_STRUC; +typedef struct _ROBO_ARL_SEARCH_RESULT_MCAST_STRUC +{ + ROBO_ARL_ENTRY_MAC_STRUC mac; /* MAC address */ + ROBO_ARL_SEARCH_RESULT_MCAST_CTRL_STRUC ctrl; /* control bits */ +} ROBO_ARL_SEARCH_RESULT_MCAST_STRUC; + +#define ROBO_ARL_RW_CTRL 0x00 /* ARL Read/Write Control : 8bit */ +#define ROBO_ARL_MAC_ADDR_IDX 0x02 /* MAC Address Index: 48bit */ +#define ROBO_ARL_VID_TABLE_IDX 0x08 /* VID Table Address Index: 8bit */ +#define ROBO_ARL_ENTRY0 0x10 /* ARL Entry 0 : 64 bit */ +#define ROBO_ARL_ENTRY1 0x18 /* ARL Entry 1 : 64 bit */ +#define ROBO_ARL_SEARCH_CTRL 0x20 /* ARL Search Control: 8bit */ +#define ROBO_ARL_SEARCH_ADDR 0x22 /* ARL Search Address: 16bit */ +#define ROBO_ARL_SEARCH_RESULT 0x24 /* ARL Search Result: 64bit */ +#define ROBO_ARL_SEARCH_RESULT_EXT 0x2c /* ARL Search Result Extension (5350): 8bit */ +#define ROBO_ARL_VID_ENTRY0 0x30 /* ARL VID Entry 0: 64bit */ +#define ROBO_ARL_VID_ENTRY1 0x32 /* ARL VID Entry 1: 64bit */ + +/* BCM5325m MANAGEMENT FRAME REGISTERS (0x6) REGISTER MAP: 8/16 bit regs */ +#define ROBO_MGMT_FRAME_RD_DATA 0x00 /* Management Frame Read Data :8bit*/ +#define ROBO_MGMT_FRAME_WR_DATA 0x01 /* Management Frame Write Data:8bit*/ +#define ROBO_MGMT_FRAME_WR_CTRL 0x02 /* Write Control: 16bit */ +#define ROBO_MGMT_FRAME_RD_STAT 0x04 /* Read Status: 16bit */ + +/* BCM5325m MEMORY ACCESS REGISTERS (Page 0x08) REGISTER MAP: 32 bit regs */ +#define MEM_TABLE_READ 1 /* for read/write state in mem access reg */ +#define MEM_TABLE_WRITE 0 /* for read/write state in mem access reg */ +#define MEM_TABLE_ACCESS_START 1 /* for mem access read/write start */ +#define MEM_TABLE_ACCESS_DONE 0 /* for mem access read/write done */ +#define VLAN_TABLE_ADDR 0x3800 /* BCM5380 only */ +#ifdef BCM5380 +#define NUM_ARL_TABLE_ENTRIES 4096 /* number of entries in ARL table */ +#define NUM_VLAN_TABLE_ENTRIES 2048 /* number of entries in VLAN table */ +#define ARL_TABLE_ADDR 0 /* offset of ARL table start */ +#else +#define NUM_ARL_TABLE_ENTRIES 2048 /* number of entries in ARL table */ +#define NUM_VLAN_TABLE_ENTRIES 256 /* number of entries in VLAN table */ +#define ARL_TABLE_ADDR 0x3800 /* offset of ARL table start */ +/* corresponding values for 5350 */ +#define NUM_ARL_TABLE_ENTRIES_5350 1024 /* number of entries in ARL table (5350) */ +#define NUM_VLAN_TABLE_ENTRIES_5350 16 /* number of entries in VLAN table */ +#define ARL_TABLE_ADDR_5350 0x1c00 /* offset of ARL table start (5350) */ +#endif +typedef struct _ROBO_MEM_ACCESS_CTRL_STRUC +{ + unsigned int memAddr:14; /* 64-bit memory address */ + unsigned char rsvd:4; /* reserved */ + unsigned char readEn:1; /* read enable (0 == write) */ + unsigned char startDone:1;/* memory access start/done */ + unsigned int rsvd1:12; /* reserved */ +} ROBO_MEM_ACCESS_CTRL_STRUC; +typedef struct _ROBO_MEM_ACCESS_DATA_STRUC +{ + unsigned int memData[2]; /* 64-bit data */ + unsigned short rsvd; /* reserved */ +} ROBO_MEM_ACCESS_DATA_STRUC; + +#ifdef BCM5380 +typedef struct _ROBO_ARL_TABLE_DATA_STRUC +{ + unsigned char MACaddr[6]; /* MAC addr */ + unsigned int portID:4; /* port ID */ + unsigned int chipID:2; /* chip ID */ + unsigned int rsvd:6; /* reserved */ + unsigned int highPrio:1; /* high priority address */ + unsigned int age:1; /* entry accessed/learned since ageing process */ + unsigned int staticAddr:1;/* entry is static */ + unsigned int valid:1; /* entry is valid */ + unsigned int vid:12; /* vlan id */ + unsigned int rsvd2:4; /* reserved */ +} ROBO_ARL_TABLE_DATA_STRUC; +#else +typedef struct _ROBO_ARL_TABLE_DATA_STRUC +{ + unsigned char MACaddr[6]; /* MAC addr */ + unsigned int portID:4; /* port ID */ + unsigned int chipID:2; /* chip ID */ + unsigned int rsvd:7; /* reserved */ + unsigned int age:1; /* entry accessed/learned since ageing process */ + unsigned int staticAddr:1;/* entry is static */ + unsigned int valid:1; /* entry is valid */ +} ROBO_ARL_TABLE_DATA_STRUC; +#endif + +/* multicast format*/ +typedef struct _ROBO_ARL_TABLE_MCAST_DATA_STRUC +{ + unsigned char MACaddr[6]; /* MAC addr */ + unsigned int portMask:12;/* multicast port mask */ + unsigned char prio:1; /* priority */ + unsigned char gigPort:1; /* gigabit port 1 mask */ + unsigned char staticEn:1; /* static */ + unsigned char valid:1; /* valid */ + unsigned int vid:12; /* vlan id */ + unsigned int rsvd2:4; /* reserved */ +} ROBO_ARL_TABLE_MCAST_DATA_STRUC; +#define ROBO_MEM_ACCESS_CTRL 0x00 /* Memory Read/Write Control :32bit*/ +#define ROBO_MEM_ACCESS_DATA 0x04 /* Memory Read/Write Data:64bit*/ + +/* BCM5325m SWITCH PORT (0x10-18) REGISTER MAP: 8/16 bit regs */ +typedef struct _ROBO_MII_CTRL_STRUC +{ + unsigned char rsvd:8; /* reserved */ + unsigned char duplex:1; /* duplex mode */ + unsigned char restartAN:1;/* restart auto-negotiation */ + unsigned char rsvd1:1; /* reserved */ + unsigned char powerDown:1;/* power down */ + unsigned char ANenable:1; /* auto-negotiation enable */ + unsigned char speed:1; /* forced speed selection */ + unsigned char loopback:1; /* loopback */ + unsigned char reset:1; /* reset */ +} ROBO_MII_CTRL_STRUC; +typedef struct _ROBO_MII_AN_ADVERT_STRUC +{ + unsigned char selector:5; /* advertise selector field */ + unsigned char T10BaseT:1; /* advertise 10BaseT */ + unsigned char T10BaseTFull:1; /* advertise 10BaseT, full duplex */ + unsigned char T100BaseX:1; /* advertise 100BaseX */ + unsigned char T100BaseXFull:1;/* advertise 100BaseX full duplex */ + unsigned char noT4:1; /* do not advertise T4 */ + unsigned char pause:1; /* advertise pause for full duplex */ + unsigned char rsvd:2; /* reserved */ + unsigned char remoteFault:1; /* transmit remote fault */ + unsigned char rsvd1:1; /* reserved */ + unsigned char nextPage:1; /* nex page operation supported */ +} ROBO_MII_AN_ADVERT_STRUC; +#define ROBO_MII_CTRL 0x00 /* Port MII Control */ +#define ROBO_MII_STAT 0x02 /* Port MII Status */ +/* Fields of link status register */ +#define ROBO_MII_STAT_JABBER (1<<1) /* Jabber detected */ +#define ROBO_MII_STAT_LINK (1<<2) /* Link status */ + +#define ROBO_MII_PHYID_HI 0x04 /* Port PHY ID High */ +#define ROBO_MII_PHYID_LO 0x06 /* Port PHY ID Low */ +#define ROBO_MII_ANA_REG 0x08 /* MII Auto-Neg Advertisement */ +#define ROBO_MII_ANP_REG 0x0a /* MII Auto-Neg Partner Ability */ +#define ROBO_MII_AN_EXP_REG 0x0c /* MII Auto-Neg Expansion */ +#define ROBO_MII_AN_NP_REG 0x0e /* MII next page */ +#define ROBO_MII_ANP_NP_REG 0x10 /* MII Partner next page */ +#define ROBO_MII_100BX_AUX_CTRL 0x20 /* 100BASE-X Auxiliary Control */ +#define ROBO_MII_100BX_AUX_STAT 0x22 /* 100BASE-X Auxiliary Status */ +#define ROBO_MII_100BX_RCV_ERR_CTR 0x24 /* 100BASE-X Receive Error Ctr */ +#define ROBO_MII_100BX_RCV_FS_ERR 0x26 /* 100BASE-X Rcv False Sense Ctr */ +#define ROBO_MII_AUX_CTRL 0x30 /* Auxiliary Control/Status */ +/* Fields of Auxiliary control register */ +#define ROBO_MII_AUX_CTRL_FD (1<<0) /* Full duplex link detected*/ +#define ROBO_MII_AUX_CTRL_SP100 (1<<1) /* Speed 100 indication */ +#define ROBO_MII_AUX_STATUS 0x32 /* Aux Status Summary */ +#define ROBO_MII_CONN_STATUS 0x34 /* Aux Connection Status */ +#define ROBO_MII_AUX_MODE2 0x36 /* Aux Mode 2 */ +#define ROBO_MII_AUX_ERR_STATUS 0x38 /* Aux Error and General Status */ +#define ROBO_MII_AUX_MULTI_PHY 0x3c /* Aux Multiple PHY Register*/ +#define ROBO_MII_BROADCOM_TEST 0x3e /* Broadcom Test Register */ + + +/* BCM5325m PORT MIB REGISTERS (Pages 0x20-0x24,0x28) REGISTER MAP: 64/32 */ +/* Tranmit Statistics */ +#define ROBO_MIB_TX_OCTETS 0x00 /* 64b: TxOctets */ +#define ROBO_MIB_TX_DROP_PKTS 0x08 /* 32b: TxDropPkts */ +#define ROBO_MIB_TX_BC_PKTS 0x10 /* 32b: TxBroadcastPkts */ +#define ROBO_MIB_TX_MC_PKTS 0x14 /* 32b: TxMulticastPkts */ +#define ROBO_MIB_TX_UC_PKTS 0x18 /* 32b: TxUnicastPkts */ +#define ROBO_MIB_TX_COLLISIONS 0x1c /* 32b: TxCollisions */ +#define ROBO_MIB_TX_SINGLE_COLLISIONS 0x20 /* 32b: TxSingleCollision */ +#define ROBO_MIB_TX_MULTI_COLLISIONS 0x24 /* 32b: TxMultiCollision */ +#define ROBO_MIB_TX_DEFER_TX 0x28 /* 32b: TxDeferred Transmit */ +#define ROBO_MIB_TX_LATE_COLLISIONS 0x2c /* 32b: TxLateCollision */ +#define ROBO_MIB_EXCESS_COLLISIONS 0x30 /* 32b: TxExcessiveCollision*/ +#define ROBO_MIB_FRAME_IN_DISCARDS 0x34 /* 32b: TxFrameInDiscards */ +#define ROBO_MIB_TX_PAUSE_PKTS 0x38 /* 32b: TxPausePkts */ + +/* Receive Statistics */ +#define ROBO_MIB_RX_OCTETS 0x44 /* 64b: RxOctets */ +#define ROBO_MIB_RX_UNDER_SIZE_PKTS 0x4c /* 32b: RxUndersizePkts(runts)*/ +#define ROBO_MIB_RX_PAUSE_PKTS 0x50 /* 32b: RxPausePkts */ +#define ROBO_MIB_RX_PKTS_64 0x54 /* 32b: RxPkts64Octets */ +#define ROBO_MIB_RX_PKTS_65_TO_127 0x58 /* 32b: RxPkts64to127Octets*/ +#define ROBO_MIB_RX_PKTS_128_TO_255 0x5c /* 32b: RxPkts128to255Octets*/ +#define ROBO_MIB_RX_PKTS_256_TO_511 0x60 /* 32b: RxPkts256to511Octets*/ +#define ROBO_MIB_RX_PKTS_512_TO_1023 0x64 /* 32b: RxPkts512to1023Octets*/ +#define ROBO_MIB_RX_PKTS_1024_TO_1522 0x68 /* 32b: RxPkts1024to1522Octets*/ +#define ROBO_MIB_RX_OVER_SIZE_PKTS 0x6c /* 32b: RxOversizePkts*/ +#define ROBO_MIB_RX_JABBERS 0x70 /* 32b: RxJabbers*/ +#define ROBO_MIB_RX_ALIGNMENT_ERRORS 0x74 /* 32b: RxAlignmentErrors*/ +#define ROBO_MIB_RX_FCS_ERRORS 0x78 /* 32b: RxFCSErrors */ +#define ROBO_MIB_RX_GOOD_OCTETS 0x7c /* 32b: RxGoodOctets */ +#define ROBO_MIB_RX_DROP_PKTS 0x84 /* 32b: RxDropPkts */ +#define ROBO_MIB_RX_UC_PKTS 0x88 /* 32b: RxUnicastPkts */ +#define ROBO_MIB_RX_MC_PKTS 0x8c /* 32b: RxMulticastPkts */ +#define ROBO_MIB_RX_BC_PKTS 0x90 /* 32b: RxBroadcastPkts */ +#define ROBO_MIB_RX_SA_CHANGES 0x94 /* 32b: RxSAChanges */ +#define ROBO_MIB_RX_FRAGMENTS 0x98 /* 32b: RxFragments */ +#define ROBO_MIB_RX_EXCESS_SZ_DISC 0x9c /* 32b: RxExcessSizeDisc*/ +#define ROBO_MIB_RX_SYMBOL_ERROR 0xa0 /* 32b: RxSymbolError */ + +/* BCM5350 MIB Statistics */ +/* Group 0 */ +#define ROBO_MIB_TX_GOOD_PKTS 0x00 /* 16b: TxGoodPkts */ +#define ROBO_MIB_TX_UNICAST_PKTS 0x02 /* 16b: TxUnicastPkts */ +#define ROBO_MIB_RX_GOOD_PKTS 0x04 /* 16b: RxGoodPkts */ +#define ROBO_MIB_RX_GOOD_UNICAST_PKTS 0x06 /* 16b: RxGoodUnicastPkts */ +/* Group 1 */ +#define ROBO_MIB_TX_COLLISION 0x00 /* 16b: TxCollision */ +#define ROBO_MIB_TX_OCTETS_5350 0x02 /* 16b: TxOctets */ +#define ROBO_MIB_RX_FCS_ERRORS_5350 0x04 /* 16b: RxFCSErrors */ +#define ROBO_MIB_RX_GOOD_OCTETS_5350 0x06 /* 16b: RxGoodOctets */ + +/* BCM5325m QoS REGISTERS (Page 0x30) REGISTER MAP: 8/16 */ +#define ROBO_QOS_CTRL 0x00 /* 16b: QoS Control Register */ +#define ROBO_QOS_LOCAL_WEIGHT_CTRL 0x10 /* 8b: Local HQ/LQ Weight Register*/ +#define ROBO_QOS_CPU_WEIGHT_CTRL 0x12 /* 8b: CPU HQ/LQ Weight Register*/ +#define ROBO_QOS_PAUSE_ENA 0x13 /* 16b: Qos Pause Enable Register*/ +#define ROBO_QOS_PRIO_THRESHOLD 0x15 /* 8b: Priority Threshold Register*/ +#define ROBO_QOS_RESERVED 0x16 /* 8b: Qos Reserved Register */ + +/* BCM5325m VLAN REGISTERS (Page 0x34) REGISTER MAP: 8/16bit */ +typedef struct _ROBO_VLAN_CTRL0_STRUC +{ + unsigned char frameControlP:2; /* 802.1P frame control */ + unsigned char frameControlQ:2; /* 802.1Q frame control */ + unsigned char dropMissedVID:1; /* enable drop missed VID packet */ + unsigned char vidMacHash:1; /* VID_MAC hash enable */ + unsigned char vidMacCheck:1; /* VID_MAC check enable */ + unsigned char VLANen:1; /* 802.1Q VLAN enable */ +} ROBO_VLAN_CTRL0_STRUC; +#define VLAN_TABLE_WRITE 1 /* for read/write state in table access reg */ +#define VLAN_TABLE_READ 0 /* for read/write state in table access reg */ +#define VLAN_ID_HIGH_BITS 0 /* static high bits in table access reg */ +#define VLAN_ID_MAX 255 /* max VLAN id */ +#define VLAN_ID_MAX5350 15 /* max VLAN id (5350) */ +#define VLAN_ID_MASK VLAN_ID_MAX /* VLAN id mask */ +#ifdef BCM5380 +#define VLAN_UNTAG_SHIFT 13 /* for postioning untag bits in write reg */ +#define VLAN_VALID 0x4000000 /* valid bit in write reg */ +#else +#define VLAN_UNTAG_SHIFT 7 /* for postioning untag bits in write reg */ +#define VLAN_VALID 0x4000 /* valid bit in write reg */ +/* corresponding values for 5350 */ +#define VLAN_UNTAG_SHIFT_5350 6 /* for postioning untag bits in write reg */ +#define VLAN_VALID_5350 0x00100000 /* valid bit in write reg */ +#endif +typedef struct _ROBO_VLAN_TABLE_ACCESS_STRUC +{ + unsigned char VLANid:8; /* VLAN ID (low 8 bits) */ + unsigned char VLANidHi:4; /* VLAN ID (fixed upper portion) */ + unsigned char readWriteState:1; /* read/write state (write = 1) */ + volatile unsigned char readWriteEnable:1; /* table read/write enable */ + unsigned char rsvd:2; /* reserved */ +} ROBO_VLAN_TABLE_ACCESS_STRUC; +#ifdef BCM5380 +typedef struct _ROBO_VLAN_READ_WRITE_STRUC +{ + unsigned int VLANgroup:13;/* VLAN group mask */ + unsigned int VLANuntag:13;/* VLAN untag enable mask */ + unsigned char valid:1; /* valid */ + unsigned char rsvd:5; /* reserved */ +} ROBO_VLAN_READ_WRITE_STRUC; +#else +typedef struct _ROBO_VLAN_READ_WRITE_STRUC +{ + unsigned char VLANgroup:7; /* VLAN group mask */ + unsigned char VLANuntag:7; /* VLAN untag enable mask */ + unsigned char valid:1; /* valid */ + unsigned char rsvd:1; /* reserved */ +} ROBO_VLAN_READ_WRITE_STRUC; +typedef struct _ROBO_VLAN_READ_WRITE_STRUC_5350 +{ + unsigned char VLANgroup:6; /* VLAN group mask */ + unsigned char VLANuntag:6; /* VLAN untag enable mask */ + unsigned char highVID:8; /* upper bits of vid */ + unsigned char valid:1; /* valid */ + unsigned int rsvd:11; /* reserved */ +} ROBO_VLAN_READ_WRITE_STRUC_5350; +#endif +#define ROBO_VLAN_CTRL0 0x00 /* 8b: VLAN Control 0 Register */ +#define ROBO_VLAN_CTRL1 0x01 /* 8b: VLAN Control 1 Register */ +#define ROBO_VLAN_CTRL2 0x02 /* 8b: VLAN Control 2 Register */ +#define ROBO_VLAN_CTRL3 0x03 /* 8b: VLAN Control 3 Register */ +#define ROBO_VLAN_CTRL4 0x04 /* 8b: VLAN Control 4 Register */ +#define ROBO_VLAN_CTRL5 0x05 /* 8b: VLAN Control 5 Register */ +#define ROBO_VLAN_TABLE_ACCESS 0x08 /* 14b: VLAN Table Access Register */ +#define ROBO_VLAN_TABLE_ACCESS_5350 0x06 /* 14b: VLAN Table Access Register (5350) */ +#define ROBO_VLAN_WRITE 0x0a /* 15b: VLAN Write Register */ +#define ROBO_VLAN_WRITE_5350 0x08 /* 15b: VLAN Write Register (5350) */ +#define ROBO_VLAN_READ 0x0c /* 15b: VLAN Read Register */ +#define ROBO_VLAN_PORT0_DEF_TAG 0x10 /* 16b: VLAN Port 0 Default Tag Register */ +#define ROBO_VLAN_PORT1_DEF_TAG 0x12 /* 16b: VLAN Port 1 Default Tag Register */ +#define ROBO_VLAN_PORT2_DEF_TAG 0x14 /* 16b: VLAN Port 2 Default Tag Register */ +#define ROBO_VLAN_PORT3_DEF_TAG 0x16 /* 16b: VLAN Port 3 Default Tag Register */ +#define ROBO_VLAN_PORT4_DEF_TAG 0x18 /* 16b: VLAN Port 4 Default Tag Register */ +#define ROBO_VLAN_PORTMII_DEF_TAG 0x1a /* 16b: VLAN Port MII Default Tag Register */ +/* 5380 only */ +#define ROBO_VLAN_PORT5_DEF_TAG 0x1a /* 16b: VLAN Port 5 Default Tag Register */ +#define ROBO_VLAN_PORT6_DEF_TAG 0x1c /* 16b: VLAN Port 6 Default Tag Register */ +#define ROBO_VLAN_PORT7_DEF_TAG 0x1e /* 16b: VLAN Port 7 Default Tag Register */ + +/* obsolete */ +#define ROBO_VLAN_PORT0_CTRL 0x00 /* 16b: Port 0 VLAN Register */ +#define ROBO_VLAN_PORT1_CTRL 0x02 /* 16b: Port 1 VLAN Register */ +#define ROBO_VLAN_PORT2_CTRL 0x04 /* 16b: Port 2 VLAN Register */ +#define ROBO_VLAN_PORT3_CTRL 0x06 /* 16b: Port 3 VLAN Register */ +#define ROBO_VLAN_PORT4_CTRL 0x08 /* 16b: Port 4 VLAN Register */ +#define ROBO_VLAN_IM_PORT_CTRL 0x10 /* 16b: Inverse MII Port VLAN Reg */ +#define ROBO_VLAN_SMP_PORT_CTRL 0x12 /* 16b: Serial Port VLAN Register */ +#define ROBO_VLAN_PORTSPI_DEF_TAG 0x1c /* 16b: VLAN Port SPI Default Tag Register */ +#define ROBO_VLAN_PRIORITY_REMAP 0x20 /* 24b: VLAN Priority Re-Map Register */ + +#ifndef _CFE_ +#pragma pack() +#endif + + +#endif /* !__BCM535M_H_ */ + + + + + diff --git a/package/utils/robocfg/src/robocfg.c b/package/utils/robocfg/src/robocfg.c new file mode 100644 index 0000000000..7a4094dd41 --- /dev/null +++ b/package/utils/robocfg/src/robocfg.c @@ -0,0 +1,581 @@ +/* + * Broadcom BCM5325E/536x switch configuration utility + * + * Copyright (C) 2005 Oleg I. Vdovikin + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/socket.h> + +/* linux stuff */ +typedef u_int64_t u64; +typedef u_int32_t u32; +typedef u_int16_t u16; +typedef u_int8_t u8; + +#include <linux/if.h> +#include <linux/sockios.h> +#include <linux/ethtool.h> +#include <linux/mii.h> + +#include "etc53xx.h" +#define ROBO_PHY_ADDR 0x1E /* robo switch phy address */ + +/* MII registers */ +#define REG_MII_PAGE 0x10 /* MII Page register */ +#define REG_MII_ADDR 0x11 /* MII Address register */ +#define REG_MII_DATA0 0x18 /* MII Data register 0 */ + +#define REG_MII_PAGE_ENABLE 1 +#define REG_MII_ADDR_WRITE 1 +#define REG_MII_ADDR_READ 2 + +/* Private et.o ioctls */ +#define SIOCGETCPHYRD (SIOCDEVPRIVATE + 9) +#define SIOCSETCPHYWR (SIOCDEVPRIVATE + 10) + +typedef struct { + struct ifreq ifr; + int fd; + int et; /* use private ioctls */ +} robo_t; + +static u16 mdio_read(robo_t *robo, u16 phy_id, u8 reg) +{ + if (robo->et) { + int args[2] = { reg }; + + if (phy_id != ROBO_PHY_ADDR) { + fprintf(stderr, + "Access to real 'phy' registers unavaliable.\n" + "Upgrade kernel driver.\n"); + + return 0xffff; + } + + robo->ifr.ifr_data = (caddr_t) args; + if (ioctl(robo->fd, SIOCGETCPHYRD, (caddr_t)&robo->ifr) < 0) { + perror("SIOCGETCPHYRD"); + exit(1); + } + + return args[1]; + } else { + struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo->ifr.ifr_data; + mii->phy_id = phy_id; + mii->reg_num = reg; + if (ioctl(robo->fd, SIOCGMIIREG, &robo->ifr) < 0) { + perror("SIOCGMIIREG"); + exit(1); + } + return mii->val_out; + } +} + +static void mdio_write(robo_t *robo, u16 phy_id, u8 reg, u16 val) +{ + if (robo->et) { + int args[2] = { reg, val }; + + if (phy_id != ROBO_PHY_ADDR) { + fprintf(stderr, + "Access to real 'phy' registers unavaliable.\n" + "Upgrade kernel driver.\n"); + return; + } + + robo->ifr.ifr_data = (caddr_t) args; + if (ioctl(robo->fd, SIOCSETCPHYWR, (caddr_t)&robo->ifr) < 0) { + perror("SIOCGETCPHYWR"); + exit(1); + } + } else { + struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo->ifr.ifr_data; + mii->phy_id = phy_id; + mii->reg_num = reg; + mii->val_in = val; + if (ioctl(robo->fd, SIOCSMIIREG, &robo->ifr) < 0) { + perror("SIOCSMIIREG"); + exit(1); + } + } +} + +static int robo_reg(robo_t *robo, u8 page, u8 reg, u8 op) +{ + int i = 3; + + /* set page number */ + mdio_write(robo, ROBO_PHY_ADDR, REG_MII_PAGE, + (page << 8) | REG_MII_PAGE_ENABLE); + + /* set register address */ + mdio_write(robo, ROBO_PHY_ADDR, REG_MII_ADDR, + (reg << 8) | op); + + /* check if operation completed */ + while (i--) { + if ((mdio_read(robo, ROBO_PHY_ADDR, REG_MII_ADDR) & 3) == 0) + return 0; + } + + fprintf(stderr, "robo_reg: timeout\n"); + exit(1); + + return 0; +} + +static void robo_read(robo_t *robo, u8 page, u8 reg, u16 *val, int count) +{ + int i; + + robo_reg(robo, page, reg, REG_MII_ADDR_READ); + + for (i = 0; i < count; i++) + val[i] = mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + i); +} + +static u16 robo_read16(robo_t *robo, u8 page, u8 reg) +{ + robo_reg(robo, page, reg, REG_MII_ADDR_READ); + + return mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0); +} + +static u32 robo_read32(robo_t *robo, u8 page, u8 reg) +{ + robo_reg(robo, page, reg, REG_MII_ADDR_READ); + + return mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0) + + (mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + 1) << 16); +} + +static void robo_write16(robo_t *robo, u8 page, u8 reg, u16 val16) +{ + /* write data */ + mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0, val16); + + robo_reg(robo, page, reg, REG_MII_ADDR_WRITE); +} + +static void robo_write32(robo_t *robo, u8 page, u8 reg, u32 val32) +{ + /* write data */ + mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0, val32 & 65535); + mdio_write(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + 1, val32 >> 16); + + robo_reg(robo, page, reg, REG_MII_ADDR_WRITE); +} + +/* checks that attached switch is 5325E/5350 */ +static int robo_vlan5350(robo_t *robo) +{ + /* set vlan access id to 15 and read it back */ + u16 val16 = 15; + robo_write16(robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16); + + /* 5365 will refuse this as it does not have this reg */ + return (robo_read16(robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350) == val16); +} + +u8 port[6] = { 0, 1, 2, 3, 4, 8 }; +char ports[6] = { 'W', '4', '3', '2', '1', 'C' }; +char *rxtx[4] = { "enabled", "rx_disabled", "tx_disabled", "disabled" }; +char *stp[8] = { "none", "disable", "block", "listen", "learn", "forward", "6", "7" }; + +struct { + char *name; + u16 bmcr; +} media[5] = { { "auto", BMCR_ANENABLE | BMCR_ANRESTART }, + { "10HD", 0 }, { "10FD", BMCR_FULLDPLX }, + { "100HD", BMCR_SPEED100 }, { "100FD", BMCR_SPEED100 | BMCR_FULLDPLX } }; + +struct { + char *name; + u16 value; +} mdix[3] = { { "auto", 0x0000 }, { "on", 0x1800 }, { "off", 0x0800 } }; + +void usage() +{ + fprintf(stderr, "Broadcom BCM5325E/536x switch configuration utility\n" + "Copyright (C) 2005 Oleg I. Vdovikin\n\n" + "This program is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n\n"); + + fprintf(stderr, "Usage: robocfg <op> ... <op>\n" + "Operations are as below:\n" + "\tshow\n" + "\tswitch <enable|disable>\n" + "\tport <port_number> [state <%s|%s|%s|%s>]\n\t\t[stp %s|%s|%s|%s|%s|%s] [tag <vlan_tag>]\n" + "\t\t[media %s|%s|%s|%s|%s] [mdi-x %s|%s|%s]\n" + "\tvlan <vlan_number> [ports <ports_list>]\n" + "\tvlans <enable|disable|reset>\n\n" + "\tports_list should be one argument, space separated, quoted if needed,\n" + "\tport number could be followed by 't' to leave packet vlan tagged (CPU \n" + "\tport default) or by 'u' to untag packet (other ports default) before \n" + "\tbringing it to the port, '*' is ignored\n" + "\nSamples:\n" + "1) ASUS WL-500g Deluxe stock config (eth0 is WAN, eth0.1 is LAN):\n" + "robocfg switch disable vlans enable reset vlan 0 ports \"0 5u\" vlan 1 ports \"1 2 3 4 5t\"" + " port 0 state enabled stp none switch enable\n" + "2) WRT54g, WL-500g Deluxe OpenWRT config (vlan0 is LAN, vlan1 is WAN):\n" + "robocfg switch disable vlans enable reset vlan 0 ports \"1 2 3 4 5t\" vlan 1 ports \"0 5t\"" + " port 0 state enabled stp none switch enable\n", + rxtx[0], rxtx[1], rxtx[2], rxtx[3], stp[0], stp[1], stp[2], stp[3], stp[4], stp[5], + media[0].name, media[1].name, media[2].name, media[3].name, media[4].name, + mdix[0].name, mdix[1].name, mdix[2].name); +} + +static robo_t robo; +int bcm53xx_probe(const char *dev) +{ + struct ethtool_drvinfo info; + unsigned int phyid; + int ret; + + fprintf(stderr, "probing %s\n", dev); + + strcpy(robo.ifr.ifr_name, dev); + memset(&info, 0, sizeof(info)); + info.cmd = ETHTOOL_GDRVINFO; + robo.ifr.ifr_data = (caddr_t)&info; + ret = ioctl(robo.fd, SIOCETHTOOL, (caddr_t)&robo.ifr); + if (ret < 0) { + perror("SIOCETHTOOL"); + return ret; + } + + if ( strcmp(info.driver, "et0") && + strcmp(info.driver, "b44") && + strcmp(info.driver, "bcm63xx_enet") ) { + fprintf(stderr, "driver not supported %s\n", info.driver); + return -ENOSYS; + } + + /* try access using MII ioctls - get phy address */ + robo.et = 0; + if (ioctl(robo.fd, SIOCGMIIPHY, &robo.ifr) < 0) + robo.et = 1; + + if (robo.et) { + unsigned int args[2] = { 2 }; + + robo.ifr.ifr_data = (caddr_t) args; + ret = ioctl(robo.fd, SIOCGETCPHYRD, (caddr_t)&robo.ifr); + if (ret < 0) { + perror("SIOCGETCPHYRD"); + return ret; + } + phyid = args[1] & 0xffff; + + args[0] = 3; + robo.ifr.ifr_data = (caddr_t) args; + ret = ioctl(robo.fd, SIOCGETCPHYRD, (caddr_t)&robo.ifr); + if (ret < 0) { + perror("SIOCGETCPHYRD"); + return ret; + } + phyid |= args[1] << 16; + } else { + struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&robo.ifr.ifr_data; + mii->phy_id = ROBO_PHY_ADDR; + mii->reg_num = 2; + ret = ioctl(robo.fd, SIOCGMIIREG, &robo.ifr); + if (ret < 0) { + perror("SIOCGMIIREG"); + return ret; + } + phyid = mii->val_out & 0xffff; + + mii->phy_id = ROBO_PHY_ADDR; + mii->reg_num = 3; + ret = ioctl(robo.fd, SIOCGMIIREG, &robo.ifr); + if (ret < 0) { + perror("SIOCGMIIREG"); + return ret; + } + phyid |= mii->val_out << 16; + } + + if (phyid == 0xffffffff || phyid == 0x55210022) { + perror("phyid"); + return -EIO; + } + + return 0; +} + +int +main(int argc, char *argv[]) +{ + u16 val16; + u16 mac[3]; + int i = 0, j; + int robo5350 = 0; + u32 phyid; + + if ((robo.fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + exit(1); + } + + if (bcm53xx_probe("eth1")) { + if (bcm53xx_probe("eth0")) { + perror("bcm53xx_probe"); + exit(1); + } + } + + robo5350 = robo_vlan5350(&robo); + + for (i = 1; i < argc;) { + if (strcasecmp(argv[i], "port") == 0 && (i + 1) < argc) + { + int index = atoi(argv[++i]); + /* read port specs */ + while (++i < argc) { + if (strcasecmp(argv[i], "state") == 0 && ++i < argc) { + for (j = 0; j < 4 && strcasecmp(argv[i], rxtx[j]); j++); + if (j < 4) { + /* change state */ + robo_write16(&robo,ROBO_CTRL_PAGE, port[index], + (robo_read16(&robo, ROBO_CTRL_PAGE, port[index]) & ~(3 << 0)) | (j << 0)); + } else { + fprintf(stderr, "Invalid state '%s'.\n", argv[i]); + exit(1); + } + } else + if (strcasecmp(argv[i], "stp") == 0 && ++i < argc) { + for (j = 0; j < 8 && strcasecmp(argv[i], stp[j]); j++); + if (j < 8) { + /* change stp */ + robo_write16(&robo,ROBO_CTRL_PAGE, port[index], + (robo_read16(&robo, ROBO_CTRL_PAGE, port[index]) & ~(7 << 5)) | (j << 5)); + } else { + fprintf(stderr, "Invalid stp '%s'.\n", argv[i]); + exit(1); + } + } else + if (strcasecmp(argv[i], "media") == 0 && ++i < argc) { + for (j = 0; j < 5 && strcasecmp(argv[i], media[j].name); j++); + if (j < 5) { + mdio_write(&robo, port[index], MII_BMCR, media[j].bmcr); + } else { + fprintf(stderr, "Invalid media '%s'.\n", argv[i]); + exit(1); + } + } else + if (strcasecmp(argv[i], "mdi-x") == 0 && ++i < argc) { + for (j = 0; j < 3 && strcasecmp(argv[i], mdix[j].name); j++); + if (j < 3) { + mdio_write(&robo, port[index], 0x1c, mdix[j].value | + (mdio_read(&robo, port[index], 0x1c) & ~0x1800)); + } else { + fprintf(stderr, "Invalid mdi-x '%s'.\n", argv[i]); + exit(1); + } + } else + if (strcasecmp(argv[i], "tag") == 0 && ++i < argc) { + j = atoi(argv[i]); + /* change vlan tag */ + robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (index << 1), j); + } else break; + } + } else + if (strcasecmp(argv[i], "vlan") == 0 && (i + 1) < argc) + { + int index = atoi(argv[++i]); + while (++i < argc) { + if (strcasecmp(argv[i], "ports") == 0 && ++i < argc) { + char *ports = argv[i]; + int untag = 0; + int member = 0; + + while (*ports >= '0' && *ports <= '9') { + j = *ports++ - '0'; + member |= 1 << j; + + /* untag if needed, CPU port requires special handling */ + if (*ports == 'u' || (j != 5 && (*ports == ' ' || *ports == 0))) + { + untag |= 1 << j; + if (*ports) ports++; + /* change default vlan tag */ + robo_write16(&robo, ROBO_VLAN_PAGE, + ROBO_VLAN_PORT0_DEF_TAG + (j << 1), index); + } else + if (*ports == '*' || *ports == 't' || *ports == ' ') ports++; + else break; + + while (*ports == ' ') ports++; + } + + if (*ports) { + fprintf(stderr, "Invalid ports '%s'.\n", argv[i]); + exit(1); + } else { + /* write config now */ + val16 = (index) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */; + if (robo5350) { + robo_write32(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350, + (1 << 20) /* valid */ | (untag << 6) | member); + robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16); + } else { + robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, + (1 << 14) /* valid */ | (untag << 7) | member); + robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16); + } + } + } else break; + } + } else + if (strcasecmp(argv[i], "switch") == 0 && (i + 1) < argc) + { + /* enable/disable switching */ + robo_write16(&robo, ROBO_CTRL_PAGE, ROBO_SWITCH_MODE, + (robo_read16(&robo, ROBO_CTRL_PAGE, ROBO_SWITCH_MODE) & ~2) | + (*argv[++i] == 'e' ? 2 : 0)); + i++; + } else + if (strcasecmp(argv[i], "vlans") == 0 && (i + 1) < argc) + { + while (++i < argc) { + if (strcasecmp(argv[i], "reset") == 0) { + /* reset vlan validity bit */ + for (j = 0; j <= (robo5350 ? VLAN_ID_MAX5350 : VLAN_ID_MAX); j++) + { + /* write config now */ + val16 = (j) /* vlan */ | (1 << 12) /* write */ | (1 << 13) /* enable */; + if (robo5350) { + robo_write32(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_WRITE_5350, 0); + robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16); + } else { + robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_WRITE, 0); + robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16); + } + } + } else + if (strcasecmp(argv[i], "enable") == 0 || strcasecmp(argv[i], "disable") == 0) + { + int disable = (*argv[i] == 'd') || (*argv[i] == 'D'); + /* enable/disable vlans */ + robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0, disable ? 0 : + (1 << 7) /* 802.1Q VLAN */ | (3 << 5) /* mac check and hash */); + + robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL1, disable ? 0 : + (1 << 1) | (1 << 2) | (1 << 3) /* RSV multicast */); + + robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL4, disable ? 0 : + (1 << 6) /* drop invalid VID frames */); + + robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL5, disable ? 0 : + (1 << 3) /* drop miss V table frames */); + + } else break; + } + } else + if (strcasecmp(argv[i], "show") == 0) + { + break; + } else { + fprintf(stderr, "Invalid option %s\n", argv[i]); + usage(); + exit(1); + } + } + + if (i == argc) { + if (argc == 1) usage(); + return 0; + } + + /* show config */ + + printf("Switch: %sabled\n", robo_read16(&robo, ROBO_CTRL_PAGE, ROBO_SWITCH_MODE) & 2 ? "en" : "dis"); + + for (i = 0; i < 6; i++) { + printf(robo_read16(&robo, ROBO_STAT_PAGE, ROBO_LINK_STAT_SUMMARY) & (1 << port[i]) ? + "Port %d(%c): %s%s " : "Port %d(%c): DOWN ", i, ports[i], + robo_read16(&robo, ROBO_STAT_PAGE, ROBO_SPEED_STAT_SUMMARY) & (1 << port[i]) ? "100" : " 10", + robo_read16(&robo, ROBO_STAT_PAGE, ROBO_DUPLEX_STAT_SUMMARY) & (1 << port[i]) ? "FD" : "HD"); + + val16 = robo_read16(&robo, ROBO_CTRL_PAGE, port[i]); + + printf("%s stp: %s vlan: %d ", rxtx[val16 & 3], stp[(val16 >> 5) & 7], + robo_read16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_PORT0_DEF_TAG + (i << 1))); + + robo_read(&robo, ROBO_STAT_PAGE, ROBO_LSA_PORT0 + port[i] * 6, mac, 3); + + printf("mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[2] >> 8, mac[2] & 255, mac[1] >> 8, mac[1] & 255, mac[0] >> 8, mac[0] & 255); + } + + val16 = robo_read16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_CTRL0); + + printf("VLANs: %s %sabled%s%s\n", + robo5350 ? "BCM5325/535x" : "BCM536x", + (val16 & (1 << 7)) ? "en" : "dis", + (val16 & (1 << 6)) ? " mac_check" : "", + (val16 & (1 << 5)) ? " mac_hash" : ""); + + /* scan VLANs */ + for (i = 0; i <= (robo5350 ? VLAN_ID_MAX5350 : VLAN_ID_MAX); i++) { + /* issue read */ + val16 = (i) /* vlan */ | (0 << 12) /* read */ | (1 << 13) /* enable */; + + if (robo5350) { + u32 val32; + robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16); + /* actual read */ + val32 = robo_read32(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_READ); + if ((val32 & (1 << 20)) /* valid */) { + printf("vlan%d:", i); + for (j = 0; j < 6; j++) { + if (val32 & (1 << j)) { + printf(" %d%s", j, (val32 & (1 << (j + 6))) ? + (j == 5 ? "u" : "") : "t"); + } + } + printf("\n"); + } + } else { + robo_write16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS, val16); + /* actual read */ + val16 = robo_read16(&robo, ROBO_VLAN_PAGE, ROBO_VLAN_READ); + if ((val16 & (1 << 14)) /* valid */) { + printf("vlan%d:", i); + for (j = 0; j < 6; j++) { + if (val16 & (1 << j)) { + printf(" %d%s", j, (val16 & (1 << (j + 7))) ? + (j == 5 ? "u" : "") : "t"); + } + } + printf("\n"); + } + } + } + + return (0); +} diff --git a/package/utils/spidev_test/Makefile b/package/utils/spidev_test/Makefile new file mode 100644 index 0000000000..807039a1f5 --- /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/usbmode/Makefile b/package/utils/usbmode/Makefile new file mode 100644 index 0000000000..491f3e572f --- /dev/null +++ b/package/utils/usbmode/Makefile @@ -0,0 +1,57 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=usbmode +PKG_VERSION:=2013-05-31 +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=git://git.openwrt.org/project/usbmode.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=b62a33af03c39a8970249ce7afe7baec7ea9b91b +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +CMAKE_INSTALL:=1 + +PKG_LICENSE:=GPLv2 +PKG_LICENSE_FILES:= + +PKG_MAINTAINER:=Felix Fietkau <nbd@openwrt.org> + +PKG_DATA_VERSION:=20121109 +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:=a7d23a03157871013a0d708ab2b1b6df +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 +endef + +define Package/usb-modeswitch/install + $(INSTALL_DIR) $(1)/etc/hotplug.d/usb $(1)/sbin + perl $(PKG_BUILD_DIR)/convert-modeswitch.pl \ + $(PKG_BUILD_DIR)/$(PKG_DATA_PATH)/usb_modeswitch.d/* \ + > $(1)/etc/usb-mode.json + $(CP) ./files/usbmode.hotplug $(1)/etc/hotplug.d/usb/20-usb_mode + $(CP) $(PKG_INSTALL_DIR)/usr/sbin/usbmode $(1)/sbin/ +endef + +$(eval $(call BuildPackage,usb-modeswitch)) diff --git a/package/utils/usbmode/files/usbmode.hotplug b/package/utils/usbmode/files/usbmode.hotplug new file mode 100644 index 0000000000..4ef2bd8daa --- /dev/null +++ b/package/utils/usbmode/files/usbmode.hotplug @@ -0,0 +1,7 @@ +. /lib/functions/procd.sh + +procd_open_service "usbmode" +procd_open_instance +procd_set_param command "/sbin/usbmode" -s +procd_close_instance +procd_close_service diff --git a/package/utils/usbreset/Makefile b/package/utils/usbreset/Makefile new file mode 100644 index 0000000000..75bfd85138 --- /dev/null +++ b/package/utils/usbreset/Makefile @@ -0,0 +1,44 @@ +# +# Copyright (C) 2011-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:=usbreset +PKG_RELEASE:=2 + +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 0000000000..087a14cfa4 --- /dev/null +++ b/package/utils/usbreset/src/usbreset.c @@ -0,0 +1,253 @@ +/* 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 <sys/ioctl.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 bool find_usbfs(void) +{ + FILE *mtab; + + char buf[1024], type[32]; + static char path[1024]; + + if ((mtab = fopen("/proc/mounts", "r")) != NULL) + { + while (fgets(buf, sizeof(buf), mtab)) + { + if (sscanf(buf, "%*s %1023s %31s ", path, type) == 2 && + !strncmp(type, "usbfs", 5)) + { + usbfs = path; + break; + } + } + + fclose(mtab); + } + + return !!usbfs; +} + +static FILE * open_devlist(void) +{ + char buf[1024]; + snprintf(buf, sizeof(buf), "%s/devices", usbfs); + return fopen(buf, "r"); +} + +static void close_devlist(FILE *devs) +{ + fclose(devs); +} + +static struct usbentry * parse_devlist(FILE *devs) +{ + char buf[1024]; + static struct usbentry dev; + + memset(&dev, 0, sizeof(dev)); + + while (fgets(buf, sizeof(buf), devs)) + { + buf[strlen(buf)-1] = 0; + + switch (buf[0]) + { + case 'T': + sscanf(buf, "T: Bus=%d Lev=%*d Prnt=%*d Port=%*d Cnt=%*d Dev#=%d", + &dev.bus_num, &dev.dev_num); + break; + + case 'P': + sscanf(buf, "P: Vendor=%x ProdID=%x", + &dev.vendor_id, &dev.product_id); + break; + + case 'S': + if (!strncmp(buf, "S: Manufacturer=", 17)) + snprintf(dev.vendor_name, sizeof(dev.vendor_name), + "%s", buf+17); + else if (!strncmp(buf, "S: Product=", 12)) + snprintf(dev.product_name, sizeof(dev.product_name), + "%s", buf+12); + break; + } + + if (dev.product_name[0]) + return &dev; + } + + return NULL; +} + +static void list_devices(void) +{ + FILE *devs = open_devlist(); + 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); + } + + close_devlist(devs); +} + +struct usbentry * find_device(int *bus, int *dev, + int *vid, int *pid, + const char *product) +{ + FILE *devs = open_devlist(); + + 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; + } + } + + close_devlist(devs); + + return match; +} + +static void reset_device(struct usbentry *dev) +{ + int fd; + char path[1024]; + + snprintf(path, sizeof(path), "%s/%03d/%03d", + usbfs, 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 (!find_usbfs()) + { + fprintf(stderr, "Unable to find usbfs, is it mounted?\n"); + return 1; + } + + 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 0000000000..2cd59ae74c --- /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:=006 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=@KERNEL/linux/utils/usb/usbutils +PKG_MD5SUM:=9d13954981f4adbe3fd02aae6dbfafa9 + +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 0000000000..ed2c10f172 --- /dev/null +++ b/package/utils/util-linux/Makefile @@ -0,0 +1,594 @@ +# +# Copyright (C) 2007-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:=util-linux +PKG_VERSION:=2.21.2 +PKG_RELEASE:=2 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=@KERNEL/linux/utils/$(PKG_NAME)/v2.21 +PKG_MD5SUM:=54ba880f1d66782c2287ee2c898520e9 + +PKG_LICENSE:=GPLv2 LGPLv2.1 BSD-3c +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_BUILD_DEPENDS:=libncurses +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 += \ + --enable-new-mount \ + --with-ncurses \ + --disable-nls \ + --disable-tls \ + --without-udev + +TARGET_CFLAGS += $(FPIC) + +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)/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/lib + $(CP) $(PKG_BUILD_DIR)/libblkid/src/.libs/libblkid.{a,so*} $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/libmount/src/.libs/libmount.{a,so*} $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/libuuid/src/.libs/libuuid.{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/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 + 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 + 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 +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 + 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 +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 + 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 +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/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 + 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, swapon, swapoff +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)/libblkid/src/.libs/libblkid.so.* $(1)/usr/lib/ +endef + +define Package/libmount/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/libmount/src/.libs/libmount.so.* $(1)/usr/lib/ +endef + +define Package/libuuid/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/libuuid/src/.libs/libuuid.so.* $(1)/usr/lib/ +endef + +define Package/agetty/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/term-utils/agetty $(1)/usr/sbin/ +endef + +define Package/blkid/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/blkid $(1)/usr/sbin/ +endef + +define Package/cal/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/cal $(1)/usr/bin/ +endef + +define Package/cfdisk/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/fdisk/.libs/cfdisk $(1)/usr/sbin/ +endef + +define Package/fdisk/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/fdisk/.libs/fdisk $(1)/usr/sbin/ +endef + +define Package/findfs/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/findfs $(1)/usr/sbin/ +endef + +define Package/flock/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/sys-utils/flock $(1)/usr/bin/ +endef + +define Package/getopt/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/getopt/getopt $(1)/usr/bin/ +endef + +define Package/hwclock/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/hwclock/hwclock $(1)/usr/sbin/ +endef + +define Package/logger/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/logger $(1)/usr/bin/ +endef + +define Package/look/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/look $(1)/usr/bin/ +endef + +define Package/losetup/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/sys-utils/losetup $(1)/usr/sbin/ +endef + +define Package/lsblk/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/lsblk $(1)/usr/bin/ +endef + +define Package/mcookie/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/mcookie $(1)/usr/bin/ +endef + +define Package/mount-utils/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/sys-utils/.libs/{u,}mount $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/sys-utils/.libs/mountpoint $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/findmnt $(1)/usr/bin/ +endef + +define Package/namei/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/namei $(1)/usr/bin/ +endef + +define Package/rename/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/rename $(1)/usr/bin/ +endef + +define Package/partx-utils/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/partx/.libs/partx $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/partx/addpart $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/partx/delpart $(1)/usr/sbin/ +endef + +define Package/script-utils/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/term-utils/script $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/term-utils/scriptreplay $(1)/usr/bin/ +endef + +define Package/setterm/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/term-utils/setterm $(1)/usr/bin/ +endef + +define Package/sfdisk/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/fdisk/sfdisk $(1)/usr/sbin/ +endef + +define Package/swap-utils/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/disk-utils/.libs/mkswap $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/disk-utils/.libs/swaplabel $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/sys-utils/.libs/swapon $(1)/usr/sbin/ + ln -sf swapon $(1)/usr/sbin/swapoff +endef + +define Package/uuidd/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/uuidd $(1)/usr/sbin/ +endef + +define Package/uuidgen/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/uuidgen $(1)/usr/bin/ +endef + +define Package/wall/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/term-utils/wall $(1)/usr/bin/ +endef + +define Package/whereis/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/whereis $(1)/usr/bin/ +endef + +define Package/wipefs/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/misc-utils/.libs/wipefs $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,libblkid)) +$(eval $(call BuildPackage,libmount)) +$(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,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/000-compile.patch b/package/utils/util-linux/patches/000-compile.patch new file mode 100644 index 0000000000..b7cc18b40c --- /dev/null +++ b/package/utils/util-linux/patches/000-compile.patch @@ -0,0 +1,44 @@ +--- a/misc-utils/cal.c ++++ b/misc-utils/cal.c +@@ -291,41 +291,6 @@ main(int argc, char **argv) { + } + #endif + +-/* +- * The traditional Unix cal utility starts the week at Sunday, +- * while ISO 8601 starts at Monday. We read the start day from +- * the locale database, which can be overridden with the +- * -s (Sunday) or -m (Monday) options. +- */ +-#if HAVE_DECL__NL_TIME_WEEK_1STDAY +- /* +- * You need to use 2 locale variables to get the first day of the week. +- * This is needed to support first_weekday=2 and first_workday=1 for +- * the rare case where working days span across 2 weeks. +- * This shell script shows the combinations and calculations involved: +- * +- * for LANG in en_US ru_RU fr_FR csb_PL POSIX; do +- * printf "%s:\t%s + %s -1 = " $LANG $(locale week-1stday first_weekday) +- * date -d"$(locale week-1stday) +$(($(locale first_weekday)-1))day" +%w +- * done +- * +- * en_US: 19971130 + 1 -1 = 0 #0 = sunday +- * ru_RU: 19971130 + 2 -1 = 1 +- * fr_FR: 19971201 + 1 -1 = 1 +- * csb_PL: 19971201 + 2 -1 = 2 +- * POSIX: 19971201 + 7 -1 = 0 +- */ +- { +- int wfd; +- union { unsigned int word; char *string; } val; +- val.string = nl_langinfo(_NL_TIME_WEEK_1STDAY); +- +- wfd = val.word; +- wfd = day_in_week(wfd % 100, (wfd / 100) % 100, wfd / (100 * 100)); +- weekstart = (wfd + *nl_langinfo(_NL_TIME_FIRST_WEEKDAY) - 1) % 7; +- } +-#endif +- + yflag = 0; + while ((ch = getopt_long(argc, argv, "13mjsyVh", longopts, NULL)) != -1) + switch(ch) { 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 0000000000..e3f048ab3c --- /dev/null +++ b/package/utils/util-linux/patches/001-no-printf-alloc.patch @@ -0,0 +1,108 @@ +for systems that don't support latest POSIX standard: %as + +https://bugs.gentoo.org/406303 + +--- a/configure.ac ++++ b/configure.ac +@@ -688,7 +688,6 @@ AC_ARG_ENABLE([libmount], + UL_BUILD_INIT([libmount]) + UL_REQUIRES_LINUX([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) + + AC_SUBST([LIBMOUNT_VERSION]) +--- 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 inline char *skip_spaces(char *s) + { + assert(s); +@@ -61,16 +65,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; + +@@ -136,6 +155,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, "%u " /* (1) id */ + "%u " /* (2) parent */ + "%u:%u " /* (3) maj:min */ +@@ -147,9 +176,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) +@@ -167,9 +202,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) { + fs->flags |= MNT_FS_KERNEL; diff --git a/package/utils/util-linux/patches/002-fix-endianess.patch b/package/utils/util-linux/patches/002-fix-endianess.patch new file mode 100644 index 0000000000..4c59932cda --- /dev/null +++ b/package/utils/util-linux/patches/002-fix-endianess.patch @@ -0,0 +1,13 @@ +Index: util-linux-2.21.2/libblkid/src/superblocks/swap.c +=================================================================== +--- util-linux-2.21.2.orig/libblkid/src/superblocks/swap.c 2012-05-15 13:51:45.814410455 +0200 ++++ util-linux-2.21.2/libblkid/src/superblocks/swap.c 2013-06-12 23:23:03.270742199 +0200 +@@ -48,7 +48,7 @@ + + /* SWAPSPACE2 - check for wrong version or zeroed pagecount */ + if (strcmp(version, "2") == 0 && +- (hdr->version != 1 || hdr->lastpage == 0)) ++ ((hdr->version != 1 && swab32(hdr->version) != 1) || hdr->lastpage == 0)) + return -1; + + /* arbitrary sanity check.. is there any garbage down there? */ diff --git a/package/utils/xfsprogs/Makefile b/package/utils/xfsprogs/Makefile new file mode 100644 index 0000000000..a7a865a0eb --- /dev/null +++ b/package/utils/xfsprogs/Makefile @@ -0,0 +1,87 @@ +# +# 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 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/xfsprogs/default + SECTION:=utils + CATEGORY:=Utilities + 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 + +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 0000000000..3003d6d210 --- /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 0000000000..30d36b4da8 --- /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 0000000000..c46e8025cd --- /dev/null +++ b/package/utils/xfsprogs/patches/110-uclibc_no_ustat.patch @@ -0,0 +1,36 @@ +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,9 @@ + #include <mntent.h> + #include <sys/stat.h> + #undef ustat ++#ifndef __UCLIBC__ + #include <sys/ustat.h> ++#endif + #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) + { ++#ifndef __UCLIBC__ + /* 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 0000000000..1e9b533654 --- /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 0000000000..b1ecda71e5 --- /dev/null +++ b/package/utils/xfsprogs/patches/130-uclibc_no_xattr.patch @@ -0,0 +1,36 @@ +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,9 @@ + #include <sys/wait.h> + #include <sys/vfs.h> + #include <sys/statvfs.h> ++#ifndef __UCLIBC__ + #include <sys/xattr.h> ++#endif + + + #ifndef XFS_XFLAG_NODEFRAG +@@ -990,6 +992,7 @@ fsr_setup_attr_fork( + int tfd, + xfs_bstat_t *bstatp) + { ++#ifndef __UCLIBC__ + 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 0000000000..f915a9cf27 --- /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 |