#include #include #include "../acl.hpp" #include #include #include #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// struct type_printer { type_printer (struct stat const &_data) : data (_data) { ; } struct stat const &data; }; //----------------------------------------------------------------------------- std::ostream& operator<< (std::ostream &os, type_printer const &val) { os << "[ "; if (val.data.st_mode & S_ISUID) os << "SUID, "; if (val.data.st_mode & S_ISGID) os << "SGID, "; if (val.data.st_mode & S_ISVTX) os << "STICKY, "; os << "{ user: " << (val.data.st_mode & S_IRUSR ? 'r' : '_') << (val.data.st_mode & S_IWUSR ? 'w' : '_') << (val.data.st_mode & S_IXUSR ? 'x' : '_') << " }, " << "{ group: " << (val.data.st_mode & S_IRGRP ? 'r' : '_') << (val.data.st_mode & S_IWGRP ? 'w' : '_') << (val.data.st_mode & S_IXGRP ? 'x' : '_') << " }, " << "{ group: " << (val.data.st_mode & S_IROTH ? 'r' : '_') << (val.data.st_mode & S_IWOTH ? 'w' : '_') << (val.data.st_mode & S_IXOTH ? 'x' : '_') << " }"; return os; } /////////////////////////////////////////////////////////////////////////////// struct mode_printer { mode_printer (struct stat const &_data) : data (_data) { ; } struct stat const &data; }; //----------------------------------------------------------------------------- std::ostream& operator<< (std::ostream &os, mode_printer const &val) { return S_ISREG (val.data.st_mode) ? os << "REGULAR" : S_ISDIR (val.data.st_mode) ? os << "DIRECTORY" : S_ISCHR (val.data.st_mode) ? os << "CHARACTER" : S_ISBLK (val.data.st_mode) ? os << "BLOCK" : S_ISFIFO (val.data.st_mode) ? os << "FIFO" : S_ISLNK (val.data.st_mode) ? os << "SYMLINK" : S_ISSOCK (val.data.st_mode) ? os << "SOCKET" : (throw std::invalid_argument ("Unhandled mode_t"), os << "_error"); } //----------------------------------------------------------------------------- std::ostream& operator<< (std::ostream &os, struct stat const &val) { return os << "{ dev: " << val.st_dev << ", ino: " << val.st_ino << ", type: " << type_printer (val) << ", mode: " << mode_printer (val) << ", uid: " << val.st_uid << ", gid: " << val.st_gid << ", size: " << val.st_size << ", blocksize: " << val.st_blksize << " }"; } /////////////////////////////////////////////////////////////////////////////// static void do_stat (char const *path) { struct stat buffer; cruft::posix::error::try_call (stat, path, &buffer); std::cout << buffer; } //----------------------------------------------------------------------------- void do_xattr (char const *path) { std::cout << ", xattr: "; { std::cout << "{ "; std::string attr_list (1024, '\0'); { auto res = listxattr (path, attr_list.data (), attr_list.size ()); if (res < 0) cruft::posix::error::throw_code (); attr_list.resize (res); } std::string keybuffer (64, '\0'); std::string val (128, '\0'); cruft::view attr_view { attr_list.data (), attr_list.size () }; for (auto const &key: cruft::tokeniser (attr_view, '\0')) { keybuffer.resize (0); std::copy (std::begin (key), std::end (key), std::back_inserter (keybuffer)); while (true) { auto const res = getxattr (path, keybuffer.c_str (), val.data (), val.size ()); if (res < 0 && errno == E2BIG) { val = "___E2BIG"; break; } if (res < 0 && errno == ERANGE) { val.resize (val.size () * 2); continue; } if (res < 0) cruft::posix::error::throw_code (); val.resize (res); break; } std::cout << keybuffer << ": " << val << ", "; } std::cout << "}"; } } //----------------------------------------------------------------------------- void do_acl (char const *path) { std::cout << cruft::acl (path, ACL_TYPE_ACCESS) << '\n'; } /////////////////////////////////////////////////////////////////////////////// int main (int argc, char **argv) { if (argc < 2) { std::cerr << argv[0] << " ...\n"; return EXIT_FAILURE; } for (int i = 1; i < argc; ++i) { std::cout << "{ stat: "; char const *path = argv[i]; do_stat (path); do_xattr (path); do_acl (path); std::cout << '\n'; } }