On Mon, 25 Apr 2022 16:56:50 +0000 rkne...@pm.me wrote: > Hi Tito, > > Thanks again for your valuable feedback for V2. I fixed your remarks in V3. > Could you please have a look at V3? > > If you are ok with the changes I would like to ask you for a sign-off so that > we can hopefully merge the tree tool soon.
Hi, looks good to me, maybe just the global vars could be removed... I don't think there is a need for me to sign-off as I have no superpowers, you need just to wait for the maintainer to say the final word. Ciao, Tito > Thanks, > Roger > > ------- Original Message ------- > On Monday, April 18th, 2022 at 2:54 PM, Roger Knecht <rkne...@pm.me> wrote: > > > > > > > > Adds the tree program to list directories and files in a tree structure. > > > > function old new delta > > tree_print - 388 +388 > > .rodata 95677 95766 +89 > > tree_main - 73 +73 > > tree_print_prefix - 28 +28 > > globals - 8 +8 > > applet_main 3192 3200 +8 > > applet_names 2747 2752 +5 > > packed_usage 34414 34396 -18 > > ------------------------------------------------------------------------------ > > (add/remove: 5/0 grow/shrink: 3/1 up/down: 599/-18) Total: 581 bytes > > > > Signed-off-by: Roger Knecht rkne...@pm.me > > > > --- > > V4 is addressing Tito's remark regarding the symlink and multiple > > directory handling. > > > > Changelog: > > > > 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 jie.zh...@analog.com > > > > > > Maxime Coste ma...@kakoune.org > > > > paste implementation > > + > > +Roger Knecht rkne...@pm.me > > > > + tree > > diff --git a/miscutils/tree.c b/miscutils/tree.c > > new file mode 100644 > > index 000000000..e053e8483 > > --- /dev/null > > +++ b/miscutils/tree.c > > @@ -0,0 +1,135 @@ > > +/* vi: set sw=4 ts=4: / > > +/ > > + * Copyright (C) 2022 Roger Knecht rkne...@pm.me > > > > + * > > + * 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, &entries, 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 > > + if (strncmp(dirent->d_name, ".", 1) != 0) { > > > > + is_file = !is_directory(dirent->d_name, 1); > > > > + is_not_last = (index + 1) < size; > > + symlink_path = xmalloc_readlink(dirent->d_name); > > > > + > > + // print tree line prefix > > + tree_print_prefix(directory); > > + > > + if (is_not_last) { > > + child_directory.prefix = PREFIX_GRAND_CHILD; > > + fputs_stdout(PREFIX_CHILD); > > + } else { > > + child_directory.prefix = PREFIX_LAST_GRAND_CHILD; > > + fputs_stdout(PREFIX_LAST_CHILD); > > + } > > + > > + // count directories and files > > + if (is_file) > > + globals.files++; > > + else > > + globals.directories++; > > + > > + if (symlink_path) { > > + // handle symlink > > + printf("%s -> %s\n", dirent->d_name, symlink_path); > > > > + free(symlink_path); > > + } else if (is_file) > > + // handle file > > + puts(dirent->d_name); > > > > + else > > + // handle directory > > + tree_print(dirent->d_name, &child_directory); > > > > + } > > + > > + // release directory entry > > + free(dirent); > > + } > > + > > + // release directory array > > + free(entries); > > + > > + // switch to parent directory > > + xchdir(".."); > > +} > > + > > +int tree_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; > > +int tree_main(int argc, char **argv) > > +{ > > + if (argc == 1) > > + // list current working directory > > + tree_print(DEFAULT_PATH, NULL); > > + > > + // list directories given as command line arguments > > + while (*(++argv)) > > + tree_print(*argv, NULL); > > + > > + // print statistic > > + printf("\n%d directories, %d files\n", globals.directories, > > globals.files); > > + > > + return EXIT_SUCCESS; > > +} > > diff --git a/testsuite/tree.tests b/testsuite/tree.tests > > new file mode 100755 > > index 000000000..bad28d46c > > --- /dev/null > > +++ b/testsuite/tree.tests > > @@ -0,0 +1,97 @@ > > +#!/bin/sh > > + > > +# Copyright 2022 by Roger Knecht rkne...@pm.me > > > > +# Licensed under GPLv2, see file LICENSE in this source tree. > > + > > +. ./testing.sh -v > > + > > +# testing "description" "command" "result" "infile" "stdin" > > + > > +testing "tree error opening dir" \ > > + "tree tree.tempdir" \ > > + "\ > > +tree.tempdir [error opening dir]\n\ > > +\n\ > > +0 directories, 0 files\n" \ > > + "" "" > > + > > +mkdir -p tree2.tempdir > > +touch tree2.tempdir/testfile > > + > > +testing "tree single file" \ > > + "cd tree2.tempdir && tree" \ > > + "\ > > +.\n\ > > +└── testfile\n\ > > +\n\ > > +0 directories, 1 files\n" \ > > + "" "" > > + > > +mkdir -p tree3.tempdir/test1 \ > > + tree3.tempdir/test2/a \ > > + tree3.tempdir/test2/b \ > > + tree3.tempdir/test3/c \ > > + tree3.tempdir/test3/d > > + > > +touch tree3.tempdir/test2/a/testfile1 \ > > + tree3.tempdir/test2/a/testfile2 \ > > + tree3.tempdir/test2/a/testfile3 \ > > + tree3.tempdir/test2/b/testfile4 \ > > + tree3.tempdir/test3/c/testfile5 \ > > + tree3.tempdir/test3/d/testfile6 \ > > + tree3.tempdir/test3/d/.testfile7 > > + > > +(cd tree3.tempdir/test2/a && ln -s ../b/testfile4 .) > > +(cd tree3.tempdir/test2/b && ln -s ../../test3 .) > > + > > +testing "tree nested directories and files" \ > > + "cd tree3.tempdir && tree" \ > > + "\ > > +.\n\ > > +├── test1\n\ > > +├── test2\n\ > > +│ ├── a\n\ > > +│ │ ├── testfile1\n\ > > +│ │ ├── testfile2\n\ > > +│ │ ├── testfile3\n\ > > +│ │ └── testfile4 -> ../b/testfile4\n\ > > > > +│ └── b\n\ > > +│ ├── test3 -> ../../test3\n\ > > > > +│ └── testfile4\n\ > > +└── test3\n\ > > + ├── c\n\ > > + │ └── testfile5\n\ > > + └── d\n\ > > + └── testfile6\n\ > > +\n\ > > +8 directories, 7 files\n" \ > > + "" "" > > + > > +testing "tree multiple directories" \ > > + "tree tree2.tempdir tree3.tempdir" \ > > + "\ > > +tree2.tempdir\n\ > > +└── testfile\n\ > > +tree3.tempdir\n\ > > +├── test1\n\ > > +├── test2\n\ > > +│ ├── a\n\ > > +│ │ ├── testfile1\n\ > > +│ │ ├── testfile2\n\ > > +│ │ ├── testfile3\n\ > > +│ │ └── testfile4 -> ../b/testfile4\n\ > > > > +│ └── b\n\ > > +│ ├── test3 -> ../../test3\n\ > > > > +│ └── testfile4\n\ > > +└── test3\n\ > > + ├── c\n\ > > + │ └── testfile5\n\ > > + └── d\n\ > > + └── testfile6\n\ > > +\n\ > > +8 directories, 8 files\n" \ > > + "" "" > > + > > +rm -rf tree.tempdir tree2.tempdir tree3.tempdir > > + > > +exit $FAILCOUNT > > -- > > 2.17.1 _______________________________________________ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox