Move SearchDirectory into a common file

Change-Id: I34fe0f2b89852eaec404adca39e396a317dfeb37
diff --git a/aos/events/logging/log_cat.cc b/aos/events/logging/log_cat.cc
index 7dabc18..5d205a8 100644
--- a/aos/events/logging/log_cat.cc
+++ b/aos/events/logging/log_cat.cc
@@ -5,7 +5,6 @@
 #include <string>
 #include <string_view>
 #include <vector>
-#include "dirent.h"
 
 #include "aos/configuration.h"
 #include "aos/events/logging/logger.h"
@@ -33,11 +32,6 @@
 DEFINE_bool(pretty, false,
             "If true, pretty print the messages on multiple lines");
 
-bool EndsWith(std::string_view str, std::string_view ending) {
-  return str.size() >= ending.size() &&
-         str.substr(str.size() - ending.size()) == ending;
-}
-
 // Print the flatbuffer out to stdout, both to remove the unnecessary cruft from
 // glog and to allow the user to readily redirect just the logged output
 // independent of any debugging information on stderr.
@@ -64,33 +58,6 @@
   }
 }
 
-void SearchDirectory(std::vector<std::string> *files, std::string filename) {
-  DIR *directory = opendir(filename.c_str());
-
-  if (directory == nullptr) {
-    // its not a directory
-    // it could be a file
-    // or it could not exist
-    if (EndsWith(filename, ".bfbs") || EndsWith(filename, ".bfbs.xz")) {
-      files->emplace_back(filename);
-    }
-    return;
-  }
-
-  struct dirent *directory_entry;
-  while ((directory_entry = readdir(directory)) != nullptr) {
-    std::string next_filename = directory_entry->d_name;
-    if (next_filename == "." || next_filename == "..") {
-      continue;
-    }
-
-    std::string path = filename + "/" + next_filename;
-    SearchDirectory(files, path);
-  }
-
-  closedir(directory);
-}
-
 int main(int argc, char **argv) {
   gflags::SetUsageMessage(
       "Usage:\n"
@@ -156,10 +123,8 @@
     LOG(FATAL) << "Expected at least 1 logfile as an argument.";
   }
 
-  std::vector<std::string> unsorted_logfiles;
-  for (int i = 1; i < argc; ++i) {
-    SearchDirectory(&unsorted_logfiles, argv[i]);
-  }
+  const std::vector<std::string> unsorted_logfiles =
+      aos::logger::FindLogs(argc, argv);
 
   const std::vector<aos::logger::LogFile> logfiles =
       aos::logger::SortParts(unsorted_logfiles);
diff --git a/aos/events/logging/logfile_sorting.cc b/aos/events/logging/logfile_sorting.cc
index 168230e..1998119 100644
--- a/aos/events/logging/logfile_sorting.cc
+++ b/aos/events/logging/logfile_sorting.cc
@@ -5,6 +5,8 @@
 #include <string>
 #include <utility>
 #include <vector>
+#include "dirent.h"
+#include "sys/stat.h"
 
 #include "aos/events/logging/logfile_utils.h"
 #include "aos/flatbuffers.h"
@@ -14,6 +16,60 @@
 namespace logger {
 namespace chrono = std::chrono;
 
+namespace {
+
+// Check if string ends with ending
+bool EndsWith(std::string_view str, std::string_view ending) {
+  return str.size() >= ending.size() &&
+         str.substr(str.size() - ending.size()) == ending;
+}
+
+bool FileExists(std::string filename) {
+  struct stat stat_results;
+  int error = stat(filename.c_str(), &stat_results);
+  return error == 0;
+}
+
+}  // namespace
+
+void FindLogs(std::vector<std::string> *files, std::string filename) {
+  DIR *directory = opendir(filename.c_str());
+
+  if (directory == nullptr) {
+    if (EndsWith(filename, ".bfbs") || EndsWith(filename, ".bfbs.xz")) {
+      files->emplace_back(filename);
+    }
+    return;
+  }
+
+  struct dirent *directory_entry;
+  while ((directory_entry = readdir(directory)) != nullptr) {
+    std::string next_filename = directory_entry->d_name;
+    if (next_filename == "." || next_filename == "..") {
+      continue;
+    }
+
+    std::string path = filename + "/" + next_filename;
+    FindLogs(files, path);
+  }
+
+  closedir(directory);
+}
+
+std::vector<std::string> FindLogs(int argc, char **argv) {
+  std::vector<std::string> found_logfiles;
+
+  for (int i = 1; i < argc; i++) {
+    std::string filename = argv[i];
+    if (FileExists(filename)) {
+      aos::logger::FindLogs(&found_logfiles, filename);
+    } else {
+      LOG(FATAL) << "File " << filename << " does not exist";
+    }
+  }
+  return found_logfiles;
+}
+
 std::vector<LogFile> SortParts(const std::vector<std::string> &parts) {
   std::vector<std::string> corrupted;
 
@@ -260,7 +316,7 @@
 std::vector<std::string> FindNodes(const std::vector<LogFile> &parts) {
   std::set<std::string> nodes;
   for (const LogFile &log_file : parts) {
-    for (const LogParts& part : log_file.parts) {
+    for (const LogParts &part : log_file.parts) {
       nodes.insert(part.node);
     }
   }
@@ -275,7 +331,7 @@
                                          std::string_view node) {
   std::vector<LogParts> result;
   for (const LogFile &log_file : parts) {
-    for (const LogParts& part : log_file.parts) {
+    for (const LogParts &part : log_file.parts) {
       if (part.node == node) {
         result.emplace_back(part);
       }
diff --git a/aos/events/logging/logfile_sorting.h b/aos/events/logging/logfile_sorting.h
index 94cb771..b955a09 100644
--- a/aos/events/logging/logfile_sorting.h
+++ b/aos/events/logging/logfile_sorting.h
@@ -2,8 +2,8 @@
 #define AOS_EVENTS_LOGGING_LOGFILE_SORTING_H_
 
 #include <iostream>
-#include <vector>
 #include <string>
+#include <vector>
 
 #include "aos/events/logging/uuid.h"
 #include "aos/time/time.h"
@@ -62,6 +62,13 @@
 std::vector<LogParts> FilterPartsForNode(const std::vector<LogFile> &parts,
                                          std::string_view node);
 
+// Recursively searches the file/folder for .bfbs and .bfbs.xz files and adds
+// them to the vector.
+void FindLogs(std::vector<std::string> *files, std::string filename);
+
+// Recursively searches for logfiles in argv[1] and onward.
+std::vector<std::string> FindLogs(int argc, char **argv);
+
 }  // namespace logger
 }  // namespace aos