From 747162109fb1c891baf6aafa1ca0410bd08d04a4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 24 May 2018 17:29:14 +0200 Subject: realpath,readlink -f: coreutils compat, closes 11021 function old new delta xmalloc_realpath_coreutils - 121 +121 Signed-off-by: Denys Vlasenko --- libbb/xreadlink.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'libbb') diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c index 9b62bcc43..6315033bb 100644 --- a/libbb/xreadlink.c +++ b/libbb/xreadlink.c @@ -122,3 +122,33 @@ char* FAST_FUNC xmalloc_realpath(const char *path) return xstrdup(realpath(path, buf)); #endif } + +char* FAST_FUNC xmalloc_realpath_coreutils(const char *path) +{ + char *buf; + + errno = 0; + buf = xmalloc_realpath(path); + /* + * There is one case when "readlink -f" and + * "realpath" from coreutils succeed, + * even though file does not exist, such as: + * /tmp/file_does_not_exist + * (the directory must exist). + */ + if (!buf && errno == ENOENT) { + char *last_slash = strrchr(path, '/'); + if (last_slash) { + *last_slash++ = '\0'; + buf = xmalloc_realpath(path); + if (buf) { + unsigned len = strlen(buf); + buf = xrealloc(buf, len + strlen(last_slash) + 2); + buf[len++] = '/'; + strcpy(buf + len, last_slash); + } + } + } + + return buf; +} -- cgit v1.2.3-55-g6feb From bf7f103ffb6e2644e9c063cba723e25635c14a52 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 26 May 2018 17:42:00 +0200 Subject: whitespace fix Signed-off-by: Denys Vlasenko --- libbb/xreadlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbb') diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c index 6315033bb..ead30e499 100644 --- a/libbb/xreadlink.c +++ b/libbb/xreadlink.c @@ -143,7 +143,7 @@ char* FAST_FUNC xmalloc_realpath_coreutils(const char *path) buf = xmalloc_realpath(path); if (buf) { unsigned len = strlen(buf); - buf = xrealloc(buf, len + strlen(last_slash) + 2); + buf = xrealloc(buf, len + strlen(last_slash) + 2); buf[len++] = '/'; strcpy(buf + len, last_slash); } -- cgit v1.2.3-55-g6feb From 43b17b1cd0dd3eac740e4770be77db2c9010ad04 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Thu, 31 May 2018 22:15:55 -0700 Subject: restore documentation on the build config language Kconfig-language.txt was deleted in commit 4fa499a17b52b back in 2006. Move to docs/ as suggested by Xabier Oneca: http://lists.busybox.net/pipermail/busybox/2014-May/080914.html Also update references to it everywhere. Signed-off-by: Kartik Agaram Signed-off-by: Denys Vlasenko --- Config.in | 2 +- archival/Config.src | 2 +- console-tools/Config.src | 2 +- coreutils/Config.src | 2 +- debianutils/Config.src | 2 +- docs/Kconfig-language.txt | 255 ++++++++++++++++++++++++++++++++++++++++ e2fsprogs/Config.src | 2 +- editors/Config.src | 2 +- findutils/Config.src | 2 +- init/Config.src | 2 +- klibc-utils/Config.src | 2 +- libbb/Config.src | 2 +- loginutils/Config.src | 2 +- miscutils/Config.src | 2 +- modutils/Config.src | 2 +- networking/Config.src | 2 +- networking/udhcp/Config.src | 2 +- printutils/Config.src | 2 +- procps/Config.src | 2 +- runit/Config.src | 2 +- selinux/Config.src | 2 +- shell/Config.src | 2 +- sysklogd/Config.src | 2 +- util-linux/Config.src | 2 +- util-linux/volume_id/Config.src | 2 +- 25 files changed, 279 insertions(+), 24 deletions(-) create mode 100644 docs/Kconfig-language.txt (limited to 'libbb') diff --git a/Config.in b/Config.in index 51ff01ef4..ae21f52ef 100644 --- a/Config.in +++ b/Config.in @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # mainmenu "Configuration" diff --git a/archival/Config.src b/archival/Config.src index 449914565..6f4f30c43 100644 --- a/archival/Config.src +++ b/archival/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Archival Utilities" diff --git a/console-tools/Config.src b/console-tools/Config.src index e6587ade4..c30caf0e1 100644 --- a/console-tools/Config.src +++ b/console-tools/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Console Utilities" diff --git a/coreutils/Config.src b/coreutils/Config.src index 7a8a3a634..1bded03a6 100644 --- a/coreutils/Config.src +++ b/coreutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Coreutils" diff --git a/debianutils/Config.src b/debianutils/Config.src index 61daeb047..17b0d8945 100644 --- a/debianutils/Config.src +++ b/debianutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Debian Utilities" diff --git a/docs/Kconfig-language.txt b/docs/Kconfig-language.txt new file mode 100644 index 000000000..0ba8932ba --- /dev/null +++ b/docs/Kconfig-language.txt @@ -0,0 +1,255 @@ +Introduction +------------ + +The configuration database is collection of configuration options +organized in a tree structure: + + +- Code maturity level options + | +- Prompt for development and/or incomplete code/drivers + +- General setup + | +- Networking support + | +- System V IPC + | +- BSD Process Accounting + | +- Sysctl support + +- Loadable module support + | +- Enable loadable module support + | +- Set version information on all module symbols + | +- Kernel module loader + +- ... + +Every entry has its own dependencies. These dependencies are used +to determine the visible of an entry. Any child entry is only +visible if its parent entry is also visible. + +Menu entries +------------ + +Most entries define a config option, all other entries help to organize +them. A single configuration option is defined like this: + +config MODVERSIONS + bool "Set version information on all module symbols" + depends MODULES + help + Usually, modules have to be recompiled whenever you switch to a new + kernel. ... + +Every line starts with a key word and can be followed by multiple +arguments. "config" starts a new config entry. The following lines +define attributes for this config option. Attributes can be the type of +the config option, input prompt, dependencies, help text and default +values. A config option can be defined multiple times with the same +name, but every definition can have only a single input prompt and the +type must not conflict. + +Menu attributes +--------------- + +A menu entry can have a number of attributes. Not all of them are +applicable everywhere (see syntax). + +- type definition: "bool"/"tristate"/"string"/"hex"/"integer" + Every config option must have a type. There are only two basic types: + tristate and string, the other types base on these two. The type + definition optionally accepts an input prompt, so these two examples + are equivalent: + + bool "Networking support" + and + bool + prompt "Networking support" + +- input prompt: "prompt" ["if" ] + Every menu entry can have at most one prompt, which is used to display + to the user. Optionally dependencies only for this prompt can be added + with "if". + +- default value: "default" ["if" ] + A config option can have any number of default values. If multiple + default values are visible, only the first defined one is active. + Default values are not limited to the menu entry, where they are + defined, this means the default can be defined somewhere else or be + overridden by an earlier definition. + The default value is only assigned to the config symbol if no other + value was set by the user (via the input prompt above). If an input + prompt is visible the default value is presented to the user and can + be overridden by him. + Optionally dependencies only for this default value can be added with + "if". + +- dependencies: "depends on"/"requires" + This defines a dependency for this menu entry. If multiple + dependencies are defined they are connected with '&&'. Dependencies + are applied to all other options within this menu entry (which also + accept "if" expression), so these two examples are equivalent: + + bool "foo" if BAR + default y if BAR + and + depends on BAR + bool "foo" + default y + +- help text: "help" + This defines a help text. The end of the help text is determined by + the level indentation, this means it ends at the first line which has + a smaller indentation than the first line of the help text. + + +Menu dependencies +----------------- + +Dependencies define the visibility of a menu entry and can also reduce +the input range of tristate symbols. The tristate logic used in the +expressions uses one more state than normal boolean logic to express the +module state. Dependency expressions have the following syntax: + + ::= (1) + '=' (2) + '!=' (3) + '(' ')' (4) + '!' (5) + '||' (6) + '&&' (7) + +Expressions are listed in decreasing order of precedence. + +(1) Convert the symbol into an expression. Boolean and tristate symbols + are simply converted into the respective expression values. All + other symbol types result in 'n'. +(2) If the values of both symbols are equal, it returns 'y', + otherwise 'n'. +(3) If the values of both symbols are equal, it returns 'n', + otherwise 'y'. +(4) Returns the value of the expression. Used to override precedence. +(5) Returns the result of (2-/expr/). +(6) Returns the result of min(/expr/, /expr/). +(7) Returns the result of max(/expr/, /expr/). + +An expression can have a value of 'n', 'm' or 'y' (or 0, 1, 2 +respectively for calculations). A menu entry becomes visible when it's +expression evaluates to 'm' or 'y'. + +There are two type of symbols: constant and nonconstant symbols. +Nonconstant symbols are the most common ones and are defined with the +'config' statement. Nonconstant symbols consist entirely of alphanumeric +characters or underscores. +Constant symbols are only part of expressions. Constant symbols are +always surrounded by single or double quotes. Within the quote any +other character is allowed and the quotes can be escaped using '\'. + +Menu structure +-------------- + +The position of a menu entry in the tree is determined in two ways. First +it can be specified explicitely: + +menu "Network device support" + depends NET + +config NETDEVICES + ... + +endmenu + +All entries within the "menu" ... "endmenu" block become a submenu of +"Network device support". All subentries inherit the dependencies from +the menu entry, e.g. this means the dependency "NET" is added to the +dependency list of the config option NETDEVICES. + +The other way to generate the menu structure is done by analyzing the +dependencies. If a menu entry somehow depends on the previous entry, it +can be made a submenu of it. First the the previous (parent) symbol must +be part of the dependency list and then one of these two condititions +must be true: +- the child entry must become invisible, if the parent is set to 'n' +- the child entry must only be visible, if the parent is visible + +config MODULES + bool "Enable loadable module support" + +config MODVERSIONS + bool "Set version information on all module symbols" + depends MODULES + +comment "module support disabled" + depends !MODULES + +MODVERSIONS directly depends on MODULES, this means it's only visible if +MODULES is different from 'n'. The comment on the other hand is always +visible when MODULES it's visible (the (empty) dependency of MODULES is +also part of the comment dependencies). + + +Kconfig syntax +-------------- + +The configuration file describes a series of menu entries, where every +line starts with a keyword (except help texts). The following keywords +end a menu entry: +- config +- choice/endchoice +- comment +- menu/endmenu +- if/endif +- source +The first four also start the definition of a menu entry. + +config: + + "config" + + +This defines a config symbol and accepts any of above +attributes as options. + +choices: + + "choice" + + + "endchoice" + +This defines a choice group and accepts any of above attributes as +options. A choice can only be of type bool or tristate, while a boolean +choice only allows a single config entry to be selected, a tristate +choice also allows any number of config entries to be set to 'm'. This +can be used if multiple drivers for a single hardware exists and only a +single driver can be compiled/loaded into the kernel, but all drivers +can be compiled as modules. +A choice accepts another option "optional", which allows to set the +choice to 'n' and no entry needs to be selected. + +comment: + + "comment" + + +This defines a comment which is displayed to the user during the +configuration process and is also echoed to the output files. The only +possible options are dependencies. + +menu: + + "menu" + + + "endmenu" + +This defines a menu block, see "Menu structure" above for more +information. The only possible options are dependencies. + +if: + + "if" + + "endif" + +This defines an if block. The dependency expression is appended +to all enclosed menu entries. + +source: + + "source" + +This reads the specified configuration file. This file is always parsed. diff --git a/e2fsprogs/Config.src b/e2fsprogs/Config.src index a20d849e6..ad15f470c 100644 --- a/e2fsprogs/Config.src +++ b/e2fsprogs/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Linux Ext2 FS Progs" diff --git a/editors/Config.src b/editors/Config.src index 0920bc494..3b2e4a6c0 100644 --- a/editors/Config.src +++ b/editors/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Editors" diff --git a/findutils/Config.src b/findutils/Config.src index 9ee71a845..c28c5844e 100644 --- a/findutils/Config.src +++ b/findutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Finding Utilities" diff --git a/init/Config.src b/init/Config.src index 5767c93f0..b19b0bea1 100644 --- a/init/Config.src +++ b/init/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Init Utilities" diff --git a/klibc-utils/Config.src b/klibc-utils/Config.src index fe7cb1315..cf4552e51 100644 --- a/klibc-utils/Config.src +++ b/klibc-utils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "klibc-utils" diff --git a/libbb/Config.src b/libbb/Config.src index 16e16480b..312aa1831 100644 --- a/libbb/Config.src +++ b/libbb/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # comment "Library Tuning" diff --git a/loginutils/Config.src b/loginutils/Config.src index 680f42118..cbb09646b 100644 --- a/loginutils/Config.src +++ b/loginutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Login/Password Management Utilities" diff --git a/miscutils/Config.src b/miscutils/Config.src index 7325fb8fa..d10b00b28 100644 --- a/miscutils/Config.src +++ b/miscutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Miscellaneous Utilities" diff --git a/modutils/Config.src b/modutils/Config.src index e413702bb..188296814 100644 --- a/modutils/Config.src +++ b/modutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Linux Module Utilities" diff --git a/networking/Config.src b/networking/Config.src index 492c60da4..2ce5287de 100644 --- a/networking/Config.src +++ b/networking/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Networking Utilities" diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index 50bff2e8c..e5958804b 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # config UDHCPD diff --git a/printutils/Config.src b/printutils/Config.src index e53b9d093..5f1d65f6c 100644 --- a/printutils/Config.src +++ b/printutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Print Utilities" diff --git a/procps/Config.src b/procps/Config.src index 515d79938..2b1b8ab11 100644 --- a/procps/Config.src +++ b/procps/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Process Utilities" diff --git a/runit/Config.src b/runit/Config.src index 8cde89680..403ec8724 100644 --- a/runit/Config.src +++ b/runit/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Runit Utilities" diff --git a/selinux/Config.src b/selinux/Config.src index 9cb755a0f..f8fcdadf9 100644 --- a/selinux/Config.src +++ b/selinux/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "SELinux Utilities" diff --git a/shell/Config.src b/shell/Config.src index 81c4ec874..959d3cb42 100644 --- a/shell/Config.src +++ b/shell/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Shells" diff --git a/sysklogd/Config.src b/sysklogd/Config.src index 684e7d414..321be0117 100644 --- a/sysklogd/Config.src +++ b/sysklogd/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "System Logging Utilities" diff --git a/util-linux/Config.src b/util-linux/Config.src index 68fcc266f..0fad3e5c0 100644 --- a/util-linux/Config.src +++ b/util-linux/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Linux System Utilities" diff --git a/util-linux/volume_id/Config.src b/util-linux/volume_id/Config.src index ac208c9cc..fe3b14a71 100644 --- a/util-linux/volume_id/Config.src +++ b/util-linux/volume_id/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # config VOLUMEID -- cgit v1.2.3-55-g6feb From 57dbe4d5ac483f928b6e80b33993c8fd6a061aa7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jun 2018 09:43:38 +0200 Subject: libbb: crypt() in newer glibc requires include Signed-off-by: Denys Vlasenko --- libbb/pw_encrypt.c | 1 + 1 file changed, 1 insertion(+) (limited to 'libbb') diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c index 1edf4b6f0..86455cd0d 100644 --- a/libbb/pw_encrypt.c +++ b/libbb/pw_encrypt.c @@ -6,6 +6,7 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +#include #include "libbb.h" /* static const uint8_t ascii64[] ALIGN1 = -- cgit v1.2.3-55-g6feb From 335766602b2598f29a3dd854654b9ba9edb6d7cb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 28 Jun 2018 14:10:00 +0200 Subject: testsuite/mount.tests: fix false positive Signed-off-by: Denys Vlasenko --- libbb/loop.c | 4 ++++ testsuite/mount.tests | 2 ++ 2 files changed, 6 insertions(+) (limited to 'libbb') diff --git a/libbb/loop.c b/libbb/loop.c index f0d4296ae..c78535a20 100644 --- a/libbb/loop.c +++ b/libbb/loop.c @@ -106,6 +106,10 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse return -errno; } +//TODO: use LOOP_CTL_GET_FREE instead of trying every loopN in sequence? a-la: +// fd = open("/dev/loop-control", O_RDWR); +// loopN = ioctl(fd, LOOP_CTL_GET_FREE); +// /* Find a loop device. */ try = *device ? *device : dev; /* 1048575 (0xfffff) is a max possible minor number in Linux circa 2010 */ diff --git a/testsuite/mount.tests b/testsuite/mount.tests index a0bc50888..91c2e8b42 100755 --- a/testsuite/mount.tests +++ b/testsuite/mount.tests @@ -10,9 +10,11 @@ test "`id -u`" = 0 || { exit 0 } +# Without MOUNT_LOOP_CREATE, the test will fail if /dev/loopN's do not exist if test x"$CONFIG_MKFS_MINIX" != x"y" \ || test x"$CONFIG_FEATURE_MINIX2" != x"y" \ || test x"$CONFIG_FEATURE_MOUNT_LOOP" != x"y" \ +|| test x"$CONFIG_FEATURE_MOUNT_LOOP_CREATE" != x"y" \ || test x"$CONFIG_FEATURE_MOUNT_FLAGS" != x"y" \ || test x"$CONFIG_FEATURE_DEVFS" = x"y" \ ; then -- cgit v1.2.3-55-g6feb From e5d5f5b9a770de5a48d1a3bd293d5d611d6624c4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 3 Jul 2018 16:27:54 +0200 Subject: hexdump: fix short file of zero butes treated as dup function old new delta bb_dump_dump 1466 1491 +25 Signed-off-by: Denys Vlasenko --- libbb/dump.c | 14 +++++++++----- testsuite/hexdump.tests | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100755 testsuite/hexdump.tests (limited to 'libbb') diff --git a/libbb/dump.c b/libbb/dump.c index 5941ef902..b4b49d709 100644 --- a/libbb/dump.c +++ b/libbb/dump.c @@ -387,7 +387,10 @@ static unsigned char *get(priv_dumper_t *dumper) if (need == blocksize) { return NULL; } - if (dumper->pub.dump_vflag != ALL && !memcmp(dumper->get__curp, dumper->get__savp, nread)) { + if (dumper->pub.dump_vflag != ALL /* not "show all"? */ + && dumper->pub.dump_vflag != FIRST /* not first line? */ + && memcmp(dumper->get__curp, dumper->get__savp, nread) == 0 /* same data? */ + ) { if (dumper->pub.dump_vflag != DUP) { puts("*"); } @@ -399,7 +402,7 @@ static unsigned char *get(priv_dumper_t *dumper) } n = fread(dumper->get__curp + nread, sizeof(unsigned char), dumper->pub.dump_length == -1 ? need : MIN(dumper->pub.dump_length, need), stdin); - if (!n) { + if (n == 0) { if (ferror(stdin)) { bb_simple_perror_msg(dumper->argv[-1]); } @@ -411,9 +414,10 @@ static unsigned char *get(priv_dumper_t *dumper) dumper->pub.dump_length -= n; } need -= n; - if (!need) { - if (dumper->pub.dump_vflag == ALL || dumper->pub.dump_vflag == FIRST - || memcmp(dumper->get__curp, dumper->get__savp, blocksize) + if (need == 0) { + if (dumper->pub.dump_vflag == ALL /* "show all"? */ + || dumper->pub.dump_vflag == FIRST /* first line? */ + || memcmp(dumper->get__curp, dumper->get__savp, blocksize) != 0 /* not same data? */ ) { if (dumper->pub.dump_vflag == DUP || dumper->pub.dump_vflag == FIRST) { dumper->pub.dump_vflag = WAIT; diff --git a/testsuite/hexdump.tests b/testsuite/hexdump.tests new file mode 100755 index 000000000..45a0c1300 --- /dev/null +++ b/testsuite/hexdump.tests @@ -0,0 +1,18 @@ +#!/bin/sh + +# Copyright 2018 by Denys Vlasenko +# Licensed under GPLv2, see file LICENSE in this source tree. + +. ./testing.sh + +# testing "description" "command" "result" "infile" "stdin" +testing 'hexdump -C with four NULs' \ + 'hexdump -C' \ + "\ +00000000 00 00 00 00 |....| +00000004 +" \ + '' \ + '\0\0\0\0' + +exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From 253f555f01fa380083a7436a569397a4e7f997b0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jul 2018 18:23:33 +0200 Subject: usage: do not print trailing space for commands which have no arguments function old new delta bb_show_usage 120 130 +10 Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'libbb') diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 769b7881c..f155d0908 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -169,8 +169,11 @@ void FAST_FUNC bb_show_usage(void) else { full_write2_str("\nUsage: "); full_write2_str(applet_name); - full_write2_str(" "); - full_write2_str(p); + if (p[0]) { + if (p[0] != '\n') + full_write2_str(" "); + full_write2_str(p); + } full_write2_str("\n"); } if (ENABLE_FEATURE_CLEAN_UP) -- cgit v1.2.3-55-g6feb From 79fb6ac7a5acc4178b66314c573aeada1d387ed9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 13 Jul 2018 20:30:02 +0200 Subject: cp: optional --reflink support function old new delta cp_main 428 512 +84 copy_file 1676 1742 +66 Signed-off-by: Denys Vlasenko --- coreutils/cp.c | 24 ++++++++++++++++++++++++ include/libbb.h | 3 +++ libbb/copy_file.c | 19 +++++++++++++++++++ 3 files changed, 46 insertions(+) (limited to 'libbb') diff --git a/coreutils/cp.c b/coreutils/cp.c index 455bffbba..b623aaf33 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -24,6 +24,11 @@ //config: help //config: Enable long options. //config: Also add support for --parents option. +//config: +//config:config FEATURE_CP_REFLINK +//config: bool "Enable --reflink[=auto] +//config: default y +//config: depends on FEATURE_CP_LONG_OPTIONS //applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp)) /* NOEXEC despite cases when it can be a "runner" (cp -r LARGE_DIR NEW_DIR) */ @@ -72,10 +77,14 @@ int cp_main(int argc, char **argv) #if ENABLE_FEATURE_CP_LONG_OPTIONS /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTNUM */ OPT_parents = 1 << (FILEUTILS_CP_OPTNUM+1), + OPT_reflink = 1 << (FILEUTILS_CP_OPTNUM+2), #endif }; #if ENABLE_FEATURE_CP_LONG_OPTIONS +# if ENABLE_FEATURE_CP_REFLINK + char *reflink = NULL; +# endif flags = getopt32long(argv, "^" FILEUTILS_CP_OPTSTR "\0" @@ -99,7 +108,22 @@ int cp_main(int argc, char **argv) "update\0" No_argument "u" "remove-destination\0" No_argument "\xff" "parents\0" No_argument "\xfe" +# if ENABLE_FEATURE_CP_REFLINK + "reflink\0" Optional_argument "\xfd" + , &reflink +# endif ); +# if ENABLE_FEATURE_CP_REFLINK + BUILD_BUG_ON(OPT_reflink != FILEUTILS_REFLINK); + if (flags & FILEUTILS_REFLINK) { + if (!reflink) + flags |= FILEUTILS_REFLINK_ALWAYS; + else if (strcmp(reflink, "always") == 0) + flags |= FILEUTILS_REFLINK_ALWAYS; + else if (strcmp(reflink, "auto") != 0) + bb_show_usage(); + } +# endif #else flags = getopt32(argv, "^" FILEUTILS_CP_OPTSTR diff --git a/include/libbb.h b/include/libbb.h index d4ba031df..94caba2bb 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -410,6 +410,9 @@ enum { /* cp.c, mv.c, install.c depend on these values. CAREFUL when changing th FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 15, /* -c */ #endif FILEUTILS_RMDEST = 1 << (16 - !ENABLE_SELINUX), /* --remove-destination */ + /* bit 17 skipped for "cp --parents" */ + FILEUTILS_REFLINK = 1 << (18 - !ENABLE_SELINUX), /* cp --reflink=auto */ + FILEUTILS_REFLINK_ALWAYS = 1 << (19 - !ENABLE_SELINUX), /* cp --reflink[=always] */ /* * Hole. cp may have some bits set here, * they should not affect remove_file()/copy_file() diff --git a/libbb/copy_file.c b/libbb/copy_file.c index 1b8befd65..98bd4fe72 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c @@ -339,9 +339,28 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) freecon(con); } } +#endif +#if ENABLE_FEATURE_CP_REFLINK +# undef BTRFS_IOCTL_MAGIC +# define BTRFS_IOCTL_MAGIC 0x94 +# undef BTRFS_IOC_CLONE +# define BTRFS_IOC_CLONE _IOW (BTRFS_IOCTL_MAGIC, 9, int) + if (flags & FILEUTILS_REFLINK) { + retval = ioctl(dst_fd, BTRFS_IOC_CLONE, src_fd); + if (retval == 0) + goto do_close; + /* reflink did not work */ + if (flags & FILEUTILS_REFLINK_ALWAYS) { + bb_perror_msg("failed to clone '%s' from '%s'", dest, source); + goto do_close; + } + /* fall through to standard copy */ + retval = 0; + } #endif if (bb_copyfd_eof(src_fd, dst_fd) == -1) retval = -1; + IF_FEATURE_CP_REFLINK(do_close:) /* Careful with writing... */ if (close(dst_fd) < 0) { bb_perror_msg("error writing to '%s'", dest); -- cgit v1.2.3-55-g6feb From 4c201c00a3650cdacad5fc098ca255416687fb0f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 17 Jul 2018 15:04:17 +0200 Subject: whitespace fixes Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 2 +- libbb/nuke_str.c | 2 +- shell/hush.c | 6 +++--- shell/random.c | 12 ++++++------ util-linux/unshare.c | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) (limited to 'libbb') diff --git a/libbb/appletlib.c b/libbb/appletlib.c index f155d0908..319bcc263 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -737,7 +737,7 @@ static void install_links(const char *busybox, int use_symbolic_links, * busybox.h::bb_install_loc_t, or else... */ int (*lf)(const char *, const char *); char *fpc; - const char *appname = applet_names; + const char *appname = applet_names; unsigned i; int rc; diff --git a/libbb/nuke_str.c b/libbb/nuke_str.c index 240e68004..b5385e956 100644 --- a/libbb/nuke_str.c +++ b/libbb/nuke_str.c @@ -12,7 +12,7 @@ void FAST_FUNC nuke_str(char *str) { - if (str) { + if (str) { while (*str) *str++ = 0; /* or: memset(str, 0, strlen(str)); - not as small as above */ diff --git a/shell/hush.c b/shell/hush.c index 238f997da..7da8f334c 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2470,7 +2470,7 @@ static void reinit_unicode_for_hush(void) */ if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV || ENABLE_UNICODE_USING_LOCALE - ) { + ) { const char *s = get_local_var_value("LC_ALL"); if (!s) s = get_local_var_value("LC_CTYPE"); if (!s) s = get_local_var_value("LANG"); @@ -5795,8 +5795,8 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int */ setup_string_in_str(&input, str); - o_addchr(&dest, '\0'); - dest.length = 0; + o_addchr(&dest, '\0'); + dest.length = 0; exp_str = NULL; for (;;) { diff --git a/shell/random.c b/shell/random.c index 5d3620516..56c7c5a3c 100644 --- a/shell/random.c +++ b/shell/random.c @@ -46,11 +46,11 @@ next_random(random_t *rnd) * Choices for a,b,c: 10,13,10; 8,9,22; 2,7,3; 23,3,24 * (given by algorithm author) */ - enum { - a = 2, - b = 7, - c = 3, - }; + enum { + a = 2, + b = 7, + c = 3, + }; uint32_t t; @@ -154,7 +154,7 @@ int main(int argc, char **argv) write(1, buf, sizeof(buf)); } - return 0; + return 0; } #endif diff --git a/util-linux/unshare.c b/util-linux/unshare.c index 7c295da1f..fffee28a0 100644 --- a/util-linux/unshare.c +++ b/util-linux/unshare.c @@ -73,7 +73,7 @@ #include "libbb.h" static void mount_or_die(const char *source, const char *target, - const char *fstype, unsigned long mountflags) + const char *fstype, unsigned long mountflags) { if (mount(source, target, fstype, mountflags, NULL)) { bb_perror_msg_and_die("can't mount %s on %s (flags:0x%lx)", -- cgit v1.2.3-55-g6feb From 41ef41b3e0a16c9f8524870a2dc4f768c237939e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 24 Jul 2018 16:54:41 +0200 Subject: hush: fix nested redirects colliding with script fds This necessitates switch from libc FILE api to a simple homegrown replacement. The change which fixes the bug here is the deleting of restore_redirected_FILEs(); line. It was prematurely moving (restoring) script fd#3. The fix is: we don't even _want_ to restore scrit fds, we are perfectly fine with them being moved. The only reason we tried to restore them is that FILE api did not allow moving of FILE->fd. function old new delta refill_HFILE_and_getc - 93 +93 hfopen - 90 +90 hfclose - 66 +66 pseudo_exec_argv 591 597 +6 hush_main 1089 1095 +6 builtin_source 209 214 +5 save_fd_on_redirect 197 200 +3 setup_redirects 320 321 +1 fgetc_interactive 235 236 +1 i_peek_and_eat_bkslash_nl 99 97 -2 expand_vars_to_list 1103 1100 -3 restore_redirects 99 52 -47 fclose_and_forget 57 - -57 remember_FILE 63 - -63 ------------------------------------------------------------------------------ (add/remove: 3/2 grow/shrink: 6/3 up/down: 271/-172) Total: 99 bytes Signed-off-by: Denys Vlasenko --- libbb/xfuncs_printf.c | 1 + shell/ash_test/ash-heredoc/heredocB.right | 3 + shell/ash_test/ash-heredoc/heredocB.tests | 12 ++ shell/ash_test/ash-redir/redir_script.tests | 4 + shell/hush.c | 234 +++++++++++++++----------- shell/hush_test/hush-heredoc/heredocB.right | 3 + shell/hush_test/hush-heredoc/heredocB.tests | 12 ++ shell/hush_test/hush-redir/redir_script.tests | 4 + 8 files changed, 175 insertions(+), 98 deletions(-) create mode 100644 shell/ash_test/ash-heredoc/heredocB.right create mode 100755 shell/ash_test/ash-heredoc/heredocB.tests create mode 100644 shell/hush_test/hush-heredoc/heredocB.right create mode 100755 shell/hush_test/hush-heredoc/heredocB.tests (limited to 'libbb') diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 7247c915b..6cc60f6c0 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c @@ -222,6 +222,7 @@ void FAST_FUNC xdup2(int from, int to) { if (dup2(from, to) != to) bb_perror_msg_and_die("can't duplicate file descriptor"); + // " %d to %d", from, to); } // "Renumber" opened fd diff --git a/shell/ash_test/ash-heredoc/heredocB.right b/shell/ash_test/ash-heredoc/heredocB.right new file mode 100644 index 000000000..43ba0b4f9 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredocB.right @@ -0,0 +1,3 @@ +one - alpha +two - beta +three - gamma diff --git a/shell/ash_test/ash-heredoc/heredocB.tests b/shell/ash_test/ash-heredoc/heredocB.tests new file mode 100755 index 000000000..45ea4687f --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredocB.tests @@ -0,0 +1,12 @@ +while read line1; do + read line2 <&3 + echo $line1 - $line2 +done <&- 3>&-" && \ test x"$fds" = x" 11>&- 3>&-" \ && { echo "Ok: script fd is not closed"; exit 0; } +# or we see that fd 3 moved to fd 10: +test x"$fds1" = x" 3>&- 4>&-" && \ +test x"$fds" = x" 10>&- 3>&-" \ +&& { echo "Ok: script fd is not closed"; exit 0; } echo "Bug: script fd is closed" echo "fds1:$fds1" diff --git a/shell/hush.c b/shell/hush.c index c26484b49..7a1513c24 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -357,6 +357,9 @@ #else # define CLEAR_RANDOM_T(rnd) ((void)0) #endif +#ifndef O_CLOEXEC +# define O_CLOEXEC 0 +#endif #ifndef F_DUPFD_CLOEXEC # define F_DUPFD_CLOEXEC F_DUPFD #endif @@ -556,11 +559,27 @@ static const char *const assignment_flag[] = { }; #endif +/* We almost can use standard FILE api, but we need an ability to move + * its fd when redirects coincide with it. No api exists for that + * (RFE for it at https://sourceware.org/bugzilla/show_bug.cgi?id=21902). + * HFILE is our internal alternative. Only supports reading. + * Since we now can, we incorporate linked list of all opened HFILEs + * into the struct (used to be a separate mini-list). + */ +typedef struct HFILE { + char *cur; + char *end; + struct HFILE *next_hfile; + int is_stdin; + int fd; + char buf[1024]; +} HFILE; + typedef struct in_str { const char *p; int peek_buf[2]; int last_char; - FILE *file; + HFILE *file; } in_str; /* The descrip member of this structure is only used to make @@ -814,14 +833,6 @@ enum { NUM_OPT_O }; - -struct FILE_list { - struct FILE_list *next; - FILE *fp; - int fd; -}; - - /* "Globals" within this file */ /* Sorted roughly by size (smaller offsets == smaller code) */ struct globals { @@ -954,7 +965,7 @@ struct globals { unsigned lineno; char *lineno_var; #endif - struct FILE_list *FILE_list; + HFILE *HFILE_list; /* Which signals have non-DFL handler (even with no traps set)? * Set at the start to: * (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS) @@ -1563,83 +1574,115 @@ static int xdup_CLOEXEC_and_close(int fd, int avoid_fd) } -/* Manipulating the list of open FILEs */ -static FILE *remember_FILE(FILE *fp) +/* Manipulating HFILEs */ +static HFILE *hfopen(const char *name) { - if (fp) { - struct FILE_list *n = xmalloc(sizeof(*n)); - n->next = G.FILE_list; - G.FILE_list = n; - n->fp = fp; - n->fd = fileno(fp); - close_on_exec_on(n->fd); + HFILE *fp; + int fd; + + fd = STDIN_FILENO; + if (name) { + fd = open(name, O_RDONLY | O_CLOEXEC); + if (fd < 0) + return NULL; + if (O_CLOEXEC == 0) /* ancient libc */ + close_on_exec_on(fd); } + + fp = xmalloc(sizeof(*fp)); + fp->is_stdin = (name == NULL); + fp->fd = fd; + fp->cur = fp->end = fp->buf; + fp->next_hfile = G.HFILE_list; + G.HFILE_list = fp; return fp; } -static void fclose_and_forget(FILE *fp) +static void hfclose(HFILE *fp) { - struct FILE_list **pp = &G.FILE_list; + HFILE **pp = &G.HFILE_list; while (*pp) { - struct FILE_list *cur = *pp; - if (cur->fp == fp) { - *pp = cur->next; - free(cur); + HFILE *cur = *pp; + if (cur == fp) { + *pp = cur->next_hfile; break; } - pp = &cur->next; + pp = &cur->next_hfile; } - fclose(fp); + if (fp->fd >= 0) + close(fp->fd); + free(fp); } -static int save_FILEs_on_redirect(int fd, int avoid_fd) +static int refill_HFILE_and_getc(HFILE *fp) { - struct FILE_list *fl = G.FILE_list; + int n; + + if (fp->fd < 0) { + /* Already saw EOF */ + return EOF; + } + /* Try to buffer more input */ + fp->cur = fp->buf; + n = safe_read(fp->fd, fp->buf, sizeof(fp->buf)); + if (n < 0) { + bb_perror_msg("read error"); + n = 0; + } + fp->end = fp->buf + n; + if (n == 0) { + /* EOF/error */ + close(fp->fd); + fp->fd = -1; + return EOF; + } + return (unsigned char)(*fp->cur++); +} +/* Inlined for common case of non-empty buffer. + */ +static ALWAYS_INLINE int hfgetc(HFILE *fp) +{ + if (fp->cur < fp->end) + return (unsigned char)(*fp->cur++); + /* Buffer empty */ + return refill_HFILE_and_getc(fp); +} +static int move_HFILEs_on_redirect(int fd, int avoid_fd) +{ + HFILE *fl = G.HFILE_list; while (fl) { if (fd == fl->fd) { /* We use it only on script files, they are all CLOEXEC */ fl->fd = xdup_CLOEXEC_and_close(fd, avoid_fd); debug_printf_redir("redirect_fd %d: matches a script fd, moving it to %d\n", fd, fl->fd); - return 1; - } - fl = fl->next; - } - return 0; -} -static void restore_redirected_FILEs(void) -{ - struct FILE_list *fl = G.FILE_list; - while (fl) { - int should_be = fileno(fl->fp); - if (fl->fd != should_be) { - debug_printf_redir("restoring script fd from %d to %d\n", fl->fd, should_be); - xmove_fd(fl->fd, should_be); - fl->fd = should_be; + return 1; /* "found and moved" */ } - fl = fl->next; + fl = fl->next_hfile; } + return 0; /* "not in the list" */ } #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU -static void close_all_FILE_list(void) +static void close_all_HFILE_list(void) { - struct FILE_list *fl = G.FILE_list; + HFILE *fl = G.HFILE_list; while (fl) { - /* fclose would also free FILE object. + /* hfclose would also free HFILE object. * It is disastrous if we share memory with a vforked parent. * I'm not sure we never come here after vfork. * Therefore just close fd, nothing more. */ - /*fclose(fl->fp); - unsafe */ - close(fl->fd); - fl = fl->next; + /*hfclose(fl); - unsafe */ + if (fl->fd >= 0) + close(fl->fd); + fl = fl->next_hfile; } } #endif -static int fd_in_FILEs(int fd) +static int fd_in_HFILEs(int fd) { - struct FILE_list *fl = G.FILE_list; + HFILE *fl = G.HFILE_list; while (fl) { if (fl->fd == fd) return 1; - fl = fl->next; + fl = fl->next_hfile; } return 0; } @@ -2580,7 +2623,7 @@ static int get_user_input(struct in_str *i) } fflush_all(); //FIXME: here ^C or SIGINT will have effect only after - r = fgetc(i->file); + r = hfgetc(i->file); /* In !ENABLE_FEATURE_EDITING we don't use read_line_input, * no ^C masking happens during fgetc, no special code for ^C: * it generates SIGINT as usual. @@ -2600,22 +2643,22 @@ static int fgetc_interactive(struct in_str *i) { int ch; /* If it's interactive stdin, get new line. */ - if (G_interactive_fd && i->file == stdin) { + if (G_interactive_fd && i->file->is_stdin) { /* Returns first char (or EOF), the rest is in i->p[] */ ch = get_user_input(i); G.promptmode = 1; /* PS2 */ debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode); } else { /* Not stdin: script file, sourced file, etc */ - do ch = fgetc(i->file); while (ch == '\0'); + do ch = hfgetc(i->file); while (ch == '\0'); } return ch; } #else -static inline int fgetc_interactive(struct in_str *i) +static ALWAYS_INLINE int fgetc_interactive(struct in_str *i) { int ch; - do ch = fgetc(i->file); while (ch == '\0'); + do ch = hfgetc(i->file); while (ch == '\0'); return ch; } #endif /* INTERACTIVE */ @@ -2730,7 +2773,7 @@ static int i_peek2(struct in_str *i) ch = i->peek_buf[1]; if (ch == 0) { /* We did not read it yet, get it now */ - do ch = fgetc(i->file); while (ch == '\0'); + do ch = hfgetc(i->file); while (ch == '\0'); i->peek_buf[1] = ch; } @@ -2774,10 +2817,10 @@ static int i_peek_and_eat_bkslash_nl(struct in_str *input) } } -static void setup_file_in_str(struct in_str *i, FILE *f) +static void setup_file_in_str(struct in_str *i, HFILE *fp) { memset(i, 0, sizeof(*i)); - i->file = f; + i->file = fp; /* i->p = NULL; */ } @@ -7106,19 +7149,19 @@ static void parse_and_run_string(const char *s) //IF_HUSH_LINENO_VAR(G.lineno = sv;) } -static void parse_and_run_file(FILE *f) +static void parse_and_run_file(HFILE *fp) { struct in_str input; IF_HUSH_LINENO_VAR(unsigned sv = G.lineno;) IF_HUSH_LINENO_VAR(G.lineno = 1;) - setup_file_in_str(&input, f); + setup_file_in_str(&input, fp); parse_and_run_stream(&input, ';'); IF_HUSH_LINENO_VAR(G.lineno = sv;) } #if ENABLE_HUSH_TICK -static FILE *generate_stream_from_string(const char *s, pid_t *pid_p) +static int generate_stream_from_string(const char *s, pid_t *pid_p) { pid_t pid; int channel[2]; @@ -7220,7 +7263,7 @@ static FILE *generate_stream_from_string(const char *s, pid_t *pid_p) free(to_free); # endif close(channel[1]); - return remember_FILE(xfdopen_for_read(channel[0])); + return channel[0]; } /* Return code is exit status of the process that is run. */ @@ -7230,7 +7273,7 @@ static int process_command_subs(o_string *dest, const char *s) pid_t pid; int status, ch, eol_cnt; - fp = generate_stream_from_string(s, &pid); + fp = xfdopen_for_read(generate_stream_from_string(s, &pid)); /* Now send results of command back into original context */ eol_cnt = 0; @@ -7249,7 +7292,7 @@ static int process_command_subs(o_string *dest, const char *s) } debug_printf("done reading from `cmd` pipe, closing it\n"); - fclose_and_forget(fp); + fclose(fp); /* We need to extract exitcode. Test case * "true; echo `sleep 1; false` $?" * should print 1 */ @@ -7427,20 +7470,17 @@ static int save_fd_on_redirect(int fd, int avoid_fd, struct squirrel **sqp) return 1; /* "we closed fd" */ } #endif + /* If this one of script's fds? */ + if (move_HFILEs_on_redirect(fd, avoid_fd)) + return 1; /* yes. "we closed fd" (actually moved it) */ + /* Are we called from setup_redirects(squirrel==NULL)? Two cases: - * (1) Redirect in a forked child. No need to save FILEs' fds, - * we aren't going to use them anymore, ok to trash. - * (2) "exec 3>FILE". Bummer. We can save script FILEs' fds, - * but how are we doing to restore them? - * "fileno(fd) = new_fd" can't be done. + * (1) Redirect in a forked child. + * (2) "exec 3>FILE". */ if (!sqp) return 0; - /* If this one of script's fds? */ - if (save_FILEs_on_redirect(fd, avoid_fd)) - return 1; /* yes. "we closed fd" */ - /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */ *sqp = add_squirrel(*sqp, fd, avoid_fd); return 0; /* "we did not close fd" */ @@ -7465,8 +7505,6 @@ static void restore_redirects(struct squirrel *sq) } /* If moved, G.interactive_fd stays on new fd, not restoring it */ - - restore_redirected_FILEs(); } #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU @@ -7474,7 +7512,7 @@ static void close_saved_fds_and_FILE_fds(void) { if (G_interactive_fd) close(G_interactive_fd); - close_all_FILE_list(); + close_all_HFILE_list(); } #endif @@ -7487,7 +7525,7 @@ static int internally_opened_fd(int fd, struct squirrel *sq) return 1; #endif /* If this one of script's fds? */ - if (fd_in_FILEs(fd)) + if (fd_in_HFILEs(fd)) return 1; if (sq) for (i = 0; sq[i].orig_fd >= 0; i++) { @@ -7512,7 +7550,7 @@ static int setup_redirects(struct command *prog, struct squirrel **sqp) save_fd_on_redirect(redir->rd_fd, /*avoid:*/ 0, sqp); /* for REDIRECT_HEREDOC2, rd_filename holds _contents_ * of the heredoc */ - debug_printf_parse("set heredoc '%s'\n", + debug_printf_redir("set heredoc '%s'\n", redir->rd_filename); setup_heredoc(redir); continue; @@ -7524,8 +7562,7 @@ static int setup_redirects(struct command *prog, struct squirrel **sqp) int mode; if (redir->rd_filename == NULL) { - /* - * Examples: + /* Examples: * "cmd >" (no filename) * "cmd > " (which is never interactive (unless -i?)) * sources $BASH_ENV here (without scanning $PATH). @@ -9902,13 +9938,15 @@ int hush_main(int argc, char **argv) G.global_argv++; debug_printf("running script '%s'\n", G.global_argv[0]); xfunc_error_retval = 127; /* for "hush /does/not/exist" case */ - input = xfopen_for_read(G.global_argv[0]); + input = hfopen(G.global_argv[0]); + if (!input) { + bb_simple_perror_msg_and_die(G.global_argv[0]); + } xfunc_error_retval = 1; - remember_FILE(input); install_special_sighandlers(); parse_and_run_file(input); #if ENABLE_FEATURE_CLEAN_UP - fclose_and_forget(input); + hfclose(input); #endif goto final_return; } @@ -10038,7 +10076,7 @@ int hush_main(int argc, char **argv) ); } - parse_and_run_file(stdin); + parse_and_run_file(hfopen(NULL)); /* stdin */ final_return: hush_exit(G.last_exitcode); @@ -10849,7 +10887,7 @@ Test that VAR is a valid variable name? static int FAST_FUNC builtin_source(char **argv) { char *arg_path, *filename; - FILE *input; + HFILE *input; save_arg_t sv; char *args_need_save; #if ENABLE_HUSH_FUNCTIONS @@ -10873,10 +10911,10 @@ static int FAST_FUNC builtin_source(char **argv) return EXIT_FAILURE; } } - input = remember_FILE(fopen_or_warn(filename, "r")); + input = hfopen(filename); free(arg_path); if (!input) { - /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ + bb_perror_msg("%s", filename); /* POSIX: non-interactive shell should abort here, * not merely fail. So far no one complained :) */ @@ -10895,7 +10933,7 @@ static int FAST_FUNC builtin_source(char **argv) /* "false; . ./empty_line; echo Zero:$?" should print 0 */ G.last_exitcode = 0; parse_and_run_file(input); - fclose_and_forget(input); + hfclose(input); if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */ restore_G_args(&sv, argv); diff --git a/shell/hush_test/hush-heredoc/heredocB.right b/shell/hush_test/hush-heredoc/heredocB.right new file mode 100644 index 000000000..43ba0b4f9 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredocB.right @@ -0,0 +1,3 @@ +one - alpha +two - beta +three - gamma diff --git a/shell/hush_test/hush-heredoc/heredocB.tests b/shell/hush_test/hush-heredoc/heredocB.tests new file mode 100755 index 000000000..45ea4687f --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredocB.tests @@ -0,0 +1,12 @@ +while read line1; do + read line2 <&3 + echo $line1 - $line2 +done <&- 3>&-" && \ test x"$fds" = x" 11>&- 3>&-" \ && { echo "Ok: script fd is not closed"; exit 0; } +# or we see that fd 3 moved to fd 10: +test x"$fds1" = x" 3>&- 4>&-" && \ +test x"$fds" = x" 10>&- 3>&-" \ +&& { echo "Ok: script fd is not closed"; exit 0; } echo "Bug: script fd is closed" echo "fds1:$fds1" -- cgit v1.2.3-55-g6feb