1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "libbb.h"
21#include "common_bufsiz.h"
22#include "unicode.h"
23
24#define prefix_buf bb_common_bufsiz1
25
26static void tree_print(unsigned count[2], const char* directory_name, char* prefix_pos)
27{
28 struct dirent **entries;
29 int index, size;
30 const char *bar = "| ";
31 const char *mid = "|-- ";
32 const char *end = "`-- ";
33
34#if ENABLE_UNICODE_SUPPORT
35 if (unicode_status == UNICODE_ON) {
36 bar = "│ ";
37 mid = "├── ";
38 end = "└── ";
39 }
40#endif
41
42
43 size = scandir(directory_name, &entries, NULL, alphasort);
44
45 if (size < 0) {
46 fputs_stdout(directory_name);
47 puts(" [error opening dir]");
48 return;
49 }
50
51
52 puts(directory_name);
53
54
55 xchdir(directory_name);
56
57
58 for (index = 0; index < size;) {
59 struct dirent *dirent = entries[index++];
60
61
62 if (dirent->d_name[0] != '.') {
63 int status;
64 struct stat statBuf;
65
66
67 status = lstat(dirent->d_name, &statBuf);
68
69 if (index == size) {
70 strcpy(prefix_pos, end);
71 } else {
72 strcpy(prefix_pos, mid);
73 }
74 fputs_stdout(prefix_buf);
75
76 if (status == 0 && S_ISLNK(statBuf.st_mode)) {
77
78 char* symlink_path = xmalloc_readlink(dirent->d_name);
79 printf("%s -> %s\n", dirent->d_name, symlink_path);
80 free(symlink_path);
81 count[1]++;
82 } else if (status == 0 && S_ISDIR(statBuf.st_mode)
83 && (prefix_pos - prefix_buf) < (COMMON_BUFSIZE - 16)
84 ) {
85
86 char* pos;
87 if (index == size) {
88 pos = stpcpy(prefix_pos, " ");
89 } else {
90 pos = stpcpy(prefix_pos, bar);
91 }
92 tree_print(count, dirent->d_name, pos);
93 count[0]++;
94 } else {
95
96 puts(dirent->d_name);
97 count[1]++;
98 }
99 }
100
101
102 free(dirent);
103 }
104
105
106 free(entries);
107
108
109 xchdir("..");
110}
111
112int tree_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
113int tree_main(int argc UNUSED_PARAM, char **argv)
114{
115 unsigned count[2] = { 0, 0 };
116
117 setup_common_bufsiz();
118 init_unicode();
119
120 if (!argv[1])
121 *argv-- = (char*)".";
122
123
124 while (*(++argv))
125 tree_print(count, *argv, prefix_buf);
126
127
128 printf("\n%u directories, %u files\n", count[0], count[1]);
129
130 return EXIT_SUCCESS;
131}
132