On Sun, 01 May 2022 12:51:16 +
Roger Knecht wrote:
> Add new applet which resembles the MS-DOS tree program to list directories
> and files in a tree structure.
>
> function old new delta
> tree_print - 388+388
> .rodata95678 95767 +89
> tree_main - 73 +73
> tree_print_prefix - 28 +28
> packed_usage 34417 34429 +12
> globals- 8 +8
> applet_main 31923200 +8
> applet_names27472752 +5
> --
> (add/remove: 5/0 grow/shrink: 4/0 up/down: 611/0) Total: 611 bytes
>
> Signed-off-by: Roger Knecht
> ---
> Changelog:
>
> V4:
> - Rephrase commit message
> - Updated bloatcheck to latest master
>
> V3:
> - Fixed symlink handling
> - Handle multiple directories in command line arguments
> - Extended tests for symlink and multiple directories
> - Reduced size by using libbb functions
>
> V2:
> - Fixed tree help text
> - Reduced size by 644 bytes
>
> AUTHORS | 3 +
> miscutils/tree.c | 135 +++
> testsuite/tree.tests | 97 +++
> 3 files changed, 235 insertions(+)
> create mode 100644 miscutils/tree.c
> create mode 100755 testsuite/tree.tests
>
> diff --git a/AUTHORS b/AUTHORS
> index 5c9a634c9..9ec0e2ee4 100644
> --- a/AUTHORS
> +++ b/AUTHORS
> @@ -181,3 +181,6 @@ Jie Zhang
>
> Maxime Coste
> paste implementation
> +
> +Roger Knecht
> +tree
> diff --git a/miscutils/tree.c b/miscutils/tree.c
> new file mode 100644
> index 0..e053e8483
> --- /dev/null
> +++ b/miscutils/tree.c
> @@ -0,0 +1,135 @@
> +/* vi: set sw=4 ts=4: */
> +/*
> + * Copyright (C) 2022 Roger Knecht
> + *
> + * Licensed under GPLv2, see file LICENSE in this source tree.
> + */
> +//config:config TREE
> +//config:bool "tree (0.6 kb)"
> +//config:default n
> +//config:help
> +//config:List files and directories in a tree structure.
> +//config:
> +
> +//applet:IF_TREE(APPLET(tree, BB_DIR_USR_BIN, BB_SUID_DROP))
> +
> +//kbuild:lib-$(CONFIG_TREE) += tree.o
> +
> +//usage:#define tree_trivial_usage NOUSAGE_STR
> +//usage:#define tree_full_usage ""
> +
> +#include "libbb.h"
> +
> +#define PREFIX_CHILD "├── "
> +#define PREFIX_LAST_CHILD "└── "
> +#define PREFIX_GRAND_CHILD "│ "
> +#define PREFIX_LAST_GRAND_CHILD ""
> +#define DEFAULT_PATH "."
> +
> +struct directory {
> + struct directory* parent;
> + const char* prefix;
> +};
> +
> +static struct globals {
> + int directories;
> + int files;
> +} globals;
> +
> +static void tree_print_prefix(struct directory* directory) {
> + if (directory) {
> + tree_print_prefix(directory->parent);
> + fputs_stdout(directory->prefix);
> + }
> +}
> +
> +static void tree_print(const char* directory_name, struct directory*
> directory) {
> + struct dirent **entries, *dirent;
> + struct directory child_directory;
> + char* symlink_path;
> + int index, size;
//> + bool is_not_last, is_file;
> +
> + // read directory entries
> + size = scandir(directory_name, , NULL, alphasort);
> +
> + if (size < 0) {
> + fputs_stdout(directory_name);
> + puts(" [error opening dir]");
> + return;
> + }
> +
> + // print directory name
> + puts(directory_name);
> +
> + // switch to sub directory
> + xchdir(directory_name);
> +
> + child_directory.parent = directory;
> +
> + // print all directory entries
> + for (index = 0; index < size; index++) {
> + dirent = entries[index];
> +
> + // filter hidden files and directories
Hi,
if (dirent->d_name[0] != '.') {
> + if (strncmp(dirent->d_name, ".", 1) != 0) {
twisted logic?
> + is_file = !is_directory(dirent->d_name, 1);
is_not_last is used only once
> + is_not_last = (index + 1) < size;
> + symlink_path = xmalloc_readlink(dirent->d_name);
> +
> + // print tree line prefix
> + tree_print_prefix(directory);
> +
if ((index + 1) < size) {
> + if (is_not_last) {
> + child_directory.prefix = PREFIX_GRAND_CHILD;
> + fputs_stdout(PREFIX_CHILD);
> + } else {
> + child_directory.prefix =
> PREFIX_LAST_GRAND_CHILD;
> +