Commit c3fe2090 authored by Juergen Hannappel's avatar Juergen Hannappel
Browse files

new tool to check for strange ACLs

parent 436f8910
......@@ -57,4 +57,4 @@ Also some of the test scripts in the tests directory include site specific confi
directory, if present.
The most comprehensive documentation can be found on http://www.desy.de/~hannappj/ewmscp/index.html
\ No newline at end of file
The most comprehensive documentation can be found on https://ewmscp.pages.desy.de/ewmscp/
......@@ -160,6 +160,10 @@ if (GPFS_FOUND)
target_link_libraries(fixGpfsAcls ${GPFS_LIBRARIES})
install(TARGETS fixGpfsAcls DESTINATION bin)
add_executable(checkGpfsAcls checkGpfsAcls.cpp gpfsFcntlHandler.cpp timer.cpp ${OPTION_SRCS})
target_link_libraries(checkGpfsAcls ${GPFS_LIBRARIES})
install(TARGETS checkGpfsAcls DESTINATION bin)
endif()
configure_file(ewmsls.in ewmsls)
......
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <gpfs.h>
#include <string>
#include <forward_list>
#include <Options.h>
#include <throwcall.h>
#include <scoped.h>
#include "gpfsFcntlHandler.h"
/** \defgroup checkGpfsAcls The checkGpfsAcls command
\{
This tool sets the ACLs of the files given on the command line
to those they would inherit from theirparent directories.
Directories given on the command line are left unchanged,
but all their content is recursively scanned and the ACLs
of all their sub-directories and files are set
as if freshly inherited.
*/
static unsigned long nDirs = 0;
static unsigned long nFiles = 0;
static options::single<size_t> maxGoodEntries('n',"maxGoodEntries",
"maximum number of aces in an acl considered good",14);
static options::single<size_t> minGoodEntries('m',"minGoodEntries",
"minimum number of aces in an acl considered good",0);
static std::map<size_t,unsigned long> aclLength;
static std::map<size_t,unsigned long> multiples;
void checkAcl(const std::string& path) {
gpfs_acl_handler acl;
acl.get(-1, path);
unsigned duplicates(0);
aclLength[acl.size()]++;
for (auto ace1 = acl.begin(); ace1 != acl.end(); ++ace1) {
for (auto ace2 = ace1 + 1; ace2 != acl.end(); ++ace2) {
if (*ace1 == *ace2) {
duplicates++;
}
}
}
multiples[duplicates]++;
if (acl.size() > maxGoodEntries || acl.size() < minGoodEntries || duplicates > 0) {
std::cout << path << " " << acl.size() << " " << duplicates << "\n";
}
}
void handleDir(const std::string& path) {
std::forward_list<std::string> subdirs;
{
scoped::Dir dir(path);
while (auto entry = readdir(dir)) {
if (entry->d_name[entry->d_name[0] != '.' ? 0 : entry->d_name[1] != '.' ? 1 : 2] == '\0') {
continue; // skip . .. and empty strings
}
if (entry->d_type == DT_DIR) {
subdirs.emplace_front(path + "/" + entry->d_name);
nDirs++;
} else if (entry->d_type == DT_REG) {
std::string filePath(path);
filePath += "/";
filePath += entry->d_name;
nFiles++;
checkAcl(filePath);
} else {
std::cerr << "ignoring '" << entry->d_name << "' in '" << path << "', it's neither dir nor file\n";
}
}
}
for (const auto& subdir : subdirs) {
checkAcl(subdir);
handleDir(subdir);
}
}
int main(int argc, const char *argv[]) {
options::parser parser(
"set the ACLs of the files given on the command line\n"
"\t to those they would inherit from theirparent directories.\n"
"\tDirectories given on the command line are left unchanged,\n"
"\t but all their content is recursively scanned and the ACLs\n"
"\t of all their sub-directories and files are set\n"
"\t as if freshly inherited.\n"
, "", {});
options::positional<options::container<std::string>>files(10, "files",
"files to be checked");
parser.fParse(argc, argv);
for (const auto& file : files) {
struct stat statbuf;
throwcall::good0(lstat(file.c_str(), &statbuf), "can't stat ", file);
if (S_ISDIR(statbuf.st_mode)) {
nDirs++;
checkAcl(file);
handleDir(file);
} else if (S_ISREG(statbuf.st_mode)) {
nFiles++;
checkAcl(file);
} else {
std::cerr << "ignoring '" << file << "', it's neither dir nor file\n";
}
}
std::cout << "processed " << nFiles << " files in " << nDirs << " directories\n";
for (const auto& item: aclLength) {
std::cout << "files with " << item.first << " aces in the acl: " << item.second << "\n";
}
for (const auto& item: multiples) {
std::cout << "files with " << item.first << " duplicates in the acl: " << item.second << "\n";
}
return 0;
}
/// \}
......@@ -44,6 +44,7 @@ class gpfs_acl_handler {
size_t size() const {
return buffer.acl.acl_nace;
};
const gpfs_ace_v4_t* begin() const;
const gpfs_ace_v4_t* end() const;
gpfs_ace_v4_t* begin();
......@@ -51,6 +52,14 @@ class gpfs_acl_handler {
void get(int fd, const std::string& path);
void set(int fd, const std::string& path);
};
inline bool operator==(const gpfs_ace_v4_t& lhs,
const gpfs_ace_v4_t& rhs) {
return lhs.aceType == rhs.aceType &&
lhs.aceFlags == rhs.aceFlags &&
lhs.aceIFlags == rhs.aceIFlags &&
lhs.aceMask == rhs.aceMask &&
lhs.aceWho == rhs.aceWho;
}
#endif
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment