[PATCH 1/2] Allow BusyBox to be built without a list of applet names
Tito
farmatito at tiscali.it
Sat Apr 30 05:29:09 UTC 2016
On 04/29/2016 09:05 PM, ..mg.. wrote:
> 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
And this should be a GoodThing (TM) ?
Ciao,
Tito
> 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
> _______________________________________________
> busybox mailing list
> busybox at busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox
>
More information about the busybox
mailing list