[PATCH v2] Added miscutil/tree.c
tito
farmatito at tiscali.it
Sun Apr 17 08:10:50 UTC 2022
On Sat, 16 Apr 2022 21:13:02 +0200
tito <farmatito at tiscali.it> wrote:
> On Sat, 16 Apr 2022 16:54:19 +0000
> Roger Knecht <rknecht at pm.me> wrote:
>
> > Adds the tree program to list directories and files in a tree structure.
> >
> > function old new delta
> > static.tree_print - 352 +352
> > .rodata 95677 95756 +79
> > tree_main - 69 +69
> > globals - 24 +24
> > applet_main 3192 3200 +8
> > applet_names 2747 2752 +5
> > packed_usage 34414 34396 -18
> > ------------------------------------------------------------------------------
> > (add/remove: 4/0 grow/shrink: 3/1 up/down: 537/-18) Total: 519 bytes
> > ---
> > As Ron pointed out V1 was overwriting the find help text and therefore invalidating
> > the bloatcheck. V1 added 1171 bytes (not 349 bytes as originally mentioned).
> >
> > V2 is reducing the size by using scandir(), chdir() and avoiding string concatenations.
> >
> > Changelog:
> >
> > V2:
> > - Fixed tree help text
> > - Reduced size by 652 bytes
>
> Hi,
> just out of curiosity, for fun and to refresh my C skills I wrote
> an alternative version of tree that is somewhat similar to yours
> in using scandir.
>
> One problem I see in your V2 is that unlike real tree it does not
> handle multiple paths as command line args:
>
> tree dir dir2 dirn
>
> Also the use of DT_DIR is problematic as only some filesystems
> have full support.
On more minor glitch is that file and dir count differs from original
tree program when links are involved.
For example:
./busybox_unstripped tree ../../test/
../../test/
├── test1
│ └── a
├── test2
│ ├── b
│ ├── c
│ ├── k
│ └── test3
├── test4
├── test5
├── test6
└── test7
4 directories, 7 files
tree ../../test/
../../test/
├── test1
│ └── a
├── test2
│ ├── b
│ ├── c
│ ├── k -> b
│ └── test3
├── test4 -> test2
├── test5
├── test6 -> test7
└── test7 -> test6
5 directories, 6 files
Ciao,
Tito
>
> Bloatcheck is:
>
> function old new delta
> tree - 501 +501
> tree_main - 125 +125
> .rodata 99024 99106 +82
> packed_usage 34414 34448 +34
> applet_main 3192 3200 +8
> applet_names 2747 2752 +5
> ------------------------------------------------------------------------------
> (add/remove: 3/0 grow/shrink: 4/0 up/down: 755/0) Total: 755 bytes
> text data bss dec hex filename
> 1002271 16403 1848 1020522 f926a busybox_old
> 1003180 16427 1848 1021455 f960f busybox_unstripped
>
> Features are:
> 1) correct link handling:
>
> ./busybox tree ../../test/
> ../../test/
> ├── test1
> │ └── a
> ├── test2
> │ ├── b
> │ ├── c
> │ └── test3
> ├── test4 -> test2
> └── test5
>
> 2) Uses scandir and passes the testsuite.
> 3) It is worth mentioning that by using alphasort
> as sorting algorithm the output of complex trees
> is somewhat different in the ordering of files
> ( for example uppercase , lowercase)
> as the real tree program.
>
> For easier review code is attached as patch and
> also in the mail body.
>
> #include "libbb.h"
>
> #define HIDDEN(s) ((s)[0] == '.')
>
> #define CHILD "├── "
> #define LAST_CHILD "└── "
> #define GRAND_CHILD "│ "
> #define LAST_GRAND_CHILD " "
>
> #define MAX_CHILD_SIZE (MAX(MAX(MAX((sizeof(CHILD)), \
> (sizeof(LAST_CHILD))), \
> (sizeof(GRAND_CHILD))), \
> (sizeof(LAST_GRAND_CHILD))))
>
> static void tree(char *path, int *dcount, int *fcount, char **list)
> {
> int i = 0;
> int n;
> int l;
> char *fullpath = NULL;
> char *linkname = NULL;
> struct dirent **namelist;
>
> if ((n = scandir(path, &namelist, NULL, alphasort)) < 0) {
> printf("%s [error opening dir]\n", path);
> return;
> } else if (!**list) {
> printf("%s\n", path);
> }
>
> l = strlen(*list);
>
> while (i < n) {
> if (!DOT_OR_DOTDOT(namelist[i]->d_name) && !HIDDEN(namelist[i]->d_name)) {
> *list = xrealloc(*list, l + MAX_CHILD_SIZE);
> strcpy(*list + l, (i == (n - 1)) ? LAST_CHILD : CHILD);
> printf("%s%s", *list, namelist[i]->d_name);
> fullpath = concat_path_file(path, namelist[i]->d_name);
> if((linkname = xmalloc_readlink(fullpath)) != NULL) {
> printf(" -> %s", linkname);
> }
> bb_putchar('\n');
> if (is_directory(fullpath, /*followLinks*/ 1)) {
> (*dcount)++;
> strcpy(*list + l, (i == (n - 1)) ? LAST_GRAND_CHILD : GRAND_CHILD);
> if (linkname == NULL) {
> tree(fullpath, dcount, fcount, list);
> }
> } else {
> (*fcount)++;
> }
> free(linkname);
> free(fullpath);
> }
> free(namelist[i]);
> i++;
> }
> strcpy(*list + l, "");
> free(namelist);
> }
>
> int tree_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
> int tree_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
> {
> int dircount = 0;
> int filecount = 0;
> char *list = xzalloc(1);
>
> if (argc == 1) {
> *argv = (char *) ".";
> } else {
> argv++;
> }
>
> do {
> tree(*argv, &dircount, &filecount, &list);
> } while (*++argv);
> printf("\n%d directories, %d files\n", dircount, filecount);
> if (ENABLE_FEATURE_CLEAN_UP) {
> free(list);
> }
> return EXIT_SUCCESS;
> }
>
> Hints on how to shrink it even more, improvements and critics are welcome! Enjoy.
>
> Ciao,
> Tito
>
More information about the busybox
mailing list