[PATCH 1/2] Allow BusyBox to be built without a list of applet names
..mg..
shoemaker at riseup.net
Fri Apr 29 19:05:24 UTC 2016
On Fri, Apr 29, 2016 at 08:54:55PM +0200, Tito wrote:
>
>
> On 04/29/2016 02:47 PM, Ron Yorston wrote:
> >Use a hash of the command name to determine which applet to execute.
> >Invalid names will also match.
>
> Hi,
> what exactly means:
> "Invalid names will also match" ?
The lookup hash isn't collision-free: more than one input string
points to the same applet. Normally invalid applet names might
cause an unexpected one to run
HTH
-mg
>
> Ciao,
> Tito
>
>
> >
> >Without applet names the following features don't work:
> >
> > - busybox --list
> > - busybox --install
> > - tab completion for applets in standalone shell mode
> > - in standalone shell mode the help builtin doesn't list applets
> >
> >Compared with the current default configuration, not storing applet
> >names gives:
> >
> >function old new delta
> >applet_hash - 734 +734
> >usr_bin 10 - -10
> >usr_sbin 11 - -11
> >applet_nameofs 14 - -14
> >install_dir 20 - -20
> >find_applet_by_name 112 69 -43
> >applet_install_loc 184 - -184
> >run_applet_and_exit 675 192 -483
> >applet_names 2536 - -2536
> >------------------------------------------------------------------------------
> >(add/remove: 1/6 grow/shrink: 0/2 up/down: 734/-3301) Total: -2567 bytes
> > text data bss dec hex filename
> > 764230 2059 1636 767925 bb7b5 busybox_old
> > 761520 2059 1636 765215 bad1f busybox_unstripped
> >
> >Signed-off-by: Ron Yorston <rmy at pobox.com>
> >---
> > Config.in | 9 +++++++++
> > applets/applet_tables.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
> > libbb/appletlib.c | 33 ++++++++++++++++++++++++++++++++-
> > libbb/lineedit.c | 2 +-
> > shell/ash.c | 2 +-
> > 5 files changed, 87 insertions(+), 5 deletions(-)
> >
> >diff --git a/Config.in b/Config.in
> >index 0a0b5d7..49ee333 100644
> >--- a/Config.in
> >+++ b/Config.in
> >@@ -116,9 +116,18 @@ config FEATURE_COMPRESS_USAGE
> > and have very little memory, this might not be a win. Otherwise,
> > you probably want this.
> >
> >+config STORE_APPLET_NAMES
> >+ bool "Store applet names"
> >+ default y
> >+ help
> >+ Enable BusyBox applet names to be stored in the binary.
> >+ Disabling this will save some space but also disables useful
> >+ features like the installer and listing applet names.
> >+
> > config FEATURE_INSTALLER
> > bool "Support --install [-s] to install applet links at runtime"
> > default y
> >+ depends on STORE_APPLET_NAMES
> > help
> > Enable 'busybox --install [-s]' support. This will allow you to use
> > busybox at runtime to create hard links or symlinks for all the
> >diff --git a/applets/applet_tables.c b/applets/applet_tables.c
> >index 843f2ec..31ea188 100644
> >--- a/applets/applet_tables.c
> >+++ b/applets/applet_tables.c
> >@@ -11,6 +11,7 @@
> > #include <sys/stat.h>
> > #include <fcntl.h>
> > #include <stdlib.h>
> >+#include <stdint.h>
> > #include <string.h>
> > #include <stdio.h>
> > #include <unistd.h>
> >@@ -34,6 +35,7 @@ struct bb_applet {
> > /* true if instead of fork(); exec("applet"); waitpid();
> > * one can simply call applet_main(argc,argv); */
> > unsigned char nofork;
> >+ uint32_t app_hash;
> > };
> >
> > /* Define struct bb_applet applets[] */
> >@@ -58,9 +60,21 @@ static int str_isalnum_(const char *s)
> > return 1;
> > }
> >
> >+#if !ENABLE_STORE_APPLET_NAMES
> >+static uint32_t hash(const char *s, uint32_t mul)
> >+{
> >+ uint32_t h = *s++;
> >+ while (*s)
> >+ h = (h * mul) ^ (uint8_t)*s++;
> >+ return (uint16_t)h & 0xffff;
> >+}
> >+#endif
> >+
> > int main(int argc, char **argv)
> > {
> > int i, j;
> >+ uint32_t mul;
> >+ int MAX_APPLET_NAME_LEN = 0;
> >
> > // In find_applet_by_name(), before linear search, narrow it down
> > // by looking at N "equidistant" names. With ~350 applets:
> >@@ -121,6 +135,8 @@ int main(int argc, char **argv)
> > }
> >
> > //printf("#ifndef SKIP_definitions\n");
> >+ mul = 0;
> >+#if ENABLE_STORE_APPLET_NAMES
> > printf("const char applet_names[] ALIGN1 = \"\"\n");
> > for (i = 0; i < NUM_APPLETS; i++) {
> > printf("\"%s\" \"\\0\"\n", applets[i].name);
> >@@ -128,10 +144,36 @@ int main(int argc, char **argv)
> > // MAX_APPLET_NAME_LEN = strlen(applets[i].name);
> > }
> > printf(";\n\n");
> >+#else
> >+ mul = 1;
> >+ collision:
> >+ for (i = 0; i < NUM_APPLETS; i++) {
> >+ int j;
> >+ uint32_t h = hash(applets[i].name, mul);
> >+ for (j = 0; j < i; j++) {
> >+ if (h == applets[j].app_hash) {
> >+ mul += 2;
> >+ goto collision;
> >+ }
> >+ }
> >+ applets[i].app_hash = h;
> >+ }
> >+#endif
> >+
> >+ printf("#define APPNAME_HASH_MUL %u\n\n", mul);
> >+ if ( mul != 0 ) {
> >+ printf("const uint16_t applet_hash[] ALIGN2 = {\n");
> >+ for (i = 0; i < NUM_APPLETS; i++) {
> >+ printf("0x%04x,\n", applets[i].app_hash);
> >+ }
> >+ printf("};\n\n");
> >+ }
> >
> > for (i = 0; i < NUM_APPLETS; i++) {
> > if (str_isalnum_(applets[i].name))
> > printf("#define APPLET_NO_%s %d\n", applets[i].name, i);
> >+ if (MAX_APPLET_NAME_LEN < strlen(applets[i].name))
> >+ MAX_APPLET_NAME_LEN = strlen(applets[i].name);
> > }
> > printf("\n");
> >
> >@@ -190,8 +232,8 @@ int main(int argc, char **argv)
> > printf("};\n");
> > #endif
> > //printf("#endif /* SKIP_definitions */\n");
> >-// printf("\n");
> >-// printf("#define MAX_APPLET_NAME_LEN %u\n", MAX_APPLET_NAME_LEN);
> >+ printf("\n");
> >+ printf("#define MAX_APPLET_NAME_LEN %u\n", MAX_APPLET_NAME_LEN);
> >
> > if (argv[2]) {
> > char line_old[80];
> >diff --git a/libbb/appletlib.c b/libbb/appletlib.c
> >index b682e6b..9a4f367 100644
> >--- a/libbb/appletlib.c
> >+++ b/libbb/appletlib.c
> >@@ -139,6 +139,7 @@ void FAST_FUNC bb_show_usage(void)
> > xfunc_die();
> > }
> >
> >+#if APPNAME_HASH_MUL == 0
> > int FAST_FUNC find_applet_by_name(const char *name)
> > {
> > unsigned i, max;
> >@@ -265,6 +266,30 @@ int FAST_FUNC find_applet_by_name(const char *name)
> > return -1;
> > #endif
> > }
> >+#else
> >+static uint32_t hash(const char *s)
> >+{
> >+ uint32_t h = *s++;
> >+ while (*s)
> >+ h = (h * APPNAME_HASH_MUL) ^ (uint8_t)*s++;
> >+ return (uint16_t)h & 0xffff;
> >+}
> >+
> >+int FAST_FUNC find_applet_by_name(const char *name)
> >+{
> >+ uint32_t h = hash(name);
> >+ int i;
> >+
> >+ if (strlen(name) > MAX_APPLET_NAME_LEN)
> >+ return -1;
> >+
> >+ for (i=0; i<NUM_APPLETS; i++)
> >+ if (applet_hash[i] == h)
> >+ return i;
> >+
> >+ return -1;
> >+}
> >+#endif
> >
> >
> > void lbb_prepare(const char *applet
> >@@ -733,7 +758,9 @@ static int busybox_main(char **argv)
> > "copyright notices.\n"
> > "\n"
> > "Usage: busybox [function [arguments]...]\n"
> >+ IF_STORE_APPLET_NAMES(
> > " or: busybox --list"IF_FEATURE_INSTALLER("[-full]")"\n"
> >+ )
> > IF_FEATURE_INSTALLER(
> > " or: busybox --install [-s] [DIR]\n"
> > )
> >@@ -753,8 +780,11 @@ static int busybox_main(char **argv)
> > "\tTo run external program, use full path (/sbin/ip instead of ip).\n"
> > )
> > "\n"
> >+ IF_STORE_APPLET_NAMES(
> > "Currently defined functions:\n"
> >+ )
> > );
> >+#if ENABLE_STORE_APPLET_NAMES
> > col = 0;
> > a = applet_names;
> > /* prevent last comma to be in the very last pos */
> >@@ -776,10 +806,11 @@ static int busybox_main(char **argv)
> > a += len2 - 1;
> > }
> > full_write2_str("\n\n");
> >+#endif
> > return 0;
> > }
> >
> >- if (is_prefixed_with(argv[1], "--list")) {
> >+ if (ENABLE_STORE_APPLET_NAMES && is_prefixed_with(argv[1], "--list")) {
> > unsigned i = 0;
> > const char *a = applet_names;
> > dup2(1, 2);
> >diff --git a/libbb/lineedit.c b/libbb/lineedit.c
> >index 3e62f46..2c35d50 100644
> >--- a/libbb/lineedit.c
> >+++ b/libbb/lineedit.c
> >@@ -775,7 +775,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
> > }
> > pf_len = strlen(pfind);
> >
> >-#if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1
> >+#if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 && ENABLE_STORE_APPLET_NAMES
> > if (type == FIND_EXE_ONLY) {
> > const char *p = applet_names;
> >
> >diff --git a/shell/ash.c b/shell/ash.c
> >index faa45a8..acaf95c 100644
> >--- a/shell/ash.c
> >+++ b/shell/ash.c
> >@@ -12588,7 +12588,7 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
> > col = 0;
> > }
> > }
> >-# if ENABLE_FEATURE_SH_STANDALONE
> >+# if ENABLE_FEATURE_SH_STANDALONE && ENABLE_STORE_APPLET_NAMES
> > {
> > const char *a = applet_names;
> > while (*a) {
> >
> _______________________________________________
> busybox mailing list
> busybox at busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox
More information about the busybox
mailing list