1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "mosapi.h"
4
5#define dirent_next(d) ((struct dirent *) ((char *) d + d->d_reclen))
6static size_t depth = 1;
7
8static void print_entry(const struct dirent *dirent)
9{
10 for (size_t i = 0; i < depth; i++)
11 printf(format: " ");
12 printf(format: "%s\n", dirent->d_name);
13}
14
15static void do_tree(void)
16{
17 const fd_t dirfd = open(path: ".", flags: OPEN_READ | OPEN_DIR);
18 if (dirfd < 0)
19 {
20 fprintf(stderr, format: "failed to open directory\n");
21 return;
22 }
23
24 char buffer[1024];
25 do
26 {
27 size_t sz = syscall_vfs_list_dir(fd: dirfd, buffer, buffer_size: sizeof(buffer));
28 if (sz == 0)
29 break;
30
31 for (const struct dirent *dirent = (struct dirent *) buffer; (char *) dirent < buffer + sz; dirent = dirent_next(dirent))
32 {
33 if (dirent->d_type == FILE_TYPE_DIRECTORY)
34 {
35 if (strcmp(str1: dirent->d_name, str2: ".") == 0 || strcmp(str1: dirent->d_name, str2: "..") == 0)
36 continue;
37
38 print_entry(dirent);
39 depth++;
40 chdir(path: dirent->d_name);
41 do_tree();
42 chdir(path: "..");
43 depth--;
44 }
45 else
46 {
47 print_entry(dirent);
48 }
49 }
50
51 } while (true);
52
53 syscall_io_close(fd: dirfd);
54}
55
56int main(int argc, char **argv)
57{
58 if (argc > 2)
59 {
60 fprintf(stderr, format: "too many arguments\n");
61 fprintf(stderr, format: "usage: %s [path]\n", argv[0]);
62 return 1;
63 }
64
65 // argv[1] may contain the path to list
66 const char *path = argc > 1 ? argv[1] : ".";
67
68 if (!chdir(path))
69 {
70 fprintf(stderr, format: "failed to chdir to '%s'\n", path);
71 return 1;
72 }
73
74 printf(format: "%s\n", path);
75 do_tree();
76 return 0;
77}
78