On Sat, 16 Apr 2022 21:13:02 +0200
tito <farmat...@tiscali.it> wrote:

> On Sat, 16 Apr 2022 16:54:19 +0000
> Roger Knecht <rkne...@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
>      

_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to