tools/stat: add trivial file meta data listing tool
This commit is contained in:
parent
6dd378d198
commit
2d7eb25167
@ -23,7 +23,7 @@ add_subdirectory(cruft/crypto)
|
|||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
foreach (t analyse compare)
|
foreach (t analyse compare stat)
|
||||||
add_executable ("${t}" "tools/${t}.cpp")
|
add_executable ("${t}" "tools/${t}.cpp")
|
||||||
target_link_libraries("${t}" cruft-crypto cruft-util)
|
target_link_libraries("${t}" cruft-crypto cruft-util)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit cc9b9b19c1a9a7002248d7f62053d49002a8b297
|
Subproject commit 174bd62a293d3e15dc4fdc3112dea21443fc1d90
|
149
tools/stat.cpp
Normal file
149
tools/stat.cpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#include <cruft/util/bitwise.hpp>
|
||||||
|
#include <cruft/util/posix/except.hpp>
|
||||||
|
#include <cruft/util/string.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/xattr.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
|
constexpr unsigned type_index (mode_t val)
|
||||||
|
{
|
||||||
|
return (val & S_IFMT) >> cruft::ctz (unsigned {S_IFMT});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
<< " }";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc < 2) {
|
||||||
|
std::cerr << argv[0] << " <target> ...\n";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; ++i) {
|
||||||
|
std::cout << "{ stat: ";
|
||||||
|
|
||||||
|
char const *path = argv[i];
|
||||||
|
|
||||||
|
{
|
||||||
|
struct stat buffer;
|
||||||
|
cruft::posix::error::try_call (stat, path, &buffer);
|
||||||
|
std::cout << buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<char const*> 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 == E2BIG) {
|
||||||
|
val.resize (val.size () * 2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res < 0)
|
||||||
|
cruft::posix::error::throw_code ();
|
||||||
|
|
||||||
|
val.resize (res);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << keybuffer << ": " << val << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << '\n';
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user