5 #include <forward_list>
21 #include <condition_variable>
30 std::deque<std::unique_ptr<T>>
queue;
35 queue.emplace_back(std::move(item));
37 template <
class ... Types>
void emplace(Types ... args) {
38 std::unique_ptr<T> item(
new T(args...));
41 template <
class ... Types> std::unique_ptr<T>
dequeue() {
46 auto item = std::move(
queue.front());
64 "ignore subdirs we may not access");
66 "be quiet, no prefix to output lines");
68 "print a list of items with type DT_UNKNOWN");
84 const std::string& aName,
85 unsigned char aOptionChar):
90 "print count of " + aName +
" items");
95 static const std::vector<itemDescriptor>&
keyToName() {
96 const static std::vector<itemDescriptor> kTN{
97 {DT_BLK,
"blockDevice",
'b'},
98 {DT_CHR,
"characterDevice",
'c'},
99 {DT_DIR,
"directory",
'd'},
100 {DT_FIFO,
"fifo",
'p'},
101 {DT_LNK,
"symlink",
'l'},
102 {DT_REG,
"file",
'f'},
103 {DT_SOCK,
"socket",
's'},
104 {DT_UNKNOWN,
"unknown",
'u'},
105 {specials::denied,
"accesDenied",
'D'},
106 {specials::noent,
"noSuchFile",
'M'},
107 {specials::notdir,
"notADirectory",
'N'}
132 if (printAll || *item.option) {
134 std::cout << item.name <<
" ";
136 std::cout <<
counters[item.index] <<
"\n";
152 static std::condition_variable
cv;
155 static std::forward_list<runnerType>&
runners() {
156 static std::forward_list<runnerType> list;
170 runners().emplace_front(dirQueue);
176 for (
auto& runner :
runners()) {
177 runner.worker.join();
178 runner.sum(sumCounter);
181 unsigned int realizedThreads(0);
182 unsigned int unusedThreads(0);
183 for (
auto& runner :
runners()) {
185 if (runner.getDirsDone() == 0) {
189 std::cerr <<
"of " << realizedThreads <<
" threads " << unusedThreads <<
" were not used\n";
202 while (
auto path = dirQueue.
dequeue()) {
206 auto result = opendir(path->c_str());
208 if (result ==
nullptr) {
212 }
else if (errno == ENOENT) {
215 }
else if (errno == ENOTDIR) {
224 while (
auto entry = readdir(dir)) {
226 if (entry->d_name[entry->d_name[0] !=
'.' ? 0 : entry->d_name[1] !=
'.' ? 1 : 2] ==
'\0') {
231 if (entry->d_type == DT_DIR) {
232 std::string subdir(*path);
234 subdir += entry->d_name;
238 std::string item(*path);
240 item += entry->d_name;
247 std::unique_lock<decltype(
listMutex)> lock;
262 auto result = opendir(path.c_str());
264 if (result ==
nullptr) {
266 counter.
count(counterType::specials::denied);
268 }
else if (errno == ENOENT) {
269 counter.
count(counterType::specials::noent);
271 }
else if (errno == ENOTDIR) {
272 counter.
count(counterType::specials::notdir);
278 std::forward_list<std::string> subdirs;
281 while (
auto entry = readdir(dir)) {
283 if (entry->d_name[entry->d_name[0] !=
'.' ? 0 : entry->d_name[1] !=
'.' ? 1 : 2] ==
'\0') {
287 counter.
count(entry->d_type);
288 if (entry->d_type == DT_DIR) {
289 subdirs.emplace_front(entry->d_name);
291 std::string item(path);
293 item += entry->d_name;
298 for (
const auto& subdir : subdirs) {
304 int main(
int argc,
const char *argv[]) {
307 "paths to consider");
310 parser.fParse(argc, argv);
314 for (
auto path : paths) {
319 nThreads = sysconf(_SC_NPROCESSORS_ONLN);
322 for (
const auto& path : paths) {
325 for (
unsigned int i = 0; i < paths.size(); i++) {
335 std::cout <<
"List of items of type DT_UNKNOWN:\n";
337 std::cout << item <<
"\n";