diff --git a/apps/ls.cpp b/apps/ls.cpp index 3ea716d9..65d6b0e3 100644 --- a/apps/ls.cpp +++ b/apps/ls.cpp @@ -1,12 +1,18 @@ #include #include #include +#include + +#include +#include +#include Result luna_main(int argc, char** argv) { StringView pathname; bool show_all { false }; bool show_almost_all { false }; + bool long_list { false }; os::ArgumentParser parser; parser.add_description("List files contained in a directory (defaults to '.', the current directory)"_sv); @@ -14,19 +20,51 @@ Result luna_main(int argc, char** argv) parser.add_positional_argument(pathname, "directory"_sv, "."_sv); parser.add_switch_argument(show_all, 'a', "all"_sv, "also list hidden files (whose filename begins with a dot)"_sv); parser.add_switch_argument(show_almost_all, 'A', "almost-all"_sv, "list all files except '.' and '..'"_sv); + parser.add_switch_argument(long_list, 'l', ""_sv, "use a long listing format"_sv); parser.parse(argc, argv); - auto dir = TRY(os::Directory::open(pathname)); + Vector files; + int dirfd = AT_FDCWD; + SharedPtr dir; - auto filter = os::Directory::Filter::Hidden; - if (show_almost_all) filter = os::Directory::Filter::ParentAndBase; - else if (show_all) - filter = os::Directory::Filter::None; + if (os::FileSystem::is_directory(pathname)) + { + dir = TRY(os::Directory::open(pathname)); + dirfd = dir->fd(); - auto files = TRY(dir->list(filter)); + auto filter = os::Directory::Filter::Hidden; + if (show_almost_all) filter = os::Directory::Filter::ParentAndBase; + else if (show_all) + filter = os::Directory::Filter::None; - auto list = TRY(String::join(files, " "_sv)); - os::println("%s", list.chars()); + files = TRY(dir->list(filter)); + } + else + { + auto str = TRY(String::from_cstring(pathname.chars())); + TRY(files.try_append(move(str))); + } + + if (!long_list) + { + auto list = TRY(String::join(files, " "_sv)); + os::println("%s", list.chars()); + } + else + { + for (const auto& file : files) + { + struct stat st; + if (fstatat(dirfd, file.chars(), &st, 0) < 0) + { + perror(file.chars()); + return 1; + } + + os::println("%6o %u %4u %4u %10lu %s", st.st_mode, st.st_nlink, st.st_uid, st.st_gid, st.st_size, + file.chars()); + } + } return 0; }