Serenity Operating System
at master 111 lines 3.2 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2020, Shannon Booth <shannon.ml.booth@gmail.com> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#include <AK/DeprecatedString.h> 9#include <LibCore/ArgsParser.h> 10#include <LibCore/DateTime.h> 11#include <LibCore/System.h> 12#include <LibMain/Main.h> 13#include <grp.h> 14#include <pwd.h> 15#include <sys/sysmacros.h> 16#include <time.h> 17 18static ErrorOr<int> stat(StringView file, bool should_follow_links) 19{ 20 auto st = TRY(should_follow_links ? Core::System::stat(file) : Core::System::lstat(file)); 21 outln(" File: {}", file); 22 outln(" Inode: {}", st.st_ino); 23 if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) 24 outln(" Device: {},{}", major(st.st_rdev), minor(st.st_rdev)); 25 else 26 outln(" Size: {}", st.st_size); 27 outln(" Links: {}", st.st_nlink); 28 outln(" Blocks: {}", st.st_blocks); 29 out(" UID: {}", st.st_uid); 30 if (auto* pwd = getpwuid(st.st_uid)) { 31 out(" ({})", pwd->pw_name); 32 } 33 outln(""); 34 out(" GID: {}", st.st_gid); 35 if (auto* grp = getgrgid(st.st_gid)) { 36 out(" ({})", grp->gr_name); 37 } 38 outln(""); 39 out(" Mode: ({:o}/", st.st_mode); 40 41 if (S_ISDIR(st.st_mode)) 42 out("d"); 43 else if (S_ISLNK(st.st_mode)) 44 out("l"); 45 else if (S_ISBLK(st.st_mode)) 46 out("b"); 47 else if (S_ISCHR(st.st_mode)) 48 out("c"); 49 else if (S_ISFIFO(st.st_mode)) 50 out("f"); 51 else if (S_ISSOCK(st.st_mode)) 52 out("s"); 53 else if (S_ISREG(st.st_mode)) 54 out("-"); 55 else 56 out("?"); 57 58 out("{:c}{:c}{:c}{:c}{:c}{:c}{:c}{:c}", 59 st.st_mode & S_IRUSR ? 'r' : '-', 60 st.st_mode & S_IWUSR ? 'w' : '-', 61 st.st_mode & S_ISUID ? 's' : (st.st_mode & S_IXUSR ? 'x' : '-'), 62 st.st_mode & S_IRGRP ? 'r' : '-', 63 st.st_mode & S_IWGRP ? 'w' : '-', 64 st.st_mode & S_ISGID ? 's' : (st.st_mode & S_IXGRP ? 'x' : '-'), 65 st.st_mode & S_IROTH ? 'r' : '-', 66 st.st_mode & S_IWOTH ? 'w' : '-'); 67 68 if (st.st_mode & S_ISVTX) 69 out("t"); 70 else 71 out("{:c}", st.st_mode & S_IXOTH ? 'x' : '-'); 72 73 outln(")"); 74 75 auto print_time = [](timespec t) { 76 outln("{}.{:09}", Core::DateTime::from_timestamp(t.tv_sec).to_deprecated_string(), t.tv_nsec); 77 }; 78 79 out("Accessed: "); 80 print_time(st.st_atim); 81 out("Modified: "); 82 print_time(st.st_mtim); 83 out(" Changed: "); 84 print_time(st.st_ctim); 85 86 return 0; 87} 88 89ErrorOr<int> serenity_main(Main::Arguments arguments) 90{ 91 TRY(Core::System::pledge("stdio rpath")); 92 93 bool should_follow_links = false; 94 Vector<StringView> files; 95 96 auto args_parser = Core::ArgsParser(); 97 args_parser.add_option(should_follow_links, "Follow links to files", nullptr, 'L'); 98 args_parser.add_positional_argument(files, "File(s) to stat", "file", Core::ArgsParser::Required::Yes); 99 args_parser.parse(arguments); 100 101 bool had_error = false; 102 for (auto& file : files) { 103 auto r = stat(file, should_follow_links); 104 if (r.is_error()) { 105 had_error = true; 106 warnln("stat: cannot stat '{}': {}", file, strerror(r.error().code())); 107 } 108 } 109 110 return had_error; 111}