Apply formatting to osquery 79/234379/3
authorSangwan Kwon <sangwan.kwon@samsung.com>
Wed, 27 May 2020 06:05:47 +0000 (15:05 +0900)
committerSangwan Kwon <sangwan.kwon@samsung.com>
Wed, 27 May 2020 06:06:10 +0000 (15:06 +0900)
Change-Id: I5ccc0302d11102c1f03c4e78ffe1af9051232e15
Signed-off-by: Sangwan Kwon <sangwan.kwon@samsung.com>
66 files changed:
src/osquery/core/plugins/plugin.cpp
src/osquery/core/plugins/plugin.h
src/osquery/core/plugins/sql.h
src/osquery/core/query.cpp
src/osquery/core/sql/column.cpp
src/osquery/core/sql/column.h
src/osquery/core/sql/diff_results.cpp
src/osquery/core/sql/diff_results.h
src/osquery/core/sql/scheduled_query.h
src/osquery/core/sql/table_row.h
src/osquery/core/tables.cpp
src/osquery/core/tests/query_tests.cpp
src/osquery/core/tests/tables_tests.cpp
src/osquery/include/osquery/plugins/logger.h [deleted symlink]
src/osquery/include/osquery/query.h
src/osquery/include/osquery/registry_factory.h
src/osquery/include/osquery/registry_interface.h
src/osquery/include/osquery/sql.h
src/osquery/include/osquery/tables.h
src/osquery/registry/registry_factory.cpp
src/osquery/registry/registry_interface.cpp
src/osquery/registry/tests/registry.cpp
src/osquery/sql/dynamic_table_row.cpp
src/osquery/sql/dynamic_table_row.h
src/osquery/sql/sql.cpp
src/osquery/sql/sqlite_util.cpp
src/osquery/sql/sqlite_util.h
src/osquery/sql/tests/sql.cpp
src/osquery/sql/tests/sql_test_utils.cpp
src/osquery/sql/tests/sqlite_util_tests.cpp
src/osquery/sql/tests/virtual_table.cpp
src/osquery/sql/virtual_sqlite_table.cpp
src/osquery/sql/virtual_table.cpp
src/osquery/sql/virtual_table.h
src/osquery/utils/base64.cpp
src/osquery/utils/chars.cpp
src/osquery/utils/chars.h
src/osquery/utils/conversions/castvariant.h
src/osquery/utils/conversions/join.h
src/osquery/utils/conversions/split.cpp
src/osquery/utils/conversions/split.h
src/osquery/utils/conversions/tests/join.cpp
src/osquery/utils/conversions/tests/split.cpp
src/osquery/utils/conversions/tests/to.cpp
src/osquery/utils/conversions/tests/tryto.cpp
src/osquery/utils/conversions/to.h
src/osquery/utils/conversions/tryto.cpp
src/osquery/utils/conversions/tryto.h
src/osquery/utils/debug/debug_only.h
src/osquery/utils/debug/tests/debug_only.cpp
src/osquery/utils/error/error.h
src/osquery/utils/error/tests/error.cpp
src/osquery/utils/expected/expected.h
src/osquery/utils/expected/tests/expected.cpp
src/osquery/utils/only_movable.h
src/osquery/utils/status/status.cpp
src/osquery/utils/status/status.h
src/osquery/utils/status/tests/status.cpp
src/osquery/utils/system/posix/env.cpp
src/osquery/utils/system/posix/errno.cpp
src/osquery/utils/system/posix/errno.h
src/osquery/utils/system/posix/filepath.cpp
src/osquery/utils/system/posix/tests/errno.cpp
src/osquery/utils/system/posix/time.cpp
src/osquery/utils/system/tests/time.cpp
src/osquery/utils/system/time.cpp

index a214b3d5ad2a5385a654b0c94700e66694541da3..afcc47ec90695666190c83187dc9603ca957b272 100644 (file)
 
 namespace osquery {
 
-void Plugin::setName(const std::string& name) {
-  if (!name_.empty() && name != name_) {
-    std::string error = "Cannot rename plugin " + name_ + " to " + name;
-    throw std::runtime_error(error);
-  }
+void Plugin::setName(const std::string& name)
+{
+       if (!name_.empty() && name != name_) {
+               std::string error = "Cannot rename plugin " + name_ + " to " + name;
+               throw std::runtime_error(error);
+       }
 
-  name_ = name;
+       name_ = name;
 }
 
-PluginResponse tableRowsToPluginResponse(const TableRows& rows) {
-  PluginResponse result;
-  for (const auto& row : rows) {
-    result.push_back(static_cast<Row>(*row));
-  }
-  return result;
+PluginResponse tableRowsToPluginResponse(const TableRows& rows)
+{
+       PluginResponse result;
+       for (const auto& row : rows) {
+               result.push_back(static_cast<Row>(*row));
+       }
+       return result;
 }
 
 } // namespace osquery
index 3ea4d8cd9ca62aa8786cec75e148c057b313e7ac..12e41b3cbb993c6232b18c5d3015f87772cdf5d1 100644 (file)
@@ -38,53 +38,56 @@ using PluginRequest = std::map<std::string, std::string>;
 using PluginResponse = std::vector<PluginRequest>;
 
 class Plugin : private boost::noncopyable {
- public:
-  virtual ~Plugin() = default;
-
- public:
-  /// The plugin may perform some initialization, not required.
-  virtual Status setUp() {
-    return Status::success();
-  }
-
-  /// The plugin may perform some tear down, release, not required.
-  virtual void tearDown() {}
-
-  /// The plugin may react to configuration updates.
-  virtual void configure() {}
-
-  /// The plugin may publish route info (other than registry type and name).
-  virtual PluginResponse routeInfo() const {
-    return PluginResponse();
-  }
-
-  /**
-   * @brief Plugins act by being called, using a request, returning a response.
-   *
-   * The plugin request is a thrift-serializable object. A response is optional
-   * but the API for using a plugin's call is defined by the registry. In most
-   * cases there are multiple supported call 'actions'. A registry type, or
-   * the plugin class, will define the action key and supported actions.
-   *
-   * @param request A plugin request input, including optional action.
-   * @param response A plugin response output.
-   *
-   * @return Status of the call, if the action was handled corrected.
-   */
-  virtual Status call(const PluginRequest& request,
-                      PluginResponse& response) = 0;
-
-  /// Allow the plugin to introspect into the registered name (for logging).
-  virtual void setName(const std::string& name) final;
-
-  /// Force call-sites to use #getName to access the plugin item's name.
-  virtual const std::string& getName() const {
-    return name_;
-  }
-
- protected:
-  /// Customized name for the plugin, usually set by the registry.
-  std::string name_;
+public:
+       virtual ~Plugin() = default;
+
+public:
+       /// The plugin may perform some initialization, not required.
+       virtual Status setUp()
+       {
+               return Status::success();
+       }
+
+       /// The plugin may perform some tear down, release, not required.
+       virtual void tearDown() {}
+
+       /// The plugin may react to configuration updates.
+       virtual void configure() {}
+
+       /// The plugin may publish route info (other than registry type and name).
+       virtual PluginResponse routeInfo() const
+       {
+               return PluginResponse();
+       }
+
+       /**
+        * @brief Plugins act by being called, using a request, returning a response.
+        *
+        * The plugin request is a thrift-serializable object. A response is optional
+        * but the API for using a plugin's call is defined by the registry. In most
+        * cases there are multiple supported call 'actions'. A registry type, or
+        * the plugin class, will define the action key and supported actions.
+        *
+        * @param request A plugin request input, including optional action.
+        * @param response A plugin response output.
+        *
+        * @return Status of the call, if the action was handled corrected.
+        */
+       virtual Status call(const PluginRequest& request,
+                                               PluginResponse& response) = 0;
+
+       /// Allow the plugin to introspect into the registered name (for logging).
+       virtual void setName(const std::string& name) final;
+
+       /// Force call-sites to use #getName to access the plugin item's name.
+       virtual const std::string& getName() const
+       {
+               return name_;
+       }
+
+protected:
+       /// Customized name for the plugin, usually set by the registry.
+       std::string name_;
 };
 
 /// Helper definition for a shared pointer to a Plugin.
index dc4d4ec51334fb830f092f6bc88de1c5b6a94707..c39b9eb6db6059f3cb5049e2c8c099f27dedcc2f 100644 (file)
 namespace osquery {
 
 class SQLPlugin : public Plugin {
- public:
-  /// Run a SQL query string against the SQL implementation.
-  virtual Status query(const std::string& query,
-                       QueryData& results,
-                       bool use_cache) const = 0;
-
-  /// Use the SQL implementation to parse a query string and return details
-  /// (name, type) about the columns.
-  virtual Status getQueryColumns(const std::string& query,
-                                 TableColumns& columns) const = 0;
-
-  /// Given a query, return the list of scanned tables.
-  virtual Status getQueryTables(const std::string& query,
-                                std::vector<std::string>& tables) const = 0;
-
-  /**
-   * @brief Attach a table at runtime.
-   *
-   * The SQL implementation plugin may need to manage how virtual tables are
-   * attached at run time. In the case of SQLite where a single DB object is
-   * managed, tables are enumerated and attached during initialization.
-   */
-  virtual Status attach(const std::string& /*name*/) {
-    return Status::success();
-  }
-
-  /// Tables may be detached by name.
-  virtual void detach(const std::string& /*name*/) {}
-
- public:
-  Status call(const PluginRequest& request, PluginResponse& response) override;
+public:
+       /// Run a SQL query string against the SQL implementation.
+       virtual Status query(const std::string& query,
+                                                QueryData& results,
+                                                bool use_cache) const = 0;
+
+       /// Use the SQL implementation to parse a query string and return details
+       /// (name, type) about the columns.
+       virtual Status getQueryColumns(const std::string& query,
+                                                                  TableColumns& columns) const = 0;
+
+       /// Given a query, return the list of scanned tables.
+       virtual Status getQueryTables(const std::string& query,
+                                                                 std::vector<std::string>& tables) const = 0;
+
+       /**
+        * @brief Attach a table at runtime.
+        *
+        * The SQL implementation plugin may need to manage how virtual tables are
+        * attached at run time. In the case of SQLite where a single DB object is
+        * managed, tables are enumerated and attached during initialization.
+        */
+       virtual Status attach(const std::string& /*name*/)
+       {
+               return Status::success();
+       }
+
+       /// Tables may be detached by name.
+       virtual void detach(const std::string& /*name*/) {}
+
+public:
+       Status call(const PluginRequest& request, PluginResponse& response) override;
 };
 
 } // namespace osquery
index a38c74995ece0495adeb69c204e7ff7f22eb6374..8231e309d536cd436dfbae6e7e963173fbf48837 100644 (file)
 
 namespace osquery {
 
-uint64_t Query::getPreviousEpoch() const {
-  return 0;
+uint64_t Query::getPreviousEpoch() const
+{
+       return 0;
 }
 
-uint64_t Query::getQueryCounter(bool new_query) const {
-  return 0;
+uint64_t Query::getQueryCounter(bool new_query) const
+{
+       return 0;
 }
 
-Status Query::getPreviousQueryResults(QueryDataSet& results) const {
-  return Status::success();
+Status Query::getPreviousQueryResults(QueryDataSet& results) const
+{
+       return Status::success();
 }
 
-std::vector<std::string> Query::getStoredQueryNames() {
-  std::vector<std::string> results;
-  return results;
+std::vector<std::string> Query::getStoredQueryNames()
+{
+       std::vector<std::string> results;
+       return results;
 }
 
-bool Query::isQueryNameInDatabase() const {
-  auto names = Query::getStoredQueryNames();
-  return std::find(names.begin(), names.end(), name_) != names.end();
+bool Query::isQueryNameInDatabase() const
+{
+       auto names = Query::getStoredQueryNames();
+       return std::find(names.begin(), names.end(), name_) != names.end();
 }
 
 static inline void saveQuery(const std::string& name,
-                             const std::string& query) {
+                                                        const std::string& query)
+{
 }
 
-bool Query::isNewQuery() const {
-  return true;
+bool Query::isNewQuery() const
+{
+       return true;
 }
 
 Status Query::addNewResults(QueryDataTyped qd,
-                            const uint64_t epoch,
-                            uint64_t& counter) const {
-  DiffResults dr;
-  return addNewResults(std::move(qd), epoch, counter, dr, false);
+                                                       const uint64_t epoch,
+                                                       uint64_t& counter) const
+{
+       DiffResults dr;
+       return addNewResults(std::move(qd), epoch, counter, dr, false);
 }
 
 Status Query::addNewResults(QueryDataTyped current_qd,
-                            const uint64_t current_epoch,
-                            uint64_t& counter,
-                            DiffResults& dr,
-                            bool calculate_diff) const {
-  // The current results are 'fresh' when not calculating a differential.
-  bool fresh_results = !calculate_diff;
-  bool new_query = false;
-  if (!isQueryNameInDatabase()) {
-    // This is the first encounter of the scheduled query.
-    fresh_results = true;
-    INFO(OSQUERY) << "Storing initial results for new scheduled query: " << name_;
-    saveQuery(name_, query_);
-  } else if (getPreviousEpoch() != current_epoch) {
-    fresh_results = true;
-    INFO(OSQUERY) << "New Epoch " << current_epoch << " for scheduled query "
-              << name_;
-  } else if (isNewQuery()) {
-    // This query is 'new' in that the previous results may be invalid.
-    new_query = true;
-    INFO(OSQUERY) << "Scheduled query has been updated: " + name_;
-    saveQuery(name_, query_);
-  }
-
-  // Use a 'target' avoid copying the query data when serializing and saving.
-  // If a differential is requested and needed the target remains the original
-  // query data, otherwise the content is moved to the differential's added set.
-  const auto* target_gd = &current_qd;
-  bool update_db = true;
-  if (!fresh_results && calculate_diff) {
-    // Get the rows from the last run of this query name.
-    QueryDataSet previous_qd;
-    auto status = getPreviousQueryResults(previous_qd);
-    if (!status.ok()) {
-      return status;
-    }
-
-    // Calculate the differential between previous and current query results.
-    dr = diff(previous_qd, current_qd);
-
-    update_db = (!dr.added.empty() || !dr.removed.empty());
-  } else {
-    dr.added = std::move(current_qd);
-    target_gd = &dr.added;
-  }
-
-  return Status::success();
+                                                       const uint64_t current_epoch,
+                                                       uint64_t& counter,
+                                                       DiffResults& dr,
+                                                       bool calculate_diff) const
+{
+       // The current results are 'fresh' when not calculating a differential.
+       bool fresh_results = !calculate_diff;
+       bool new_query = false;
+       if (!isQueryNameInDatabase()) {
+               // This is the first encounter of the scheduled query.
+               fresh_results = true;
+               INFO(OSQUERY) << "Storing initial results for new scheduled query: " << name_;
+               saveQuery(name_, query_);
+       } else if (getPreviousEpoch() != current_epoch) {
+               fresh_results = true;
+               INFO(OSQUERY) << "New Epoch " << current_epoch << " for scheduled query "
+                                         << name_;
+       } else if (isNewQuery()) {
+               // This query is 'new' in that the previous results may be invalid.
+               new_query = true;
+               INFO(OSQUERY) << "Scheduled query has been updated: " + name_;
+               saveQuery(name_, query_);
+       }
+
+       // Use a 'target' avoid copying the query data when serializing and saving.
+       // If a differential is requested and needed the target remains the original
+       // query data, otherwise the content is moved to the differential's added set.
+       const auto* target_gd = &current_qd;
+       bool update_db = true;
+       if (!fresh_results && calculate_diff) {
+               // Get the rows from the last run of this query name.
+               QueryDataSet previous_qd;
+               auto status = getPreviousQueryResults(previous_qd);
+               if (!status.ok()) {
+                       return status;
+               }
+
+               // Calculate the differential between previous and current query results.
+               dr = diff(previous_qd, current_qd);
+
+               update_db = (!dr.added.empty() || !dr.removed.empty());
+       } else {
+               dr.added = std::move(current_qd);
+               target_gd = &dr.added;
+       }
+
+       return Status::success();
 }
 
 }
index 78f469bc88889ec42e75e510d272c7c894e282f7..9c1d738f43b673b6af01ea922d740c9672870438 100644 (file)
 namespace osquery {
 
 const std::map<ColumnType, std::string> kColumnTypeNames = {
-    {UNKNOWN_TYPE, "UNKNOWN"},
-    {TEXT_TYPE, "TEXT"},
-    {INTEGER_TYPE, "INTEGER"},
-    {BIGINT_TYPE, "BIGINT"},
-    {UNSIGNED_BIGINT_TYPE, "UNSIGNED BIGINT"},
-    {DOUBLE_TYPE, "DOUBLE"},
-    {BLOB_TYPE, "BLOB"},
+       {UNKNOWN_TYPE, "UNKNOWN"},
+       {TEXT_TYPE, "TEXT"},
+       {INTEGER_TYPE, "INTEGER"},
+       {BIGINT_TYPE, "BIGINT"},
+       {UNSIGNED_BIGINT_TYPE, "UNSIGNED BIGINT"},
+       {DOUBLE_TYPE, "DOUBLE"},
+       {BLOB_TYPE, "BLOB"},
 };
 
 }
index 8fcd965d7b33d2fb2d26633e1fe361856b4c1212..4ebf1c2a2a364d1f5520b0453b7b227423ff54de 100644 (file)
@@ -35,62 +35,64 @@ namespace osquery {
  * to communicate these subtleties to the user.
  */
 enum class ColumnOptions {
-  /// Default/no options.
-  DEFAULT = 0,
-
-  /// Treat this column as a primary key.
-  INDEX = 1,
-
-  /// This column MUST be included in the query predicate.
-  REQUIRED = 2,
-
-  /*
-   * @brief This column is used to generate additional information.
-   *
-   * If this column is included in the query predicate, the table will generate
-   * additional information. Consider the browser_plugins or shell history
-   * tables: by default they list the plugins or history relative to the user
-   * running the query. However, if the calling query specifies a UID explicitly
-   * in the predicate, the meaning of the table changes and results for that
-   * user are returned instead.
-   */
-  ADDITIONAL = 4,
-
-  /*
-   * @brief This column can be used to optimize the query.
-   *
-   * If this column is included in the query predicate, the table will generate
-   * optimized information. Consider the system_controls table, a default filter
-   * without a query predicate lists all of the keys. When a specific domain is
-   * included in the predicate then the table will only issue syscalls/lookups
-   * for that domain, greatly optimizing the time and utilization.
-   *
-   * This optimization does not mean the column is an index.
-   */
-  OPTIMIZED = 8,
-
-  /// This column should be hidden from '*'' selects.
-  HIDDEN = 16,
+       /// Default/no options.
+       DEFAULT = 0,
+
+       /// Treat this column as a primary key.
+       INDEX = 1,
+
+       /// This column MUST be included in the query predicate.
+       REQUIRED = 2,
+
+       /*
+        * @brief This column is used to generate additional information.
+        *
+        * If this column is included in the query predicate, the table will generate
+        * additional information. Consider the browser_plugins or shell history
+        * tables: by default they list the plugins or history relative to the user
+        * running the query. However, if the calling query specifies a UID explicitly
+        * in the predicate, the meaning of the table changes and results for that
+        * user are returned instead.
+        */
+       ADDITIONAL = 4,
+
+       /*
+        * @brief This column can be used to optimize the query.
+        *
+        * If this column is included in the query predicate, the table will generate
+        * optimized information. Consider the system_controls table, a default filter
+        * without a query predicate lists all of the keys. When a specific domain is
+        * included in the predicate then the table will only issue syscalls/lookups
+        * for that domain, greatly optimizing the time and utilization.
+        *
+        * This optimization does not mean the column is an index.
+        */
+       OPTIMIZED = 8,
+
+       /// This column should be hidden from '*'' selects.
+       HIDDEN = 16,
 };
 
 /// Treat column options as a set of flags.
-inline ColumnOptions operator|(ColumnOptions a, ColumnOptions b) {
-  return static_cast<ColumnOptions>(static_cast<int>(a) | static_cast<int>(b));
+inline ColumnOptions operator|(ColumnOptions a, ColumnOptions b)
+{
+       return static_cast<ColumnOptions>(static_cast<int>(a) | static_cast<int>(b));
 }
 
 /// Treat column options as a set of flags.
-inline size_t operator&(ColumnOptions a, ColumnOptions b) {
-  return static_cast<size_t>(a) & static_cast<size_t>(b);
+inline size_t operator&(ColumnOptions a, ColumnOptions b)
+{
+       return static_cast<size_t>(a) & static_cast<size_t>(b);
 }
 
 enum ColumnType {
-  UNKNOWN_TYPE = 0,
-  TEXT_TYPE,
-  INTEGER_TYPE,
-  BIGINT_TYPE,
-  UNSIGNED_BIGINT_TYPE,
-  DOUBLE_TYPE,
-  BLOB_TYPE,
+       UNKNOWN_TYPE = 0,
+       TEXT_TYPE,
+       INTEGER_TYPE,
+       BIGINT_TYPE,
+       UNSIGNED_BIGINT_TYPE,
+       DOUBLE_TYPE,
+       BLOB_TYPE,
 };
 
 /// Map of type constant to the SQLite string-name representation.
@@ -101,7 +103,7 @@ using TableName = std::string;
 
 /// Alias for an ordered list of column name and corresponding SQL type.
 using TableColumns =
-    std::vector<std::tuple<std::string, ColumnType, ColumnOptions>>;
+       std::vector<std::tuple<std::string, ColumnType, ColumnOptions>>;
 
 /// Alias for map of column alias sets.
 using ColumnAliasSet = std::map<std::string, std::set<std::string>>;
index ba35e573e827888999a9651f1bd992efab25dcbf..4fc42dba4db5f13fdbb1c6a89ad639e4b9e776bd 100644 (file)
 
 namespace osquery {
 
-DiffResults diff(QueryDataSet& old, QueryDataTyped& current) {
-  DiffResults r;
+DiffResults diff(QueryDataSet& old, QueryDataTyped& current)
+{
+       DiffResults r;
 
-  for (auto& i : current) {
-    auto item = old.find(i);
-    if (item != old.end()) {
-      old.erase(item);
-    } else {
-      r.added.push_back(i);
-    }
-  }
+       for (auto& i : current) {
+               auto item = old.find(i);
+               if (item != old.end()) {
+                       old.erase(item);
+               } else {
+                       r.added.push_back(i);
+               }
+       }
 
-  for (auto& i : old) {
-    r.removed.push_back(std::move(i));
-  }
+       for (auto& i : old) {
+               r.removed.push_back(std::move(i));
+       }
 
-  return r;
+       return r;
 }
 
 } // namespace osquery
index 0b1732e39fbdd2e4311b3ee8268f71ee8699f1f0..edbf025b393b57e19cf5d08dbf2e286fec9ae98a 100644 (file)
@@ -22,26 +22,28 @@ namespace osquery {
  * "removed" subset of rows.
  */
 struct DiffResults : private only_movable {
- public:
-  /// vector of added rows
-  QueryDataTyped added;
-
-  /// vector of removed rows
-  QueryDataTyped removed;
-
-  DiffResults() {}
-  DiffResults(DiffResults&&) = default;
-  DiffResults& operator=(DiffResults&&) = default;
-
-  /// equals operator
-  bool operator==(const DiffResults& comp) const {
-    return (comp.added == added) && (comp.removed == removed);
-  }
-
-  /// not equals operator
-  bool operator!=(const DiffResults& comp) const {
-    return !(*this == comp);
-  }
+public:
+       /// vector of added rows
+       QueryDataTyped added;
+
+       /// vector of removed rows
+       QueryDataTyped removed;
+
+       DiffResults() {}
+       DiffResults(DiffResults&&) = default;
+       DiffResults& operator=(DiffResults&&) = default;
+
+       /// equals operator
+       bool operator==(const DiffResults& comp) const
+       {
+               return (comp.added == added) && (comp.removed == removed);
+       }
+
+       /// not equals operator
+       bool operator!=(const DiffResults& comp) const
+       {
+               return !(*this == comp);
+       }
 };
 
 /**
index e50758ffafdfd0fd398a5c4e7082c9cccb7845b7..8dd928aa697e8e10f0965916b5e612da8bf4cf89 100644 (file)
@@ -22,53 +22,55 @@ namespace osquery {
  * attributes. Those attributes are represented in this data structure.
  */
 struct ScheduledQuery : private only_movable {
-  /// Name of the pack containing query
-  std::string pack_name;
-
-  /// Name of the query
-  std::string name;
-
-  /// The SQL query.
-  std::string query;
-
-  /// Owner of the query
-  std::string oncall;
-
-  /// How often the query should be executed, in second.
-  size_t interval{0};
-
-  /// A temporary splayed internal.
-  size_t splayed_interval{0};
-
-  /**
-   * @brief Queries are blacklisted based on logic in the configuration.
-   *
-   * Most calls to inspect scheduled queries will abstract away the blacklisting
-   * concept and only return non-blacklisted queries. The config may be asked
-   * to return all queries, thus it is important to capture this optional data.
-   */
-  bool blacklisted{false};
-
-  /// Set of query options.
-  std::map<std::string, bool> options;
-
-  ScheduledQuery(const std::string& pack_name,
-                 const std::string& name,
-                 const std::string& query)
-      : pack_name(pack_name), name(name), query(query) {}
-  ScheduledQuery() = default;
-  ScheduledQuery(ScheduledQuery&&) = default;
-  ScheduledQuery& operator=(ScheduledQuery&&) = default;
-
-  /// equals operator
-  bool operator==(const ScheduledQuery& comp) const {
-    return (comp.query == query) && (comp.interval == interval);
-  }
-
-  /// not equals operator
-  bool operator!=(const ScheduledQuery& comp) const {
-    return !(*this == comp);
-  }
+       /// Name of the pack containing query
+       std::string pack_name;
+
+       /// Name of the query
+       std::string name;
+
+       /// The SQL query.
+       std::string query;
+
+       /// Owner of the query
+       std::string oncall;
+
+       /// How often the query should be executed, in second.
+       size_t interval{0};
+
+       /// A temporary splayed internal.
+       size_t splayed_interval{0};
+
+       /**
+        * @brief Queries are blacklisted based on logic in the configuration.
+        *
+        * Most calls to inspect scheduled queries will abstract away the blacklisting
+        * concept and only return non-blacklisted queries. The config may be asked
+        * to return all queries, thus it is important to capture this optional data.
+        */
+       bool blacklisted{false};
+
+       /// Set of query options.
+       std::map<std::string, bool> options;
+
+       ScheduledQuery(const std::string& pack_name,
+                                  const std::string& name,
+                                  const std::string& query)
+               : pack_name(pack_name), name(name), query(query) {}
+       ScheduledQuery() = default;
+       ScheduledQuery(ScheduledQuery&&) = default;
+       ScheduledQuery& operator=(ScheduledQuery&&) = default;
+
+       /// equals operator
+       bool operator==(const ScheduledQuery& comp) const
+       {
+               return (comp.query == query) && (comp.interval == interval);
+       }
+
+       /// not equals operator
+       bool operator!=(const ScheduledQuery& comp) const
+       {
+               return !(*this == comp);
+       }
 };
 
 } // namespace osquery
index 9b517c5c1deaab8c1b00b76a54621e43402843dd..5d63e84e12cbbe57717d151973288c30dd5404fc 100644 (file)
@@ -28,36 +28,36 @@ using TableRows = std::vector<TableRowHolder>;
  * a map<string, string> or code generated with type-safe fields.
  */
 class TableRow {
- public:
-  TableRow() = default;
-  virtual ~TableRow() {}
-
-  /**
-   * Output the rowid of the current row into pRowid, returning SQLITE_OK if
-   * successful or SQLITE_ERROR if not.
-   */
-  virtual int get_rowid(sqlite_int64 default_value,
-                        sqlite_int64* pRowid) const = 0;
-  /**
-   * Invoke the appropriate sqlite3_result_xxx method for the given column, or
-   * null if the value does not fit the column type.
-   */
-  virtual int get_column(sqlite3_context* ctx,
-                         sqlite3_vtab* pVtab,
-                         int col) = 0;
-  /**
-   * Clone this row.
-   */
-  virtual TableRowHolder clone() const = 0;
-
-  /**
-   * Convert this row to a string map.
-   */
-  virtual operator Row() const = 0;
-
- protected:
-  TableRow(const TableRow&) = default;
-  TableRow& operator=(const TableRow&) = default;
+public:
+       TableRow() = default;
+       virtual ~TableRow() {}
+
+       /**
+        * Output the rowid of the current row into pRowid, returning SQLITE_OK if
+        * successful or SQLITE_ERROR if not.
+        */
+       virtual int get_rowid(sqlite_int64 default_value,
+                                                 sqlite_int64* pRowid) const = 0;
+       /**
+        * Invoke the appropriate sqlite3_result_xxx method for the given column, or
+        * null if the value does not fit the column type.
+        */
+       virtual int get_column(sqlite3_context* ctx,
+                                                  sqlite3_vtab* pVtab,
+                                                  int col) = 0;
+       /**
+        * Clone this row.
+        */
+       virtual TableRowHolder clone() const = 0;
+
+       /**
+        * Convert this row to a string map.
+        */
+       virtual operator Row() const = 0;
+
+protected:
+       TableRow(const TableRow&) = default;
+       TableRow& operator=(const TableRow&) = default;
 };
 
 } // namespace osquery
index 8d1c4003373c0d76af6930fb807e2bd2db510c06..48ced6c41f2719acf0ddaf38e6b4ee6e205b74a7 100644 (file)
@@ -20,26 +20,29 @@ size_t TablePlugin::kCacheInterval = 0;
 size_t TablePlugin::kCacheStep = 0;
 
 Status TablePlugin::addExternal(const std::string& name,
-                                const PluginResponse& response) {
-  // Attach the table.
-  if (response.size() == 0) {
-    // Invalid table route info.
-    // Tables must broadcast their column information, this is used while the
-    // core is deciding if the extension's route is valid.
-    return Status(1, "Invalid route info");
-  }
+                                                               const PluginResponse& response)
+{
+       // Attach the table.
+       if (response.size() == 0) {
+               // Invalid table route info.
+               // Tables must broadcast their column information, this is used while the
+               // core is deciding if the extension's route is valid.
+               return Status(1, "Invalid route info");
+       }
 
-  // Use the SQL registry to attach the name/definition.
-  return Registry::call("sql", "sql", {{"action", "attach"}, {"table", name}});
+       // Use the SQL registry to attach the name/definition.
+       return Registry::call("sql", "sql", {{"action", "attach"}, {"table", name}});
 }
 
-void TablePlugin::removeExternal(const std::string& name) {
-  // Detach the table name.
-  Registry::call("sql", "sql", {{"action", "detach"}, {"table", name}});
+void TablePlugin::removeExternal(const std::string& name)
+{
+       // Detach the table name.
+       Registry::call("sql", "sql", {{"action", "detach"}, {"table", name}});
 }
 
 void TablePlugin::setRequestFromContext(const QueryContext& context,
-                                                                               PluginRequest& request) {
+                                                                               PluginRequest& request)
+{
        vist::json::Json document;
        vist::json::Array constraints;
 
@@ -69,7 +72,8 @@ void TablePlugin::setRequestFromContext(const QueryContext& context,
        DEBUG(OSQUERY) << "request context->" << request["context"];
 }
 
-QueryContext TablePlugin::getContextFromRequest(const PluginRequest& request) const {
+QueryContext TablePlugin::getContextFromRequest(const PluginRequest& request) const
+{
        QueryContext context;
        if (request.count("context") == 0)
                return context;
@@ -83,13 +87,13 @@ QueryContext TablePlugin::getContextFromRequest(const PluginRequest& request) co
                UsedColumns colsUsed;
                Array array = document.get<Array>("colsUsed");
                for (auto i = 0; i < array.size(); i++) {
-                       std::string name = array.at(i); 
+                       std::string name = array.at(i);
                        colsUsed.insert(name);
                }
                context.colsUsed = colsUsed;
        }
 
-       Array constraints = document.get<Array>("constraints"); 
+       Array constraints = document.get<Array>("constraints");
        for (auto i = 0; i < constraints.size(); i++) {
                auto constraint = Object::Create(constraints.at(i));
                std::string name = constraint["name"];
@@ -100,350 +104,368 @@ QueryContext TablePlugin::getContextFromRequest(const PluginRequest& request) co
 }
 
 UsedColumnsBitset TablePlugin::usedColumnsToBitset(
-    const UsedColumns usedColumns) const {
-  UsedColumnsBitset result;
-
-  const auto columns = this->columns();
-  const auto aliases = this->aliasedColumns();
-  for (size_t i = 0; i < columns.size(); i++) {
-    auto column_name = std::get<0>(columns[i]);
-    const auto& aliased_name = aliases.find(column_name);
-    if (aliased_name != aliases.end()) {
-      column_name = aliased_name->second;
-    }
-    if (usedColumns.find(column_name) != usedColumns.end()) {
-      result.set(i);
-    }
-  }
+       const UsedColumns usedColumns) const
+{
+       UsedColumnsBitset result;
+
+       const auto columns = this->columns();
+       const auto aliases = this->aliasedColumns();
+       for (size_t i = 0; i < columns.size(); i++) {
+               auto column_name = std::get<0>(columns[i]);
+               const auto& aliased_name = aliases.find(column_name);
+               if (aliased_name != aliases.end()) {
+                       column_name = aliased_name->second;
+               }
+               if (usedColumns.find(column_name) != usedColumns.end()) {
+                       result.set(i);
+               }
+       }
 
-  return result;
+       return result;
 }
 
 Status TablePlugin::call(const PluginRequest& request,
-                         PluginResponse& response) {
-  response.clear();
-
-  // TablePlugin API calling requires an action.
-  if (request.count("action") == 0) {
-    return Status(1, "Table plugins must include a request action");
-  }
-
-  const auto& action = request.at("action");
-
-  if (action == "generate") {
-    auto context = getContextFromRequest(request);
-    TableRows result = generate(context);
-    response = tableRowsToPluginResponse(result);
-  } else if (action == "delete") {
-    auto context = getContextFromRequest(request);
-    response = delete_(context, request);
-  } else if (action == "insert") {
-    auto context = getContextFromRequest(request);
-    response = insert(context, request);
-  } else if (action == "update") {
-    auto context = getContextFromRequest(request);
-    response = update(context, request);
-  } else if (action == "columns") {
-    response = routeInfo();
-  } else {
-    return Status(1, "Unknown table plugin action: " + action);
-  }
-
-  return Status::success();
-}
-
-std::string TablePlugin::columnDefinition(bool is_extension) const {
-  return osquery::columnDefinition(columns(), is_extension);
-}
-
-PluginResponse TablePlugin::routeInfo() const {
-  // Route info consists of the serialized column information.
-  PluginResponse response;
-  for (const auto& column : columns()) {
-    response.push_back(
-        {{"id", "column"},
-         {"name", std::get<0>(column)},
-         {"type", columnTypeName(std::get<1>(column))},
-         {"op", INTEGER(static_cast<size_t>(std::get<2>(column)))}});
-  }
-  // Each table name alias is provided such that the core may add the views.
-  // These views need to be removed when the backing table is detached.
-  for (const auto& alias : aliases()) {
-    response.push_back({{"id", "alias"}, {"alias", alias}});
-  }
-
-  // Each column alias must be provided, additionally to the column's option.
-  // This sets up the value-replacement move within the SQL implementation.
-  for (const auto& target : columnAliases()) {
-    for (const auto& alias : target.second) {
-      response.push_back(
-          {{"id", "columnAlias"}, {"name", alias}, {"target", target.first}});
-    }
-  }
-
-  response.push_back(
-      {{"id", "attributes"},
-       {"attributes", INTEGER(static_cast<size_t>(attributes()))}});
-  return response;
-}
-
-static bool cacheAllowed(const TableColumns& cols, const QueryContext& ctx) {
-  if (!ctx.useCache()) {
-    // The query execution did not request use of the warm cache.
-    return false;
-  }
-
-  auto uncachable = ColumnOptions::INDEX | ColumnOptions::REQUIRED |
-                    ColumnOptions::ADDITIONAL | ColumnOptions::OPTIMIZED;
-  for (const auto& column : cols) {
-    auto opts = std::get<2>(column) & uncachable;
-    if (opts && ctx.constraints.at(std::get<0>(column)).exists()) {
-      return false;
-    }
-  }
-  return true;
-}
-
-bool TablePlugin::isCached(size_t step, const QueryContext& ctx) const {
-  // Perform the step comparison first, because it's easy.
-  return (step < last_cached_ + last_interval_ && cacheAllowed(columns(), ctx));
-}
-
-TableRows TablePlugin::getCache() const {
-  TableRows results;
-  return results;
+                                                PluginResponse& response)
+{
+       response.clear();
+
+       // TablePlugin API calling requires an action.
+       if (request.count("action") == 0) {
+               return Status(1, "Table plugins must include a request action");
+       }
+
+       const auto& action = request.at("action");
+
+       if (action == "generate") {
+               auto context = getContextFromRequest(request);
+               TableRows result = generate(context);
+               response = tableRowsToPluginResponse(result);
+       } else if (action == "delete") {
+               auto context = getContextFromRequest(request);
+               response = delete_(context, request);
+       } else if (action == "insert") {
+               auto context = getContextFromRequest(request);
+               response = insert(context, request);
+       } else if (action == "update") {
+               auto context = getContextFromRequest(request);
+               response = update(context, request);
+       } else if (action == "columns") {
+               response = routeInfo();
+       } else {
+               return Status(1, "Unknown table plugin action: " + action);
+       }
+
+       return Status::success();
+}
+
+std::string TablePlugin::columnDefinition(bool is_extension) const
+{
+       return osquery::columnDefinition(columns(), is_extension);
+}
+
+PluginResponse TablePlugin::routeInfo() const
+{
+       // Route info consists of the serialized column information.
+       PluginResponse response;
+       for (const auto& column : columns()) {
+               response.push_back({
+                       {"id", "column"},
+                       {"name", std::get<0>(column)},
+                       {"type", columnTypeName(std::get<1>(column))},
+                       {"op", INTEGER(static_cast<size_t>(std::get<2>(column)))}});
+       }
+       // Each table name alias is provided such that the core may add the views.
+       // These views need to be removed when the backing table is detached.
+       for (const auto& alias : aliases()) {
+               response.push_back({{"id", "alias"}, {"alias", alias}});
+       }
+
+       // Each column alias must be provided, additionally to the column's option.
+       // This sets up the value-replacement move within the SQL implementation.
+       for (const auto& target : columnAliases()) {
+               for (const auto& alias : target.second) {
+                       response.push_back(
+                       {{"id", "columnAlias"}, {"name", alias}, {"target", target.first}});
+               }
+       }
+
+       response.push_back({
+               {"id", "attributes"},
+               {"attributes", INTEGER(static_cast<size_t>(attributes()))}});
+       return response;
+}
+
+static bool cacheAllowed(const TableColumns& cols, const QueryContext& ctx)
+{
+       if (!ctx.useCache()) {
+               // The query execution did not request use of the warm cache.
+               return false;
+       }
+
+       auto uncachable = ColumnOptions::INDEX | ColumnOptions::REQUIRED |
+                                         ColumnOptions::ADDITIONAL | ColumnOptions::OPTIMIZED;
+       for (const auto& column : cols) {
+               auto opts = std::get<2>(column) & uncachable;
+               if (opts && ctx.constraints.at(std::get<0>(column)).exists()) {
+                       return false;
+               }
+       }
+       return true;
+}
+
+bool TablePlugin::isCached(size_t step, const QueryContext& ctx) const
+{
+       // Perform the step comparison first, because it's easy.
+       return (step < last_cached_ + last_interval_ && cacheAllowed(columns(), ctx));
+}
+
+TableRows TablePlugin::getCache() const
+{
+       TableRows results;
+       return results;
 }
 
 void TablePlugin::setCache(size_t step,
-                           size_t interval,
-                           const QueryContext& ctx,
-                           const TableRows& results) {
-  return;
-}
-
-std::string columnDefinition(const TableColumns& columns, bool is_extension) {
-  std::map<std::string, bool> epilog;
-  bool indexed = false;
-  std::vector<std::string> pkeys;
-
-  std::string statement = "(";
-  for (size_t i = 0; i < columns.size(); ++i) {
-    const auto& column = columns.at(i);
-    statement +=
-        '`' + std::get<0>(column) + "` " + columnTypeName(std::get<1>(column));
-    auto& options = std::get<2>(column);
-    if (options & (ColumnOptions::INDEX | ColumnOptions::ADDITIONAL)) {
-      if (options & ColumnOptions::INDEX) {
-        indexed = true;
-      }
-      pkeys.push_back(std::get<0>(column));
-      epilog["WITHOUT ROWID"] = true;
-    }
-    if (options & ColumnOptions::HIDDEN) {
-      statement += " HIDDEN";
-    }
-    if (i < columns.size() - 1) {
-      statement += ", ";
-    }
-  }
-
-  // If there are only 'additional' columns (rare), do not attempt a pkey.
-  if (!indexed) {
-    epilog["WITHOUT ROWID"] = false;
-    pkeys.clear();
-  }
-
-  // Append the primary keys, if any were defined.
-  if (!pkeys.empty()) {
-    statement += ", PRIMARY KEY (";
-    for (auto pkey = pkeys.begin(); pkey != pkeys.end();) {
-      statement += '`' + std::move(*pkey) + '`';
-      if (++pkey != pkeys.end()) {
-        statement += ", ";
-      }
-    }
-    statement += ')';
-  }
-
-  // Tables implemented by extension can be made read/write; make sure to always
-  // keep the rowid column, as we need it to reference rows when handling UPDATE
-  // and DELETE queries
-  if (is_extension) {
-    epilog["WITHOUT ROWID"] = false;
-  }
-
-  statement += ')';
-  for (auto& ei : epilog) {
-    if (ei.second) {
-      statement += ' ' + std::move(ei.first);
-    }
-  }
-  return statement;
+                                                  size_t interval,
+                                                  const QueryContext& ctx,
+                                                  const TableRows& results)
+{
+       return;
+}
+
+std::string columnDefinition(const TableColumns& columns, bool is_extension)
+{
+       std::map<std::string, bool> epilog;
+       bool indexed = false;
+       std::vector<std::string> pkeys;
+
+       std::string statement = "(";
+       for (size_t i = 0; i < columns.size(); ++i) {
+               const auto& column = columns.at(i);
+               statement +=
+                       '`' + std::get<0>(column) + "` " + columnTypeName(std::get<1>(column));
+               auto& options = std::get<2>(column);
+               if (options & (ColumnOptions::INDEX | ColumnOptions::ADDITIONAL)) {
+                       if (options & ColumnOptions::INDEX) {
+                               indexed = true;
+                       }
+                       pkeys.push_back(std::get<0>(column));
+                       epilog["WITHOUT ROWID"] = true;
+               }
+               if (options & ColumnOptions::HIDDEN) {
+                       statement += " HIDDEN";
+               }
+               if (i < columns.size() - 1) {
+                       statement += ", ";
+               }
+       }
+
+       // If there are only 'additional' columns (rare), do not attempt a pkey.
+       if (!indexed) {
+               epilog["WITHOUT ROWID"] = false;
+               pkeys.clear();
+       }
+
+       // Append the primary keys, if any were defined.
+       if (!pkeys.empty()) {
+               statement += ", PRIMARY KEY (";
+               for (auto pkey = pkeys.begin(); pkey != pkeys.end();) {
+                       statement += '`' + std::move(*pkey) + '`';
+                       if (++pkey != pkeys.end()) {
+                               statement += ", ";
+                       }
+               }
+               statement += ')';
+       }
+
+       // Tables implemented by extension can be made read/write; make sure to always
+       // keep the rowid column, as we need it to reference rows when handling UPDATE
+       // and DELETE queries
+       if (is_extension) {
+               epilog["WITHOUT ROWID"] = false;
+       }
+
+       statement += ')';
+       for (auto& ei : epilog) {
+               if (ei.second) {
+                       statement += ' ' + std::move(ei.first);
+               }
+       }
+       return statement;
 }
 
 std::string columnDefinition(const PluginResponse& response,
-                             bool aliases,
-                             bool is_extension) {
-  TableColumns columns;
-  // Maintain a map of column to the type, for alias type lookups.
-  std::map<std::string, ColumnType> column_types;
-  for (const auto& column : response) {
-    auto id = column.find("id");
-    if (id == column.end()) {
-      continue;
-    }
-
-    auto cname = column.find("name");
-    auto ctype = column.find("type");
-    if (id->second == "column" && cname != column.end() &&
-        ctype != column.end()) {
-      auto options = ColumnOptions::DEFAULT;
-
-      auto cop = column.find("op");
-      if (cop != column.end()) {
-        auto op = tryTo<int>(cop->second);
-        if (op) {
-          options = static_cast<ColumnOptions>(op.take());
-        }
-      }
-      auto column_type = columnTypeName(ctype->second);
-      columns.push_back(make_tuple(cname->second, column_type, options));
-      if (aliases) {
-        column_types[cname->second] = column_type;
-      }
-    } else if (id->second == "columnAlias" && cname != column.end() &&
-               aliases) {
-      auto ctarget = column.find("target");
-      if (ctarget != column.end()) {
-        auto target_ctype = column_types.find(ctarget->second);
-        if (target_ctype != column_types.end()) {
-          columns.push_back(make_tuple(
-              cname->second, target_ctype->second, ColumnOptions::HIDDEN));
-        }
-      }
-    }
-  }
-  return columnDefinition(columns, is_extension);
-}
-
-ColumnType columnTypeName(const std::string& type) {
-  for (const auto& col : kColumnTypeNames) {
-    if (col.second == type) {
-      return col.first;
-    }
-  }
-  return UNKNOWN_TYPE;
-}
-
-bool ConstraintList::exists(const ConstraintOperatorFlag ops) const {
-  if (ops == ANY_OP) {
-    return (constraints_.size() > 0);
-  } else {
-    for (const struct Constraint& c : constraints_) {
-      if (c.op & ops) {
-        return true;
-      }
-    }
-    return false;
-  }
-}
-
-bool ConstraintList::matches(const std::string& expr) const {
-  // Support each SQL affinity type casting.
-  if (affinity == TEXT_TYPE) {
-    return literal_matches<TEXT_LITERAL>(expr);
-  } else if (affinity == INTEGER_TYPE) {
-    auto lexpr = tryTo<INTEGER_LITERAL>(expr);
-    if (lexpr) {
-      return literal_matches<INTEGER_LITERAL>(lexpr.take());
-    }
-  } else if (affinity == BIGINT_TYPE) {
-    auto lexpr = tryTo<BIGINT_LITERAL>(expr);
-    if (lexpr) {
-      return literal_matches<BIGINT_LITERAL>(lexpr.take());
-    }
-  } else if (affinity == UNSIGNED_BIGINT_TYPE) {
-    auto lexpr = tryTo<UNSIGNED_BIGINT_LITERAL>(expr);
-    if (lexpr) {
-      return literal_matches<UNSIGNED_BIGINT_LITERAL>(lexpr.take());
-    }
-  }
-
-  return false;
+                                                        bool aliases,
+                                                        bool is_extension)
+{
+       TableColumns columns;
+       // Maintain a map of column to the type, for alias type lookups.
+       std::map<std::string, ColumnType> column_types;
+       for (const auto& column : response) {
+               auto id = column.find("id");
+               if (id == column.end()) {
+                       continue;
+               }
+
+               auto cname = column.find("name");
+               auto ctype = column.find("type");
+               if (id->second == "column" && cname != column.end() &&
+                       ctype != column.end()) {
+                       auto options = ColumnOptions::DEFAULT;
+
+                       auto cop = column.find("op");
+                       if (cop != column.end()) {
+                               auto op = tryTo<int>(cop->second);
+                               if (op) {
+                                       options = static_cast<ColumnOptions>(op.take());
+                               }
+                       }
+                       auto column_type = columnTypeName(ctype->second);
+                       columns.push_back(make_tuple(cname->second, column_type, options));
+                       if (aliases) {
+                               column_types[cname->second] = column_type;
+                       }
+               } else if (id->second == "columnAlias" && cname != column.end() &&
+                                  aliases) {
+                       auto ctarget = column.find("target");
+                       if (ctarget != column.end()) {
+                               auto target_ctype = column_types.find(ctarget->second);
+                               if (target_ctype != column_types.end()) {
+                                       columns.push_back(make_tuple(
+                                                                                 cname->second, target_ctype->second, ColumnOptions::HIDDEN));
+                               }
+                       }
+               }
+       }
+       return columnDefinition(columns, is_extension);
+}
+
+ColumnType columnTypeName(const std::string& type)
+{
+       for (const auto& col : kColumnTypeNames) {
+               if (col.second == type) {
+                       return col.first;
+               }
+       }
+       return UNKNOWN_TYPE;
+}
+
+bool ConstraintList::exists(const ConstraintOperatorFlag ops) const
+{
+       if (ops == ANY_OP) {
+               return (constraints_.size() > 0);
+       } else {
+               for (const struct Constraint& c : constraints_) {
+                       if (c.op & ops) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+}
+
+bool ConstraintList::matches(const std::string& expr) const
+{
+       // Support each SQL affinity type casting.
+       if (affinity == TEXT_TYPE) {
+               return literal_matches<TEXT_LITERAL>(expr);
+       } else if (affinity == INTEGER_TYPE) {
+               auto lexpr = tryTo<INTEGER_LITERAL>(expr);
+               if (lexpr) {
+                       return literal_matches<INTEGER_LITERAL>(lexpr.take());
+               }
+       } else if (affinity == BIGINT_TYPE) {
+               auto lexpr = tryTo<BIGINT_LITERAL>(expr);
+               if (lexpr) {
+                       return literal_matches<BIGINT_LITERAL>(lexpr.take());
+               }
+       } else if (affinity == UNSIGNED_BIGINT_TYPE) {
+               auto lexpr = tryTo<UNSIGNED_BIGINT_LITERAL>(expr);
+               if (lexpr) {
+                       return literal_matches<UNSIGNED_BIGINT_LITERAL>(lexpr.take());
+               }
+       }
+
+       return false;
 }
 
 template <typename T>
-bool ConstraintList::literal_matches(const T& base_expr) const {
-  bool aggregate = true;
-  for (size_t i = 0; i < constraints_.size(); ++i) {
-    auto constraint_expr = tryTo<T>(constraints_[i].expr);
-    if (!constraint_expr) {
-      // Cannot cast input constraint to column type.
-      return false;
-    }
-    if (constraints_[i].op == EQUALS) {
-      aggregate = aggregate && (base_expr == constraint_expr.take());
-    } else if (constraints_[i].op == GREATER_THAN) {
-      aggregate = aggregate && (base_expr > constraint_expr.take());
-    } else if (constraints_[i].op == LESS_THAN) {
-      aggregate = aggregate && (base_expr < constraint_expr.take());
-    } else if (constraints_[i].op == GREATER_THAN_OR_EQUALS) {
-      aggregate = aggregate && (base_expr >= constraint_expr.take());
-    } else if (constraints_[i].op == LESS_THAN_OR_EQUALS) {
-      aggregate = aggregate && (base_expr <= constraint_expr.take());
-    } else {
-      // Unsupported constraint. Should match every thing.
-      return true;
-    }
-    if (!aggregate) {
-      // Speed up comparison.
-      return false;
-    }
-  }
-  return true;
-}
-
-std::set<std::string> ConstraintList::getAll(ConstraintOperator op) const {
-  std::set<std::string> set;
-  for (size_t i = 0; i < constraints_.size(); ++i) {
-    if (constraints_[i].op == op) {
-      // TODO: this does not apply a distinct.
-      set.insert(constraints_[i].expr);
-    }
-  }
-  return set;
+bool ConstraintList::literal_matches(const T& base_expr) const
+{
+       bool aggregate = true;
+       for (size_t i = 0; i < constraints_.size(); ++i) {
+               auto constraint_expr = tryTo<T>(constraints_[i].expr);
+               if (!constraint_expr) {
+                       // Cannot cast input constraint to column type.
+                       return false;
+               }
+               if (constraints_[i].op == EQUALS) {
+                       aggregate = aggregate && (base_expr == constraint_expr.take());
+               } else if (constraints_[i].op == GREATER_THAN) {
+                       aggregate = aggregate && (base_expr > constraint_expr.take());
+               } else if (constraints_[i].op == LESS_THAN) {
+                       aggregate = aggregate && (base_expr < constraint_expr.take());
+               } else if (constraints_[i].op == GREATER_THAN_OR_EQUALS) {
+                       aggregate = aggregate && (base_expr >= constraint_expr.take());
+               } else if (constraints_[i].op == LESS_THAN_OR_EQUALS) {
+                       aggregate = aggregate && (base_expr <= constraint_expr.take());
+               } else {
+                       // Unsupported constraint. Should match every thing.
+                       return true;
+               }
+               if (!aggregate) {
+                       // Speed up comparison.
+                       return false;
+               }
+       }
+       return true;
+}
+
+std::set<std::string> ConstraintList::getAll(ConstraintOperator op) const
+{
+       std::set<std::string> set;
+       for (size_t i = 0; i < constraints_.size(); ++i) {
+               if (constraints_[i].op == op) {
+                       // TODO: this does not apply a distinct.
+                       set.insert(constraints_[i].expr);
+               }
+       }
+       return set;
 }
 
 template <typename T>
-std::set<T> ConstraintList::getAll(ConstraintOperator /* op */) const {
-  std::set<T> cs;
-  for (const auto& item : constraints_) {
-    auto exp = tryTo<T>(item.expr);
-    if (exp) {
-      cs.insert(exp.take());
-    }
-  }
-  return cs;
+std::set<T> ConstraintList::getAll(ConstraintOperator /* op */) const
+{
+       std::set<T> cs;
+       for (const auto& item : constraints_) {
+               auto exp = tryTo<T>(item.expr);
+               if (exp) {
+                       cs.insert(exp.take());
+               }
+       }
+       return cs;
 }
 
 template <>
-std::set<std::string> ConstraintList::getAll(ConstraintOperator op) const {
-  return getAll(op);
+std::set<std::string> ConstraintList::getAll(ConstraintOperator op) const
+{
+       return getAll(op);
 }
 
 /// Explicit getAll for INTEGER.
 template std::set<INTEGER_LITERAL> ConstraintList::getAll<int>(
-    ConstraintOperator) const;
+       ConstraintOperator) const;
 
 /// Explicit getAll for BIGINT.
 template std::set<long long> ConstraintList::getAll<long long>(
-    ConstraintOperator) const;
+       ConstraintOperator) const;
 
 /// Explicit getAll for UNSIGNED_BIGINT.
 template std::set<unsigned long long>
-    ConstraintList::getAll<unsigned long long>(ConstraintOperator) const;
+ConstraintList::getAll<unsigned long long>(ConstraintOperator) const;
 
-vist::json::Object ConstraintList::serialize() const {
+vist::json::Object ConstraintList::serialize() const
+{
        // format: { "affinity": "TEXT", "list": [ { "expr": "1", "op": 2 } ] }
        vist::json::Array list;
        for (const auto& constraint : constraints_) {
@@ -460,12 +482,13 @@ vist::json::Object ConstraintList::serialize() const {
        return object;
 }
 
-void ConstraintList::deserialize(vist::json::Object& obj) {
+void ConstraintList::deserialize(vist::json::Object& obj)
+{
        using namespace vist::json;
        Array list = obj.get<Array>("list");
        for (auto i = 0; i < list.size(); i++) {
                auto element = vist::json::Object::Create(list.at(i));
-               int op = element["op"]; 
+               int op = element["op"];
                Constraint constraint(static_cast<unsigned char>(op));
                constraint.expr = static_cast<std::string>(element["expr"]);
                this->constraints_.emplace_back(std::move(constraint));
@@ -475,61 +498,70 @@ void ConstraintList::deserialize(vist::json::Object& obj) {
        this->affinity = columnTypeName(name);
 }
 
-bool QueryContext::isColumnUsed(const std::string& colName) const {
-  return !colsUsed || colsUsed->find(colName) != colsUsed->end();
+bool QueryContext::isColumnUsed(const std::string& colName) const
+{
+       return !colsUsed || colsUsed->find(colName) != colsUsed->end();
 }
 
 bool QueryContext::isAnyColumnUsed(
-    std::initializer_list<std::string> colNames) const {
-  for (auto& colName : colNames) {
-    if (isColumnUsed(colName)) {
-      return true;
-    }
-  }
-  return false;
+       std::initializer_list<std::string> colNames) const
+{
+       for (auto& colName : colNames) {
+               if (isColumnUsed(colName)) {
+                       return true;
+               }
+       }
+       return false;
 }
 
-void QueryContext::useCache(bool use_cache) {
-  use_cache_ = use_cache;
+void QueryContext::useCache(bool use_cache)
+{
+       use_cache_ = use_cache;
 }
 
-bool QueryContext::useCache() const {
-  return use_cache_;
+bool QueryContext::useCache() const
+{
+       return use_cache_;
 }
 
 void QueryContext::setCache(const std::string& index,
-                            const TableRowHolder& cache) {
-  table_->cache[index] = cache->clone();
+                                                       const TableRowHolder& cache)
+{
+       table_->cache[index] = cache->clone();
 }
 
-bool QueryContext::isCached(const std::string& index) const {
-  return (table_->cache.count(index) != 0);
+bool QueryContext::isCached(const std::string& index) const
+{
+       return (table_->cache.count(index) != 0);
 }
 
-TableRowHolder QueryContext::getCache(const std::string& index) {
-  return table_->cache[index]->clone();
+TableRowHolder QueryContext::getCache(const std::string& index)
+{
+       return table_->cache[index]->clone();
 }
 
 bool QueryContext::hasConstraint(const std::string& column,
-                                 ConstraintOperator op) const {
-  if (constraints.count(column) == 0) {
-    return false;
-  }
-  return constraints.at(column).exists(op);
+                                                                ConstraintOperator op) const
+{
+       if (constraints.count(column) == 0) {
+               return false;
+       }
+       return constraints.at(column).exists(op);
 }
 
 Status QueryContext::expandConstraints(
-    const std::string& column,
-    ConstraintOperator op,
-    std::set<std::string>& output,
-    std::function<Status(const std::string& constraint,
-                         std::set<std::string>& output)> predicate) {
-  for (const auto& constraint : constraints[column].getAll(op)) {
-    auto status = predicate(constraint, output);
-    if (!status) {
-      return status;
-    }
-  }
-  return Status(0);
+       const std::string& column,
+       ConstraintOperator op,
+       std::set<std::string>& output,
+       std::function<Status(const std::string& constraint,
+                                                std::set<std::string>& output)> predicate)
+{
+       for (const auto& constraint : constraints[column].getAll(op)) {
+               auto status = predicate(constraint, output);
+               if (!status) {
+                       return status;
+               }
+       }
+       return Status(0);
 }
 } // namespace osquery
index 1c9c110bfedb8e2ddb99083434b39fc7e9c7a8ed..338b72d4fda0b9b6ef266d0576c2ecfd4a28cfb7 100644 (file)
@@ -22,135 +22,143 @@ namespace osquery {
 DECLARE_bool(disable_database);
 DECLARE_bool(log_numerics_as_numbers);
 class QueryTests : public testing::Test {
- public:
-  QueryTests() {
-    registryAndPluginInit();
-    FLAGS_disable_database = true;
-    DatabasePlugin::setAllowOpen(true);
-    DatabasePlugin::initPlugin();
-  }
+public:
+       QueryTests()
+       {
+               registryAndPluginInit();
+               FLAGS_disable_database = true;
+               DatabasePlugin::setAllowOpen(true);
+               DatabasePlugin::initPlugin();
+       }
 };
 
-TEST_F(QueryTests, test_private_members) {
-  auto query = getOsqueryScheduledQuery();
-  auto cf = Query("foobar", query);
-  EXPECT_EQ(cf.query_, query.query);
+TEST_F(QueryTests, test_private_members)
+{
+       auto query = getOsqueryScheduledQuery();
+       auto cf = Query("foobar", query);
+       EXPECT_EQ(cf.query_, query.query);
 }
 
-TEST_F(QueryTests, test_add_and_get_current_results) {
-  FLAGS_log_numerics_as_numbers = true;
-  // Test adding a "current" set of results to a scheduled query instance.
-  auto query = getOsqueryScheduledQuery();
-  auto cf = Query("foobar", query);
-  uint64_t counter = 128;
-  auto status = cf.addNewResults(getTestDBExpectedResults(), 0, counter);
-  EXPECT_TRUE(status.ok());
-  EXPECT_EQ(status.toString(), "OK");
-  EXPECT_EQ(counter, 0UL);
-
-  // Simulate results from several schedule runs, calculate differentials.
-  uint64_t expected_counter = counter + 1;
-  for (auto result : getTestDBResultStream()) {
-    // Get the results from the previous query execution (from the DB).
-    QueryDataSet previous_qd;
-    status = cf.getPreviousQueryResults(previous_qd);
-    EXPECT_TRUE(status.ok());
-    EXPECT_EQ(status.toString(), "OK");
-
-    // Add the "current" results and output the differentials.
-    DiffResults dr;
-    counter = 128;
-    auto s = cf.addNewResults(result.second, 0, counter, dr, true);
-    EXPECT_TRUE(s.ok());
-    EXPECT_EQ(counter, expected_counter++);
-
-    // Call the diffing utility directly.
-    DiffResults expected = diff(previous_qd, result.second);
-    EXPECT_EQ(dr, expected);
-
-    // After Query::addNewResults the previous results are now current.
-    QueryDataSet qds_previous;
-    cf.getPreviousQueryResults(qds_previous);
-
-    QueryDataSet qds;
-    for (auto& i : result.second) {
-      qds.insert(i);
-    }
-
-    EXPECT_EQ(qds_previous, qds);
-  }
+TEST_F(QueryTests, test_add_and_get_current_results)
+{
+       FLAGS_log_numerics_as_numbers = true;
+       // Test adding a "current" set of results to a scheduled query instance.
+       auto query = getOsqueryScheduledQuery();
+       auto cf = Query("foobar", query);
+       uint64_t counter = 128;
+       auto status = cf.addNewResults(getTestDBExpectedResults(), 0, counter);
+       EXPECT_TRUE(status.ok());
+       EXPECT_EQ(status.toString(), "OK");
+       EXPECT_EQ(counter, 0UL);
+
+       // Simulate results from several schedule runs, calculate differentials.
+       uint64_t expected_counter = counter + 1;
+       for (auto result : getTestDBResultStream()) {
+               // Get the results from the previous query execution (from the DB).
+               QueryDataSet previous_qd;
+               status = cf.getPreviousQueryResults(previous_qd);
+               EXPECT_TRUE(status.ok());
+               EXPECT_EQ(status.toString(), "OK");
+
+               // Add the "current" results and output the differentials.
+               DiffResults dr;
+               counter = 128;
+               auto s = cf.addNewResults(result.second, 0, counter, dr, true);
+               EXPECT_TRUE(s.ok());
+               EXPECT_EQ(counter, expected_counter++);
+
+               // Call the diffing utility directly.
+               DiffResults expected = diff(previous_qd, result.second);
+               EXPECT_EQ(dr, expected);
+
+               // After Query::addNewResults the previous results are now current.
+               QueryDataSet qds_previous;
+               cf.getPreviousQueryResults(qds_previous);
+
+               QueryDataSet qds;
+               for (auto& i : result.second) {
+                       qds.insert(i);
+               }
+
+               EXPECT_EQ(qds_previous, qds);
+       }
 }
 
-TEST_F(QueryTests, test_get_query_results) {
-  // Grab an expected set of query data and add it as the previous result.
-  auto encoded_qd = getSerializedQueryDataJSON();
-  auto query = getOsqueryScheduledQuery();
-  auto status = setDatabaseValue(kQueries, "foobar", encoded_qd.first);
-  EXPECT_TRUE(status.ok());
-
-  // Use the Query retrieval API to check the now "previous" result.
-  QueryDataSet previous_qd;
-  auto cf = Query("foobar", query);
-  status = cf.getPreviousQueryResults(previous_qd);
-  EXPECT_TRUE(status.ok());
+TEST_F(QueryTests, test_get_query_results)
+{
+       // Grab an expected set of query data and add it as the previous result.
+       auto encoded_qd = getSerializedQueryDataJSON();
+       auto query = getOsqueryScheduledQuery();
+       auto status = setDatabaseValue(kQueries, "foobar", encoded_qd.first);
+       EXPECT_TRUE(status.ok());
+
+       // Use the Query retrieval API to check the now "previous" result.
+       QueryDataSet previous_qd;
+       auto cf = Query("foobar", query);
+       status = cf.getPreviousQueryResults(previous_qd);
+       EXPECT_TRUE(status.ok());
 }
 
-TEST_F(QueryTests, test_query_name_not_found_in_db) {
-  // Try to retrieve results from a query that has not executed.
-  QueryDataSet previous_qd;
-  auto query = getOsqueryScheduledQuery();
-  auto cf = Query("not_a_real_query", query);
-  auto status = cf.getPreviousQueryResults(previous_qd);
-  EXPECT_FALSE(status.ok());
-  EXPECT_TRUE(previous_qd.empty());
+TEST_F(QueryTests, test_query_name_not_found_in_db)
+{
+       // Try to retrieve results from a query that has not executed.
+       QueryDataSet previous_qd;
+       auto query = getOsqueryScheduledQuery();
+       auto cf = Query("not_a_real_query", query);
+       auto status = cf.getPreviousQueryResults(previous_qd);
+       EXPECT_FALSE(status.ok());
+       EXPECT_TRUE(previous_qd.empty());
 }
 
-TEST_F(QueryTests, test_is_query_name_in_database) {
-  auto query = getOsqueryScheduledQuery();
-  auto cf = Query("foobar", query);
-  auto encoded_qd = getSerializedQueryDataJSON();
-  auto status = setDatabaseValue(kQueries, "foobar", encoded_qd.first);
-  EXPECT_TRUE(status.ok());
-  // Now test that the query name exists.
-  EXPECT_TRUE(cf.isQueryNameInDatabase());
+TEST_F(QueryTests, test_is_query_name_in_database)
+{
+       auto query = getOsqueryScheduledQuery();
+       auto cf = Query("foobar", query);
+       auto encoded_qd = getSerializedQueryDataJSON();
+       auto status = setDatabaseValue(kQueries, "foobar", encoded_qd.first);
+       EXPECT_TRUE(status.ok());
+       // Now test that the query name exists.
+       EXPECT_TRUE(cf.isQueryNameInDatabase());
 }
 
-TEST_F(QueryTests, test_query_name_updated) {
-  // Try to retrieve results from a query that has not executed.
-  QueryDataSet previous_qd;
-  auto query = getOsqueryScheduledQuery();
-  auto cf = Query("will_update_query", query);
-  EXPECT_TRUE(cf.isNewQuery());
-  EXPECT_TRUE(cf.isNewQuery());
-
-  DiffResults dr;
-  uint64_t counter = 128;
-  auto results = getTestDBExpectedResults();
-  cf.addNewResults(results, 0, counter, dr);
-  EXPECT_FALSE(cf.isNewQuery());
-  EXPECT_EQ(counter, 0UL);
-
-  query.query += " LIMIT 1";
-  counter = 128;
-  auto cf2 = Query("will_update_query", query);
-  EXPECT_TRUE(cf2.isQueryNameInDatabase());
-  EXPECT_TRUE(cf2.isNewQuery());
-  cf2.addNewResults(results, 0, counter, dr);
-  EXPECT_FALSE(cf2.isNewQuery());
-  EXPECT_EQ(counter, 0UL);
+TEST_F(QueryTests, test_query_name_updated)
+{
+       // Try to retrieve results from a query that has not executed.
+       QueryDataSet previous_qd;
+       auto query = getOsqueryScheduledQuery();
+       auto cf = Query("will_update_query", query);
+       EXPECT_TRUE(cf.isNewQuery());
+       EXPECT_TRUE(cf.isNewQuery());
+
+       DiffResults dr;
+       uint64_t counter = 128;
+       auto results = getTestDBExpectedResults();
+       cf.addNewResults(results, 0, counter, dr);
+       EXPECT_FALSE(cf.isNewQuery());
+       EXPECT_EQ(counter, 0UL);
+
+       query.query += " LIMIT 1";
+       counter = 128;
+       auto cf2 = Query("will_update_query", query);
+       EXPECT_TRUE(cf2.isQueryNameInDatabase());
+       EXPECT_TRUE(cf2.isNewQuery());
+       cf2.addNewResults(results, 0, counter, dr);
+       EXPECT_FALSE(cf2.isNewQuery());
+       EXPECT_EQ(counter, 0UL);
 }
 
-TEST_F(QueryTests, test_get_stored_query_names) {
-  auto query = getOsqueryScheduledQuery();
-  auto cf = Query("foobar", query);
-  auto encoded_qd = getSerializedQueryDataJSON();
-  auto status = setDatabaseValue(kQueries, "foobar", encoded_qd.first);
-  EXPECT_TRUE(status.ok());
-
-  // Stored query names is a factory method included alongside every query.
-  // It will include the set of query names with existing "previous" results.
-  auto names = cf.getStoredQueryNames();
-  auto in_vector = std::find(names.begin(), names.end(), "foobar");
-  EXPECT_NE(in_vector, names.end());
+TEST_F(QueryTests, test_get_stored_query_names)
+{
+       auto query = getOsqueryScheduledQuery();
+       auto cf = Query("foobar", query);
+       auto encoded_qd = getSerializedQueryDataJSON();
+       auto status = setDatabaseValue(kQueries, "foobar", encoded_qd.first);
+       EXPECT_TRUE(status.ok());
+
+       // Stored query names is a factory method included alongside every query.
+       // It will include the set of query names with existing "previous" results.
+       auto names = cf.getStoredQueryNames();
+       auto in_vector = std::find(names.begin(), names.end(), "foobar");
+       EXPECT_NE(in_vector, names.end());
 }
 }
index 703c2b6badcb5ccee944bf30f8a73692e51f06f4..b945b0fbca4031a297d19a6f663df93baa95f04e 100644 (file)
@@ -19,176 +19,185 @@ DECLARE_bool(disable_database);
 
 class TablesTests : public testing::Test {
 protected:
- void SetUp() {
-   Initializer::platformSetup();
-   registryAndPluginInit();
-   FLAGS_disable_database = true;
-   DatabasePlugin::setAllowOpen(true);
-   DatabasePlugin::initPlugin();
- }
+       void SetUp()
+       {
+               Initializer::platformSetup();
+               registryAndPluginInit();
+               FLAGS_disable_database = true;
+               DatabasePlugin::setAllowOpen(true);
+               DatabasePlugin::initPlugin();
+       }
 };
 
-TEST_F(TablesTests, test_constraint) {
-  auto constraint = Constraint(EQUALS);
-  constraint.expr = "none";
+TEST_F(TablesTests, test_constraint)
+{
+       auto constraint = Constraint(EQUALS);
+       constraint.expr = "none";
 
-  EXPECT_EQ(constraint.op, EQUALS);
-  EXPECT_EQ(constraint.expr, "none");
+       EXPECT_EQ(constraint.op, EQUALS);
+       EXPECT_EQ(constraint.expr, "none");
 }
 
-TEST_F(TablesTests, test_constraint_list) {
-  struct ConstraintList cl;
+TEST_F(TablesTests, test_constraint_list)
+{
+       struct ConstraintList cl;
 
-  auto constraint = Constraint(EQUALS);
-  constraint.expr = "some";
+       auto constraint = Constraint(EQUALS);
+       constraint.expr = "some";
 
-  // The constraint list is a simple struct.
-  cl.add(constraint);
-  EXPECT_EQ(cl.constraints_.size(), 1U);
+       // The constraint list is a simple struct.
+       cl.add(constraint);
+       EXPECT_EQ(cl.constraints_.size(), 1U);
 
-  constraint = Constraint(EQUALS);
-  constraint.expr = "some_other";
-  cl.add(constraint);
+       constraint = Constraint(EQUALS);
+       constraint.expr = "some_other";
+       cl.add(constraint);
 
-  constraint = Constraint(GREATER_THAN);
-  constraint.expr = "more_than";
-  cl.add(constraint);
-  EXPECT_EQ(cl.constraints_.size(), 3U);
+       constraint = Constraint(GREATER_THAN);
+       constraint.expr = "more_than";
+       cl.add(constraint);
+       EXPECT_EQ(cl.constraints_.size(), 3U);
 
-  auto all_equals = cl.getAll(EQUALS);
-  EXPECT_EQ(all_equals.size(), 2U);
+       auto all_equals = cl.getAll(EQUALS);
+       EXPECT_EQ(all_equals.size(), 2U);
 }
 
-TEST_F(TablesTests, test_constraint_matching) {
-  struct ConstraintList cl;
-  // An empty constraint list has expectations.
-  EXPECT_FALSE(cl.exists());
-  EXPECT_FALSE(cl.exists(GREATER_THAN));
-  EXPECT_TRUE(cl.notExistsOrMatches("some"));
-
-  auto constraint = Constraint(EQUALS);
-  constraint.expr = "some";
-  cl.add(constraint);
-
-  // Test existence checks based on flags.
-  EXPECT_TRUE(cl.exists());
-  EXPECT_TRUE(cl.exists(EQUALS));
-  EXPECT_TRUE(cl.exists(EQUALS | LESS_THAN));
-  EXPECT_FALSE(cl.exists(LESS_THAN));
-
-  EXPECT_TRUE(cl.notExistsOrMatches("some"));
-  EXPECT_TRUE(cl.matches("some"));
-  EXPECT_FALSE(cl.notExistsOrMatches("not_some"));
-
-  struct ConstraintList cl2;
-  cl2.affinity = INTEGER_TYPE;
-  constraint = Constraint(LESS_THAN);
-  constraint.expr = "1000";
-  cl2.add(constraint);
-  constraint = Constraint(GREATER_THAN);
-  constraint.expr = "1";
-  cl2.add(constraint);
-
-  // Test both SQL-provided string types.
-  EXPECT_TRUE(cl2.matches("10"));
-  // ...and the type literal.
-  EXPECT_TRUE(cl2.matches(10));
-
-  // Test operator lower bounds.
-  EXPECT_FALSE(cl2.matches(0));
-  EXPECT_FALSE(cl2.matches(1));
-
-  // Test operator upper bounds.
-  EXPECT_FALSE(cl2.matches(1000));
-  EXPECT_FALSE(cl2.matches(1001));
-
-  // Now test inclusive bounds.
-  struct ConstraintList cl3;
-  constraint = Constraint(LESS_THAN_OR_EQUALS);
-  constraint.expr = "1000";
-  cl3.add(constraint);
-  constraint = Constraint(GREATER_THAN_OR_EQUALS);
-  constraint.expr = "1";
-  cl3.add(constraint);
-
-  EXPECT_FALSE(cl3.matches(1001));
-  EXPECT_TRUE(cl3.matches(1000));
-
-  EXPECT_FALSE(cl3.matches(0));
-  EXPECT_TRUE(cl3.matches(1));
+TEST_F(TablesTests, test_constraint_matching)
+{
+       struct ConstraintList cl;
+       // An empty constraint list has expectations.
+       EXPECT_FALSE(cl.exists());
+       EXPECT_FALSE(cl.exists(GREATER_THAN));
+       EXPECT_TRUE(cl.notExistsOrMatches("some"));
+
+       auto constraint = Constraint(EQUALS);
+       constraint.expr = "some";
+       cl.add(constraint);
+
+       // Test existence checks based on flags.
+       EXPECT_TRUE(cl.exists());
+       EXPECT_TRUE(cl.exists(EQUALS));
+       EXPECT_TRUE(cl.exists(EQUALS | LESS_THAN));
+       EXPECT_FALSE(cl.exists(LESS_THAN));
+
+       EXPECT_TRUE(cl.notExistsOrMatches("some"));
+       EXPECT_TRUE(cl.matches("some"));
+       EXPECT_FALSE(cl.notExistsOrMatches("not_some"));
+
+       struct ConstraintList cl2;
+       cl2.affinity = INTEGER_TYPE;
+       constraint = Constraint(LESS_THAN);
+       constraint.expr = "1000";
+       cl2.add(constraint);
+       constraint = Constraint(GREATER_THAN);
+       constraint.expr = "1";
+       cl2.add(constraint);
+
+       // Test both SQL-provided string types.
+       EXPECT_TRUE(cl2.matches("10"));
+       // ...and the type literal.
+       EXPECT_TRUE(cl2.matches(10));
+
+       // Test operator lower bounds.
+       EXPECT_FALSE(cl2.matches(0));
+       EXPECT_FALSE(cl2.matches(1));
+
+       // Test operator upper bounds.
+       EXPECT_FALSE(cl2.matches(1000));
+       EXPECT_FALSE(cl2.matches(1001));
+
+       // Now test inclusive bounds.
+       struct ConstraintList cl3;
+       constraint = Constraint(LESS_THAN_OR_EQUALS);
+       constraint.expr = "1000";
+       cl3.add(constraint);
+       constraint = Constraint(GREATER_THAN_OR_EQUALS);
+       constraint.expr = "1";
+       cl3.add(constraint);
+
+       EXPECT_FALSE(cl3.matches(1001));
+       EXPECT_TRUE(cl3.matches(1000));
+
+       EXPECT_FALSE(cl3.matches(0));
+       EXPECT_TRUE(cl3.matches(1));
 }
 
-TEST_F(TablesTests, test_constraint_map) {
-  ConstraintMap cm;
+TEST_F(TablesTests, test_constraint_map)
+{
+       ConstraintMap cm;
 
-  cm["path"].add(Constraint(EQUALS, "some"));
+       cm["path"].add(Constraint(EQUALS, "some"));
 
-  // If a constraint list exists for a map key, normal constraints apply.
-  EXPECT_TRUE(cm["path"].matches("some"));
-  EXPECT_FALSE(cm["path"].matches("not_some"));
+       // If a constraint list exists for a map key, normal constraints apply.
+       EXPECT_TRUE(cm["path"].matches("some"));
+       EXPECT_FALSE(cm["path"].matches("not_some"));
 
-  // If a constraint list does not exist, then all checks will match.
-  // If there is no predicate clause then all results will match.
-  EXPECT_TRUE(cm["not_path"].matches("some"));
-  EXPECT_TRUE(cm["not_path"].notExistsOrMatches("some"));
-  EXPECT_FALSE(cm["not_path"].exists());
-  EXPECT_FALSE(cm["not_path"].existsAndMatches("some"));
+       // If a constraint list does not exist, then all checks will match.
+       // If there is no predicate clause then all results will match.
+       EXPECT_TRUE(cm["not_path"].matches("some"));
+       EXPECT_TRUE(cm["not_path"].notExistsOrMatches("some"));
+       EXPECT_FALSE(cm["not_path"].exists());
+       EXPECT_FALSE(cm["not_path"].existsAndMatches("some"));
 
-  // And of the column has constraints:
-  EXPECT_TRUE(cm["path"].notExistsOrMatches("some"));
-  EXPECT_FALSE(cm["path"].notExistsOrMatches("not_some"));
-  EXPECT_TRUE(cm["path"].exists());
-  EXPECT_TRUE(cm["path"].existsAndMatches("some"));
+       // And of the column has constraints:
+       EXPECT_TRUE(cm["path"].notExistsOrMatches("some"));
+       EXPECT_FALSE(cm["path"].notExistsOrMatches("not_some"));
+       EXPECT_TRUE(cm["path"].exists());
+       EXPECT_TRUE(cm["path"].existsAndMatches("some"));
 }
 
-TEST_F(TablesTests, test_constraint_map_cast) {
-  ConstraintMap cm;
+TEST_F(TablesTests, test_constraint_map_cast)
+{
+       ConstraintMap cm;
 
-  cm["num"].affinity = INTEGER_TYPE;
-  cm["num"].add(Constraint(EQUALS, "hello"));
+       cm["num"].affinity = INTEGER_TYPE;
+       cm["num"].add(Constraint(EQUALS, "hello"));
 
-  EXPECT_FALSE(cm["num"].existsAndMatches("hello"));
+       EXPECT_FALSE(cm["num"].existsAndMatches("hello"));
 }
 
 class TestTablePlugin : public TablePlugin {
- public:
-  void testSetCache(size_t step, size_t interval) {
-    TableRows r;
-    QueryContext ctx;
-    ctx.useCache(true);
-    setCache(step, interval, ctx, r);
-  }
-
-  bool testIsCached(size_t interval) {
-    QueryContext ctx;
-    ctx.useCache(true);
-    return isCached(interval, ctx);
-  }
+public:
+       void testSetCache(size_t step, size_t interval)
+       {
+               TableRows r;
+               QueryContext ctx;
+               ctx.useCache(true);
+               setCache(step, interval, ctx, r);
+       }
+
+       bool testIsCached(size_t interval)
+       {
+               QueryContext ctx;
+               ctx.useCache(true);
+               return isCached(interval, ctx);
+       }
 };
 
-TEST_F(TablesTests, test_caching) {
-  TestTablePlugin test;
-  // By default the interval and step is 0, so a step of 5 will not be cached.
-  EXPECT_FALSE(test.testIsCached(5));
-
-  TablePlugin::kCacheInterval = 5;
-  TablePlugin::kCacheStep = 1;
-  EXPECT_FALSE(test.testIsCached(5));
-  // Set the current time to 1, and the interval at 5.
-  test.testSetCache(TablePlugin::kCacheStep, TablePlugin::kCacheInterval);
-  // Time at 1 is cached for an interval of 5, so at time 5 the cache is fresh.
-  EXPECT_TRUE(test.testIsCached(5));
-  // 6 is the end of the cache, it is not fresh.
-  EXPECT_FALSE(test.testIsCached(6));
-  // 7 is past the cache, it is not fresh.
-  EXPECT_FALSE(test.testIsCached(7));
-
-  // Set the time at now to 2.
-  TablePlugin::kCacheStep = 2;
-  test.testSetCache(TablePlugin::kCacheStep, TablePlugin::kCacheInterval);
-  EXPECT_TRUE(test.testIsCached(5));
-  // Now 6 is within the freshness of 2 + 5.
-  EXPECT_TRUE(test.testIsCached(6));
-  EXPECT_FALSE(test.testIsCached(7));
+TEST_F(TablesTests, test_caching)
+{
+       TestTablePlugin test;
+       // By default the interval and step is 0, so a step of 5 will not be cached.
+       EXPECT_FALSE(test.testIsCached(5));
+
+       TablePlugin::kCacheInterval = 5;
+       TablePlugin::kCacheStep = 1;
+       EXPECT_FALSE(test.testIsCached(5));
+       // Set the current time to 1, and the interval at 5.
+       test.testSetCache(TablePlugin::kCacheStep, TablePlugin::kCacheInterval);
+       // Time at 1 is cached for an interval of 5, so at time 5 the cache is fresh.
+       EXPECT_TRUE(test.testIsCached(5));
+       // 6 is the end of the cache, it is not fresh.
+       EXPECT_FALSE(test.testIsCached(6));
+       // 7 is past the cache, it is not fresh.
+       EXPECT_FALSE(test.testIsCached(7));
+
+       // Set the time at now to 2.
+       TablePlugin::kCacheStep = 2;
+       test.testSetCache(TablePlugin::kCacheStep, TablePlugin::kCacheInterval);
+       EXPECT_TRUE(test.testIsCached(5));
+       // Now 6 is within the freshness of 2 + 5.
+       EXPECT_TRUE(test.testIsCached(6));
+       EXPECT_FALSE(test.testIsCached(7));
 }
 }
diff --git a/src/osquery/include/osquery/plugins/logger.h b/src/osquery/include/osquery/plugins/logger.h
deleted file mode 120000 (symlink)
index f298b6f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../core/plugins/logger.h
\ No newline at end of file
index 05b615819f6248bd81232b1f720adc88009f1148..4dfa95ceb98c473a6e8b6b90302fbb5c5c1951cd 100644 (file)
@@ -32,185 +32,187 @@ class Status;
  * results in potentially-differential form for a logger.
  */
 struct QueryLogItem {
- public:
-  /// Differential results from the query.
-  DiffResults results;
+public:
+       /// Differential results from the query.
+       DiffResults results;
 
-  /// Optional snapshot results, no differential applied.
-  QueryDataTyped snapshot_results;
+       /// Optional snapshot results, no differential applied.
+       QueryDataTyped snapshot_results;
 
-  /// The name of the scheduled query.
-  std::string name;
+       /// The name of the scheduled query.
+       std::string name;
 
-  /// The identifier (hostname, or uuid) of the host.
-  std::string identifier;
+       /// The identifier (hostname, or uuid) of the host.
+       std::string identifier;
 
-  /// The time that the query was executed, seconds as UNIX time.
-  size_t time{0};
+       /// The time that the query was executed, seconds as UNIX time.
+       size_t time{0};
 
-  /// The epoch at the time the query was executed
-  uint64_t epoch{};
+       /// The epoch at the time the query was executed
+       uint64_t epoch{};
 
-  /// Query execution counter for current epoch
-  uint64_t counter{0};
+       /// Query execution counter for current epoch
+       uint64_t counter{0};
 
-  /// The time that the query was executed, an ASCII string.
-  std::string calendar_time;
+       /// The time that the query was executed, an ASCII string.
+       std::string calendar_time;
 
-  /// A set of additional fields to emit with the log line.
-  std::map<std::string, std::string> decorations;
+       /// A set of additional fields to emit with the log line.
+       std::map<std::string, std::string> decorations;
 
-  /// equals operator
-  bool operator==(const QueryLogItem& comp) const {
-    return (comp.results == results) && (comp.name == name);
-  }
+       /// equals operator
+       bool operator==(const QueryLogItem& comp) const
+       {
+               return (comp.results == results) && (comp.name == name);
+       }
 
-  /// not equals operator
-  bool operator!=(const QueryLogItem& comp) const {
-    return !(*this == comp);
-  }
+       /// not equals operator
+       bool operator!=(const QueryLogItem& comp) const
+       {
+               return !(*this == comp);
+       }
 };
 
 /**
  * @brief Interact with the historical on-disk storage for a given query.
  */
 class Query {
- public:
-  /**
-   * @brief Constructor which sets up necessary parameters of a Query object.
-   *
-   * Given a query, this constructor calculates the value of columnFamily_,
-   * which can be accessed via the getColumnFamilyName getter method.
-   *
-   * @param name The query name.
-   * @param q a SheduledQuery struct.
-   */
-  explicit Query(std::string name, const ScheduledQuery& q)
-      : query_(q.query), name_(std::move(name)) {}
-
-  /**
-   * @brief Serialize the data in RocksDB into a useful data structure
-   *
-   * This method retrieves the data from RocksDB and returns the data in a
-   * std::multiset, in-order to apply binary search in diff function.
-   *
-   * @param results the output QueryDataSet struct.
-   *
-   * @return the success or failure of the operation.
-   */
-  Status getPreviousQueryResults(QueryDataSet& results) const;
-
-  /**
-   * @brief Get the epoch associated with the previous query results.
-   *
-   * This method retrieves the epoch associated with the results data that was
-   * was stored in rocksdb.
-   *
-   * @return the epoch associated with the previous query results.
-   */
-  uint64_t getPreviousEpoch() const;
-
-  /**
-   * @brief Get the query invocation counter.
-   *
-   * This method returns query invocation counter. If the query is a new query,
-   * 0 is returned. Otherwise the counter associated with the query is retrieved
-   * from database and incremented by 1.
-   *
-   * @param new_query Whether or not the query is new.
-   *
-   * @return the query invocation counter.
-   */
-  uint64_t getQueryCounter(bool new_query) const;
-
-  /**
-   * @brief Check if a given scheduled query exists in the database.
-   *
-   * @return true if the scheduled query already exists in the database.
-   */
-  bool isQueryNameInDatabase() const;
-
-  /**
-   * @brief Check if a query (not query name) is 'new' or altered.
-   *
-   * @return true if the scheduled query has not been altered.
-   */
-  bool isNewQuery() const;
-
-  /**
-   * @brief Add a new set of results to the persistent storage.
-   *
-   * Given the results of the execution of a scheduled query, add the results
-   * to the database using addNewResults.
-   *
-   * @param qd the QueryDataTyped object, which has the results of the query.
-   * @param epoch the epoch associated with QueryData
-   * @param counter [output] the output that holds the query execution counter.
-   *
-   * @return the success or failure of the operation.
-   */
-  Status addNewResults(QueryDataTyped qd,
-                       uint64_t epoch,
-                       uint64_t& counter) const;
-
-  /**
-   * @brief Add a new set of results to the persistent storage and get back
-   * the differential results.
-   *
-   * Given the results of an execution of a scheduled query, add the results
-   * to the database using addNewResults and get back a data structure
-   * indicating what rows in the query's results have changed.
-   *
-   * @param qd the QueryDataTyped object containing query results to store.
-   * @param epoch the epoch associated with QueryData
-   * @param counter the output that holds the query execution counter.
-   * @param dr an output to a DiffResults object populated based on last run.
-   * @param calculate_diff default true to populate dr.
-   *
-   * @return the success or failure of the operation.
-   */
-  Status addNewResults(QueryDataTyped qd,
-                       uint64_t epoch,
-                       uint64_t& counter,
-                       DiffResults& dr,
-                       bool calculate_diff = true) const;
-
-  /**
-   * @brief The most recent result set for a scheduled query.
-   *
-   * @param qd the output QueryData object.
-   *
-   * @return the success or failure of the operation.
-   */
-  Status getCurrentResults(QueryData& qd);
-
- public:
-  /**
-   * @brief Get the names of all historical queries.
-   *
-   * If you'd like to perform some database maintenance, getStoredQueryNames()
-   * allows you to get a vector of the names of all queries which are
-   * currently stored in RocksDB
-   *
-   * @return a vector containing the string names of all scheduled queries.
-   */
-  static std::vector<std::string> getStoredQueryNames();
-
- private:
-  /// The scheduled query's query string.
-  std::string query_;
-
-  /// The scheduled query name.
-  std::string name_;
-
- private:
-  FRIEND_TEST(QueryTests, test_private_members);
-  FRIEND_TEST(QueryTests, test_add_and_get_current_results);
-  FRIEND_TEST(QueryTests, test_is_query_name_in_database);
-  FRIEND_TEST(QueryTests, test_get_stored_query_names);
-  FRIEND_TEST(QueryTests, test_get_executions);
-  FRIEND_TEST(QueryTests, test_get_query_results);
-  FRIEND_TEST(QueryTests, test_query_name_not_found_in_db);
+public:
+       /**
+        * @brief Constructor which sets up necessary parameters of a Query object.
+        *
+        * Given a query, this constructor calculates the value of columnFamily_,
+        * which can be accessed via the getColumnFamilyName getter method.
+        *
+        * @param name The query name.
+        * @param q a SheduledQuery struct.
+        */
+       explicit Query(std::string name, const ScheduledQuery& q)
+               : query_(q.query), name_(std::move(name)) {}
+
+       /**
+        * @brief Serialize the data in RocksDB into a useful data structure
+        *
+        * This method retrieves the data from RocksDB and returns the data in a
+        * std::multiset, in-order to apply binary search in diff function.
+        *
+        * @param results the output QueryDataSet struct.
+        *
+        * @return the success or failure of the operation.
+        */
+       Status getPreviousQueryResults(QueryDataSet& results) const;
+
+       /**
+        * @brief Get the epoch associated with the previous query results.
+        *
+        * This method retrieves the epoch associated with the results data that was
+        * was stored in rocksdb.
+        *
+        * @return the epoch associated with the previous query results.
+        */
+       uint64_t getPreviousEpoch() const;
+
+       /**
+        * @brief Get the query invocation counter.
+        *
+        * This method returns query invocation counter. If the query is a new query,
+        * 0 is returned. Otherwise the counter associated with the query is retrieved
+        * from database and incremented by 1.
+        *
+        * @param new_query Whether or not the query is new.
+        *
+        * @return the query invocation counter.
+        */
+       uint64_t getQueryCounter(bool new_query) const;
+
+       /**
+        * @brief Check if a given scheduled query exists in the database.
+        *
+        * @return true if the scheduled query already exists in the database.
+        */
+       bool isQueryNameInDatabase() const;
+
+       /**
+        * @brief Check if a query (not query name) is 'new' or altered.
+        *
+        * @return true if the scheduled query has not been altered.
+        */
+       bool isNewQuery() const;
+
+       /**
+        * @brief Add a new set of results to the persistent storage.
+        *
+        * Given the results of the execution of a scheduled query, add the results
+        * to the database using addNewResults.
+        *
+        * @param qd the QueryDataTyped object, which has the results of the query.
+        * @param epoch the epoch associated with QueryData
+        * @param counter [output] the output that holds the query execution counter.
+        *
+        * @return the success or failure of the operation.
+        */
+       Status addNewResults(QueryDataTyped qd,
+                                                uint64_t epoch,
+                                                uint64_t& counter) const;
+
+       /**
+        * @brief Add a new set of results to the persistent storage and get back
+        * the differential results.
+        *
+        * Given the results of an execution of a scheduled query, add the results
+        * to the database using addNewResults and get back a data structure
+        * indicating what rows in the query's results have changed.
+        *
+        * @param qd the QueryDataTyped object containing query results to store.
+        * @param epoch the epoch associated with QueryData
+        * @param counter the output that holds the query execution counter.
+        * @param dr an output to a DiffResults object populated based on last run.
+        * @param calculate_diff default true to populate dr.
+        *
+        * @return the success or failure of the operation.
+        */
+       Status addNewResults(QueryDataTyped qd,
+                                                uint64_t epoch,
+                                                uint64_t& counter,
+                                                DiffResults& dr,
+                                                bool calculate_diff = true) const;
+
+       /**
+        * @brief The most recent result set for a scheduled query.
+        *
+        * @param qd the output QueryData object.
+        *
+        * @return the success or failure of the operation.
+        */
+       Status getCurrentResults(QueryData& qd);
+
+public:
+       /**
+        * @brief Get the names of all historical queries.
+        *
+        * If you'd like to perform some database maintenance, getStoredQueryNames()
+        * allows you to get a vector of the names of all queries which are
+        * currently stored in RocksDB
+        *
+        * @return a vector containing the string names of all scheduled queries.
+        */
+       static std::vector<std::string> getStoredQueryNames();
+
+private:
+       /// The scheduled query's query string.
+       std::string query_;
+
+       /// The scheduled query name.
+       std::string name_;
+
+private:
+       FRIEND_TEST(QueryTests, test_private_members);
+       FRIEND_TEST(QueryTests, test_add_and_get_current_results);
+       FRIEND_TEST(QueryTests, test_is_query_name_in_database);
+       FRIEND_TEST(QueryTests, test_get_stored_query_names);
+       FRIEND_TEST(QueryTests, test_get_executions);
+       FRIEND_TEST(QueryTests, test_get_query_results);
+       FRIEND_TEST(QueryTests, test_query_name_not_found_in_db);
 };
 
 } // namespace osquery
index c56470079c1f226951244d6d05577970ad82bfc4..d444e32e6b899da5c46f888d69f36e45c534c861 100644 (file)
 namespace osquery {
 
 class RegistryFactory : private boost::noncopyable {
- public:
-  /// Singleton accessor.
-  static RegistryFactory& get();
-
-  /**
-   * @brief Call a registry item.
-   *
-   * Registry 'calling' is the primary interaction osquery has with the Plugin
-   * APIs, which register items. Each item is an instance of a specialized
-   * Plugin, whose life/scope is maintained by the specific registry identified
-   * by a unique name.
-   *
-   * The specialized plugin type will expose a `call` method that parses a
-   * PluginRequest then perform some action and return a PluginResponse.
-   * Each registry provides a `call` method that performs the registry item
-   * (Plugin instance) look up, and passes and retrieves the request and
-   * response.
-   *
-   * @param registry_name The unique registry name containing item_name,
-   * @param item_name The name of the plugin used to REGISTER.
-   * @param request The PluginRequest object handled by the Plugin item.
-   * @param response The output.
-   * @return A status from the Plugin.
-   */
-  static Status call(const std::string& registry_name,
-                     const std::string& item_name,
-                     const PluginRequest& request,
-                     PluginResponse& response);
-
-  /// A helper call that does not return a response (only status).
-  static Status call(const std::string& registry_name,
-                     const std::string& item_name,
-                     const PluginRequest& request);
-
-  /// A helper call that uses the active plugin (if the registry has one).
-  static Status call(const std::string& registry_name,
-                     const PluginRequest& request,
-                     PluginResponse& response);
-
-  /// A helper call that uses the active plugin (if the registry has one).
-  static Status call(const std::string& registry_name,
-                     const PluginRequest& request);
-
-  /// Run `setUp` on every registry that is not marked 'lazy'.
-  static void setUp();
-
- public:
-  /// Direct access to a registry instance.
-  RegistryInterfaceRef registry(const std::string& registry_name) const;
-
-  void add(const std::string& name, RegistryInterfaceRef reg);
-
-  /// Direct access to all registries.
-  std::map<std::string, RegistryInterfaceRef> all() const;
-
-  /// Direct access to all plugin instances for a given registry name.
-  std::map<std::string, PluginRef> plugins(
-      const std::string& registry_name) const;
-
-  /// Direct access to a plugin instance.
-  PluginRef plugin(const std::string& registry_name,
-                   const std::string& item_name) const;
-
-  /// Adds an alias for an internal registry item. This registry will only
-  /// broadcast the alias name.
-  Status addAlias(const std::string& registry_name,
-                  const std::string& item_name,
-                  const std::string& alias);
-
-  /// Returns the item_name or the item alias if an alias exists.
-  std::string getAlias(const std::string& registry_name,
-                       const std::string& alias) const;
-
-  /// Set a registry's active plugin.
-  Status setActive(const std::string& registry_name,
-                   const std::string& item_name);
-
-  /// Get a registry's active plugin.
-  std::string getActive(const std::string& registry_nane) const;
-
-  bool exists(const std::string& registry_name) const {
-    return (registries_.count(registry_name) > 0);
-  }
-
-  /// Check if a registry item exists, optionally search only local registries.
-  bool exists(const std::string& registry_name,
-              const std::string& item_name,
-              bool local = false) const;
-
-  /// Get a list of the registry names.
-  std::vector<std::string> names() const;
-
-  /// Get a list of the registry item names for a given registry.
-  std::vector<std::string> names(const std::string& registry_name) const;
-
-  /// Return the number of registries.
-  size_t count() const {
-    return registries_.size();
-  }
-
-  /// Return the number of registry items for a given registry name.
-  size_t count(const std::string& registry_name) const;
-
-  /// Enable/disable duplicate registry item support using aliasing.
-  void allowDuplicates(bool allow) {
-    allow_duplicates_ = allow;
-  }
-
-  /// Check if duplicate registry items using registry aliasing are allowed.
-  bool allowDuplicates() {
-    return allow_duplicates_;
-  }
-
- private:
-  /// Check if the registries are locked.
-  bool locked() {
-    return locked_;
-  }
-
-  /// Set the registry locked status.
-  void locked(bool locked) {
-    locked_ = locked;
-  }
-
- protected:
-  RegistryFactory() = default;
-  virtual ~RegistryFactory() = default;
-
- private:
-  /// Track duplicate registry item support, used for testing.
-  bool allow_duplicates_{false};
-
-  /// Track registry "locking", while locked a registry cannot add/create.
-  bool locked_{false};
-
-  /// The primary storage for constructed registries.
-  std::map<std::string, RegistryInterfaceRef> registries_;
-
-  /// Protector for broadcast lookups and external registry mutations.
-  mutable Mutex mutex_;
-
- private:
-  friend class RegistryInterface;
+public:
+       /// Singleton accessor.
+       static RegistryFactory& get();
+
+       /**
+        * @brief Call a registry item.
+        *
+        * Registry 'calling' is the primary interaction osquery has with the Plugin
+        * APIs, which register items. Each item is an instance of a specialized
+        * Plugin, whose life/scope is maintained by the specific registry identified
+        * by a unique name.
+        *
+        * The specialized plugin type will expose a `call` method that parses a
+        * PluginRequest then perform some action and return a PluginResponse.
+        * Each registry provides a `call` method that performs the registry item
+        * (Plugin instance) look up, and passes and retrieves the request and
+        * response.
+        *
+        * @param registry_name The unique registry name containing item_name,
+        * @param item_name The name of the plugin used to REGISTER.
+        * @param request The PluginRequest object handled by the Plugin item.
+        * @param response The output.
+        * @return A status from the Plugin.
+        */
+       static Status call(const std::string& registry_name,
+                                          const std::string& item_name,
+                                          const PluginRequest& request,
+                                          PluginResponse& response);
+
+       /// A helper call that does not return a response (only status).
+       static Status call(const std::string& registry_name,
+                                          const std::string& item_name,
+                                          const PluginRequest& request);
+
+       /// A helper call that uses the active plugin (if the registry has one).
+       static Status call(const std::string& registry_name,
+                                          const PluginRequest& request,
+                                          PluginResponse& response);
+
+       /// A helper call that uses the active plugin (if the registry has one).
+       static Status call(const std::string& registry_name,
+                                          const PluginRequest& request);
+
+       /// Run `setUp` on every registry that is not marked 'lazy'.
+       static void setUp();
+
+public:
+       /// Direct access to a registry instance.
+       RegistryInterfaceRef registry(const std::string& registry_name) const;
+
+       void add(const std::string& name, RegistryInterfaceRef reg);
+
+       /// Direct access to all registries.
+       std::map<std::string, RegistryInterfaceRef> all() const;
+
+       /// Direct access to all plugin instances for a given registry name.
+       std::map<std::string, PluginRef> plugins(
+               const std::string& registry_name) const;
+
+       /// Direct access to a plugin instance.
+       PluginRef plugin(const std::string& registry_name,
+                                        const std::string& item_name) const;
+
+       /// Adds an alias for an internal registry item. This registry will only
+       /// broadcast the alias name.
+       Status addAlias(const std::string& registry_name,
+                                       const std::string& item_name,
+                                       const std::string& alias);
+
+       /// Returns the item_name or the item alias if an alias exists.
+       std::string getAlias(const std::string& registry_name,
+                                                const std::string& alias) const;
+
+       /// Set a registry's active plugin.
+       Status setActive(const std::string& registry_name,
+                                        const std::string& item_name);
+
+       /// Get a registry's active plugin.
+       std::string getActive(const std::string& registry_nane) const;
+
+       bool exists(const std::string& registry_name) const
+       {
+               return (registries_.count(registry_name) > 0);
+       }
+
+       /// Check if a registry item exists, optionally search only local registries.
+       bool exists(const std::string& registry_name,
+                               const std::string& item_name,
+                               bool local = false) const;
+
+       /// Get a list of the registry names.
+       std::vector<std::string> names() const;
+
+       /// Get a list of the registry item names for a given registry.
+       std::vector<std::string> names(const std::string& registry_name) const;
+
+       /// Return the number of registries.
+       size_t count() const
+       {
+               return registries_.size();
+       }
+
+       /// Return the number of registry items for a given registry name.
+       size_t count(const std::string& registry_name) const;
+
+       /// Enable/disable duplicate registry item support using aliasing.
+       void allowDuplicates(bool allow)
+       {
+               allow_duplicates_ = allow;
+       }
+
+       /// Check if duplicate registry items using registry aliasing are allowed.
+       bool allowDuplicates()
+       {
+               return allow_duplicates_;
+       }
+
+private:
+       /// Check if the registries are locked.
+       bool locked()
+       {
+               return locked_;
+       }
+
+       /// Set the registry locked status.
+       void locked(bool locked)
+       {
+               locked_ = locked;
+       }
+
+protected:
+       RegistryFactory() = default;
+       virtual ~RegistryFactory() = default;
+
+private:
+       /// Track duplicate registry item support, used for testing.
+       bool allow_duplicates_{false};
+
+       /// Track registry "locking", while locked a registry cannot add/create.
+       bool locked_{false};
+
+       /// The primary storage for constructed registries.
+       std::map<std::string, RegistryInterfaceRef> registries_;
+
+       /// Protector for broadcast lookups and external registry mutations.
+       mutable Mutex mutex_;
+
+private:
+       friend class RegistryInterface;
 };
 
 /**
@@ -180,67 +186,71 @@ namespace registries {
 
 template <class R>
 class AR : public AutoRegisterInterface {
- public:
-  AR(const char* t, const char* n, bool optional)
-      : AutoRegisterInterface(t, n, optional) {}
-
-  void run() override {
-    RegistryFactory::get().add(
-        type_, std::make_shared<RegistryType<R>>(name_, optional_));
-  }
+public:
+       AR(const char* t, const char* n, bool optional)
+               : AutoRegisterInterface(t, n, optional) {}
+
+       void run() override
+       {
+               RegistryFactory::get().add(
+                       type_, std::make_shared<RegistryType<R>>(name_, optional_));
+       }
 };
 
 template <class P>
 class AP : public AutoRegisterInterface {
- public:
-  AP(const char* t, const char* n, bool optional)
-      : AutoRegisterInterface(t, n, optional) {}
-
-  void run() override {
-    auto registry = RegistryFactory::get().registry(type_);
-    registry->add(name_, std::make_shared<P>(), optional_);
-  }
+public:
+       AP(const char* t, const char* n, bool optional)
+               : AutoRegisterInterface(t, n, optional) {}
+
+       void run() override
+       {
+               auto registry = RegistryFactory::get().registry(type_);
+               registry->add(name_, std::make_shared<P>(), optional_);
+       }
 };
 
 template <class R>
 struct RI {
-  RI(const char* class_name,
-     const char* registry_name,
-     bool is_optional = false) {
-    AutoRegisterInterface::autoloadRegistry(
-        std::make_unique<AR<R>>(class_name, registry_name, is_optional));
-  }
+       RI(const char* class_name,
+          const char* registry_name,
+          bool is_optional = false)
+       {
+               AutoRegisterInterface::autoloadRegistry(
+                       std::make_unique<AR<R>>(class_name, registry_name, is_optional));
+       }
 };
 
 template <class P>
 struct PI {
-  PI(const char* registry_name,
-     const char* plugin_name,
-     bool is_optional = false) {
-    AutoRegisterInterface::autoloadPlugin(
-        std::make_unique<AP<P>>(registry_name, plugin_name, is_optional));
-  }
+       PI(const char* registry_name,
+          const char* plugin_name,
+          bool is_optional = false)
+       {
+               AutoRegisterInterface::autoloadPlugin(
+                       std::make_unique<AP<P>>(registry_name, plugin_name, is_optional));
+       }
 };
 } // namespace registries
 
 #define CREATE_REGISTRY(class_name, registry_name)                             \
-  namespace registries {                                                       \
-  const RI<class_name> k##class_name(registry_name, registry_name, false);     \
-  }
+       namespace registries {                                                       \
+       const RI<class_name> k##class_name(registry_name, registry_name, false);     \
+       }
 
 #define CREATE_LAZY_REGISTRY(class_name, registry_name)                        \
-  namespace registries {                                                       \
-  const RI<class_name> k##class_name(registry_name, registry_name, true);      \
-  }
+       namespace registries {                                                       \
+       const RI<class_name> k##class_name(registry_name, registry_name, true);      \
+       }
 
 #define REGISTER(class_name, registry_name, plugin_name)                       \
-  namespace registries {                                                       \
-  const PI<class_name> k##class_name(registry_name, plugin_name, false);       \
-  }
+       namespace registries {                                                       \
+       const PI<class_name> k##class_name(registry_name, plugin_name, false);       \
+       }
 
 #define REGISTER_INTERNAL(class_name, registry_name, plugin_name)              \
-  namespace registries {                                                       \
-  const PI<class_name> k##class_name(registry_name, plugin_name, true);        \
-  }
+       namespace registries {                                                       \
+       const PI<class_name> k##class_name(registry_name, plugin_name, true);        \
+       }
 
 } // namespace osquery
index 7f9f3351cc275aa25b0d835a1f4afbbb34d17f7d..0d9fdf5192baf9bf81cd5f99deef59a32efe6cd1 100644 (file)
@@ -29,144 +29,144 @@ class Status;
  * @brief This is the registry interface.
  */
 class RegistryInterface : private boost::noncopyable {
- public:
-  explicit RegistryInterface(std::string name, bool auto_setup = false)
-      : name_(std::move(name)), auto_setup_(auto_setup) {}
-  virtual ~RegistryInterface() = default;
-
-  /**
-   * @brief This is the only way to add plugins to a registry.
-   *
-   * It must be implemented by the templated child, which knows the type of
-   * registry and which can downcast the input plugin.
-   *
-   * @param plugin_name An indexable name for the plugin.
-   * @param plugin_item A type-specific plugin reference.
-   * @param internal true if this is internal to the osquery SDK.
-   */
-  virtual Status add(const std::string& plugin_name,
-                     const PluginRef& plugin_item,
-                     bool internal = false) = 0;
-
-  /**
-   * @brief Remove a registry item by its identifier.
-   *
-   * @param item_name An identifier for this registry plugin.
-   */
-  void remove(const std::string& item_name);
-
-  /// Allow a registry type to react to configuration updates.
-  virtual void configure();
-
-  /// Check if a given plugin name is considered internal.
-  bool isInternal(const std::string& item_name) const;
-
-  /// Get the 'active' plugin, return success with the active plugin name.
-  std::string getActive() const;
-
-  /// Allow others to introspect into the registered name (for reporting).
-  virtual std::string getName() const;
-
-  /// Facility method to check if a registry item exists.
-  bool exists(const std::string& item_name, bool local = false) const;
-
-  /// Facility method to count the number of items in this registry.
-  size_t count() const;
-
-  /// Facility method to list the registry item identifiers.
-  std::vector<std::string> names() const;
-
-  /**
-   * @brief Allow a plugin to perform some setup functions when osquery starts.
-   *
-   * Doing work in a plugin constructor has unknown behavior. Plugins may
-   * be constructed at anytime during osquery's life, including global variable
-   * instantiation. To have a reliable state (aka, flags have been parsed,
-   * and logs are ready to stream), do construction work in Plugin::setUp.
-   *
-   * The registry `setUp` will iterate over all of its registry items and call
-   * their setup unless the registry is lazy (see CREATE_REGISTRY).
-   */
-  virtual void setUp();
-
-  virtual PluginRef plugin(const std::string& plugin_name) const = 0;
-
-  /// Construct and return a map of plugin names to their implementation.
-  std::map<std::string, PluginRef> plugins();
-
- protected:
-  /**
-   * @brief The only method a plugin user should call.
-   *
-   * Registry plugins are used internally and externally. They may belong
-   * to the process making the call or to an external process via a thrift
-   * transport.
-   *
-   * All plugin input and output must be serializable. The plugin types
-   * RegistryType usually exposes protected serialization methods for the
-   * data structures used by plugins (registry items).
-   *
-   * @param item_name The plugin identifier to call.
-   * @param request The plugin request, usually containing an action request.
-   * @param response If successful, the requested information.
-   * @return Success if the plugin was called, and response was filled.
-   */
-  virtual Status call(const std::string& item_name,
-                      const PluginRequest& request,
-                      PluginResponse& response);
-
-  /// Allow the registry to introspect into the registered name (for logging).
-  void setname(const std::string& name);
-
-  /**
-   * @brief The implementation adder will call addPlugin.
-   *
-   * Once a downcast is completed the work for adding internal/external
-   * indexes is provided here.
-   */
-  Status addPlugin(const std::string& plugin_name,
-                   const PluginRef& plugin_item,
-                   bool internal);
-
-  /// Set an 'active' plugin to receive registry calls when no item name given.
-  Status setActive(const std::string& item_name);
-
-  /// Create a registry item alias for a given item name.
-  Status addAlias(const std::string& item_name, const std::string& alias);
-
-  /// Get the registry item name for a given alias.
-  std::string getAlias(const std::string& alias) const;
-
- protected:
-  /// The identifier for this registry, used to register items.
-  std::string name_;
-
-  /// Does this registry run setUp on each registry item at initialization.
-  bool auto_setup_;
-
- protected:
-  /// A map of registered plugin instances to their registered identifier.
-  std::map<std::string, PluginRef> items_;
-
-  /// If aliases are used, a map of alias to item name.
-  std::map<std::string, std::string> aliases_;
-
-  /// Keep a lookup of registry items that are blacklisted from broadcast.
-  std::vector<std::string> internal_;
-
-  /// Support an 'active' mode where calls without a specific item name will
-  /// be directed to the 'active' plugin.
-  std::string active_;
-
-  /// Protect concurrent accesses to object's data
-  mutable Mutex mutex_;
-
- private:
-  friend class RegistryFactory;
-
-  bool isInternal_(const std::string& item_name) const;
-
-  bool exists_(const std::string& item_name, bool local) const;
+public:
+       explicit RegistryInterface(std::string name, bool auto_setup = false)
+               : name_(std::move(name)), auto_setup_(auto_setup) {}
+       virtual ~RegistryInterface() = default;
+
+       /**
+        * @brief This is the only way to add plugins to a registry.
+        *
+        * It must be implemented by the templated child, which knows the type of
+        * registry and which can downcast the input plugin.
+        *
+        * @param plugin_name An indexable name for the plugin.
+        * @param plugin_item A type-specific plugin reference.
+        * @param internal true if this is internal to the osquery SDK.
+        */
+       virtual Status add(const std::string& plugin_name,
+                                          const PluginRef& plugin_item,
+                                          bool internal = false) = 0;
+
+       /**
+        * @brief Remove a registry item by its identifier.
+        *
+        * @param item_name An identifier for this registry plugin.
+        */
+       void remove(const std::string& item_name);
+
+       /// Allow a registry type to react to configuration updates.
+       virtual void configure();
+
+       /// Check if a given plugin name is considered internal.
+       bool isInternal(const std::string& item_name) const;
+
+       /// Get the 'active' plugin, return success with the active plugin name.
+       std::string getActive() const;
+
+       /// Allow others to introspect into the registered name (for reporting).
+       virtual std::string getName() const;
+
+       /// Facility method to check if a registry item exists.
+       bool exists(const std::string& item_name, bool local = false) const;
+
+       /// Facility method to count the number of items in this registry.
+       size_t count() const;
+
+       /// Facility method to list the registry item identifiers.
+       std::vector<std::string> names() const;
+
+       /**
+        * @brief Allow a plugin to perform some setup functions when osquery starts.
+        *
+        * Doing work in a plugin constructor has unknown behavior. Plugins may
+        * be constructed at anytime during osquery's life, including global variable
+        * instantiation. To have a reliable state (aka, flags have been parsed,
+        * and logs are ready to stream), do construction work in Plugin::setUp.
+        *
+        * The registry `setUp` will iterate over all of its registry items and call
+        * their setup unless the registry is lazy (see CREATE_REGISTRY).
+        */
+       virtual void setUp();
+
+       virtual PluginRef plugin(const std::string& plugin_name) const = 0;
+
+       /// Construct and return a map of plugin names to their implementation.
+       std::map<std::string, PluginRef> plugins();
+
+protected:
+       /**
+        * @brief The only method a plugin user should call.
+        *
+        * Registry plugins are used internally and externally. They may belong
+        * to the process making the call or to an external process via a thrift
+        * transport.
+        *
+        * All plugin input and output must be serializable. The plugin types
+        * RegistryType usually exposes protected serialization methods for the
+        * data structures used by plugins (registry items).
+        *
+        * @param item_name The plugin identifier to call.
+        * @param request The plugin request, usually containing an action request.
+        * @param response If successful, the requested information.
+        * @return Success if the plugin was called, and response was filled.
+        */
+       virtual Status call(const std::string& item_name,
+                                               const PluginRequest& request,
+                                               PluginResponse& response);
+
+       /// Allow the registry to introspect into the registered name (for logging).
+       void setname(const std::string& name);
+
+       /**
+        * @brief The implementation adder will call addPlugin.
+        *
+        * Once a downcast is completed the work for adding internal/external
+        * indexes is provided here.
+        */
+       Status addPlugin(const std::string& plugin_name,
+                                        const PluginRef& plugin_item,
+                                        bool internal);
+
+       /// Set an 'active' plugin to receive registry calls when no item name given.
+       Status setActive(const std::string& item_name);
+
+       /// Create a registry item alias for a given item name.
+       Status addAlias(const std::string& item_name, const std::string& alias);
+
+       /// Get the registry item name for a given alias.
+       std::string getAlias(const std::string& alias) const;
+
+protected:
+       /// The identifier for this registry, used to register items.
+       std::string name_;
+
+       /// Does this registry run setUp on each registry item at initialization.
+       bool auto_setup_;
+
+protected:
+       /// A map of registered plugin instances to their registered identifier.
+       std::map<std::string, PluginRef> items_;
+
+       /// If aliases are used, a map of alias to item name.
+       std::map<std::string, std::string> aliases_;
+
+       /// Keep a lookup of registry items that are blacklisted from broadcast.
+       std::vector<std::string> internal_;
+
+       /// Support an 'active' mode where calls without a specific item name will
+       /// be directed to the 'active' plugin.
+       std::string active_;
+
+       /// Protect concurrent accesses to object's data
+       mutable Mutex mutex_;
+
+private:
+       friend class RegistryFactory;
+
+       bool isInternal_(const std::string& item_name) const;
+
+       bool exists_(const std::string& item_name, bool local) const;
 };
 
 /**
@@ -178,45 +178,47 @@ class RegistryInterface : private boost::noncopyable {
  */
 template <class PluginType>
 class RegistryType : public RegistryInterface {
- protected:
-  using PluginTypeRef = std::shared_ptr<PluginType>;
-
- public:
-  explicit RegistryType(const std::string& name, bool auto_setup = false)
-      : RegistryInterface(name, auto_setup) {}
-  ~RegistryType() override = default;
-
-  Status add(const std::string& plugin_name,
-             const PluginRef& plugin_item,
-             bool internal = false) override {
-    if (nullptr == std::dynamic_pointer_cast<PluginType>(plugin_item)) {
-      throw std::runtime_error("Cannot add foreign plugin type: " +
-                               plugin_name);
-    }
-    return addPlugin(plugin_name, plugin_item, internal);
-  }
-
-  /**
-   * @brief A raw accessor for a registry plugin.
-   *
-   * If there is no plugin with an item_name identifier this will throw
-   * and out_of_range exception.
-   *
-   * @param plugin_name An identifier for this registry plugin.
-   * @return A std::shared_ptr of type RegistryType.
-   */
-  PluginRef plugin(const std::string& plugin_name) const override {
-    ReadLock lock(mutex_);
-
-    if (items_.count(plugin_name) == 0) {
-      return nullptr;
-    }
-    return items_.at(plugin_name);
-  }
-
- private:
-  FRIEND_TEST(EventsTests, test_event_subscriber_configure);
-  FRIEND_TEST(VirtualTableTests, test_indexing_costs);
+protected:
+       using PluginTypeRef = std::shared_ptr<PluginType>;
+
+public:
+       explicit RegistryType(const std::string& name, bool auto_setup = false)
+               : RegistryInterface(name, auto_setup) {}
+       ~RegistryType() override = default;
+
+       Status add(const std::string& plugin_name,
+                          const PluginRef& plugin_item,
+                          bool internal = false) override
+       {
+               if (nullptr == std::dynamic_pointer_cast<PluginType>(plugin_item)) {
+                       throw std::runtime_error("Cannot add foreign plugin type: " +
+                                                                        plugin_name);
+               }
+               return addPlugin(plugin_name, plugin_item, internal);
+       }
+
+       /**
+        * @brief A raw accessor for a registry plugin.
+        *
+        * If there is no plugin with an item_name identifier this will throw
+        * and out_of_range exception.
+        *
+        * @param plugin_name An identifier for this registry plugin.
+        * @return A std::shared_ptr of type RegistryType.
+        */
+       PluginRef plugin(const std::string& plugin_name) const override
+       {
+               ReadLock lock(mutex_);
+
+               if (items_.count(plugin_name) == 0) {
+                       return nullptr;
+               }
+               return items_.at(plugin_name);
+       }
+
+private:
+       FRIEND_TEST(EventsTests, test_event_subscriber_configure);
+       FRIEND_TEST(VirtualTableTests, test_indexing_costs);
 };
 
 /// Helper definitions for a shared pointer to the basic Registry type.
@@ -226,34 +228,34 @@ class AutoRegisterInterface;
 using AutoRegisterSet = std::vector<std::unique_ptr<AutoRegisterInterface>>;
 
 class AutoRegisterInterface {
- public:
-  /// The registry name, or type identifier.
-  std::string type_;
+public:
+       /// The registry name, or type identifier.
+       std::string type_;
 
-  /// The registry or plugin name.
-  std::string name_;
+       /// The registry or plugin name.
+       std::string name_;
 
-  /// Either autoload a registry, or create an internal plugin.
-  bool optional_;
+       /// Either autoload a registry, or create an internal plugin.
+       bool optional_;
 
-  AutoRegisterInterface(const char* _type, const char* _name, bool optional);
-  virtual ~AutoRegisterInterface() = default;
+       AutoRegisterInterface(const char* _type, const char* _name, bool optional);
+       virtual ~AutoRegisterInterface() = default;
 
-  /// A call-in for the iterator.
-  virtual void run() = 0;
+       /// A call-in for the iterator.
+       virtual void run() = 0;
 
- public:
-  /// Access all registries.
-  static AutoRegisterSet& registries();
+public:
+       /// Access all registries.
+       static AutoRegisterSet& registries();
 
-  /// Insert a new registry.
-  static void autoloadRegistry(std::unique_ptr<AutoRegisterInterface> ar_);
+       /// Insert a new registry.
+       static void autoloadRegistry(std::unique_ptr<AutoRegisterInterface> ar_);
 
-  /// Access all plugins.
-  static AutoRegisterSet& plugins();
+       /// Access all plugins.
+       static AutoRegisterSet& plugins();
 
-  /// Insert a new plugin.
-  static void autoloadPlugin(std::unique_ptr<AutoRegisterInterface> ar_);
+       /// Insert a new plugin.
+       static void autoloadPlugin(std::unique_ptr<AutoRegisterInterface> ar_);
 };
 
 void registryAndPluginInit();
index d3bf6b09e1ad4870f6eedcdf8e30aa5852f52aec..aa2ea5edef95402a7764ca633c34a0b616e9b255 100644 (file)
@@ -36,123 +36,123 @@ namespace osquery {
  * @endcode
  */
 class SQL : private only_movable {
- public:
-  /**
-   * @brief Instantiate an instance of the class with a query.
-   *
-   * @param query An osquery SQL query.
-   * @param use_cache [optional] Set true to use the query cache.
-   */
-  explicit SQL(const std::string& query, bool use_cache = false);
-
-  /// Allow moving.
-  SQL(SQL&&) noexcept = default;
-
-  /// Allow move assignment.
-  SQL& operator=(SQL&&) = default;
-
- public:
-  /**
-   * @brief Const accessor for the rows returned by the query.
-   *
-   * @return A QueryData object of the query results.
-   */
-  const QueryData& rows() const;
-
-  /**
-   * @brief Accessor for the rows returned by the query.
-   *
-   * @return A QueryData object of the query results.
-   */
-  QueryData& rows();
-
-  /**
-   * @brief Column information for the query
-   *
-   * @return A ColumnNames object for the query
-   */
-  const ColumnNames& columns() const;
-
-  /**
-   * @brief Accessor to switch off of when checking the success of a query.
-   *
-   * @return A bool indicating the success or failure of the operation.
-   */
-  bool ok() const;
-
-  /**
-   * @brief Get the status returned by the query.
-   *
-   * @return The query status.
-   */
-  const Status& getStatus() const;
-
-  /**
-   * @brief Accessor for the message string indicating the status of the query.
-   *
-   * @return The message string indicating the status of the query.
-   */
-  std::string getMessageString() const;
-
-
- public:
-  /**
-   * @brief Get all, 'SELECT * ...', results given a virtual table name.
-   *
-   * @param table The name of the virtual table.
-   * @return A QueryData object of the 'SELECT *...' query results.
-   */
-  static QueryData selectAllFrom(const std::string& table);
-
-  /**
-   * @brief Get all with constraint, 'SELECT * ... where', results given
-   * a virtual table name and single constraint.
-   *
-   * @param table The name of the virtual table.
-   * @param column Table column name to apply constraint.
-   * @param op The SQL comparative operator.
-   * @param expr The constraint expression.
-   * @return A QueryData object of the 'SELECT *...' query results.
-   */
-  static QueryData selectAllFrom(const std::string& table,
-                                 const std::string& column,
-                                 ConstraintOperator op,
-                                 const std::string& expr);
-
-  /**
-   * @brief Get columns with constraint, 'SELECT [columns] ... where', results
-   * given a virtual table name, column names, and single constraint.
-   *
-   * @param columns the columns to return
-   * @param table The name of the virtual table.
-   * @param column Table column name to apply constraint.
-   * @param op The SQL comparative operator.
-   * @param expr The constraint expression.
-   * @return A QueryData object of the 'SELECT [columns] ...' query results.
-   */
-  static QueryData selectFrom(const std::initializer_list<std::string>& columns,
-                              const std::string& table,
-                              const std::string& column,
-                              ConstraintOperator op,
-                              const std::string& expr);
-
- protected:
-  /**
-   * @brief Private default constructor.
-   *
-   * The osquery::SQL class should only ever be instantiated with a query.
-   */
-  SQL() = default;
-
- protected:
-  /// The internal member which holds the results of the query.
-  QueryData results_;
-
-  /// The internal member which holds the status of the query.
-  Status status_;
-
-  /// The internal member which holds the column names and order for the query
-  ColumnNames columns_;
+public:
+       /**
+        * @brief Instantiate an instance of the class with a query.
+        *
+        * @param query An osquery SQL query.
+        * @param use_cache [optional] Set true to use the query cache.
+        */
+       explicit SQL(const std::string& query, bool use_cache = false);
+
+       /// Allow moving.
+       SQL(SQL&&) noexcept = default;
+
+       /// Allow move assignment.
+       SQL& operator=(SQL&&) = default;
+
+public:
+       /**
+        * @brief Const accessor for the rows returned by the query.
+        *
+        * @return A QueryData object of the query results.
+        */
+       const QueryData& rows() const;
+
+       /**
+        * @brief Accessor for the rows returned by the query.
+        *
+        * @return A QueryData object of the query results.
+        */
+       QueryData& rows();
+
+       /**
+        * @brief Column information for the query
+        *
+        * @return A ColumnNames object for the query
+        */
+       const ColumnNames& columns() const;
+
+       /**
+        * @brief Accessor to switch off of when checking the success of a query.
+        *
+        * @return A bool indicating the success or failure of the operation.
+        */
+       bool ok() const;
+
+       /**
+        * @brief Get the status returned by the query.
+        *
+        * @return The query status.
+        */
+       const Status& getStatus() const;
+
+       /**
+        * @brief Accessor for the message string indicating the status of the query.
+        *
+        * @return The message string indicating the status of the query.
+        */
+       std::string getMessageString() const;
+
+
+public:
+       /**
+        * @brief Get all, 'SELECT * ...', results given a virtual table name.
+        *
+        * @param table The name of the virtual table.
+        * @return A QueryData object of the 'SELECT *...' query results.
+        */
+       static QueryData selectAllFrom(const std::string& table);
+
+       /**
+        * @brief Get all with constraint, 'SELECT * ... where', results given
+        * a virtual table name and single constraint.
+        *
+        * @param table The name of the virtual table.
+        * @param column Table column name to apply constraint.
+        * @param op The SQL comparative operator.
+        * @param expr The constraint expression.
+        * @return A QueryData object of the 'SELECT *...' query results.
+        */
+       static QueryData selectAllFrom(const std::string& table,
+                                                                  const std::string& column,
+                                                                  ConstraintOperator op,
+                                                                  const std::string& expr);
+
+       /**
+        * @brief Get columns with constraint, 'SELECT [columns] ... where', results
+        * given a virtual table name, column names, and single constraint.
+        *
+        * @param columns the columns to return
+        * @param table The name of the virtual table.
+        * @param column Table column name to apply constraint.
+        * @param op The SQL comparative operator.
+        * @param expr The constraint expression.
+        * @return A QueryData object of the 'SELECT [columns] ...' query results.
+        */
+       static QueryData selectFrom(const std::initializer_list<std::string>& columns,
+                                                               const std::string& table,
+                                                               const std::string& column,
+                                                               ConstraintOperator op,
+                                                               const std::string& expr);
+
+protected:
+       /**
+        * @brief Private default constructor.
+        *
+        * The osquery::SQL class should only ever be instantiated with a query.
+        */
+       SQL() = default;
+
+protected:
+       /// The internal member which holds the results of the query.
+       QueryData results_;
+
+       /// The internal member which holds the status of the query.
+       Status status_;
+
+       /// The internal member which holds the column names and order for the query
+       ColumnNames columns_;
 };
 
 
@@ -182,8 +182,8 @@ class SQL : private only_movable {
  * @return A status indicating query success.
  */
 Status query(const std::string& query,
-             QueryData& results,
-             bool use_cache = false);
+                        QueryData& results,
+                        bool use_cache = false);
 
 /**
  * @brief Analyze a query, providing information about the result columns.
index 232d8d642dcd4fb3dd10a8e82af20c19180de613..091cb65ed2c17154aca1ebb7b9825bf167b3a872 100644 (file)
@@ -52,38 +52,46 @@ class Status;
  * time.
  */
 template <typename Type>
-inline std::string __sqliteField(const Type& source) noexcept {
-  return std::to_string(source);
+inline std::string __sqliteField(const Type& source) noexcept
+{
+       return std::to_string(source);
 }
 
 template <size_t N>
-inline std::string __sqliteField(const char (&source)[N]) noexcept {
-  return std::string(source, N - 1U);
+inline std::string __sqliteField(const char (&source)[N]) noexcept
+{
+       return std::string(source, N - 1U);
 }
 
 template <size_t N>
-inline std::string __sqliteField(const unsigned char (&source)[N]) noexcept {
-  return std::string(reinterpret_cast<const char*>(source), N - 1U);
+inline std::string __sqliteField(const unsigned char (&source)[N]) noexcept
+{
+       return std::string(reinterpret_cast<const char*>(source), N - 1U);
 }
 
-inline std::string __sqliteField(const char* source) noexcept {
-  return std::string(source);
+inline std::string __sqliteField(const char* source) noexcept
+{
+       return std::string(source);
 }
 
-inline std::string __sqliteField(char* const source) noexcept {
-  return std::string(source);
+inline std::string __sqliteField(char* const source) noexcept
+{
+       return std::string(source);
 }
 
-inline std::string __sqliteField(const unsigned char* source) noexcept {
-  return std::string(reinterpret_cast<const char*>(source));
+inline std::string __sqliteField(const unsigned char* source) noexcept
+{
+       return std::string(reinterpret_cast<const char*>(source));
 }
 
-inline std::string __sqliteField(unsigned char* const source) noexcept {
-  return std::string(reinterpret_cast<char* const>(source));
+inline std::string __sqliteField(unsigned char* const source) noexcept
+{
+       return std::string(reinterpret_cast<char* const>(source));
 }
 
-inline std::string __sqliteField(const std::string& source) noexcept {
-  return source;
+inline std::string __sqliteField(const std::string& source) noexcept
+{
+       return source;
 }
 
 #ifdef WIN32
@@ -128,16 +136,16 @@ inline std::string __sqliteField(const std::string& source) noexcept {
  * expression the table generator may limit the data appropriately.
  */
 enum ConstraintOperator : unsigned char {
-  EQUALS = 2,
-  GREATER_THAN = 4,
-  LESS_THAN_OR_EQUALS = 8,
-  LESS_THAN = 16,
-  GREATER_THAN_OR_EQUALS = 32,
-  MATCH = 64,
-  LIKE = 65,
-  GLOB = 66,
-  REGEXP = 67,
-  UNIQUE = 1,
+       EQUALS = 2,
+       GREATER_THAN = 4,
+       LESS_THAN_OR_EQUALS = 8,
+       LESS_THAN = 16,
+       GREATER_THAN_OR_EQUALS = 32,
+       MATCH = 64,
+       LIKE = 65,
+       GLOB = 66,
+       REGEXP = 67,
+       UNIQUE = 1,
 };
 
 /// Type for flags for what constraint operators are admissible.
@@ -152,17 +160,18 @@ using ConstraintOperatorFlag = unsigned char;
  * The constraint is applied to columns which have literal and affinity types.
  */
 struct Constraint {
-  unsigned char op;
-  std::string expr;
-
-  /// Construct a Constraint with the most-basic information, the operator.
-  explicit Constraint(unsigned char _op) {
-    op = _op;
-  }
-
-  // A constraint list in a context knows only the operator at creation.
-  explicit Constraint(unsigned char _op, std::string _expr)
-      : op(_op), expr(std::move(_expr)) {}
+       unsigned char op;
+       std::string expr;
+
+       /// Construct a Constraint with the most-basic information, the operator.
+       explicit Constraint(unsigned char _op)
+       {
+               op = _op;
+       }
+
+       // A constraint list in a context knows only the operator at creation.
+       explicit Constraint(unsigned char _op, std::string _expr)
+               : op(_op), expr(std::move(_expr)) {}
 };
 
 
@@ -170,41 +179,43 @@ struct Constraint {
  * @brief Attributes about a Table implementation.
  */
 enum class TableAttributes {
-  /// Default no-op attribute.
-  NONE = 0,
+       /// Default no-op attribute.
+       NONE = 0,
 
-  /// This table is a 'utility' and is always available locally.
-  UTILITY = 1,
+       /// This table is a 'utility' and is always available locally.
+       UTILITY = 1,
 
-  /// The results from this table may be cached within a schedule.
-  CACHEABLE = 2,
+       /// The results from this table may be cached within a schedule.
+       CACHEABLE = 2,
 
-  /// The results are backed by a set time-indexed, always growing, events.
-  EVENT_BASED = 4,
+       /// The results are backed by a set time-indexed, always growing, events.
+       EVENT_BASED = 4,
 
-  /// This table inspect items relative to each user, a JOIN may be required.
-  USER_BASED = 8,
+       /// This table inspect items relative to each user, a JOIN may be required.
+       USER_BASED = 8,
 
-  /// This table's data requires an osquery kernel extension/module.
-  KERNEL_REQUIRED = 16,
+       /// This table's data requires an osquery kernel extension/module.
+       KERNEL_REQUIRED = 16,
 };
 
 /// Treat table attributes as a set of flags.
-inline TableAttributes operator|(TableAttributes a, TableAttributes b) {
-  return static_cast<TableAttributes>(static_cast<int>(a) |
-                                      static_cast<int>(b));
+inline TableAttributes operator|(TableAttributes a, TableAttributes b)
+{
+       return static_cast<TableAttributes>(static_cast<int>(a) |
+                                                                               static_cast<int>(b));
 }
 
 /// Treat column options as a set of flags.
-inline size_t operator&(TableAttributes a, TableAttributes b) {
-  return static_cast<size_t>(a) & static_cast<size_t>(b);
+inline size_t operator&(TableAttributes a, TableAttributes b)
+{
+       return static_cast<size_t>(a) & static_cast<size_t>(b);
 }
 
 
 
 /// Alias for an ordered list of column name and corresponding SQL type.
 using TableColumns =
-    std::vector<std::tuple<std::string, ColumnType, ColumnOptions>>;
+       std::vector<std::tuple<std::string, ColumnType, ColumnOptions>>;
 
 /// Alias for map of column alias sets.
 using ColumnAliasSet = std::map<std::string, std::set<std::string>>;
@@ -226,140 +237,145 @@ struct QueryContext;
  * A constraint list supports all AS_LITERAL types, and all ConstraintOperators.
  */
 struct ConstraintList : private boost::noncopyable {
- public:
-  /// The SQLite affinity type.
-  ColumnType affinity{TEXT_TYPE};
-
-  /**
-   * @brief Check if an expression matches the query constraints.
-   *
-   * Evaluate ALL constraints in this ConstraintList against the string
-   * expression. The affinity of the constraint will be used as the affinite
-   * and lexical type of the expression and set of constraint expressions.
-   * If there are no predicate constraints in this list, all expression will
-   * match. Constraints are limitations.
-   *
-   * @param expr a SQL type expression of the column literal type to check.
-   * @return If the expression matched all constraints.
-   */
-  bool matches(const std::string& expr) const;
-
-  /**
-   * @brief Check if an expression matches the query constraints.
-   *
-   * `matches` also supports the set of SQL affinite types.
-   * The expression expr will be evaluated as a string and compared using
-   * the affinity of the constraint.
-   *
-   * @param expr a SQL type expression of the column literal type to check.
-   * @return If the expression matched all constraints.
-   */
-  template <typename T>
-  bool matches(const T& expr) const {
-    return matches(SQL_TEXT(expr));
-  }
-
-  /**
-   * @brief Check and return if there are constraints on this column.
-   *
-   * A ConstraintList is used in a ConstraintMap with a column name as the
-   * map index. Tables that act on optional constraints should check if any
-   * constraint was provided.  The ops parameter serves to specify which
-   * operators we want to check existence for.
-   *
-   * @param ops (Optional: default ANY_OP) The operators types to look for.
-   * @return true if any constraint exists.
-   */
-  bool exists(ConstraintOperatorFlag ops = ANY_OP) const;
-
-  /**
-   * @brief Check if a constraint exists AND matches the type expression.
-   *
-   * See ConstraintList::exists and ConstraintList::matches.
-   *
-   * @param expr The expression to match.
-   * @return true if any constraint exists AND matches the type expression.
-   */
-  template <typename T>
-  bool existsAndMatches(const T& expr) const {
-    return (exists() && matches(expr));
-  }
-
-  /**
-   * @brief Check if a constraint is missing or matches a type expression.
-   *
-   * A ConstraintList is used in a ConstraintMap with a column name as the
-   * map index. Tables that act on required constraints can make decisions
-   * on missing constraints or a constraint match.
-   *
-   * @param expr The expression to match.
-   * @return true if constraint is missing or matches the type expression.
-   */
-  template <typename T>
-  bool notExistsOrMatches(const T& expr) const {
-    return (!exists() || matches(expr));
-  }
-
-  /**
-   * @brief Helper templated function for ConstraintList::matches.
-   */
-  template <typename T>
-  bool literal_matches(const T& base_expr) const;
-
-  /**
-   * @brief Get all expressions for a given ConstraintOperator.
-   *
-   * This is most useful if the table generation requires as column.
-   * The generator may `getAll(EQUALS)` then iterate.
-   *
-   * @param op the ConstraintOperator.
-   * @return A list of TEXT%-represented types matching the operator.
-   */
-  std::set<std::string> getAll(ConstraintOperator op) const;
-
-  /// See ConstraintList::getAll, but as a selected literal type.
-  template <typename T>
-  std::set<T> getAll(ConstraintOperator op) const;
-
-  /// Constraint list accessor, types and operator.
-  const std::vector<struct Constraint>& getAll() const {
-    return constraints_;
-  }
-
-  /**
-   * @brief Add a new Constraint to the list of constraints.
-   *
-   * @param constraint a new operator/expression to constrain.
-   */
-  void add(const struct Constraint& constraint) {
-    constraints_.push_back(constraint);
-  }
-
-  /**
-   * @brief Serialize a ConstraintList into a property tree.
-   *
-   * The property tree will use the format:
-   * {
-   *   "affinity": affinity,
-   *   "list": [
-   *     {"op": op, "expr": expr}, ...
-   *   ]
-   * }
-   */
-  vist::json::Object serialize() const;
-
-  void deserialize(vist::json::Object& obj);
-
-
- private:
-  /// List of constraint operator/expressions.
-  std::vector<struct Constraint> constraints_;
-
- private:
-  friend struct QueryContext;
-
- private:
-   FRIEND_TEST(TablesTests, test_constraint_list);
+public:
+       /// The SQLite affinity type.
+       ColumnType affinity{TEXT_TYPE};
+
+       /**
+        * @brief Check if an expression matches the query constraints.
+        *
+        * Evaluate ALL constraints in this ConstraintList against the string
+        * expression. The affinity of the constraint will be used as the affinite
+        * and lexical type of the expression and set of constraint expressions.
+        * If there are no predicate constraints in this list, all expression will
+        * match. Constraints are limitations.
+        *
+        * @param expr a SQL type expression of the column literal type to check.
+        * @return If the expression matched all constraints.
+        */
+       bool matches(const std::string& expr) const;
+
+       /**
+        * @brief Check if an expression matches the query constraints.
+        *
+        * `matches` also supports the set of SQL affinite types.
+        * The expression expr will be evaluated as a string and compared using
+        * the affinity of the constraint.
+        *
+        * @param expr a SQL type expression of the column literal type to check.
+        * @return If the expression matched all constraints.
+        */
+       template <typename T>
+       bool matches(const T& expr) const
+       {
+               return matches(SQL_TEXT(expr));
+       }
+
+       /**
+        * @brief Check and return if there are constraints on this column.
+        *
+        * A ConstraintList is used in a ConstraintMap with a column name as the
+        * map index. Tables that act on optional constraints should check if any
+        * constraint was provided.  The ops parameter serves to specify which
+        * operators we want to check existence for.
+        *
+        * @param ops (Optional: default ANY_OP) The operators types to look for.
+        * @return true if any constraint exists.
+        */
+       bool exists(ConstraintOperatorFlag ops = ANY_OP) const;
+
+       /**
+        * @brief Check if a constraint exists AND matches the type expression.
+        *
+        * See ConstraintList::exists and ConstraintList::matches.
+        *
+        * @param expr The expression to match.
+        * @return true if any constraint exists AND matches the type expression.
+        */
+       template <typename T>
+       bool existsAndMatches(const T& expr) const
+       {
+               return (exists() && matches(expr));
+       }
+
+       /**
+        * @brief Check if a constraint is missing or matches a type expression.
+        *
+        * A ConstraintList is used in a ConstraintMap with a column name as the
+        * map index. Tables that act on required constraints can make decisions
+        * on missing constraints or a constraint match.
+        *
+        * @param expr The expression to match.
+        * @return true if constraint is missing or matches the type expression.
+        */
+       template <typename T>
+       bool notExistsOrMatches(const T& expr) const
+       {
+               return (!exists() || matches(expr));
+       }
+
+       /**
+        * @brief Helper templated function for ConstraintList::matches.
+        */
+       template <typename T>
+       bool literal_matches(const T& base_expr) const;
+
+       /**
+        * @brief Get all expressions for a given ConstraintOperator.
+        *
+        * This is most useful if the table generation requires as column.
+        * The generator may `getAll(EQUALS)` then iterate.
+        *
+        * @param op the ConstraintOperator.
+        * @return A list of TEXT%-represented types matching the operator.
+        */
+       std::set<std::string> getAll(ConstraintOperator op) const;
+
+       /// See ConstraintList::getAll, but as a selected literal type.
+       template <typename T>
+       std::set<T> getAll(ConstraintOperator op) const;
+
+       /// Constraint list accessor, types and operator.
+       const std::vector<struct Constraint>& getAll() const
+       {
+               return constraints_;
+       }
+
+       /**
+        * @brief Add a new Constraint to the list of constraints.
+        *
+        * @param constraint a new operator/expression to constrain.
+        */
+       void add(const struct Constraint& constraint)
+       {
+               constraints_.push_back(constraint);
+       }
+
+       /**
+        * @brief Serialize a ConstraintList into a property tree.
+        *
+        * The property tree will use the format:
+        * {
+        *   "affinity": affinity,
+        *   "list": [
+        *     {"op": op, "expr": expr}, ...
+        *   ]
+        * }
+        */
+       vist::json::Object serialize() const;
+
+       void deserialize(vist::json::Object& obj);
+
+
+private:
+       /// List of constraint operator/expressions.
+       std::vector<struct Constraint> constraints_;
+
+private:
+       friend struct QueryContext;
+
+private:
+       FRIEND_TEST(TablesTests, test_constraint_list);
 };
 
 /// Pass a constraint map to the query request.
@@ -372,8 +388,8 @@ using ConstraintSet = std::vector<std::pair<std::string, struct Constraint>>;
 using UsedColumns = std::unordered_set<std::string>;
 
 /// Keep track of which columns are used, as a bitset
-using UsedColumnsBitset = std::bitset<
-    std::numeric_limits<decltype(sqlite3_index_info().colUsed)>::digits>;
+using UsedColumnsBitset = std::bitset <
+                                                 std::numeric_limits<decltype(sqlite3_index_info().colUsed)>::digits >;
 
 /**
  * @brief osquery table content descriptor.
@@ -390,50 +406,50 @@ using UsedColumnsBitset = std::bitset<
  * a cache or choose not to generate certain columns.
  */
 struct VirtualTableContent {
-  /// Friendly name for the table.
-  TableName name;
-
-  /// Table column structure, retrieved once via the TablePlugin call API.
-  TableColumns columns;
-
-  /// Attributes are copied into the content such that they can be quickly
-  /// passed to the SQL and optional Query for inspection.
-  TableAttributes attributes{TableAttributes::NONE};
-
-  /**
-   * @brief Table column aliases structure.
-   *
-   * This is used within xColumn to move content from special HIDDEN columns
-   * that act as aliases. If these columns are requested the content is moved
-   * from the new non-deprecated name.
-   */
-  std::map<std::string, size_t> aliases;
-
-  /// Transient set of virtual table access constraints.
-  std::unordered_map<size_t, ConstraintSet> constraints;
-
-  /// Transient set of virtual table used columns
-  std::unordered_map<size_t, UsedColumns> colsUsed;
-
-  /// Transient set of virtual table used columns (as bitmasks)
-  std::unordered_map<size_t, UsedColumnsBitset> colsUsedBitsets;
-
-  /*
-   * @brief A table implementation specific query result cache.
-   *
-   * Virtual tables may 'cache' information between filter requests. This is
-   * intended to provide optimization for very latent/expensive tables where
-   * complex joins may result in duplicate filter requests.
-   *
-   * The cache is implemented as a map of row data. The cache concept
-   * should utilize a primary key as an index, and may store arbitrary data.
-   * More intense caching may use the backing store though the general database
-   * set and get calls.
-   *
-   * The in-memory, non-backing store, cache is expired after each query run.
-   * This caching does not affect or use the schedule results cache.
-   */
-  std::map<std::string, TableRowHolder> cache;
+       /// Friendly name for the table.
+       TableName name;
+
+       /// Table column structure, retrieved once via the TablePlugin call API.
+       TableColumns columns;
+
+       /// Attributes are copied into the content such that they can be quickly
+       /// passed to the SQL and optional Query for inspection.
+       TableAttributes attributes{TableAttributes::NONE};
+
+       /**
+        * @brief Table column aliases structure.
+        *
+        * This is used within xColumn to move content from special HIDDEN columns
+        * that act as aliases. If these columns are requested the content is moved
+        * from the new non-deprecated name.
+        */
+       std::map<std::string, size_t> aliases;
+
+       /// Transient set of virtual table access constraints.
+       std::unordered_map<size_t, ConstraintSet> constraints;
+
+       /// Transient set of virtual table used columns
+       std::unordered_map<size_t, UsedColumns> colsUsed;
+
+       /// Transient set of virtual table used columns (as bitmasks)
+       std::unordered_map<size_t, UsedColumnsBitset> colsUsedBitsets;
+
+       /*
+        * @brief A table implementation specific query result cache.
+        *
+        * Virtual tables may 'cache' information between filter requests. This is
+        * intended to provide optimization for very latent/expensive tables where
+        * complex joins may result in duplicate filter requests.
+        *
+        * The cache is implemented as a map of row data. The cache concept
+        * should utilize a primary key as an index, and may store arbitrary data.
+        * More intense caching may use the backing store though the general database
+        * set and get calls.
+        *
+        * The in-memory, non-backing store, cache is expired after each query run.
+        * This caching does not affect or use the schedule results cache.
+        */
+       std::map<std::string, TableRowHolder> cache;
 };
 
 /**
@@ -441,206 +457,216 @@ struct VirtualTableContent {
  * on query components like predicate constraints and limits.
  */
 struct QueryContext {
-  /// Construct a context without cache support.
-  QueryContext() {
-    table_ = std::make_shared<VirtualTableContent>();
-  }
-
-  /// If the context was created without content, it is ephemeral.
-  ~QueryContext() = default;
-
-  /// Construct a context and set the table content for caching.
-  explicit QueryContext(std::shared_ptr<VirtualTableContent> content)
-      : enable_cache_(true), table_(std::move(content)) {}
-
-  /// Disallow copying
-  QueryContext(const QueryContext&) = delete;
-
-  /// Disallow copy assignment.
-  QueryContext& operator=(const QueryContext&) = delete;
-
-  /// Allow moving.
-  QueryContext(QueryContext&& other)
-      : constraints(std::move(other.constraints)),
-        colsUsed(std::move(other.colsUsed)),
-        enable_cache_(other.enable_cache_),
-        use_cache_(other.use_cache_),
-        table_(other.table_) {
-    other.enable_cache_ = false;
-    other.table_ = nullptr;
-  }
-
-  /// Allow move assignment.
-  QueryContext& operator=(QueryContext&& other) {
-    std::swap(constraints, other.constraints);
-    std::swap(colsUsed, other.colsUsed);
-    std::swap(enable_cache_, other.enable_cache_);
-    std::swap(use_cache_, other.use_cache_);
-    std::swap(table_, other.table_);
-
-    return *this;
-  }
-
-  /**
-   * @brief Check if a constraint exists for a given column operator pair.
-   *
-   * Operator and expression existence and matching occurs on the constraint
-   * list for a given column name. The query context maintains a map of columns
-   * to potentially empty constraint lists. Check if a constraint exists with
-   * any operator or for a specific operator, usually equality (EQUALS).
-   *
-   * @param column The name of a column within this table.
-   * @param op Check for a specific constraint operator (default EQUALS).
-   * @return true if a constraint exists, false if empty or no operator match.
-   */
-  bool hasConstraint(const std::string& column,
-                     ConstraintOperator op = EQUALS) const;
-
-  /**
-   * @brief Apply a predicate function to each expression in a constraint list.
-   *
-   * Most constraint sets are use to extract expressions or perform a row
-   * generation for each expressions (given an operator).
-   *
-   * This prevents the caller (table implementation) from extracting the set
-   * and iterating separately on potentially duplicate and copied data. The
-   * predicate function is provided two arguments:
-   *  - An iterating reference to each expression for the given operator.
-   *
-   * @param column The name of a column within this table.
-   * @param op The comparison or expression operator (e.g., EQUALS).
-   * @param predicate A predicate receiving each expression.
-   */
-  template <typename T>
-  void iteritems(const std::string& column,
-                 ConstraintOperator op,
-                 std::function<void(const T& expr)> predicate) const {
-    if (constraints.count(column) > 0) {
-      const auto& list = constraints.at(column);
-      if (list.affinity == TEXT_TYPE) {
-        for (const auto& constraint : list.constraints_) {
-          if (constraint.op == op) {
-            predicate(constraint.expr);
-          }
-        }
-      } else {
-        auto constraint_set = list.getAll<T>(op);
-        for (const auto& constraint : constraint_set) {
-          predicate(constraint);
-        }
-      }
-    }
-  }
-
-  /// Helper for string type (most all types are TEXT/VARCHAR).
-  void iteritems(const std::string& column,
-                 ConstraintOperator op,
-                 std::function<void(const std::string& expr)> predicate) const {
-    return iteritems<std::string>(column, op, std::move(predicate));
-  }
-
-  /**
-   * @brief Expand a list of constraints into a set of values.
-   *
-   * This is most (perhaps only) helpful with filesystem globbing inputs.
-   * The requirement is a constraint column that takes an expandable input.
-   * This method will accept an expand predicate and return the aggregate set of
-   * expanded items.
-   *
-   * In the future this will be a templated type that restricts the predicate
-   * to act on the column's affinite type and returns a similar-typed set.
-   *
-   * @param column The name of a column within this table.
-   * @param op An operator to retrieve from the constraint list.
-   * @param output The output parameter, a set of expanded values.
-   * @param predicate A predicate lambda to apply to each constraint.
-   * @return An aggregate status, if any predicate fails the operation fails.
-   */
-  Status expandConstraints(
-      const std::string& column,
-      ConstraintOperator op,
-      std::set<std::string>& output,
-      std::function<Status(const std::string& constraint,
-                           std::set<std::string>& output)> predicate);
-
-  /// Check if the given column is used by the query
-  bool isColumnUsed(const std::string& colName) const;
-
-  /// Check if any of the given columns is used by the query
-  bool isAnyColumnUsed(std::initializer_list<std::string> colNames) const;
-
-  inline bool isAnyColumnUsed(UsedColumnsBitset desiredBitset) const {
-    return !colsUsedBitset || (*colsUsedBitset & desiredBitset).any();
-  }
-
-  template <typename Type>
-  inline void setTextColumnIfUsed(Row& r,
-                                  const std::string& colName,
-                                  const Type& value) const {
-    if (isColumnUsed(colName)) {
-      r[colName] = TEXT(value);
-    }
-  }
-
-  template <typename Type>
-  inline void setIntegerColumnIfUsed(Row& r,
-                                     const std::string& colName,
-                                     const Type& value) const {
-    if (isColumnUsed(colName)) {
-      r[colName] = INTEGER(value);
-    }
-  }
-
-  template <typename Type>
-  inline void setBigIntColumnIfUsed(Row& r,
-                                    const std::string& colName,
-                                    const Type& value) const {
-    if (isColumnUsed(colName)) {
-      r[colName] = BIGINT(value);
-    }
-  }
-
-  inline void setColumnIfUsed(Row& r,
-                              const std::string& colName,
-                              const std::string& value) const {
-    if (isColumnUsed(colName)) {
-      r[colName] = value;
-    }
-  }
-
-  /// Check if a table-defined index exists within the query cache.
-  bool isCached(const std::string& index) const;
-
-  /// Retrieve an index within the query cache.
-  TableRowHolder getCache(const std::string& index);
-
-  /// Request the context use the warm query cache.
-  void useCache(bool use_cache);
-
-  /// Check if the query requested use of the warm query cache.
-  bool useCache() const;
-
-  /// Set the entire cache for an index.
-  void setCache(const std::string& index, const TableRowHolder& _cache);
-
-  /// The map of column name to constraint list.
-  ConstraintMap constraints;
-
-  boost::optional<UsedColumns> colsUsed;
-  boost::optional<UsedColumnsBitset> colsUsedBitset;
-
- private:
-  /// If false then the context is maintaining an ephemeral cache.
-  bool enable_cache_{false};
-
-  /// If the context is allowed to use the warm query cache.
-  bool use_cache_{false};
-
-  /// Persistent table content for table caching.
-  std::shared_ptr<VirtualTableContent> table_;
-
- private:
-  friend class TablePlugin;
+       /// Construct a context without cache support.
+       QueryContext()
+       {
+               table_ = std::make_shared<VirtualTableContent>();
+       }
+
+       /// If the context was created without content, it is ephemeral.
+       ~QueryContext() = default;
+
+       /// Construct a context and set the table content for caching.
+       explicit QueryContext(std::shared_ptr<VirtualTableContent> content)
+               : enable_cache_(true), table_(std::move(content)) {}
+
+       /// Disallow copying
+       QueryContext(const QueryContext&) = delete;
+
+       /// Disallow copy assignment.
+       QueryContext& operator=(const QueryContext&) = delete;
+
+       /// Allow moving.
+       QueryContext(QueryContext&& other)
+               : constraints(std::move(other.constraints)),
+                 colsUsed(std::move(other.colsUsed)),
+                 enable_cache_(other.enable_cache_),
+                 use_cache_(other.use_cache_),
+                 table_(other.table_)
+       {
+               other.enable_cache_ = false;
+               other.table_ = nullptr;
+       }
+
+       /// Allow move assignment.
+       QueryContext& operator=(QueryContext&& other)
+       {
+               std::swap(constraints, other.constraints);
+               std::swap(colsUsed, other.colsUsed);
+               std::swap(enable_cache_, other.enable_cache_);
+               std::swap(use_cache_, other.use_cache_);
+               std::swap(table_, other.table_);
+
+               return *this;
+       }
+
+       /**
+        * @brief Check if a constraint exists for a given column operator pair.
+        *
+        * Operator and expression existence and matching occurs on the constraint
+        * list for a given column name. The query context maintains a map of columns
+        * to potentially empty constraint lists. Check if a constraint exists with
+        * any operator or for a specific operator, usually equality (EQUALS).
+        *
+        * @param column The name of a column within this table.
+        * @param op Check for a specific constraint operator (default EQUALS).
+        * @return true if a constraint exists, false if empty or no operator match.
+        */
+       bool hasConstraint(const std::string& column,
+                                          ConstraintOperator op = EQUALS) const;
+
+       /**
+        * @brief Apply a predicate function to each expression in a constraint list.
+        *
+        * Most constraint sets are use to extract expressions or perform a row
+        * generation for each expressions (given an operator).
+        *
+        * This prevents the caller (table implementation) from extracting the set
+        * and iterating separately on potentially duplicate and copied data. The
+        * predicate function is provided two arguments:
+        *  - An iterating reference to each expression for the given operator.
+        *
+        * @param column The name of a column within this table.
+        * @param op The comparison or expression operator (e.g., EQUALS).
+        * @param predicate A predicate receiving each expression.
+        */
+       template <typename T>
+       void iteritems(const std::string& column,
+                                  ConstraintOperator op,
+                                  std::function<void(const T& expr)> predicate) const
+       {
+               if (constraints.count(column) > 0) {
+                       const auto& list = constraints.at(column);
+                       if (list.affinity == TEXT_TYPE) {
+                               for (const auto& constraint : list.constraints_) {
+                                       if (constraint.op == op) {
+                                               predicate(constraint.expr);
+                                       }
+                               }
+                       } else {
+                               auto constraint_set = list.getAll<T>(op);
+                               for (const auto& constraint : constraint_set) {
+                                       predicate(constraint);
+                               }
+                       }
+               }
+       }
+
+       /// Helper for string type (most all types are TEXT/VARCHAR).
+       void iteritems(const std::string& column,
+                                  ConstraintOperator op,
+                                  std::function<void(const std::string& expr)> predicate) const
+       {
+               return iteritems<std::string>(column, op, std::move(predicate));
+       }
+
+       /**
+        * @brief Expand a list of constraints into a set of values.
+        *
+        * This is most (perhaps only) helpful with filesystem globbing inputs.
+        * The requirement is a constraint column that takes an expandable input.
+        * This method will accept an expand predicate and return the aggregate set of
+        * expanded items.
+        *
+        * In the future this will be a templated type that restricts the predicate
+        * to act on the column's affinite type and returns a similar-typed set.
+        *
+        * @param column The name of a column within this table.
+        * @param op An operator to retrieve from the constraint list.
+        * @param output The output parameter, a set of expanded values.
+        * @param predicate A predicate lambda to apply to each constraint.
+        * @return An aggregate status, if any predicate fails the operation fails.
+        */
+       Status expandConstraints(
+               const std::string& column,
+               ConstraintOperator op,
+               std::set<std::string>& output,
+               std::function<Status(const std::string& constraint,
+                                                        std::set<std::string>& output)> predicate);
+
+       /// Check if the given column is used by the query
+       bool isColumnUsed(const std::string& colName) const;
+
+       /// Check if any of the given columns is used by the query
+       bool isAnyColumnUsed(std::initializer_list<std::string> colNames) const;
+
+       inline bool isAnyColumnUsed(UsedColumnsBitset desiredBitset) const
+       {
+               return !colsUsedBitset || (*colsUsedBitset & desiredBitset).any();
+       }
+
+       template <typename Type>
+       inline void setTextColumnIfUsed(Row& r,
+                                                                       const std::string& colName,
+                                                                       const Type& value) const
+       {
+               if (isColumnUsed(colName)) {
+                       r[colName] = TEXT(value);
+               }
+       }
+
+       template <typename Type>
+       inline void setIntegerColumnIfUsed(Row& r,
+                                                                          const std::string& colName,
+                                                                          const Type& value) const
+       {
+               if (isColumnUsed(colName)) {
+                       r[colName] = INTEGER(value);
+               }
+       }
+
+       template <typename Type>
+       inline void setBigIntColumnIfUsed(Row& r,
+                                                                         const std::string& colName,
+                                                                         const Type& value) const
+       {
+               if (isColumnUsed(colName)) {
+                       r[colName] = BIGINT(value);
+               }
+       }
+
+       inline void setColumnIfUsed(Row& r,
+                                                               const std::string& colName,
+                                                               const std::string& value) const
+       {
+               if (isColumnUsed(colName)) {
+                       r[colName] = value;
+               }
+       }
+
+       /// Check if a table-defined index exists within the query cache.
+       bool isCached(const std::string& index) const;
+
+       /// Retrieve an index within the query cache.
+       TableRowHolder getCache(const std::string& index);
+
+       /// Request the context use the warm query cache.
+       void useCache(bool use_cache);
+
+       /// Check if the query requested use of the warm query cache.
+       bool useCache() const;
+
+       /// Set the entire cache for an index.
+       void setCache(const std::string& index, const TableRowHolder& _cache);
+
+       /// The map of column name to constraint list.
+       ConstraintMap constraints;
+
+       boost::optional<UsedColumns> colsUsed;
+       boost::optional<UsedColumnsBitset> colsUsedBitset;
+
+private:
+       /// If false then the context is maintaining an ephemeral cache.
+       bool enable_cache_{false};
+
+       /// If the context is allowed to use the warm query cache.
+       bool use_cache_{false};
+
+       /// Persistent table content for table caching.
+       std::shared_ptr<VirtualTableContent> table_;
+
+private:
+       friend class TablePlugin;
 };
 
 using QueryContext = struct QueryContext;
@@ -657,235 +683,245 @@ using Constraint = struct Constraint;
  * in osquery/tables/templates/default.cpp.in
  */
 class TablePlugin : public Plugin {
- public:
-  /**
-   * @brief Table name aliases create full-scan VIEWs for tables.
-   *
-   * Aliases allow table names to be changed/deprecated without breaking
-   * existing deployments and scheduled queries.
-   *
-   * @return A string vector of qtable name aliases.
-   */
-  virtual std::vector<std::string> aliases() const {
-    return {};
-  }
-
-  /// Return the table's column name and type pairs.
-  virtual TableColumns columns() const {
-    return TableColumns();
-  }
-
-  /// Define a map of target columns to optional aliases.
-  virtual ColumnAliasSet columnAliases() const {
-    return ColumnAliasSet();
-  }
-
-  /// Define a map of aliases to canoical columns
-  virtual AliasColumnMap aliasedColumns() const {
-    AliasColumnMap result;
-    ColumnAliasSet aliases = columnAliases();
-
-    for (const auto& columnAliases : aliases) {
-      const auto& columnName = columnAliases.first;
-      for (const auto& alias : columnAliases.second) {
-        result[alias] = columnName;
-      }
-    }
-
-    return AliasColumnMap();
-  }
-
-  /// Return a set of attribute flags.
-  virtual TableAttributes attributes() const {
-    return TableAttributes::NONE;
-  }
-
-  /**
-   * @brief Generate a complete table representation.
-   *
-   * The TablePlugin::generate method is the most important part of the table.
-   * This should return a best-effort match of the expected results for a
-   * query. In common cases, this returns all rows for a virtual table.
-   * For EventSubscriber tables this will perform database lookups for events
-   * matching several conditions such as time within the SQL query or the last
-   * time the EventSubscriber was called.
-   *
-   * The context input is filled in "as best possible" by SQLite's
-   * virtual table APIs. In the best case this context include a limit or
-   * constraints organized by each possible column.
-   *
-   * @param context A query context filled in by SQLite's virtual table API.
-   * @return The result rows for this table, given the query context.
-   */
-  virtual TableRows generate(QueryContext& context) {
-    (void)context;
-    return TableRows();
-  }
-
-  /// Callback for DELETE statements
-  virtual QueryData delete_(QueryContext& context,
-                            const PluginRequest& request) {
-    boost::ignore_unused(context);
-    boost::ignore_unused(request);
-
-    return {{std::make_pair("status", "readonly")}};
-  }
-
-  /// Callback for INSERT statements
-  virtual QueryData insert(QueryContext& context,
-                           const PluginRequest& request) {
-    boost::ignore_unused(context);
-    boost::ignore_unused(request);
-
-    return {{std::make_pair("status", "readonly")}};
-  }
-
-  /// Callback for UPDATE statements
-  virtual QueryData update(QueryContext& context,
-                           const PluginRequest& request) {
-    boost::ignore_unused(context);
-    boost::ignore_unused(request);
-
-    return {{std::make_pair("status", "readonly")}};
-  }
-
- protected:
-  /// An SQL table containing the table definition/syntax.
-  std::string columnDefinition(bool is_extension = false) const;
-
-  /// Return the name and column pairs for attaching virtual tables.
-  PluginResponse routeInfo() const override;
-
-  /**
-   * @brief Check if there are fresh cache results for this table.
-   *
-   * Table results are considered fresh when evaluated against a given interval.
-   * The interval is the expected rate for which this data should be generated.
-   * Caching and cache freshness only applies to queries acting on tables
-   * within a schedule. If two queries "one" and "two" both inspect the
-   * table "processes" at the interval 60. The first executed will cache results
-   * and the second will use the cached results.
-   *
-   * Table results are not cached if a QueryContext contains constraints or
-   * provides HOB (hand-off blocks) to additional tables within a query.
-   * Currently, the query scheduler cannot communicate to table implementations.
-   * An interval is set globally by the scheduler and passed to the table
-   * implementation as a future-proof API. There is no "shortcut" for caching
-   * when used in external tables. A cache lookup within an extension means
-   * a database call API and re-serialization to the virtual table APIs. In
-   * practice this does not perform well and is explicitly disabled.
-   *
-   * @param interval The interval this query expects the tables results.
-   * @param ctx The query context.
-   * @return True if the cache contains fresh results, otherwise false.
-   */
-  bool isCached(size_t interval, const QueryContext& ctx) const;
-
-  /**
-   * @brief Perform a database lookup of cached results and deserialize.
-   *
-   * If a query determined the table's cached results are fresh, it may ask the
-   * table to retrieve results from the database and deserialized them into
-   * table row data.
-   *
-   * @return The deserialized row data of cached results.
-   */
-  TableRows getCache() const;
-
-  /**
-   * @brief Similar to getCache, stores the results from generate.
-   *
-   * Set will serialize and save the results as JSON to be retrieved later.
-   * It will inspect the query context, if any required/indexed/optimized or
-   * additional columns are used then the cache will not be saved.
-   */
-  void setCache(size_t step,
-                size_t interval,
-                const QueryContext& ctx,
-                const TableRows& results);
-
- private:
-  /// The last time in seconds the table data results were saved to cache.
-  size_t last_cached_{0};
-
-  /// The last interval in seconds when the table data was cached.
-  size_t last_interval_{0};
-
- public:
-  /**
-   * @brief The scheduled interval for the executing query.
-   *
-   * Scheduled queries execute within a pseudo-mutex, and each may communicate
-   * their scheduled interval to internal TablePlugin implementations. If the
-   * table is cachable then the interval can be used to calculate freshness.
-   */
-  static size_t kCacheInterval;
-
-  /// The schedule step, this is the current position of the schedule.
-  static size_t kCacheStep;
-
- public:
-  /**
-   * @brief The registry call "router".
-   *
-   * Like all of osquery's Plugin%s, the TablePlugin uses a "call" router to
-   * handle requests and responses from extensions. The TablePlugin uses an
-   * "action" key, which can be:
-   *   - generate: call the plugin's row generate method (defined in spec).
-   *   - columns: return a list of column name and SQLite types.
-   *   - definition: return an SQL statement for table creation.
-   *
-   * @param request The plugin request, must include an action key.
-   * @param response A plugin response, for generation this contains the rows.
-   */
-  Status call(const PluginRequest& request, PluginResponse& response) override;
-
- public:
-  /// Helper data structure transformation methods.
-  static void setRequestFromContext(const QueryContext& context,
-                                    PluginRequest& request);
-
- public:
-  /**
-   * @brief Add a virtual table that exists in an extension.
-   *
-   * When external table plugins are registered the core will attach them
-   * as virtual tables to the SQL internal implementation.
-   *
-   * @param name The table name.
-   * @param info The route info (column name and type pairs).
-   */
-  static Status addExternal(const std::string& name,
-                            const PluginResponse& info);
-
-  /// Remove an extension's table from the SQL virtual database.
-  static void removeExternal(const std::string& name);
-
- private:
-  /// Helper data structure transformation methods.
-  QueryContext getContextFromRequest(const PluginRequest& request) const;
-
-  UsedColumnsBitset usedColumnsToBitset(const UsedColumns usedColumns) const;
-  friend class RegistryFactory;
-  FRIEND_TEST(VirtualTableTests, test_tableplugin_columndefinition);
-  FRIEND_TEST(VirtualTableTests, test_tableplugin_statement);
-  FRIEND_TEST(VirtualTableTests, test_indexing_costs);
-  FRIEND_TEST(VirtualTableTests, test_table_results_cache);
-  FRIEND_TEST(VirtualTableTests, test_yield_generator);
+public:
+       /**
+        * @brief Table name aliases create full-scan VIEWs for tables.
+        *
+        * Aliases allow table names to be changed/deprecated without breaking
+        * existing deployments and scheduled queries.
+        *
+        * @return A string vector of qtable name aliases.
+        */
+       virtual std::vector<std::string> aliases() const
+       {
+               return {};
+       }
+
+       /// Return the table's column name and type pairs.
+       virtual TableColumns columns() const
+       {
+               return TableColumns();
+       }
+
+       /// Define a map of target columns to optional aliases.
+       virtual ColumnAliasSet columnAliases() const
+       {
+               return ColumnAliasSet();
+       }
+
+       /// Define a map of aliases to canoical columns
+       virtual AliasColumnMap aliasedColumns() const
+       {
+               AliasColumnMap result;
+               ColumnAliasSet aliases = columnAliases();
+
+               for (const auto& columnAliases : aliases) {
+                       const auto& columnName = columnAliases.first;
+                       for (const auto& alias : columnAliases.second) {
+                               result[alias] = columnName;
+                       }
+               }
+
+               return AliasColumnMap();
+       }
+
+       /// Return a set of attribute flags.
+       virtual TableAttributes attributes() const
+       {
+               return TableAttributes::NONE;
+       }
+
+       /**
+        * @brief Generate a complete table representation.
+        *
+        * The TablePlugin::generate method is the most important part of the table.
+        * This should return a best-effort match of the expected results for a
+        * query. In common cases, this returns all rows for a virtual table.
+        * For EventSubscriber tables this will perform database lookups for events
+        * matching several conditions such as time within the SQL query or the last
+        * time the EventSubscriber was called.
+        *
+        * The context input is filled in "as best possible" by SQLite's
+        * virtual table APIs. In the best case this context include a limit or
+        * constraints organized by each possible column.
+        *
+        * @param context A query context filled in by SQLite's virtual table API.
+        * @return The result rows for this table, given the query context.
+        */
+       virtual TableRows generate(QueryContext& context)
+       {
+               (void)context;
+               return TableRows();
+       }
+
+       /// Callback for DELETE statements
+       virtual QueryData delete_(QueryContext& context,
+                                                         const PluginRequest& request)
+       {
+               boost::ignore_unused(context);
+               boost::ignore_unused(request);
+
+               return {{std::make_pair("status", "readonly")}};
+       }
+
+       /// Callback for INSERT statements
+       virtual QueryData insert(QueryContext& context,
+                                                        const PluginRequest& request)
+       {
+               boost::ignore_unused(context);
+               boost::ignore_unused(request);
+
+               return {{std::make_pair("status", "readonly")}};
+       }
+
+       /// Callback for UPDATE statements
+       virtual QueryData update(QueryContext& context,
+                                                        const PluginRequest& request)
+       {
+               boost::ignore_unused(context);
+               boost::ignore_unused(request);
+
+               return {{std::make_pair("status", "readonly")}};
+       }
+
+protected:
+       /// An SQL table containing the table definition/syntax.
+       std::string columnDefinition(bool is_extension = false) const;
+
+       /// Return the name and column pairs for attaching virtual tables.
+       PluginResponse routeInfo() const override;
+
+       /**
+        * @brief Check if there are fresh cache results for this table.
+        *
+        * Table results are considered fresh when evaluated against a given interval.
+        * The interval is the expected rate for which this data should be generated.
+        * Caching and cache freshness only applies to queries acting on tables
+        * within a schedule. If two queries "one" and "two" both inspect the
+        * table "processes" at the interval 60. The first executed will cache results
+        * and the second will use the cached results.
+        *
+        * Table results are not cached if a QueryContext contains constraints or
+        * provides HOB (hand-off blocks) to additional tables within a query.
+        * Currently, the query scheduler cannot communicate to table implementations.
+        * An interval is set globally by the scheduler and passed to the table
+        * implementation as a future-proof API. There is no "shortcut" for caching
+        * when used in external tables. A cache lookup within an extension means
+        * a database call API and re-serialization to the virtual table APIs. In
+        * practice this does not perform well and is explicitly disabled.
+        *
+        * @param interval The interval this query expects the tables results.
+        * @param ctx The query context.
+        * @return True if the cache contains fresh results, otherwise false.
+        */
+       bool isCached(size_t interval, const QueryContext& ctx) const;
+
+       /**
+        * @brief Perform a database lookup of cached results and deserialize.
+        *
+        * If a query determined the table's cached results are fresh, it may ask the
+        * table to retrieve results from the database and deserialized them into
+        * table row data.
+        *
+        * @return The deserialized row data of cached results.
+        */
+       TableRows getCache() const;
+
+       /**
+        * @brief Similar to getCache, stores the results from generate.
+        *
+        * Set will serialize and save the results as JSON to be retrieved later.
+        * It will inspect the query context, if any required/indexed/optimized or
+        * additional columns are used then the cache will not be saved.
+        */
+       void setCache(size_t step,
+                                 size_t interval,
+                                 const QueryContext& ctx,
+                                 const TableRows& results);
+
+private:
+       /// The last time in seconds the table data results were saved to cache.
+       size_t last_cached_{0};
+
+       /// The last interval in seconds when the table data was cached.
+       size_t last_interval_{0};
+
+public:
+       /**
+        * @brief The scheduled interval for the executing query.
+        *
+        * Scheduled queries execute within a pseudo-mutex, and each may communicate
+        * their scheduled interval to internal TablePlugin implementations. If the
+        * table is cachable then the interval can be used to calculate freshness.
+        */
+       static size_t kCacheInterval;
+
+       /// The schedule step, this is the current position of the schedule.
+       static size_t kCacheStep;
+
+public:
+       /**
+        * @brief The registry call "router".
+        *
+        * Like all of osquery's Plugin%s, the TablePlugin uses a "call" router to
+        * handle requests and responses from extensions. The TablePlugin uses an
+        * "action" key, which can be:
+        *   - generate: call the plugin's row generate method (defined in spec).
+        *   - columns: return a list of column name and SQLite types.
+        *   - definition: return an SQL statement for table creation.
+        *
+        * @param request The plugin request, must include an action key.
+        * @param response A plugin response, for generation this contains the rows.
+        */
+       Status call(const PluginRequest& request, PluginResponse& response) override;
+
+public:
+       /// Helper data structure transformation methods.
+       static void setRequestFromContext(const QueryContext& context,
+                                                                         PluginRequest& request);
+
+public:
+       /**
+        * @brief Add a virtual table that exists in an extension.
+        *
+        * When external table plugins are registered the core will attach them
+        * as virtual tables to the SQL internal implementation.
+        *
+        * @param name The table name.
+        * @param info The route info (column name and type pairs).
+        */
+       static Status addExternal(const std::string& name,
+                                                         const PluginResponse& info);
+
+       /// Remove an extension's table from the SQL virtual database.
+       static void removeExternal(const std::string& name);
+
+private:
+       /// Helper data structure transformation methods.
+       QueryContext getContextFromRequest(const PluginRequest& request) const;
+
+       UsedColumnsBitset usedColumnsToBitset(const UsedColumns usedColumns) const;
+       friend class RegistryFactory;
+       FRIEND_TEST(VirtualTableTests, test_tableplugin_columndefinition);
+       FRIEND_TEST(VirtualTableTests, test_tableplugin_statement);
+       FRIEND_TEST(VirtualTableTests, test_indexing_costs);
+       FRIEND_TEST(VirtualTableTests, test_table_results_cache);
+       FRIEND_TEST(VirtualTableTests, test_yield_generator);
 };
 
 /// Helper method to generate the virtual table CREATE statement.
 std::string columnDefinition(const TableColumns& columns,
-                             bool is_extension = false);
+                                                        bool is_extension = false);
 
 /// Helper method to generate the virtual table CREATE statement.
 std::string columnDefinition(const PluginResponse& response,
-                             bool aliases = false,
-                             bool is_extension = false);
+                                                        bool aliases = false,
+                                                        bool is_extension = false);
 
 /// Get the string representation for an SQLite column type.
-inline const std::string& columnTypeName(ColumnType type) {
-  return kColumnTypeNames.at(type);
+inline const std::string& columnTypeName(ColumnType type)
+{
+       return kColumnTypeNames.at(type);
 }
 
 /// Get the column type from the string representation.
index fb2acff093f6ffc99a72f0b59331ac4f514996d0..8b64ece6410faa1103b653e91944b184582b14c5 100644 (file)
 
 namespace osquery {
 
-RegistryFactory& RegistryFactory::get() {
-  static RegistryFactory instance;
-  return instance;
+RegistryFactory& RegistryFactory::get()
+{
+       static RegistryFactory instance;
+       return instance;
 }
 
-void RegistryFactory::add(const std::string& name, RegistryInterfaceRef reg) {
-  if (exists(name)) {
-    throw std::runtime_error("Cannot add duplicate registry: " + name);
-  }
-  registries_[name] = std::move(reg);
+void RegistryFactory::add(const std::string& name, RegistryInterfaceRef reg)
+{
+       if (exists(name)) {
+               throw std::runtime_error("Cannot add duplicate registry: " + name);
+       }
+       registries_[name] = std::move(reg);
 }
 
-RegistryInterfaceRef RegistryFactory::registry(const std::string& t) const {
-  if (!exists(t)) {
-    throw std::runtime_error("Unknown registry requested: " + t);
-  }
-  return registries_.at(t);
+RegistryInterfaceRef RegistryFactory::registry(const std::string& t) const
+{
+       if (!exists(t)) {
+               throw std::runtime_error("Unknown registry requested: " + t);
+       }
+       return registries_.at(t);
 }
 
-std::map<std::string, RegistryInterfaceRef> RegistryFactory::all() const {
-  return registries_;
+std::map<std::string, RegistryInterfaceRef> RegistryFactory::all() const
+{
+       return registries_;
 }
 
 std::map<std::string, PluginRef> RegistryFactory::plugins(
-    const std::string& registry_name) const {
-  return registry(registry_name)->plugins();
+       const std::string& registry_name) const
+{
+       return registry(registry_name)->plugins();
 }
 
 PluginRef RegistryFactory::plugin(const std::string& registry_name,
-                                  const std::string& item_name) const {
-  return registry(registry_name)->plugin(item_name);
+                                                                 const std::string& item_name) const
+{
+       return registry(registry_name)->plugin(item_name);
 }
 
 /// Adds an alias for an internal registry item. This registry will only
 /// broadcast the alias name.
 Status RegistryFactory::addAlias(const std::string& registry_name,
-                                 const std::string& item_name,
-                                 const std::string& alias) {
-  if (!exists(registry_name)) {
-    return Status(1, "Unknown registry: " + registry_name);
-  }
-  return registries_.at(registry_name)->addAlias(item_name, alias);
+                                                                const std::string& item_name,
+                                                                const std::string& alias)
+{
+       if (!exists(registry_name)) {
+               return Status(1, "Unknown registry: " + registry_name);
+       }
+       return registries_.at(registry_name)->addAlias(item_name, alias);
 }
 
 /// Returns the item_name or the item alias if an alias exists.
 std::string RegistryFactory::getAlias(const std::string& registry_name,
-                                      const std::string& alias) const {
-  if (!exists(registry_name)) {
-    return alias;
-  }
-  return registries_.at(registry_name)->getAlias(alias);
+                                                                         const std::string& alias) const
+{
+       if (!exists(registry_name)) {
+               return alias;
+       }
+       return registries_.at(registry_name)->getAlias(alias);
 }
 
 Status RegistryFactory::call(const std::string& registry_name,
-                             const std::string& item_name,
-                             const PluginRequest& request,
-                             PluginResponse& response) {
-  // Forward factory call to the registry.
-  try {
-    if (item_name.find(',') != std::string::npos) {
-      // Call is multiplexing plugins (usually for multiple loggers).
-      for (const auto& item : osquery::split(item_name, ",")) {
-        get().registry(registry_name)->call(item, request, response);
-      }
-      // All multiplexed items are called without regard for statuses.
-      return Status(0);
-    }
-    return get().registry(registry_name)->call(item_name, request, response);
-  } catch (const std::exception& e) {
-    ERROR(OSQUERY) << registry_name << " registry " << item_name
-               << " plugin caused exception: " << e.what();
-    return Status(1, e.what());
-  } catch (...) {
-    ERROR(OSQUERY) << registry_name << " registry " << item_name
-               << " plugin caused unknown exception";
-    return Status(2, "Unknown exception");
-  }
+                                                        const std::string& item_name,
+                                                        const PluginRequest& request,
+                                                        PluginResponse& response)
+{
+       // Forward factory call to the registry.
+       try {
+               if (item_name.find(',') != std::string::npos) {
+                       // Call is multiplexing plugins (usually for multiple loggers).
+                       for (const auto& item : osquery::split(item_name, ",")) {
+                               get().registry(registry_name)->call(item, request, response);
+                       }
+                       // All multiplexed items are called without regard for statuses.
+                       return Status(0);
+               }
+               return get().registry(registry_name)->call(item_name, request, response);
+       } catch (const std::exception& e) {
+               ERROR(OSQUERY) << registry_name << " registry " << item_name
+                                          << " plugin caused exception: " << e.what();
+               return Status(1, e.what());
+       } catch (...) {
+               ERROR(OSQUERY) << registry_name << " registry " << item_name
+                                          << " plugin caused unknown exception";
+               return Status(2, "Unknown exception");
+       }
 }
 
 Status RegistryFactory::call(const std::string& registry_name,
-                             const std::string& item_name,
-                             const PluginRequest& request) {
-  PluginResponse response;
-  // Wrapper around a call expecting a response.
-  return call(registry_name, item_name, request, response);
+                                                        const std::string& item_name,
+                                                        const PluginRequest& request)
+{
+       PluginResponse response;
+       // Wrapper around a call expecting a response.
+       return call(registry_name, item_name, request, response);
 }
 
 Status RegistryFactory::call(const std::string& registry_name,
-                             const PluginRequest& request,
-                             PluginResponse& response) {
-  auto plugin = get().registry(registry_name)->getActive();
-  return call(registry_name, plugin, request, response);
+                                                        const PluginRequest& request,
+                                                        PluginResponse& response)
+{
+       auto plugin = get().registry(registry_name)->getActive();
+       return call(registry_name, plugin, request, response);
 }
 
 Status RegistryFactory::call(const std::string& registry_name,
-                             const PluginRequest& request) {
-  PluginResponse response;
-  return call(registry_name, request, response);
+                                                        const PluginRequest& request)
+{
+       PluginResponse response;
+       return call(registry_name, request, response);
 }
 
 Status RegistryFactory::setActive(const std::string& registry_name,
-                                  const std::string& item_name) {
-  WriteLock lock(mutex_);
-  return registry(registry_name)->setActive(item_name);
+                                                                 const std::string& item_name)
+{
+       WriteLock lock(mutex_);
+       return registry(registry_name)->setActive(item_name);
 }
 
-std::string RegistryFactory::getActive(const std::string& registry_name) const {
-  return registry(registry_name)->getActive();
+std::string RegistryFactory::getActive(const std::string& registry_name) const
+{
+       return registry(registry_name)->getActive();
 }
 
-void RegistryFactory::setUp() {
-  for (const auto& registry : get().all()) {
-    registry.second->setUp();
-  }
+void RegistryFactory::setUp()
+{
+       for (const auto& registry : get().all()) {
+               registry.second->setUp();
+       }
 }
 
 bool RegistryFactory::exists(const std::string& registry_name,
-                             const std::string& item_name,
-                             bool local) const {
-  if (!exists(registry_name)) {
-    return false;
-  }
+                                                        const std::string& item_name,
+                                                        bool local) const
+{
+       if (!exists(registry_name)) {
+               return false;
+       }
 
-  // Check the registry.
-  return registry(registry_name)->exists(item_name, local);
+       // Check the registry.
+       return registry(registry_name)->exists(item_name, local);
 }
 
-std::vector<std::string> RegistryFactory::names() const {
-  std::vector<std::string> names;
-  for (const auto& registry : all()) {
-    names.push_back(registry.second->getName());
-  }
-  return names;
+std::vector<std::string> RegistryFactory::names() const
+{
+       std::vector<std::string> names;
+       for (const auto& registry : all()) {
+               names.push_back(registry.second->getName());
+       }
+       return names;
 }
 
 std::vector<std::string> RegistryFactory::names(
-    const std::string& registry_name) const {
-  if (registries_.at(registry_name) == nullptr) {
-    std::vector<std::string> names;
-    return names;
-  }
-  return registry(registry_name)->names();
-}
-
-size_t RegistryFactory::count(const std::string& registry_name) const {
-  if (!exists(registry_name)) {
-    return 0;
-  }
-  return registry(registry_name)->count();
+       const std::string& registry_name) const
+{
+       if (registries_.at(registry_name) == nullptr) {
+               std::vector<std::string> names;
+               return names;
+       }
+       return registry(registry_name)->names();
+}
+
+size_t RegistryFactory::count(const std::string& registry_name) const
+{
+       if (!exists(registry_name)) {
+               return 0;
+       }
+       return registry(registry_name)->count();
 }
 
 } // namespace osquery
index ddacdee3b1d233f613c047963a39c768de602398..8205aa7eee769d28bb5f3b0da69e094b3d448462 100644 (file)
 #include <osquery/utils/conversions/split.h>
 
 namespace osquery {
-void RegistryInterface::remove(const std::string& item_name) {
-  if (items_.count(item_name) > 0) {
-    items_[item_name]->tearDown();
-    items_.erase(item_name);
-  }
-
-  // Populate list of aliases to remove (those that mask item_name).
-  std::vector<std::string> removed_aliases;
-  for (const auto& alias : aliases_) {
-    if (alias.second == item_name) {
-      removed_aliases.push_back(alias.first);
-    }
-  }
-
-  for (const auto& alias : removed_aliases) {
-    aliases_.erase(alias);
-  }
+void RegistryInterface::remove(const std::string& item_name)
+{
+       if (items_.count(item_name) > 0) {
+               items_[item_name]->tearDown();
+               items_.erase(item_name);
+       }
+
+       // Populate list of aliases to remove (those that mask item_name).
+       std::vector<std::string> removed_aliases;
+       for (const auto& alias : aliases_) {
+               if (alias.second == item_name) {
+                       removed_aliases.push_back(alias.first);
+               }
+       }
+
+       for (const auto& alias : removed_aliases) {
+               aliases_.erase(alias);
+       }
 }
 
-bool RegistryInterface::isInternal(const std::string& item_name) const {
-  ReadLock lock(mutex_);
+bool RegistryInterface::isInternal(const std::string& item_name) const
+{
+       ReadLock lock(mutex_);
 
-  return isInternal_(item_name);
+       return isInternal_(item_name);
 }
 
-std::string RegistryInterface::getActive() const {
-  ReadLock lock(mutex_);
+std::string RegistryInterface::getActive() const
+{
+       ReadLock lock(mutex_);
 
-  return active_;
+       return active_;
 }
 
-std::string RegistryInterface::getName() const {
-  ReadLock lock(mutex_);
+std::string RegistryInterface::getName() const
+{
+       ReadLock lock(mutex_);
 
-  return name_;
+       return name_;
 }
 
-size_t RegistryInterface::count() const {
-  ReadLock lock(mutex_);
+size_t RegistryInterface::count() const
+{
+       ReadLock lock(mutex_);
 
-  return items_.size();
+       return items_.size();
 }
 
-Status RegistryInterface::setActive(const std::string& item_name) {
-// FIXME
-//  UpgradeLock lock(mutex_);
-
-  // Default support multiple active plugins.
-  for (const auto& item : osquery::split(item_name, ",")) {
-    if (items_.count(item) == 0) {
-      return Status::failure("Unknown registry plugin: " + item);
-    }
-  }
-
-  Status status;
-  {
-// FIXME
-//    WriteUpgradeLock wlock(lock);
-    active_ = item_name;
-  }
-
-  // The active plugin is setup when initialized.
-  for (const auto& item : osquery::split(item_name, ",")) {
-    if (exists_(item, true)) {
-      status = RegistryFactory::get().plugin(name_, item)->setUp();
-    }
-
-    if (!status.ok()) {
-      break;
-    }
-  }
-  return status;
+Status RegistryInterface::setActive(const std::string& item_name)
+{
+       // FIXME
+       //  UpgradeLock lock(mutex_);
+
+       // Default support multiple active plugins.
+       for (const auto& item : osquery::split(item_name, ",")) {
+               if (items_.count(item) == 0) {
+                       return Status::failure("Unknown registry plugin: " + item);
+               }
+       }
+
+       Status status;
+       {
+               // FIXME
+               //    WriteUpgradeLock wlock(lock);
+               active_ = item_name;
+       }
+
+       // The active plugin is setup when initialized.
+       for (const auto& item : osquery::split(item_name, ",")) {
+               if (exists_(item, true)) {
+                       status = RegistryFactory::get().plugin(name_, item)->setUp();
+               }
+
+               if (!status.ok()) {
+                       break;
+               }
+       }
+       return status;
 }
 
 Status RegistryInterface::call(const std::string& item_name,
-                               const PluginRequest& request,
-                               PluginResponse& response) {
-  if (item_name.empty()) {
-    return Status::failure("No registry item name specified");
-  }
-  PluginRef plugin;
-  {
-    ReadLock lock(mutex_);
-
-    // Search local plugins (items) for the plugin.
-    if (items_.count(item_name) > 0) {
-      plugin = items_.at(item_name);
-    }
-  }
-  if (plugin) {
-    return plugin->call(request, response);
-  }
-
-  return Status::failure("Unknown registry name: " + item_name);
+                                                          const PluginRequest& request,
+                                                          PluginResponse& response)
+{
+       if (item_name.empty()) {
+               return Status::failure("No registry item name specified");
+       }
+       PluginRef plugin;
+       {
+               ReadLock lock(mutex_);
+
+               // Search local plugins (items) for the plugin.
+               if (items_.count(item_name) > 0) {
+                       plugin = items_.at(item_name);
+               }
+       }
+       if (plugin) {
+               return plugin->call(request, response);
+       }
+
+       return Status::failure("Unknown registry name: " + item_name);
 }
 
 Status RegistryInterface::addAlias(const std::string& item_name,
-                                   const std::string& alias) {
-  WriteLock lock(mutex_);
-
-  if (aliases_.count(alias) > 0) {
-    return Status::failure("Duplicate alias: " + alias);
-  }
-  aliases_[alias] = item_name;
-  return Status::success();
+                                                                  const std::string& alias)
+{
+       WriteLock lock(mutex_);
+
+       if (aliases_.count(alias) > 0) {
+               return Status::failure("Duplicate alias: " + alias);
+       }
+       aliases_[alias] = item_name;
+       return Status::success();
 }
 
-std::string RegistryInterface::getAlias(const std::string& alias) const {
-  ReadLock lock(mutex_);
+std::string RegistryInterface::getAlias(const std::string& alias) const
+{
+       ReadLock lock(mutex_);
 
-  if (aliases_.count(alias) == 0) {
-    return alias;
-  }
-  return aliases_.at(alias);
+       if (aliases_.count(alias) == 0) {
+               return alias;
+       }
+       return aliases_.at(alias);
 }
 
 Status RegistryInterface::addPlugin(const std::string& plugin_name,
-                                    const PluginRef& plugin_item,
-                                    bool internal) {
-  WriteLock lock(mutex_);
+                                                                       const PluginRef& plugin_item,
+                                                                       bool internal)
+{
+       WriteLock lock(mutex_);
 
-  if (items_.count(plugin_name) > 0) {
-    return Status::failure("Duplicate registry item exists: " + plugin_name);
-  }
+       if (items_.count(plugin_name) > 0) {
+               return Status::failure("Duplicate registry item exists: " + plugin_name);
+       }
 
-  plugin_item->setName(plugin_name);
-  items_.emplace(std::make_pair(plugin_name, plugin_item));
+       plugin_item->setName(plugin_name);
+       items_.emplace(std::make_pair(plugin_name, plugin_item));
 
-  // The item can be listed as internal, meaning it does not broadcast.
-  if (internal) {
-    internal_.push_back(plugin_name);
-  }
+       // The item can be listed as internal, meaning it does not broadcast.
+       if (internal) {
+               internal_.push_back(plugin_name);
+       }
 
-  return Status::success();
+       return Status::success();
 }
 
-void RegistryInterface::setUp() {
-  ReadLock lock(mutex_);
-
-  // If this registry does not auto-setup do NOT setup the registry items.
-  if (!auto_setup_) {
-    return;
-  }
-
-  // If the registry is using a single 'active' plugin, setUp that plugin.
-  // For config and logger, only setUp the selected plugin.
-  if (active_.size() != 0 && exists_(active_, true)) {
-    items_.at(active_)->setUp();
-    return;
-  }
-
-  // Try to set up each of the registry items.
-  // If they fail, remove them from the registry.
-  std::vector<std::string> failed;
-  for (auto& item : items_) {
-    if (!item.second->setUp().ok()) {
-      failed.push_back(item.first);
-    }
-  }
-
-  for (const auto& failed_item : failed) {
-    remove(failed_item);
-  }
+void RegistryInterface::setUp()
+{
+       ReadLock lock(mutex_);
+
+       // If this registry does not auto-setup do NOT setup the registry items.
+       if (!auto_setup_) {
+               return;
+       }
+
+       // If the registry is using a single 'active' plugin, setUp that plugin.
+       // For config and logger, only setUp the selected plugin.
+       if (active_.size() != 0 && exists_(active_, true)) {
+               items_.at(active_)->setUp();
+               return;
+       }
+
+       // Try to set up each of the registry items.
+       // If they fail, remove them from the registry.
+       std::vector<std::string> failed;
+       for (auto& item : items_) {
+               if (!item.second->setUp().ok()) {
+                       failed.push_back(item.first);
+               }
+       }
+
+       for (const auto& failed_item : failed) {
+               remove(failed_item);
+       }
 }
 
-void RegistryInterface::configure() {
-  ReadLock lock(mutex_);
-
-  if (!active_.empty() && exists_(active_, true)) {
-    items_.at(active_)->configure();
-  } else {
-    for (auto& item : items_) {
-      item.second->configure();
-    }
-  }
+void RegistryInterface::configure()
+{
+       ReadLock lock(mutex_);
+
+       if (!active_.empty() && exists_(active_, true)) {
+               items_.at(active_)->configure();
+       } else {
+               for (auto& item : items_) {
+                       item.second->configure();
+               }
+       }
 }
 
 /// Facility method to check if a registry item exists.
-bool RegistryInterface::exists(const std::string& item_name, bool local) const {
-  ReadLock lock(mutex_);
+bool RegistryInterface::exists(const std::string& item_name, bool local) const
+{
+       ReadLock lock(mutex_);
 
-  return exists_(item_name, local);
+       return exists_(item_name, local);
 }
 
 /// Facility method to list the registry item identifiers.
-std::vector<std::string> RegistryInterface::names() const {
-  ReadLock lock(mutex_);
+std::vector<std::string> RegistryInterface::names() const
+{
+       ReadLock lock(mutex_);
 
-  std::vector<std::string> names;
-  for (const auto& item : items_) {
-    names.push_back(item.first);
-  }
+       std::vector<std::string> names;
+       for (const auto& item : items_) {
+               names.push_back(item.first);
+       }
 
-  return names;
+       return names;
 }
 
-std::map<std::string, PluginRef> RegistryInterface::plugins() {
-  ReadLock lock(mutex_);
+std::map<std::string, PluginRef> RegistryInterface::plugins()
+{
+       ReadLock lock(mutex_);
 
-  return items_;
+       return items_;
 }
 
-void RegistryInterface::setname(const std::string& name) {
-  WriteLock lock(mutex_);
+void RegistryInterface::setname(const std::string& name)
+{
+       WriteLock lock(mutex_);
 
-  name_ = name;
+       name_ = name;
 }
 
-bool RegistryInterface::isInternal_(const std::string& item_name) const {
-  if (std::find(internal_.begin(), internal_.end(), item_name) ==
-      internal_.end()) {
-    return false;
-  }
-  return true;
+bool RegistryInterface::isInternal_(const std::string& item_name) const
+{
+       if (std::find(internal_.begin(), internal_.end(), item_name) ==
+               internal_.end()) {
+               return false;
+       }
+       return true;
 }
 
 bool RegistryInterface::exists_(const std::string& item_name,
-                                bool local) const {
-  return (items_.count(item_name) > 0);
+                                                               bool local) const
+{
+       return (items_.count(item_name) > 0);
 }
 
 AutoRegisterInterface::AutoRegisterInterface(const char* _type,
-                                             const char* _name,
-                                             bool optional)
-    : type_(_type), name_(_name), optional_(optional) {}
-
-AutoRegisterSet& AutoRegisterInterface::registries() {
-  static AutoRegisterSet registries_;
-  return registries_;
+                                                                                        const char* _name,
+                                                                                        bool optional)
+       : type_(_type), name_(_name), optional_(optional) {}
+
+AutoRegisterSet& AutoRegisterInterface::registries()
+{
+       static AutoRegisterSet registries_;
+       return registries_;
 }
 
-AutoRegisterSet& AutoRegisterInterface::plugins() {
-  static AutoRegisterSet plugins_;
-  return plugins_;
+AutoRegisterSet& AutoRegisterInterface::plugins()
+{
+       static AutoRegisterSet plugins_;
+       return plugins_;
 }
 
 void AutoRegisterInterface::autoloadRegistry(
-    std::unique_ptr<AutoRegisterInterface> ar_) {
-  registries().push_back(std::move(ar_));
+       std::unique_ptr<AutoRegisterInterface> ar_)
+{
+       registries().push_back(std::move(ar_));
 }
 
 void AutoRegisterInterface::autoloadPlugin(
-    std::unique_ptr<AutoRegisterInterface> ar_) {
-  plugins().push_back(std::move(ar_));
+       std::unique_ptr<AutoRegisterInterface> ar_)
+{
+       plugins().push_back(std::move(ar_));
 }
 
-void registryAndPluginInit() {
-  for (const auto& it : AutoRegisterInterface::registries()) {
-    it->run();
-  }
+void registryAndPluginInit()
+{
+       for (const auto& it : AutoRegisterInterface::registries()) {
+               it->run();
+       }
 
-  for (const auto& it : AutoRegisterInterface::plugins()) {
-    it->run();
-  }
+       for (const auto& it : AutoRegisterInterface::plugins()) {
+               it->run();
+       }
 
-  AutoRegisterSet().swap(AutoRegisterInterface::registries());
-  AutoRegisterSet().swap(AutoRegisterInterface::plugins());
+       AutoRegisterSet().swap(AutoRegisterInterface::registries());
+       AutoRegisterSet().swap(AutoRegisterInterface::plugins());
 }
 
 } // namespace osquery
index 9e643e47f6ce1dbe98891610afa2bd3b3c12f4d8..81a6ef4da0f03875967512aceb9f9ff2e3f19e00 100644 (file)
@@ -18,222 +18,238 @@ namespace osquery {
 class TestCoreRegistry : public RegistryFactory {};
 
 class CatPlugin : public Plugin {
- public:
-  CatPlugin() : some_value_(0) {}
+public:
+       CatPlugin() : some_value_(0) {}
 
-  Status call(const PluginRequest&, PluginResponse&) override {
-    return Status(0);
-  }
+       Status call(const PluginRequest&, PluginResponse&) override
+       {
+               return Status(0);
+       }
 
- protected:
-  int some_value_;
+protected:
+       int some_value_;
 };
 
 class DogPlugin : public Plugin {
- public:
-  DogPlugin() : some_value_(10000) {}
+public:
+       DogPlugin() : some_value_(10000) {}
 
-  Status call(const PluginRequest&, PluginResponse&) override {
-    return Status(0);
-  }
+       Status call(const PluginRequest&, PluginResponse&) override
+       {
+               return Status(0);
+       }
 
- protected:
-  int some_value_;
+protected:
+       int some_value_;
 };
 
 class RegistryTests : public testing::Test {
- public:
-  void SetUp() override {
-    if (!kSetUp) {
-      TestCoreRegistry::get().add(
-          "cat", std::make_shared<RegistryType<CatPlugin>>("cat"));
-      TestCoreRegistry::get().add(
-          "dog", std::make_shared<RegistryType<DogPlugin>>("dog"));
-      kSetUp = true;
-    }
-  }
-
-  static bool kSetUp;
+public:
+       void SetUp() override
+       {
+               if (!kSetUp) {
+                       TestCoreRegistry::get().add(
+                               "cat", std::make_shared<RegistryType<CatPlugin>>("cat"));
+                       TestCoreRegistry::get().add(
+                               "dog", std::make_shared<RegistryType<DogPlugin>>("dog"));
+                       kSetUp = true;
+               }
+       }
+
+       static bool kSetUp;
 };
 
 bool RegistryTests::kSetUp{false};
 
 class HouseCat : public CatPlugin {
- public:
-  Status setUp() {
-    // Make sure the Plugin implementation's init is called.
-    some_value_ = 9000;
-    return Status::success();
-  }
+public:
+       Status setUp()
+       {
+               // Make sure the Plugin implementation's init is called.
+               some_value_ = 9000;
+               return Status::success();
+       }
 };
 
 /// This is a manual registry type without a name, so we cannot broadcast
 /// this registry type and it does NOT need to conform to a registry API.
 class CatRegistry : public RegistryType<CatPlugin> {
- public:
-  CatRegistry(const std::string& name) : RegistryType(name) {}
+public:
+       CatRegistry(const std::string& name) : RegistryType(name) {}
 };
 
-TEST_F(RegistryTests, test_registry) {
-  CatRegistry cats("cats");
+TEST_F(RegistryTests, test_registry)
+{
+       CatRegistry cats("cats");
 
-  /// Add a CatRegistry item (a plugin) called "house".
-  cats.add("house", std::make_shared<HouseCat>());
-  EXPECT_EQ(cats.count(), 1U);
+       /// Add a CatRegistry item (a plugin) called "house".
+       cats.add("house", std::make_shared<HouseCat>());
+       EXPECT_EQ(cats.count(), 1U);
 
-  /// Try to add the same plugin with the same name, this is meaningless.
-  cats.add("house", std::make_shared<HouseCat>());
+       /// Try to add the same plugin with the same name, this is meaningless.
+       cats.add("house", std::make_shared<HouseCat>());
 
-  /// Now add the same plugin with a different name, a new plugin instance
-  /// will be created and registered.
-  cats.add("house2", std::make_shared<HouseCat>());
-  EXPECT_EQ(cats.count(), 2U);
+       /// Now add the same plugin with a different name, a new plugin instance
+       /// will be created and registered.
+       cats.add("house2", std::make_shared<HouseCat>());
+       EXPECT_EQ(cats.count(), 2U);
 
-  /// Request a plugin to call an API method.
-  auto cat = cats.plugin("house");
-  cats.setUp();
+       /// Request a plugin to call an API method.
+       auto cat = cats.plugin("house");
+       cats.setUp();
 
-  /// Now let's iterate over every registered Cat plugin.
-  EXPECT_EQ(cats.plugins().size(), 2U);
+       /// Now let's iterate over every registered Cat plugin.
+       EXPECT_EQ(cats.plugins().size(), 2U);
 }
 
-TEST_F(RegistryTests, test_auto_factory) {
-  /// Using the registry, and a registry type by name, we can register a
-  /// plugin HouseCat called "house" like above.
-  auto cat_registry = TestCoreRegistry::get().registry("cat");
-  cat_registry->add("auto_house", std::make_shared<HouseCat>());
-  cat_registry->setUp();
-
-  /// When acting on registries by name we can check the broadcasted
-  /// registry name of other plugin processes (via Thrift) as well as
-  /// internally registered plugins like HouseCat.
-  EXPECT_EQ(TestCoreRegistry::get().registry("cat")->count(), 1U);
-  EXPECT_EQ(TestCoreRegistry::get().count("cat"), 1U);
-
-  /// And we can call an API method, since we guarantee CatPlugins conform
-  /// to the "TestCoreRegistry"'s "TestPluginAPI".
-  auto cat = TestCoreRegistry::get().plugin("cat", "auto_house");
-  auto same_cat = TestCoreRegistry::get().plugin("cat", "auto_house");
-  EXPECT_EQ(cat, same_cat);
+TEST_F(RegistryTests, test_auto_factory)
+{
+       /// Using the registry, and a registry type by name, we can register a
+       /// plugin HouseCat called "house" like above.
+       auto cat_registry = TestCoreRegistry::get().registry("cat");
+       cat_registry->add("auto_house", std::make_shared<HouseCat>());
+       cat_registry->setUp();
+
+       /// When acting on registries by name we can check the broadcasted
+       /// registry name of other plugin processes (via Thrift) as well as
+       /// internally registered plugins like HouseCat.
+       EXPECT_EQ(TestCoreRegistry::get().registry("cat")->count(), 1U);
+       EXPECT_EQ(TestCoreRegistry::get().count("cat"), 1U);
+
+       /// And we can call an API method, since we guarantee CatPlugins conform
+       /// to the "TestCoreRegistry"'s "TestPluginAPI".
+       auto cat = TestCoreRegistry::get().plugin("cat", "auto_house");
+       auto same_cat = TestCoreRegistry::get().plugin("cat", "auto_house");
+       EXPECT_EQ(cat, same_cat);
 }
 
 class Doge : public DogPlugin {
- public:
-  Doge() {
-    some_value_ = 100000;
-  }
+public:
+       Doge()
+       {
+               some_value_ = 100000;
+       }
 };
 
 class BadDoge : public DogPlugin {
- public:
-  Status setUp() {
-    return Status(1, "Expect error... this is a bad dog");
-  }
+public:
+       Status setUp()
+       {
+               return Status(1, "Expect error... this is a bad dog");
+       }
 };
 
-TEST_F(RegistryTests, test_auto_registries) {
-  auto dog_registry = TestCoreRegistry::get().registry("dog");
-  dog_registry->add("doge", std::make_shared<Doge>());
-  dog_registry->setUp();
+TEST_F(RegistryTests, test_auto_registries)
+{
+       auto dog_registry = TestCoreRegistry::get().registry("dog");
+       dog_registry->add("doge", std::make_shared<Doge>());
+       dog_registry->setUp();
 
-  EXPECT_EQ(TestCoreRegistry::get().count("dog"), 1U);
+       EXPECT_EQ(TestCoreRegistry::get().count("dog"), 1U);
 }
 
-TEST_F(RegistryTests, test_persistent_registries) {
-  EXPECT_EQ(TestCoreRegistry::get().count("cat"), 1U);
+TEST_F(RegistryTests, test_persistent_registries)
+{
+       EXPECT_EQ(TestCoreRegistry::get().count("cat"), 1U);
 }
 
-TEST_F(RegistryTests, test_registry_exceptions) {
-  auto dog_registry = TestCoreRegistry::get().registry("dog");
-  EXPECT_TRUE(dog_registry->add("doge2", std::make_shared<Doge>()).ok());
-  // Bad dog will be added fine.
-  EXPECT_TRUE(dog_registry->add("bad_doge", std::make_shared<BadDoge>()).ok());
-  dog_registry->setUp();
-  // Make sure bad dog does exist.
-  EXPECT_TRUE(TestCoreRegistry::get().exists("dog", "bad_doge"));
-  EXPECT_EQ(TestCoreRegistry::get().count("dog"), 3U);
-
-  unsigned int exception_count = 0;
-  try {
-    TestCoreRegistry::get().registry("does_not_exist");
-  } catch (const std::runtime_error& /* e */) {
-    exception_count++;
-  }
-
-  EXPECT_EQ(exception_count, 1U);
+TEST_F(RegistryTests, test_registry_exceptions)
+{
+       auto dog_registry = TestCoreRegistry::get().registry("dog");
+       EXPECT_TRUE(dog_registry->add("doge2", std::make_shared<Doge>()).ok());
+       // Bad dog will be added fine.
+       EXPECT_TRUE(dog_registry->add("bad_doge", std::make_shared<BadDoge>()).ok());
+       dog_registry->setUp();
+       // Make sure bad dog does exist.
+       EXPECT_TRUE(TestCoreRegistry::get().exists("dog", "bad_doge"));
+       EXPECT_EQ(TestCoreRegistry::get().count("dog"), 3U);
+
+       unsigned int exception_count = 0;
+       try {
+               TestCoreRegistry::get().registry("does_not_exist");
+       } catch (const std::runtime_error& /* e */) {
+               exception_count++;
+       }
+
+       EXPECT_EQ(exception_count, 1U);
 }
 
 class WidgetPlugin : public Plugin {
- public:
-  /// The route information will usually be provided by the plugin type.
-  /// The plugin/registry item will set some structures for the plugin
-  /// to parse and format. BUT a plugin/registry item can also fill this
-  /// information in if the plugin type/registry type exposes routeInfo as
-  /// a virtual method.
-  PluginResponse routeInfo() const {
-    PluginResponse info;
-    info.push_back({{"name", name_}});
-    return info;
-  }
-
-  /// Plugin types should contain generic request/response formatters and
-  /// decorators.
-  std::string secretPower(const PluginRequest& request) const {
-    if (request.count("secret_power") > 0U) {
-      return request.at("secret_power");
-    }
-    return "no_secret_power";
-  }
+public:
+       /// The route information will usually be provided by the plugin type.
+       /// The plugin/registry item will set some structures for the plugin
+       /// to parse and format. BUT a plugin/registry item can also fill this
+       /// information in if the plugin type/registry type exposes routeInfo as
+       /// a virtual method.
+       PluginResponse routeInfo() const
+       {
+               PluginResponse info;
+               info.push_back({{"name", name_}});
+               return info;
+       }
+
+       /// Plugin types should contain generic request/response formatters and
+       /// decorators.
+       std::string secretPower(const PluginRequest& request) const
+       {
+               if (request.count("secret_power") > 0U) {
+                       return request.at("secret_power");
+               }
+               return "no_secret_power";
+       }
 };
 
 class SpecialWidget : public WidgetPlugin {
- public:
-  Status call(const PluginRequest& request, PluginResponse& response);
+public:
+       Status call(const PluginRequest& request, PluginResponse& response);
 };
 
 Status SpecialWidget::call(const PluginRequest& request,
-                           PluginResponse& response) {
-  response.push_back(request);
-  response[0]["from"] = name_;
-  response[0]["secret_power"] = secretPower(request);
-  return Status::success();
+                                                  PluginResponse& response)
+{
+       response.push_back(request);
+       response[0]["from"] = name_;
+       response[0]["secret_power"] = secretPower(request);
+       return Status::success();
 }
 
 #define UNUSED(x) (void)(x)
 
-TEST_F(RegistryTests, test_registry_api) {
-  TestCoreRegistry::get().add(
-      "widgets", std::make_shared<RegistryType<WidgetPlugin>>("widgets"));
+TEST_F(RegistryTests, test_registry_api)
+{
+       TestCoreRegistry::get().add(
+               "widgets", std::make_shared<RegistryType<WidgetPlugin>>("widgets"));
 
-  auto widgets = TestCoreRegistry::get().registry("widgets");
-  widgets->add("special", std::make_shared<SpecialWidget>());
+       auto widgets = TestCoreRegistry::get().registry("widgets");
+       widgets->add("special", std::make_shared<SpecialWidget>());
 
-  // Test route info propagation, from item to registry, to broadcast.
-  auto ri = TestCoreRegistry::get().plugin("widgets", "special")->routeInfo();
-  EXPECT_EQ(ri[0].at("name"), "special");
+       // Test route info propagation, from item to registry, to broadcast.
+       auto ri = TestCoreRegistry::get().plugin("widgets", "special")->routeInfo();
+       EXPECT_EQ(ri[0].at("name"), "special");
 
-  PluginResponse response;
-  PluginRequest request;
-  auto status = TestCoreRegistry::call("widgets", "special", request, response);
-  EXPECT_TRUE(status.ok());
-  EXPECT_EQ(response[0].at("from"), "special");
-  EXPECT_EQ(response[0].at("secret_power"), "no_secret_power");
+       PluginResponse response;
+       PluginRequest request;
+       auto status = TestCoreRegistry::call("widgets", "special", request, response);
+       EXPECT_TRUE(status.ok());
+       EXPECT_EQ(response[0].at("from"), "special");
+       EXPECT_EQ(response[0].at("secret_power"), "no_secret_power");
 
-  request["secret_power"] = "magic";
-  status = TestCoreRegistry::call("widgets", "special", request, response);
-  EXPECT_EQ(response[0].at("secret_power"), "magic");
+       request["secret_power"] = "magic";
+       status = TestCoreRegistry::call("widgets", "special", request, response);
+       EXPECT_EQ(response[0].at("secret_power"), "magic");
 }
 
-TEST_F(RegistryTests, test_real_registry) {
-  EXPECT_TRUE(Registry::get().count() > 0U);
-
-  bool has_one_registered = false;
-  for (const auto& registry : Registry::get().all()) {
-    if (Registry::get().count(registry.first) > 0) {
-      has_one_registered = true;
-      break;
-    }
-  }
-  EXPECT_TRUE(has_one_registered);
+TEST_F(RegistryTests, test_real_registry)
+{
+       EXPECT_TRUE(Registry::get().count() > 0U);
+
+       bool has_one_registered = false;
+       for (const auto& registry : Registry::get().all()) {
+               if (Registry::get().count(registry.first) > 0) {
+                       has_one_registered = true;
+                       break;
+               }
+       }
+       EXPECT_TRUE(has_one_registered);
 }
 }
index c5285c85a235b44724a31ca516b913ece96ca0ce..60929bf837954b81b6383fa74ce8212bdb12b6f2 100644 (file)
 
 namespace osquery {
 
-TableRows tableRowsFromQueryData(QueryData&& rows) {
-  TableRows result;
+TableRows tableRowsFromQueryData(QueryData&& rows)
+{
+       TableRows result;
 
-  for (auto&& row : rows) {
-    result.push_back(TableRowHolder(new DynamicTableRow(std::move(row))));
-  }
+       for (auto&& row : rows) {
+               result.push_back(TableRowHolder(new DynamicTableRow(std::move(row))));
+       }
 
-  return result;
+       return result;
 }
 
 int DynamicTableRow::get_rowid(sqlite_int64 default_value,
-                               sqlite_int64* pRowid) const {
-  auto& current_row = this->row;
-  auto rowid_it = current_row.find("rowid");
-  if (rowid_it != current_row.end()) {
-    const auto& rowid_text_field = rowid_it->second;
+                                                          sqlite_int64* pRowid) const
+{
+       auto& current_row = this->row;
+       auto rowid_it = current_row.find("rowid");
+       if (rowid_it != current_row.end()) {
+               const auto& rowid_text_field = rowid_it->second;
 
-    auto exp = tryTo<long long>(rowid_text_field, 10);
-    if (exp.isError()) {
-      DEBUG(OSQUERY) << "Invalid rowid value returned " << exp.getError();
-      return SQLITE_ERROR;
-    }
-    *pRowid = exp.take();
+               auto exp = tryTo<long long>(rowid_text_field, 10);
+               if (exp.isError()) {
+                       DEBUG(OSQUERY) << "Invalid rowid value returned " << exp.getError();
+                       return SQLITE_ERROR;
+               }
+               *pRowid = exp.take();
 
-  } else {
-    *pRowid = default_value;
-  }
-  return SQLITE_OK;
+       } else {
+               *pRowid = default_value;
+       }
+       return SQLITE_OK;
 }
 
 int DynamicTableRow::get_column(sqlite3_context* ctx,
-                                sqlite3_vtab* vtab,
-                                int col) {
-  VirtualTable* pVtab = (VirtualTable*)vtab;
-  auto& column_name = std::get<0>(pVtab->content->columns[col]);
-  auto& type = std::get<1>(pVtab->content->columns[col]);
-  if (pVtab->content->aliases.count(column_name)) {
-    // Overwrite the aliased column with the type and name of the new column.
-    type = std::get<1>(
-        pVtab->content->columns[pVtab->content->aliases.at(column_name)]);
-    column_name = std::get<0>(
-        pVtab->content->columns[pVtab->content->aliases.at(column_name)]);
-  }
+                                                               sqlite3_vtab* vtab,
+                                                               int col)
+{
+       VirtualTable* pVtab = (VirtualTable*)vtab;
+       auto& column_name = std::get<0>(pVtab->content->columns[col]);
+       auto& type = std::get<1>(pVtab->content->columns[col]);
+       if (pVtab->content->aliases.count(column_name)) {
+               // Overwrite the aliased column with the type and name of the new column.
+               type = std::get<1>(
+                                  pVtab->content->columns[pVtab->content->aliases.at(column_name)]);
+               column_name = std::get<0>(
+                                                 pVtab->content->columns[pVtab->content->aliases.at(column_name)]);
+       }
 
-  // Attempt to cast each xFilter-populated row/column to the SQLite type.
-  const auto& value = row[column_name];
-  if (this->row.count(column_name) == 0) {
-    // Missing content.
-    DEBUG(OSQUERY) << "Error " << column_name << " is empty";
-    sqlite3_result_null(ctx);
-  } else if (type == TEXT_TYPE || type == BLOB_TYPE) {
-    sqlite3_result_text(
-        ctx, value.c_str(), static_cast<int>(value.size()), SQLITE_STATIC);
-  } else if (type == INTEGER_TYPE) {
-    auto afinite = tryTo<long>(value, 0);
-    if (afinite.isError()) {
-      DEBUG(OSQUERY) << "Error casting " << column_name << " (" << value
-              << ") to INTEGER";
-      sqlite3_result_null(ctx);
-    } else {
-      sqlite3_result_int(ctx, afinite.take());
-    }
-  } else if (type == BIGINT_TYPE || type == UNSIGNED_BIGINT_TYPE) {
-    auto afinite = tryTo<long long>(value, 0);
-    if (afinite.isError()) {
-      DEBUG(OSQUERY) << "Error casting " << column_name << " (" << value
-              << ") to BIGINT";
-      sqlite3_result_null(ctx);
-    } else {
-      sqlite3_result_int64(ctx, afinite.take());
-    }
-  } else if (type == DOUBLE_TYPE) {
-    char* end = nullptr;
-    double afinite = strtod(value.c_str(), &end);
-    if (end == nullptr || end == value.c_str() || *end != '\0') {
-      DEBUG(OSQUERY) << "Error casting " << column_name << " (" << value
-              << ") to DOUBLE";
-      sqlite3_result_null(ctx);
-    } else {
-      sqlite3_result_double(ctx, afinite);
-    }
-  } else {
-    ERROR(OSQUERY) << "Error unknown column type " << column_name;
-  }
+       // Attempt to cast each xFilter-populated row/column to the SQLite type.
+       const auto& value = row[column_name];
+       if (this->row.count(column_name) == 0) {
+               // Missing content.
+               DEBUG(OSQUERY) << "Error " << column_name << " is empty";
+               sqlite3_result_null(ctx);
+       } else if (type == TEXT_TYPE || type == BLOB_TYPE) {
+               sqlite3_result_text(
+                       ctx, value.c_str(), static_cast<int>(value.size()), SQLITE_STATIC);
+       } else if (type == INTEGER_TYPE) {
+               auto afinite = tryTo<long>(value, 0);
+               if (afinite.isError()) {
+                       DEBUG(OSQUERY) << "Error casting " << column_name << " (" << value
+                                                  << ") to INTEGER";
+                       sqlite3_result_null(ctx);
+               } else {
+                       sqlite3_result_int(ctx, afinite.take());
+               }
+       } else if (type == BIGINT_TYPE || type == UNSIGNED_BIGINT_TYPE) {
+               auto afinite = tryTo<long long>(value, 0);
+               if (afinite.isError()) {
+                       DEBUG(OSQUERY) << "Error casting " << column_name << " (" << value
+                                                  << ") to BIGINT";
+                       sqlite3_result_null(ctx);
+               } else {
+                       sqlite3_result_int64(ctx, afinite.take());
+               }
+       } else if (type == DOUBLE_TYPE) {
+               char* end = nullptr;
+               double afinite = strtod(value.c_str(), &end);
+               if (end == nullptr || end == value.c_str() || *end != '\0') {
+                       DEBUG(OSQUERY) << "Error casting " << column_name << " (" << value
+                                                  << ") to DOUBLE";
+                       sqlite3_result_null(ctx);
+               } else {
+                       sqlite3_result_double(ctx, afinite);
+               }
+       } else {
+               ERROR(OSQUERY) << "Error unknown column type " << column_name;
+       }
 
-  return SQLITE_OK;
+       return SQLITE_OK;
 }
 
-TableRowHolder DynamicTableRow::clone() const {
-  Row new_row = row;
-  return TableRowHolder(new DynamicTableRow(std::move(new_row)));
+TableRowHolder DynamicTableRow::clone() const
+{
+       Row new_row = row;
+       return TableRowHolder(new DynamicTableRow(std::move(new_row)));
 }
 
 } // namespace osquery
index 7da1493014657f6ba4768ec51d62961c0e891fd6..b8a5c3430b973886a5d57e204067d31c95a5428b 100644 (file)
@@ -15,64 +15,74 @@ namespace osquery {
 
 /** A TableRow backed by a string map. */
 class DynamicTableRow : public TableRow {
- public:
-  DynamicTableRow() : row() {}
-  DynamicTableRow(Row&& r) : row(std::move(r)) {}
-  DynamicTableRow(
-      std::initializer_list<std::pair<const std::string, std::string>> init)
-      : row(init) {}
-  DynamicTableRow(const DynamicTableRow&) = delete;
-  DynamicTableRow& operator=(const DynamicTableRow&) = delete;
-  explicit operator Row() const {
-    return row;
-  }
-  virtual int get_rowid(sqlite_int64 default_value, sqlite_int64* pRowid) const;
-  virtual int get_column(sqlite3_context* ctx, sqlite3_vtab* pVtab, int col);
-  virtual TableRowHolder clone() const;
-  inline std::string& operator[](const std::string& key) {
-    return row[key];
-  }
-  inline std::string& operator[](std::string&& key) {
-    return row[key];
-  }
-  inline size_t count(const std::string& key) const {
-    return row.count(key);
-  }
+public:
+       DynamicTableRow() : row() {}
+       DynamicTableRow(Row&& r) : row(std::move(r)) {}
+       DynamicTableRow(
+               std::initializer_list<std::pair<const std::string, std::string>> init)
+               : row(init) {}
+       DynamicTableRow(const DynamicTableRow&) = delete;
+       DynamicTableRow& operator=(const DynamicTableRow&) = delete;
+       explicit operator Row() const
+       {
+               return row;
+       }
+       virtual int get_rowid(sqlite_int64 default_value, sqlite_int64* pRowid) const;
+       virtual int get_column(sqlite3_context* ctx, sqlite3_vtab* pVtab, int col);
+       virtual TableRowHolder clone() const;
+       inline std::string& operator[](const std::string& key)
+       {
+               return row[key];
+       }
+       inline std::string& operator[](std::string&& key)
+       {
+               return row[key];
+       }
+       inline size_t count(const std::string& key) const
+       {
+               return row.count(key);
+       }
 
- private:
-  Row row;
+private:
+       Row row;
 };
 /// Syntactic sugar making DynamicRows inside of TableRowHolders easier to work
 /// with. This should go away once strongly typed rows are used everywhere.
 class DynamicTableRowHolder {
- public:
-  DynamicTableRowHolder() : row(new DynamicTableRow()), ptr(row) {}
-  DynamicTableRowHolder(
-      std::initializer_list<std::pair<const std::string, std::string>> init)
-      : row(new DynamicTableRow(init)), ptr(row) {}
-  inline operator TableRowHolder &&() {
-    return std::move(ptr);
-  }
-  inline std::string& operator[](const std::string& key) {
-    return (*row)[key];
-  }
-  inline std::string& operator[](std::string&& key) {
-    return (*row)[key];
-  }
-  inline size_t count(const std::string& key) {
-    return (*row).count(key);
-  }
+public:
+       DynamicTableRowHolder() : row(new DynamicTableRow()), ptr(row) {}
+       DynamicTableRowHolder(
+               std::initializer_list<std::pair<const std::string, std::string>> init)
+               : row(new DynamicTableRow(init)), ptr(row) {}
+       inline operator TableRowHolder&& ()
+       {
+               return std::move(ptr);
+       }
+       inline std::string& operator[](const std::string& key)
+       {
+               return (*row)[key];
+       }
+       inline std::string& operator[](std::string&& key)
+       {
+               return (*row)[key];
+       }
+       inline size_t count(const std::string& key)
+       {
+               return (*row).count(key);
+       }
 
- private:
-  DynamicTableRow* row;
-  TableRowHolder ptr;
+private:
+       DynamicTableRow* row;
+       TableRowHolder ptr;
 };
-inline DynamicTableRowHolder make_table_row() {
-  return DynamicTableRowHolder();
+inline DynamicTableRowHolder make_table_row()
+{
+       return DynamicTableRowHolder();
 }
 inline DynamicTableRowHolder make_table_row(
-    std::initializer_list<std::pair<const std::string, std::string>> init) {
-  return DynamicTableRowHolder(init);
+       std::initializer_list<std::pair<const std::string, std::string>> init)
+{
+       return DynamicTableRowHolder(init);
 }
 
 /// Converts a QueryData struct to TableRows. Intended for use only in
index 905f931ee8b1bc0d7261a708cefc2d5dea4b5b3e..6244e924c642be2d38ce6dda807e42d4277fa334 100644 (file)
@@ -22,199 +22,216 @@ namespace osquery {
 
 CREATE_LAZY_REGISTRY(SQLPlugin, "sql");
 
-SQL::SQL(const std::string& query, bool use_cache) {
-  TableColumns table_columns;
-  status_ = getQueryColumns(query, table_columns);
-  if (status_.ok()) {
-    for (auto c : table_columns) {
-      columns_.push_back(std::get<0>(c));
-    }
-    status_ = osquery::query(query, results_, use_cache);
-  }
+SQL::SQL(const std::string& query, bool use_cache)
+{
+       TableColumns table_columns;
+       status_ = getQueryColumns(query, table_columns);
+       if (status_.ok()) {
+               for (auto c : table_columns) {
+                       columns_.push_back(std::get<0>(c));
+               }
+               status_ = osquery::query(query, results_, use_cache);
+       }
 }
 
-const QueryData& SQL::rows() const {
-  return results_;
+const QueryData& SQL::rows() const
+{
+       return results_;
 }
 
-QueryData& SQL::rows() {
-  return results_;
+QueryData& SQL::rows()
+{
+       return results_;
 }
 
-const ColumnNames& SQL::columns() const {
-  return columns_;
+const ColumnNames& SQL::columns() const
+{
+       return columns_;
 }
 
-bool SQL::ok() const {
-  return status_.ok();
+bool SQL::ok() const
+{
+       return status_.ok();
 }
 
-const Status& SQL::getStatus() const {
-  return status_;
+const Status& SQL::getStatus() const
+{
+       return status_;
 }
 
-std::string SQL::getMessageString() const {
-  return status_.toString();
+std::string SQL::getMessageString() const
+{
+       return status_.toString();
 }
 
-static inline void escapeNonPrintableBytes(std::string& data) {
-  std::string escaped;
-  // clang-format off
-  char const hex_chars[16] = {
-    '0', '1', '2', '3', '4', '5', '6', '7',
-    '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
-  };
-  // clang-format on
+static inline void escapeNonPrintableBytes(std::string& data)
+{
+       std::string escaped;
+       // clang-format off
+       char const hex_chars[16] = {
+               '0', '1', '2', '3', '4', '5', '6', '7',
+               '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
+       };
+       // clang-format on
 
-  bool needs_replacement = false;
-  for (size_t i = 0; i < data.length(); i++) {
-    if (((unsigned char)data[i]) < 0x20 || ((unsigned char)data[i]) >= 0x80) {
-      needs_replacement = true;
-      escaped += "\\x";
-      escaped += hex_chars[(((unsigned char)data[i])) >> 4];
-      escaped += hex_chars[((unsigned char)data[i] & 0x0F) >> 0];
-    } else {
-      escaped += data[i];
-    }
-  }
+       bool needs_replacement = false;
+       for (size_t i = 0; i < data.length(); i++) {
+               if (((unsigned char)data[i]) < 0x20 || ((unsigned char)data[i]) >= 0x80) {
+                       needs_replacement = true;
+                       escaped += "\\x";
+                       escaped += hex_chars[(((unsigned char)data[i])) >> 4];
+                       escaped += hex_chars[((unsigned char)data[i] & 0x0F) >> 0];
+               } else {
+                       escaped += data[i];
+               }
+       }
 
-  // Only replace if any escapes were made.
-  if (needs_replacement) {
-    data = std::move(escaped);
-  }
+       // Only replace if any escapes were made.
+       if (needs_replacement) {
+               data = std::move(escaped);
+       }
 }
 
-void escapeNonPrintableBytesEx(std::string& data) {
-  return escapeNonPrintableBytes(data);
+void escapeNonPrintableBytesEx(std::string& data)
+{
+       return escapeNonPrintableBytes(data);
 }
 
-QueryData SQL::selectAllFrom(const std::string& table) {
-  PluginResponse response;
-  Registry::call("table", table, {{"action", "generate"}}, response);
-  return response;
+QueryData SQL::selectAllFrom(const std::string& table)
+{
+       PluginResponse response;
+       Registry::call("table", table, {{"action", "generate"}}, response);
+       return response;
 }
 
 QueryData SQL::selectAllFrom(const std::string& table,
-                             const std::string& column,
-                             ConstraintOperator op,
-                             const std::string& expr) {
-  return selectFrom({}, table, column, op, expr);
+                                                        const std::string& column,
+                                                        ConstraintOperator op,
+                                                        const std::string& expr)
+{
+       return selectFrom({}, table, column, op, expr);
 }
 
 QueryData SQL::selectFrom(const std::initializer_list<std::string>& columns,
-                          const std::string& table,
-                          const std::string& column,
-                          ConstraintOperator op,
-                          const std::string& expr) {
-  PluginRequest request = {{"action", "generate"}};
-  // Create a fake content, there will be no caching.
-  QueryContext ctx;
-  ctx.constraints[column].add(Constraint(op, expr));
-  if (columns.size() > 0) {
-    auto colsUsed = UsedColumns(columns);
-    colsUsed.insert(column);
-    ctx.colsUsed = colsUsed;
-  }
-  // We can't set colsUsedBitset here (because we don't know the column
-  // indexes). The plugin that handles the request will figure it out from the
-  // column names.
-  TablePlugin::setRequestFromContext(ctx, request);
-
-  PluginResponse response;
-  Registry::call("table", table, request, response);
-  response.erase(
-      std::remove_if(response.begin(),
-                     response.end(),
-                     [&ctx, &column](const PluginRequest& row) -> bool {
-                       return !ctx.constraints[column].matches(row.at(column));
-                     }),
-      response.end());
-  return response;
-}
-
-Status SQLPlugin::call(const PluginRequest& request, PluginResponse& response) {
-  response.clear();
-  if (request.count("action") == 0) {
-    return Status(1, "SQL plugin must include a request action");
-  }
-
-  if (request.at("action") == "query") {
-    bool use_cache = (request.count("cache") && request.at("cache") == "1");
-    return this->query(request.at("query"), response, use_cache);
-  } else if (request.at("action") == "columns") {
-    TableColumns columns;
-    auto status = this->getQueryColumns(request.at("query"), columns);
-    // Convert columns to response
-    for (const auto& column : columns) {
-      response.push_back(
-          {{"n", std::get<0>(column)},
-           {"t", columnTypeName(std::get<1>(column))},
-           {"o", INTEGER(static_cast<size_t>(std::get<2>(column)))}});
-    }
-    return status;
-  } else if (request.at("action") == "attach") {
-    // Attach a virtual table name using an optional included definition.
-    return this->attach(request.at("table"));
-  } else if (request.at("action") == "detach") {
-    this->detach(request.at("table"));
-    return Status::success();
-  } else if (request.at("action") == "tables") {
-    std::vector<std::string> tables;
-    auto status = this->getQueryTables(request.at("query"), tables);
-    if (status.ok()) {
-      for (const auto& table : tables) {
-        response.push_back({{"t", table}});
-      }
-    }
-    return status;
-  }
-  return Status(1, "Unknown action");
-}
-
-Status query(const std::string& q, QueryData& results, bool use_cache) {
-  return Registry::call(
-      "sql",
-      "sql",
-      {{"action", "query"}, {"cache", (use_cache) ? "1" : "0"}, {"query", q}},
-      results);
-}
-
-Status getQueryColumns(const std::string& q, TableColumns& columns) {
-  PluginResponse response;
-  auto status = Registry::call(
-      "sql", "sql", {{"action", "columns"}, {"query", q}}, response);
-
-  // Convert response to columns
-  for (const auto& item : response) {
-    columns.push_back(make_tuple(
-        item.at("n"), columnTypeName(item.at("t")), ColumnOptions::DEFAULT));
-  }
-  return status;
+                                                 const std::string& table,
+                                                 const std::string& column,
+                                                 ConstraintOperator op,
+                                                 const std::string& expr)
+{
+       PluginRequest request = {{"action", "generate"}};
+       // Create a fake content, there will be no caching.
+       QueryContext ctx;
+       ctx.constraints[column].add(Constraint(op, expr));
+       if (columns.size() > 0) {
+               auto colsUsed = UsedColumns(columns);
+               colsUsed.insert(column);
+               ctx.colsUsed = colsUsed;
+       }
+       // We can't set colsUsedBitset here (because we don't know the column
+       // indexes). The plugin that handles the request will figure it out from the
+       // column names.
+       TablePlugin::setRequestFromContext(ctx, request);
+
+       PluginResponse response;
+       Registry::call("table", table, request, response);
+       response.erase(
+               std::remove_if(response.begin(),
+                                          response.end(),
+       [&ctx, &column](const PluginRequest & row) -> bool {
+               return !ctx.constraints[column].matches(row.at(column));
+       }),
+       response.end());
+       return response;
+}
+
+Status SQLPlugin::call(const PluginRequest& request, PluginResponse& response)
+{
+       response.clear();
+       if (request.count("action") == 0) {
+               return Status(1, "SQL plugin must include a request action");
+       }
+
+       if (request.at("action") == "query") {
+               bool use_cache = (request.count("cache") && request.at("cache") == "1");
+               return this->query(request.at("query"), response, use_cache);
+       } else if (request.at("action") == "columns") {
+               TableColumns columns;
+               auto status = this->getQueryColumns(request.at("query"), columns);
+               // Convert columns to response
+               for (const auto& column : columns) {
+                       response.push_back({
+                               {"n", std::get<0>(column)},
+                               {"t", columnTypeName(std::get<1>(column))},
+                               {"o", INTEGER(static_cast<size_t>(std::get<2>(column)))}});
+               }
+               return status;
+       } else if (request.at("action") == "attach") {
+               // Attach a virtual table name using an optional included definition.
+               return this->attach(request.at("table"));
+       } else if (request.at("action") == "detach") {
+               this->detach(request.at("table"));
+               return Status::success();
+       } else if (request.at("action") == "tables") {
+               std::vector<std::string> tables;
+               auto status = this->getQueryTables(request.at("query"), tables);
+               if (status.ok()) {
+                       for (const auto& table : tables) {
+                               response.push_back({{"t", table}});
+                       }
+               }
+               return status;
+       }
+       return Status(1, "Unknown action");
+}
+
+Status query(const std::string& q, QueryData& results, bool use_cache)
+{
+       return Registry::call(
+                          "sql",
+                          "sql",
+       {{"action", "query"}, {"cache", (use_cache) ? "1" : "0"}, {"query", q}},
+       results);
+}
+
+Status getQueryColumns(const std::string& q, TableColumns& columns)
+{
+       PluginResponse response;
+       auto status = Registry::call(
+       "sql", "sql", {{"action", "columns"}, {"query", q}}, response);
+
+       // Convert response to columns
+       for (const auto& item : response) {
+               columns.push_back(make_tuple(
+                                                         item.at("n"), columnTypeName(item.at("t")), ColumnOptions::DEFAULT));
+       }
+       return status;
 }
 
 Status mockGetQueryTables(std::string copy_q,
-                          std::vector<std::string>& tables) {
-  std::transform(copy_q.begin(), copy_q.end(), copy_q.begin(), ::tolower);
-  auto offset_from = copy_q.find("from ");
-  if (offset_from == std::string::npos) {
-    return Status(1);
-  }
-
-  auto simple_tables = osquery::split(copy_q.substr(offset_from + 5), ",");
-  for (const auto& table : simple_tables) {
-    tables.push_back(table);
-  }
-  return Status(0);
-}
-
-Status getQueryTables(const std::string& q, std::vector<std::string>& tables) {
-  PluginResponse response;
-  auto status = Registry::call(
-      "sql", "sql", {{"action", "tables"}, {"query", q}}, response);
-
-  for (const auto& table : response) {
-    tables.push_back(table.at("t"));
-  }
-  return status;
+                                                 std::vector<std::string>& tables)
+{
+       std::transform(copy_q.begin(), copy_q.end(), copy_q.begin(), ::tolower);
+       auto offset_from = copy_q.find("from ");
+       if (offset_from == std::string::npos) {
+               return Status(1);
+       }
+
+       auto simple_tables = osquery::split(copy_q.substr(offset_from + 5), ",");
+       for (const auto& table : simple_tables) {
+               tables.push_back(table);
+       }
+       return Status(0);
+}
+
+Status getQueryTables(const std::string& q, std::vector<std::string>& tables)
+{
+       PluginResponse response;
+       auto status = Registry::call(
+       "sql", "sql", {{"action", "tables"}, {"query", q}}, response);
+
+       for (const auto& table : response) {
+               tables.push_back(table.at("t"));
+       }
+       return status;
 }
 }
index b38a8394a3f4f42b234f4c5d1780ec800a0126e2..9656324002714a87cb63e30342bddc2222502698 100644 (file)
@@ -35,31 +35,31 @@ using SQLiteDBInstanceRef = std::shared_ptr<SQLiteDBInstance>;
  */
 // clang-format off
 const std::map<int, std::string> kSQLiteReturnCodes = {
-    {0, "SQLITE_OK"},        {1, "SQLITE_ERROR"},       {2, "SQLITE_INTERNAL"},
-    {3, "SQLITE_PERM"},      {4, "SQLITE_ABORT"},       {5, "SQLITE_BUSY"},
-    {6, "SQLITE_LOCKED"},    {7, "SQLITE_NOMEM"},       {8, "SQLITE_READONLY"},
-    {9, "SQLITE_INTERRUPT"}, {10, "SQLITE_IOERR"},      {11, "SQLITE_CORRUPT"},
-    {12, "SQLITE_NOTFOUND"}, {13, "SQLITE_FULL"},       {14, "SQLITE_CANTOPEN"},
-    {15, "SQLITE_PROTOCOL"}, {16, "SQLITE_EMPTY"},      {17, "SQLITE_SCHEMA"},
-    {18, "SQLITE_TOOBIG"},   {19, "SQLITE_CONSTRAINT"}, {20, "SQLITE_MISMATCH"},
-    {21, "SQLITE_MISUSE"},   {22, "SQLITE_NOLFS"},      {23, "SQLITE_AUTH"},
-    {24, "SQLITE_FORMAT"},   {25, "SQLITE_RANGE"},      {26, "SQLITE_NOTADB"},
-    {27, "SQLITE_NOTICE"},   {28, "SQLITE_WARNING"},    {100, "SQLITE_ROW"},
-    {101, "SQLITE_DONE"},
+       {0, "SQLITE_OK"},        {1, "SQLITE_ERROR"},       {2, "SQLITE_INTERNAL"},
+       {3, "SQLITE_PERM"},      {4, "SQLITE_ABORT"},       {5, "SQLITE_BUSY"},
+       {6, "SQLITE_LOCKED"},    {7, "SQLITE_NOMEM"},       {8, "SQLITE_READONLY"},
+       {9, "SQLITE_INTERRUPT"}, {10, "SQLITE_IOERR"},      {11, "SQLITE_CORRUPT"},
+       {12, "SQLITE_NOTFOUND"}, {13, "SQLITE_FULL"},       {14, "SQLITE_CANTOPEN"},
+       {15, "SQLITE_PROTOCOL"}, {16, "SQLITE_EMPTY"},      {17, "SQLITE_SCHEMA"},
+       {18, "SQLITE_TOOBIG"},   {19, "SQLITE_CONSTRAINT"}, {20, "SQLITE_MISMATCH"},
+       {21, "SQLITE_MISUSE"},   {22, "SQLITE_NOLFS"},      {23, "SQLITE_AUTH"},
+       {24, "SQLITE_FORMAT"},   {25, "SQLITE_RANGE"},      {26, "SQLITE_NOTADB"},
+       {27, "SQLITE_NOTICE"},   {28, "SQLITE_WARNING"},    {100, "SQLITE_ROW"},
+       {101, "SQLITE_DONE"},
 };
 
 const std::map<std::string, std::string> kMemoryDBSettings = {
-    {"synchronous", "OFF"},      {"count_changes", "OFF"},
-    {"default_temp_store", "0"}, {"auto_vacuum", "FULL"},
-    {"journal_mode", "OFF"},     {"cache_size", "0"},
-    {"page_count", "0"},
+       {"synchronous", "OFF"},      {"count_changes", "OFF"},
+       {"default_temp_store", "0"}, {"auto_vacuum", "FULL"},
+       {"journal_mode", "OFF"},     {"cache_size", "0"},
+       {"page_count", "0"},
 };
 // clang-format on
 
 #define OpComparator(x)                                                        \
-  { x, QueryPlanner::Opcode(OpReg::P2, INTEGER_TYPE) }
+       { x, QueryPlanner::Opcode(OpReg::P2, INTEGER_TYPE) }
 #define Arithmetic(x)                                                          \
-  { x, QueryPlanner::Opcode(OpReg::P3, BIGINT_TYPE) }
+       { x, QueryPlanner::Opcode(OpReg::P3, BIGINT_TYPE) }
 
 /**
  * @brief A map from opcode to pair of result register and resultant type.
@@ -69,125 +69,133 @@ const std::map<std::string, std::string> kMemoryDBSettings = {
  * comparators, aggregates, and copies.
  */
 const std::map<std::string, QueryPlanner::Opcode> kSQLOpcodes = {
-    {"Concat", QueryPlanner::Opcode(OpReg::P3, TEXT_TYPE)},
-    {"AggStep", QueryPlanner::Opcode(OpReg::P3, BIGINT_TYPE)},
-    {"AggStep0", QueryPlanner::Opcode(OpReg::P3, BIGINT_TYPE)},
-    {"Integer", QueryPlanner::Opcode(OpReg::P2, INTEGER_TYPE)},
-    {"Int64", QueryPlanner::Opcode(OpReg::P2, BIGINT_TYPE)},
-    {"String", QueryPlanner::Opcode(OpReg::P2, TEXT_TYPE)},
-    {"String8", QueryPlanner::Opcode(OpReg::P2, TEXT_TYPE)},
-    {"Or", QueryPlanner::Opcode(OpReg::P3, INTEGER_TYPE)},
-    {"And", QueryPlanner::Opcode(OpReg::P3, INTEGER_TYPE)},
-
-    // Arithmetic yields a BIGINT for safety.
-    Arithmetic("BitAnd"),
-    Arithmetic("BitOr"),
-    Arithmetic("ShiftLeft"),
-    Arithmetic("ShiftRight"),
-    Arithmetic("Add"),
-    Arithmetic("Subtract"),
-    Arithmetic("Multiply"),
-    Arithmetic("Divide"),
-    Arithmetic("Remainder"),
-
-    // Comparators result in booleans and are treated as INTEGERs.
-    OpComparator("Not"),
-    OpComparator("IsNull"),
-    OpComparator("NotNull"),
-    OpComparator("Ne"),
-    OpComparator("Eq"),
-    OpComparator("Gt"),
-    OpComparator("Le"),
-    OpComparator("Lt"),
-    OpComparator("Ge"),
-    OpComparator("IfNeg"),
-    OpComparator("IfNotZero"),
+       {"Concat", QueryPlanner::Opcode(OpReg::P3, TEXT_TYPE)},
+       {"AggStep", QueryPlanner::Opcode(OpReg::P3, BIGINT_TYPE)},
+       {"AggStep0", QueryPlanner::Opcode(OpReg::P3, BIGINT_TYPE)},
+       {"Integer", QueryPlanner::Opcode(OpReg::P2, INTEGER_TYPE)},
+       {"Int64", QueryPlanner::Opcode(OpReg::P2, BIGINT_TYPE)},
+       {"String", QueryPlanner::Opcode(OpReg::P2, TEXT_TYPE)},
+       {"String8", QueryPlanner::Opcode(OpReg::P2, TEXT_TYPE)},
+       {"Or", QueryPlanner::Opcode(OpReg::P3, INTEGER_TYPE)},
+       {"And", QueryPlanner::Opcode(OpReg::P3, INTEGER_TYPE)},
+
+       // Arithmetic yields a BIGINT for safety.
+       Arithmetic("BitAnd"),
+       Arithmetic("BitOr"),
+       Arithmetic("ShiftLeft"),
+       Arithmetic("ShiftRight"),
+       Arithmetic("Add"),
+       Arithmetic("Subtract"),
+       Arithmetic("Multiply"),
+       Arithmetic("Divide"),
+       Arithmetic("Remainder"),
+
+       // Comparators result in booleans and are treated as INTEGERs.
+       OpComparator("Not"),
+       OpComparator("IsNull"),
+       OpComparator("NotNull"),
+       OpComparator("Ne"),
+       OpComparator("Eq"),
+       OpComparator("Gt"),
+       OpComparator("Le"),
+       OpComparator("Lt"),
+       OpComparator("Ge"),
+       OpComparator("IfNeg"),
+       OpComparator("IfNotZero"),
 };
 
 RecursiveMutex SQLiteDBInstance::kPrimaryAttachMutex;
 
 /// The SQLiteSQLPlugin implements the "sql" registry for internal/core.
 class SQLiteSQLPlugin : public SQLPlugin {
- public:
-  /// Execute SQL and store results.
-  Status query(const std::string& query,
-               QueryData& results,
-               bool use_cache) const override;
+public:
+       /// Execute SQL and store results.
+       Status query(const std::string& query,
+                                QueryData& results,
+                                bool use_cache) const override;
 
-  /// Introspect, explain, the suspected types selected in an SQL statement.
-  Status getQueryColumns(const std::string& query,
-                         TableColumns& columns) const override;
+       /// Introspect, explain, the suspected types selected in an SQL statement.
+       Status getQueryColumns(const std::string& query,
+                                                  TableColumns& columns) const override;
 
-  /// Similar to getQueryColumns but return the scanned tables.
-  Status getQueryTables(const std::string& query,
-                        std::vector<std::string>& tables) const override;
+       /// Similar to getQueryColumns but return the scanned tables.
+       Status getQueryTables(const std::string& query,
+                                                 std::vector<std::string>& tables) const override;
 
-  /// Create a SQLite module and attach (CREATE).
-  Status attach(const std::string& name) override;
+       /// Create a SQLite module and attach (CREATE).
+       Status attach(const std::string& name) override;
 
-  /// Detach a virtual table (DROP).
-  void detach(const std::string& name) override;
+       /// Detach a virtual table (DROP).
+       void detach(const std::string& name) override;
 };
 
 /// SQL provider for osquery internal/core.
 REGISTER_INTERNAL(SQLiteSQLPlugin, "sql", "sql");
 
-std::string getStringForSQLiteReturnCode(int code) {
-  if (kSQLiteReturnCodes.find(code) != kSQLiteReturnCodes.end()) {
-    return kSQLiteReturnCodes.at(code);
-  } else {
-    std::ostringstream s;
-    s << "Error: " << code << " is not a valid SQLite result code";
-    return s.str();
-  }
+std::string getStringForSQLiteReturnCode(int code)
+{
+       if (kSQLiteReturnCodes.find(code) != kSQLiteReturnCodes.end()) {
+               return kSQLiteReturnCodes.at(code);
+       } else {
+               std::ostringstream s;
+               s << "Error: " << code << " is not a valid SQLite result code";
+               return s.str();
+       }
 }
 
 Status SQLiteSQLPlugin::query(const std::string& query,
-                              QueryData& results,
-                              bool use_cache) const {
-  auto dbc = SQLiteDBManager::get();
-  dbc->useCache(use_cache);
-  auto result = queryInternal(query, results, dbc);
-  dbc->clearAffectedTables();
-  return result;
+                                                         QueryData& results,
+                                                         bool use_cache) const
+{
+       auto dbc = SQLiteDBManager::get();
+       dbc->useCache(use_cache);
+       auto result = queryInternal(query, results, dbc);
+       dbc->clearAffectedTables();
+       return result;
 }
 
 Status SQLiteSQLPlugin::getQueryColumns(const std::string& query,
-                                        TableColumns& columns) const {
-  auto dbc = SQLiteDBManager::get();
-  return getQueryColumnsInternal(query, columns, dbc);
+                                                                               TableColumns& columns) const
+{
+       auto dbc = SQLiteDBManager::get();
+       return getQueryColumnsInternal(query, columns, dbc);
 }
 
 Status SQLiteSQLPlugin::getQueryTables(const std::string& query,
-                                       std::vector<std::string>& tables) const {
-  auto dbc = SQLiteDBManager::get();
-  QueryPlanner planner(query, dbc);
-  tables = planner.tables();
-  return Status(0);
+                                                                          std::vector<std::string>& tables) const
+{
+       auto dbc = SQLiteDBManager::get();
+       QueryPlanner planner(query, dbc);
+       tables = planner.tables();
+       return Status(0);
 }
 
-SQLInternal::SQLInternal(const std::string& query, bool use_cache) {
-  auto dbc = SQLiteDBManager::get();
-  dbc->useCache(use_cache);
-  status_ = queryInternal(query, resultsTyped_, dbc);
+SQLInternal::SQLInternal(const std::string& query, bool use_cache)
+{
+       auto dbc = SQLiteDBManager::get();
+       dbc->useCache(use_cache);
+       status_ = queryInternal(query, resultsTyped_, dbc);
 
-  // One of the advantages of using SQLInternal (aside from the Registry-bypass)
-  // is the ability to "deep-inspect" the table attributes and actions.
-  event_based_ = (dbc->getAttributes() & TableAttributes::EVENT_BASED) != 0;
+       // One of the advantages of using SQLInternal (aside from the Registry-bypass)
+       // is the ability to "deep-inspect" the table attributes and actions.
+       event_based_ = (dbc->getAttributes() & TableAttributes::EVENT_BASED) != 0;
 
-  dbc->clearAffectedTables();
+       dbc->clearAffectedTables();
 }
 
-QueryDataTyped& SQLInternal::rowsTyped() {
-  return resultsTyped_;
+QueryDataTyped& SQLInternal::rowsTyped()
+{
+       return resultsTyped_;
 }
 
-const Status& SQLInternal::getStatus() const {
-  return status_;
+const Status& SQLInternal::getStatus() const
+{
+       return status_;
 }
 
-bool SQLInternal::eventBased() const {
-  return event_based_;
+bool SQLInternal::eventBased() const
+{
+       return event_based_;
 }
 
 // Temporary:  I'm going to move this from sql.cpp to here in change immediately
@@ -196,452 +204,481 @@ bool SQLInternal::eventBased() const {
 extern void escapeNonPrintableBytesEx(std::string& str);
 
 class StringEscaperVisitor : public boost::static_visitor<> {
- public:
-  void operator()(long long& i) const { // NO-OP
-  }
-
-  void operator()(double& d) const { // NO-OP
-  }
-
-  void operator()(std::string& str) const {
-    escapeNonPrintableBytesEx(str);
-  }
+public:
+       void operator()(long long& i) const   // NO-OP
+       {
+       }
+
+       void operator()(double& d) const   // NO-OP
+       {
+       }
+
+       void operator()(std::string& str) const
+       {
+               escapeNonPrintableBytesEx(str);
+       }
 };
 
-void SQLInternal::escapeResults() {
-  StringEscaperVisitor visitor;
-  for (auto& rowTyped : resultsTyped_) {
-    for (auto& column : rowTyped) {
-      boost::apply_visitor(visitor, column.second);
-    }
-  }
+void SQLInternal::escapeResults()
+{
+       StringEscaperVisitor visitor;
+       for (auto& rowTyped : resultsTyped_) {
+               for (auto& column : rowTyped) {
+                       boost::apply_visitor(visitor, column.second);
+               }
+       }
 }
 
-Status SQLiteSQLPlugin::attach(const std::string& name) {
-  PluginResponse response;
-  auto status =
-      Registry::call("table", name, {{"action", "columns"}}, response);
-  if (!status.ok()) {
-    return status;
-  }
+Status SQLiteSQLPlugin::attach(const std::string& name)
+{
+       PluginResponse response;
+       auto status =
+       Registry::call("table", name, {{"action", "columns"}}, response);
+       if (!status.ok()) {
+               return status;
+       }
 
-  bool is_extension = true;
-  auto statement = columnDefinition(response, false, is_extension);
+       bool is_extension = true;
+       auto statement = columnDefinition(response, false, is_extension);
 
-  // Attach requests occurring via the plugin/registry APIs must act on the
-  // primary database. To allow this, getConnection can explicitly request the
-  // primary instance and avoid the contention decisions.
-  auto dbc = SQLiteDBManager::getConnection(true);
+       // Attach requests occurring via the plugin/registry APIs must act on the
+       // primary database. To allow this, getConnection can explicitly request the
+       // primary instance and avoid the contention decisions.
+       auto dbc = SQLiteDBManager::getConnection(true);
 
-  // Attach as an extension, allowing read/write tables
-  return attachTableInternal(name, statement, dbc, is_extension);
+       // Attach as an extension, allowing read/write tables
+       return attachTableInternal(name, statement, dbc, is_extension);
 }
 
-void SQLiteSQLPlugin::detach(const std::string& name) {
-  auto dbc = SQLiteDBManager::get();
-  if (!dbc->isPrimary()) {
-    return;
-  }
-  detachTableInternal(name, dbc);
+void SQLiteSQLPlugin::detach(const std::string& name)
+{
+       auto dbc = SQLiteDBManager::get();
+       if (!dbc->isPrimary()) {
+               return;
+       }
+       detachTableInternal(name, dbc);
 }
 
 SQLiteDBInstance::SQLiteDBInstance(sqlite3*& db, Mutex& mtx)
-    : db_(db), lock_(mtx, std::try_to_lock) {
-  if (lock_.owns_lock()) {
-    primary_ = true;
-  } else {
-    db_ = nullptr;
-    DEBUG(OSQUERY) << "DBManager contention: opening transient SQLite database";
-    init();
-  }
+       : db_(db), lock_(mtx, std::try_to_lock)
+{
+       if (lock_.owns_lock()) {
+               primary_ = true;
+       } else {
+               db_ = nullptr;
+               DEBUG(OSQUERY) << "DBManager contention: opening transient SQLite database";
+               init();
+       }
 }
 
-static inline void openOptimized(sqlite3*& db) {
-  sqlite3_open(":memory:", &db);
+static inline void openOptimized(sqlite3*& db)
+{
+       sqlite3_open(":memory:", &db);
 
-  std::string settings;
-  for (const auto& setting : kMemoryDBSettings) {
-    settings += "PRAGMA " + setting.first + "=" + setting.second + "; ";
-  }
-  sqlite3_exec(db, settings.c_str(), nullptr, nullptr, nullptr);
+       std::string settings;
+       for (const auto& setting : kMemoryDBSettings) {
+               settings += "PRAGMA " + setting.first + "=" + setting.second + "; ";
+       }
+       sqlite3_exec(db, settings.c_str(), nullptr, nullptr, nullptr);
 }
 
-void SQLiteDBInstance::init() {
-  primary_ = false;
-  openOptimized(db_);
+void SQLiteDBInstance::init()
+{
+       primary_ = false;
+       openOptimized(db_);
 }
 
-void SQLiteDBInstance::useCache(bool use_cache) {
-  use_cache_ = use_cache;
+void SQLiteDBInstance::useCache(bool use_cache)
+{
+       use_cache_ = use_cache;
 }
 
-bool SQLiteDBInstance::useCache() const {
-  return use_cache_;
+bool SQLiteDBInstance::useCache() const
+{
+       return use_cache_;
 }
 
-RecursiveLock SQLiteDBInstance::attachLock() const {
-  if (isPrimary()) {
-    return RecursiveLock(kPrimaryAttachMutex);
-  }
-  return RecursiveLock(attach_mutex_);
+RecursiveLock SQLiteDBInstance::attachLock() const
+{
+       if (isPrimary()) {
+               return RecursiveLock(kPrimaryAttachMutex);
+       }
+       return RecursiveLock(attach_mutex_);
 }
 
 void SQLiteDBInstance::addAffectedTable(
-    std::shared_ptr<VirtualTableContent> table) {
-  // An xFilter/scan was requested for this virtual table.
-  affected_tables_.insert(std::make_pair(table->name, std::move(table)));
-}
-
-bool SQLiteDBInstance::tableCalled(VirtualTableContent const& table) {
-  return (affected_tables_.count(table.name) > 0);
-}
-
-TableAttributes SQLiteDBInstance::getAttributes() const {
-  const SQLiteDBInstance* rdbc = this;
-  if (isPrimary() && !managed_) {
-    // Similarly to clearAffectedTables, the connection may be forwarded.
-    rdbc = SQLiteDBManager::getConnection(true).get();
-  }
-
-  TableAttributes attributes = TableAttributes::NONE;
-  for (const auto& table : rdbc->affected_tables_) {
-    attributes = table.second->attributes | attributes;
-  }
-  return attributes;
-}
-
-void SQLiteDBInstance::clearAffectedTables() {
-  if (isPrimary() && !managed_) {
-    // A primary instance must forward clear requests to the DB manager's
-    // 'connection' instance. This is a temporary primary instance.
-    SQLiteDBManager::getConnection(true)->clearAffectedTables();
-    return;
-  }
-
-  for (const auto& table : affected_tables_) {
-    table.second->constraints.clear();
-    table.second->cache.clear();
-    table.second->colsUsed.clear();
-    table.second->colsUsedBitsets.clear();
-  }
-  // Since the affected tables are cleared, there are no more affected tables.
-  // There is no concept of compounding tables between queries.
-  affected_tables_.clear();
-  use_cache_ = false;
-}
-
-SQLiteDBInstance::~SQLiteDBInstance() {
-  if (!isPrimary() && db_ != nullptr) {
-    sqlite3_close(db_);
-  } else {
-    db_ = nullptr;
-  }
-}
-
-SQLiteDBManager::SQLiteDBManager() : db_(nullptr) {
-  sqlite3_soft_heap_limit64(1);
-}
-
-bool SQLiteDBManager::isDisabled(const std::string& table_name) {
-  const auto& element = instance().disabled_tables_.find(table_name);
-  return (element != instance().disabled_tables_.end());
-}
-
-void SQLiteDBManager::resetPrimary() {
-  auto& self = instance();
-
-  WriteLock connection_lock(self.mutex_);
-  self.connection_.reset();
-
-  {
-    WriteLock create_lock(self.create_mutex_);
-    sqlite3_close(self.db_);
-    self.db_ = nullptr;
-  }
-}
-
-SQLiteDBInstanceRef SQLiteDBManager::getUnique() {
-  auto instance = std::make_shared<SQLiteDBInstance>();
-  attachVirtualTables(instance);
-  return instance;
-}
-
-SQLiteDBInstanceRef SQLiteDBManager::getConnection(bool primary) {
-  auto& self = instance();
-  WriteLock lock(self.create_mutex_);
-
-  if (self.db_ == nullptr) {
-    // Create primary SQLite DB instance.
-    openOptimized(self.db_);
-    self.connection_ = SQLiteDBInstanceRef(new SQLiteDBInstance(self.db_));
-    attachVirtualTables(self.connection_);
-  }
-
-  // Internal usage may request the primary connection explicitly.
-  if (primary) {
-    return self.connection_;
-  }
-
-  // Create a 'database connection' for the managed database instance.
-  auto instance = std::make_shared<SQLiteDBInstance>(self.db_, self.mutex_);
-  if (!instance->isPrimary()) {
-    attachVirtualTables(instance);
-  }
-  return instance;
-}
+       std::shared_ptr<VirtualTableContent> table)
+{
+       // An xFilter/scan was requested for this virtual table.
+       affected_tables_.insert(std::make_pair(table->name, std::move(table)));
+}
+
+bool SQLiteDBInstance::tableCalled(VirtualTableContent const& table)
+{
+       return (affected_tables_.count(table.name) > 0);
+}
+
+TableAttributes SQLiteDBInstance::getAttributes() const
+{
+       const SQLiteDBInstance* rdbc = this;
+       if (isPrimary() && !managed_) {
+               // Similarly to clearAffectedTables, the connection may be forwarded.
+               rdbc = SQLiteDBManager::getConnection(true).get();
+       }
+
+       TableAttributes attributes = TableAttributes::NONE;
+       for (const auto& table : rdbc->affected_tables_) {
+               attributes = table.second->attributes | attributes;
+       }
+       return attributes;
+}
+
+void SQLiteDBInstance::clearAffectedTables()
+{
+       if (isPrimary() && !managed_) {
+               // A primary instance must forward clear requests to the DB manager's
+               // 'connection' instance. This is a temporary primary instance.
+               SQLiteDBManager::getConnection(true)->clearAffectedTables();
+               return;
+       }
+
+       for (const auto& table : affected_tables_) {
+               table.second->constraints.clear();
+               table.second->cache.clear();
+               table.second->colsUsed.clear();
+               table.second->colsUsedBitsets.clear();
+       }
+       // Since the affected tables are cleared, there are no more affected tables.
+       // There is no concept of compounding tables between queries.
+       affected_tables_.clear();
+       use_cache_ = false;
+}
+
+SQLiteDBInstance::~SQLiteDBInstance()
+{
+       if (!isPrimary() && db_ != nullptr) {
+               sqlite3_close(db_);
+       } else {
+               db_ = nullptr;
+       }
+}
+
+SQLiteDBManager::SQLiteDBManager() : db_(nullptr)
+{
+       sqlite3_soft_heap_limit64(1);
+}
+
+bool SQLiteDBManager::isDisabled(const std::string& table_name)
+{
+       const auto& element = instance().disabled_tables_.find(table_name);
+       return (element != instance().disabled_tables_.end());
+}
+
+void SQLiteDBManager::resetPrimary()
+{
+       auto& self = instance();
+
+       WriteLock connection_lock(self.mutex_);
+       self.connection_.reset();
+
+       {
+               WriteLock create_lock(self.create_mutex_);
+               sqlite3_close(self.db_);
+               self.db_ = nullptr;
+       }
+}
+
+SQLiteDBInstanceRef SQLiteDBManager::getUnique()
+{
+       auto instance = std::make_shared<SQLiteDBInstance>();
+       attachVirtualTables(instance);
+       return instance;
+}
+
+SQLiteDBInstanceRef SQLiteDBManager::getConnection(bool primary)
+{
+       auto& self = instance();
+       WriteLock lock(self.create_mutex_);
+
+       if (self.db_ == nullptr) {
+               // Create primary SQLite DB instance.
+               openOptimized(self.db_);
+               self.connection_ = SQLiteDBInstanceRef(new SQLiteDBInstance(self.db_));
+               attachVirtualTables(self.connection_);
+       }
+
+       // Internal usage may request the primary connection explicitly.
+       if (primary) {
+               return self.connection_;
+       }
 
-SQLiteDBManager::~SQLiteDBManager() {
-  connection_ = nullptr;
-  if (db_ != nullptr) {
-    sqlite3_close(db_);
-    db_ = nullptr;
-  }
+       // Create a 'database connection' for the managed database instance.
+       auto instance = std::make_shared<SQLiteDBInstance>(self.db_, self.mutex_);
+       if (!instance->isPrimary()) {
+               attachVirtualTables(instance);
+       }
+       return instance;
+}
+
+SQLiteDBManager::~SQLiteDBManager()
+{
+       connection_ = nullptr;
+       if (db_ != nullptr) {
+               sqlite3_close(db_);
+               db_ = nullptr;
+       }
 }
 
 QueryPlanner::QueryPlanner(const std::string& query,
-                           const SQLiteDBInstanceRef& instance) {
-  QueryData plan;
-  queryInternal("EXPLAIN QUERY PLAN " + query, plan, instance);
-  queryInternal("EXPLAIN " + query, program_, instance);
-
-  for (const auto& row : plan) {
-    auto details = osquery::split(row.at("detail"));
-    if (details.size() > 2 && details[0] == "SCAN") {
-      tables_.push_back(details[2]);
-    }
-  }
-}
-
-Status QueryPlanner::applyTypes(TableColumns& columns) {
-  std::map<size_t, ColumnType> column_types;
-  for (const auto& row : program_) {
-    if (row.at("opcode") == "ResultRow") {
-      // The column parsing is finished.
-      auto k = boost::lexical_cast<size_t>(row.at("p1"));
-      for (const auto& type : column_types) {
-        if (type.first - k < columns.size()) {
-          std::get<1>(columns[type.first - k]) = type.second;
-        }
-      }
-    }
-
-    if (row.at("opcode") == "Copy") {
-      // Copy P1 -> P1 + P3 into P2 -> P2 + P3.
-      auto from = boost::lexical_cast<size_t>(row.at("p1"));
-      auto to = boost::lexical_cast<size_t>(row.at("p2"));
-      auto size = boost::lexical_cast<size_t>(row.at("p3"));
-      for (size_t i = 0; i <= size; i++) {
-        if (column_types.count(from + i)) {
-          column_types[to + i] = std::move(column_types[from + i]);
-          column_types.erase(from + i);
-        }
-      }
-    } else if (row.at("opcode") == "Cast") {
-      auto value = boost::lexical_cast<size_t>(row.at("p1"));
-      auto to = boost::lexical_cast<size_t>(row.at("p2"));
-      switch (to) {
-      case 'A': // BLOB
-        column_types[value] = BLOB_TYPE;
-        break;
-      case 'B': // TEXT
-        column_types[value] = TEXT_TYPE;
-        break;
-      case 'C': // NUMERIC
-        // We don't exactly have an equivalent to NUMERIC (which includes such
-        // things as DATETIME and DECIMAL
-        column_types[value] = UNKNOWN_TYPE;
-        break;
-      case 'D': // INTEGER
-        column_types[value] = BIGINT_TYPE;
-        break;
-      case 'E': // REAL
-        column_types[value] = DOUBLE_TYPE;
-        break;
-      default:
-        column_types[value] = UNKNOWN_TYPE;
-        break;
-      }
-    }
-
-    if (kSQLOpcodes.count(row.at("opcode"))) {
-      const auto& op = kSQLOpcodes.at(row.at("opcode"));
-      auto k = boost::lexical_cast<size_t>(row.at(Opcode::regString(op.reg)));
-      column_types[k] = op.type;
-    }
-  }
-
-  return Status(0);
+                                                  const SQLiteDBInstanceRef& instance)
+{
+       QueryData plan;
+       queryInternal("EXPLAIN QUERY PLAN " + query, plan, instance);
+       queryInternal("EXPLAIN " + query, program_, instance);
+
+       for (const auto& row : plan) {
+               auto details = osquery::split(row.at("detail"));
+               if (details.size() > 2 && details[0] == "SCAN") {
+                       tables_.push_back(details[2]);
+               }
+       }
+}
+
+Status QueryPlanner::applyTypes(TableColumns& columns)
+{
+       std::map<size_t, ColumnType> column_types;
+       for (const auto& row : program_) {
+               if (row.at("opcode") == "ResultRow") {
+                       // The column parsing is finished.
+                       auto k = boost::lexical_cast<size_t>(row.at("p1"));
+                       for (const auto& type : column_types) {
+                               if (type.first - k < columns.size()) {
+                                       std::get<1>(columns[type.first - k]) = type.second;
+                               }
+                       }
+               }
+
+               if (row.at("opcode") == "Copy") {
+                       // Copy P1 -> P1 + P3 into P2 -> P2 + P3.
+                       auto from = boost::lexical_cast<size_t>(row.at("p1"));
+                       auto to = boost::lexical_cast<size_t>(row.at("p2"));
+                       auto size = boost::lexical_cast<size_t>(row.at("p3"));
+                       for (size_t i = 0; i <= size; i++) {
+                               if (column_types.count(from + i)) {
+                                       column_types[to + i] = std::move(column_types[from + i]);
+                                       column_types.erase(from + i);
+                               }
+                       }
+               } else if (row.at("opcode") == "Cast") {
+                       auto value = boost::lexical_cast<size_t>(row.at("p1"));
+                       auto to = boost::lexical_cast<size_t>(row.at("p2"));
+                       switch (to) {
+                       case 'A': // BLOB
+                               column_types[value] = BLOB_TYPE;
+                               break;
+                       case 'B': // TEXT
+                               column_types[value] = TEXT_TYPE;
+                               break;
+                       case 'C': // NUMERIC
+                               // We don't exactly have an equivalent to NUMERIC (which includes such
+                               // things as DATETIME and DECIMAL
+                               column_types[value] = UNKNOWN_TYPE;
+                               break;
+                       case 'D': // INTEGER
+                               column_types[value] = BIGINT_TYPE;
+                               break;
+                       case 'E': // REAL
+                               column_types[value] = DOUBLE_TYPE;
+                               break;
+                       default:
+                               column_types[value] = UNKNOWN_TYPE;
+                               break;
+                       }
+               }
+
+               if (kSQLOpcodes.count(row.at("opcode"))) {
+                       const auto& op = kSQLOpcodes.at(row.at("opcode"));
+                       auto k = boost::lexical_cast<size_t>(row.at(Opcode::regString(op.reg)));
+                       column_types[k] = op.type;
+               }
+       }
+
+       return Status(0);
 }
 
 // Wrapper for legacy method until all uses can be replaced
 Status queryInternal(const std::string& query,
-                     QueryData& results,
-                     const SQLiteDBInstanceRef& instance) {
-  QueryDataTyped typedResults;
-  Status status = queryInternal(query, typedResults, instance);
-  if (status.ok()) {
-    results.reserve(typedResults.size());
-    for (const auto& row : typedResults) {
-      Row r;
-      for (const auto& col : row) {
-        r[col.first] = castVariant(col.second);
-      }
-      results.push_back(std::move(r));
-    }
-  }
-  return status;
+                                        QueryData& results,
+                                        const SQLiteDBInstanceRef& instance)
+{
+       QueryDataTyped typedResults;
+       Status status = queryInternal(query, typedResults, instance);
+       if (status.ok()) {
+               results.reserve(typedResults.size());
+               for (const auto& row : typedResults) {
+                       Row r;
+                       for (const auto& col : row) {
+                               r[col.first] = castVariant(col.second);
+                       }
+                       results.push_back(std::move(r));
+               }
+       }
+       return status;
 }
 
 Status readRows(sqlite3_stmt* prepared_statement,
-                QueryDataTyped& results,
-                const SQLiteDBInstanceRef& instance) {
-  // Do nothing with a null prepared_statement (eg, if the sql was just
-  // whitespace)
-  if (prepared_statement == nullptr) {
-    return Status::success();
-  }
-  int rc = sqlite3_step(prepared_statement);
-  /* if we have a result set row... */
-  if (SQLITE_ROW == rc) {
-    // First collect the column names
-    int num_columns = sqlite3_column_count(prepared_statement);
-    std::vector<std::string> colNames;
-    colNames.reserve(num_columns);
-    for (int i = 0; i < num_columns; i++) {
-      colNames.push_back(sqlite3_column_name(prepared_statement, i));
-    }
-
-    do {
-      RowTyped row;
-      for (int i = 0; i < num_columns; i++) {
-        switch (sqlite3_column_type(prepared_statement, i)) {
-        case SQLITE_INTEGER:
-          row[colNames[i]] = static_cast<long long>(
-              sqlite3_column_int64(prepared_statement, i));
-          break;
-        case SQLITE_FLOAT:
-          row[colNames[i]] = sqlite3_column_double(prepared_statement, i);
-          break;
-        case SQLITE_NULL:
-          row[colNames[i]] = "";
-          break;
-        default:
-          // Everything else (SQLITE_TEXT, SQLITE3_TEXT, SQLITE_BLOB) is
-          // obtained/conveyed as text/string
-          row[colNames[i]] = std::string(reinterpret_cast<const char*>(
-              sqlite3_column_text(prepared_statement, i)));
-        }
-      }
-      results.push_back(std::move(row));
-      rc = sqlite3_step(prepared_statement);
-    } while (SQLITE_ROW == rc);
-  }
-  if (rc != SQLITE_DONE) {
-    return Status::failure(sqlite3_errmsg(instance->db()));
-  }
-
-  rc = sqlite3_finalize(prepared_statement);
-  if (rc != SQLITE_OK) {
-    return Status::failure(sqlite3_errmsg(instance->db()));
-  }
-
-  return Status::success();
+                               QueryDataTyped& results,
+                               const SQLiteDBInstanceRef& instance)
+{
+       // Do nothing with a null prepared_statement (eg, if the sql was just
+       // whitespace)
+       if (prepared_statement == nullptr) {
+               return Status::success();
+       }
+       int rc = sqlite3_step(prepared_statement);
+       /* if we have a result set row... */
+       if (SQLITE_ROW == rc) {
+               // First collect the column names
+               int num_columns = sqlite3_column_count(prepared_statement);
+               std::vector<std::string> colNames;
+               colNames.reserve(num_columns);
+               for (int i = 0; i < num_columns; i++) {
+                       colNames.push_back(sqlite3_column_name(prepared_statement, i));
+               }
+
+               do {
+                       RowTyped row;
+                       for (int i = 0; i < num_columns; i++) {
+                               switch (sqlite3_column_type(prepared_statement, i)) {
+                               case SQLITE_INTEGER:
+                                       row[colNames[i]] = static_cast<long long>(
+                                                                                  sqlite3_column_int64(prepared_statement, i));
+                                       break;
+                               case SQLITE_FLOAT:
+                                       row[colNames[i]] = sqlite3_column_double(prepared_statement, i);
+                                       break;
+                               case SQLITE_NULL:
+                                       row[colNames[i]] = "";
+                                       break;
+                               default:
+                                       // Everything else (SQLITE_TEXT, SQLITE3_TEXT, SQLITE_BLOB) is
+                                       // obtained/conveyed as text/string
+                                       row[colNames[i]] = std::string(reinterpret_cast<const char*>(
+                                                                                                          sqlite3_column_text(prepared_statement, i)));
+                               }
+                       }
+                       results.push_back(std::move(row));
+                       rc = sqlite3_step(prepared_statement);
+               } while (SQLITE_ROW == rc);
+       }
+       if (rc != SQLITE_DONE) {
+               return Status::failure(sqlite3_errmsg(instance->db()));
+       }
+
+       rc = sqlite3_finalize(prepared_statement);
+       if (rc != SQLITE_OK) {
+               return Status::failure(sqlite3_errmsg(instance->db()));
+       }
+
+       return Status::success();
 }
 
 Status queryInternal(const std::string& query,
-                     QueryDataTyped& results,
-                     const SQLiteDBInstanceRef& instance) {
-  sqlite3_stmt* prepared_statement{nullptr}; /* Statement to execute. */
-
-  int rc = SQLITE_OK; /* Return Code */
-  const char* leftover_sql = nullptr; /* Tail of unprocessed SQL */
-  const char* sql = query.c_str(); /* SQL to be processed */
-
-  /* The big while loop.  One iteration per statement */
-  while ((sql[0] != '\0') && (SQLITE_OK == rc)) {
-    const auto lock = instance->attachLock();
-
-    // Trim leading whitespace
-    while (isspace(sql[0])) {
-      sql++;
-    }
-    rc = sqlite3_prepare_v2(
-        instance->db(), sql, -1, &prepared_statement, &leftover_sql);
-    if (rc != SQLITE_OK) {
-      Status s = Status::failure(sqlite3_errmsg(instance->db()));
-      sqlite3_finalize(prepared_statement);
-      return s;
-    }
-
-    Status s = readRows(prepared_statement, results, instance);
-    if (!s.ok()) {
-      return s;
-    }
-
-    sql = leftover_sql;
-  } /* end while */
-  sqlite3_db_release_memory(instance->db());
-  return Status::success();
+                                        QueryDataTyped& results,
+                                        const SQLiteDBInstanceRef& instance)
+{
+       sqlite3_stmt* prepared_statement{nullptr}; /* Statement to execute. */
+
+       int rc = SQLITE_OK; /* Return Code */
+       const char* leftover_sql = nullptr; /* Tail of unprocessed SQL */
+       const char* sql = query.c_str(); /* SQL to be processed */
+
+       /* The big while loop.  One iteration per statement */
+       while ((sql[0] != '\0') && (SQLITE_OK == rc)) {
+               const auto lock = instance->attachLock();
+
+               // Trim leading whitespace
+               while (isspace(sql[0])) {
+                       sql++;
+               }
+               rc = sqlite3_prepare_v2(
+                                instance->db(), sql, -1, &prepared_statement, &leftover_sql);
+               if (rc != SQLITE_OK) {
+                       Status s = Status::failure(sqlite3_errmsg(instance->db()));
+                       sqlite3_finalize(prepared_statement);
+                       return s;
+               }
+
+               Status s = readRows(prepared_statement, results, instance);
+               if (!s.ok()) {
+                       return s;
+               }
+
+               sql = leftover_sql;
+       } /* end while */
+       sqlite3_db_release_memory(instance->db());
+       return Status::success();
 }
 
 Status getQueryColumnsInternal(const std::string& q,
-                               TableColumns& columns,
-                               const SQLiteDBInstanceRef& instance) {
-  Status status = Status();
-  TableColumns results;
-  {
-    auto lock = instance->attachLock();
-
-    // Turn the query into a prepared statement
-    sqlite3_stmt* stmt{nullptr};
-    auto rc = sqlite3_prepare_v2(instance->db(),
-                                 q.c_str(),
-                                 static_cast<int>(q.length() + 1),
-                                 &stmt,
-                                 nullptr);
-    if (rc != SQLITE_OK || stmt == nullptr) {
-      if (stmt != nullptr) {
-        sqlite3_finalize(stmt);
-      }
-      return Status(1, sqlite3_errmsg(instance->db()));
-    }
-
-    // Get column count
-    auto num_columns = sqlite3_column_count(stmt);
-    results.reserve(num_columns);
-
-    // Get column names and types
-    bool unknown_type = false;
-    for (int i = 0; i < num_columns; ++i) {
-      auto col_name = sqlite3_column_name(stmt, i);
-      auto col_type = sqlite3_column_decltype(stmt, i);
-
-      if (col_name == nullptr) {
-        status = Status(1, "Could not get column type");
-        break;
-      }
-
-      if (col_type == nullptr) {
-        // Types are only returned for table columns (not expressions).
-        col_type = "UNKNOWN";
-        unknown_type = true;
-      }
-      results.push_back(std::make_tuple(
-          col_name, columnTypeName(col_type), ColumnOptions::DEFAULT));
-    }
-
-    // An unknown type means we have to parse the plan and SQLite opcodes.
-    if (unknown_type) {
-      QueryPlanner planner(q, instance);
-      planner.applyTypes(results);
-    }
-    sqlite3_finalize(stmt);
-  }
-
-  if (status.ok()) {
-    columns = std::move(results);
-  }
-
-  return status;
+                                                          TableColumns& columns,
+                                                          const SQLiteDBInstanceRef& instance)
+{
+       Status status = Status();
+       TableColumns results;
+       {
+               auto lock = instance->attachLock();
+
+               // Turn the query into a prepared statement
+               sqlite3_stmt* stmt{nullptr};
+               auto rc = sqlite3_prepare_v2(instance->db(),
+                                                                        q.c_str(),
+                                                                        static_cast<int>(q.length() + 1),
+                                                                        &stmt,
+                                                                        nullptr);
+               if (rc != SQLITE_OK || stmt == nullptr) {
+                       if (stmt != nullptr) {
+                               sqlite3_finalize(stmt);
+                       }
+                       return Status(1, sqlite3_errmsg(instance->db()));
+               }
+
+               // Get column count
+               auto num_columns = sqlite3_column_count(stmt);
+               results.reserve(num_columns);
+
+               // Get column names and types
+               bool unknown_type = false;
+               for (int i = 0; i < num_columns; ++i) {
+                       auto col_name = sqlite3_column_name(stmt, i);
+                       auto col_type = sqlite3_column_decltype(stmt, i);
+
+                       if (col_name == nullptr) {
+                               status = Status(1, "Could not get column type");
+                               break;
+                       }
+
+                       if (col_type == nullptr) {
+                               // Types are only returned for table columns (not expressions).
+                               col_type = "UNKNOWN";
+                               unknown_type = true;
+                       }
+                       results.push_back(std::make_tuple(
+                                                                 col_name, columnTypeName(col_type), ColumnOptions::DEFAULT));
+               }
+
+               // An unknown type means we have to parse the plan and SQLite opcodes.
+               if (unknown_type) {
+                       QueryPlanner planner(q, instance);
+                       planner.applyTypes(results);
+               }
+               sqlite3_finalize(stmt);
+       }
+
+       if (status.ok()) {
+               columns = std::move(results);
+       }
+
+       return status;
 }
 } // namespace osquery
index a11a075e8465cab6ffe01e6d645a192982aaac83..55ad02b837bc2d1c99c6ea46b783be2cd5ededfd 100644 (file)
@@ -42,98 +42,101 @@ class SQLiteDBManager;
  * SQLiteDBInstance.
  */
 class SQLiteDBInstance : private boost::noncopyable {
- public:
-  SQLiteDBInstance() {
-    init();
-  }
-  SQLiteDBInstance(sqlite3*& db, Mutex& mtx);
-  ~SQLiteDBInstance();
-
-  /// Check if the instance is the osquery primary.
-  bool isPrimary() const {
-    return primary_;
-  }
-
-  /// Generate a new 'transient' connection.
-  void init();
-
-  /**
-   * @brief Accessor to the internal `sqlite3` object, do not store references
-   * to the object within osquery code.
-   */
-  sqlite3* db() const {
-    return db_;
-  }
-
-  /// Allow a virtual table implementation to record use/access of a table.
-  void addAffectedTable(std::shared_ptr<VirtualTableContent> table);
-
-  /// Clear per-query state of a table affected by the use of this instance.
-  void clearAffectedTables();
-
-  /// Check if a virtual table had been called already.
-  bool tableCalled(VirtualTableContent const& table);
-
-  /// Request that virtual tables use a warm cache for their results.
-  void useCache(bool use_cache);
-
-  /// Check if the query requested use of the warm query cache.
-  bool useCache() const;
-
-  /// Lock the database for attaching virtual tables.
-  RecursiveLock attachLock() const;
-
- private:
-  /// Handle the primary/forwarding requests for table attribute accesses.
-  TableAttributes getAttributes() const;
-
- private:
-  /// An opaque constructor only used by the DBManager.
-  explicit SQLiteDBInstance(sqlite3* db)
-      : primary_(true), managed_(true), db_(db) {}
-
- private:
-  /// Introspection into the database pointer, primary means managed.
-  bool primary_{false};
-
-  /// Track whether this instance is managed internally by the DB manager.
-  bool managed_{false};
-
-  /// True if this query should bypass table cache.
-  bool use_cache_{false};
-
-  /// Either the managed primary database or an ephemeral instance.
-  sqlite3* db_{nullptr};
-
-  /**
-   * @brief An attempted unique lock on the manager's primary database mutex.
-   *
-   * This lock is not always acquired. If it is then this instance has locked
-   * access to the 'primary' SQLite database.
-   */
-  WriteLock lock_;
-
-  /**
-   * @brief A mutex protecting access to this instance's SQLite database.
-   *
-   * Attaching, and other access, can occur async from the registry APIs.
-   *
-   * If a database is primary then the static attach mutex is used.
-   */
-  mutable RecursiveMutex attach_mutex_;
-
-  /// See attach_mutex_ but used for the primary database.
-  static RecursiveMutex kPrimaryAttachMutex;
-
-  /// Vector of tables that need their constraints cleared after execution.
-  std::map<std::string, std::shared_ptr<VirtualTableContent>> affected_tables_;
-
- private:
-  friend class SQLiteDBManager;
-  friend class SQLInternal;
-
- private:
-  FRIEND_TEST(SQLiteUtilTests, test_affected_tables);
+public:
+       SQLiteDBInstance()
+       {
+               init();
+       }
+       SQLiteDBInstance(sqlite3*& db, Mutex& mtx);
+       ~SQLiteDBInstance();
+
+       /// Check if the instance is the osquery primary.
+       bool isPrimary() const
+       {
+               return primary_;
+       }
+
+       /// Generate a new 'transient' connection.
+       void init();
+
+       /**
+        * @brief Accessor to the internal `sqlite3` object, do not store references
+        * to the object within osquery code.
+        */
+       sqlite3* db() const
+       {
+               return db_;
+       }
+
+       /// Allow a virtual table implementation to record use/access of a table.
+       void addAffectedTable(std::shared_ptr<VirtualTableContent> table);
+
+       /// Clear per-query state of a table affected by the use of this instance.
+       void clearAffectedTables();
+
+       /// Check if a virtual table had been called already.
+       bool tableCalled(VirtualTableContent const& table);
+
+       /// Request that virtual tables use a warm cache for their results.
+       void useCache(bool use_cache);
+
+       /// Check if the query requested use of the warm query cache.
+       bool useCache() const;
+
+       /// Lock the database for attaching virtual tables.
+       RecursiveLock attachLock() const;
+
+private:
+       /// Handle the primary/forwarding requests for table attribute accesses.
+       TableAttributes getAttributes() const;
+
+private:
+       /// An opaque constructor only used by the DBManager.
+       explicit SQLiteDBInstance(sqlite3* db)
+               : primary_(true), managed_(true), db_(db) {}
+
+private:
+       /// Introspection into the database pointer, primary means managed.
+       bool primary_{false};
+
+       /// Track whether this instance is managed internally by the DB manager.
+       bool managed_{false};
+
+       /// True if this query should bypass table cache.
+       bool use_cache_{false};
+
+       /// Either the managed primary database or an ephemeral instance.
+       sqlite3* db_{nullptr};
+
+       /**
+        * @brief An attempted unique lock on the manager's primary database mutex.
+        *
+        * This lock is not always acquired. If it is then this instance has locked
+        * access to the 'primary' SQLite database.
+        */
+       WriteLock lock_;
+
+       /**
+        * @brief A mutex protecting access to this instance's SQLite database.
+        *
+        * Attaching, and other access, can occur async from the registry APIs.
+        *
+        * If a database is primary then the static attach mutex is used.
+        */
+       mutable RecursiveMutex attach_mutex_;
+
+       /// See attach_mutex_ but used for the primary database.
+       static RecursiveMutex kPrimaryAttachMutex;
+
+       /// Vector of tables that need their constraints cleared after execution.
+       std::map<std::string, std::shared_ptr<VirtualTableContent>> affected_tables_;
+
+private:
+       friend class SQLiteDBManager;
+       friend class SQLInternal;
+
+private:
+       FRIEND_TEST(SQLiteUtilTests, test_affected_tables);
 };
 
 using SQLiteDBInstanceRef = std::shared_ptr<SQLiteDBInstance>;
@@ -146,89 +149,91 @@ using SQLiteDBInstanceRef = std::shared_ptr<SQLiteDBInstance>;
  * resources as well as provide optimization around resource access.
  */
 class SQLiteDBManager : private boost::noncopyable {
- public:
-  static SQLiteDBManager& instance() {
-    static SQLiteDBManager instance;
-    return instance;
-  }
-
-  /**
-   * @brief Return a fully configured `sqlite3` database object wrapper.
-   *
-   * An osquery database is basically just a SQLite3 database with several
-   * virtual tables attached. This method is the main abstraction for accessing
-   * SQLite3 databases within osquery.
-   *
-   * A RAII wrapper around the `sqlite3` database will manage attaching tables
-   * and freeing resources when the instance (connection per-say) goes out of
-   * scope. Using the SQLiteDBManager will also try to optimize the number of
-   * `sqlite3` databases in use by managing a single global instance and
-   * returning resource-safe transient databases if there's access contention.
-   *
-   * Note: osquery::initOsquery must be called before calling `get` in order
-   * for virtual tables to be registered.
-   *
-   * @return a SQLiteDBInstance with all virtual tables attached.
-   */
-  static SQLiteDBInstanceRef get() {
-    return getConnection();
-  }
-
-  /// See `get` but always return a transient DB connection (for testing).
-  static SQLiteDBInstanceRef getUnique();
-
-  /**
-   * @brief Reset the primary database connection.
-   *
-   * Over time it may be helpful to remove SQLite's arena.
-   * We can periodically close and re-initialize and connect virtual tables.
-   */
-  static void resetPrimary();
-
-  /**
-   * @brief Check if `table_name` is disabled.
-   *
-   * Check if `table_name` is in the list of tables passed in to the
-   * `--disable_tables` flag.
-   *
-   * @param The name of the Table to check.
-   * @return If `table_name` is disabled.
-   */
-  static bool isDisabled(const std::string& table_name);
-
- protected:
-  SQLiteDBManager();
-  virtual ~SQLiteDBManager();
-
- public:
-  SQLiteDBManager(SQLiteDBManager const&) = delete;
-  SQLiteDBManager& operator=(SQLiteDBManager const&) = delete;
-
- private:
-  /// Primary (managed) sqlite3 database.
-  sqlite3* db_{nullptr};
-
-  /// The primary connection maintains an opaque instance.
-  SQLiteDBInstanceRef connection_{nullptr};
-
-  /// Mutex and lock around sqlite3 access.
-  Mutex mutex_;
-
-  /// A write mutex for initializing the primary database.
-  Mutex create_mutex_;
-
-  /// Member variable to hold set of disabled tables.
-  std::unordered_set<std::string> disabled_tables_;
-
-  /// Parse a comma-delimited set of tables names, passed in as a flag.
-  void setDisabledTables(const std::string& s);
-
-  /// Request a connection, optionally request the primary connection.
-  static SQLiteDBInstanceRef getConnection(bool primary = false);
-
- private:
-  friend class SQLiteDBInstance;
-  friend class SQLiteSQLPlugin;
+public:
+       static SQLiteDBManager& instance()
+       {
+               static SQLiteDBManager instance;
+               return instance;
+       }
+
+       /**
+        * @brief Return a fully configured `sqlite3` database object wrapper.
+        *
+        * An osquery database is basically just a SQLite3 database with several
+        * virtual tables attached. This method is the main abstraction for accessing
+        * SQLite3 databases within osquery.
+        *
+        * A RAII wrapper around the `sqlite3` database will manage attaching tables
+        * and freeing resources when the instance (connection per-say) goes out of
+        * scope. Using the SQLiteDBManager will also try to optimize the number of
+        * `sqlite3` databases in use by managing a single global instance and
+        * returning resource-safe transient databases if there's access contention.
+        *
+        * Note: osquery::initOsquery must be called before calling `get` in order
+        * for virtual tables to be registered.
+        *
+        * @return a SQLiteDBInstance with all virtual tables attached.
+        */
+       static SQLiteDBInstanceRef get()
+       {
+               return getConnection();
+       }
+
+       /// See `get` but always return a transient DB connection (for testing).
+       static SQLiteDBInstanceRef getUnique();
+
+       /**
+        * @brief Reset the primary database connection.
+        *
+        * Over time it may be helpful to remove SQLite's arena.
+        * We can periodically close and re-initialize and connect virtual tables.
+        */
+       static void resetPrimary();
+
+       /**
+        * @brief Check if `table_name` is disabled.
+        *
+        * Check if `table_name` is in the list of tables passed in to the
+        * `--disable_tables` flag.
+        *
+        * @param The name of the Table to check.
+        * @return If `table_name` is disabled.
+        */
+       static bool isDisabled(const std::string& table_name);
+
+protected:
+       SQLiteDBManager();
+       virtual ~SQLiteDBManager();
+
+public:
+       SQLiteDBManager(SQLiteDBManager const&) = delete;
+       SQLiteDBManager& operator=(SQLiteDBManager const&) = delete;
+
+private:
+       /// Primary (managed) sqlite3 database.
+       sqlite3* db_{nullptr};
+
+       /// The primary connection maintains an opaque instance.
+       SQLiteDBInstanceRef connection_{nullptr};
+
+       /// Mutex and lock around sqlite3 access.
+       Mutex mutex_;
+
+       /// A write mutex for initializing the primary database.
+       Mutex create_mutex_;
+
+       /// Member variable to hold set of disabled tables.
+       std::unordered_set<std::string> disabled_tables_;
+
+       /// Parse a comma-delimited set of tables names, passed in as a flag.
+       void setDisabledTables(const std::string& s);
+
+       /// Request a connection, optionally request the primary connection.
+       static SQLiteDBInstanceRef getConnection(bool primary = false);
+
+private:
+       friend class SQLiteDBInstance;
+       friend class SQLiteSQLPlugin;
 };
 
 /**
@@ -242,61 +247,63 @@ class SQLiteDBManager : private boost::noncopyable {
  * once per new query and only when needed (aka an unusable expression).
  */
 class QueryPlanner : private boost::noncopyable {
- public:
-  explicit QueryPlanner(const std::string& query)
-      : QueryPlanner(query, SQLiteDBManager::get()) {}
-  QueryPlanner(const std::string& query, const SQLiteDBInstanceRef& instance);
-  ~QueryPlanner() {}
-
- public:
-  /**
-   * @brief Scan the plan and program for opcodes that infer types.
-   *
-   * This allows column type inference based on column expressions. The query
-   * column introspection may use a QueryPlanner to apply types to the unknown
-   * columns (which are usually expressions).
-   *
-   * @param column an ordered set of columns to fill in type information.
-   * @return success if all columns types were found, otherwise false.
-   */
-  Status applyTypes(TableColumns& columns);
-
-  /// Get the list of tables filtered by this query.
-  std::vector<std::string> tables() const {
-    return tables_;
-  }
-
-  /**
-   * @brief A helper structure to represent an opcode's result and type.
-   *
-   * An opcode can be defined by a register and type, for the sake of the
-   * only known use case of resultant type determination.
-   */
-  struct Opcode {
-    enum Register {
-      P1 = 0,
-      P2,
-      P3,
-    };
-
-    Register reg;
-    ColumnType type;
-
-   public:
-    Opcode(Register r, ColumnType t) : reg(r), type(t) {}
-
-    /// Return a register as its column string name.
-    static std::string regString(Register r) {
-      static std::vector<std::string> regs = {"p1", "p2", "p3"};
-      return regs[r];
-    }
-  };
-
- private:
-  /// The results of EXPLAIN q.
-  QueryData program_;
-  /// The order of tables scanned.
-  std::vector<std::string> tables_;
+public:
+       explicit QueryPlanner(const std::string& query)
+               : QueryPlanner(query, SQLiteDBManager::get()) {}
+       QueryPlanner(const std::string& query, const SQLiteDBInstanceRef& instance);
+       ~QueryPlanner() {}
+
+public:
+       /**
+        * @brief Scan the plan and program for opcodes that infer types.
+        *
+        * This allows column type inference based on column expressions. The query
+        * column introspection may use a QueryPlanner to apply types to the unknown
+        * columns (which are usually expressions).
+        *
+        * @param column an ordered set of columns to fill in type information.
+        * @return success if all columns types were found, otherwise false.
+        */
+       Status applyTypes(TableColumns& columns);
+
+       /// Get the list of tables filtered by this query.
+       std::vector<std::string> tables() const
+       {
+               return tables_;
+       }
+
+       /**
+        * @brief A helper structure to represent an opcode's result and type.
+        *
+        * An opcode can be defined by a register and type, for the sake of the
+        * only known use case of resultant type determination.
+        */
+       struct Opcode {
+               enum Register {
+                       P1 = 0,
+                       P2,
+                       P3,
+               };
+
+               Register reg;
+               ColumnType type;
+
+       public:
+               Opcode(Register r, ColumnType t) : reg(r), type(t) {}
+
+               /// Return a register as its column string name.
+               static std::string regString(Register r)
+               {
+                       static std::vector<std::string> regs = {"p1", "p2", "p3"};
+                       return regs[r];
+               }
+       };
+
+private:
+       /// The results of EXPLAIN q.
+       QueryData program_;
+       /// The order of tables scanned.
+       std::vector<std::string> tables_;
 };
 
 /// Specific SQLite opcodes that change column/expression type.
@@ -316,8 +323,8 @@ extern const std::map<std::string, QueryPlanner::Opcode> kSQLOpcodes;
  * @return A status indicating SQL query results.
  */
 Status queryInternal(const std::string& q,
-                     QueryDataTyped& results,
-                     const SQLiteDBInstanceRef& instance);
+                                        QueryDataTyped& results,
+                                        const SQLiteDBInstanceRef& instance);
 
 /**
  * @brief SQLite Internal: Execute a query on a specific database
@@ -333,8 +340,8 @@ Status queryInternal(const std::string& q,
  * @return A status indicating SQL query results.
  */
 Status queryInternal(const std::string& q,
-                     QueryData& results,
-                     const SQLiteDBInstanceRef& instance);
+                                        QueryData& results,
+                                        const SQLiteDBInstanceRef& instance);
 
 /**
  * @brief SQLite Intern: Analyze a query, providing information about the
@@ -352,57 +359,57 @@ Status queryInternal(const std::string& q,
  * @return status indicating success or failure of the operation
  */
 Status getQueryColumnsInternal(const std::string& q,
-                               TableColumns& columns,
-                               const SQLiteDBInstanceRef& instance);
+                                                          TableColumns& columns,
+                                                          const SQLiteDBInstanceRef& instance);
 
 /**
  * @brief SQLInternal: like SQL, but backed by internal calls, and deals
  * with QueryDataTyped results.
  */
 class SQLInternal : private only_movable {
- public:
-  /**
-   * @brief Instantiate an instance of the class with an internal query.
-   *
-   * @param query An osquery SQL query.
-   * @param use_cache [optional] Set true to use the query cache.
-   */
-  explicit SQLInternal(const std::string& query, bool use_cache = false);
-
- public:
-  /**
-   * @brief Const accessor for the rows returned by the query.
-   *
-   * @return A QueryDataTyped object of the query results.
-   */
-  QueryDataTyped& rowsTyped();
-
-  const Status& getStatus() const;
-
-  /**
-   * @brief Check if the SQL query's results use event-based tables.
-   *
-   * Higher level SQL facilities, like the scheduler, may act differently when
-   * the results of a query (including a JOIN) are event-based. For example,
-   * it does not make sense to perform set difference checks for an
-   * always-append result set.
-   *
-   * All the tables used in the query will be checked. The TableAttributes of
-   * each will be ORed and if any include EVENT_BASED, this will return true.
-   */
-  bool eventBased() const;
-
-  /// ASCII escape the results of the query.
-  void escapeResults();
-
- private:
-  /// The internal member which holds the typed results of the query.
-  QueryDataTyped resultsTyped_;
-
-  /// The internal member which holds the status of the query.
-  Status status_;
-  /// Before completing the execution, store a check for EVENT_BASED.
-  bool event_based_{false};
+public:
+       /**
+        * @brief Instantiate an instance of the class with an internal query.
+        *
+        * @param query An osquery SQL query.
+        * @param use_cache [optional] Set true to use the query cache.
+        */
+       explicit SQLInternal(const std::string& query, bool use_cache = false);
+
+public:
+       /**
+        * @brief Const accessor for the rows returned by the query.
+        *
+        * @return A QueryDataTyped object of the query results.
+        */
+       QueryDataTyped& rowsTyped();
+
+       const Status& getStatus() const;
+
+       /**
+        * @brief Check if the SQL query's results use event-based tables.
+        *
+        * Higher level SQL facilities, like the scheduler, may act differently when
+        * the results of a query (including a JOIN) are event-based. For example,
+        * it does not make sense to perform set difference checks for an
+        * always-append result set.
+        *
+        * All the tables used in the query will be checked. The TableAttributes of
+        * each will be ORed and if any include EVENT_BASED, this will return true.
+        */
+       bool eventBased() const;
+
+       /// ASCII escape the results of the query.
+       void escapeResults();
+
+private:
+       /// The internal member which holds the typed results of the query.
+       QueryDataTyped resultsTyped_;
+
+       /// The internal member which holds the status of the query.
+       Status status_;
+       /// Before completing the execution, store a check for EVENT_BASED.
+       bool event_based_{false};
 };
 
 /**
@@ -460,7 +467,7 @@ void registerFilesystemExtensions(sqlite3* db);
  * @param results The TableRows data structure that will hold the returned rows
  */
 Status genTableRowsForSqliteTable(const boost::filesystem::path& sqlite_db,
-                                  const std::string& sqlite_query,
-                                  TableRows& results,
-                                  bool respect_locking = true);
+                                                                 const std::string& sqlite_query,
+                                                                 TableRows& results,
+                                                                 bool respect_locking = true);
 } // namespace osquery
index 3438580b75e9d061ddb622b456c8859c7a0f211c..c520c45ca345fff2143df08a71fb20ef6d382aec 100644 (file)
@@ -20,91 +20,96 @@ namespace osquery {
 extern void escapeNonPrintableBytesEx(std::string& data);
 
 class SQLTests : public testing::Test {
- public:
-  void SetUp() override {
-    registryAndPluginInit();
-  }
+public:
+       void SetUp() override
+       {
+               registryAndPluginInit();
+       }
 };
 
 class TestTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const {
-    return {
-        std::make_tuple("test_int", INTEGER_TYPE, ColumnOptions::DEFAULT),
-        std::make_tuple("test_text", TEXT_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
-  TableRows generate(QueryContext& ctx) {
-    TableRows results;
-    if (ctx.constraints["test_int"].existsAndMatches("1")) {
-      results.push_back(
-          make_table_row({{"test_int", "1"}, {"test_text", "0"}}));
-    } else {
-      results.push_back(
-          make_table_row({{"test_int", "0"}, {"test_text", "1"}}));
-    }
-
-    auto ints = ctx.constraints["test_int"].getAll<int>(EQUALS);
-    for (const auto& int_match : ints) {
-      results.push_back(make_table_row({{"test_int", INTEGER(int_match)}}));
-    }
-
-    return results;
-  }
+private:
+       TableColumns columns() const
+       {
+               return {
+                       std::make_tuple("test_int", INTEGER_TYPE, ColumnOptions::DEFAULT),
+                       std::make_tuple("test_text", TEXT_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+       TableRows generate(QueryContext& ctx)
+       {
+               TableRows results;
+               if (ctx.constraints["test_int"].existsAndMatches("1")) {
+                       results.push_back(
+                       make_table_row({{"test_int", "1"}, {"test_text", "0"}}));
+               } else {
+                       results.push_back(
+                       make_table_row({{"test_int", "0"}, {"test_text", "1"}}));
+               }
+
+               auto ints = ctx.constraints["test_int"].getAll<int>(EQUALS);
+               for (const auto& int_match : ints) {
+                       results.push_back(make_table_row({{"test_int", INTEGER(int_match)}}));
+               }
+
+               return results;
+       }
 };
 
-TEST_F(SQLTests, test_raw_access_context) {
-  auto tables = RegistryFactory::get().registry("table");
-  tables->add("test", std::make_shared<TestTablePlugin>());
-  auto results = SQL::selectAllFrom("test");
+TEST_F(SQLTests, test_raw_access_context)
+{
+       auto tables = RegistryFactory::get().registry("table");
+       tables->add("test", std::make_shared<TestTablePlugin>());
+       auto results = SQL::selectAllFrom("test");
 
-  EXPECT_EQ(results.size(), 1U);
-  EXPECT_EQ(results[0]["test_text"], "1");
+       EXPECT_EQ(results.size(), 1U);
+       EXPECT_EQ(results[0]["test_text"], "1");
 
-  results = SQL::selectAllFrom("test", "test_int", EQUALS, "1");
-  EXPECT_EQ(results.size(), 2U);
+       results = SQL::selectAllFrom("test", "test_int", EQUALS, "1");
+       EXPECT_EQ(results.size(), 2U);
 
-  results = SQL::selectAllFrom("test", "test_int", EQUALS, "2");
-  EXPECT_EQ(results.size(), 1U);
-  EXPECT_EQ(results[0]["test_int"], "2");
+       results = SQL::selectAllFrom("test", "test_int", EQUALS, "2");
+       EXPECT_EQ(results.size(), 1U);
+       EXPECT_EQ(results[0]["test_int"], "2");
 }
 
-TEST_F(SQLTests, test_sql_escape) {
-  std::string input = "しかたがない";
-  escapeNonPrintableBytesEx(input);
-  EXPECT_EQ(input,
-            "\\xE3\\x81\\x97\\xE3\\x81\\x8B\\xE3\\x81\\x9F\\xE3\\x81\\x8C\\xE3"
-            "\\x81\\xAA\\xE3\\x81\\x84");
-
-  input = "悪因悪果";
-  escapeNonPrintableBytesEx(input);
-  EXPECT_EQ(input,
-            "\\xE6\\x82\\xAA\\xE5\\x9B\\xA0\\xE6\\x82\\xAA\\xE6\\x9E\\x9C");
-
-  input = "モンスターハンター";
-  escapeNonPrintableBytesEx(input);
-  EXPECT_EQ(input,
-            "\\xE3\\x83\\xA2\\xE3\\x83\\xB3\\xE3\\x82\\xB9\\xE3\\x82\\xBF\\xE3"
-            "\\x83\\xBC\\xE3\\x83\\x8F\\xE3\\x83\\xB3\\xE3\\x82\\xBF\\xE3\\x83"
-            "\\xBC");
-
-  input = "съешь же ещё этих мягких французских булок, да выпей чаю";
-  escapeNonPrintableBytesEx(input);
-  EXPECT_EQ(
-      input,
-      "\\xD1\\x81\\xD1\\x8A\\xD0\\xB5\\xD1\\x88\\xD1\\x8C \\xD0\\xB6\\xD0\\xB5 "
-      "\\xD0\\xB5\\xD1\\x89\\xD1\\x91 \\xD1\\x8D\\xD1\\x82\\xD0\\xB8\\xD1\\x85 "
-      "\\xD0\\xBC\\xD1\\x8F\\xD0\\xB3\\xD0\\xBA\\xD0\\xB8\\xD1\\x85 "
-      "\\xD1\\x84\\xD1\\x80\\xD0\\xB0\\xD0\\xBD\\xD1\\x86\\xD1\\x83\\xD0\\xB7\\"
-      "xD1\\x81\\xD0\\xBA\\xD0\\xB8\\xD1\\x85 "
-      "\\xD0\\xB1\\xD1\\x83\\xD0\\xBB\\xD0\\xBE\\xD0\\xBA, "
-      "\\xD0\\xB4\\xD0\\xB0 \\xD0\\xB2\\xD1\\x8B\\xD0\\xBF\\xD0\\xB5\\xD0\\xB9 "
-      "\\xD1\\x87\\xD0\\xB0\\xD1\\x8E");
-
-  input = "The quick brown fox jumps over the lazy dog.";
-  escapeNonPrintableBytesEx(input);
-  EXPECT_EQ(input, "The quick brown fox jumps over the lazy dog.");
+TEST_F(SQLTests, test_sql_escape)
+{
+       std::string input = "しかたがない";
+       escapeNonPrintableBytesEx(input);
+       EXPECT_EQ(input,
+                         "\\xE3\\x81\\x97\\xE3\\x81\\x8B\\xE3\\x81\\x9F\\xE3\\x81\\x8C\\xE3"
+                         "\\x81\\xAA\\xE3\\x81\\x84");
+
+       input = "悪因悪果";
+       escapeNonPrintableBytesEx(input);
+       EXPECT_EQ(input,
+                         "\\xE6\\x82\\xAA\\xE5\\x9B\\xA0\\xE6\\x82\\xAA\\xE6\\x9E\\x9C");
+
+       input = "モンスターハンター";
+       escapeNonPrintableBytesEx(input);
+       EXPECT_EQ(input,
+                         "\\xE3\\x83\\xA2\\xE3\\x83\\xB3\\xE3\\x82\\xB9\\xE3\\x82\\xBF\\xE3"
+                         "\\x83\\xBC\\xE3\\x83\\x8F\\xE3\\x83\\xB3\\xE3\\x82\\xBF\\xE3\\x83"
+                         "\\xBC");
+
+       input = "съешь же ещё этих мягких французских булок, да выпей чаю";
+       escapeNonPrintableBytesEx(input);
+       EXPECT_EQ(
+               input,
+               "\\xD1\\x81\\xD1\\x8A\\xD0\\xB5\\xD1\\x88\\xD1\\x8C \\xD0\\xB6\\xD0\\xB5 "
+               "\\xD0\\xB5\\xD1\\x89\\xD1\\x91 \\xD1\\x8D\\xD1\\x82\\xD0\\xB8\\xD1\\x85 "
+               "\\xD0\\xBC\\xD1\\x8F\\xD0\\xB3\\xD0\\xBA\\xD0\\xB8\\xD1\\x85 "
+               "\\xD1\\x84\\xD1\\x80\\xD0\\xB0\\xD0\\xBD\\xD1\\x86\\xD1\\x83\\xD0\\xB7\\"
+               "xD1\\x81\\xD0\\xBA\\xD0\\xB8\\xD1\\x85 "
+               "\\xD0\\xB1\\xD1\\x83\\xD0\\xBB\\xD0\\xBE\\xD0\\xBA, "
+               "\\xD0\\xB4\\xD0\\xB0 \\xD0\\xB2\\xD1\\x8B\\xD0\\xBF\\xD0\\xB5\\xD0\\xB9 "
+               "\\xD1\\x87\\xD0\\xB0\\xD1\\x8E");
+
+       input = "The quick brown fox jumps over the lazy dog.";
+       escapeNonPrintableBytesEx(input);
+       EXPECT_EQ(input, "The quick brown fox jumps over the lazy dog.");
 }
 
 }
index e48adeaa8f1367c3bf80bfd0f12cb867e2ea7947..f722a79206fc64288097b2129b41f1ecb90e9c0c 100644 (file)
@@ -3,81 +3,84 @@
 
 namespace osquery {
 
-QueryDataTyped getTestDBExpectedResults() {
-  QueryDataTyped d;
-  RowTyped row1;
-  row1["username"] = "mike";
-  row1["age"] = 23LL;
-  d.push_back(row1);
-  RowTyped row2;
-  row2["username"] = "matt";
-  row2["age"] = 24LL;
-  d.push_back(row2);
-  return d;
+QueryDataTyped getTestDBExpectedResults()
+{
+       QueryDataTyped d;
+       RowTyped row1;
+       row1["username"] = "mike";
+       row1["age"] = 23LL;
+       d.push_back(row1);
+       RowTyped row2;
+       row2["username"] = "matt";
+       row2["age"] = 24LL;
+       d.push_back(row2);
+       return d;
 }
 
-std::vector<std::pair<std::string, QueryDataTyped>> getTestDBResultStream() {
-  std::vector<std::pair<std::string, QueryDataTyped>> results;
+std::vector<std::pair<std::string, QueryDataTyped>> getTestDBResultStream()
+{
+       std::vector<std::pair<std::string, QueryDataTyped>> results;
 
-  std::string q2 =
-      R"(INSERT INTO test_table (username, age) VALUES ("joe", 25))";
-  QueryDataTyped d2;
-  RowTyped row2_1;
-  row2_1["username"] = "mike";
-  row2_1["age"] = 23LL;
-  d2.push_back(row2_1);
-  RowTyped row2_2;
-  row2_2["username"] = "matt";
-  row2_2["age"] = 24LL;
-  d2.push_back(row2_2);
-  RowTyped row2_3;
-  row2_3["username"] = "joe";
-  row2_3["age"] = 25LL;
-  d2.push_back(row2_3);
-  results.push_back(std::make_pair(q2, d2));
+       std::string q2 =
+               R"(INSERT INTO test_table (username, age) VALUES ("joe", 25))";
+       QueryDataTyped d2;
+       RowTyped row2_1;
+       row2_1["username"] = "mike";
+       row2_1["age"] = 23LL;
+       d2.push_back(row2_1);
+       RowTyped row2_2;
+       row2_2["username"] = "matt";
+       row2_2["age"] = 24LL;
+       d2.push_back(row2_2);
+       RowTyped row2_3;
+       row2_3["username"] = "joe";
+       row2_3["age"] = 25LL;
+       d2.push_back(row2_3);
+       results.push_back(std::make_pair(q2, d2));
 
-  std::string q3 = R"(UPDATE test_table SET age = 27 WHERE username = "matt")";
-  QueryDataTyped d3;
-  RowTyped row3_1;
-  row3_1["username"] = "mike";
-  row3_1["age"] = 23LL;
-  d3.push_back(row3_1);
-  RowTyped row3_2;
-  row3_2["username"] = "matt";
-  row3_2["age"] = 27LL;
-  d3.push_back(row3_2);
-  RowTyped row3_3;
-  row3_3["username"] = "joe";
-  row3_3["age"] = 25LL;
-  d3.push_back(row3_3);
-  results.push_back(std::make_pair(q3, d3));
+       std::string q3 = R"(UPDATE test_table SET age = 27 WHERE username = "matt")";
+       QueryDataTyped d3;
+       RowTyped row3_1;
+       row3_1["username"] = "mike";
+       row3_1["age"] = 23LL;
+       d3.push_back(row3_1);
+       RowTyped row3_2;
+       row3_2["username"] = "matt";
+       row3_2["age"] = 27LL;
+       d3.push_back(row3_2);
+       RowTyped row3_3;
+       row3_3["username"] = "joe";
+       row3_3["age"] = 25LL;
+       d3.push_back(row3_3);
+       results.push_back(std::make_pair(q3, d3));
 
-  std::string q4 =
-      R"(DELETE FROM test_table WHERE username = "matt" AND age = 27)";
-  QueryDataTyped d4;
-  RowTyped row4_1;
-  row4_1["username"] = "mike";
-  row4_1["age"] = 23LL;
-  d4.push_back(row4_1);
-  RowTyped row4_2;
-  row4_2["username"] = "joe";
-  row4_2["age"] = 25LL;
-  d4.push_back(row4_2);
-  results.push_back(std::make_pair(q4, d4));
+       std::string q4 =
+               R"(DELETE FROM test_table WHERE username = "matt" AND age = 27)";
+       QueryDataTyped d4;
+       RowTyped row4_1;
+       row4_1["username"] = "mike";
+       row4_1["age"] = 23LL;
+       d4.push_back(row4_1);
+       RowTyped row4_2;
+       row4_2["username"] = "joe";
+       row4_2["age"] = 25LL;
+       d4.push_back(row4_2);
+       results.push_back(std::make_pair(q4, d4));
 
-  return results;
+       return results;
 }
 
-ColumnNames getSerializedRowColumnNames(bool unordered_and_repeated) {
-  ColumnNames cn;
-  if (unordered_and_repeated) {
-    cn.push_back("repeated_column");
-  }
-  cn.push_back("alphabetical");
-  cn.push_back("foo");
-  cn.push_back("meaning_of_life");
-  cn.push_back("repeated_column");
-  return cn;
+ColumnNames getSerializedRowColumnNames(bool unordered_and_repeated)
+{
+       ColumnNames cn;
+       if (unordered_and_repeated) {
+               cn.push_back("repeated_column");
+       }
+       cn.push_back("alphabetical");
+       cn.push_back("foo");
+       cn.push_back("meaning_of_life");
+       cn.push_back("repeated_column");
+       return cn;
 }
 
 } // namespace osquery
index de26224d894fb8ecbd05b1c387f5047aab7383c1..c577ae02f86d9bb3603a58aa1fabafd7658288cc 100644 (file)
 
 namespace osquery {
 class SQLiteUtilTests : public testing::Test {
- public:
-  void SetUp() override {
-    registryAndPluginInit();
-  }
+public:
+       void SetUp() override
+       {
+               registryAndPluginInit();
+       }
 };
 
-std::shared_ptr<SQLiteDBInstance> getTestDBC() {
-  auto dbc = SQLiteDBManager::getUnique();
-  char* err = nullptr;
-  std::vector<std::string> queries = {
-      "CREATE TABLE test_table (username varchar(30) primary key, age int)",
-      "INSERT INTO test_table VALUES (\"mike\", 23)",
-      "INSERT INTO test_table VALUES (\"matt\", 24)"};
-
-  for (auto q : queries) {
-    sqlite3_exec(dbc->db(), q.c_str(), nullptr, nullptr, &err);
-    if (err != nullptr) {
-      throw std::domain_error(std::string("Cannot create testing DBC's db: ") +
-                              err);
-    }
-  }
-
-  return dbc;
+std::shared_ptr<SQLiteDBInstance> getTestDBC()
+{
+       auto dbc = SQLiteDBManager::getUnique();
+       char* err = nullptr;
+       std::vector<std::string> queries = {
+               "CREATE TABLE test_table (username varchar(30) primary key, age int)",
+               "INSERT INTO test_table VALUES (\"mike\", 23)",
+               "INSERT INTO test_table VALUES (\"matt\", 24)"
+       };
+
+       for (auto q : queries) {
+               sqlite3_exec(dbc->db(), q.c_str(), nullptr, nullptr, &err);
+               if (err != nullptr) {
+                       throw std::domain_error(std::string("Cannot create testing DBC's db: ") +
+                                                                       err);
+               }
+       }
+
+       return dbc;
 }
 
-TEST_F(SQLiteUtilTests, test_zero_as_float_doesnt_convert_to_int) {
-  auto sql = SQL("SELECT 0.0 as zero");
-  EXPECT_TRUE(sql.ok());
-  EXPECT_EQ(sql.rows().size(), 1U);
-  Row r;
-  r["zero"] = "0.0";
-  EXPECT_EQ(sql.rows()[0], r);
+TEST_F(SQLiteUtilTests, test_zero_as_float_doesnt_convert_to_int)
+{
+       auto sql = SQL("SELECT 0.0 as zero");
+       EXPECT_TRUE(sql.ok());
+       EXPECT_EQ(sql.rows().size(), 1U);
+       Row r;
+       r["zero"] = "0.0";
+       EXPECT_EQ(sql.rows()[0], r);
 }
 
-TEST_F(SQLiteUtilTests, test_precision_is_maintained) {
-  auto sql = SQL("SELECT 0.123456789 as high_precision, 0.12 as low_precision");
-  EXPECT_TRUE(sql.ok());
-  EXPECT_EQ(sql.rows().size(), 1U);
-  Row r;
-  r["high_precision"] = "0.123456789";
-  r["low_precision"] = "0.12";
-  EXPECT_EQ(sql.rows()[0], r);
+TEST_F(SQLiteUtilTests, test_precision_is_maintained)
+{
+       auto sql = SQL("SELECT 0.123456789 as high_precision, 0.12 as low_precision");
+       EXPECT_TRUE(sql.ok());
+       EXPECT_EQ(sql.rows().size(), 1U);
+       Row r;
+       r["high_precision"] = "0.123456789";
+       r["low_precision"] = "0.12";
+       EXPECT_EQ(sql.rows()[0], r);
 }
 
-TEST_F(SQLiteUtilTests, test_sqlite_instance_manager) {
-  auto dbc1 = SQLiteDBManager::get();
-  auto dbc2 = SQLiteDBManager::get();
-  EXPECT_NE(dbc1->db(), dbc2->db());
-  EXPECT_EQ(dbc1->db(), dbc1->db());
+TEST_F(SQLiteUtilTests, test_sqlite_instance_manager)
+{
+       auto dbc1 = SQLiteDBManager::get();
+       auto dbc2 = SQLiteDBManager::get();
+       EXPECT_NE(dbc1->db(), dbc2->db());
+       EXPECT_EQ(dbc1->db(), dbc1->db());
 }
 
-TEST_F(SQLiteUtilTests, test_sqlite_instance) {
-  // Don't do this at home kids.
-  // Keep a copy of the internal DB and let the SQLiteDBInstance go oos.
-  auto internal_db = SQLiteDBManager::get()->db();
-  // Compare the internal DB to another request with no SQLiteDBInstances
-  // in scope, meaning the primary will be returned.
-  EXPECT_EQ(internal_db, SQLiteDBManager::get()->db());
+TEST_F(SQLiteUtilTests, test_sqlite_instance)
+{
+       // Don't do this at home kids.
+       // Keep a copy of the internal DB and let the SQLiteDBInstance go oos.
+       auto internal_db = SQLiteDBManager::get()->db();
+       // Compare the internal DB to another request with no SQLiteDBInstances
+       // in scope, meaning the primary will be returned.
+       EXPECT_EQ(internal_db, SQLiteDBManager::get()->db());
 }
 
-TEST_F(SQLiteUtilTests, test_reset) {
-  auto internal_db = SQLiteDBManager::get()->db();
-  ASSERT_NE(nullptr, internal_db);
+TEST_F(SQLiteUtilTests, test_reset)
+{
+       auto internal_db = SQLiteDBManager::get()->db();
+       ASSERT_NE(nullptr, internal_db);
 
-  sqlite3_exec(internal_db,
-               "create view test_view as select 'test';",
-               nullptr,
-               nullptr,
-               nullptr);
+       sqlite3_exec(internal_db,
+                                "create view test_view as select 'test';",
+                                nullptr,
+                                nullptr,
+                                nullptr);
 
-  SQLiteDBManager::resetPrimary();
-  auto instance = SQLiteDBManager::get();
+       SQLiteDBManager::resetPrimary();
+       auto instance = SQLiteDBManager::get();
 
-  QueryDataTyped results;
-  queryInternal("select * from test_view", results, instance);
+       QueryDataTyped results;
+       queryInternal("select * from test_view", results, instance);
 
-  // Assume the internal (primary) database we reset and recreated.
-  EXPECT_EQ(results.size(), 0U);
+       // Assume the internal (primary) database we reset and recreated.
+       EXPECT_EQ(results.size(), 0U);
 }
 
-TEST_F(SQLiteUtilTests, test_direct_query_execution) {
-  auto dbc = getTestDBC();
-  QueryDataTyped results;
-  auto status = queryInternal(kTestQuery, results, dbc);
-  EXPECT_TRUE(status.ok());
-  EXPECT_EQ(results, getTestDBExpectedResults());
+TEST_F(SQLiteUtilTests, test_direct_query_execution)
+{
+       auto dbc = getTestDBC();
+       QueryDataTyped results;
+       auto status = queryInternal(kTestQuery, results, dbc);
+       EXPECT_TRUE(status.ok());
+       EXPECT_EQ(results, getTestDBExpectedResults());
 }
 
-TEST_F(SQLiteUtilTests, test_aggregate_query) {
-  auto dbc = getTestDBC();
-  QueryDataTyped results;
-  auto status = queryInternal(kTestQuery, results, dbc);
-  EXPECT_TRUE(status.ok());
-  EXPECT_EQ(results, getTestDBExpectedResults());
+TEST_F(SQLiteUtilTests, test_aggregate_query)
+{
+       auto dbc = getTestDBC();
+       QueryDataTyped results;
+       auto status = queryInternal(kTestQuery, results, dbc);
+       EXPECT_TRUE(status.ok());
+       EXPECT_EQ(results, getTestDBExpectedResults());
 }
 
-TEST_F(SQLiteUtilTests, test_no_results_query) {
-  auto dbc = getTestDBC();
-  QueryDataTyped results;
-  auto status = queryInternal(
-      "select * from test_table where username=\"A_NON_EXISTENT_NAME\"",
-      results,
-      dbc);
-  EXPECT_TRUE(status.ok());
+TEST_F(SQLiteUtilTests, test_no_results_query)
+{
+       auto dbc = getTestDBC();
+       QueryDataTyped results;
+       auto status = queryInternal(
+                                         "select * from test_table where username=\"A_NON_EXISTENT_NAME\"",
+                                         results,
+                                         dbc);
+       EXPECT_TRUE(status.ok());
 }
 
-TEST_F(SQLiteUtilTests, test_whitespace_query) {
-  auto dbc = getTestDBC();
-  QueryDataTyped results;
-  auto status = queryInternal("     ", results, dbc);
-  EXPECT_TRUE(status.ok());
+TEST_F(SQLiteUtilTests, test_whitespace_query)
+{
+       auto dbc = getTestDBC();
+       QueryDataTyped results;
+       auto status = queryInternal("     ", results, dbc);
+       EXPECT_TRUE(status.ok());
 }
 
-TEST_F(SQLiteUtilTests, test_get_test_db_result_stream) {
-  auto dbc = getTestDBC();
-  auto results = getTestDBResultStream();
-  for (auto r : results) {
-    char* err_char = nullptr;
-    sqlite3_exec(dbc->db(), (r.first).c_str(), nullptr, nullptr, &err_char);
-    EXPECT_TRUE(err_char == nullptr);
-    if (err_char != nullptr) {
-      sqlite3_free(err_char);
-      ASSERT_TRUE(false);
-    }
-
-    QueryDataTyped expected;
-    auto status = queryInternal(kTestQuery, expected, dbc);
-    EXPECT_EQ(expected, r.second);
-  }
+TEST_F(SQLiteUtilTests, test_get_test_db_result_stream)
+{
+       auto dbc = getTestDBC();
+       auto results = getTestDBResultStream();
+       for (auto r : results) {
+               char* err_char = nullptr;
+               sqlite3_exec(dbc->db(), (r.first).c_str(), nullptr, nullptr, &err_char);
+               EXPECT_TRUE(err_char == nullptr);
+               if (err_char != nullptr) {
+                       sqlite3_free(err_char);
+                       ASSERT_TRUE(false);
+               }
+
+               QueryDataTyped expected;
+               auto status = queryInternal(kTestQuery, expected, dbc);
+               EXPECT_EQ(expected, r.second);
+       }
 }
 
 } // namespace osquery
index 1c28ac3054d07d46fdd8446c473d69eeb2d803a7..f7cef0df2cae0ac7f060251d51e55fb63170474a 100644 (file)
 namespace osquery {
 
 class VirtualTableTests : public testing::Test {
- public:
-  void SetUp() override {
-    registryAndPluginInit();
-  }
+public:
+       void SetUp() override
+       {
+               registryAndPluginInit();
+       }
 };
 
 // sample plugin used on tests
 class sampleTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("foo", INTEGER_TYPE, ColumnOptions::DEFAULT),
-        std::make_tuple("bar", TEXT_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("foo", INTEGER_TYPE, ColumnOptions::DEFAULT),
+                       std::make_tuple("bar", TEXT_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
 };
 
-TEST_F(VirtualTableTests, test_tableplugin_columndefinition) {
-  auto table = std::make_shared<sampleTablePlugin>();
-  EXPECT_EQ("(`foo` INTEGER, `bar` TEXT)", table->columnDefinition(false));
+TEST_F(VirtualTableTests, test_tableplugin_columndefinition)
+{
+       auto table = std::make_shared<sampleTablePlugin>();
+       EXPECT_EQ("(`foo` INTEGER, `bar` TEXT)", table->columnDefinition(false));
 }
 
 class optionsTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple(
-            "id", INTEGER_TYPE, ColumnOptions::INDEX | ColumnOptions::REQUIRED),
-        std::make_tuple("username", TEXT_TYPE, ColumnOptions::OPTIMIZED),
-        std::make_tuple("name", TEXT_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
- private:
-  FRIEND_TEST(VirtualTableTests, test_tableplugin_options);
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple(
+                               "id", INTEGER_TYPE, ColumnOptions::INDEX | ColumnOptions::REQUIRED),
+                       std::make_tuple("username", TEXT_TYPE, ColumnOptions::OPTIMIZED),
+                       std::make_tuple("name", TEXT_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+private:
+       FRIEND_TEST(VirtualTableTests, test_tableplugin_options);
 };
 
-TEST_F(VirtualTableTests, test_tableplugin_options) {
-  auto table = std::make_shared<optionsTablePlugin>();
-  EXPECT_EQ(ColumnOptions::INDEX | ColumnOptions::REQUIRED,
-            std::get<2>(table->columns()[0]));
-
-  PluginResponse response;
-  PluginRequest request = {{"action", "columns"}};
-  EXPECT_TRUE(table->call(request, response).ok());
-  auto index_required =
-      static_cast<size_t>(ColumnOptions::INDEX | ColumnOptions::REQUIRED);
-  EXPECT_EQ(INTEGER(index_required), response[0]["op"]);
-
-  response = table->routeInfo();
-  EXPECT_EQ(INTEGER(index_required), response[0]["op"]);
-
-  std::string expected_statement =
-      "(`id` INTEGER, `username` TEXT, `name` TEXT, PRIMARY KEY (`id`)) "
-      "WITHOUT ROWID";
-  EXPECT_EQ(expected_statement, columnDefinition(response, true, false));
+TEST_F(VirtualTableTests, test_tableplugin_options)
+{
+       auto table = std::make_shared<optionsTablePlugin>();
+       EXPECT_EQ(ColumnOptions::INDEX | ColumnOptions::REQUIRED,
+                         std::get<2>(table->columns()[0]));
+
+       PluginResponse response;
+       PluginRequest request = {{"action", "columns"}};
+       EXPECT_TRUE(table->call(request, response).ok());
+       auto index_required =
+               static_cast<size_t>(ColumnOptions::INDEX | ColumnOptions::REQUIRED);
+       EXPECT_EQ(INTEGER(index_required), response[0]["op"]);
+
+       response = table->routeInfo();
+       EXPECT_EQ(INTEGER(index_required), response[0]["op"]);
+
+       std::string expected_statement =
+               "(`id` INTEGER, `username` TEXT, `name` TEXT, PRIMARY KEY (`id`)) "
+               "WITHOUT ROWID";
+       EXPECT_EQ(expected_statement, columnDefinition(response, true, false));
 }
 
 class moreOptionsTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("id", INTEGER_TYPE, ColumnOptions::INDEX),
-        std::make_tuple("username", TEXT_TYPE, ColumnOptions::ADDITIONAL),
-        std::make_tuple("name", TEXT_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
- private:
-  FRIEND_TEST(VirtualTableTests, test_tableplugin_moreoptions);
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("id", INTEGER_TYPE, ColumnOptions::INDEX),
+                       std::make_tuple("username", TEXT_TYPE, ColumnOptions::ADDITIONAL),
+                       std::make_tuple("name", TEXT_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+private:
+       FRIEND_TEST(VirtualTableTests, test_tableplugin_moreoptions);
 };
 
-TEST_F(VirtualTableTests, test_tableplugin_moreoptions) {
-  auto table = std::make_shared<moreOptionsTablePlugin>();
+TEST_F(VirtualTableTests, test_tableplugin_moreoptions)
+{
+       auto table = std::make_shared<moreOptionsTablePlugin>();
 
-  PluginResponse response;
-  PluginRequest request = {{"action", "columns"}};
-  EXPECT_TRUE(table->call(request, response).ok());
+       PluginResponse response;
+       PluginRequest request = {{"action", "columns"}};
+       EXPECT_TRUE(table->call(request, response).ok());
 
-  std::string expected_statement =
-      "(`id` INTEGER, `username` TEXT, `name` TEXT, PRIMARY KEY (`id`, "
-      "`username`)) WITHOUT ROWID";
-  EXPECT_EQ(expected_statement, columnDefinition(response, true, false));
+       std::string expected_statement =
+               "(`id` INTEGER, `username` TEXT, `name` TEXT, PRIMARY KEY (`id`, "
+               "`username`)) WITHOUT ROWID";
+       EXPECT_EQ(expected_statement, columnDefinition(response, true, false));
 }
 
 class aliasesTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("username", TEXT_TYPE, ColumnOptions::DEFAULT),
-        std::make_tuple("name", TEXT_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
-  std::vector<std::string> aliases() const override {
-    return {"aliases1", "aliases2"};
-  }
-
-  ColumnAliasSet columnAliases() const override {
-    return {
-        {"username", {"user_name"}},
-        {"name", {"name1", "name2"}},
-    };
-  }
-
- private:
-  FRIEND_TEST(VirtualTableTests, test_tableplugin_aliases);
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("username", TEXT_TYPE, ColumnOptions::DEFAULT),
+                       std::make_tuple("name", TEXT_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+       std::vector<std::string> aliases() const override
+       {
+               return {"aliases1", "aliases2"};
+       }
+
+       ColumnAliasSet columnAliases() const override
+       {
+               return {
+                       {"username", {"user_name"}},
+                       {"name", {"name1", "name2"}},
+               };
+       }
+
+private:
+       FRIEND_TEST(VirtualTableTests, test_tableplugin_aliases);
 };
 
-TEST_F(VirtualTableTests, test_tableplugin_aliases) {
-  auto table = std::make_shared<aliasesTablePlugin>();
-  std::vector<std::string> expected_aliases = {"aliases1", "aliases2"};
-  EXPECT_EQ(expected_aliases, table->aliases());
-
-  PluginResponse response;
-  PluginRequest request = {{"action", "columns"}};
-  EXPECT_TRUE(table->call(request, response).ok());
-
-  auto default_option = static_cast<size_t>(ColumnOptions::DEFAULT);
-  PluginResponse expected_response = {
-      {{"id", "column"},
-       {"name", "username"},
-       {"type", "TEXT"},
-       {"op", INTEGER(default_option)}},
-      {{"id", "column"},
-       {"name", "name"},
-       {"type", "TEXT"},
-       {"op", INTEGER(default_option)}},
-      {{"alias", "aliases1"}, {"id", "alias"}},
-      {{"alias", "aliases2"}, {"id", "alias"}},
-      {{"id", "columnAlias"}, {"name", "name1"}, {"target", "name"}},
-      {{"id", "columnAlias"}, {"name", "name2"}, {"target", "name"}},
-      {{"id", "columnAlias"}, {"name", "user_name"}, {"target", "username"}},
-      {{"attributes", "0"}, {"id", "attributes"}},
-  };
-  EXPECT_EQ(response, expected_response);
-
-  // Compare the expected table definitions.
-  std::string expected_statement =
-      "(`username` TEXT, `name` TEXT, `name1` TEXT HIDDEN, `name2` TEXT HIDDEN,"
-      " `user_name` TEXT HIDDEN)";
-  EXPECT_EQ(expected_statement, columnDefinition(response, true, false));
-  expected_statement = "(`username` TEXT, `name` TEXT)";
-  EXPECT_EQ(expected_statement, columnDefinition(response, false, false));
+TEST_F(VirtualTableTests, test_tableplugin_aliases)
+{
+       auto table = std::make_shared<aliasesTablePlugin>();
+       std::vector<std::string> expected_aliases = {"aliases1", "aliases2"};
+       EXPECT_EQ(expected_aliases, table->aliases());
+
+       PluginResponse response;
+       PluginRequest request = {{"action", "columns"}};
+       EXPECT_TRUE(table->call(request, response).ok());
+
+       auto default_option = static_cast<size_t>(ColumnOptions::DEFAULT);
+       PluginResponse expected_response = {
+               {       {"id", "column"},
+                       {"name", "username"},
+                       {"type", "TEXT"},
+                       {"op", INTEGER(default_option)}
+               },
+               {       {"id", "column"},
+                       {"name", "name"},
+                       {"type", "TEXT"},
+                       {"op", INTEGER(default_option)}
+               },
+               {{"alias", "aliases1"}, {"id", "alias"}},
+               {{"alias", "aliases2"}, {"id", "alias"}},
+               {{"id", "columnAlias"}, {"name", "name1"}, {"target", "name"}},
+               {{"id", "columnAlias"}, {"name", "name2"}, {"target", "name"}},
+               {{"id", "columnAlias"}, {"name", "user_name"}, {"target", "username"}},
+               {{"attributes", "0"}, {"id", "attributes"}},
+       };
+       EXPECT_EQ(response, expected_response);
+
+       // Compare the expected table definitions.
+       std::string expected_statement =
+               "(`username` TEXT, `name` TEXT, `name1` TEXT HIDDEN, `name2` TEXT HIDDEN,"
+               " `user_name` TEXT HIDDEN)";
+       EXPECT_EQ(expected_statement, columnDefinition(response, true, false));
+       expected_statement = "(`username` TEXT, `name` TEXT)";
+       EXPECT_EQ(expected_statement, columnDefinition(response, false, false));
 }
 
-TEST_F(VirtualTableTests, test_sqlite3_attach_vtable) {
-  auto table = std::make_shared<sampleTablePlugin>();
-  table->setName("sample");
-
-  // Request a managed "connection".
-  // This will be a single (potentially locked) instance or a transient
-  // SQLite database if there is contention and a lock was not requested.
-  auto dbc = SQLiteDBManager::get();
-
-  // Virtual tables require the registry/plugin API to query tables.
-  auto status =
-      attachTableInternal("failed_sample", "(foo INTEGER)", dbc, false);
-  EXPECT_EQ(status.getCode(), SQLITE_ERROR);
-
-  // The table attach will complete only when the table name is registered.
-  auto tables = RegistryFactory::get().registry("table");
-  tables->add("sample", std::make_shared<sampleTablePlugin>());
-
-  PluginResponse response;
-  status = Registry::call("table", "sample", {{"action", "columns"}}, response);
-  ASSERT_TRUE(status.ok());
-
-  // Use the table name, plugin-generated schema to attach.
-  status = attachTableInternal(
-      "sample", columnDefinition(response, false, false), dbc, false);
-  EXPECT_EQ(status.getCode(), SQLITE_OK);
-
-  std::string const q = "SELECT sql FROM sqlite_temp_master WHERE tbl_name='sample';";
-  QueryData results;
-  status = queryInternal(q, results, dbc);
-  EXPECT_EQ(
-      "CREATE VIRTUAL TABLE sample USING sample(`foo` INTEGER, `bar` TEXT)",
-      results[0]["sql"]);
+TEST_F(VirtualTableTests, test_sqlite3_attach_vtable)
+{
+       auto table = std::make_shared<sampleTablePlugin>();
+       table->setName("sample");
+
+       // Request a managed "connection".
+       // This will be a single (potentially locked) instance or a transient
+       // SQLite database if there is contention and a lock was not requested.
+       auto dbc = SQLiteDBManager::get();
+
+       // Virtual tables require the registry/plugin API to query tables.
+       auto status =
+               attachTableInternal("failed_sample", "(foo INTEGER)", dbc, false);
+       EXPECT_EQ(status.getCode(), SQLITE_ERROR);
+
+       // The table attach will complete only when the table name is registered.
+       auto tables = RegistryFactory::get().registry("table");
+       tables->add("sample", std::make_shared<sampleTablePlugin>());
+
+       PluginResponse response;
+       status = Registry::call("table", "sample", {{"action", "columns"}}, response);
+       ASSERT_TRUE(status.ok());
+
+       // Use the table name, plugin-generated schema to attach.
+       status = attachTableInternal(
+                                "sample", columnDefinition(response, false, false), dbc, false);
+       EXPECT_EQ(status.getCode(), SQLITE_OK);
+
+       std::string const q = "SELECT sql FROM sqlite_temp_master WHERE tbl_name='sample';";
+       QueryData results;
+       status = queryInternal(q, results, dbc);
+       EXPECT_EQ(
+               "CREATE VIRTUAL TABLE sample USING sample(`foo` INTEGER, `bar` TEXT)",
+               results[0]["sql"]);
 }
 
 class pTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("x", INTEGER_TYPE, ColumnOptions::DEFAULT),
-        std::make_tuple("y", INTEGER_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
- public:
-  TableRows generate(QueryContext&) override {
-    TableRows tr;
-    tr.push_back(make_table_row({{"x", "1"}, {"y", "2"}}));
-    tr.push_back(make_table_row({{"x", "2"}, {"y", "1"}}));
-    return tr;
-  }
-
- private:
-  FRIEND_TEST(VirtualTableTests, test_constraints_stacking);
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("x", INTEGER_TYPE, ColumnOptions::DEFAULT),
+                       std::make_tuple("y", INTEGER_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+public:
+       TableRows generate(QueryContext&) override
+       {
+               TableRows tr;
+               tr.push_back(make_table_row({{"x", "1"}, {"y", "2"}}));
+               tr.push_back(make_table_row({{"x", "2"}, {"y", "1"}}));
+               return tr;
+       }
+
+private:
+       FRIEND_TEST(VirtualTableTests, test_constraints_stacking);
 };
 
 class kTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("x", INTEGER_TYPE, ColumnOptions::DEFAULT),
-        std::make_tuple("z", INTEGER_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
- public:
-  TableRows generate(QueryContext&) override {
-    TableRows tr;
-    tr.push_back(make_table_row({{"x", "1"}, {"z", "2"}}));
-    tr.push_back(make_table_row({{"x", "2"}, {"z", "1"}}));
-    return tr;
-  }
-
- private:
-  FRIEND_TEST(VirtualTableTests, test_constraints_stacking);
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("x", INTEGER_TYPE, ColumnOptions::DEFAULT),
+                       std::make_tuple("z", INTEGER_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+public:
+       TableRows generate(QueryContext&) override
+       {
+               TableRows tr;
+               tr.push_back(make_table_row({{"x", "1"}, {"z", "2"}}));
+               tr.push_back(make_table_row({{"x", "2"}, {"z", "1"}}));
+               return tr;
+       }
+
+private:
+       FRIEND_TEST(VirtualTableTests, test_constraints_stacking);
 };
 
 static QueryData makeResult(const std::string& col,
-                            const std::vector<std::string>& values) {
-  QueryData results;
-  for (const auto& value : values) {
-    Row r;
-    r[col] = value;
-    results.push_back(r);
-  }
-  return results;
+                                                       const std::vector<std::string>& values)
+{
+       QueryData results;
+       for (const auto& value : values) {
+               Row r;
+               r[col] = value;
+               results.push_back(r);
+       }
+       return results;
 }
 
 #define MP std::make_pair
 
-TEST_F(VirtualTableTests, test_constraints_stacking) {
-  // Add two testing tables to the registry.
-  auto tables = RegistryFactory::get().registry("table");
-  tables->add("p", std::make_shared<pTablePlugin>());
-  tables->add("k", std::make_shared<kTablePlugin>());
-  auto dbc = SQLiteDBManager::getUnique();
-
-  {
-    // To simplify the attach, just access the column definition directly.
-    auto p = std::make_shared<pTablePlugin>();
-    attachTableInternal("p", p->columnDefinition(false), dbc, false);
-    auto k = std::make_shared<kTablePlugin>();
-    attachTableInternal("k", k->columnDefinition(false), dbc, false);
-  }
-
-  std::vector<std::pair<std::string, QueryData>> constraint_tests = {
-      MP("select k.x from p, k", makeResult("x", {"1", "2", "1", "2"})),
-      MP("select k.x from (select * from k) k2, p, k where k.x = p.x",
-         makeResult("x", {"1", "1", "2", "2"})),
-      MP("select k.x from (select * from k where z = 1) k2, p, k where k.x = "
-         "p.x",
-         makeResult("x", {"1", "2"})),
-      MP("select k.x from k k1, (select * from p) p1, k where k.x = p1.x",
-         makeResult("x", {"1", "1", "2", "2"})),
-      MP("select k.x from (select * from p) p1, k, (select * from k) k2 where "
-         "k.x = p1.x",
-         makeResult("x", {"1", "1", "2", "2"})),
-      MP("select k.x from (select * from p) p1, k, (select * from k where z = "
-         "2) k2 where k.x = p1.x",
-         makeResult("x", {"1", "2"})),
-      MP("select k.x from k, (select * from p) p1, k k2, (select * from k "
-         "where z = 1) k3 where k.x = p1.x",
-         makeResult("x", {"1", "1", "2", "2"})),
-      MP("select p.x from (select * from k where z = 1) k1, (select * from k "
-         "where z != 1) k2, p where p.x = k2.x",
-         makeResult("x", {"1"})),
-      MP("select p.x from (select * from k, (select x as xx from k where x = "
-         "1) k2 where z = 1) k1, (select * from k where z != 1) k2, p, k as k3 "
-         "where p.x = k2.x",
-         makeResult("x", {"1", "1"})),
-  };
-
-  for (const auto& test : constraint_tests) {
-    QueryData results;
-    queryInternal(test.first, results, dbc);
-    EXPECT_EQ(results, test.second) << "Unexpected result for the query: " << test.first;
-  }
-
-  std::vector<QueryData> union_results = {
-      makeResult("x", {"1", "2"}),
-      makeResult("x", {"1", "2"}),
-      makeResult("x", {"1", "2"}),
-      makeResult("x", {"1", "2"}),
-      makeResult("x", {"1", "2"}),
-      makeResult("x", {"1", "2"}),
-      makeResult("x", {"1", "2"}),
-      makeResult("x", {"1"}),
-      makeResult("x", {"1"}),
-  };
-
-  size_t index = 0;
-  for (const auto& test : constraint_tests) {
-    QueryData results;
-    queryInternal(test.first + " union " + test.first, results, dbc);
-    EXPECT_EQ(results, union_results[index++]);
-  }
+TEST_F(VirtualTableTests, test_constraints_stacking)
+{
+       // Add two testing tables to the registry.
+       auto tables = RegistryFactory::get().registry("table");
+       tables->add("p", std::make_shared<pTablePlugin>());
+       tables->add("k", std::make_shared<kTablePlugin>());
+       auto dbc = SQLiteDBManager::getUnique();
+
+       {
+               // To simplify the attach, just access the column definition directly.
+               auto p = std::make_shared<pTablePlugin>();
+               attachTableInternal("p", p->columnDefinition(false), dbc, false);
+               auto k = std::make_shared<kTablePlugin>();
+               attachTableInternal("k", k->columnDefinition(false), dbc, false);
+       }
+
+       std::vector<std::pair<std::string, QueryData>> constraint_tests = {
+               MP("select k.x from p, k", makeResult("x", {"1", "2", "1", "2"})),
+               MP("select k.x from (select * from k) k2, p, k where k.x = p.x",
+               makeResult("x", {"1", "1", "2", "2"})),
+               MP("select k.x from (select * from k where z = 1) k2, p, k where k.x = "
+                  "p.x",
+               makeResult("x", {"1", "2"})),
+               MP("select k.x from k k1, (select * from p) p1, k where k.x = p1.x",
+               makeResult("x", {"1", "1", "2", "2"})),
+               MP("select k.x from (select * from p) p1, k, (select * from k) k2 where "
+                  "k.x = p1.x",
+               makeResult("x", {"1", "1", "2", "2"})),
+               MP("select k.x from (select * from p) p1, k, (select * from k where z = "
+                  "2) k2 where k.x = p1.x",
+               makeResult("x", {"1", "2"})),
+               MP("select k.x from k, (select * from p) p1, k k2, (select * from k "
+                  "where z = 1) k3 where k.x = p1.x",
+               makeResult("x", {"1", "1", "2", "2"})),
+               MP("select p.x from (select * from k where z = 1) k1, (select * from k "
+                  "where z != 1) k2, p where p.x = k2.x",
+               makeResult("x", {"1"})),
+               MP("select p.x from (select * from k, (select x as xx from k where x = "
+                  "1) k2 where z = 1) k1, (select * from k where z != 1) k2, p, k as k3 "
+                  "where p.x = k2.x",
+               makeResult("x", {"1", "1"})),
+       };
+
+       for (const auto& test : constraint_tests) {
+               QueryData results;
+               queryInternal(test.first, results, dbc);
+               EXPECT_EQ(results, test.second) << "Unexpected result for the query: " << test.first;
+       }
+
+       std::vector<QueryData> union_results = {
+               makeResult("x", {"1", "2"}),
+               makeResult("x", {"1", "2"}),
+               makeResult("x", {"1", "2"}),
+               makeResult("x", {"1", "2"}),
+               makeResult("x", {"1", "2"}),
+               makeResult("x", {"1", "2"}),
+               makeResult("x", {"1", "2"}),
+               makeResult("x", {"1"}),
+               makeResult("x", {"1"}),
+       };
+
+       size_t index = 0;
+       for (const auto& test : constraint_tests) {
+               QueryData results;
+               queryInternal(test.first + " union " + test.first, results, dbc);
+               EXPECT_EQ(results, union_results[index++]);
+       }
 }
 
 class jsonTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("data", TEXT_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
- public:
-  TableRows generate(QueryContext&) override {
-    TableRows results;
-    results.push_back(make_table_row({{"data", "{\"test\": 1}"}}));
-    return results;
-  }
-
- private:
-  FRIEND_TEST(VirtualTableTests, test_json_extract);
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("data", TEXT_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+public:
+       TableRows generate(QueryContext&) override
+       {
+               TableRows results;
+               results.push_back(make_table_row({{"data", "{\"test\": 1}"}}));
+               return results;
+       }
+
+private:
+       FRIEND_TEST(VirtualTableTests, test_json_extract);
 };
 
-TEST_F(VirtualTableTests, test_json_extract) {
-  // Get a database connection.
-  auto tables = RegistryFactory::get().registry("table");
-  auto json = std::make_shared<jsonTablePlugin>();
-  tables->add("json", json);
-
-  auto dbc = SQLiteDBManager::getUnique();
-  attachTableInternal("json", json->columnDefinition(false), dbc, false);
-
-  QueryData results;
-  // Run a query with a join within.
-  std::string statement =
-      "SELECT JSON_EXTRACT(data, '$.test') AS test FROM json;";
-  auto status = queryInternal(statement, results, dbc);
-  ASSERT_TRUE(status.ok());
-  ASSERT_EQ(results.size(), 1U);
-  EXPECT_EQ(results[0]["test"], "1");
+TEST_F(VirtualTableTests, test_json_extract)
+{
+       // Get a database connection.
+       auto tables = RegistryFactory::get().registry("table");
+       auto json = std::make_shared<jsonTablePlugin>();
+       tables->add("json", json);
+
+       auto dbc = SQLiteDBManager::getUnique();
+       attachTableInternal("json", json->columnDefinition(false), dbc, false);
+
+       QueryData results;
+       // Run a query with a join within.
+       std::string statement =
+               "SELECT JSON_EXTRACT(data, '$.test') AS test FROM json;";
+       auto status = queryInternal(statement, results, dbc);
+       ASSERT_TRUE(status.ok());
+       ASSERT_EQ(results.size(), 1U);
+       EXPECT_EQ(results[0]["test"], "1");
 }
 
-TEST_F(VirtualTableTests, test_null_values) {
-  auto dbc = SQLiteDBManager::getUnique();
-
-  std::string statement = "SELECT NULL as null_value;";
-  {
-    QueryData results;
-    auto status = queryInternal(statement, results, dbc);
-    ASSERT_TRUE(status.ok());
-    EXPECT_EQ(results[0]["null_value"], "");
-  }
-
-  // Try INTEGER.
-  {
-    QueryData results;
-    statement = "SELECT CAST(NULL as INTEGER) as null_value;";
-    queryInternal(statement, results, dbc);
-    EXPECT_EQ(results[0]["null_value"], "");
-  }
-
-  // BIGINT.
-  {
-    QueryData results;
-    statement = "SELECT CAST(NULL as BIGINT) as null_value;";
-    queryInternal(statement, results, dbc);
-    EXPECT_EQ(results[0]["null_value"], "");
-  }
-
-  // Try DOUBLE.
-  {
-    QueryData results;
-    statement = "SELECT CAST(NULL as DOUBLE) as null_value;";
-    queryInternal(statement, results, dbc);
-    EXPECT_EQ(results[0]["null_value"], "");
-  }
+TEST_F(VirtualTableTests, test_null_values)
+{
+       auto dbc = SQLiteDBManager::getUnique();
+
+       std::string statement = "SELECT NULL as null_value;";
+       {
+               QueryData results;
+               auto status = queryInternal(statement, results, dbc);
+               ASSERT_TRUE(status.ok());
+               EXPECT_EQ(results[0]["null_value"], "");
+       }
+
+       // Try INTEGER.
+       {
+               QueryData results;
+               statement = "SELECT CAST(NULL as INTEGER) as null_value;";
+               queryInternal(statement, results, dbc);
+               EXPECT_EQ(results[0]["null_value"], "");
+       }
+
+       // BIGINT.
+       {
+               QueryData results;
+               statement = "SELECT CAST(NULL as BIGINT) as null_value;";
+               queryInternal(statement, results, dbc);
+               EXPECT_EQ(results[0]["null_value"], "");
+       }
+
+       // Try DOUBLE.
+       {
+               QueryData results;
+               statement = "SELECT CAST(NULL as DOUBLE) as null_value;";
+               queryInternal(statement, results, dbc);
+               EXPECT_EQ(results[0]["null_value"], "");
+       }
 }
 
 class cacheTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("data", TEXT_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
- public:
-  TableRows generate(QueryContext& context) override {
-    TableRows results;
-    if (context.isCached("awesome_data")) {
-      // There is cache entry for awesome data.
-      results.push_back(make_table_row({{"data", "more_awesome_data"}}));
-    } else {
-      auto tr = make_table_row({{"data", "awesome_data"}});
-      context.setCache("awesome_data", static_cast<TableRowHolder&&>(tr));
-      results.push_back(std::move(tr));
-    }
-    return results;
-  }
-
- private:
-  FRIEND_TEST(VirtualTableTests, test_table_cache);
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("data", TEXT_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+public:
+       TableRows generate(QueryContext& context) override
+       {
+               TableRows results;
+               if (context.isCached("awesome_data")) {
+                       // There is cache entry for awesome data.
+                       results.push_back(make_table_row({{"data", "more_awesome_data"}}));
+               } else {
+                       auto tr = make_table_row({{"data", "awesome_data"}});
+                       context.setCache("awesome_data", static_cast < TableRowHolder && >(tr));
+                       results.push_back(std::move(tr));
+               }
+               return results;
+       }
+
+private:
+       FRIEND_TEST(VirtualTableTests, test_table_cache);
 };
 
-TEST_F(VirtualTableTests, test_table_cache) {
-  // Get a database connection.
-  auto tables = RegistryFactory::get().registry("table");
-  auto cache = std::make_shared<cacheTablePlugin>();
-  tables->add("cache", cache);
-  auto dbc = SQLiteDBManager::getUnique();
-  attachTableInternal("cache", cache->columnDefinition(false), dbc, false);
-
-  QueryData results;
-  // Run a query with a join within.
-  std::string statement = "SELECT c2.data as data FROM cache c1, cache c2;";
-  auto status = queryInternal(statement, results, dbc);
-  dbc->clearAffectedTables();
-  ASSERT_TRUE(status.ok());
-  ASSERT_EQ(results.size(), 1U);
-  EXPECT_EQ(results[0]["data"], "more_awesome_data");
-
-  // Run the query again, the virtual table cache should have been expired.
-  results.clear();
-  statement = "SELECT data from cache c1";
-  queryInternal(statement, results, dbc);
-  ASSERT_EQ(results.size(), 1U);
-  ASSERT_EQ(results[0]["data"], "awesome_data");
+TEST_F(VirtualTableTests, test_table_cache)
+{
+       // Get a database connection.
+       auto tables = RegistryFactory::get().registry("table");
+       auto cache = std::make_shared<cacheTablePlugin>();
+       tables->add("cache", cache);
+       auto dbc = SQLiteDBManager::getUnique();
+       attachTableInternal("cache", cache->columnDefinition(false), dbc, false);
+
+       QueryData results;
+       // Run a query with a join within.
+       std::string statement = "SELECT c2.data as data FROM cache c1, cache c2;";
+       auto status = queryInternal(statement, results, dbc);
+       dbc->clearAffectedTables();
+       ASSERT_TRUE(status.ok());
+       ASSERT_EQ(results.size(), 1U);
+       EXPECT_EQ(results[0]["data"], "more_awesome_data");
+
+       // Run the query again, the virtual table cache should have been expired.
+       results.clear();
+       statement = "SELECT data from cache c1";
+       queryInternal(statement, results, dbc);
+       ASSERT_EQ(results.size(), 1U);
+       ASSERT_EQ(results[0]["data"], "awesome_data");
 }
 
 class tableCacheTablePlugin : public TablePlugin {
- public:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("i", TEXT_TYPE, ColumnOptions::INDEX),
-        std::make_tuple("d", TEXT_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
-  TableAttributes attributes() const override {
-    return TableAttributes::CACHEABLE;
-  }
-
-  TableRows generate(QueryContext& ctx) override {
-    if (isCached(60, ctx)) {
-      return getCache();
-    }
-
-    generates_++;
-    auto r = make_table_row();
-    r["i"] = "1";
-    TableRows result;
-    result.push_back(std::move(r));
-    setCache(60, 1, ctx, result);
-    return result;
-  }
-
-  size_t generates_{0};
+public:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("i", TEXT_TYPE, ColumnOptions::INDEX),
+                       std::make_tuple("d", TEXT_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+       TableAttributes attributes() const override
+       {
+               return TableAttributes::CACHEABLE;
+       }
+
+       TableRows generate(QueryContext& ctx) override
+       {
+               if (isCached(60, ctx)) {
+                       return getCache();
+               }
+
+               generates_++;
+               auto r = make_table_row();
+               r["i"] = "1";
+               TableRows result;
+               result.push_back(std::move(r));
+               setCache(60, 1, ctx, result);
+               return result;
+       }
+
+       size_t generates_{0};
 };
 
-TEST_F(VirtualTableTests, test_table_results_cache) {
-  // Get a database connection.
-  auto tables = RegistryFactory::get().registry("table");
-  auto cache = std::make_shared<tableCacheTablePlugin>();
-  tables->add("table_cache", cache);
-  auto dbc = SQLiteDBManager::getUnique();
-  attachTableInternal(
-      "table_cache", cache->columnDefinition(false), dbc, false);
-
-  QueryData results;
-  std::string statement = "SELECT * from table_cache;";
-  auto status = queryInternal(statement, results, dbc);
-  dbc->clearAffectedTables();
-
-  ASSERT_TRUE(status.ok());
-  EXPECT_EQ(results.size(), 1U);
-  EXPECT_EQ(cache->generates_, 1U);
-
-  // Run the query again, the virtual table cache was not requested.
-  results.clear();
-  statement = "SELECT * from table_cache;";
-  queryInternal(statement, results, dbc);
-  EXPECT_EQ(results.size(), 1U);
-
-  // The table should have used the cache.
-  EXPECT_EQ(cache->generates_, 2U);
-
-  // Now request that caching be used.
-  dbc->useCache(true);
-
-  // Run the query again, the virtual table cache will be populated.
-  results.clear();
-  statement = "SELECT * from table_cache;";
-  queryInternal(statement, results, dbc);
-  EXPECT_EQ(results.size(), 1U);
-  EXPECT_EQ(cache->generates_, 3U);
-
-  // Run the query again, the virtual table cache will be returned.
-  results.clear();
-  statement = "SELECT * from table_cache;";
-  queryInternal(statement, results, dbc);
-  EXPECT_EQ(results.size(), 1U);
-  EXPECT_EQ(cache->generates_, 3U);
-
-  // Once last time with constraints that invalidate the cache results.
-  results.clear();
-  statement = "SELECT * from table_cache where i = '1';";
-  queryInternal(statement, results, dbc);
-  EXPECT_EQ(results.size(), 1U);
-
-  // The table should NOT have used the cache.
-  EXPECT_EQ(cache->generates_, 4U);
+TEST_F(VirtualTableTests, test_table_results_cache)
+{
+       // Get a database connection.
+       auto tables = RegistryFactory::get().registry("table");
+       auto cache = std::make_shared<tableCacheTablePlugin>();
+       tables->add("table_cache", cache);
+       auto dbc = SQLiteDBManager::getUnique();
+       attachTableInternal(
+               "table_cache", cache->columnDefinition(false), dbc, false);
+
+       QueryData results;
+       std::string statement = "SELECT * from table_cache;";
+       auto status = queryInternal(statement, results, dbc);
+       dbc->clearAffectedTables();
+
+       ASSERT_TRUE(status.ok());
+       EXPECT_EQ(results.size(), 1U);
+       EXPECT_EQ(cache->generates_, 1U);
+
+       // Run the query again, the virtual table cache was not requested.
+       results.clear();
+       statement = "SELECT * from table_cache;";
+       queryInternal(statement, results, dbc);
+       EXPECT_EQ(results.size(), 1U);
+
+       // The table should have used the cache.
+       EXPECT_EQ(cache->generates_, 2U);
+
+       // Now request that caching be used.
+       dbc->useCache(true);
+
+       // Run the query again, the virtual table cache will be populated.
+       results.clear();
+       statement = "SELECT * from table_cache;";
+       queryInternal(statement, results, dbc);
+       EXPECT_EQ(results.size(), 1U);
+       EXPECT_EQ(cache->generates_, 3U);
+
+       // Run the query again, the virtual table cache will be returned.
+       results.clear();
+       statement = "SELECT * from table_cache;";
+       queryInternal(statement, results, dbc);
+       EXPECT_EQ(results.size(), 1U);
+       EXPECT_EQ(cache->generates_, 3U);
+
+       // Once last time with constraints that invalidate the cache results.
+       results.clear();
+       statement = "SELECT * from table_cache where i = '1';";
+       queryInternal(statement, results, dbc);
+       EXPECT_EQ(results.size(), 1U);
+
+       // The table should NOT have used the cache.
+       EXPECT_EQ(cache->generates_, 4U);
 }
 
 class likeTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("i", TEXT_TYPE, ColumnOptions::INDEX),
-        std::make_tuple("op", TEXT_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
- public:
-  TableRows generate(QueryContext& context) override {
-    TableRows results;
-
-    // To test, we'll move all predicate constraints into the result set.
-    // First we'll move constrains for the column `i` using operands =, LIKE.
-    auto i = context.constraints["i"].getAll(EQUALS);
-    for (const auto& constraint : i) {
-      auto r = make_table_row();
-      r["i"] = constraint;
-      r["op"] = "EQUALS";
-      results.push_back(std::move(r));
-    }
-
-    i = context.constraints["i"].getAll(LIKE);
-    for (const auto& constraint : i) {
-      auto r = make_table_row();
-      r["i"] = constraint;
-      r["op"] = "LIKE";
-      results.push_back(std::move(r));
-    }
-
-    return results;
-  }
-
- private:
-  FRIEND_TEST(VirtualTableTests, test_like_constraints);
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("i", TEXT_TYPE, ColumnOptions::INDEX),
+                       std::make_tuple("op", TEXT_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+public:
+       TableRows generate(QueryContext& context) override
+       {
+               TableRows results;
+
+               // To test, we'll move all predicate constraints into the result set.
+               // First we'll move constrains for the column `i` using operands =, LIKE.
+               auto i = context.constraints["i"].getAll(EQUALS);
+               for (const auto& constraint : i) {
+                       auto r = make_table_row();
+                       r["i"] = constraint;
+                       r["op"] = "EQUALS";
+                       results.push_back(std::move(r));
+               }
+
+               i = context.constraints["i"].getAll(LIKE);
+               for (const auto& constraint : i) {
+                       auto r = make_table_row();
+                       r["i"] = constraint;
+                       r["op"] = "LIKE";
+                       results.push_back(std::move(r));
+               }
+
+               return results;
+       }
+
+private:
+       FRIEND_TEST(VirtualTableTests, test_like_constraints);
 };
 
-TEST_F(VirtualTableTests, test_like_constraints) {
-  auto table = std::make_shared<likeTablePlugin>();
-  auto table_registry = RegistryFactory::get().registry("table");
-  table_registry->add("like_table", table);
-
-  auto dbc = SQLiteDBManager::getUnique();
-  attachTableInternal("like_table", table->columnDefinition(false), dbc, false);
-
-  // Base case, without constrains this table has no results.
-  QueryData results;
-  queryInternal("SELECT * FROM like_table", results, dbc);
-  dbc->clearAffectedTables();
-  ASSERT_EQ(results.size(), 0U);
-
-  // A single EQUAL constraint's value is emitted.
-  queryInternal("SELECT * FROM like_table WHERE i = '1'", results, dbc);
-  dbc->clearAffectedTables();
-  ASSERT_EQ(results.size(), 1U);
-  EXPECT_EQ(results[0]["i"], "1");
-  EXPECT_EQ(results[0]["op"], "EQUALS");
-
-  // When using OR, both values should be added.
-  results.clear();
-  queryInternal(
-      "SELECT * FROM like_table WHERE i = '1' OR i = '2'", results, dbc);
-  dbc->clearAffectedTables();
-  ASSERT_EQ(results.size(), 2U);
-  EXPECT_EQ(results[0]["i"], "1");
-  EXPECT_EQ(results[0]["op"], "EQUALS");
-  EXPECT_EQ(results[1]["i"], "2");
-  EXPECT_EQ(results[1]["op"], "EQUALS");
-
-  // When using a LIKE, the value (with substitution character) is emitted.
-  results.clear();
-  queryInternal(
-      "SELECT * FROM like_table WHERE i LIKE '/test/1/%'", results, dbc);
-  dbc->clearAffectedTables();
-  ASSERT_EQ(results.size(), 1U);
-  EXPECT_EQ(results[0]["i"], "/test/1/%");
-  EXPECT_EQ(results[0]["op"], "LIKE");
-
-  // As with EQUAL, multiple LIKEs mean multiple values.
-  results.clear();
-  queryInternal(
-      "SELECT * FROM like_table WHERE i LIKE '/test/1/%' OR i LIKE '/test/2/%'",
-      results,
-      dbc);
-  dbc->clearAffectedTables();
-  ASSERT_EQ(results.size(), 2U);
-  EXPECT_EQ(results[0]["i"], "/test/1/%");
-  EXPECT_EQ(results[0]["op"], "LIKE");
-  EXPECT_EQ(results[1]["i"], "/test/2/%");
-  EXPECT_EQ(results[1]["op"], "LIKE");
-
-  // As with EQUAL, multiple LIKEs mean multiple values.
-  results.clear();
-  queryInternal(
-      "SELECT * FROM like_table WHERE i LIKE '/home/%/downloads' OR i LIKE "
-      "'/home/%/documents'",
-      results,
-      dbc);
-  dbc->clearAffectedTables();
-  ASSERT_EQ(results.size(), 2U);
-  EXPECT_EQ(results[0]["i"], "/home/%/downloads");
-  EXPECT_EQ(results[0]["op"], "LIKE");
-  EXPECT_EQ(results[1]["i"], "/home/%/documents");
-  EXPECT_EQ(results[1]["op"], "LIKE");
+TEST_F(VirtualTableTests, test_like_constraints)
+{
+       auto table = std::make_shared<likeTablePlugin>();
+       auto table_registry = RegistryFactory::get().registry("table");
+       table_registry->add("like_table", table);
+
+       auto dbc = SQLiteDBManager::getUnique();
+       attachTableInternal("like_table", table->columnDefinition(false), dbc, false);
+
+       // Base case, without constrains this table has no results.
+       QueryData results;
+       queryInternal("SELECT * FROM like_table", results, dbc);
+       dbc->clearAffectedTables();
+       ASSERT_EQ(results.size(), 0U);
+
+       // A single EQUAL constraint's value is emitted.
+       queryInternal("SELECT * FROM like_table WHERE i = '1'", results, dbc);
+       dbc->clearAffectedTables();
+       ASSERT_EQ(results.size(), 1U);
+       EXPECT_EQ(results[0]["i"], "1");
+       EXPECT_EQ(results[0]["op"], "EQUALS");
+
+       // When using OR, both values should be added.
+       results.clear();
+       queryInternal(
+               "SELECT * FROM like_table WHERE i = '1' OR i = '2'", results, dbc);
+       dbc->clearAffectedTables();
+       ASSERT_EQ(results.size(), 2U);
+       EXPECT_EQ(results[0]["i"], "1");
+       EXPECT_EQ(results[0]["op"], "EQUALS");
+       EXPECT_EQ(results[1]["i"], "2");
+       EXPECT_EQ(results[1]["op"], "EQUALS");
+
+       // When using a LIKE, the value (with substitution character) is emitted.
+       results.clear();
+       queryInternal(
+               "SELECT * FROM like_table WHERE i LIKE '/test/1/%'", results, dbc);
+       dbc->clearAffectedTables();
+       ASSERT_EQ(results.size(), 1U);
+       EXPECT_EQ(results[0]["i"], "/test/1/%");
+       EXPECT_EQ(results[0]["op"], "LIKE");
+
+       // As with EQUAL, multiple LIKEs mean multiple values.
+       results.clear();
+       queryInternal(
+               "SELECT * FROM like_table WHERE i LIKE '/test/1/%' OR i LIKE '/test/2/%'",
+               results,
+               dbc);
+       dbc->clearAffectedTables();
+       ASSERT_EQ(results.size(), 2U);
+       EXPECT_EQ(results[0]["i"], "/test/1/%");
+       EXPECT_EQ(results[0]["op"], "LIKE");
+       EXPECT_EQ(results[1]["i"], "/test/2/%");
+       EXPECT_EQ(results[1]["op"], "LIKE");
+
+       // As with EQUAL, multiple LIKEs mean multiple values.
+       results.clear();
+       queryInternal(
+               "SELECT * FROM like_table WHERE i LIKE '/home/%/downloads' OR i LIKE "
+               "'/home/%/documents'",
+               results,
+               dbc);
+       dbc->clearAffectedTables();
+       ASSERT_EQ(results.size(), 2U);
+       EXPECT_EQ(results[0]["i"], "/home/%/downloads");
+       EXPECT_EQ(results[0]["op"], "LIKE");
+       EXPECT_EQ(results[1]["i"], "/home/%/documents");
+       EXPECT_EQ(results[1]["op"], "LIKE");
 }
 
 class indexIOptimizedTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("i", INTEGER_TYPE, ColumnOptions::INDEX),
-        std::make_tuple("j", INTEGER_TYPE, ColumnOptions::DEFAULT),
-        std::make_tuple("text", INTEGER_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
- public:
-  TableRows generate(QueryContext& context) override {
-    scans++;
-
-    TableRows results;
-    auto indexes = context.constraints["i"].getAll<int>(EQUALS);
-    for (const auto& i : indexes) {
-      results.push_back(make_table_row(
-          {{"i", INTEGER(i)}, {"j", INTEGER(i * 10)}, {"text", "none"}}));
-    }
-    if (indexes.empty()) {
-      for (size_t i = 0; i < 100; i++) {
-        results.push_back(make_table_row(
-            {{"i", INTEGER(i)}, {"j", INTEGER(i * 10)}, {"text", "some"}}));
-      }
-    }
-    return results;
-  }
-
-  // Here the goal is to expect/assume the number of scans.
-  size_t scans{0};
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("i", INTEGER_TYPE, ColumnOptions::INDEX),
+                       std::make_tuple("j", INTEGER_TYPE, ColumnOptions::DEFAULT),
+                       std::make_tuple("text", INTEGER_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+public:
+       TableRows generate(QueryContext& context) override
+       {
+               scans++;
+
+               TableRows results;
+               auto indexes = context.constraints["i"].getAll<int>(EQUALS);
+               for (const auto& i : indexes) {
+                       results.push_back(make_table_row(
+                       {{"i", INTEGER(i)}, {"j", INTEGER(i * 10)}, {"text", "none"}}));
+               }
+               if (indexes.empty()) {
+                       for (size_t i = 0; i < 100; i++) {
+                               results.push_back(make_table_row(
+                               {{"i", INTEGER(i)}, {"j", INTEGER(i * 10)}, {"text", "some"}}));
+                       }
+               }
+               return results;
+       }
+
+       // Here the goal is to expect/assume the number of scans.
+       size_t scans{0};
 };
 
 class indexJOptimizedTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("j", INTEGER_TYPE, ColumnOptions::INDEX),
-        std::make_tuple("text", INTEGER_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
- public:
-  TableRows generate(QueryContext& context) override {
-    scans++;
-
-    TableRows results;
-    auto indexes = context.constraints["j"].getAll<int>(EQUALS);
-    for (const auto& j : indexes) {
-      results.push_back(make_table_row({{"j", INTEGER(j)}, {"text", "none"}}));
-    }
-    if (indexes.empty()) {
-      for (size_t j = 0; j < 100; j++) {
-        results.push_back(
-            make_table_row({{"j", INTEGER(j)}, {"text", "some"}}));
-      }
-    }
-    return results;
-  }
-
-  // Here the goal is to expect/assume the number of scans.
-  size_t scans{0};
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("j", INTEGER_TYPE, ColumnOptions::INDEX),
+                       std::make_tuple("text", INTEGER_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+public:
+       TableRows generate(QueryContext& context) override
+       {
+               scans++;
+
+               TableRows results;
+               auto indexes = context.constraints["j"].getAll<int>(EQUALS);
+               for (const auto& j : indexes) {
+                       results.push_back(make_table_row({{"j", INTEGER(j)}, {"text", "none"}}));
+               }
+               if (indexes.empty()) {
+                       for (size_t j = 0; j < 100; j++) {
+                               results.push_back(
+                               make_table_row({{"j", INTEGER(j)}, {"text", "some"}}));
+                       }
+               }
+               return results;
+       }
+
+       // Here the goal is to expect/assume the number of scans.
+       size_t scans{0};
 };
 
 class defaultScanTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("i", INTEGER_TYPE, ColumnOptions::DEFAULT),
-        std::make_tuple("text", INTEGER_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
- public:
-  TableRows generate(QueryContext& context) override {
-    scans++;
-
-    TableRows results;
-    for (size_t i = 0; i < 10; i++) {
-      results.push_back(make_table_row({{"i", INTEGER(i)}, {"text", "some"}}));
-    }
-    return results;
-  }
-
-  // Here the goal is to expect/assume the number of scans.
-  size_t scans{0};
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("i", INTEGER_TYPE, ColumnOptions::DEFAULT),
+                       std::make_tuple("text", INTEGER_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+public:
+       TableRows generate(QueryContext& context) override
+       {
+               scans++;
+
+               TableRows results;
+               for (size_t i = 0; i < 10; i++) {
+                       results.push_back(make_table_row({{"i", INTEGER(i)}, {"text", "some"}}));
+               }
+               return results;
+       }
+
+       // Here the goal is to expect/assume the number of scans.
+       size_t scans{0};
 };
 
 class colsUsedTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("col1", TEXT_TYPE, ColumnOptions::DEFAULT),
-        std::make_tuple("col2", TEXT_TYPE, ColumnOptions::DEFAULT),
-        std::make_tuple("col3", TEXT_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
-  ColumnAliasSet columnAliases() const override {
-    return {
-        {"col2", {"aliasToCol2"}},
-    };
-  }
-
- public:
-  TableRows generate(QueryContext& context) override {
-    auto r = make_table_row();
-    if (context.isColumnUsed("col1")) {
-      r["col1"] = "value1";
-    }
-    if (context.isColumnUsed("col2")) {
-      r["col2"] = "value2";
-    }
-    if (context.isColumnUsed("col3")) {
-      r["col3"] = "value3";
-    }
-    TableRows result;
-    result.push_back(std::move(r));
-    return result;
-  }
-
- private:
-  FRIEND_TEST(VirtualTableTests, test_used_columns);
-  FRIEND_TEST(VirtualTableTests, test_used_columns_with_alias);
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("col1", TEXT_TYPE, ColumnOptions::DEFAULT),
+                       std::make_tuple("col2", TEXT_TYPE, ColumnOptions::DEFAULT),
+                       std::make_tuple("col3", TEXT_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+       ColumnAliasSet columnAliases() const override
+       {
+               return {
+                       {"col2", {"aliasToCol2"}},
+               };
+       }
+
+public:
+       TableRows generate(QueryContext& context) override
+       {
+               auto r = make_table_row();
+               if (context.isColumnUsed("col1")) {
+                       r["col1"] = "value1";
+               }
+               if (context.isColumnUsed("col2")) {
+                       r["col2"] = "value2";
+               }
+               if (context.isColumnUsed("col3")) {
+                       r["col3"] = "value3";
+               }
+               TableRows result;
+               result.push_back(std::move(r));
+               return result;
+       }
+
+private:
+       FRIEND_TEST(VirtualTableTests, test_used_columns);
+       FRIEND_TEST(VirtualTableTests, test_used_columns_with_alias);
 };
 
-TEST_F(VirtualTableTests, test_used_columns) {
-  // Add testing table to the registry.
-  auto tables = RegistryFactory::get().registry("table");
-  auto colsUsed = std::make_shared<colsUsedTablePlugin>();
-  tables->add("colsUsed1", colsUsed);
-  auto dbc = SQLiteDBManager::getUnique();
-  attachTableInternal(
-      "colsUsed1", colsUsed->columnDefinition(false), dbc, false);
-
-  QueryData results;
-  auto status = queryInternal("SELECT col1, col3 FROM colsUsed1", results, dbc);
-  EXPECT_TRUE(status.ok());
-  ASSERT_EQ(results.size(), 1U);
-  EXPECT_EQ(results[0]["col1"], "value1");
-  EXPECT_EQ(results[0].find("col2"), results[0].end());
-  EXPECT_EQ(results[0]["col3"], "value3");
-  EXPECT_EQ(results[0].find("aliasToCol2"), results[0].end());
+TEST_F(VirtualTableTests, test_used_columns)
+{
+       // Add testing table to the registry.
+       auto tables = RegistryFactory::get().registry("table");
+       auto colsUsed = std::make_shared<colsUsedTablePlugin>();
+       tables->add("colsUsed1", colsUsed);
+       auto dbc = SQLiteDBManager::getUnique();
+       attachTableInternal(
+               "colsUsed1", colsUsed->columnDefinition(false), dbc, false);
+
+       QueryData results;
+       auto status = queryInternal("SELECT col1, col3 FROM colsUsed1", results, dbc);
+       EXPECT_TRUE(status.ok());
+       ASSERT_EQ(results.size(), 1U);
+       EXPECT_EQ(results[0]["col1"], "value1");
+       EXPECT_EQ(results[0].find("col2"), results[0].end());
+       EXPECT_EQ(results[0]["col3"], "value3");
+       EXPECT_EQ(results[0].find("aliasToCol2"), results[0].end());
 }
 
-TEST_F(VirtualTableTests, test_used_columns_with_alias) {
-  // Add testing table to the registry.
-  auto tables = RegistryFactory::get().registry("table");
-  auto colsUsed = std::make_shared<colsUsedTablePlugin>();
-  tables->add("colsUsed2", colsUsed);
-  auto dbc = SQLiteDBManager::getUnique();
-  attachTableInternal(
-      "colsUsed2", colsUsed->columnDefinition(false), dbc, false);
-
-  QueryData results;
-  auto status =
-      queryInternal("SELECT aliasToCol2 FROM colsUsed2", results, dbc);
-  EXPECT_TRUE(status.ok());
-  ASSERT_EQ(results.size(), 1U);
-  EXPECT_EQ(results[0].find("col1"), results[0].end());
-  EXPECT_EQ(results[0].find("col2"), results[0].end());
-  EXPECT_EQ(results[0].find("col3"), results[0].end());
-  EXPECT_EQ(results[0]["aliasToCol2"], "value2");
+TEST_F(VirtualTableTests, test_used_columns_with_alias)
+{
+       // Add testing table to the registry.
+       auto tables = RegistryFactory::get().registry("table");
+       auto colsUsed = std::make_shared<colsUsedTablePlugin>();
+       tables->add("colsUsed2", colsUsed);
+       auto dbc = SQLiteDBManager::getUnique();
+       attachTableInternal(
+               "colsUsed2", colsUsed->columnDefinition(false), dbc, false);
+
+       QueryData results;
+       auto status =
+               queryInternal("SELECT aliasToCol2 FROM colsUsed2", results, dbc);
+       EXPECT_TRUE(status.ok());
+       ASSERT_EQ(results.size(), 1U);
+       EXPECT_EQ(results[0].find("col1"), results[0].end());
+       EXPECT_EQ(results[0].find("col2"), results[0].end());
+       EXPECT_EQ(results[0].find("col3"), results[0].end());
+       EXPECT_EQ(results[0]["aliasToCol2"], "value2");
 }
 
 class colsUsedBitsetTablePlugin : public TablePlugin {
- private:
-  TableColumns columns() const override {
-    return {
-        std::make_tuple("col1", TEXT_TYPE, ColumnOptions::DEFAULT),
-        std::make_tuple("col2", TEXT_TYPE, ColumnOptions::DEFAULT),
-        std::make_tuple("col3", TEXT_TYPE, ColumnOptions::DEFAULT),
-    };
-  }
-
-  ColumnAliasSet columnAliases() const override {
-    return {
-        {"col2", {"aliasToCol2"}},
-    };
-  }
-
- public:
-  TableRows generate(QueryContext& context) override {
-    TableRows results;
-    auto r = make_table_row();
-    if (context.isAnyColumnUsed(UsedColumnsBitset(0x1))) {
-      r["col1"] = "value1";
-    }
-    if (context.isAnyColumnUsed(UsedColumnsBitset(0x2))) {
-      r["col2"] = "value2";
-    }
-    if (context.isAnyColumnUsed(UsedColumnsBitset(0x4))) {
-      r["col3"] = "value3";
-    }
-    results.push_back(std::move(r));
-    return results;
-  }
-
- private:
-  FRIEND_TEST(VirtualTableTests, test_used_columns_bitset);
-  FRIEND_TEST(VirtualTableTests, test_used_columns_bitset_with_alias);
+private:
+       TableColumns columns() const override
+       {
+               return {
+                       std::make_tuple("col1", TEXT_TYPE, ColumnOptions::DEFAULT),
+                       std::make_tuple("col2", TEXT_TYPE, ColumnOptions::DEFAULT),
+                       std::make_tuple("col3", TEXT_TYPE, ColumnOptions::DEFAULT),
+               };
+       }
+
+       ColumnAliasSet columnAliases() const override
+       {
+               return {
+                       {"col2", {"aliasToCol2"}},
+               };
+       }
+
+public:
+       TableRows generate(QueryContext& context) override
+       {
+               TableRows results;
+               auto r = make_table_row();
+               if (context.isAnyColumnUsed(UsedColumnsBitset(0x1))) {
+                       r["col1"] = "value1";
+               }
+               if (context.isAnyColumnUsed(UsedColumnsBitset(0x2))) {
+                       r["col2"] = "value2";
+               }
+               if (context.isAnyColumnUsed(UsedColumnsBitset(0x4))) {
+                       r["col3"] = "value3";
+               }
+               results.push_back(std::move(r));
+               return results;
+       }
+
+private:
+       FRIEND_TEST(VirtualTableTests, test_used_columns_bitset);
+       FRIEND_TEST(VirtualTableTests, test_used_columns_bitset_with_alias);
 };
 
-TEST_F(VirtualTableTests, test_used_columns_bitset) {
-  // Add testing table to the registry.
-  auto tables = RegistryFactory::get().registry("table");
-  auto colsUsed = std::make_shared<colsUsedBitsetTablePlugin>();
-  tables->add("colsUsedBitset1", colsUsed);
-  auto dbc = SQLiteDBManager::getUnique();
-  attachTableInternal(
-      "colsUsedBitset1", colsUsed->columnDefinition(false), dbc, false);
-
-  QueryData results;
-  auto status =
-      queryInternal("SELECT col1, col3 FROM colsUsedBitset1", results, dbc);
-  EXPECT_TRUE(status.ok());
-  ASSERT_EQ(results.size(), 1U);
-  EXPECT_EQ(results[0]["col1"], "value1");
-  EXPECT_EQ(results[0].find("col2"), results[0].end());
-  EXPECT_EQ(results[0]["col3"], "value3");
-  EXPECT_EQ(results[0].find("aliasToCol2"), results[0].end());
+TEST_F(VirtualTableTests, test_used_columns_bitset)
+{
+       // Add testing table to the registry.
+       auto tables = RegistryFactory::get().registry("table");
+       auto colsUsed = std::make_shared<colsUsedBitsetTablePlugin>();
+       tables->add("colsUsedBitset1", colsUsed);
+       auto dbc = SQLiteDBManager::getUnique();
+       attachTableInternal(
+               "colsUsedBitset1", colsUsed->columnDefinition(false), dbc, false);
+
+       QueryData results;
+       auto status =
+               queryInternal("SELECT col1, col3 FROM colsUsedBitset1", results, dbc);
+       EXPECT_TRUE(status.ok());
+       ASSERT_EQ(results.size(), 1U);
+       EXPECT_EQ(results[0]["col1"], "value1");
+       EXPECT_EQ(results[0].find("col2"), results[0].end());
+       EXPECT_EQ(results[0]["col3"], "value3");
+       EXPECT_EQ(results[0].find("aliasToCol2"), results[0].end());
 }
 
-TEST_F(VirtualTableTests, test_used_columns_bitset_with_alias) {
-  // Add testing table to the registry.
-  auto tables = RegistryFactory::get().registry("table");
-  auto colsUsed = std::make_shared<colsUsedBitsetTablePlugin>();
-  tables->add("colsUsedBitset2", colsUsed);
-  auto dbc = SQLiteDBManager::getUnique();
-  attachTableInternal(
-      "colsUsedBitset2", colsUsed->columnDefinition(false), dbc, false);
-
-  QueryData results;
-  auto status =
-      queryInternal("SELECT aliasToCol2 FROM colsUsedBitset2", results, dbc);
-  EXPECT_TRUE(status.ok());
-  ASSERT_EQ(results.size(), 1U);
-  EXPECT_EQ(results[0].find("col1"), results[0].end());
-  EXPECT_EQ(results[0].find("col2"), results[0].end());
-  EXPECT_EQ(results[0].find("col3"), results[0].end());
-  EXPECT_EQ(results[0]["aliasToCol2"], "value2");
+TEST_F(VirtualTableTests, test_used_columns_bitset_with_alias)
+{
+       // Add testing table to the registry.
+       auto tables = RegistryFactory::get().registry("table");
+       auto colsUsed = std::make_shared<colsUsedBitsetTablePlugin>();
+       tables->add("colsUsedBitset2", colsUsed);
+       auto dbc = SQLiteDBManager::getUnique();
+       attachTableInternal(
+               "colsUsedBitset2", colsUsed->columnDefinition(false), dbc, false);
+
+       QueryData results;
+       auto status =
+               queryInternal("SELECT aliasToCol2 FROM colsUsedBitset2", results, dbc);
+       EXPECT_TRUE(status.ok());
+       ASSERT_EQ(results.size(), 1U);
+       EXPECT_EQ(results[0].find("col1"), results[0].end());
+       EXPECT_EQ(results[0].find("col2"), results[0].end());
+       EXPECT_EQ(results[0].find("col3"), results[0].end());
+       EXPECT_EQ(results[0]["aliasToCol2"], "value2");
 }
 } // namespace osquery
index 57fc4c31b52d0b5f82bfede3874050e2a7cb7204..b01567d93510a85427e2d8c4e5c7a09475f3bb99 100644 (file)
@@ -20,94 +20,97 @@ namespace errc = boost::system::errc;
 
 namespace osquery {
 
-const char* getSystemVFS(bool respect_locking) {
-  return "unix-none";
+const char* getSystemVFS(bool respect_locking)
+{
+       return "unix-none";
 }
 
 Status genSqliteTableRow(sqlite3_stmt* stmt,
-                         TableRows& qd,
-                         const fs::path& sqlite_db) {
-  auto r = make_table_row();
-  for (int i = 0; i < sqlite3_column_count(stmt); ++i) {
-    auto column_name = std::string(sqlite3_column_name(stmt, i));
-    auto column_type = sqlite3_column_type(stmt, i);
-    switch (column_type) {
-    case SQLITE_TEXT: {
-      auto text_value = sqlite3_column_text(stmt, i);
-      if (text_value != nullptr) {
-        r[column_name] = std::string(reinterpret_cast<const char*>(text_value));
-      }
-      break;
-    }
-    case SQLITE_FLOAT: {
-      auto float_value = sqlite3_column_double(stmt, i);
-      r[column_name] = DOUBLE(float_value);
-      break;
-    }
-    case SQLITE_INTEGER: {
-      auto int_value = sqlite3_column_int(stmt, i);
-      r[column_name] = INTEGER(int_value);
-      break;
-    }
-    }
-  }
-  if (r.count("path") > 0) {
-    WARN(OSQUERY) << "Row contains a path key, refusing to overwrite";
-  } else {
-    r["path"] = sqlite_db.string();
-  }
-  qd.push_back(std::move(r));
-  return Status::success();
+                                                TableRows& qd,
+                                                const fs::path& sqlite_db)
+{
+       auto r = make_table_row();
+       for (int i = 0; i < sqlite3_column_count(stmt); ++i) {
+               auto column_name = std::string(sqlite3_column_name(stmt, i));
+               auto column_type = sqlite3_column_type(stmt, i);
+               switch (column_type) {
+               case SQLITE_TEXT: {
+                       auto text_value = sqlite3_column_text(stmt, i);
+                       if (text_value != nullptr) {
+                               r[column_name] = std::string(reinterpret_cast<const char*>(text_value));
+                       }
+                       break;
+               }
+               case SQLITE_FLOAT: {
+                       auto float_value = sqlite3_column_double(stmt, i);
+                       r[column_name] = DOUBLE(float_value);
+                       break;
+               }
+               case SQLITE_INTEGER: {
+                       auto int_value = sqlite3_column_int(stmt, i);
+                       r[column_name] = INTEGER(int_value);
+                       break;
+               }
+               }
+       }
+       if (r.count("path") > 0) {
+               WARN(OSQUERY) << "Row contains a path key, refusing to overwrite";
+       } else {
+               r["path"] = sqlite_db.string();
+       }
+       qd.push_back(std::move(r));
+       return Status::success();
 }
 
 Status genTableRowsForSqliteTable(const fs::path& sqlite_db,
-                                  const std::string& sqlite_query,
-                                  TableRows& results,
-                                  bool respect_locking) {
-  sqlite3* db = nullptr;
-  boost::system::error_code ec;
-  if (sqlite_db.empty()) {
-    return Status(1, "Database path does not exist");
-  }
+                                                                 const std::string& sqlite_query,
+                                                                 TableRows& results,
+                                                                 bool respect_locking)
+{
+       sqlite3* db = nullptr;
+       boost::system::error_code ec;
+       if (sqlite_db.empty()) {
+               return Status(1, "Database path does not exist");
+       }
 
-  // A tri-state determination of presence
-  if (!fs::exists(sqlite_db, ec) || ec.value() != errc::success) {
-    return Status(1, ec.message());
-  }
+       // A tri-state determination of presence
+       if (!fs::exists(sqlite_db, ec) || ec.value() != errc::success) {
+               return Status(1, ec.message());
+       }
 
-  auto rc = sqlite3_open_v2(
-      sqlite_db.string().c_str(),
-      &db,
-      (SQLITE_OPEN_READONLY | SQLITE_OPEN_PRIVATECACHE | SQLITE_OPEN_NOMUTEX),
-      getSystemVFS(respect_locking));
-  if (rc != SQLITE_OK || db == nullptr) {
-    DEBUG(OSQUERY) << "Cannot open specified database: "
-            << getStringForSQLiteReturnCode(rc);
-    if (db != nullptr) {
-      sqlite3_close(db);
-    }
-    return Status(1, "Could not open database");
-  }
+       auto rc = sqlite3_open_v2(
+                                 sqlite_db.string().c_str(),
+                                 &db,
+                                 (SQLITE_OPEN_READONLY | SQLITE_OPEN_PRIVATECACHE | SQLITE_OPEN_NOMUTEX),
+                                 getSystemVFS(respect_locking));
+       if (rc != SQLITE_OK || db == nullptr) {
+               DEBUG(OSQUERY) << "Cannot open specified database: "
+                                          << getStringForSQLiteReturnCode(rc);
+               if (db != nullptr) {
+                       sqlite3_close(db);
+               }
+               return Status(1, "Could not open database");
+       }
 
-  sqlite3_stmt* stmt = nullptr;
-  rc = sqlite3_prepare_v2(db, sqlite_query.c_str(), -1, &stmt, nullptr);
-  if (rc != SQLITE_OK) {
-    sqlite3_close(db);
-    DEBUG(OSQUERY) << "Could not prepare database at path: " << sqlite_db;
-    return Status(rc, "Could not prepare database");
-  }
+       sqlite3_stmt* stmt = nullptr;
+       rc = sqlite3_prepare_v2(db, sqlite_query.c_str(), -1, &stmt, nullptr);
+       if (rc != SQLITE_OK) {
+               sqlite3_close(db);
+               DEBUG(OSQUERY) << "Could not prepare database at path: " << sqlite_db;
+               return Status(rc, "Could not prepare database");
+       }
 
-  while ((sqlite3_step(stmt)) == SQLITE_ROW) {
-    auto s = genSqliteTableRow(stmt, results, sqlite_db);
-    if (!s.ok()) {
-      break;
-    }
-  }
+       while ((sqlite3_step(stmt)) == SQLITE_ROW) {
+               auto s = genSqliteTableRow(stmt, results, sqlite_db);
+               if (!s.ok()) {
+                       break;
+               }
+       }
 
-  // Close handles and free memory
-  sqlite3_finalize(stmt);
-  sqlite3_close(db);
+       // Close handles and free memory
+       sqlite3_finalize(stmt);
+       sqlite3_close(db);
 
-  return Status{};
+       return Status{};
 }
 } // namespace osquery
index ecf02523290d21d2b598a8999e91088b8b3a98c3..92218426f44dbf8ba75f24f1802cfbd45f207d59 100644 (file)
@@ -37,30 +37,31 @@ static std::atomic<size_t> kPlannerCursorID{0};
  */
 static std::atomic<size_t> kConstraintIndexID{0};
 
-static inline std::string opString(unsigned char op) {
-  switch (op) {
-  case EQUALS:
-    return "=";
-  case GREATER_THAN:
-    return ">";
-  case LESS_THAN_OR_EQUALS:
-    return "<=";
-  case LESS_THAN:
-    return "<";
-  case GREATER_THAN_OR_EQUALS:
-    return ">=";
-  case LIKE:
-    return "LIKE";
-  case MATCH:
-    return "MATCH";
-  case GLOB:
-    return "GLOB";
-  case REGEXP:
-    return "REGEX";
-  case UNIQUE:
-    return "UNIQUE";
-  }
-  return "?";
+static inline std::string opString(unsigned char op)
+{
+       switch (op) {
+       case EQUALS:
+               return "=";
+       case GREATER_THAN:
+               return ">";
+       case LESS_THAN_OR_EQUALS:
+               return "<=";
+       case LESS_THAN:
+               return "<";
+       case GREATER_THAN_OR_EQUALS:
+               return ">=";
+       case LIKE:
+               return "LIKE";
+       case MATCH:
+               return "MATCH";
+       case GLOB:
+               return "GLOB";
+       case REGEXP:
+               return "REGEX";
+       case UNIQUE:
+               return "UNIQUE";
+       }
+       return "?";
 }
 
 namespace {
@@ -70,53 +71,55 @@ std::unordered_map<std::string, struct sqlite3_module> sqlite_module_map;
 Mutex sqlite_module_map_mutex;
 
 bool getColumnValue(std::string& value,
-                    size_t index,
-                    size_t argc,
-                    sqlite3_value** argv) {
-  value.clear();
-
-  if (index >= argc) {
-    return false;
-  }
-
-  auto sqlite_value = argv[index];
-  switch (sqlite3_value_type(sqlite_value)) {
-  case SQLITE_INTEGER: {
-    auto temp = sqlite3_value_int64(sqlite_value);
-    value = std::to_string(temp);
-    break;
-  }
-
-  case SQLITE_FLOAT: {
-    auto temp = sqlite3_value_double(sqlite_value);
-    value = std::to_string(temp);
-    break;
-  }
-
-  case SQLITE_BLOB:
-  case SQLITE3_TEXT: {
-    auto data_ptr = static_cast<const char*>(sqlite3_value_blob(sqlite_value));
-    auto buffer_size = static_cast<size_t>(sqlite3_value_bytes(sqlite_value));
-
-    value.assign(data_ptr, buffer_size);
-    break;
-  }
-
-  case SQLITE_NULL: {
-    break;
-  }
-
-  default: {
-    ERROR(OSQUERY) << "Invalid column type returned by sqlite";
-    return false;
-  }
-  }
-
-  return true;
+                                       size_t index,
+                                       size_t argc,
+                                       sqlite3_value** argv)
+{
+       value.clear();
+
+       if (index >= argc) {
+               return false;
+       }
+
+       auto sqlite_value = argv[index];
+       switch (sqlite3_value_type(sqlite_value)) {
+       case SQLITE_INTEGER: {
+               auto temp = sqlite3_value_int64(sqlite_value);
+               value = std::to_string(temp);
+               break;
+       }
+
+       case SQLITE_FLOAT: {
+               auto temp = sqlite3_value_double(sqlite_value);
+               value = std::to_string(temp);
+               break;
+       }
+
+       case SQLITE_BLOB:
+       case SQLITE3_TEXT: {
+               auto data_ptr = static_cast<const char*>(sqlite3_value_blob(sqlite_value));
+               auto buffer_size = static_cast<size_t>(sqlite3_value_bytes(sqlite_value));
+
+               value.assign(data_ptr, buffer_size);
+               break;
+       }
+
+       case SQLITE_NULL: {
+               break;
+       }
+
+       default: {
+               ERROR(OSQUERY) << "Invalid column type returned by sqlite";
+               return false;
+       }
+       }
+
+       return true;
 }
 
 /// PATCH START //////////////////////////////////////////////////////////////
-int serializeDeleteParameters(std::string& serialized, VirtualTable* pVtab) {
+int serializeDeleteParameters(std::string& serialized, VirtualTable* pVtab)
+{
        auto content = pVtab->content;
        if (content->constraints.size() <= 0) {
                ERROR(OSQUERY) << "Invalid constraints arguments";
@@ -149,7 +152,8 @@ int serializeDeleteParameters(std::string& serialized, VirtualTable* pVtab) {
 int serializeUpdateParameters(std::string& serialized,
                                                          size_t argc,
                                                          sqlite3_value** argv,
-                                                         const TableColumns& columnDescriptors) {
+                                                         const TableColumns& columnDescriptors)
+{
        if (columnDescriptors.size() != argc - 2U) {
                DEBUG(VIST) << "Wrong column count: " << argc - 2U
                                        << ". Expected: " << columnDescriptors.size();
@@ -172,7 +176,7 @@ int serializeUpdateParameters(std::string& serialized,
                switch (receivedValueType) {
                case SQLITE_INTEGER: {
                        if (columnType != INTEGER_TYPE && columnType != BIGINT_TYPE &&
-                                       columnType != UNSIGNED_BIGINT_TYPE) {
+                               columnType != UNSIGNED_BIGINT_TYPE) {
                                return SQLITE_MISMATCH;
                        }
 
@@ -197,7 +201,7 @@ int serializeUpdateParameters(std::string& serialized,
                        else
                                typeMismatch = columnType != TEXT_TYPE;
 
-                       if (typeMismatch) 
+                       if (typeMismatch)
                                return SQLITE_MISMATCH;
 
                        auto data_pointer = sqlite3_value_blob(sqlite_value);
@@ -238,803 +242,823 @@ int serializeUpdateParameters(std::string& serialized,
 }
 
 void setTableErrorMessage(sqlite3_vtab* vtable,
-                          const std::string& error_message) {
-  // We are required to always replace the pointer with memory
-  // allocated with sqlite3_malloc. This buffer is freed automatically
-  // by sqlite3 on exit
-  //
-  // Documentation: https://www.sqlite.org/vtab.html section 1.2
-
-  if (vtable->zErrMsg != nullptr) {
-    sqlite3_free(vtable->zErrMsg);
-  }
-
-  auto buffer_size = static_cast<int>(error_message.size() + 1);
-
-  vtable->zErrMsg = static_cast<char*>(sqlite3_malloc(buffer_size));
-  if (vtable->zErrMsg != nullptr) {
-    memcpy(vtable->zErrMsg, error_message.c_str(), buffer_size);
-  }
+                                                 const std::string& error_message)
+{
+       // We are required to always replace the pointer with memory
+       // allocated with sqlite3_malloc. This buffer is freed automatically
+       // by sqlite3 on exit
+       //
+       // Documentation: https://www.sqlite.org/vtab.html section 1.2
+
+       if (vtable->zErrMsg != nullptr) {
+               sqlite3_free(vtable->zErrMsg);
+       }
+
+       auto buffer_size = static_cast<int>(error_message.size() + 1);
+
+       vtable->zErrMsg = static_cast<char*>(sqlite3_malloc(buffer_size));
+       if (vtable->zErrMsg != nullptr) {
+               memcpy(vtable->zErrMsg, error_message.c_str(), buffer_size);
+       }
 }
 } // namespace
 
-inline std::string table_doc(const std::string& name) {
-  return "https://osquery.io/schema/#" + name;
+inline std::string table_doc(const std::string& name)
+{
+       return "https://osquery.io/schema/#" + name;
 }
 
-static void plan(const std::string& output) {
+static void plan(const std::string& output)
+{
 }
 
-int xOpen(sqlite3_vtab* tab, sqlite3_vtab_cursor** ppCursor) {
-  auto* pCur = new BaseCursor;
-  auto* pVtab = (VirtualTable*)tab;
-  plan("Opening cursor (" + std::to_string(kPlannerCursorID) +
-       ") for table: " + pVtab->content->name);
-  pCur->id = kPlannerCursorID++;
-  pCur->base.pVtab = tab;
-  *ppCursor = (sqlite3_vtab_cursor*)pCur;
+int xOpen(sqlite3_vtab* tab, sqlite3_vtab_cursor** ppCursor)
+{
+       auto* pCur = new BaseCursor;
+       auto* pVtab = (VirtualTable*)tab;
+       plan("Opening cursor (" + std::to_string(kPlannerCursorID) +
+                ") for table: " + pVtab->content->name);
+       pCur->id = kPlannerCursorID++;
+       pCur->base.pVtab = tab;
+       *ppCursor = (sqlite3_vtab_cursor*)pCur;
 
-  return SQLITE_OK;
+       return SQLITE_OK;
 }
 
-int xClose(sqlite3_vtab_cursor* cur) {
-  BaseCursor* pCur = (BaseCursor*)cur;
-  plan("Closing cursor (" + std::to_string(pCur->id) + ")");
-  delete pCur;
-  return SQLITE_OK;
+int xClose(sqlite3_vtab_cursor* cur)
+{
+       BaseCursor* pCur = (BaseCursor*)cur;
+       plan("Closing cursor (" + std::to_string(pCur->id) + ")");
+       delete pCur;
+       return SQLITE_OK;
 }
 
-int xEof(sqlite3_vtab_cursor* cur) {
-  BaseCursor* pCur = (BaseCursor*)cur;
+int xEof(sqlite3_vtab_cursor* cur)
+{
+       BaseCursor* pCur = (BaseCursor*)cur;
 
-  if (pCur->row >= pCur->n) {
-    // If the requested row exceeds the size of the row set then all rows
-    // have been visited, clear the data container.
-    return true;
-  }
-  return false;
+       if (pCur->row >= pCur->n) {
+               // If the requested row exceeds the size of the row set then all rows
+               // have been visited, clear the data container.
+               return true;
+       }
+       return false;
 }
 
-int xDestroy(sqlite3_vtab* p) {
-  auto* pVtab = (VirtualTable*)p;
-  delete pVtab;
-  return SQLITE_OK;
+int xDestroy(sqlite3_vtab* p)
+{
+       auto* pVtab = (VirtualTable*)p;
+       delete pVtab;
+       return SQLITE_OK;
 }
 
-int xNext(sqlite3_vtab_cursor* cur) {
-  BaseCursor* pCur = (BaseCursor*)cur;
-  pCur->row++;
-  return SQLITE_OK;
+int xNext(sqlite3_vtab_cursor* cur)
+{
+       BaseCursor* pCur = (BaseCursor*)cur;
+       pCur->row++;
+       return SQLITE_OK;
 }
 
-int xRowid(sqlite3_vtab_cursor* cur, sqlite_int64* pRowid) {
-  *pRowid = 0;
+int xRowid(sqlite3_vtab_cursor* cur, sqlite_int64* pRowid)
+{
+       *pRowid = 0;
 
-  const BaseCursor* pCur = (BaseCursor*)cur;
-  auto data_it = std::next(pCur->rows.begin(), pCur->row);
-  if (data_it >= pCur->rows.end()) {
-    return SQLITE_ERROR;
-  }
+       const BaseCursor* pCur = (BaseCursor*)cur;
+       auto data_it = std::next(pCur->rows.begin(), pCur->row);
+       if (data_it >= pCur->rows.end()) {
+               return SQLITE_ERROR;
+       }
 
-  // Use the rowid returned by the extension, if available; most likely, this
-  // will only be used by extensions providing read/write tables
-  const auto& current_row = *data_it;
-  return current_row->get_rowid(pCur->row, pRowid);
+       // Use the rowid returned by the extension, if available; most likely, this
+       // will only be used by extensions providing read/write tables
+       const auto& current_row = *data_it;
+       return current_row->get_rowid(pCur->row, pRowid);
 }
 
 int xUpdate(sqlite3_vtab* p,
-            int argc,
-            sqlite3_value** argv,
-            sqlite3_int64* pRowid) {
-  auto argument_count = static_cast<size_t>(argc);
-  auto* pVtab = (VirtualTable*)p;
+                       int argc,
+                       sqlite3_value** argv,
+                       sqlite3_int64* pRowid)
+{
+       auto argument_count = static_cast<size_t>(argc);
+       auto* pVtab = (VirtualTable*)p;
 
-  auto content = pVtab->content;
-  const auto& columnDescriptors = content->columns;
+       auto content = pVtab->content;
+       const auto& columnDescriptors = content->columns;
+
+       std::string table_name = pVtab->content->name;
+
+       // The SQLite instance communicates to the TablePlugin via the context.
+       QueryContext context(content);
+       PluginRequest plugin_request;
+
+       if (argument_count == 1U) {
+               // This is a simple delete operation
+               plugin_request = {{"action", "delete"}};
+
+               auto row_to_delete = sqlite3_value_int64(argv[0]);
+               plugin_request.insert({"id", std::to_string(row_to_delete)});
+
+               /// PATCH START //////////////////////////////////////////////////////////////
+               std::string json_values;
+               serializeDeleteParameters(json_values, reinterpret_cast<VirtualTable*>(p));
+               plugin_request.insert({"json_values", json_values});
+               /// PATCH END ////////////////////////////////////////////////////////////////
+       } else if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
+               // This is an INSERT query; if the rowid has been generated for us, we'll
+               // find it inside argv[1]
+               plugin_request = {{"action", "insert"}};
+
+               // Add the values to insert; we should have a value for each column present
+               // in the table, even if the user did not specify a value (in which case
+               // we will find a nullptr)
+               std::string json_values;
+               auto serializerError = serializeUpdateParameters(
+                                                                  json_values, argument_count, argv, columnDescriptors);
+               if (serializerError != SQLITE_OK) {
+                       DEBUG(OSQUERY) << "Failed to serialize the UPDATE request";
+                       return serializerError;
+               }
 
-  std::string table_name = pVtab->content->name;
+               plugin_request.insert({"json_values", json_values});
 
-  // The SQLite instance communicates to the TablePlugin via the context.
-  QueryContext context(content);
-  PluginRequest plugin_request;
+               if (sqlite3_value_type(argv[1]) != SQLITE_NULL) {
+                       plugin_request.insert({"auto_rowid", "true"});
 
-  if (argument_count == 1U) {
-    // This is a simple delete operation
-    plugin_request = {{"action", "delete"}};
+                       std::string auto_generated_rowid;
+                       if (!getColumnValue(auto_generated_rowid, 1U, argument_count, argv)) {
+                               DEBUG(OSQUERY) << "Failed to retrieve the column value";
+                               return SQLITE_ERROR;
+                       }
 
-    auto row_to_delete = sqlite3_value_int64(argv[0]);
-    plugin_request.insert({"id", std::to_string(row_to_delete)});
+                       plugin_request.insert({"id", auto_generated_rowid});
 
-/// PATCH START //////////////////////////////////////////////////////////////
-       std::string json_values;
-       serializeDeleteParameters(json_values, reinterpret_cast<VirtualTable*>(p));
-       plugin_request.insert({"json_values", json_values});
-/// PATCH END ////////////////////////////////////////////////////////////////
-  } else if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
-    // This is an INSERT query; if the rowid has been generated for us, we'll
-    // find it inside argv[1]
-    plugin_request = {{"action", "insert"}};
-
-    // Add the values to insert; we should have a value for each column present
-    // in the table, even if the user did not specify a value (in which case
-    // we will find a nullptr)
-       std::string json_values;
-       auto serializerError = serializeUpdateParameters(
-               json_values, argument_count, argv, columnDescriptors);
-       if (serializerError != SQLITE_OK) {
-               DEBUG(OSQUERY) << "Failed to serialize the UPDATE request";
-               return serializerError;
+               } else {
+                       plugin_request.insert({"auto_rowid", "false"});
+               }
+
+       } else if (sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
+               // This is an UPDATE query; we have to update the rowid value in some
+               // cases (if argv[1] is populated)
+               plugin_request = {{"action", "update"}};
+
+               std::string current_rowid;
+               if (!getColumnValue(current_rowid, 0U, argument_count, argv)) {
+                       DEBUG(OSQUERY) << "Failed to retrieve the column value";
+                       return SQLITE_ERROR;
+               }
+
+               plugin_request.insert({"id", current_rowid});
+
+               // Get the new rowid, if any
+               if (sqlite3_value_type(argv[1]) == SQLITE_INTEGER) {
+                       std::string new_rowid;
+                       if (!getColumnValue(new_rowid, 1U, argument_count, argv)) {
+                               DEBUG(OSQUERY) << "Failed to retrieve the column value";
+                               return SQLITE_ERROR;
+                       }
+
+                       if (new_rowid != plugin_request.at("id")) {
+                               plugin_request.insert({"new_id", new_rowid});
+                       }
+               }
+
+               // Get the values to update
+               std::string json_values;
+               auto serializerError = serializeUpdateParameters(
+                                                                  json_values, argument_count, argv, columnDescriptors);
+               if (serializerError != SQLITE_OK) {
+                       DEBUG(OSQUERY) << "Failed to serialize the UPDATE request";
+                       return serializerError;
+               }
+
+               plugin_request.insert({"json_values", json_values});
+
+       } else {
+               DEBUG(OSQUERY) << "Invalid xUpdate call";
+               return SQLITE_ERROR;
        }
 
-       plugin_request.insert({"json_values", json_values});
-
-    if (sqlite3_value_type(argv[1]) != SQLITE_NULL) {
-      plugin_request.insert({"auto_rowid", "true"});
-
-      std::string auto_generated_rowid;
-      if (!getColumnValue(auto_generated_rowid, 1U, argument_count, argv)) {
-        DEBUG(OSQUERY) << "Failed to retrieve the column value";
-        return SQLITE_ERROR;
-      }
-
-      plugin_request.insert({"id", auto_generated_rowid});
-
-    } else {
-      plugin_request.insert({"auto_rowid", "false"});
-    }
-
-  } else if (sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
-    // This is an UPDATE query; we have to update the rowid value in some
-    // cases (if argv[1] is populated)
-    plugin_request = {{"action", "update"}};
-
-    std::string current_rowid;
-    if (!getColumnValue(current_rowid, 0U, argument_count, argv)) {
-      DEBUG(OSQUERY) << "Failed to retrieve the column value";
-      return SQLITE_ERROR;
-    }
-
-    plugin_request.insert({"id", current_rowid});
-
-    // Get the new rowid, if any
-    if (sqlite3_value_type(argv[1]) == SQLITE_INTEGER) {
-      std::string new_rowid;
-      if (!getColumnValue(new_rowid, 1U, argument_count, argv)) {
-        DEBUG(OSQUERY) << "Failed to retrieve the column value";
-        return SQLITE_ERROR;
-      }
-
-      if (new_rowid != plugin_request.at("id")) {
-        plugin_request.insert({"new_id", new_rowid});
-      }
-    }
-
-    // Get the values to update
-       std::string json_values;
-       auto serializerError = serializeUpdateParameters(
-               json_values, argument_count, argv, columnDescriptors);
-       if (serializerError != SQLITE_OK) {
-               DEBUG(OSQUERY) << "Failed to serialize the UPDATE request";
-               return serializerError;
+       TablePlugin::setRequestFromContext(context, plugin_request);
+
+       // Forward the query to the table extension
+       PluginResponse response_list;
+       Registry::call("table", table_name, plugin_request, response_list);
+
+       // Validate the response
+       if (response_list.size() != 1) {
+               DEBUG(OSQUERY) << "Invalid response from the extension table";
+               return SQLITE_ERROR;
+       }
+
+       const auto& response = response_list.at(0);
+       if (response.count("status") == 0) {
+               DEBUG(OSQUERY) << "Invalid response from the extension table; the status field is "
+                                          "missing";
+
+               return SQLITE_ERROR;
+       }
+
+       const auto& status_value = response.at("status");
+       if (status_value == "readonly") {
+               auto error_message =
+                       "table " + pVtab->content->name + " may not be modified";
+
+               setTableErrorMessage(p, error_message);
+               return SQLITE_READONLY;
+
+       } else if (status_value == "failure") {
+               auto custom_error_message_it = response.find("message");
+               if (custom_error_message_it == response.end()) {
+                       return SQLITE_ERROR;
+               }
+
+               const auto& custom_error_message = custom_error_message_it->second;
+               setTableErrorMessage(p, custom_error_message);
+               return SQLITE_ERROR;
+
+       } else if (status_value == "constraint") {
+               return SQLITE_CONSTRAINT;
+
+       } else if (status_value != "success") {
+               DEBUG(OSQUERY) << "Invalid response from the extension table; the status field "
+                                          "could not be recognized";
+
+               return SQLITE_ERROR;
        }
 
-       plugin_request.insert({"json_values", json_values});
-
-  } else {
-    DEBUG(OSQUERY) << "Invalid xUpdate call";
-    return SQLITE_ERROR;
-  }
-
-  TablePlugin::setRequestFromContext(context, plugin_request);
-
-  // Forward the query to the table extension
-  PluginResponse response_list;
-  Registry::call("table", table_name, plugin_request, response_list);
-
-  // Validate the response
-  if (response_list.size() != 1) {
-    DEBUG(OSQUERY) << "Invalid response from the extension table";
-    return SQLITE_ERROR;
-  }
-
-  const auto& response = response_list.at(0);
-  if (response.count("status") == 0) {
-    DEBUG(OSQUERY) << "Invalid response from the extension table; the status field is "
-               "missing";
-
-    return SQLITE_ERROR;
-  }
-
-  const auto& status_value = response.at("status");
-  if (status_value == "readonly") {
-    auto error_message =
-        "table " + pVtab->content->name + " may not be modified";
-
-    setTableErrorMessage(p, error_message);
-    return SQLITE_READONLY;
-
-  } else if (status_value == "failure") {
-    auto custom_error_message_it = response.find("message");
-    if (custom_error_message_it == response.end()) {
-      return SQLITE_ERROR;
-    }
-
-    const auto& custom_error_message = custom_error_message_it->second;
-    setTableErrorMessage(p, custom_error_message);
-    return SQLITE_ERROR;
-
-  } else if (status_value == "constraint") {
-    return SQLITE_CONSTRAINT;
-
-  } else if (status_value != "success") {
-    DEBUG(OSQUERY) << "Invalid response from the extension table; the status field "
-               "could not be recognized";
-
-    return SQLITE_ERROR;
-  }
-
-/*
-  // INSERT actions must always return a valid rowid to sqlite
-  if (plugin_request.at("action") == "insert") {
-    std::string rowid;
-
-    if (plugin_request.at("auto_rowid") == "true") {
-      if (!getColumnValue(rowid, 1U, argument_count, argv)) {
-        DEBUG(OSQUERY) << "Failed to retrieve the rowid value";
-        return SQLITE_ERROR;
-      }
-
-    } else {
-      auto id_it = response.find("id");
-      if (id_it == response.end()) {
-        DEBUG(OSQUERY) << "The plugin did not return a row id";
-        return SQLITE_ERROR;
-      }
-
-      rowid = id_it->second;
-    }
-
-    auto exp = tryTo<long long>(rowid);
-    if (exp.isError()) {
-      DEBUG(OSQUERY) << "The plugin did not return a valid row id";
-      return SQLITE_ERROR;
-    }
-    *pRowid = exp.take();
-  }
-*/
-  return SQLITE_OK;
+       /*
+         // INSERT actions must always return a valid rowid to sqlite
+         if (plugin_request.at("action") == "insert") {
+           std::string rowid;
+
+           if (plugin_request.at("auto_rowid") == "true") {
+             if (!getColumnValue(rowid, 1U, argument_count, argv)) {
+               DEBUG(OSQUERY) << "Failed to retrieve the rowid value";
+               return SQLITE_ERROR;
+             }
+
+           } else {
+             auto id_it = response.find("id");
+             if (id_it == response.end()) {
+               DEBUG(OSQUERY) << "The plugin did not return a row id";
+               return SQLITE_ERROR;
+             }
+
+             rowid = id_it->second;
+           }
+
+           auto exp = tryTo<long long>(rowid);
+           if (exp.isError()) {
+             DEBUG(OSQUERY) << "The plugin did not return a valid row id";
+             return SQLITE_ERROR;
+           }
+           *pRowid = exp.take();
+         }
+       */
+       return SQLITE_OK;
 }
 
 int xCreate(sqlite3* db,
-            void* pAux,
-            int argc,
-            const char* const* argv,
-            sqlite3_vtab** ppVtab,
-            char** pzErr) {
-  auto* pVtab = new VirtualTable;
-  if (argc == 0 || argv[0] == nullptr) {
-    delete pVtab;
-    return SQLITE_NOMEM;
-  }
-
-  memset(pVtab, 0, sizeof(VirtualTable));
-  pVtab->content = std::make_shared<VirtualTableContent>();
-  pVtab->instance = (SQLiteDBInstance*)pAux;
-
-  // Create a TablePlugin Registry call, expect column details as the response.
-  PluginResponse response;
-  pVtab->content->name = std::string(argv[0]);
-  const auto& name = pVtab->content->name;
-
-  // Get the table column information.
-  auto status =
-      Registry::call("table", name, {{"action", "columns"}}, response);
-  if (!status.ok() || response.size() == 0) {
-    delete pVtab;
-    return SQLITE_ERROR;
-  }
-
-  bool is_extension = false;
-
-  // Generate an SQL create table statement from the retrieved column details.
-  // This call to columnDefinition requests column aliases (as HIDDEN columns).
-  auto statement =
-      "CREATE TABLE " + name + columnDefinition(response, true, is_extension);
-
-  int rc = sqlite3_declare_vtab(db, statement.c_str());
-  if (rc != SQLITE_OK || !status.ok() || response.size() == 0) {
-    ERROR(OSQUERY) << "Error creating virtual table: " << name << " (" << rc
-               << "): " << getStringForSQLiteReturnCode(rc);
-
-    DEBUG(OSQUERY) << "Cannot create virtual table using: " << statement;
-    delete pVtab;
-    return (rc != SQLITE_OK) ? rc : SQLITE_ERROR;
-  }
-
-  // Tables may request aliases as views.
-  std::set<std::string> views;
-
-  // Keep a local copy of the column details in the VirtualTableContent struct.
-  // This allows introspection into the column type without additional calls.
-  for (const auto& column : response) {
-    auto cid = column.find("id");
-    if (cid == column.end()) {
-      // This does not define a column type.
-      continue;
-    }
-
-    auto cname = column.find("name");
-    auto ctype = column.find("type");
-    if (cid->second == "column" && cname != column.end() &&
-        ctype != column.end()) {
-      // This is a malformed column definition.
-      // Populate the virtual table specific persistent column information.
-      auto options = ColumnOptions::DEFAULT;
-      auto cop = column.find("op");
-      if (cop != column.end()) {
-        auto op = tryTo<long>(cop->second);
-        if (op) {
-          options = static_cast<ColumnOptions>(op.take());
-        }
-      }
-
-      pVtab->content->columns.push_back(std::make_tuple(
-          cname->second, columnTypeName(ctype->second), options));
-    } else if (cid->second == "alias") {
-      // Create associated views for table aliases.
-      auto calias = column.find("alias");
-      if (calias != column.end()) {
-        views.insert(calias->second);
-      }
-    } else if (cid->second == "columnAlias" && cname != column.end()) {
-      auto ctarget = column.find("target");
-      if (ctarget == column.end()) {
-        continue;
-      }
-
-      // Record the column in the set of columns.
-      // This is required because SQLITE uses indexes to identify columns.
-      // Use an UNKNOWN_TYPE as a pseudo-mask, since the type does not matter.
-      pVtab->content->columns.push_back(
-          std::make_tuple(cname->second, UNKNOWN_TYPE, ColumnOptions::HIDDEN));
-      // Record a mapping of the requested column alias name.
-      size_t target_index = 0;
-      for (size_t i = 0; i < pVtab->content->columns.size(); i++) {
-        const auto& target_column = pVtab->content->columns[i];
-        if (std::get<0>(target_column) == ctarget->second) {
-          target_index = i;
-          break;
-        }
-      }
-      pVtab->content->aliases[cname->second] = target_index;
-    } else if (cid->second == "attributes") {
-      auto cattr = column.find("attributes");
-      // Store the attributes locally so they may be passed to the SQL object.
-      if (cattr != column.end()) {
-        auto attr = tryTo<long>(cattr->second);
-        if (attr) {
-          pVtab->content->attributes =
-              static_cast<TableAttributes>(attr.take());
-        }
-      }
-    }
-  }
-
-  // Create the requested 'aliases'.
-  for (const auto& view : views) {
-    statement = "CREATE VIEW " + view + " AS SELECT * FROM " + name;
-    sqlite3_exec(db, statement.c_str(), nullptr, nullptr, nullptr);
-  }
-
-  *ppVtab = (sqlite3_vtab*)pVtab;
-  return rc;
+                       void* pAux,
+                       int argc,
+                       const char* const* argv,
+                       sqlite3_vtab** ppVtab,
+                       char** pzErr)
+{
+       auto* pVtab = new VirtualTable;
+       if (argc == 0 || argv[0] == nullptr) {
+               delete pVtab;
+               return SQLITE_NOMEM;
+       }
+
+       memset(pVtab, 0, sizeof(VirtualTable));
+       pVtab->content = std::make_shared<VirtualTableContent>();
+       pVtab->instance = (SQLiteDBInstance*)pAux;
+
+       // Create a TablePlugin Registry call, expect column details as the response.
+       PluginResponse response;
+       pVtab->content->name = std::string(argv[0]);
+       const auto& name = pVtab->content->name;
+
+       // Get the table column information.
+       auto status =
+       Registry::call("table", name, {{"action", "columns"}}, response);
+       if (!status.ok() || response.size() == 0) {
+               delete pVtab;
+               return SQLITE_ERROR;
+       }
+
+       bool is_extension = false;
+
+       // Generate an SQL create table statement from the retrieved column details.
+       // This call to columnDefinition requests column aliases (as HIDDEN columns).
+       auto statement =
+               "CREATE TABLE " + name + columnDefinition(response, true, is_extension);
+
+       int rc = sqlite3_declare_vtab(db, statement.c_str());
+       if (rc != SQLITE_OK || !status.ok() || response.size() == 0) {
+               ERROR(OSQUERY) << "Error creating virtual table: " << name << " (" << rc
+                                          << "): " << getStringForSQLiteReturnCode(rc);
+
+               DEBUG(OSQUERY) << "Cannot create virtual table using: " << statement;
+               delete pVtab;
+               return (rc != SQLITE_OK) ? rc : SQLITE_ERROR;
+       }
+
+       // Tables may request aliases as views.
+       std::set<std::string> views;
+
+       // Keep a local copy of the column details in the VirtualTableContent struct.
+       // This allows introspection into the column type without additional calls.
+       for (const auto& column : response) {
+               auto cid = column.find("id");
+               if (cid == column.end()) {
+                       // This does not define a column type.
+                       continue;
+               }
+
+               auto cname = column.find("name");
+               auto ctype = column.find("type");
+               if (cid->second == "column" && cname != column.end() &&
+                       ctype != column.end()) {
+                       // This is a malformed column definition.
+                       // Populate the virtual table specific persistent column information.
+                       auto options = ColumnOptions::DEFAULT;
+                       auto cop = column.find("op");
+                       if (cop != column.end()) {
+                               auto op = tryTo<long>(cop->second);
+                               if (op) {
+                                       options = static_cast<ColumnOptions>(op.take());
+                               }
+                       }
+
+                       pVtab->content->columns.push_back(std::make_tuple(
+                                                                                                 cname->second, columnTypeName(ctype->second), options));
+               } else if (cid->second == "alias") {
+                       // Create associated views for table aliases.
+                       auto calias = column.find("alias");
+                       if (calias != column.end()) {
+                               views.insert(calias->second);
+                       }
+               } else if (cid->second == "columnAlias" && cname != column.end()) {
+                       auto ctarget = column.find("target");
+                       if (ctarget == column.end()) {
+                               continue;
+                       }
+
+                       // Record the column in the set of columns.
+                       // This is required because SQLITE uses indexes to identify columns.
+                       // Use an UNKNOWN_TYPE as a pseudo-mask, since the type does not matter.
+                       pVtab->content->columns.push_back(
+                               std::make_tuple(cname->second, UNKNOWN_TYPE, ColumnOptions::HIDDEN));
+                       // Record a mapping of the requested column alias name.
+                       size_t target_index = 0;
+                       for (size_t i = 0; i < pVtab->content->columns.size(); i++) {
+                               const auto& target_column = pVtab->content->columns[i];
+                               if (std::get<0>(target_column) == ctarget->second) {
+                                       target_index = i;
+                                       break;
+                               }
+                       }
+                       pVtab->content->aliases[cname->second] = target_index;
+               } else if (cid->second == "attributes") {
+                       auto cattr = column.find("attributes");
+                       // Store the attributes locally so they may be passed to the SQL object.
+                       if (cattr != column.end()) {
+                               auto attr = tryTo<long>(cattr->second);
+                               if (attr) {
+                                       pVtab->content->attributes =
+                                               static_cast<TableAttributes>(attr.take());
+                               }
+                       }
+               }
+       }
+
+       // Create the requested 'aliases'.
+       for (const auto& view : views) {
+               statement = "CREATE VIEW " + view + " AS SELECT * FROM " + name;
+               sqlite3_exec(db, statement.c_str(), nullptr, nullptr, nullptr);
+       }
+
+       *ppVtab = (sqlite3_vtab*)pVtab;
+       return rc;
 }
 
-int xColumn(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int col) {
-  BaseCursor* pCur = (BaseCursor*)cur;
-  const auto* pVtab = (VirtualTable*)cur->pVtab;
-  if (col >= static_cast<int>(pVtab->content->columns.size())) {
-    // Requested column index greater than column set size.
-    return SQLITE_ERROR;
-  }
+int xColumn(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int col)
+{
+       BaseCursor* pCur = (BaseCursor*)cur;
+       const auto* pVtab = (VirtualTable*)cur->pVtab;
+       if (col >= static_cast<int>(pVtab->content->columns.size())) {
+               // Requested column index greater than column set size.
+               return SQLITE_ERROR;
+       }
 
-  TableRowHolder& row = pCur->rows[pCur->row];
-  return row->get_column(ctx, cur->pVtab, col);
+       TableRowHolder& row = pCur->rows[pCur->row];
+       return row->get_column(ctx, cur->pVtab, col);
 }
 
-static inline bool sensibleComparison(ColumnType type, unsigned char op) {
-  if (type == TEXT_TYPE) {
-    if (op == GREATER_THAN || op == GREATER_THAN_OR_EQUALS || op == LESS_THAN ||
-        op == LESS_THAN_OR_EQUALS) {
-      return false;
-    }
-  }
-  return true;
+static inline bool sensibleComparison(ColumnType type, unsigned char op)
+{
+       if (type == TEXT_TYPE) {
+               if (op == GREATER_THAN || op == GREATER_THAN_OR_EQUALS || op == LESS_THAN ||
+                       op == LESS_THAN_OR_EQUALS) {
+                       return false;
+               }
+       }
+       return true;
 }
 
-static int xBestIndex(sqlite3_vtab* tab, sqlite3_index_info* pIdxInfo) {
-  auto* pVtab = (VirtualTable*)tab;
-  const auto& columns = pVtab->content->columns;
-
-  ConstraintSet constraints;
-  // Keep track of the index used for each valid constraint.
-  // Expect this index to correspond with argv within xFilter.
-  size_t expr_index = 0;
-  // If any constraints are unusable increment the cost of the index.
-  double cost = 1;
-
-  // Tables may have requirements or use indexes.
-  bool required_satisfied = false;
-  bool index_used = false;
-
-  // Expressions operating on the same virtual table are loosely identified by
-  // the consecutive sets of terms each of the constraint sets are applied onto.
-  // Subsequent attempts from failed (unusable) constraints replace the set,
-  // while new sets of terms append.
-  if (pIdxInfo->nConstraint > 0) {
-    for (size_t i = 0; i < static_cast<size_t>(pIdxInfo->nConstraint); ++i) {
-      // Record the term index (this index exists across all expressions).
-      const auto& constraint_info = pIdxInfo->aConstraint[i];
+static int xBestIndex(sqlite3_vtab* tab, sqlite3_index_info* pIdxInfo)
+{
+       auto* pVtab = (VirtualTable*)tab;
+       const auto& columns = pVtab->content->columns;
+
+       ConstraintSet constraints;
+       // Keep track of the index used for each valid constraint.
+       // Expect this index to correspond with argv within xFilter.
+       size_t expr_index = 0;
+       // If any constraints are unusable increment the cost of the index.
+       double cost = 1;
+
+       // Tables may have requirements or use indexes.
+       bool required_satisfied = false;
+       bool index_used = false;
+
+       // Expressions operating on the same virtual table are loosely identified by
+       // the consecutive sets of terms each of the constraint sets are applied onto.
+       // Subsequent attempts from failed (unusable) constraints replace the set,
+       // while new sets of terms append.
+       if (pIdxInfo->nConstraint > 0) {
+               for (size_t i = 0; i < static_cast<size_t>(pIdxInfo->nConstraint); ++i) {
+                       // Record the term index (this index exists across all expressions).
+                       const auto& constraint_info = pIdxInfo->aConstraint[i];
 #if defined(DEBUG)
-      plan("Evaluating constraints for table: " + pVtab->content->name +
-           " [index=" + std::to_string(i) +
-           " column=" + std::to_string(constraint_info.iColumn) +
-           " term=" + std::to_string((int)constraint_info.iTermOffset) +
-           " usable=" + std::to_string((int)constraint_info.usable) + "]");
+                       plan("Evaluating constraints for table: " + pVtab->content->name +
+                                " [index=" + std::to_string(i) +
+                                " column=" + std::to_string(constraint_info.iColumn) +
+                                " term=" + std::to_string((int)constraint_info.iTermOffset) +
+                                " usable=" + std::to_string((int)constraint_info.usable) + "]");
 #endif
-      if (!constraint_info.usable) {
-        // A higher cost less priority, prefer more usable query constraints.
-        cost += 10;
-        continue;
-      }
-
-      // Lookup the column name given an index into the table column set.
-      if (constraint_info.iColumn < 0 ||
-          static_cast<size_t>(constraint_info.iColumn) >=
-              pVtab->content->columns.size()) {
-        cost += 10;
-        continue;
-      }
-      const auto& name = std::get<0>(columns[constraint_info.iColumn]);
-      const auto& type = std::get<1>(columns[constraint_info.iColumn]);
-      if (!sensibleComparison(type, constraint_info.op)) {
-        cost += 10;
-        continue;
-      }
-
-      // Check if this constraint is on an index or required column.
-      const auto& options = std::get<2>(columns[constraint_info.iColumn]);
-      if (options & ColumnOptions::REQUIRED) {
-        index_used = true;
-        required_satisfied = true;
-      } else if (options & (ColumnOptions::INDEX | ColumnOptions::ADDITIONAL)) {
-        index_used = true;
-      }
-
-      // Save a pair of the name and the constraint operator.
-      // Use this constraint during xFilter by performing a scan and column
-      // name lookup through out all cursor constraint lists.
-      constraints.push_back(
-          std::make_pair(name, Constraint(constraint_info.op)));
-      pIdxInfo->aConstraintUsage[i].argvIndex = static_cast<int>(++expr_index);
+                       if (!constraint_info.usable) {
+                               // A higher cost less priority, prefer more usable query constraints.
+                               cost += 10;
+                               continue;
+                       }
+
+                       // Lookup the column name given an index into the table column set.
+                       if (constraint_info.iColumn < 0 ||
+                               static_cast<size_t>(constraint_info.iColumn) >=
+                               pVtab->content->columns.size()) {
+                               cost += 10;
+                               continue;
+                       }
+                       const auto& name = std::get<0>(columns[constraint_info.iColumn]);
+                       const auto& type = std::get<1>(columns[constraint_info.iColumn]);
+                       if (!sensibleComparison(type, constraint_info.op)) {
+                               cost += 10;
+                               continue;
+                       }
+
+                       // Check if this constraint is on an index or required column.
+                       const auto& options = std::get<2>(columns[constraint_info.iColumn]);
+                       if (options & ColumnOptions::REQUIRED) {
+                               index_used = true;
+                               required_satisfied = true;
+                       } else if (options & (ColumnOptions::INDEX | ColumnOptions::ADDITIONAL)) {
+                               index_used = true;
+                       }
+
+                       // Save a pair of the name and the constraint operator.
+                       // Use this constraint during xFilter by performing a scan and column
+                       // name lookup through out all cursor constraint lists.
+                       constraints.push_back(
+                               std::make_pair(name, Constraint(constraint_info.op)));
+                       pIdxInfo->aConstraintUsage[i].argvIndex = static_cast<int>(++expr_index);
 #if defined(DEBUG)
-      plan("Adding constraint for table: " + pVtab->content->name +
-           " [column=" + name + " arg_index=" + std::to_string(expr_index) +
-           " op=" + std::to_string(constraint_info.op) + "]");
+                       plan("Adding constraint for table: " + pVtab->content->name +
+                                " [column=" + name + " arg_index=" + std::to_string(expr_index) +
+                                " op=" + std::to_string(constraint_info.op) + "]");
 #endif
-    }
-  }
-
-  // Check the table for a required column.
-  for (const auto& column : columns) {
-    auto& options = std::get<2>(column);
-    if ((options & ColumnOptions::REQUIRED) && !required_satisfied) {
-      // A column is marked required, but no constraint satisfies.
-      return SQLITE_CONSTRAINT;
-    }
-  }
-
-  if (!index_used) {
-    // A column is marked index, but no index constraint was provided.
-    cost += 200;
-  }
-
-  UsedColumns colsUsed;
-  UsedColumnsBitset colsUsedBitset(pIdxInfo->colUsed);
-  if (colsUsedBitset.any()) {
-    for (size_t i = 0; i < columns.size(); i++) {
-      // Check whether the column is used. colUsed has one bit for each of the
-      // first 63 columns, and the 64th bit indicates that at least one other
-      // column is used.
-      auto bit = i < 63 ? i : 63U;
-      if (colsUsedBitset[bit]) {
-        auto column_name = std::get<0>(columns[i]);
-
-        if (pVtab->content->aliases.count(column_name)) {
-          colsUsedBitset.reset(bit);
-          auto real_column_index = pVtab->content->aliases[column_name];
-          bit = real_column_index < 63 ? real_column_index : 63U;
-          colsUsedBitset.set(bit);
-          column_name = std::get<0>(columns[real_column_index]);
-        }
-        colsUsed.insert(column_name);
-      }
-    }
-  }
-
-  pIdxInfo->idxNum = static_cast<int>(kConstraintIndexID++);
+               }
+       }
+
+       // Check the table for a required column.
+       for (const auto& column : columns) {
+               auto& options = std::get<2>(column);
+               if ((options & ColumnOptions::REQUIRED) && !required_satisfied) {
+                       // A column is marked required, but no constraint satisfies.
+                       return SQLITE_CONSTRAINT;
+               }
+       }
+
+       if (!index_used) {
+               // A column is marked index, but no index constraint was provided.
+               cost += 200;
+       }
+
+       UsedColumns colsUsed;
+       UsedColumnsBitset colsUsedBitset(pIdxInfo->colUsed);
+       if (colsUsedBitset.any()) {
+               for (size_t i = 0; i < columns.size(); i++) {
+                       // Check whether the column is used. colUsed has one bit for each of the
+                       // first 63 columns, and the 64th bit indicates that at least one other
+                       // column is used.
+                       auto bit = i < 63 ? i : 63U;
+                       if (colsUsedBitset[bit]) {
+                               auto column_name = std::get<0>(columns[i]);
+
+                               if (pVtab->content->aliases.count(column_name)) {
+                                       colsUsedBitset.reset(bit);
+                                       auto real_column_index = pVtab->content->aliases[column_name];
+                                       bit = real_column_index < 63 ? real_column_index : 63U;
+                                       colsUsedBitset.set(bit);
+                                       column_name = std::get<0>(columns[real_column_index]);
+                               }
+                               colsUsed.insert(column_name);
+                       }
+               }
+       }
+
+       pIdxInfo->idxNum = static_cast<int>(kConstraintIndexID++);
 #if defined(DEBUG)
-  plan("Recording constraint set for table: " + pVtab->content->name +
-       " [cost=" + std::to_string(cost) +
-       " size=" + std::to_string(constraints.size()) +
-       " idx=" + std::to_string(pIdxInfo->idxNum) + "]");
+       plan("Recording constraint set for table: " + pVtab->content->name +
+                " [cost=" + std::to_string(cost) +
+                " size=" + std::to_string(constraints.size()) +
+                " idx=" + std::to_string(pIdxInfo->idxNum) + "]");
 #endif
-  // Add the constraint set to the table's tracked constraints.
-  pVtab->content->constraints[pIdxInfo->idxNum] = std::move(constraints);
-  pVtab->content->colsUsed[pIdxInfo->idxNum] = std::move(colsUsed);
-  pVtab->content->colsUsedBitsets[pIdxInfo->idxNum] = colsUsedBitset;
-  pIdxInfo->estimatedCost = cost;
-  return SQLITE_OK;
+       // Add the constraint set to the table's tracked constraints.
+       pVtab->content->constraints[pIdxInfo->idxNum] = std::move(constraints);
+       pVtab->content->colsUsed[pIdxInfo->idxNum] = std::move(colsUsed);
+       pVtab->content->colsUsedBitsets[pIdxInfo->idxNum] = colsUsedBitset;
+       pIdxInfo->estimatedCost = cost;
+       return SQLITE_OK;
 }
 
 static int xFilter(sqlite3_vtab_cursor* pVtabCursor,
-                   int idxNum,
-                   const char* idxStr,
-                   int argc,
-                   sqlite3_value** argv) {
-  BaseCursor* pCur = (BaseCursor*)pVtabCursor;
-  auto* pVtab = (VirtualTable*)pVtabCursor->pVtab;
-  auto content = pVtab->content;
-  pVtab->instance->addAffectedTable(content);
-
-  pCur->row = 0;
-  pCur->n = 0;
-  QueryContext context(content);
-
-  // The SQLite instance communicates to the TablePlugin via the context.
-  context.useCache(pVtab->instance->useCache());
-
-  // Track required columns, this is different than the requirements check
-  // that occurs within BestIndex because this scan includes a cursor.
-  // For each cursor used, if a requirement exists, we need to scan the
-  // selected set of constraints for a match.
-  bool required_satisfied = true;
-
-  // The specialized table attribute USER_BASED imposes a special requirement
-  // for UID. This may be represented in the requirements, but otherwise
-  // would benefit from specific notification to the caller.
-  bool user_based_satisfied = !(
-      (content->attributes & TableAttributes::USER_BASED) > 0);
-
-  // For event-based tables, help the caller if events are disabled.
-  bool events_satisfied =
-      ((content->attributes & TableAttributes::EVENT_BASED) == 0);
-
-  std::map<std::string, ColumnOptions> options;
-  for (size_t i = 0; i < content->columns.size(); ++i) {
-    // Set the column affinity for each optional constraint list.
-    // There is a separate list for each column name.
-    auto column_name = std::get<0>(content->columns[i]);
-    context.constraints[column_name].affinity =
-        std::get<1>(content->columns[i]);
-    // Save the column options for comparison within constraints enumeration.
-    options[column_name] = std::get<2>(content->columns[i]);
-    if (options[column_name] & ColumnOptions::REQUIRED) {
-      required_satisfied = false;
-    }
-  }
-
-// Filtering between cursors happens iteratively, not consecutively.
-// If there are multiple sets of constraints, they apply to each cursor.
+                                  int idxNum,
+                                  const char* idxStr,
+                                  int argc,
+                                  sqlite3_value** argv)
+{
+       BaseCursor* pCur = (BaseCursor*)pVtabCursor;
+       auto* pVtab = (VirtualTable*)pVtabCursor->pVtab;
+       auto content = pVtab->content;
+       pVtab->instance->addAffectedTable(content);
+
+       pCur->row = 0;
+       pCur->n = 0;
+       QueryContext context(content);
+
+       // The SQLite instance communicates to the TablePlugin via the context.
+       context.useCache(pVtab->instance->useCache());
+
+       // Track required columns, this is different than the requirements check
+       // that occurs within BestIndex because this scan includes a cursor.
+       // For each cursor used, if a requirement exists, we need to scan the
+       // selected set of constraints for a match.
+       bool required_satisfied = true;
+
+       // The specialized table attribute USER_BASED imposes a special requirement
+       // for UID. This may be represented in the requirements, but otherwise
+       // would benefit from specific notification to the caller.
+       bool user_based_satisfied = !(
+                                                                       (content->attributes & TableAttributes::USER_BASED) > 0);
+
+       // For event-based tables, help the caller if events are disabled.
+       bool events_satisfied =
+               ((content->attributes & TableAttributes::EVENT_BASED) == 0);
+
+       std::map<std::string, ColumnOptions> options;
+       for (size_t i = 0; i < content->columns.size(); ++i) {
+               // Set the column affinity for each optional constraint list.
+               // There is a separate list for each column name.
+               auto column_name = std::get<0>(content->columns[i]);
+               context.constraints[column_name].affinity =
+                       std::get<1>(content->columns[i]);
+               // Save the column options for comparison within constraints enumeration.
+               options[column_name] = std::get<2>(content->columns[i]);
+               if (options[column_name] & ColumnOptions::REQUIRED) {
+                       required_satisfied = false;
+               }
+       }
+
+       // Filtering between cursors happens iteratively, not consecutively.
+       // If there are multiple sets of constraints, they apply to each cursor.
 #if defined(DEBUG)
-  plan("Filtering called for table: " + content->name +
-       " [constraint_count=" + std::to_string(content->constraints.size()) +
-       " argc=" + std::to_string(argc) + " idx=" + std::to_string(idxNum) +
-       "]");
+       plan("Filtering called for table: " + content->name +
+                " [constraint_count=" + std::to_string(content->constraints.size()) +
+                " argc=" + std::to_string(argc) + " idx=" + std::to_string(idxNum) +
+                "]");
 #endif
 
-  // Iterate over every argument to xFilter, filling in constraint values.
-  if (content->constraints.size() > 0) {
-    auto& constraints = content->constraints[idxNum];
-    if (argc > 0) {
-      for (size_t i = 0; i < static_cast<size_t>(argc); ++i) {
-        auto expr = (const char*)sqlite3_value_text(argv[i]);
-        if (expr == nullptr || expr[0] == 0) {
-          // SQLite did not expose the expression value.
-          continue;
-        }
-        // Set the expression from SQLite's now-populated argv.
-        auto& constraint = constraints[i];
-        constraint.second.expr = std::string(expr);
-        plan("Adding constraint to cursor (" + std::to_string(pCur->id) +
-             "): " + constraint.first + " " + opString(constraint.second.op) +
-             " " + constraint.second.expr);
-        // Add the constraint to the column-sorted query request map.
-        context.constraints[constraint.first].add(constraint.second);
-      }
-    } else if (constraints.size() > 0) {
-      // Constraints failed.
-    }
-
-    // Evaluate index and optimized constraint requirements.
-    // These are satisfied regardless of expression content availability.
-    for (const auto& constraint : constraints) {
-      if (options[constraint.first] & ColumnOptions::REQUIRED) {
-        // A required option exists in the constraints.
-        required_satisfied = true;
-      }
-
-      if (!user_based_satisfied &&
-          (constraint.first == "uid" || constraint.first == "username")) {
-        // UID was required and exists in the constraints.
-        user_based_satisfied = true;
-      }
-    }
-  }
-
-  if (!content->colsUsedBitsets.empty()) {
-    context.colsUsedBitset = content->colsUsedBitsets[idxNum];
-  } else {
-    // Unspecified; have to assume all columns are used
-    context.colsUsedBitset->set();
-  }
-  if (content->colsUsed.size() > 0) {
-    context.colsUsed = content->colsUsed[idxNum];
-  }
-
-  if (!user_based_satisfied) {
-    WARN(OSQUERY) << "The " << pVtab->content->name
-                 << " table returns data based on the current user by default, "
-                    "consider JOINing against the users table";
-  } else if (!required_satisfied) {
-    WARN(OSQUERY)
-        << "Table " << pVtab->content->name
-        << " was queried without a required column in the WHERE clause";
-  } else if (!events_satisfied) {
-    WARN(OSQUERY) << "Table " << pVtab->content->name
-                 << " is event-based but events are disabled";
-  }
-
-  // Reset the virtual table contents.
-  pCur->rows.clear();
-  options.clear();
-
-  // Generate the row data set.
-  plan("Scanning rows for cursor (" + std::to_string(pCur->id) + ")");
-  if (Registry::get().exists("table", pVtab->content->name, true)) {
-    auto plugin = Registry::get().plugin("table", pVtab->content->name);
-    auto table = std::dynamic_pointer_cast<TablePlugin>(plugin);
-    pCur->rows = table->generate(context);
-  } else {
-    PluginRequest request = {{"action", "generate"}};
-    TablePlugin::setRequestFromContext(context, request);
-    QueryData qd;
-    Registry::call("table", pVtab->content->name, request, qd);
-    pCur->rows = tableRowsFromQueryData(std::move(qd));
-  }
-
-  // Set the number of rows.
-  pCur->n = pCur->rows.size();
-  return SQLITE_OK;
+       // Iterate over every argument to xFilter, filling in constraint values.
+       if (content->constraints.size() > 0) {
+               auto& constraints = content->constraints[idxNum];
+               if (argc > 0) {
+                       for (size_t i = 0; i < static_cast<size_t>(argc); ++i) {
+                               auto expr = (const char*)sqlite3_value_text(argv[i]);
+                               if (expr == nullptr || expr[0] == 0) {
+                                       // SQLite did not expose the expression value.
+                                       continue;
+                               }
+                               // Set the expression from SQLite's now-populated argv.
+                               auto& constraint = constraints[i];
+                               constraint.second.expr = std::string(expr);
+                               plan("Adding constraint to cursor (" + std::to_string(pCur->id) +
+                                        "): " + constraint.first + " " + opString(constraint.second.op) +
+                                        " " + constraint.second.expr);
+                               // Add the constraint to the column-sorted query request map.
+                               context.constraints[constraint.first].add(constraint.second);
+                       }
+               } else if (constraints.size() > 0) {
+                       // Constraints failed.
+               }
+
+               // Evaluate index and optimized constraint requirements.
+               // These are satisfied regardless of expression content availability.
+               for (const auto& constraint : constraints) {
+                       if (options[constraint.first] & ColumnOptions::REQUIRED) {
+                               // A required option exists in the constraints.
+                               required_satisfied = true;
+                       }
+
+                       if (!user_based_satisfied &&
+                               (constraint.first == "uid" || constraint.first == "username")) {
+                               // UID was required and exists in the constraints.
+                               user_based_satisfied = true;
+                       }
+               }
+       }
+
+       if (!content->colsUsedBitsets.empty()) {
+               context.colsUsedBitset = content->colsUsedBitsets[idxNum];
+       } else {
+               // Unspecified; have to assume all columns are used
+               context.colsUsedBitset->set();
+       }
+       if (content->colsUsed.size() > 0) {
+               context.colsUsed = content->colsUsed[idxNum];
+       }
+
+       if (!user_based_satisfied) {
+               WARN(OSQUERY) << "The " << pVtab->content->name
+                                         << " table returns data based on the current user by default, "
+                                         "consider JOINing against the users table";
+       } else if (!required_satisfied) {
+               WARN(OSQUERY)
+                               << "Table " << pVtab->content->name
+                               << " was queried without a required column in the WHERE clause";
+       } else if (!events_satisfied) {
+               WARN(OSQUERY) << "Table " << pVtab->content->name
+                                         << " is event-based but events are disabled";
+       }
+
+       // Reset the virtual table contents.
+       pCur->rows.clear();
+       options.clear();
+
+       // Generate the row data set.
+       plan("Scanning rows for cursor (" + std::to_string(pCur->id) + ")");
+       if (Registry::get().exists("table", pVtab->content->name, true)) {
+               auto plugin = Registry::get().plugin("table", pVtab->content->name);
+               auto table = std::dynamic_pointer_cast<TablePlugin>(plugin);
+               pCur->rows = table->generate(context);
+       } else {
+               PluginRequest request = {{"action", "generate"}};
+               TablePlugin::setRequestFromContext(context, request);
+               QueryData qd;
+               Registry::call("table", pVtab->content->name, request, qd);
+               pCur->rows = tableRowsFromQueryData(std::move(qd));
+       }
+
+       // Set the number of rows.
+       pCur->n = pCur->rows.size();
+       return SQLITE_OK;
 }
 
 struct sqlite3_module* getVirtualTableModule(const std::string& table_name,
-                                             bool extension) {
-// FIXME
-//  UpgradeLock lock(sqlite_module_map_mutex);
-
-  if (sqlite_module_map.find(table_name) != sqlite_module_map.end()) {
-    return &sqlite_module_map[table_name];
-  }
-
-//  WriteUpgradeLock wlock(lock);
-
-  sqlite_module_map[table_name] = {};
-  sqlite_module_map[table_name].xCreate = tables::sqlite::xCreate;
-  sqlite_module_map[table_name].xConnect = tables::sqlite::xCreate;
-  sqlite_module_map[table_name].xBestIndex = tables::sqlite::xBestIndex;
-  sqlite_module_map[table_name].xDisconnect = tables::sqlite::xDestroy;
-  sqlite_module_map[table_name].xDestroy = tables::sqlite::xDestroy;
-  sqlite_module_map[table_name].xOpen = tables::sqlite::xOpen;
-  sqlite_module_map[table_name].xClose = tables::sqlite::xClose;
-  sqlite_module_map[table_name].xFilter = tables::sqlite::xFilter;
-  sqlite_module_map[table_name].xNext = tables::sqlite::xNext;
-  sqlite_module_map[table_name].xEof = tables::sqlite::xEof;
-  sqlite_module_map[table_name].xColumn = tables::sqlite::xColumn;
-  sqlite_module_map[table_name].xRowid = tables::sqlite::xRowid;
-  sqlite_module_map[table_name].xUpdate = tables::sqlite::xUpdate;
-
-  // Allow the table to receive INSERT/UPDATE/DROP events if it is
-  // implemented from an extension and is overwriting the right methods
-  // in the TablePlugin class
-
-  return &sqlite_module_map[table_name];
+                                                                                        bool extension)
+{
+       // FIXME
+       //  UpgradeLock lock(sqlite_module_map_mutex);
+
+       if (sqlite_module_map.find(table_name) != sqlite_module_map.end()) {
+               return &sqlite_module_map[table_name];
+       }
+
+       //  WriteUpgradeLock wlock(lock);
+
+       sqlite_module_map[table_name] = {};
+       sqlite_module_map[table_name].xCreate = tables::sqlite::xCreate;
+       sqlite_module_map[table_name].xConnect = tables::sqlite::xCreate;
+       sqlite_module_map[table_name].xBestIndex = tables::sqlite::xBestIndex;
+       sqlite_module_map[table_name].xDisconnect = tables::sqlite::xDestroy;
+       sqlite_module_map[table_name].xDestroy = tables::sqlite::xDestroy;
+       sqlite_module_map[table_name].xOpen = tables::sqlite::xOpen;
+       sqlite_module_map[table_name].xClose = tables::sqlite::xClose;
+       sqlite_module_map[table_name].xFilter = tables::sqlite::xFilter;
+       sqlite_module_map[table_name].xNext = tables::sqlite::xNext;
+       sqlite_module_map[table_name].xEof = tables::sqlite::xEof;
+       sqlite_module_map[table_name].xColumn = tables::sqlite::xColumn;
+       sqlite_module_map[table_name].xRowid = tables::sqlite::xRowid;
+       sqlite_module_map[table_name].xUpdate = tables::sqlite::xUpdate;
+
+       // Allow the table to receive INSERT/UPDATE/DROP events if it is
+       // implemented from an extension and is overwriting the right methods
+       // in the TablePlugin class
+
+       return &sqlite_module_map[table_name];
 }
 } // namespace sqlite
 } // namespace tables
 
 Status attachTableInternal(const std::string& name,
-                           const std::string& statement,
-                           const SQLiteDBInstanceRef& instance,
-                           bool is_extension) {
-  if (SQLiteDBManager::isDisabled(name)) {
-    DEBUG(OSQUERY) << "Table " << name << " is disabled, not attaching";
-    return Status(0, getStringForSQLiteReturnCode(0));
-  }
-
-  struct sqlite3_module* module =
-      tables::sqlite::getVirtualTableModule(name, is_extension);
-  if (module == nullptr) {
-    DEBUG(OSQUERY) << "Failed to retrieve the virtual table module for \"" << name
-            << "\"";
-    return Status(1);
-  }
-
-  // Note, if the clientData API is used then this will save a registry call
-  // within xCreate.
-  auto lock(instance->attachLock());
-
-  int rc = sqlite3_create_module(
-      instance->db(), name.c_str(), module, (void*)&(*instance));
-
-  if (rc == SQLITE_OK || rc == SQLITE_MISUSE) {
-    auto format =
-        "CREATE VIRTUAL TABLE temp." + name + " USING " + name + statement;
-
-    rc =
-        sqlite3_exec(instance->db(), format.c_str(), nullptr, nullptr, nullptr);
-
-  } else {
-    ERROR(OSQUERY) << "Error attaching table: " << name << " (" << rc << ")";
-  }
-
-  return Status(rc, getStringForSQLiteReturnCode(rc));
+                                                  const std::string& statement,
+                                                  const SQLiteDBInstanceRef& instance,
+                                                  bool is_extension)
+{
+       if (SQLiteDBManager::isDisabled(name)) {
+               DEBUG(OSQUERY) << "Table " << name << " is disabled, not attaching";
+               return Status(0, getStringForSQLiteReturnCode(0));
+       }
+
+       struct sqlite3_module* module =
+               tables::sqlite::getVirtualTableModule(name, is_extension);
+       if (module == nullptr) {
+               DEBUG(OSQUERY) << "Failed to retrieve the virtual table module for \"" << name
+                                          << "\"";
+               return Status(1);
+       }
+
+       // Note, if the clientData API is used then this will save a registry call
+       // within xCreate.
+       auto lock(instance->attachLock());
+
+       int rc = sqlite3_create_module(
+                                instance->db(), name.c_str(), module, (void*) & (*instance));
+
+       if (rc == SQLITE_OK || rc == SQLITE_MISUSE) {
+               auto format =
+                       "CREATE VIRTUAL TABLE temp." + name + " USING " + name + statement;
+
+               rc =
+                       sqlite3_exec(instance->db(), format.c_str(), nullptr, nullptr, nullptr);
+
+       } else {
+               ERROR(OSQUERY) << "Error attaching table: " << name << " (" << rc << ")";
+       }
+
+       return Status(rc, getStringForSQLiteReturnCode(rc));
 }
 
 Status detachTableInternal(const std::string& name,
-                           const SQLiteDBInstanceRef& instance) {
-  auto lock(instance->attachLock());
-  auto format = "DROP TABLE IF EXISTS temp." + name;
-  int rc = sqlite3_exec(instance->db(), format.c_str(), nullptr, nullptr, 0);
-  if (rc != SQLITE_OK) {
-    ERROR(OSQUERY) << "Error detaching table: " << name << " (" << rc << ")";
-  }
-
-  return Status(rc, getStringForSQLiteReturnCode(rc));
+                                                  const SQLiteDBInstanceRef& instance)
+{
+       auto lock(instance->attachLock());
+       auto format = "DROP TABLE IF EXISTS temp." + name;
+       int rc = sqlite3_exec(instance->db(), format.c_str(), nullptr, nullptr, 0);
+       if (rc != SQLITE_OK) {
+               ERROR(OSQUERY) << "Error detaching table: " << name << " (" << rc << ")";
+       }
+
+       return Status(rc, getStringForSQLiteReturnCode(rc));
 }
 
 Status attachFunctionInternal(
-    const std::string& name,
-    std::function<
-        void(sqlite3_context* context, int argc, sqlite3_value** argv)> func) {
-  // Hold the manager connection instance again in callbacks.
-  auto dbc = SQLiteDBManager::get();
-  // Add some shell-specific functions to the instance.
-  auto lock(dbc->attachLock());
-  int rc = sqlite3_create_function(
-      dbc->db(),
-      name.c_str(),
-      0,
-      SQLITE_UTF8,
-      nullptr,
-      *func.target<void (*)(sqlite3_context*, int, sqlite3_value**)>(),
-      nullptr,
-      nullptr);
-  return Status(rc);
+       const std::string& name,
+       std::function <
+       void(sqlite3_context* context, int argc, sqlite3_value** argv) > func)
+{
+       // Hold the manager connection instance again in callbacks.
+       auto dbc = SQLiteDBManager::get();
+       // Add some shell-specific functions to the instance.
+       auto lock(dbc->attachLock());
+       int rc = sqlite3_create_function(
+                                dbc->db(),
+                                name.c_str(),
+                                0,
+                                SQLITE_UTF8,
+                                nullptr,
+                                *func.target<void (*)(sqlite3_context*, int, sqlite3_value**)>(),
+                                nullptr,
+                                nullptr);
+       return Status(rc);
 }
 
-void attachVirtualTables(const SQLiteDBInstanceRef& instance) {
-  PluginResponse response;
-  bool is_extension = false;
-
-  for (const auto& name : RegistryFactory::get().names("table")) {
-    // Column information is nice for virtual table create call.
-    auto status =
-        Registry::call("table", name, {{"action", "columns"}}, response);
-    if (status.ok()) {
-      auto statement = columnDefinition(response, true, is_extension);
-      attachTableInternal(name, statement, instance, is_extension);
-    }
-  }
+void attachVirtualTables(const SQLiteDBInstanceRef& instance)
+{
+       PluginResponse response;
+       bool is_extension = false;
+
+       for (const auto& name : RegistryFactory::get().names("table")) {
+               // Column information is nice for virtual table create call.
+               auto status =
+               Registry::call("table", name, {{"action", "columns"}}, response);
+               if (status.ok()) {
+                       auto statement = columnDefinition(response, true, is_extension);
+                       attachTableInternal(name, statement, instance, is_extension);
+               }
+       }
 }
 } // namespace osquery
index b9636c8e2d5b28a3a04e4eab1f2526a5f630f1fd..af09402aafc6046e814f909278df7726b61cdb18 100644 (file)
@@ -33,24 +33,24 @@ extern RecursiveMutex kAttachMutex;
  * Only used in the SQLite virtual table module methods.
  */
 struct BaseCursor : private boost::noncopyable {
- public:
-  /// SQLite virtual table cursor.
-  sqlite3_vtab_cursor base;
+public:
+       /// SQLite virtual table cursor.
+       sqlite3_vtab_cursor base;
 
-  /// Track cursors for optional planner output.
-  size_t id{0};
+       /// Track cursors for optional planner output.
+       size_t id{0};
 
-  /// Table data generated from last access.
-  TableRows rows;
+       /// Table data generated from last access.
+       TableRows rows;
 
-  /// Results of current call.
-  TableRowHolder current;
+       /// Results of current call.
+       TableRowHolder current;
 
-  /// Current cursor position.
-  size_t row{0};
+       /// Current cursor position.
+       size_t row{0};
 
-  /// Total number of rows.
-  size_t n{0};
+       /// Total number of rows.
+       size_t n{0};
 };
 
 /**
@@ -60,30 +60,30 @@ struct BaseCursor : private boost::noncopyable {
  * This adds each table plugin class to the state tracking in SQLite.
  */
 struct VirtualTable : private boost::noncopyable {
-  /// The SQLite-provided virtual table structure.
-  sqlite3_vtab base;
+       /// The SQLite-provided virtual table structure.
+       sqlite3_vtab base;
 
-  /// Added structure: A content structure with metadata about the table.
-  std::shared_ptr<VirtualTableContent> content;
+       /// Added structure: A content structure with metadata about the table.
+       std::shared_ptr<VirtualTableContent> content;
 
-  /// Added structure: The thread-local DB instance associated with the query.
-  SQLiteDBInstance* instance{nullptr};
+       /// Added structure: The thread-local DB instance associated with the query.
+       SQLiteDBInstance* instance{nullptr};
 };
 
 /// Attach a table plugin name to an in-memory SQLite database.
 Status attachTableInternal(const std::string& name,
-                           const std::string& statement,
-                           const SQLiteDBInstanceRef& instance,
-                           bool is_extension);
+                                                  const std::string& statement,
+                                                  const SQLiteDBInstanceRef& instance,
+                                                  bool is_extension);
 
 /// Detach (drop) a table.
 Status detachTableInternal(const std::string& name,
-                           const SQLiteDBInstanceRef& instance);
+                                                  const SQLiteDBInstanceRef& instance);
 
 Status attachFunctionInternal(
-    const std::string& name,
-    std::function<
-        void(sqlite3_context* context, int argc, sqlite3_value** argv)> func);
+       const std::string& name,
+       std::function <
+       void(sqlite3_context* context, int argc, sqlite3_value** argv) > func);
 
 /// Attach all table plugins to an in-memory SQLite database.
 void attachVirtualTables(const SQLiteDBInstanceRef& instance);
index ac2cde2bdbc42869d397afbe51e1af2a4c375281..b5e3154e87f72da7228b49b1a902e34aa8ee05ff 100644 (file)
@@ -30,39 +30,41 @@ typedef bai::base64_from_binary<base64_enc> it_base64;
 
 } // namespace
 
-std::string decode(std::string encoded) {
-  boost::erase_all(encoded, "\r\n");
-  boost::erase_all(encoded, "\n");
-  boost::trim_right_if(encoded, boost::is_any_of("="));
+std::string decode(std::string encoded)
+{
+       boost::erase_all(encoded, "\r\n");
+       boost::erase_all(encoded, "\n");
+       boost::trim_right_if(encoded, boost::is_any_of("="));
 
-  if (encoded.empty()) {
-    return encoded;
-  }
+       if (encoded.empty()) {
+               return encoded;
+       }
 
-  try {
-    return std::string(base64_dec(encoded.data()),
-                       base64_dec(encoded.data() + encoded.size()));
-  } catch (const boost::archive::iterators::dataflow_exception& e) {
-    INFO(OSQUERY) << "Could not base64 decode string: " << e.what();
-    return "";
-  }
+       try {
+               return std::string(base64_dec(encoded.data()),
+                                                  base64_dec(encoded.data() + encoded.size()));
+       } catch (const boost::archive::iterators::dataflow_exception& e) {
+               INFO(OSQUERY) << "Could not base64 decode string: " << e.what();
+               return "";
+       }
 }
 
-std::string encode(const std::string& unencoded) {
-  if (unencoded.empty()) {
-    return unencoded;
-  }
+std::string encode(const std::string& unencoded)
+{
+       if (unencoded.empty()) {
+               return unencoded;
+       }
 
-  size_t writePaddChars = (3U - unencoded.length() % 3U) % 3U;
-  try {
-    auto encoded =
-        std::string(it_base64(unencoded.begin()), it_base64(unencoded.end()));
-    encoded.append(std::string(writePaddChars, '='));
-    return encoded;
-  } catch (const boost::archive::iterators::dataflow_exception& e) {
-    INFO(OSQUERY) << "Could not base64 decode string: " << e.what();
-    return "";
-  }
+       size_t writePaddChars = (3U - unencoded.length() % 3U) % 3U;
+       try {
+               auto encoded =
+                       std::string(it_base64(unencoded.begin()), it_base64(unencoded.end()));
+               encoded.append(std::string(writePaddChars, '='));
+               return encoded;
+       } catch (const boost::archive::iterators::dataflow_exception& e) {
+               INFO(OSQUERY) << "Could not base64 decode string: " << e.what();
+               return "";
+       }
 }
 
 } // namespace base64
index be53fe9c97720d46d0dbba749a5b43f27f8f2322..85d2fda185c2cbfc8a7b9bf4e89a797d97d1a7e0 100644 (file)
 
 namespace osquery {
 
-bool isPrintable(const std::string& check) {
-  for (const unsigned char ch : check) {
-    if (ch >= 0x7F || ch <= 0x1F) {
-      return false;
-    }
-  }
-  return true;
+bool isPrintable(const std::string& check)
+{
+       for (const unsigned char ch : check) {
+               if (ch >= 0x7F || ch <= 0x1F) {
+                       return false;
+               }
+       }
+       return true;
 }
 
-size_t utf8StringSize(const std::string& str) {
-  size_t res = 0;
-  std::string::const_iterator it = str.begin();
-  for (; it != str.end(); incUtf8StringIterator(it, str.end())) {
-    res++;
-  }
+size_t utf8StringSize(const std::string& str)
+{
+       size_t res = 0;
+       std::string::const_iterator it = str.begin();
+       for (; it != str.end(); incUtf8StringIterator(it, str.end())) {
+               res++;
+       }
 
-  return res;
+       return res;
 }
 
-std::string unescapeUnicode(const std::string& escaped) {
-  if (escaped.size() < 6) {
-    return escaped;
-  }
+std::string unescapeUnicode(const std::string& escaped)
+{
+       if (escaped.size() < 6) {
+               return escaped;
+       }
 
-  std::string unescaped;
-  unescaped.reserve(escaped.size());
-  for (size_t i = 0; i < escaped.size(); ++i) {
-    if (i < escaped.size() - 5 && '\\' == escaped[i] && 'u' == escaped[i + 1]) {
-      // Assume 2-byte wide unicode.
-      auto const exp = tryTo<long>(escaped.substr(i + 2, 4), 16);
-      if (exp.isError()) {
-        WARN(OSQUERY) << "Unescaping a string with length: " << escaped.size()
-                     << " failed at: " << i;
-        return "";
-      }
-      long const value = exp.get();
-      if (value < 255) {
-        unescaped += static_cast<char>(value);
-        i += 5;
-        continue;
-      }
-    } else if (i < escaped.size() - 1 && '\\' == escaped[i] &&
-               '\\' == escaped[i + 1]) {
-      // In the case of \\users 'sers' is not a unicode character
-      // If we see \\ we should skip them and we do this by adding
-      // an extra jump forward.
-      unescaped += escaped[i];
-      ++i;
-    }
-    unescaped += escaped[i];
-  }
-  return unescaped;
+       std::string unescaped;
+       unescaped.reserve(escaped.size());
+       for (size_t i = 0; i < escaped.size(); ++i) {
+               if (i < escaped.size() - 5 && '\\' == escaped[i] && 'u' == escaped[i + 1]) {
+                       // Assume 2-byte wide unicode.
+                       auto const exp = tryTo<long>(escaped.substr(i + 2, 4), 16);
+                       if (exp.isError()) {
+                               WARN(OSQUERY) << "Unescaping a string with length: " << escaped.size()
+                                                         << " failed at: " << i;
+                               return "";
+                       }
+                       long const value = exp.get();
+                       if (value < 255) {
+                               unescaped += static_cast<char>(value);
+                               i += 5;
+                               continue;
+                       }
+               } else if (i < escaped.size() - 1 && '\\' == escaped[i] &&
+                                  '\\' == escaped[i + 1]) {
+                       // In the case of \\users 'sers' is not a unicode character
+                       // If we see \\ we should skip them and we do this by adding
+                       // an extra jump forward.
+                       unescaped += escaped[i];
+                       ++i;
+               }
+               unescaped += escaped[i];
+       }
+       return unescaped;
 }
 
 } // namespace osquery
index af9437eaae83b209e35bb062398420b34d481ca9..0df44335c0808b984be06d63529fc37345a90e3f 100644 (file)
@@ -24,20 +24,21 @@ bool isPrintable(const std::string& check);
  * @brief In-line helper function for use with utf8StringSize
  */
 template <typename _Iterator1, typename _Iterator2>
-size_t incUtf8StringIterator(_Iterator1& it, const _Iterator2& last) {
-  if (it == last) {
-    return 0;
-  }
-
-  size_t res = 1;
-  for (++it; last != it; ++it, ++res) {
-    unsigned char c = *it;
-    if (!(c & 0x80) || ((c & 0xC0) == 0xC0)) {
-      break;
-    }
-  }
-
-  return res;
+size_t incUtf8StringIterator(_Iterator1& it, const _Iterator2& last)
+{
+       if (it == last) {
+               return 0;
+       }
+
+       size_t res = 1;
+       for (++it; last != it; ++it, ++res) {
+               unsigned char c = *it;
+               if (!(c & 0x80) || ((c & 0xC0) == 0xC0)) {
+                       break;
+               }
+       }
+
+       return res;
 }
 
 /**
index 9960dbeb3b9f715577fc0556989936de46cd8993..2f660f7f4388ac33ba39c13259c3e1238d503088 100644 (file)
@@ -16,27 +16,31 @@ namespace osquery {
 /* We do this so that we get '0.0' from double 0.0 instead of '0'
  */
 class CastVisitor : public boost::static_visitor<std::string> {
- public:
-  std::string operator()(const long long& i) const {
-    return std::to_string(i);
-  }
+public:
+       std::string operator()(const long long& i) const
+       {
+               return std::to_string(i);
+       }
 
-  std::string operator()(const double& d) const {
-    std::string s{boost::lexical_cast<std::string>(d)};
-    if (s.find('.') == std::string::npos) {
-      s += ".0";
-    }
-    return s;
-  }
+       std::string operator()(const double& d) const
+       {
+               std::string s{boost::lexical_cast<std::string>(d)};
+               if (s.find('.') == std::string::npos) {
+                       s += ".0";
+               }
+               return s;
+       }
 
-  std::string operator()(const std::string& str) const {
-    return str;
-  }
+       std::string operator()(const std::string& str) const
+       {
+               return str;
+       }
 };
 
 inline std::string castVariant(
-    const boost::variant<long long, double, std::string>& var) {
-  static const CastVisitor visitor;
-  return boost::apply_visitor(visitor, var);
+       const boost::variant<long long, double, std::string>& var)
+{
+       static const CastVisitor visitor;
+       return boost::apply_visitor(visitor, var);
 }
 } // namespace osquery
index 57a6b3fcc28518e75f62623e7905f62b00dc6307..7e7361318d893b3f40b903ce008eb8a511b0b68c 100644 (file)
@@ -23,8 +23,9 @@ namespace osquery {
  * @return the joined string.
  */
 template <typename SequenceType>
-inline std::string join(const SequenceType& s, const std::string& tok) {
-  return boost::algorithm::join(s, tok);
+inline std::string join(const SequenceType& s, const std::string& tok)
+{
+       return boost::algorithm::join(s, tok);
 }
 
 } // namespace osquery
index c5a01525615fe9a67c105943440db686d26797bf..153c807e543699ab49b9ec28be45db76acfc4ba2 100644 (file)
 
 namespace osquery {
 
-std::vector<std::string> split(const std::string& s, const std::string& delim) {
-  std::vector<std::string> elems;
-  boost::split(elems, s, boost::is_any_of(delim));
-  auto start =
-      std::remove_if(elems.begin(), elems.end(), [](const std::string& t) {
-        return t.size() == 0;
-      });
-  elems.erase(start, elems.end());
-  for (auto& each : elems) {
-    boost::algorithm::trim(each);
-  }
-  return elems;
+std::vector<std::string> split(const std::string& s, const std::string& delim)
+{
+       std::vector<std::string> elems;
+       boost::split(elems, s, boost::is_any_of(delim));
+       auto start =
+       std::remove_if(elems.begin(), elems.end(), [](const std::string & t) {
+               return t.size() == 0;
+       });
+       elems.erase(start, elems.end());
+       for (auto& each : elems) {
+               boost::algorithm::trim(each);
+       }
+       return elems;
 }
 
 std::vector<std::string> split(const std::string& s,
-                               char delim,
-                               size_t occurrences) {
-  auto delims = std::string(1, delim);
-  // Split the string normally with the required delimiter.
-  auto content = split(s, delims);
-  // While the result split exceeds the number of requested occurrences, join.
-  std::vector<std::string> accumulator;
-  std::vector<std::string> elems;
-  for (size_t i = 0; i < content.size(); i++) {
-    if (i < occurrences) {
-      elems.push_back(content.at(i));
-    } else {
-      accumulator.push_back(content.at(i));
-    }
-  }
-  // Join the optional accumulator.
-  if (accumulator.size() > 0) {
-    elems.push_back(boost::algorithm::join(accumulator, delims));
-  }
-  return elems;
+                                                          char delim,
+                                                          size_t occurrences)
+{
+       auto delims = std::string(1, delim);
+       // Split the string normally with the required delimiter.
+       auto content = split(s, delims);
+       // While the result split exceeds the number of requested occurrences, join.
+       std::vector<std::string> accumulator;
+       std::vector<std::string> elems;
+       for (size_t i = 0; i < content.size(); i++) {
+               if (i < occurrences) {
+                       elems.push_back(content.at(i));
+               } else {
+                       accumulator.push_back(content.at(i));
+               }
+       }
+       // Join the optional accumulator.
+       if (accumulator.size() > 0) {
+               elems.push_back(boost::algorithm::join(accumulator, delims));
+       }
+       return elems;
 }
 
 }
index eaec8995fee4cb71e5e6ea2dd6f0423877a19e53..3d15e0e5c73d6299a532f7cbcd4785446f677bc0 100644 (file)
@@ -24,7 +24,7 @@ namespace osquery {
  * @return a vector of strings split by delim.
  */
 std::vector<std::string> split(const std::string& s,
-                               const std::string& delim = "\t ");
+                                                          const std::string& delim = "\t ");
 
 /**
  * @brief Split a given string based on an delimiter.
@@ -36,7 +36,7 @@ std::vector<std::string> split(const std::string& s,
  * @return a vector of strings split by delim for occurrences.
  */
 std::vector<std::string> split(const std::string& s,
-                               char delim,
-                               size_t occurrences);
+                                                          char delim,
+                                                          size_t occurrences);
 
 }
index 8000927da8b0a09b5439d350ee6fb7e3b633c149..0cb5f3d03ec15f6c696132c7e4002f865b92b45a 100644 (file)
 
 #include <osquery/utils/conversions/join.h>
 
-namespace osquery{
+namespace osquery {
 
 class ConversionsTests : public testing::Test {};
 
-TEST_F(ConversionsTests, test_join) {
-  std::vector<std::string> content = {
-      "one", "two", "three",
-  };
-  EXPECT_EQ(join(content, ", "), "one, two, three");
+TEST_F(ConversionsTests, test_join)
+{
+       std::vector<std::string> content = {
+               "one", "two", "three",
+       };
+       EXPECT_EQ(join(content, ", "), "one, two, three");
 }
 
 }
index e1e9e6dff7c4898a90e1def65811959eef0f83a7..a342cdd4a9cd25bb9de08befdc058318190fa095 100644 (file)
@@ -17,39 +17,42 @@ namespace osquery {
 class ConversionsTests : public testing::Test {};
 
 struct SplitStringTestData {
-  std::string test_string;
-  std::string delim;
-  std::vector<std::string> test_vector;
+       std::string test_string;
+       std::string delim;
+       std::vector<std::string> test_vector;
 };
 
-std::vector<SplitStringTestData> generateSplitStringTestData() {
-  SplitStringTestData s1;
-  s1.test_string = "a b\tc";
-  s1.test_vector = {"a", "b", "c"};
+std::vector<SplitStringTestData> generateSplitStringTestData()
+{
+       SplitStringTestData s1;
+       s1.test_string = "a b\tc";
+       s1.test_vector = {"a", "b", "c"};
 
-  SplitStringTestData s2;
-  s2.test_string = " a b   c";
-  s2.test_vector = {"a", "b", "c"};
+       SplitStringTestData s2;
+       s2.test_string = " a b   c";
+       s2.test_vector = {"a", "b", "c"};
 
-  SplitStringTestData s3;
-  s3.test_string = "  a     b   c";
-  s3.test_vector = {"a", "b", "c"};
+       SplitStringTestData s3;
+       s3.test_string = "  a     b   c";
+       s3.test_vector = {"a", "b", "c"};
 
-  return {s1, s2, s3};
+       return {s1, s2, s3};
 }
 
-TEST_F(ConversionsTests, test_split) {
-  for (const auto& i : generateSplitStringTestData()) {
-    EXPECT_EQ(split(i.test_string), i.test_vector);
-  }
+TEST_F(ConversionsTests, test_split)
+{
+       for (const auto& i : generateSplitStringTestData()) {
+               EXPECT_EQ(split(i.test_string), i.test_vector);
+       }
 }
 
-TEST_F(ConversionsTests, test_split_occurrences) {
-  std::string content = "T: 'S:S'";
-  std::vector<std::string> expected = {
-      "T", "'S:S'",
-  };
-  EXPECT_EQ(split(content, ':', 1), expected);
+TEST_F(ConversionsTests, test_split_occurrences)
+{
+       std::string content = "T: 'S:S'";
+       std::vector<std::string> expected = {
+               "T", "'S:S'",
+       };
+       EXPECT_EQ(split(content, ':', 1), expected);
 }
 
 } // namespace osquery
index 064831ae7ca68010a1873d49a0512c533b5479e3..598ce960ce8dda5113abd90ecf75950ee3675539 100644 (file)
@@ -18,38 +18,40 @@ namespace osquery {
 class NonFailingConversionsTests : public testing::Test {};
 
 enum class TestGreenColor {
-  Green,
-  Pine,
-  Fern,
-  Olive,
+       Green,
+       Pine,
+       Fern,
+       Olive,
 };
 
-TEST_F(NonFailingConversionsTests, to_string_from_enum_class) {
-  EXPECT_NE(std::string::npos,
-            to<std::string>(TestGreenColor::Green).find("TestGreenColor[0]"));
-  EXPECT_NE(std::string::npos,
-            to<std::string>(TestGreenColor::Pine).find("TestGreenColor[1]"));
-  EXPECT_NE(std::string::npos,
-            to<std::string>(TestGreenColor::Fern).find("TestGreenColor[2]"));
+TEST_F(NonFailingConversionsTests, to_string_from_enum_class)
+{
+       EXPECT_NE(std::string::npos,
+                         to<std::string>(TestGreenColor::Green).find("TestGreenColor[0]"));
+       EXPECT_NE(std::string::npos,
+                         to<std::string>(TestGreenColor::Pine).find("TestGreenColor[1]"));
+       EXPECT_NE(std::string::npos,
+                         to<std::string>(TestGreenColor::Fern).find("TestGreenColor[2]"));
 }
 
 enum class TestOrangeColor {
-  Orange,
-  Fire,
-  Clay,
-  Cider,
+       Orange,
+       Fire,
+       Clay,
+       Cider,
 };
 
-TEST_F(NonFailingConversionsTests, to_string_from_old_enum) {
-  EXPECT_NE(
-      std::string::npos,
-      to<std::string>(TestOrangeColor::Orange).find("TestOrangeColor[0]"));
-  EXPECT_NE(std::string::npos,
-            to<std::string>(TestOrangeColor::Fire).find("TestOrangeColor[1]"));
-  EXPECT_NE(std::string::npos,
-            to<std::string>(TestOrangeColor::Clay).find("TestOrangeColor[2]"));
-  EXPECT_NE(std::string::npos,
-            to<std::string>(TestOrangeColor::Cider).find("TestOrangeColor[3]"));
+TEST_F(NonFailingConversionsTests, to_string_from_old_enum)
+{
+       EXPECT_NE(
+               std::string::npos,
+               to<std::string>(TestOrangeColor::Orange).find("TestOrangeColor[0]"));
+       EXPECT_NE(std::string::npos,
+                         to<std::string>(TestOrangeColor::Fire).find("TestOrangeColor[1]"));
+       EXPECT_NE(std::string::npos,
+                         to<std::string>(TestOrangeColor::Clay).find("TestOrangeColor[2]"));
+       EXPECT_NE(std::string::npos,
+                         to<std::string>(TestOrangeColor::Cider).find("TestOrangeColor[3]"));
 }
 
 } // namespace osquery
index 6b2dce0cb4ee2641102e18eb686f7e3dfd29de60..bb867da6cbe10a9b422d75c55777a176994549a2 100644 (file)
@@ -18,312 +18,335 @@ namespace osquery {
 class ConversionsTests : public testing::Test {};
 
 
-TEST_F(ConversionsTests, tryTo_same_type) {
-  class First {};
-  // rvalue
-  auto ret0 = tryTo<First>(First{});
-  ASSERT_FALSE(ret0.isError());
-
-  auto test_lvalue = First{};
-  auto ret1 = tryTo<First>(test_lvalue);
-  ASSERT_FALSE(ret1.isError());
-
-  const auto const_test_lvalue = First{};
-  auto ret2 = tryTo<First>(const_test_lvalue);
-  ASSERT_FALSE(ret2.isError());
+TEST_F(ConversionsTests, tryTo_same_type)
+{
+       class First {};
+       // rvalue
+       auto ret0 = tryTo<First>(First{});
+       ASSERT_FALSE(ret0.isError());
+
+       auto test_lvalue = First{};
+       auto ret1 = tryTo<First>(test_lvalue);
+       ASSERT_FALSE(ret1.isError());
+
+       const auto const_test_lvalue = First{};
+       auto ret2 = tryTo<First>(const_test_lvalue);
+       ASSERT_FALSE(ret2.isError());
 }
 
 template <typename ValueType, typename StrType>
-void testTryToForRvalue(ValueType value, const StrType& str) {
-  auto ret = tryTo<ValueType>(StrType{str});
-  ASSERT_FALSE(ret.isError());
-  ASSERT_EQ(ret.get(), value);
+void testTryToForRvalue(ValueType value, const StrType& str)
+{
+       auto ret = tryTo<ValueType>(StrType{str});
+       ASSERT_FALSE(ret.isError());
+       ASSERT_EQ(ret.get(), value);
 }
 
 template <typename ValueType, typename StrType>
-void testTryToForLValue(ValueType value, StrType str) {
-  auto ret = tryTo<ValueType>(str);
-  ASSERT_FALSE(ret.isError());
-  ASSERT_EQ(ret.get(), value);
+void testTryToForLValue(ValueType value, StrType str)
+{
+       auto ret = tryTo<ValueType>(str);
+       ASSERT_FALSE(ret.isError());
+       ASSERT_EQ(ret.get(), value);
 }
 
 template <typename ValueType, typename StrType>
-void testTryToForConstLValue(ValueType value, const StrType str) {
-  auto ret = tryTo<ValueType>(str);
-  ASSERT_FALSE(ret.isError());
-  ASSERT_EQ(ret.get(), value);
+void testTryToForConstLValue(ValueType value, const StrType str)
+{
+       auto ret = tryTo<ValueType>(str);
+       ASSERT_FALSE(ret.isError());
+       ASSERT_EQ(ret.get(), value);
 }
 
 template <typename ValueType, typename StrType>
-void testTryToForString(ValueType value, const StrType str) {
-  testTryToForRvalue(value, str);
-  testTryToForLValue(value, str);
-  testTryToForConstLValue(value, str);
+void testTryToForString(ValueType value, const StrType str)
+{
+       testTryToForRvalue(value, str);
+       testTryToForLValue(value, str);
+       testTryToForConstLValue(value, str);
 }
 
 template <typename ValueType>
-void testTryToForValue(ValueType value) {
-  testTryToForString(value, std::to_string(value));
-  testTryToForString(value, std::to_wstring(value));
+void testTryToForValue(ValueType value)
+{
+       testTryToForString(value, std::to_string(value));
+       testTryToForString(value, std::to_wstring(value));
 }
 
 template <typename IntType>
-void testTryToForUnsignedInt() {
-  testTryToForValue<IntType>(119);
-  testTryToForValue<IntType>(std::numeric_limits<IntType>::max());
-  testTryToForValue<IntType>(std::numeric_limits<IntType>::min());
-  testTryToForValue<IntType>(std::numeric_limits<IntType>::lowest());
-  {
-    auto ret = tryTo<IntType>(std::string{"0xfb"}, 16);
-    ASSERT_FALSE(ret.isError());
-    ASSERT_EQ(ret.get(), 251);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"FB"}, 16);
-    ASSERT_FALSE(ret.isError());
-    ASSERT_EQ(ret.get(), 251);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"0xFb"}, 16);
-    ASSERT_FALSE(ret.isError());
-    ASSERT_EQ(ret.get(), 251);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"E1bC2"}, 16);
-    ASSERT_FALSE(ret.isError());
-    ASSERT_EQ(ret.get(), 924610);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"10101"}, 2);
-    ASSERT_FALSE(ret.isError());
-    ASSERT_EQ(ret.get(), 21);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"035"}, 8);
-    ASSERT_FALSE(ret.isError());
-    ASSERT_EQ(ret.get(), 29);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"47"}, 8);
-    ASSERT_FALSE(ret.isError());
-    ASSERT_EQ(ret.get(), 39);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"+15"});
-    ASSERT_FALSE(ret.isError());
-    ASSERT_EQ(ret.get(), 15);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"+1A"}, 16);
-    ASSERT_FALSE(ret.isError());
-    ASSERT_EQ(ret.get(), 26);
-  }
-  // failure tests
-  {
-    auto ret = tryTo<IntType>(std::string{""});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"x"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"xor"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{".1"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"(10)"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"O"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"lO0"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"IV"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"s1"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"u1"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"#12"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"%99"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"*483"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"/488"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"\\493"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"+ 19"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string(2, '\0'));
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
+void testTryToForUnsignedInt()
+{
+       testTryToForValue<IntType>(119);
+       testTryToForValue<IntType>(std::numeric_limits<IntType>::max());
+       testTryToForValue<IntType>(std::numeric_limits<IntType>::min());
+       testTryToForValue<IntType>(std::numeric_limits<IntType>::lowest());
+       {
+               auto ret = tryTo<IntType>(std::string{"0xfb"}, 16);
+               ASSERT_FALSE(ret.isError());
+               ASSERT_EQ(ret.get(), 251);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"FB"}, 16);
+               ASSERT_FALSE(ret.isError());
+               ASSERT_EQ(ret.get(), 251);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"0xFb"}, 16);
+               ASSERT_FALSE(ret.isError());
+               ASSERT_EQ(ret.get(), 251);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"E1bC2"}, 16);
+               ASSERT_FALSE(ret.isError());
+               ASSERT_EQ(ret.get(), 924610);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"10101"}, 2);
+               ASSERT_FALSE(ret.isError());
+               ASSERT_EQ(ret.get(), 21);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"035"}, 8);
+               ASSERT_FALSE(ret.isError());
+               ASSERT_EQ(ret.get(), 29);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"47"}, 8);
+               ASSERT_FALSE(ret.isError());
+               ASSERT_EQ(ret.get(), 39);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"+15"});
+               ASSERT_FALSE(ret.isError());
+               ASSERT_EQ(ret.get(), 15);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"+1A"}, 16);
+               ASSERT_FALSE(ret.isError());
+               ASSERT_EQ(ret.get(), 26);
+       }
+       // failure tests
+       {
+               auto ret = tryTo<IntType>(std::string{""});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"x"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"xor"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{".1"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"(10)"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"O"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"lO0"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"IV"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"s1"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"u1"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"#12"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"%99"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"*483"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"/488"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"\\493"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"+ 19"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string(2, '\0'));
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
 }
 
 template <typename IntType>
-void testTryToForSignedInt() {
-  testTryToForUnsignedInt<IntType>();
-  testTryToForValue<int>(-126);
-  {
-    auto ret = tryTo<IntType>(std::string{"-7A"}, 16);
-    ASSERT_FALSE(ret.isError());
-    ASSERT_EQ(ret.get(), -122);
-  }
-  // failure tests
-  {
-    auto ret = tryTo<IntType>(std::string{"--14779"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"+-1813"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
-  {
-    auto ret = tryTo<IntType>(std::string{"- 3"});
-    ASSERT_TRUE(ret.isError());
-    ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
-  }
+void testTryToForSignedInt()
+{
+       testTryToForUnsignedInt<IntType>();
+       testTryToForValue<int>(-126);
+       {
+               auto ret = tryTo<IntType>(std::string{"-7A"}, 16);
+               ASSERT_FALSE(ret.isError());
+               ASSERT_EQ(ret.get(), -122);
+       }
+       // failure tests
+       {
+               auto ret = tryTo<IntType>(std::string{"--14779"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"+-1813"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
+       {
+               auto ret = tryTo<IntType>(std::string{"- 3"});
+               ASSERT_TRUE(ret.isError());
+               ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
+       }
 }
 
-TEST_F(ConversionsTests, try_i_to_string_and_back) {
-  testTryToForSignedInt<int>();
+TEST_F(ConversionsTests, try_i_to_string_and_back)
+{
+       testTryToForSignedInt<int>();
 }
 
-TEST_F(ConversionsTests, try_l_to_string_and_back) {
-  testTryToForSignedInt<long>();
+TEST_F(ConversionsTests, try_l_to_string_and_back)
+{
+       testTryToForSignedInt<long>();
 }
 
-TEST_F(ConversionsTests, try_ll_to_string_and_back) {
-  testTryToForSignedInt<long long>();
+TEST_F(ConversionsTests, try_ll_to_string_and_back)
+{
+       testTryToForSignedInt<long long>();
 }
 
-TEST_F(ConversionsTests, try_i32_to_string_and_back) {
-  testTryToForSignedInt<std::int32_t>();
+TEST_F(ConversionsTests, try_i32_to_string_and_back)
+{
+       testTryToForSignedInt<std::int32_t>();
 }
 
-TEST_F(ConversionsTests, try_i64_to_string_and_back) {
-  testTryToForSignedInt<std::int64_t>();
+TEST_F(ConversionsTests, try_i64_to_string_and_back)
+{
+       testTryToForSignedInt<std::int64_t>();
 }
 
-TEST_F(ConversionsTests, try_imax_to_string_and_back) {
-  testTryToForSignedInt<std::intmax_t>();
+TEST_F(ConversionsTests, try_imax_to_string_and_back)
+{
+       testTryToForSignedInt<std::intmax_t>();
 }
 
-TEST_F(ConversionsTests, try_u_to_string_and_back) {
-  testTryToForUnsignedInt<unsigned>();
+TEST_F(ConversionsTests, try_u_to_string_and_back)
+{
+       testTryToForUnsignedInt<unsigned>();
 }
 
-TEST_F(ConversionsTests, try_ul_to_string_and_back) {
-  testTryToForUnsignedInt<unsigned long>();
+TEST_F(ConversionsTests, try_ul_to_string_and_back)
+{
+       testTryToForUnsignedInt<unsigned long>();
 }
 
-TEST_F(ConversionsTests, try_ull_to_string_and_back) {
-  testTryToForUnsignedInt<unsigned long long>();
+TEST_F(ConversionsTests, try_ull_to_string_and_back)
+{
+       testTryToForUnsignedInt<unsigned long long>();
 }
 
-TEST_F(ConversionsTests, try_u32_to_string_and_back) {
-  testTryToForUnsignedInt<std::uint32_t>();
+TEST_F(ConversionsTests, try_u32_to_string_and_back)
+{
+       testTryToForUnsignedInt<std::uint32_t>();
 }
 
-TEST_F(ConversionsTests, try_u64_to_string_and_back) {
-  testTryToForUnsignedInt<std::uint64_t>();
+TEST_F(ConversionsTests, try_u64_to_string_and_back)
+{
+       testTryToForUnsignedInt<std::uint64_t>();
 }
 
-TEST_F(ConversionsTests, try_umax_to_string_and_back) {
-  testTryToForUnsignedInt<std::uintmax_t>();
+TEST_F(ConversionsTests, try_umax_to_string_and_back)
+{
+       testTryToForUnsignedInt<std::uintmax_t>();
 }
 
-TEST_F(ConversionsTests, try_size_t_to_string_and_back) {
-  testTryToForUnsignedInt<std::size_t>();
+TEST_F(ConversionsTests, try_size_t_to_string_and_back)
+{
+       testTryToForUnsignedInt<std::size_t>();
 }
 
-TEST_F(ConversionsTests, tryTo_string_to_boolean_valid_args) {
-  const auto test_table = std::unordered_map<std::string, bool>{
-      {"1", true},        {"0", false},       {"y", true},
-      {"n", false},       {"yes", true},      {"yEs", true},
-      {"Yes", true},      {"no", false},      {"No", false},
-      {"t", true},        {"T", true},        {"f", false},
-      {"F", false},       {"true", true},     {"True", true},
-      {"tRUE", true},     {"false", false},   {"fALse", false},
-      {"ok", true},       {"OK", true},       {"Ok", true},
-      {"enable", true},   {"Enable", true},   {"ENABLE", true},
-      {"disable", false}, {"Disable", false}, {"DISABLE", false},
-  };
-  for (const auto& argAndAnswer : test_table) {
-    auto exp = tryTo<bool>(argAndAnswer.first);
-    ASSERT_FALSE(exp.isError());
-    EXPECT_EQ(argAndAnswer.second, exp.get());
-  }
+TEST_F(ConversionsTests, tryTo_string_to_boolean_valid_args)
+{
+       const auto test_table = std::unordered_map<std::string, bool> {
+               {"1", true},        {"0", false},       {"y", true},
+               {"n", false},       {"yes", true},      {"yEs", true},
+               {"Yes", true},      {"no", false},      {"No", false},
+               {"t", true},        {"T", true},        {"f", false},
+               {"F", false},       {"true", true},     {"True", true},
+               {"tRUE", true},     {"false", false},   {"fALse", false},
+               {"ok", true},       {"OK", true},       {"Ok", true},
+               {"enable", true},   {"Enable", true},   {"ENABLE", true},
+               {"disable", false}, {"Disable", false}, {"DISABLE", false},
+       };
+       for (const auto& argAndAnswer : test_table) {
+               auto exp = tryTo<bool>(argAndAnswer.first);
+               ASSERT_FALSE(exp.isError());
+               EXPECT_EQ(argAndAnswer.second, exp.get());
+       }
 }
 
-TEST_F(ConversionsTests, tryTo_string_to_boolean_invalid_args) {
-  const auto test_table = std::vector<std::string>{
-      "",       "\0",      "\n",      "\x06",  "\x15",   "\x27",     "ADS",
-      "7251",   "20.09",   "M0V+K7V", "+",     "-",      ".",        "@",
-      "1.0",    "11",      "00",      " 0",    "1 ",     "2",        "10",
-      "100%",   "_0",      "1_",      "1.",    "2.",     "E",        "a",
-      "b",      "d",       "e",       "o",     "p",      "uh",       "nix",
-      "nixie",  "nixy",    "nixey",   "nay",   "nah",    "no way",   "veto",
-      "yea",    "yeah",    "yep",     "okey",  "aye",    "roger",    "uh-huh",
-      "righto", "yup",     "yuppers", "ja",    "surely", "amen",     "totally",
-      "sure",   "yessir",  "true.",   "tru",   "tr",     "tr.",      "ff",
-      "yy",     "nn",      "nope",    "null",  "nil",    "dis",      "able",
-      "pos",    "neg",     "ack",     "ACK",   "NAK",    "enabled",  "disabled",
-      "valid",  "invalid", "void",    "allow", "permit", "positive", "negative",
-  };
-  for (const auto& wrong : test_table) {
-    auto exp = tryTo<bool>(wrong);
-    ASSERT_TRUE(exp.isError());
-    EXPECT_EQ(ConversionError::InvalidArgument, exp.getErrorCode());
-  }
+TEST_F(ConversionsTests, tryTo_string_to_boolean_invalid_args)
+{
+       const auto test_table = std::vector<std::string> {
+               "",       "\0",      "\n",      "\x06",  "\x15",   "\x27",     "ADS",
+               "7251",   "20.09",   "M0V+K7V", "+",     "-",      ".",        "@",
+               "1.0",    "11",      "00",      " 0",    "1 ",     "2",        "10",
+               "100%",   "_0",      "1_",      "1.",    "2.",     "E",        "a",
+               "b",      "d",       "e",       "o",     "p",      "uh",       "nix",
+               "nixie",  "nixy",    "nixey",   "nay",   "nah",    "no way",   "veto",
+               "yea",    "yeah",    "yep",     "okey",  "aye",    "roger",    "uh-huh",
+               "righto", "yup",     "yuppers", "ja",    "surely", "amen",     "totally",
+               "sure",   "yessir",  "true.",   "tru",   "tr",     "tr.",      "ff",
+               "yy",     "nn",      "nope",    "null",  "nil",    "dis",      "able",
+               "pos",    "neg",     "ack",     "ACK",   "NAK",    "enabled",  "disabled",
+               "valid",  "invalid", "void",    "allow", "permit", "positive", "negative",
+       };
+       for (const auto& wrong : test_table) {
+               auto exp = tryTo<bool>(wrong);
+               ASSERT_TRUE(exp.isError());
+               EXPECT_EQ(ConversionError::InvalidArgument, exp.getErrorCode());
+       }
 }
 
 } // namespace osquery
index 712ee683812b9182f6dcd4396f7b326de53b2adc..b12a443d8afc5b6b32936a01b960b6b18ea1415c 100644 (file)
@@ -26,16 +26,17 @@ namespace osquery {
  * to<std::string>(En::First) -> "En::First[1]"
  */
 template <typename ToType, typename FromType>
-inline typename std::enable_if<std::is_enum<FromType>::value &&
-                                   std::is_same<ToType, std::string>::value,
-                               ToType>::type
-to(FromType from) noexcept {
-  auto str = ToType{boost::core::demangle(typeid(from).name())};
-  str.append("[");
-  str.append(std::to_string(
-      static_cast<typename std::underlying_type<FromType>::type>(from)));
-  str.append("]");
-  return str;
+inline typename std::enable_if < std::is_enum<FromType>::value&&
+std::is_same<ToType, std::string>::value,
+       ToType >::type
+       to(FromType from) noexcept
+{
+       auto str = ToType{boost::core::demangle(typeid(from).name())};
+       str.append("[");
+       str.append(std::to_string(
+                                  static_cast<typename std::underlying_type<FromType>::type>(from)));
+       str.append("]");
+       return str;
 }
 
 } // namespace osquery
index 7f3ab316797ded6335109cd075f18c141d7c6a78..57456883bce6f9ffa1e9990bd42fa5f75ee626ce 100644 (file)
@@ -16,37 +16,38 @@ namespace osquery {
 
 namespace impl {
 
-Expected<bool, ConversionError> stringToBool(std::string from) {
- static const auto table = std::unordered_map<std::string, bool>{
-     {"1", true},
-     {"0", false},
-     {"y", true},
-     {"yes", true},
-     {"n", false},
-     {"no", false},
-     {"t", true},
-     {"true", true},
-     {"f", false},
-     {"false", false},
-     {"ok", true},
-     {"disable", false},
-     {"enable", true},
- };
- using CharType = std::string::value_type;
- // Classic locale could be used here because all available string
- // representations of boolean have ascii encoding. It must be a bit faster.
- static const auto& ctype =
-     std::use_facet<std::ctype<CharType>>(std::locale::classic());
- for (auto& ch : from) {
-   ch = ctype.tolower(ch);
- }
- const auto it = table.find(from);
- if (it == table.end()) {
-   return createError(ConversionError::InvalidArgument)
-          << "Wrong string representation of boolean "
-          << boost::io::quoted(from);
- }
- return it->second;
+Expected<bool, ConversionError> stringToBool(std::string from)
+{
+       static const auto table = std::unordered_map<std::string, bool> {
+               {"1", true},
+               {"0", false},
+               {"y", true},
+               {"yes", true},
+               {"n", false},
+               {"no", false},
+               {"t", true},
+               {"true", true},
+               {"f", false},
+               {"false", false},
+               {"ok", true},
+               {"disable", false},
+               {"enable", true},
+       };
+       using CharType = std::string::value_type;
+       // Classic locale could be used here because all available string
+       // representations of boolean have ascii encoding. It must be a bit faster.
+       static const auto& ctype =
+               std::use_facet<std::ctype<CharType>>(std::locale::classic());
+       for (auto& ch : from) {
+               ch = ctype.tolower(ch);
+       }
+       const auto it = table.find(from);
+       if (it == table.end()) {
+               return createError(ConversionError::InvalidArgument)
+                          << "Wrong string representation of boolean "
+                          << boost::io::quoted(from);
+       }
+       return it->second;
 }
 
 } // namespace impl
index 2cc81c11c6ee77c2780ed535c1e17a910b468104..7dc014157a3061bb3d4aee4ea7cb6f7c56eeaa0f 100644 (file)
 namespace osquery {
 
 enum class ConversionError {
-  InvalidArgument,
-  OutOfRange,
-  Unknown,
+       InvalidArgument,
+       OutOfRange,
+       Unknown,
 };
 
 template <typename ToType, typename FromType>
-inline typename std::enable_if<
-    std::is_same<ToType,
-                 typename std::remove_cv<typename std::remove_reference<
-                     FromType>::type>::type>::value,
-    Expected<ToType, ConversionError>>::type
-tryTo(FromType&& from) {
-  return std::forward<FromType>(from);
+inline typename std::enable_if <
+std::is_same<ToType,
+       typename std::remove_cv<typename std::remove_reference<
+       FromType>::type>::type>::value,
+       Expected<ToType, ConversionError >>::type
+       tryTo(FromType&& from)
+{
+       return std::forward<FromType>(from);
 }
 
 namespace impl {
 
 template <typename Type>
 struct IsStlString {
-  static constexpr bool value = std::is_same<Type, std::string>::value ||
-                                std::is_same<Type, std::wstring>::value;
+       static constexpr bool value = std::is_same<Type, std::string>::value ||
+                                                                 std::is_same<Type, std::wstring>::value;
 };
 
 template <typename Type>
 struct IsInteger {
-  static constexpr bool value =
-      std::is_integral<Type>::value && !std::is_same<Type, bool>::value;
+       static constexpr bool value =
+               std::is_integral<Type>::value && !std::is_same<Type, bool>::value;
 };
 
-template <typename FromType,
-          typename ToType,
-          typename IntType,
-          typename =
-              typename std::enable_if<std::is_same<ToType, IntType>::value &&
-                                          IsStlString<FromType>::value,
-                                      IntType>::type>
+template < typename FromType,
+                  typename ToType,
+                  typename IntType,
+                  typename =
+                  typename std::enable_if < std::is_same<ToType, IntType>::value &&
+                                                                        IsStlString<FromType>::value,
+                                                                        IntType >::type >
 struct IsConversionFromStringToIntEnabledFor {
-  using type = IntType;
+       using type = IntType;
 };
 
 template <typename ToType, typename FromType>
 inline
-    typename IsConversionFromStringToIntEnabledFor<FromType, ToType, int>::type
-    throwingStringToInt(const FromType& from, const int base) {
-  auto pos = std::size_t{};
-  return std::stoi(from, &pos, base);
+typename IsConversionFromStringToIntEnabledFor<FromType, ToType, int>::type
+throwingStringToInt(const FromType& from, const int base)
+{
+       auto pos = std::size_t{};
+       return std::stoi(from, &pos, base);
 }
 
 template <typename ToType, typename FromType>
 inline typename IsConversionFromStringToIntEnabledFor<FromType,
-                                                      ToType,
-                                                      long int>::type
-throwingStringToInt(const FromType& from, const int base) {
-  auto pos = std::size_t{};
-  return std::stol(from, &pos, base);
+          ToType,
+          long int>::type
+          throwingStringToInt(const FromType& from, const int base)
+{
+       auto pos = std::size_t{};
+       return std::stol(from, &pos, base);
 }
 
 template <typename ToType, typename FromType>
 inline typename IsConversionFromStringToIntEnabledFor<FromType,
-                                                      ToType,
-                                                      long long int>::type
-throwingStringToInt(const FromType& from, const int base) {
-  auto pos = std::size_t{};
-  return std::stoll(from, &pos, base);
+          ToType,
+          long long int>::type
+          throwingStringToInt(const FromType& from, const int base)
+{
+       auto pos = std::size_t{};
+       return std::stoll(from, &pos, base);
 }
 
 template <typename ToType, typename FromType>
 inline typename IsConversionFromStringToIntEnabledFor<FromType,
-                                                      ToType,
-                                                      unsigned int>::type
-throwingStringToInt(const FromType& from, const int base) {
-  auto pos = std::size_t{};
-  return std::stoul(from, &pos, base);
+          ToType,
+          unsigned int>::type
+          throwingStringToInt(const FromType& from, const int base)
+{
+       auto pos = std::size_t{};
+       return std::stoul(from, &pos, base);
 }
 
 template <typename ToType, typename FromType>
 inline typename IsConversionFromStringToIntEnabledFor<FromType,
-                                                      ToType,
-                                                      unsigned long int>::type
-throwingStringToInt(const FromType& from, const int base) {
-  auto pos = std::size_t{};
-  return std::stoul(from, &pos, base);
+          ToType,
+          unsigned long int>::type
+          throwingStringToInt(const FromType& from, const int base)
+{
+       auto pos = std::size_t{};
+       return std::stoul(from, &pos, base);
 }
 
 template <typename ToType, typename FromType>
 inline
-    typename IsConversionFromStringToIntEnabledFor<FromType,
-                                                   ToType,
-                                                   unsigned long long int>::type
-    throwingStringToInt(const FromType& from, const int base) {
-  auto pos = std::size_t{};
-  return std::stoull(from, &pos, base);
+typename IsConversionFromStringToIntEnabledFor<FromType,
+                ToType,
+                unsigned long long int>::type
+                throwingStringToInt(const FromType& from, const int base)
+{
+       auto pos = std::size_t{};
+       return std::stoull(from, &pos, base);
 }
 
 Expected<bool, ConversionError> stringToBool(std::string from);
@@ -117,26 +124,27 @@ Expected<bool, ConversionError> stringToBool(std::string from);
  * Template tryTo for [w]string to integer conversion
  */
 template <typename ToType, typename FromType>
-inline typename std::enable_if<impl::IsInteger<ToType>::value &&
-                                   impl::IsStlString<FromType>::value,
-                               Expected<ToType, ConversionError>>::type
-tryTo(const FromType& from, const int base = 10) noexcept {
-  try {
-    return impl::throwingStringToInt<ToType>(from, base);
-  } catch (const std::invalid_argument& ia) {
-    return createError(ConversionError::InvalidArgument)
-           << "If no conversion could be performed. " << ia.what();
-  } catch (const std::out_of_range& oor) {
-    return createError(ConversionError::OutOfRange)
-           << "Value read is out of the range of representable values by an "
-              "int. "
-           << oor.what();
-  } catch (...) {
-    return createError(ConversionError::Unknown)
-           << "Unknown error during conversion "
-           << boost::core::demangle(typeid(FromType).name()) << " to "
-           << boost::core::demangle(typeid(ToType).name()) << " base " << base;
-  }
+inline typename std::enable_if < impl::IsInteger<ToType>::value&&
+impl::IsStlString<FromType>::value,
+        Expected<ToType, ConversionError >>::type
+        tryTo(const FromType& from, const int base = 10) noexcept
+{
+       try {
+               return impl::throwingStringToInt<ToType>(from, base);
+       } catch (const std::invalid_argument& ia) {
+               return createError(ConversionError::InvalidArgument)
+                          << "If no conversion could be performed. " << ia.what();
+       } catch (const std::out_of_range& oor) {
+               return createError(ConversionError::OutOfRange)
+                          << "Value read is out of the range of representable values by an "
+                          "int. "
+                          << oor.what();
+       } catch (...) {
+               return createError(ConversionError::Unknown)
+                          << "Unknown error during conversion "
+                          << boost::core::demangle(typeid(FromType).name()) << " to "
+                          << boost::core::demangle(typeid(ToType).name()) << " base " << base;
+       }
 }
 
 /**
@@ -152,13 +160,15 @@ tryTo(const FromType& from, const int base = 10) noexcept {
  */
 template <typename ToType>
 inline typename std::enable_if<std::is_same<ToType, bool>::value,
-                               Expected<ToType, ConversionError>>::type
-tryTo(std::string from) {
-  return impl::stringToBool(std::move(from));
+          Expected<ToType, ConversionError>>::type
+          tryTo(std::string from)
+{
+       return impl::stringToBool(std::move(from));
 }
 
-inline size_t operator"" _sz(unsigned long long int x) {
-  return x;
+inline size_t operator"" _sz(unsigned long long int x)
+{
+       return x;
 }
 
 }
index 3e784a218dea9f539e89a3a5467c39a98ff7b2b4..7d9e0e0b516b42e5cb03bb4375f56bbbc023eca5 100644 (file)
@@ -21,12 +21,13 @@ namespace debug_only {
 /**
  * Use it for unconditional abort with message only in debug mode
  */
-inline void fail(const char* msg) {
+inline void fail(const char* msg)
+{
 #ifndef NDEBUG
-  std::cerr << "Failure in debug mode: \"" << msg << "\"\n";
-  assert(false && "Failure in debug mode");
+       std::cerr << "Failure in debug mode: \"" << msg << "\"\n";
+       assert(false && "Failure in debug mode");
 #endif
-  boost::ignore_unused(msg);
+       boost::ignore_unused(msg);
 }
 
 /**
@@ -34,27 +35,29 @@ inline void fail(const char* msg) {
  * See examples of usage in tests osquery/debug/tests/debug_only_tests.cpp
  */
 template <typename FunctionType>
-inline void verify(FunctionType checker, const char* msg) {
+inline void verify(FunctionType checker, const char* msg)
+{
 #ifndef NDEBUG
-  if (!checker()) {
-    fail(msg);
-  }
+       if (!checker()) {
+               fail(msg);
+       }
 #endif
-  boost::ignore_unused(checker);
-  boost::ignore_unused(msg);
+       boost::ignore_unused(checker);
+       boost::ignore_unused(msg);
 }
 
 /**
  * Pretty much the same as verify, but for the simple boolean condition
  */
-inline void verifyTrue(bool expected_true, const char* msg) {
+inline void verifyTrue(bool expected_true, const char* msg)
+{
 #ifndef NDEBUG
-  if (!expected_true) {
-    fail(msg);
-  }
+       if (!expected_true) {
+               fail(msg);
+       }
 #endif
-  boost::ignore_unused(expected_true);
-  boost::ignore_unused(msg);
+       boost::ignore_unused(expected_true);
+       boost::ignore_unused(msg);
 }
 
 /**
@@ -67,69 +70,74 @@ inline void verifyTrue(bool expected_true, const char* msg) {
  */
 template <typename VarType>
 class Var final {
- public:
-  explicit Var()
+public:
+       explicit Var()
 #ifndef NDEBUG
-      : value_(VarType{})
+               : value_(VarType {})
 #endif
-  {
-  }
+       {
+       }
 
-  Var(VarType value)
+       Var(VarType value)
 #ifndef NDEBUG
-      : value_(std::move(value))
+               : value_(std::move(value))
 #endif
-  {
-    boost::ignore_unused(value);
-  }
+       {
+               boost::ignore_unused(value);
+       }
 
-  inline void verify(const char* msg) const {
+       inline void verify(const char* msg) const
+       {
 #ifndef NDEBUG
-    if (!value_) {
-      fail(msg);
-    }
+               if (!value_) {
+                       fail(msg);
+               }
 #endif
-    boost::ignore_unused(msg);
-  }
+               boost::ignore_unused(msg);
+       }
 
-  template <typename FunctionType>
-  inline void verify(FunctionType checker, const char* msg) const {
+       template <typename FunctionType>
+       inline void verify(FunctionType checker, const char* msg) const
+       {
 #ifndef NDEBUG
-    if (!checker(value_)) {
-      fail(msg);
-    }
+               if (!checker(value_)) {
+                       fail(msg);
+               }
 #endif
-    boost::ignore_unused(checker);
-    boost::ignore_unused(msg);
-  }
+               boost::ignore_unused(checker);
+               boost::ignore_unused(msg);
+       }
 
-  inline void verifyEqual(const VarType& other, const char* msg) const {
+       inline void verifyEqual(const VarType& other, const char* msg) const
+       {
 #ifndef NDEBUG
-    if (value_ != other) {
-      fail(msg);
-    }
+               if (value_ != other) {
+                       fail(msg);
+               }
 #endif
-    boost::ignore_unused(other);
-    boost::ignore_unused(msg);
-  }
+               boost::ignore_unused(other);
+               boost::ignore_unused(msg);
+       }
 
-  inline void set(const VarType& newValue) const {
+       inline void set(const VarType& newValue) const
+       {
 #ifndef NDEBUG
-    value_ = newValue;
+               value_ = newValue;
 #endif
-    boost::ignore_unused(newValue);
-  }
+               boost::ignore_unused(newValue);
+       }
 
-  template <typename FunctionType>
-  inline void update(FunctionType modifier) const {
+       template <typename FunctionType>
+       inline void update(FunctionType modifier) const
+       {
 #ifndef NDEBUG
-    value_ = modifier(value_);
+               value_ = modifier(value_);
 #endif
-    boost::ignore_unused(modifier);
-  }
+               boost::ignore_unused(modifier);
+       }
 
 #ifndef NDEBUG
-  mutable VarType value_;
+       mutable VarType value_;
 #endif
 };
 
index a88f4b376505863a59a33afc58bb44ce82464105..74c36cedfccc5a71d984593b153cbd214b4f0ec0 100644 (file)
@@ -22,157 +22,186 @@ class TestEmptyClass {};
 
 } // namespace
 
-GTEST_TEST(DebugOnly, fail) {
+GTEST_TEST(DebugOnly, fail)
+{
 #ifndef NDEBUG
-  ASSERT_DEATH(debug_only::fail("This code should fail"),
-               "debug.*This code should fail");
+       ASSERT_DEATH(debug_only::fail("This code should fail"),
+                                "debug.*This code should fail");
 #endif
 }
 
-GTEST_TEST(DebugOnly, verify) {
+GTEST_TEST(DebugOnly, verify)
+{
 #ifndef NDEBUG
-  ASSERT_DEATH(
-      debug_only::verify([]() { return false; },
-                         "This code should fail because lambda return false"),
-      "debug.*This code should fail because lambda return false");
+       ASSERT_DEATH(
+       debug_only::verify([]() {
+               return false;
+       },
+       "This code should fail because lambda return false"),
+       "debug.*This code should fail because lambda return false");
 #endif
 }
 
-GTEST_TEST(DebugOnly, verifyTrue) {
-  debug_only::verifyTrue(true, "This code must not fail");
+GTEST_TEST(DebugOnly, verifyTrue)
+{
+       debug_only::verifyTrue(true, "This code must not fail");
 #ifndef NDEBUG
-  ASSERT_DEATH(debug_only::verifyTrue(false, "This code should fail"),
-               "debug.*This code should fail");
+       ASSERT_DEATH(debug_only::verifyTrue(false, "This code should fail"),
+                                "debug.*This code should fail");
 #endif
 }
 
-GTEST_TEST(DebugOnly, verify_do_nothing_in_non_debug_mode) {
+GTEST_TEST(DebugOnly, verify_do_nothing_in_non_debug_mode)
+{
 #ifdef NDEBUG
-  // This code will be compiled and run only in release mode according to macro
-  // conditions around. That means code inside lambda is not going to be run.
-  // Let's check it here.
-  debug_only::verify(
-      []() {
-        EXPECT_TRUE(false);
-        return false;
-      },
-      "This check should not fail");
+       // This code will be compiled and run only in release mode according to macro
+       // conditions around. That means code inside lambda is not going to be run.
+       // Let's check it here.
+       debug_only::verify(
+       []() {
+               EXPECT_TRUE(false);
+               return false;
+       },
+       "This check should not fail");
 #endif
 }
 
-GTEST_TEST(DebugOnlyVar, size) {
+GTEST_TEST(DebugOnlyVar, size)
+{
 #ifndef NDEBUG
-  ASSERT_EQ(sizeof(long long), sizeof(debug_only::Var<long long>));
+       ASSERT_EQ(sizeof(long long), sizeof(debug_only::Var<long long>));
 #else
-  ASSERT_EQ(sizeof(TestEmptyClass), sizeof(debug_only::Var<long long>));
+       ASSERT_EQ(sizeof(TestEmptyClass), sizeof(debug_only::Var<long long>));
 #endif
 }
 
-GTEST_TEST(DebugOnlyVar, verify) {
-  auto var = debug_only::Var<int>{0};
-  var.verify([](auto v) { return v == 0; }, "This should be fine");
-  var.verifyEqual(0, "This also should be fine");
+GTEST_TEST(DebugOnlyVar, verify)
+{
+       auto var = debug_only::Var<int> {0};
+       var.verify([](auto v) {
+               return v == 0;
+       }, "This should be fine");
+       var.verifyEqual(0, "This also should be fine");
 #ifndef NDEBUG
-  ASSERT_DEATH(var.verify([](auto v) { return v == 9; },
-                          "There is some funny joke supposed to be here"),
-               "debug.*There is some funny joke supposed to be here");
-  ASSERT_DEATH(var.verifyEqual(12, "One more hilarious joke, have a fun"),
-               "debug.*One more hilarious joke, have a fun");
-  ASSERT_DEATH(var.verify("And one more, don't worry this is the last one"),
-               "debug.*And one more, don't worry this is the last one");
+       ASSERT_DEATH(var.verify([](auto v) {
+               return v == 9;
+       },
+       "There is some funny joke supposed to be here"),
+       "debug.*There is some funny joke supposed to be here");
+       ASSERT_DEATH(var.verifyEqual(12, "One more hilarious joke, have a fun"),
+                                "debug.*One more hilarious joke, have a fun");
+       ASSERT_DEATH(var.verify("And one more, don't worry this is the last one"),
+                                "debug.*And one more, don't worry this is the last one");
 #endif
 }
 
-GTEST_TEST(DebugOnlyVar, implicit_constructor) {
-  // object can be created from underlying value
-  debug_only::Var<int> dbg_var = 12;
-  dbg_var.verifyEqual(12, "This check should not fail");
+GTEST_TEST(DebugOnlyVar, implicit_constructor)
+{
+       // object can be created from underlying value
+       debug_only::Var<int> dbg_var = 12;
+       dbg_var.verifyEqual(12, "This check should not fail");
 }
 
-GTEST_TEST(DebugOnlyVar, set) {
-  auto var = debug_only::Var<int>{12};
-  var.verify(
-      [](auto value) {
-        EXPECT_EQ(12, value);
-        return true;
-      },
-      "This check should not fail");
-  var.set(291);
-  var.verify(
-      [](auto value) {
-        EXPECT_EQ(291, value);
-        return true;
-      },
-      "This check should not fail");
+GTEST_TEST(DebugOnlyVar, set)
+{
+       auto var = debug_only::Var<int> {12};
+       var.verify(
+       [](auto value) {
+               EXPECT_EQ(12, value);
+               return true;
+       },
+       "This check should not fail");
+       var.set(291);
+       var.verify(
+       [](auto value) {
+               EXPECT_EQ(291, value);
+               return true;
+       },
+       "This check should not fail");
 }
 
-GTEST_TEST(DebugOnlyVar, update) {
-  auto var = debug_only::Var<int>{12};
-  var.verify(
-      [](auto value) {
-        EXPECT_EQ(12, value);
-        return true;
-      },
-      "This check should not fail");
-  // where
-  var.update([](auto old) { return old + 17; });
-  // let's verify update was successful
-  var.verify(
-      [](auto value) {
-        EXPECT_EQ(12 + 17, value);
-        return true;
-      },
-      "This check should not fail");
+GTEST_TEST(DebugOnlyVar, update)
+{
+       auto var = debug_only::Var<int> {12};
+       var.verify(
+       [](auto value) {
+               EXPECT_EQ(12, value);
+               return true;
+       },
+       "This check should not fail");
+       // where
+       var.update([](auto old) {
+               return old + 17;
+       });
+       // let's verify update was successful
+       var.verify(
+       [](auto value) {
+               EXPECT_EQ(12 + 17, value);
+               return true;
+       },
+       "This check should not fail");
 }
 
-GTEST_TEST(DebugOnlyVar, verify_in_non_debug_mode_should_not_be_run) {
-  auto var = debug_only::Var<int>{12};
-  var.verify(
-      [](auto value) {
-        EXPECT_EQ(12, value);
-        return true;
-      },
-      "This check should not fail");
+GTEST_TEST(DebugOnlyVar, verify_in_non_debug_mode_should_not_be_run)
+{
+       auto var = debug_only::Var<int> {12};
+       var.verify(
+       [](auto value) {
+               EXPECT_EQ(12, value);
+               return true;
+       },
+       "This check should not fail");
 #ifdef NDEBUG
-  // This code will be compiled and run only in release mode according to macro
-  // conditions around. That means code inside lambda is not going to be run.
-  // Let's check it here.
-  var.verify(
-      [](auto value) {
-        boost::ignore_unused(value);
-        EXPECT_TRUE(false);
-        return false;
-      },
-      "This check should not fail");
+       // This code will be compiled and run only in release mode according to macro
+       // conditions around. That means code inside lambda is not going to be run.
+       // Let's check it here.
+       var.verify(
+       [](auto value) {
+               boost::ignore_unused(value);
+               EXPECT_TRUE(false);
+               return false;
+       },
+       "This check should not fail");
 #endif
 }
 
 struct Gun {
-  explicit Gun(int bullets) : bullets_(bullets) {}
-
-  void shot() {
-    dbg.update([this](auto v) { return bullets_ == 0 ? v + 1 : v; });
-    --bullets_;
-  }
-
-  int bullets_;
-  debug_only::Var<int> dbg = 0;
+       explicit Gun(int bullets) : bullets_(bullets) {}
+
+       void shot()
+       {
+               dbg.update([this](auto v) {
+                       return bullets_ == 0 ? v + 1 : v;
+               });
+               --bullets_;
+       }
+
+       int bullets_;
+       debug_only::Var<int> dbg = 0;
 };
 
-GTEST_TEST(DebugOnlyVar, example_debug_check_watchdog) {
-  auto gun = Gun(2);
-  gun.shot();
-  gun.shot();
-  gun.dbg.verify([](auto v) { return v == 0; },
-                 "There is not supposed to have a failure, just an example");
+GTEST_TEST(DebugOnlyVar, example_debug_check_watchdog)
+{
+       auto gun = Gun(2);
+       gun.shot();
+       gun.shot();
+       gun.dbg.verify([](auto v) {
+               return v == 0;
+       },
+       "There is not supposed to have a failure, just an example");
 }
 
-GTEST_TEST(DebugOnlyVar, example_debug_check_return_value) {
-  auto test_function = [](int i) { return std::to_string(i); };
-  debug_only::Var<std::string> dbg = test_function(11);
-  dbg.verify([](const auto& str) { return !str.empty(); },
-             "The return value is not supposed to be empty string. But for "
-             "performance reasons let's check it only in debug mode.");
+GTEST_TEST(DebugOnlyVar, example_debug_check_return_value)
+{
+       auto test_function = [](int i) {
+               return std::to_string(i);
+       };
+       debug_only::Var<std::string> dbg = test_function(11);
+       dbg.verify([](const auto & str) {
+               return !str.empty();
+       },
+       "The return value is not supposed to be empty string. But for "
+       "performance reasons let's check it only in debug mode.");
 }
 
 } // namespace osquery
index 2fbe3039afcad7c2171c691328b9cc76c051e9ec..5ef55334a69624bdc9a61dd5d6c1288220ee623d 100644 (file)
 namespace osquery {
 
 class ErrorBase {
- public:
-  virtual std::string getNonRecursiveMessage() const = 0;
-  virtual std::string getMessage() const = 0;
-  virtual ~ErrorBase() = default;
-  ErrorBase() = default;
-  ErrorBase(const ErrorBase& other) = default;
+public:
+       virtual std::string getNonRecursiveMessage() const = 0;
+       virtual std::string getMessage() const = 0;
+       virtual ~ErrorBase() = default;
+       ErrorBase() = default;
+       ErrorBase(const ErrorBase& other) = default;
 };
 
 template <typename ErrorCodeEnumType>
 class Error final : public ErrorBase {
- public:
-  using SelfType = Error<ErrorCodeEnumType>;
-
-  explicit Error(ErrorCodeEnumType error_code,
-                 std::string message,
-                 std::unique_ptr<ErrorBase> underlying_error = nullptr)
-      : errorCode_(error_code),
-        message_(std::move(message)),
-        underlyingError_(std::move(underlying_error)) {}
-
-  explicit Error(ErrorCodeEnumType error_code,
-                 std::unique_ptr<ErrorBase> underlying_error = nullptr)
-      : errorCode_(error_code), underlyingError_(std::move(underlying_error)) {}
-
-  virtual ~Error() = default;
-
-  Error(Error&& other) = default;
-  Error(const Error& other) = delete;
-
-  Error& operator=(Error&& other) = default;
-  Error& operator=(const Error& other) = delete;
-
-  ErrorCodeEnumType getErrorCode() const {
-    return errorCode_;
-  }
-
-  bool hasUnderlyingError() const {
-    return underlyingError_ != nullptr;
-  }
-
-  const ErrorBase& getUnderlyingError() const {
-    return *underlyingError_;
-  }
-
-  std::unique_ptr<ErrorBase> takeUnderlyingError() const {
-    return std::move(underlyingError_);
-  }
-
-  std::string getNonRecursiveMessage() const override {
-    std::string full_message = to<std::string>(errorCode_);
-    if (message_.size() > 0) {
-      full_message += " (" + message_ + ")";
-    }
-    return full_message;
-  }
-
-  std::string getMessage() const override {
-    std::string full_message = getNonRecursiveMessage();
-    if (underlyingError_) {
-      full_message += " <- " + underlyingError_->getMessage();
-    }
-    return full_message;
-  }
-
-  void appendToMessage(const std::string& text) {
-    message_.append(text);
-  }
-
- private:
-  ErrorCodeEnumType errorCode_;
-  std::string message_;
-  std::unique_ptr<ErrorBase> underlyingError_;
+public:
+       using SelfType = Error<ErrorCodeEnumType>;
+
+       explicit Error(ErrorCodeEnumType error_code,
+                                  std::string message,
+                                  std::unique_ptr<ErrorBase> underlying_error = nullptr)
+               : errorCode_(error_code),
+                 message_(std::move(message)),
+                 underlyingError_(std::move(underlying_error)) {}
+
+       explicit Error(ErrorCodeEnumType error_code,
+                                  std::unique_ptr<ErrorBase> underlying_error = nullptr)
+               : errorCode_(error_code), underlyingError_(std::move(underlying_error)) {}
+
+       virtual ~Error() = default;
+
+       Error(Error&& other) = default;
+       Error(const Error& other) = delete;
+
+       Error& operator=(Error&& other) = default;
+       Error& operator=(const Error& other) = delete;
+
+       ErrorCodeEnumType getErrorCode() const
+       {
+               return errorCode_;
+       }
+
+       bool hasUnderlyingError() const
+       {
+               return underlyingError_ != nullptr;
+       }
+
+       const ErrorBase& getUnderlyingError() const
+       {
+               return *underlyingError_;
+       }
+
+       std::unique_ptr<ErrorBase> takeUnderlyingError() const
+       {
+               return std::move(underlyingError_);
+       }
+
+       std::string getNonRecursiveMessage() const override
+       {
+               std::string full_message = to<std::string>(errorCode_);
+               if (message_.size() > 0) {
+                       full_message += " (" + message_ + ")";
+               }
+               return full_message;
+       }
+
+       std::string getMessage() const override
+       {
+               std::string full_message = getNonRecursiveMessage();
+               if (underlyingError_) {
+                       full_message += " <- " + underlyingError_->getMessage();
+               }
+               return full_message;
+       }
+
+       void appendToMessage(const std::string& text)
+       {
+               message_.append(text);
+       }
+
+private:
+       ErrorCodeEnumType errorCode_;
+       std::string message_;
+       std::unique_ptr<ErrorBase> underlyingError_;
 };
 
 template <class T>
-inline bool operator==(const Error<T>& lhs, const Error<T>& rhs) {
-  return lhs.getErrorCode() == rhs.getErrorCode();
+inline bool operator==(const Error<T>& lhs, const Error<T>& rhs)
+{
+       return lhs.getErrorCode() == rhs.getErrorCode();
 }
 
 template <class T>
-inline bool operator==(const Error<T>* lhs, const T rhs) {
-  return lhs->getErrorCode() == rhs;
+inline bool operator==(const Error<T>* lhs, const T rhs)
+{
+       return lhs->getErrorCode() == rhs;
 }
 
 template <class T>
-inline bool operator==(const Error<T>& lhs, const T rhs) {
-  return lhs.getErrorCode() == rhs;
+inline bool operator==(const Error<T>& lhs, const T rhs)
+{
+       return lhs.getErrorCode() == rhs;
 }
 
 template <class T>
-inline bool operator==(const ErrorBase& lhs, const T rhs) {
-  try {
-    const Error<T>& casted_lhs = dynamic_cast<const Error<T>&>(lhs);
-    return casted_lhs == rhs;
-  } catch (std::bad_cast _) {
-    return false;
-  }
+inline bool operator==(const ErrorBase& lhs, const T rhs)
+{
+       try {
+               const Error<T>& casted_lhs = dynamic_cast<const Error<T>&>(lhs);
+               return casted_lhs == rhs;
+       } catch (std::bad_cast _) {
+               return false;
+       }
 }
 
-inline std::ostream& operator<<(std::ostream& out, const ErrorBase& error) {
-  out << error.getMessage();
-  return out;
+inline std::ostream& operator<<(std::ostream& out, const ErrorBase& error)
+{
+       out << error.getMessage();
+       return out;
 }
 
 template <typename ErrorCodeEnumType, typename OtherErrorCodeEnumType>
 OSQUERY_NODISCARD Error<ErrorCodeEnumType> createError(
-    ErrorCodeEnumType error_code,
-    Error<OtherErrorCodeEnumType> underlying_error) {
-  return Error<ErrorCodeEnumType>(
-      error_code,
-      std::make_unique<Error<OtherErrorCodeEnumType>>(
-          std::move(underlying_error)));
+       ErrorCodeEnumType error_code,
+       Error<OtherErrorCodeEnumType> underlying_error)
+{
+       return Error<ErrorCodeEnumType>(
+                          error_code,
+                          std::make_unique<Error<OtherErrorCodeEnumType>>(
+                                  std::move(underlying_error)));
 }
 
 template <typename ErrorCodeEnumType>
 OSQUERY_NODISCARD Error<ErrorCodeEnumType> createError(
-    ErrorCodeEnumType error_code) {
-  return Error<ErrorCodeEnumType>(error_code);
+       ErrorCodeEnumType error_code)
+{
+       return Error<ErrorCodeEnumType>(error_code);
 }
 
 template <typename ErrorType,
-          typename ValueType,
-          typename = typename std::enable_if<
-              std::is_base_of<ErrorBase, ErrorType>::value>::type>
-inline ErrorType operator<<(ErrorType&& error, const ValueType& value) {
-  std::ostringstream ostr{};
-  ostr << value;
-  error.appendToMessage(ostr.str());
-  return std::forward<ErrorType>(error);
+                 typename ValueType,
+                 typename = typename std::enable_if<
+                         std::is_base_of<ErrorBase, ErrorType>::value>::type>
+inline ErrorType operator<<(ErrorType && error, const ValueType& value)
+{
+       std::ostringstream ostr{};
+       ostr << value;
+       error.appendToMessage(ostr.str());
+       return std::forward<ErrorType>(error);
 }
 
 } // namespace osquery
index 4af8024bfebaa904ae85504359a78b951ebe62de..211570100cdc9b974c09f4d5ce6b3de3caca514e 100644 (file)
 #include <osquery/utils/error/error.h>
 
 enum class TestError {
-  SomeError = 1,
-  AnotherError = 2,
-  MusicError,
+       SomeError = 1,
+       AnotherError = 2,
+       MusicError,
 };
 
-GTEST_TEST(ErrorTest, initialization) {
-  auto error = osquery::Error<TestError>(TestError::SomeError, "TestMessage");
-  EXPECT_FALSE(error.hasUnderlyingError());
-  EXPECT_TRUE(error == TestError::SomeError);
+GTEST_TEST(ErrorTest, initialization)
+{
+       auto error = osquery::Error<TestError>(TestError::SomeError, "TestMessage");
+       EXPECT_FALSE(error.hasUnderlyingError());
+       EXPECT_TRUE(error == TestError::SomeError);
 
-  auto shortMsg = error.getNonRecursiveMessage();
-  EXPECT_NE(std::string::npos, shortMsg.find("TestError[1]"));
+       auto shortMsg = error.getNonRecursiveMessage();
+       EXPECT_NE(std::string::npos, shortMsg.find("TestError[1]"));
 
-  auto fullMsg = error.getMessage();
-  EXPECT_NE(std::string::npos, fullMsg.find("TestError[1]"));
-  EXPECT_NE(std::string::npos, fullMsg.find("TestMessage"));
+       auto fullMsg = error.getMessage();
+       EXPECT_NE(std::string::npos, fullMsg.find("TestError[1]"));
+       EXPECT_NE(std::string::npos, fullMsg.find("TestMessage"));
 }
 
-GTEST_TEST(ErrorTest, recursive) {
-  auto orignalError = std::make_unique<osquery::Error<TestError>>(
-      TestError::SomeError, "SuperTestMessage");
-  auto error = osquery::Error<TestError>(
-      TestError::AnotherError, "TestMessage", std::move(orignalError));
-  EXPECT_TRUE(error.hasUnderlyingError());
-
-  auto shortMsg = error.getNonRecursiveMessage();
-  EXPECT_EQ(std::string::npos, shortMsg.find("TestError[1]"));
-  EXPECT_NE(std::string::npos, shortMsg.find("TestError[2]"));
-
-  auto fullMsg = error.getMessage();
-  EXPECT_NE(std::string::npos, fullMsg.find("TestError[1]"));
-  EXPECT_NE(std::string::npos, fullMsg.find("SuperTestMessage"));
-  EXPECT_NE(std::string::npos, fullMsg.find("TestError[2]"));
-  EXPECT_NE(std::string::npos, fullMsg.find("TestMessage"));
+GTEST_TEST(ErrorTest, recursive)
+{
+       auto orignalError = std::make_unique<osquery::Error<TestError>>(
+                                                       TestError::SomeError, "SuperTestMessage");
+       auto error = osquery::Error<TestError>(
+                                        TestError::AnotherError, "TestMessage", std::move(orignalError));
+       EXPECT_TRUE(error.hasUnderlyingError());
+
+       auto shortMsg = error.getNonRecursiveMessage();
+       EXPECT_EQ(std::string::npos, shortMsg.find("TestError[1]"));
+       EXPECT_NE(std::string::npos, shortMsg.find("TestError[2]"));
+
+       auto fullMsg = error.getMessage();
+       EXPECT_NE(std::string::npos, fullMsg.find("TestError[1]"));
+       EXPECT_NE(std::string::npos, fullMsg.find("SuperTestMessage"));
+       EXPECT_NE(std::string::npos, fullMsg.find("TestError[2]"));
+       EXPECT_NE(std::string::npos, fullMsg.find("TestMessage"));
 }
 
-bool stringContains(const std::string& where, const std::string& what) {
-  return boost::contains(where, what);
+bool stringContains(const std::string& where, const std::string& what)
+{
+       return boost::contains(where, what);
 };
 
-GTEST_TEST(ErrorTest, createErrorSimple) {
-  const auto msg = std::string{
-      "\"!ab#c$d%e&f'g(h)i*j+k,l-m.n/o\" this is not a human readable text"};
-  auto err = osquery::createError(TestError::AnotherError) << msg;
-  EXPECT_EQ(TestError::AnotherError, err.getErrorCode());
-  EXPECT_FALSE(err.hasUnderlyingError());
-
-  auto shortMsg = err.getMessage();
-  EXPECT_PRED2(stringContains, shortMsg, "TestError");
-  EXPECT_PRED2(stringContains, shortMsg, msg);
+GTEST_TEST(ErrorTest, createErrorSimple)
+{
+       const auto msg = std::string{
+               "\"!ab#c$d%e&f'g(h)i*j+k,l-m.n/o\" this is not a human readable text"};
+       auto err = osquery::createError(TestError::AnotherError) << msg;
+       EXPECT_EQ(TestError::AnotherError, err.getErrorCode());
+       EXPECT_FALSE(err.hasUnderlyingError());
+
+       auto shortMsg = err.getMessage();
+       EXPECT_PRED2(stringContains, shortMsg, "TestError");
+       EXPECT_PRED2(stringContains, shortMsg, msg);
 }
 
-GTEST_TEST(ErrorTest, createErrorFromOtherError) {
-  const auto firstMsg = std::string{"2018-06-28 08:13 451014"};
-
-  auto firstErr = osquery::createError(TestError::SomeError) << firstMsg;
-  EXPECT_EQ(TestError::SomeError, firstErr.getErrorCode());
-  EXPECT_FALSE(firstErr.hasUnderlyingError());
-
-  EXPECT_PRED2(stringContains, firstErr.getMessage(), firstMsg);
-
-  const auto secondMsg = std::string{"what's wrong with the first message?!"};
-  auto secondErr =
-      osquery::createError(TestError::AnotherError, std::move(firstErr))
-      << secondMsg;
-  EXPECT_EQ(TestError::AnotherError, secondErr.getErrorCode());
-  EXPECT_TRUE(secondErr.hasUnderlyingError());
-  auto secondShortMsg = secondErr.getMessage();
-  EXPECT_PRED2(stringContains, secondShortMsg, "TestError");
-  EXPECT_PRED2(stringContains, secondShortMsg, firstMsg);
-  EXPECT_PRED2(stringContains, secondShortMsg, secondMsg);
+GTEST_TEST(ErrorTest, createErrorFromOtherError)
+{
+       const auto firstMsg = std::string{"2018-06-28 08:13 451014"};
+
+       auto firstErr = osquery::createError(TestError::SomeError) << firstMsg;
+       EXPECT_EQ(TestError::SomeError, firstErr.getErrorCode());
+       EXPECT_FALSE(firstErr.hasUnderlyingError());
+
+       EXPECT_PRED2(stringContains, firstErr.getMessage(), firstMsg);
+
+       const auto secondMsg = std::string{"what's wrong with the first message?!"};
+       auto secondErr =
+               osquery::createError(TestError::AnotherError, std::move(firstErr))
+               << secondMsg;
+       EXPECT_EQ(TestError::AnotherError, secondErr.getErrorCode());
+       EXPECT_TRUE(secondErr.hasUnderlyingError());
+       auto secondShortMsg = secondErr.getMessage();
+       EXPECT_PRED2(stringContains, secondShortMsg, "TestError");
+       EXPECT_PRED2(stringContains, secondShortMsg, firstMsg);
+       EXPECT_PRED2(stringContains, secondShortMsg, secondMsg);
 }
 
-GTEST_TEST(ErrorTest, createErrorAndStreamToIt) {
-  const auto a4 = std::string{"A4"};
-  const auto err = osquery::createError(TestError::MusicError)
-                   << "Do" << '-' << "Re"
-                   << "-Mi"
-                   << "-Fa"
-                   << "-Sol"
-                   << "-La"
-                   << "-Si La" << boost::io::quoted(a4) << ' ' << 440 << " Hz";
-  EXPECT_EQ(TestError::MusicError, err.getErrorCode());
-  auto fullMsg = err.getMessage();
-  EXPECT_PRED2(
-      stringContains, fullMsg, "Do-Re-Mi-Fa-Sol-La-Si La\"A4\" 440 Hz");
+GTEST_TEST(ErrorTest, createErrorAndStreamToIt)
+{
+       const auto a4 = std::string{"A4"};
+       const auto err = osquery::createError(TestError::MusicError)
+                                        << "Do" << '-' << "Re"
+                                        << "-Mi"
+                                        << "-Fa"
+                                        << "-Sol"
+                                        << "-La"
+                                        << "-Si La" << boost::io::quoted(a4) << ' ' << 440 << " Hz";
+       EXPECT_EQ(TestError::MusicError, err.getErrorCode());
+       auto fullMsg = err.getMessage();
+       EXPECT_PRED2(
+               stringContains, fullMsg, "Do-Re-Mi-Fa-Sol-La-Si La\"A4\" 440 Hz");
 }
index a3252ce468e597159f7c1b9e5dd3c01e4320d57a..664cd87cae9f8437e93cf2961f0f16bd5e72300b 100644 (file)
@@ -72,170 +72,192 @@ namespace osquery {
 
 template <typename ValueType_, typename ErrorCodeEnumType>
 class Expected final {
- public:
-  using ValueType = ValueType_;
-  using ErrorType = Error<ErrorCodeEnumType>;
-  using SelfType = Expected<ValueType, ErrorCodeEnumType>;
-
-  static_assert(
-      !std::is_pointer<ValueType>::value,
-      "Please do not use raw pointers as expected value, "
-      "use smart pointers instead. See CppCoreGuidelines for explanation. "
-      "https://github.com/isocpp/CppCoreGuidelines/blob/master/"
-      "CppCoreGuidelines.md#Rf-unique_ptr");
-  static_assert(!std::is_reference<ValueType>::value,
-                "Expected does not support reference as a value type");
-  static_assert(std::is_enum<ErrorCodeEnumType>::value,
-                "ErrorCodeEnumType template parameter must be enum");
-
- public:
-  Expected(ValueType value) : object_{std::move(value)} {}
-
-  Expected(ErrorType error) : object_{std::move(error)} {}
-
-  explicit Expected(ErrorCodeEnumType code, std::string message)
-      : object_{ErrorType(code, message)} {}
-
-  Expected() = delete;
-  Expected(ErrorBase* error) = delete;
-
-  Expected(Expected&& other)
-      : object_(std::move(other.object_)), errorChecked_(other.errorChecked_) {
-    other.errorChecked_.set(true);
-  }
-
-  Expected& operator=(Expected&& other) {
-    if (this != &other) {
-      errorChecked_.verify("Expected was not checked before assigning");
-
-      object_ = std::move(other.object_);
-      errorChecked_ = other.errorChecked_;
-      other.errorChecked_.set(true);
-    }
-    return *this;
-  }
-
-  Expected(const Expected&) = delete;
-  Expected& operator=(const Expected& other) = delete;
-
-  ~Expected() {
-    errorChecked_.verify("Expected was not checked before destruction");
-  }
-
-  static SelfType success(ValueType value) {
-    return SelfType{std::move(value)};
-  }
-
-  static SelfType failure(std::string message) {
-    auto defaultCode = ErrorCodeEnumType{};
-    return SelfType(defaultCode, std::move(message));
-  }
-
-  static SelfType failure(ErrorCodeEnumType code, std::string message) {
-    return SelfType(code, std::move(message));
-  }
-
-  ErrorType takeError() && = delete;
-  ErrorType takeError() & {
-    verifyIsError();
-    return std::move(boost::get<ErrorType>(object_));
-  }
-
-  const ErrorType& getError() const&& = delete;
-  const ErrorType& getError() const& {
-    verifyIsError();
-    return boost::get<ErrorType>(object_);
-  }
-
-  ErrorCodeEnumType getErrorCode() const&& = delete;
-  ErrorCodeEnumType getErrorCode() const& {
-    return getError().getErrorCode();
-  }
-
-  bool isError() const noexcept {
-    errorChecked_.set(true);
-    return object_.which() == kErrorType_;
-  }
-
-  void ignoreResult() const noexcept {
-    errorChecked_.set(true);
-  }
-
-  bool isValue() const noexcept {
-    return !isError();
-  }
-
-  explicit operator bool() const noexcept {
-    return isValue();
-  }
-
-  ValueType& get() && = delete;
-  ValueType& get() & {
-    verifyIsValue();
-    return boost::get<ValueType>(object_);
-  }
-
-  const ValueType& get() const&& = delete;
-  const ValueType& get() const& {
-    verifyIsValue();
-    return boost::get<ValueType>(object_);
-  }
-
-  ValueType take() && = delete;
-  ValueType take() & {
-    return std::move(get());
-  }
-
-  template <typename ValueTypeUniversal = ValueType>
-  typename std::enable_if<
-      std::is_same<typename std::decay<ValueTypeUniversal>::type,
-                   ValueType>::value,
-      ValueType>::type
-  takeOr(ValueTypeUniversal&& defaultValue) {
-    if (isError()) {
-      return std::forward<ValueTypeUniversal>(defaultValue);
-    }
-    return std::move(get());
-  }
-
-  ValueType* operator->() && = delete;
-  ValueType* operator->() & {
-    return &get();
-  }
-
-  const ValueType* operator->() const&& = delete;
-  const ValueType* operator->() const& {
-    return &get();
-  }
-
-  ValueType& operator*() && = delete;
-  ValueType& operator*() & {
-    return get();
-  }
-
-  const ValueType& operator*() const&& = delete;
-  const ValueType& operator*() const& {
-    return get();
-  }
-
- private:
-  inline void verifyIsError() const {
-    debug_only::verify([this]() { return object_.which() == kErrorType_; },
-                       "Do not try to get error from Expected with value");
-  }
-
-  inline void verifyIsValue() const {
-    debug_only::verify([this]() { return object_.which() == kValueType_; },
-                       "Do not try to get value from Expected with error");
-  }
-
- private:
-  boost::variant<ValueType, ErrorType> object_;
-  enum ETypeId {
-    kValueType_ = 0,
-    kErrorType_ = 1,
-  };
-  debug_only::Var<bool> errorChecked_ = false;
+public:
+       using ValueType = ValueType_;
+       using ErrorType = Error<ErrorCodeEnumType>;
+       using SelfType = Expected<ValueType, ErrorCodeEnumType>;
+
+       static_assert(
+               !std::is_pointer<ValueType>::value,
+               "Please do not use raw pointers as expected value, "
+               "use smart pointers instead. See CppCoreGuidelines for explanation. "
+               "https://github.com/isocpp/CppCoreGuidelines/blob/master/"
+               "CppCoreGuidelines.md#Rf-unique_ptr");
+       static_assert(!std::is_reference<ValueType>::value,
+                                 "Expected does not support reference as a value type");
+       static_assert(std::is_enum<ErrorCodeEnumType>::value,
+                                 "ErrorCodeEnumType template parameter must be enum");
+
+public:
+       Expected(ValueType value) : object_{std::move(value)} {}
+
+       Expected(ErrorType error) : object_{std::move(error)} {}
+
+       explicit Expected(ErrorCodeEnumType code, std::string message)
+               : object_{ErrorType(code, message)} {}
+
+       Expected() = delete;
+       Expected(ErrorBase* error) = delete;
+
+       Expected(Expected&& other)
+               : object_(std::move(other.object_)), errorChecked_(other.errorChecked_)
+       {
+               other.errorChecked_.set(true);
+       }
+
+       Expected& operator=(Expected&& other)
+       {
+               if (this != &other) {
+                       errorChecked_.verify("Expected was not checked before assigning");
+
+                       object_ = std::move(other.object_);
+                       errorChecked_ = other.errorChecked_;
+                       other.errorChecked_.set(true);
+               }
+               return *this;
+       }
+
+       Expected(const Expected&) = delete;
+       Expected& operator=(const Expected& other) = delete;
+
+       ~Expected()
+       {
+               errorChecked_.verify("Expected was not checked before destruction");
+       }
+
+       static SelfType success(ValueType value)
+       {
+               return SelfType{std::move(value)};
+       }
+
+       static SelfType failure(std::string message)
+       {
+               auto defaultCode = ErrorCodeEnumType{};
+               return SelfType(defaultCode, std::move(message));
+       }
+
+       static SelfType failure(ErrorCodeEnumType code, std::string message)
+       {
+               return SelfType(code, std::move(message));
+       }
+
+       ErrorType takeError()&& = delete;
+       ErrorType takeError()& {
+               verifyIsError();
+               return std::move(boost::get<ErrorType>(object_));
+       }
+
+       const ErrorType& getError() const&& = delete;
+       const ErrorType& getError() const&
+       {
+               verifyIsError();
+               return boost::get<ErrorType>(object_);
+       }
+
+       ErrorCodeEnumType getErrorCode() const&& = delete;
+       ErrorCodeEnumType getErrorCode() const&
+       {
+               return getError().getErrorCode();
+       }
+
+       bool isError() const noexcept
+       {
+               errorChecked_.set(true);
+               return object_.which() == kErrorType_;
+       }
+
+       void ignoreResult() const noexcept
+       {
+               errorChecked_.set(true);
+       }
+
+       bool isValue() const noexcept
+       {
+               return !isError();
+       }
+
+       explicit operator bool() const noexcept
+       {
+               return isValue();
+       }
+
+       ValueType& get()&& = delete;
+       ValueType& get()& {
+               verifyIsValue();
+               return boost::get<ValueType>(object_);
+       }
+
+       const ValueType& get() const&& = delete;
+       const ValueType& get() const&
+       {
+               verifyIsValue();
+               return boost::get<ValueType>(object_);
+       }
+
+       ValueType take()&& = delete;
+       ValueType take()& {
+               return std::move(get());
+       }
+
+       template <typename ValueTypeUniversal = ValueType>
+       typename std::enable_if <
+       std::is_same<typename std::decay<ValueTypeUniversal>::type,
+               ValueType>::value,
+               ValueType >::type
+               takeOr(ValueTypeUniversal && defaultValue)
+       {
+               if (isError()) {
+                       return std::forward<ValueTypeUniversal>(defaultValue);
+               }
+               return std::move(get());
+       }
+
+       ValueType* operator->()&& = delete;
+       ValueType* operator->()& {
+               return &get();
+       }
+
+       const ValueType* operator->() const&& = delete;
+       const ValueType* operator->() const&
+       {
+               return &get();
+       }
+
+       ValueType& operator*()&& = delete;
+       ValueType& operator*()& {
+               return get();
+       }
+
+       const ValueType& operator*() const&& = delete;
+       const ValueType& operator*() const&
+       {
+               return get();
+       }
+
+private:
+       inline void verifyIsError() const
+       {
+               debug_only::verify([this]() {
+                       return object_.which() == kErrorType_;
+               },
+               "Do not try to get error from Expected with value");
+       }
+
+       inline void verifyIsValue() const
+       {
+               debug_only::verify([this]() {
+                       return object_.which() == kValueType_;
+               },
+               "Do not try to get value from Expected with error");
+       }
+
+private:
+       boost::variant<ValueType, ErrorType> object_;
+       enum ETypeId {
+               kValueType_ = 0,
+               kErrorType_ = 1,
+       };
+       debug_only::Var<bool> errorChecked_ = false;
 };
 
 template <typename ValueType, typename ErrorCodeEnumType>
index 24d62a353149b7572537874d61f56baa951886ff..168c0a8c0566ae4844af5a6207b8756bfc1684b9 100644 (file)
 namespace osquery {
 
 enum class TestError {
-  Some,
-  Another,
-  Semantic,
-  Logical,
-  Runtime,
+       Some,
+       Another,
+       Semantic,
+       Logical,
+       Runtime,
 };
 
-GTEST_TEST(ExpectedTest, success_contructor_initialization) {
-  Expected<std::string, TestError> value = std::string("Test");
-  EXPECT_TRUE(value);
-  EXPECT_TRUE(value.isValue());
-  EXPECT_FALSE(value.isError());
-  EXPECT_EQ(value.get(), "Test");
+GTEST_TEST(ExpectedTest, success_contructor_initialization)
+{
+       Expected<std::string, TestError> value = std::string("Test");
+       EXPECT_TRUE(value);
+       EXPECT_TRUE(value.isValue());
+       EXPECT_FALSE(value.isError());
+       EXPECT_EQ(value.get(), "Test");
 }
 
-GTEST_TEST(ExpectedTest, failure_error_contructor_initialization) {
-  Expected<std::string, TestError> error =
-      Error<TestError>(TestError::Some, "Please try again");
-  EXPECT_FALSE(error);
-  EXPECT_FALSE(error.isValue());
-  EXPECT_TRUE(error.isError());
-  EXPECT_EQ(error.getErrorCode(), TestError::Some);
+GTEST_TEST(ExpectedTest, failure_error_contructor_initialization)
+{
+       Expected<std::string, TestError> error =
+               Error<TestError>(TestError::Some, "Please try again");
+       EXPECT_FALSE(error);
+       EXPECT_FALSE(error.isValue());
+       EXPECT_TRUE(error.isError());
+       EXPECT_EQ(error.getErrorCode(), TestError::Some);
 }
 
-bool stringContains(const std::string& what, const std::string& where) {
-  return boost::contains(what, where);
+bool stringContains(const std::string& what, const std::string& where)
+{
+       return boost::contains(what, where);
 };
 
-GTEST_TEST(ExpectedTest, failure_error_str_contructor_initialization) {
-  const auto msg =
-      std::string{"\"#$%&'()*+,-./089:;<[=]>\" is it a valid error message?"};
-  auto expected = Expected<std::string, TestError>::failure(msg);
-  EXPECT_FALSE(expected);
-  EXPECT_TRUE(expected.isError());
-  EXPECT_EQ(expected.getErrorCode(), TestError::Some);
-  auto fullMsg = expected.getError().getMessage();
-  EXPECT_PRED2(stringContains, fullMsg, msg);
+GTEST_TEST(ExpectedTest, failure_error_str_contructor_initialization)
+{
+       const auto msg =
+               std::string{"\"#$%&'()*+,-./089:;<[=]>\" is it a valid error message?"};
+       auto expected = Expected<std::string, TestError>::failure(msg);
+       EXPECT_FALSE(expected);
+       EXPECT_TRUE(expected.isError());
+       EXPECT_EQ(expected.getErrorCode(), TestError::Some);
+       auto fullMsg = expected.getError().getMessage();
+       EXPECT_PRED2(stringContains, fullMsg, msg);
 }
 
-osquery::ExpectedUnique<std::string, TestError> testFunction() {
-  return std::make_unique<std::string>("Test");
+osquery::ExpectedUnique<std::string, TestError> testFunction()
+{
+       return std::make_unique<std::string>("Test");
 }
 
-GTEST_TEST(ExpectedTest, ExpectedSharedTestFunction) {
-  osquery::Expected<std::shared_ptr<std::string>, TestError> sharedPointer =
-      std::make_shared<std::string>("Test");
-  EXPECT_TRUE(sharedPointer);
-  EXPECT_EQ(**sharedPointer, "Test");
-
-  osquery::ExpectedShared<std::string, TestError> sharedPointer2 =
-      std::make_shared<std::string>("Test");
-  EXPECT_TRUE(sharedPointer2);
-  EXPECT_EQ(**sharedPointer2, "Test");
+GTEST_TEST(ExpectedTest, ExpectedSharedTestFunction)
+{
+       osquery::Expected<std::shared_ptr<std::string>, TestError> sharedPointer =
+               std::make_shared<std::string>("Test");
+       EXPECT_TRUE(sharedPointer);
+       EXPECT_EQ(**sharedPointer, "Test");
+
+       osquery::ExpectedShared<std::string, TestError> sharedPointer2 =
+               std::make_shared<std::string>("Test");
+       EXPECT_TRUE(sharedPointer2);
+       EXPECT_EQ(**sharedPointer2, "Test");
 }
 
-GTEST_TEST(ExpectedTest, ExpectedUniqueTestFunction) {
-  auto uniquePointer = testFunction();
-  EXPECT_TRUE(uniquePointer);
-  EXPECT_EQ(**uniquePointer, "Test");
+GTEST_TEST(ExpectedTest, ExpectedUniqueTestFunction)
+{
+       auto uniquePointer = testFunction();
+       EXPECT_TRUE(uniquePointer);
+       EXPECT_EQ(**uniquePointer, "Test");
 }
 
-GTEST_TEST(ExpectedTest, ExpectedSharedWithError) {
-  osquery::ExpectedShared<std::string, TestError> error =
-      Error<TestError>(TestError::Another, "Some message");
-  EXPECT_FALSE(error);
-  EXPECT_EQ(error.getErrorCode(), TestError::Another);
+GTEST_TEST(ExpectedTest, ExpectedSharedWithError)
+{
+       osquery::ExpectedShared<std::string, TestError> error =
+               Error<TestError>(TestError::Another, "Some message");
+       EXPECT_FALSE(error);
+       EXPECT_EQ(error.getErrorCode(), TestError::Another);
 }
 
-GTEST_TEST(ExpectedTest, ExpectedOptional) {
-  boost::optional<std::string> optional = std::string("123");
-  osquery::Expected<boost::optional<std::string>, TestError> optionalExpected =
-      optional;
-  EXPECT_TRUE(optionalExpected);
-  EXPECT_EQ(**optionalExpected, "123");
+GTEST_TEST(ExpectedTest, ExpectedOptional)
+{
+       boost::optional<std::string> optional = std::string("123");
+       osquery::Expected<boost::optional<std::string>, TestError> optionalExpected =
+               optional;
+       EXPECT_TRUE(optionalExpected);
+       EXPECT_EQ(**optionalExpected, "123");
 }
 
 template <typename ValueType>
 using LocalExpected = Expected<ValueType, TestError>;
 
-GTEST_TEST(ExpectedTest, createError_example) {
-  auto giveMeDozen = [](bool valid) -> LocalExpected<int> {
-    if (valid) {
-      return 50011971;
-    }
-    return createError(TestError::Logical)
-           << "an error message is supposed to be here";
-  };
-  auto v = giveMeDozen(true);
-  EXPECT_TRUE(v);
-  ASSERT_FALSE(v.isError());
-  EXPECT_EQ(*v, 50011971);
-
-  auto errV = giveMeDozen(false);
-  EXPECT_FALSE(errV);
-  ASSERT_TRUE(errV.isError());
-  EXPECT_EQ(errV.getErrorCode(), TestError::Logical);
+GTEST_TEST(ExpectedTest, createError_example)
+{
+       auto giveMeDozen = [](bool valid) -> LocalExpected<int> {
+               if (valid)
+               {
+                       return 50011971;
+               }
+               return createError(TestError::Logical)
+                               << "an error message is supposed to be here";
+       };
+       auto v = giveMeDozen(true);
+       EXPECT_TRUE(v);
+       ASSERT_FALSE(v.isError());
+       EXPECT_EQ(*v, 50011971);
+
+       auto errV = giveMeDozen(false);
+       EXPECT_FALSE(errV);
+       ASSERT_TRUE(errV.isError());
+       EXPECT_EQ(errV.getErrorCode(), TestError::Logical);
 }
 
-GTEST_TEST(ExpectedTest, ExpectedSuccess_example) {
-  auto giveMeStatus = [](bool valid) -> ExpectedSuccess<TestError> {
-    if (valid) {
-      return Success{};
-    }
-    return Error<TestError>(TestError::Runtime,
-                            "an error message is supposed to be here");
-  };
-  auto s = giveMeStatus(true);
-  EXPECT_TRUE(s);
-  ASSERT_FALSE(s.isError());
-
-  auto errS = giveMeStatus(false);
-  EXPECT_FALSE(errS);
-  ASSERT_TRUE(errS.isError());
+GTEST_TEST(ExpectedTest, ExpectedSuccess_example)
+{
+       auto giveMeStatus = [](bool valid) -> ExpectedSuccess<TestError> {
+               if (valid)
+               {
+                       return Success{};
+               }
+               return Error<TestError>(TestError::Runtime,
+                                                               "an error message is supposed to be here");
+       };
+       auto s = giveMeStatus(true);
+       EXPECT_TRUE(s);
+       ASSERT_FALSE(s.isError());
+
+       auto errS = giveMeStatus(false);
+       EXPECT_FALSE(errS);
+       ASSERT_TRUE(errS.isError());
 }
 
-GTEST_TEST(ExpectedTest, nested_errors_example) {
-  const auto msg = std::string{"Write a good error message"};
-  auto firstFailureSource = [&msg]() -> Expected<std::vector<int>, TestError> {
-    return createError(TestError::Semantic) << msg;
-  };
-  auto giveMeNestedError = [&]() -> Expected<std::vector<int>, TestError> {
-    auto ret = firstFailureSource();
-    ret.isError();
-    return createError(TestError::Runtime, ret.takeError()) << msg;
-  };
-  auto ret = giveMeNestedError();
-  EXPECT_FALSE(ret);
-  ASSERT_TRUE(ret.isError());
-  EXPECT_EQ(ret.getErrorCode(), TestError::Runtime);
-  ASSERT_TRUE(ret.getError().hasUnderlyingError());
-  EXPECT_PRED2(stringContains, ret.getError().getMessage(), msg);
+GTEST_TEST(ExpectedTest, nested_errors_example)
+{
+       const auto msg = std::string{"Write a good error message"};
+       auto firstFailureSource = [&msg]() -> Expected<std::vector<int>, TestError> {
+               return createError(TestError::Semantic) << msg;
+       };
+       auto giveMeNestedError = [&]() -> Expected<std::vector<int>, TestError> {
+               auto ret = firstFailureSource();
+               ret.isError();
+               return createError(TestError::Runtime, ret.takeError()) << msg;
+       };
+       auto ret = giveMeNestedError();
+       EXPECT_FALSE(ret);
+       ASSERT_TRUE(ret.isError());
+       EXPECT_EQ(ret.getErrorCode(), TestError::Runtime);
+       ASSERT_TRUE(ret.getError().hasUnderlyingError());
+       EXPECT_PRED2(stringContains, ret.getError().getMessage(), msg);
 }
 
-GTEST_TEST(ExpectedTest, error_handling_example) {
-  auto failureSource = []() -> Expected<std::vector<int>, TestError> {
-    return createError(TestError::Runtime) << "Test error message ()*+,-.";
-  };
-  auto ret = failureSource();
-  if (ret.isError()) {
-    switch (ret.getErrorCode()) {
-    case TestError::Some:
-    case TestError::Another:
-    case TestError::Semantic:
-    case TestError::Logical:
-      FAIL() << "There is must be a Runtime type of error";
-    case TestError::Runtime:
-      SUCCEED();
-    }
-  } else {
-    FAIL() << "There is must be an error";
-  }
+GTEST_TEST(ExpectedTest, error_handling_example)
+{
+       auto failureSource = []() -> Expected<std::vector<int>, TestError> {
+               return createError(TestError::Runtime) << "Test error message ()*+,-.";
+       };
+       auto ret = failureSource();
+       if (ret.isError()) {
+               switch (ret.getErrorCode()) {
+               case TestError::Some:
+               case TestError::Another:
+               case TestError::Semantic:
+               case TestError::Logical:
+                       FAIL() << "There is must be a Runtime type of error";
+               case TestError::Runtime:
+                       SUCCEED();
+               }
+       } else {
+               FAIL() << "There is must be an error";
+       }
 }
 
-GTEST_TEST(ExpectedTest, expected_was_not_checked_before_destruction_failure) {
-  auto action = []() { auto expected = ExpectedSuccess<TestError>{Success()}; };
+GTEST_TEST(ExpectedTest, expected_was_not_checked_before_destruction_failure)
+{
+       auto action = []() {
+               auto expected = ExpectedSuccess<TestError> {Success()};
+       };
 #ifndef NDEBUG
-  ASSERT_DEATH(action(), "Expected was not checked before destruction");
+       ASSERT_DEATH(action(), "Expected was not checked before destruction");
 #else
-  boost::ignore_unused(action);
+       boost::ignore_unused(action);
 #endif
 }
 
-GTEST_TEST(ExpectedTest, expected_was_not_checked_before_assigning_failure) {
-  auto action = []() {
-    auto expected = ExpectedSuccess<TestError>{Success()};
-    expected = ExpectedSuccess<TestError>{Success()};
-    expected.isValue();
-  };
+GTEST_TEST(ExpectedTest, expected_was_not_checked_before_assigning_failure)
+{
+       auto action = []() {
+               auto expected = ExpectedSuccess<TestError> {Success()};
+               expected = ExpectedSuccess<TestError> {Success()};
+               expected.isValue();
+       };
 #ifndef NDEBUG
-  ASSERT_DEATH(action(), "Expected was not checked before assigning");
+       ASSERT_DEATH(action(), "Expected was not checked before assigning");
 #else
-  boost::ignore_unused(action);
+       boost::ignore_unused(action);
 #endif
 }
 
-GTEST_TEST(ExpectedTest, expected_move_is_safe) {
-  auto expected = ExpectedSuccess<TestError>{Success()};
-  expected.isValue();
-  expected = ExpectedSuccess<TestError>{Success()};
-  expected.isValue();
+GTEST_TEST(ExpectedTest, expected_move_is_safe)
+{
+       auto expected = ExpectedSuccess<TestError> {Success()};
+       expected.isValue();
+       expected = ExpectedSuccess<TestError> {Success()};
+       expected.isValue();
 }
 
-GTEST_TEST(ExpectedTest, get_value_from_expected_with_error) {
-  auto action = []() {
-    auto expected = Expected<int, TestError>(TestError::Logical,
-                                             "Test error message @#$0k+Qh");
-    auto value = expected.get();
-    boost::ignore_unused(value);
-  };
+GTEST_TEST(ExpectedTest, get_value_from_expected_with_error)
+{
+       auto action = []() {
+               auto expected = Expected<int, TestError>(TestError::Logical,
+                                                                                                "Test error message @#$0k+Qh");
+               auto value = expected.get();
+               boost::ignore_unused(value);
+       };
 #ifndef NDEBUG
-  ASSERT_DEATH(action(), "Do not try to get value from Expected with error");
+       ASSERT_DEATH(action(), "Do not try to get value from Expected with error");
 #else
-  boost::ignore_unused(action);
+       boost::ignore_unused(action);
 #endif
 }
 
-GTEST_TEST(ExpectedTest, const_get_value_from_expected_with_error) {
-  auto action = []() {
-    const auto expected = Expected<int, TestError>(
-        TestError::Semantic, "Test error message {}()[].");
-    auto value = expected.get();
-    boost::ignore_unused(value);
-  };
+GTEST_TEST(ExpectedTest, const_get_value_from_expected_with_error)
+{
+       auto action = []() {
+               const auto expected = Expected<int, TestError>(
+                                                                 TestError::Semantic, "Test error message {}()[].");
+               auto value = expected.get();
+               boost::ignore_unused(value);
+       };
 #ifndef NDEBUG
-  ASSERT_DEATH(action(), "Do not try to get value from Expected with error");
+       ASSERT_DEATH(action(), "Do not try to get value from Expected with error");
 #else
-  boost::ignore_unused(action);
+       boost::ignore_unused(action);
 #endif
 }
 
-GTEST_TEST(ExpectedTest, take_value_from_expected_with_error) {
-  auto action = []() {
-    auto expected = Expected<int, TestError>(TestError::Semantic,
-                                             "Test error message !&^?<>.");
-    auto value = expected.take();
-    boost::ignore_unused(value);
-  };
+GTEST_TEST(ExpectedTest, take_value_from_expected_with_error)
+{
+       auto action = []() {
+               auto expected = Expected<int, TestError>(TestError::Semantic,
+                                                                                                "Test error message !&^?<>.");
+               auto value = expected.take();
+               boost::ignore_unused(value);
+       };
 #ifndef NDEBUG
-  ASSERT_DEATH(action(), "Do not try to get value from Expected with error");
+       ASSERT_DEATH(action(), "Do not try to get value from Expected with error");
 #else
-  boost::ignore_unused(action);
+       boost::ignore_unused(action);
 #endif
 }
 
-GTEST_TEST(ExpectedTest, get_error_from_expected_with_value) {
-  auto action = []() {
-    auto expected = Expected<int, TestError>(228);
-    const auto& error = expected.getError();
-    boost::ignore_unused(error);
-  };
+GTEST_TEST(ExpectedTest, get_error_from_expected_with_value)
+{
+       auto action = []() {
+               auto expected = Expected<int, TestError>(228);
+               const auto& error = expected.getError();
+               boost::ignore_unused(error);
+       };
 #ifndef NDEBUG
-  ASSERT_DEATH(action(), "Do not try to get error from Expected with value");
+       ASSERT_DEATH(action(), "Do not try to get error from Expected with value");
 #else
-  boost::ignore_unused(action);
+       boost::ignore_unused(action);
 #endif
 }
 
-GTEST_TEST(ExpectedTest, take_error_from_expected_with_value) {
-  auto action = []() {
-    auto expected = Expected<int, TestError>(228);
-    return expected.takeError();
-  };
+GTEST_TEST(ExpectedTest, take_error_from_expected_with_value)
+{
+       auto action = []() {
+               auto expected = Expected<int, TestError>(228);
+               return expected.takeError();
+       };
 #ifndef NDEBUG
-  ASSERT_DEATH(action(), "Do not try to get error from Expected with value");
+       ASSERT_DEATH(action(), "Do not try to get error from Expected with value");
 #else
-  boost::ignore_unused(action);
+       boost::ignore_unused(action);
 #endif
 }
 
-GTEST_TEST(ExpectedTest, value__takeOr) {
-  const auto text = std::string{"some text"};
-  auto callable = [&text]() -> Expected<std::string, TestError> {
-    return text;
-  };
-  auto expected = callable();
-  EXPECT_EQ(expected ? expected.take() : std::string{"default text"}, text);
+GTEST_TEST(ExpectedTest, value__takeOr)
+{
+       const auto text = std::string{"some text"};
+       auto callable = [&text]() -> Expected<std::string, TestError> {
+               return text;
+       };
+       auto expected = callable();
+       EXPECT_EQ(expected ? expected.take() : std::string{"default text"}, text);
 
-  EXPECT_EQ(callable().takeOr(std::string{"default text"}), text);
+       EXPECT_EQ(callable().takeOr(std::string{"default text"}), text);
 }
 
-GTEST_TEST(ExpectedTest, error__takeOr) {
-  auto expected =
-      Expected<std::string, TestError>(TestError::Semantic, "error message");
-  EXPECT_EQ(expected.takeOr(std::string{"default text"}), "default text");
+GTEST_TEST(ExpectedTest, error__takeOr)
+{
+       auto expected =
+               Expected<std::string, TestError>(TestError::Semantic, "error message");
+       EXPECT_EQ(expected.takeOr(std::string{"default text"}), "default text");
 }
 
-GTEST_TEST(ExpectedTest, error__takeOr_with_user_defined_class) {
-  class SomeTestClass {
-   public:
-    explicit SomeTestClass(const std::string& prefix, const std::string& sufix)
-        : text{prefix + " - " + sufix} {}
-
-    std::string text;
-  };
-  auto callable = []() -> Expected<SomeTestClass, TestError> {
-    return createError(TestError::Semantic) << "error message";
-  };
-  EXPECT_EQ(callable().takeOr(SomeTestClass("427 BC", "347 BC")).text,
-            "427 BC - 347 BC");
+GTEST_TEST(ExpectedTest, error__takeOr_with_user_defined_class)
+{
+       class SomeTestClass {
+       public:
+               explicit SomeTestClass(const std::string& prefix, const std::string& sufix)
+                       : text{prefix + " - " + sufix} {}
+
+               std::string text;
+       };
+       auto callable = []() -> Expected<SomeTestClass, TestError> {
+               return createError(TestError::Semantic) << "error message";
+       };
+       EXPECT_EQ(callable().takeOr(SomeTestClass("427 BC", "347 BC")).text,
+                         "427 BC - 347 BC");
 }
 
-GTEST_TEST(ExpectedTest, value_takeOr_with_rvalue_as_an_argument) {
-  auto value = int{312};
-  auto callable = []() -> Expected<int, TestError> { return 306; };
-  value = callable().takeOr(value);
-  EXPECT_EQ(value, 306);
+GTEST_TEST(ExpectedTest, value_takeOr_with_rvalue_as_an_argument)
+{
+       auto value = int{312};
+       auto callable = []() -> Expected<int, TestError> { return 306; };
+       value = callable().takeOr(value);
+       EXPECT_EQ(value, 306);
 }
 
-GTEST_TEST(ExpectedTest, error_takeOr_with_rvalue_as_an_argument) {
-  auto value = int{312};
-  auto callable = []() -> Expected<int, TestError> {
-    return createError(TestError::Logical) << "error message";
-  };
-  value = callable().takeOr(value);
-  EXPECT_EQ(value, 312);
+GTEST_TEST(ExpectedTest, error_takeOr_with_rvalue_as_an_argument)
+{
+       auto value = int{312};
+       auto callable = []() -> Expected<int, TestError> {
+               return createError(TestError::Logical) << "error message";
+       };
+       value = callable().takeOr(value);
+       EXPECT_EQ(value, 312);
 }
 
 } // namespace osquery
index 55f3f4d1ab90fa1a14623bf2ac46b9528a224d2f..72bd550e1220bc3091b001909e3773600cb895eb 100644 (file)
@@ -17,25 +17,25 @@ namespace osquery {
  * their's as default.
  */
 class only_movable {
- protected:
-  /// Boilerplate self default constructor.
-  only_movable() = default;
+protected:
+       /// Boilerplate self default constructor.
+       only_movable() = default;
 
-  /// Boilerplate self destructor.
-  ~only_movable() = default;
+       /// Boilerplate self destructor.
+       ~only_movable() = default;
 
-  /// Boilerplate move constructor.
-  only_movable(only_movable&&) noexcept = default;
+       /// Boilerplate move constructor.
+       only_movable(only_movable&&) noexcept = default;
 
-  /// Boilerplate move assignment.
-  only_movable& operator=(only_movable&&) = default;
+       /// Boilerplate move assignment.
+       only_movable& operator=(only_movable&&) = default;
 
- public:
-  /// Important, a private copy constructor prevents copying.
-  only_movable(const only_movable&) = delete;
+public:
+       /// Important, a private copy constructor prevents copying.
+       only_movable(const only_movable&) = delete;
 
-  /// Important, a private copy assignment constructor prevents copying.
-  only_movable& operator=(const only_movable&) = delete;
+       /// Important, a private copy assignment constructor prevents copying.
+       only_movable& operator=(const only_movable&) = delete;
 };
 
 } // namespace osquery
index 725f5d1e144c11869edbc2bdb75544a33ee08dc5..fa27967b66fd0496c0d891bcc14f372c804b2f19 100644 (file)
@@ -14,15 +14,17 @@ namespace osquery {
 
 constexpr int Status::kSuccessCode;
 
-Status Status::failure(int code, std::string message) {
-  assert(code != Status::kSuccessCode &&
-         "Using 'failure' to create Status object with a kSuccessCode");
-  return Status(code, std::move(message));
+Status Status::failure(int code, std::string message)
+{
+       assert(code != Status::kSuccessCode &&
+                  "Using 'failure' to create Status object with a kSuccessCode");
+       return Status(code, std::move(message));
 }
 
-::std::ostream& operator<<(::std::ostream& os, const Status& s) {
-  return os << "Status(" << s.getCode() << R"(, ")" << s.getMessage()
-            << R"("))";
+::std::ostream& operator<<(::std::ostream& os, const Status& s)
+{
+       return os << "Status(" << s.getCode() << R"(, ")" << s.getMessage()
+                  << R"("))";
 }
 
 } // namespace osquery
index f78f0c1f2ebf4d8391a3cf02c0aae73d9acf51cf..d0bcb263de50e98216e12f24d96530b7eb8ca369 100644 (file)
@@ -31,141 +31,152 @@ namespace osquery {
  */
 
 class Status {
- public:
-  static constexpr int kSuccessCode = 0;
-  /**
-   * @brief Default constructor
-   *
-   * Note that the default constructor initialized an osquery::Status instance
-   * to a state such that a successful operation is indicated.
-   */
-  explicit Status(int c = Status::kSuccessCode) : code_(c), message_("OK") {}
-
-  /**
-   * @brief A constructor which can be used to concisely express the status of
-   * an operation.
-   *
-   * @param c a status code. The idiom is that a zero status code indicates a
-   * successful operation and a non-zero status code indicates a failed
-   * operation.
-   * @param m a message indicating some extra detail regarding the operation.
-   * If all operations were successful, this message should be "OK".
-   * Otherwise, it doesn't matter what the string is, as long as both the
-   * setter and caller agree.
-   */
-  Status(int c, std::string m) : code_(c), message_(std::move(m)) {}
-
-  Status(const ErrorBase& error) : code_(1), message_(error.getMessage()) {}
-
- public:
-  /**
-   * @brief A getter for the status code property
-   *
-   * @return an integer representing the status code of the operation.
-   */
-  int getCode() const {
-    return code_;
-  }
-
-  /**
-   * @brief A getter for the message property
-   *
-   * @return a string representing arbitrary additional information about the
-   * success or failure of an operation. On successful operations, the idiom
-   * is for the message to be "OK"
-   */
-  std::string getMessage() const {
-    return message_;
-  }
-
-  /**
-   * @brief A convenience method to check if the return code is
-   * Status::kSuccessCode
-   *
-   * @code{.cpp}
-   *   auto s = doSomething();
-   *   if (s.ok()) {
-   *     LOG(INFO) << "doing work";
-   *   } else {
-   *     LOG(ERROR) << s.toString();
-   *   }
-   * @endcode
-   *
-   * @return a boolean which is true if the status code is Status::kSuccessCode,
-   * false otherwise.
-   */
-  bool ok() const {
-    return getCode() == Status::kSuccessCode;
-  }
-
-  /**
-   * @brief A synonym for osquery::Status::getMessage()
-   *
-   * @see getMessage()
-   */
-  std::string toString() const {
-    return getMessage();
-  }
-  std::string what() const {
-    return getMessage();
-  }
-
-  /**
-   * @brief implicit conversion to bool
-   *
-   * Allows easy use of Status in an if statement, as below:
-   *
-   * @code{.cpp}
-   *   if (doSomethingThatReturnsStatus()) {
-   *     LOG(INFO) << "Success!";
-   *   }
-   * @endcode
-   */
-  /* explicit */ explicit operator bool() const {
-    return ok();
-  }
-
-  static Status success() {
-    return Status(kSuccessCode);
-  }
-
-  static Status failure(std::string message) {
-    return Status(1, std::move(message));
-  }
-
-  static Status failure(int code, std::string message);
-
-  // Below operator implementations useful for testing with gtest
-
-  // Enables use of gtest (ASSERT|EXPECT)_EQ
-  bool operator==(const Status& rhs) const {
-    return (code_ == rhs.getCode()) && (message_ == rhs.getMessage());
-  }
-
-  // Enables use of gtest (ASSERT|EXPECT)_NE
-  bool operator!=(const Status& rhs) const {
-    return !operator==(rhs);
-  }
-
-  // Enables pretty-printing in gtest (ASSERT|EXPECT)_(EQ|NE)
-  friend ::std::ostream& operator<<(::std::ostream& os, const Status& s);
-
- private:
-  /// the internal storage of the status code
-  int code_;
-
-  /// the internal storage of the status message
-  std::string message_;
+public:
+       static constexpr int kSuccessCode = 0;
+       /**
+        * @brief Default constructor
+        *
+        * Note that the default constructor initialized an osquery::Status instance
+        * to a state such that a successful operation is indicated.
+        */
+       explicit Status(int c = Status::kSuccessCode) : code_(c), message_("OK") {}
+
+       /**
+        * @brief A constructor which can be used to concisely express the status of
+        * an operation.
+        *
+        * @param c a status code. The idiom is that a zero status code indicates a
+        * successful operation and a non-zero status code indicates a failed
+        * operation.
+        * @param m a message indicating some extra detail regarding the operation.
+        * If all operations were successful, this message should be "OK".
+        * Otherwise, it doesn't matter what the string is, as long as both the
+        * setter and caller agree.
+        */
+       Status(int c, std::string m) : code_(c), message_(std::move(m)) {}
+
+       Status(const ErrorBase& error) : code_(1), message_(error.getMessage()) {}
+
+public:
+       /**
+        * @brief A getter for the status code property
+        *
+        * @return an integer representing the status code of the operation.
+        */
+       int getCode() const
+       {
+               return code_;
+       }
+
+       /**
+        * @brief A getter for the message property
+        *
+        * @return a string representing arbitrary additional information about the
+        * success or failure of an operation. On successful operations, the idiom
+        * is for the message to be "OK"
+        */
+       std::string getMessage() const
+       {
+               return message_;
+       }
+
+       /**
+        * @brief A convenience method to check if the return code is
+        * Status::kSuccessCode
+        *
+        * @code{.cpp}
+        *   auto s = doSomething();
+        *   if (s.ok()) {
+        *     LOG(INFO) << "doing work";
+        *   } else {
+        *     LOG(ERROR) << s.toString();
+        *   }
+        * @endcode
+        *
+        * @return a boolean which is true if the status code is Status::kSuccessCode,
+        * false otherwise.
+        */
+       bool ok() const
+       {
+               return getCode() == Status::kSuccessCode;
+       }
+
+       /**
+        * @brief A synonym for osquery::Status::getMessage()
+        *
+        * @see getMessage()
+        */
+       std::string toString() const
+       {
+               return getMessage();
+       }
+       std::string what() const
+       {
+               return getMessage();
+       }
+
+       /**
+        * @brief implicit conversion to bool
+        *
+        * Allows easy use of Status in an if statement, as below:
+        *
+        * @code{.cpp}
+        *   if (doSomethingThatReturnsStatus()) {
+        *     LOG(INFO) << "Success!";
+        *   }
+        * @endcode
+        */
+       /* explicit */ explicit operator bool() const
+       {
+               return ok();
+       }
+
+       static Status success()
+       {
+               return Status(kSuccessCode);
+       }
+
+       static Status failure(std::string message)
+       {
+               return Status(1, std::move(message));
+       }
+
+       static Status failure(int code, std::string message);
+
+       // Below operator implementations useful for testing with gtest
+
+       // Enables use of gtest (ASSERT|EXPECT)_EQ
+       bool operator==(const Status& rhs) const
+       {
+               return (code_ == rhs.getCode()) && (message_ == rhs.getMessage());
+       }
+
+       // Enables use of gtest (ASSERT|EXPECT)_NE
+       bool operator!=(const Status& rhs) const
+       {
+               return !operator==(rhs);
+       }
+
+       // Enables pretty-printing in gtest (ASSERT|EXPECT)_(EQ|NE)
+       friend ::std::ostream& operator<<(::std::ostream& os, const Status& s);
+
+private:
+       /// the internal storage of the status code
+       int code_;
+
+       /// the internal storage of the status message
+       std::string message_;
 };
 
 ::std::ostream& operator<<(::std::ostream& os, const Status& s);
 
 template <typename ToType, typename ValueType, typename ErrorCodeEnumType>
 inline
-    typename std::enable_if<std::is_same<ToType, Status>::value, Status>::type
-    to(const Expected<ValueType, ErrorCodeEnumType>& expected) {
-  return expected ? Status::success()
-                  : Status::failure(expected.getError().getMessage());
+typename std::enable_if<std::is_same<ToType, Status>::value, Status>::type
+to(const Expected<ValueType, ErrorCodeEnumType>& expected)
+{
+       return expected ? Status::success()
+                  : Status::failure(expected.getError().getMessage());
 }
 
 } // namespace osquery
index 99f599ca65e64fc65cae1005cca25c80d7038a88..5b4211e01a47cf62e96c96f0919a23fae62dc6c1 100644 (file)
@@ -16,89 +16,102 @@ namespace osquery {
 
 class StatusTests : public testing::Test {};
 
-TEST_F(StatusTests, test_constructor) {
-  auto s = Status(5, "message");
-  EXPECT_EQ(s.getCode(), 5);
-  EXPECT_EQ(s.getMessage(), "message");
+TEST_F(StatusTests, test_constructor)
+{
+       auto s = Status(5, "message");
+       EXPECT_EQ(s.getCode(), 5);
+       EXPECT_EQ(s.getMessage(), "message");
 }
 
-TEST_F(StatusTests, test_constructor_2) {
-  Status s;
-  EXPECT_EQ(s.getCode(), 0);
-  EXPECT_EQ(s.getMessage(), "OK");
+TEST_F(StatusTests, test_constructor_2)
+{
+       Status s;
+       EXPECT_EQ(s.getCode(), 0);
+       EXPECT_EQ(s.getMessage(), "OK");
 }
 
-TEST_F(StatusTests, test_ok) {
-  auto s1 = Status(5, "message");
-  EXPECT_FALSE(s1.ok());
-  auto s2 = Status(0, "message");
-  EXPECT_TRUE(s2.ok());
+TEST_F(StatusTests, test_ok)
+{
+       auto s1 = Status(5, "message");
+       EXPECT_FALSE(s1.ok());
+       auto s2 = Status(0, "message");
+       EXPECT_TRUE(s2.ok());
 }
 
-TEST_F(StatusTests, test_to_string) {
-  auto s = Status(0, "foobar");
-  EXPECT_EQ(s.toString(), "foobar");
+TEST_F(StatusTests, test_to_string)
+{
+       auto s = Status(0, "foobar");
+       EXPECT_EQ(s.toString(), "foobar");
 }
 
-TEST_F(StatusTests, test_default_constructor) {
-  auto s = Status{};
-  EXPECT_TRUE(s.ok());
+TEST_F(StatusTests, test_default_constructor)
+{
+       auto s = Status{};
+       EXPECT_TRUE(s.ok());
 }
 
-TEST_F(StatusTests, test_success_code) {
-  auto s = Status(Status::kSuccessCode);
-  EXPECT_TRUE(s.ok());
+TEST_F(StatusTests, test_success_code)
+{
+       auto s = Status(Status::kSuccessCode);
+       EXPECT_TRUE(s.ok());
 }
 
-TEST_F(StatusTests, test_success) {
-  auto s = Status::success();
-  EXPECT_TRUE(s.ok());
+TEST_F(StatusTests, test_success)
+{
+       auto s = Status::success();
+       EXPECT_TRUE(s.ok());
 }
 
-TEST_F(StatusTests, test_failure_single_arg) {
-  auto s = Status::failure("Some proper error message.");
-  EXPECT_EQ(s.toString(), "Some proper error message.");
-  EXPECT_FALSE(s.ok());
+TEST_F(StatusTests, test_failure_single_arg)
+{
+       auto s = Status::failure("Some proper error message.");
+       EXPECT_EQ(s.toString(), "Some proper error message.");
+       EXPECT_FALSE(s.ok());
 }
 
-TEST_F(StatusTests, test_failure_double_arg) {
-  auto s = Status::failure(105, "One more proper error message!");
-  EXPECT_EQ(s.toString(), "One more proper error message!");
-  EXPECT_FALSE(s.ok());
+TEST_F(StatusTests, test_failure_double_arg)
+{
+       auto s = Status::failure(105, "One more proper error message!");
+       EXPECT_EQ(s.toString(), "One more proper error message!");
+       EXPECT_FALSE(s.ok());
 }
 
-TEST_F(StatusTests, test_failure_with_success_code) {
+TEST_F(StatusTests, test_failure_with_success_code)
+{
 #ifndef NDEBUG
-  ASSERT_DEATH(Status::failure(Status::kSuccessCode, "message"),
-               "Using 'failure' to create Status object with a kSuccessCode");
+       ASSERT_DEATH(Status::failure(Status::kSuccessCode, "message"),
+                                "Using 'failure' to create Status object with a kSuccessCode");
 #endif
 }
 
 namespace {
 
 enum class TestError {
-  Semantic = 1,
+       Semantic = 1,
 };
 
-bool stringContains(const std::string& where, const std::string& what) {
-  return boost::contains(where, what);
+bool stringContains(const std::string& where, const std::string& what)
+{
+       return boost::contains(where, what);
 };
 
 } // namespace
 
-TEST_F(StatusTests, test_expected_to_status_failure) {
-  const auto expected = Expected<std::string, TestError>(
-      TestError::Semantic, "The ultimate failure reason");
-  auto s = to<Status>(expected);
-  EXPECT_FALSE(s.ok());
-  EXPECT_PRED2(stringContains, s.toString(), "The ultimate failure reason");
+TEST_F(StatusTests, test_expected_to_status_failure)
+{
+       const auto expected = Expected<std::string, TestError>(
+                                                         TestError::Semantic, "The ultimate failure reason");
+       auto s = to<Status>(expected);
+       EXPECT_FALSE(s.ok());
+       EXPECT_PRED2(stringContains, s.toString(), "The ultimate failure reason");
 }
 
-TEST_F(StatusTests, test_expected_to_status_success) {
-  const auto expected =
-      Expected<std::string, TestError>("This is not a failure");
-  auto s = to<Status>(expected);
-  EXPECT_TRUE(s.ok());
-  EXPECT_EQ(s, Status::success());
+TEST_F(StatusTests, test_expected_to_status_success)
+{
+       const auto expected =
+               Expected<std::string, TestError>("This is not a failure");
+       auto s = to<Status>(expected);
+       EXPECT_TRUE(s.ok());
+       EXPECT_EQ(s, Status::success());
 }
 }
index c86b5021a6b252be824f554b61664215a86e4001..6e878bc3dfbc3749279baebaef376b3313e83acb 100644 (file)
 
 namespace osquery {
 
-bool setEnvVar(const std::string& name, const std::string& value) {
-  auto ret = ::setenv(name.c_str(), value.c_str(), 1);
-  return (ret == 0);
+bool setEnvVar(const std::string& name, const std::string& value)
+{
+       auto ret = ::setenv(name.c_str(), value.c_str(), 1);
+       return (ret == 0);
 }
 
-bool unsetEnvVar(const std::string& name) {
-  auto ret = ::unsetenv(name.c_str());
-  return (ret == 0);
+bool unsetEnvVar(const std::string& name)
+{
+       auto ret = ::unsetenv(name.c_str());
+       return (ret == 0);
 }
 
-boost::optional<std::string> getEnvVar(const std::string& name) {
-  char* value = ::getenv(name.c_str());
-  if (value) {
-    return std::string(value);
-  }
-  return boost::none;
+boost::optional<std::string> getEnvVar(const std::string& name)
+{
+       char* value = ::getenv(name.c_str());
+       if (value) {
+               return std::string(value);
+       }
+       return boost::none;
 }
 
 } // namespace osquery
index aa82abde9633ed509b7c66e5adbea0ef7d71d249..d86ce2efc0f72d39bca7bbbf3fd7a16cd91ea7a4 100644 (file)
 
 namespace osquery {
 
-std::string platformStrerr(int errnum) {
-  return ::strerror(errnum);
+std::string platformStrerr(int errnum)
+{
+       return ::strerror(errnum);
 }
 
 namespace impl {
 
-PosixError toPosixSystemError(int from_errno) {
-  static auto const table = std::unordered_map<int, PosixError>{
-      {EPERM, PosixError::PERM},     {ENOENT, PosixError::NOENT},
-      {ESRCH, PosixError::SRCH},     {EINTR, PosixError::INTR},
-      {EIO, PosixError::IO},         {ENXIO, PosixError::NXIO},
-      {E2BIG, PosixError::T_BIG},    {ENOEXEC, PosixError::NOEXEC},
-      {EBADF, PosixError::BADF},     {ECHILD, PosixError::CHILD},
-      {EAGAIN, PosixError::AGAIN},   {ENOMEM, PosixError::NOMEM},
-      {EACCES, PosixError::ACCES},   {EFAULT, PosixError::FAULT},
-      {ENOTBLK, PosixError::NOTBLK}, {EBUSY, PosixError::BUSY},
-      {EEXIST, PosixError::EXIST},   {EXDEV, PosixError::XDEV},
-      {ENODEV, PosixError::NODEV},   {ENOTDIR, PosixError::NOTDIR},
-      {EISDIR, PosixError::ISDIR},   {EINVAL, PosixError::INVAL},
-      {ENFILE, PosixError::NFILE},   {EMFILE, PosixError::MFILE},
-      {ENOTTY, PosixError::NOTTY},   {ETXTBSY, PosixError::TXTBSY},
-      {EFBIG, PosixError::FBIG},     {ENOSPC, PosixError::NOSPC},
-      {ESPIPE, PosixError::SPIPE},   {EROFS, PosixError::ROFS},
-      {EMLINK, PosixError::MLINK},   {EPIPE, PosixError::PIPE},
-      {EDOM, PosixError::DOM},       {ERANGE, PosixError::RANGE},
-  };
-  auto const it = table.find(from_errno);
-  if (it == table.end()) {
-    return PosixError::Unknown;
-  }
-  return it->second;
+PosixError toPosixSystemError(int from_errno)
+{
+       static auto const table = std::unordered_map<int, PosixError> {
+               {EPERM, PosixError::PERM},     {ENOENT, PosixError::NOENT},
+               {ESRCH, PosixError::SRCH},     {EINTR, PosixError::INTR},
+               {EIO, PosixError::IO},         {ENXIO, PosixError::NXIO},
+               {E2BIG, PosixError::T_BIG},    {ENOEXEC, PosixError::NOEXEC},
+               {EBADF, PosixError::BADF},     {ECHILD, PosixError::CHILD},
+               {EAGAIN, PosixError::AGAIN},   {ENOMEM, PosixError::NOMEM},
+               {EACCES, PosixError::ACCES},   {EFAULT, PosixError::FAULT},
+               {ENOTBLK, PosixError::NOTBLK}, {EBUSY, PosixError::BUSY},
+               {EEXIST, PosixError::EXIST},   {EXDEV, PosixError::XDEV},
+               {ENODEV, PosixError::NODEV},   {ENOTDIR, PosixError::NOTDIR},
+               {EISDIR, PosixError::ISDIR},   {EINVAL, PosixError::INVAL},
+               {ENFILE, PosixError::NFILE},   {EMFILE, PosixError::MFILE},
+               {ENOTTY, PosixError::NOTTY},   {ETXTBSY, PosixError::TXTBSY},
+               {EFBIG, PosixError::FBIG},     {ENOSPC, PosixError::NOSPC},
+               {ESPIPE, PosixError::SPIPE},   {EROFS, PosixError::ROFS},
+               {EMLINK, PosixError::MLINK},   {EPIPE, PosixError::PIPE},
+               {EDOM, PosixError::DOM},       {ERANGE, PosixError::RANGE},
+       };
+       auto const it = table.find(from_errno);
+       if (it == table.end()) {
+               return PosixError::Unknown;
+       }
+       return it->second;
 }
 
 } // namespace impl
index f5c285d4f8fbb8833310e75fdb3e4f81d6fd98d4..43eb0af1e116906515fec0dac7e32f6ab1fa1438 100644 (file)
 namespace osquery {
 
 enum class PosixError {
-  Unknown = 0,
-  PERM = EPERM,
-  NOENT = ENOENT,
-  SRCH = ESRCH,
-  INTR = EINTR,
-  IO = EIO,
-  NXIO = ENXIO,
-  T_BIG = E2BIG,
-  NOEXEC = ENOEXEC,
-  BADF = EBADF,
-  CHILD = ECHILD,
-  AGAIN = EAGAIN,
-  NOMEM = ENOMEM,
-  ACCES = EACCES,
-  FAULT = EFAULT,
-  NOTBLK = ENOTBLK,
-  BUSY = EBUSY,
-  EXIST = EEXIST,
-  XDEV = EXDEV,
-  NODEV = ENODEV,
-  NOTDIR = ENOTDIR,
-  ISDIR = EISDIR,
-  INVAL = EINVAL,
-  NFILE = ENFILE,
-  MFILE = EMFILE,
-  NOTTY = ENOTTY,
-  TXTBSY = ETXTBSY,
-  FBIG = EFBIG,
-  NOSPC = ENOSPC,
-  SPIPE = ESPIPE,
-  ROFS = EROFS,
-  MLINK = EMLINK,
-  PIPE = EPIPE,
-  DOM = EDOM,
-  RANGE = ERANGE,
+       Unknown = 0,
+       PERM = EPERM,
+       NOENT = ENOENT,
+       SRCH = ESRCH,
+       INTR = EINTR,
+       IO = EIO,
+       NXIO = ENXIO,
+       T_BIG = E2BIG,
+       NOEXEC = ENOEXEC,
+       BADF = EBADF,
+       CHILD = ECHILD,
+       AGAIN = EAGAIN,
+       NOMEM = ENOMEM,
+       ACCES = EACCES,
+       FAULT = EFAULT,
+       NOTBLK = ENOTBLK,
+       BUSY = EBUSY,
+       EXIST = EEXIST,
+       XDEV = EXDEV,
+       NODEV = ENODEV,
+       NOTDIR = ENOTDIR,
+       ISDIR = EISDIR,
+       INVAL = EINVAL,
+       NFILE = ENFILE,
+       MFILE = EMFILE,
+       NOTTY = ENOTTY,
+       TXTBSY = ETXTBSY,
+       FBIG = EFBIG,
+       NOSPC = ENOSPC,
+       SPIPE = ESPIPE,
+       ROFS = EROFS,
+       MLINK = EMLINK,
+       PIPE = EPIPE,
+       DOM = EDOM,
+       RANGE = ERANGE,
 };
 
 namespace impl {
@@ -60,9 +60,10 @@ PosixError toPosixSystemError(int from_errno);
 
 template <typename ToType>
 inline typename std::enable_if<std::is_same<ToType, PosixError>::value,
-                               PosixError>::type
-to(int from_errno) {
-  return impl::toPosixSystemError(from_errno);
+          PosixError>::type
+          to(int from_errno)
+{
+       return impl::toPosixSystemError(from_errno);
 }
 
 } // namespace osquery
index d017dcb22c9ef12ec8e0e1fe31a8ab921912b512..0a8c51a9c3feba2fef7c8253c5446c1e259f143d 100644 (file)
 
 namespace osquery {
 
-const std::string canonicalize_file_name(const char* name) {
+const std::string canonicalize_file_name(const char* name)
+{
 #ifdef PATH_MAX
-  // On supported platforms where PATH_MAX is defined we can pass null
-  // as buffer, and allow libc to alloced space
-  // On centos/ubuntu libc will use realloc so we will be able to resolve
-  // any path
-  // On darwin libc will allocate PATH_MAX buffer for us
-  char* resolved = realpath(name, nullptr);
-  std::string result = (resolved == nullptr) ? name : resolved;
-  free(resolved);
+       // On supported platforms where PATH_MAX is defined we can pass null
+       // as buffer, and allow libc to alloced space
+       // On centos/ubuntu libc will use realloc so we will be able to resolve
+       // any path
+       // On darwin libc will allocate PATH_MAX buffer for us
+       char* resolved = realpath(name, nullptr);
+       std::string result = (resolved == nullptr) ? name : resolved;
+       free(resolved);
 #else
 #warning PATH_MAX is undefined, please read comment below
-  // PATH_MAX is not defined, very likely it's not officially supported
-  // os, our best guess is _PC_PATH_MAX if available
-  // In case of failure fallback to "safe" buffer of 8K
+       // PATH_MAX is not defined, very likely it's not officially supported
+       // os, our best guess is _PC_PATH_MAX if available
+       // In case of failure fallback to "safe" buffer of 8K
 
-  long int path_max = pathconf(name, _PC_PATH_MAX);
-  if (path_max <= 0) {
-    path_max = 8 * 1024;
-  }
-  char* buffer = static_cast<char*>(malloc(path_max));
-  char* resolved = realpath(name, buffer);
-  std::string result = (resolved == nullptr) ? name : resolved;
-  free(buffer);
+       long int path_max = pathconf(name, _PC_PATH_MAX);
+       if (path_max <= 0) {
+               path_max = 8 * 1024;
+       }
+       char* buffer = static_cast<char*>(malloc(path_max));
+       char* resolved = realpath(name, buffer);
+       std::string result = (resolved == nullptr) ? name : resolved;
+       free(buffer);
 #endif
-  return result;
+       return result;
 }
 
 } // namespace osquery
index af2ce82cc303fcf70f02e4d3b83b1290700b0346..c08d0451368ee5fd7421ac4fc557e77656e8d932 100644 (file)
@@ -17,16 +17,17 @@ namespace {
 
 class PosixErrnoTests : public testing::Test {};
 
-TEST_F(PosixErrnoTests, to) {
-  EXPECT_EQ(PosixError::Unknown, to<PosixError>(0));
-  EXPECT_EQ(PosixError::Unknown, to<PosixError>(-1));
-  EXPECT_EQ(PosixError::Unknown, to<PosixError>(98765));
-  EXPECT_EQ(PosixError::Unknown, to<PosixError>(987654));
-
-  EXPECT_EQ(PosixError::PIPE, to<PosixError>(EPIPE));
-  EXPECT_EQ(PosixError::DOM, to<PosixError>(EDOM));
-  EXPECT_EQ(PosixError::RANGE, to<PosixError>(ERANGE));
-  EXPECT_EQ(PosixError::T_BIG, to<PosixError>(E2BIG));
+TEST_F(PosixErrnoTests, to)
+{
+       EXPECT_EQ(PosixError::Unknown, to<PosixError>(0));
+       EXPECT_EQ(PosixError::Unknown, to<PosixError>(-1));
+       EXPECT_EQ(PosixError::Unknown, to<PosixError>(98765));
+       EXPECT_EQ(PosixError::Unknown, to<PosixError>(987654));
+
+       EXPECT_EQ(PosixError::PIPE, to<PosixError>(EPIPE));
+       EXPECT_EQ(PosixError::DOM, to<PosixError>(EDOM));
+       EXPECT_EQ(PosixError::RANGE, to<PosixError>(ERANGE));
+       EXPECT_EQ(PosixError::T_BIG, to<PosixError>(E2BIG));
 }
 
 } // namespace
index fa3d889d3cead5921b0820786d596098559735bf..24fbfa112bbe8d4d50bddd6edca61d5aaefdafe6 100644 (file)
 
 namespace osquery {
 
-std::string platformAsctime(const struct tm* timeptr) {
-  if (timeptr == nullptr) {
-    return "";
-  }
+std::string platformAsctime(const struct tm* timeptr)
+{
+       if (timeptr == nullptr) {
+               return "";
+       }
 
-  // Manual says at least 26 characters.
-  char buffer[32] = {0};
-  return ::asctime_r(timeptr, buffer);
+       // Manual says at least 26 characters.
+       char buffer[32] = {0};
+       return ::asctime_r(timeptr, buffer);
 }
 
 } // namespace osquery
index c5f366d79c14afea748254b38c7878be166cc754..c6683628a1b4608d471cc6c028ff688d2e49bbda 100644 (file)
@@ -14,21 +14,23 @@ namespace osquery {
 
 class TimeTests : public testing::Test {};
 
-TEST_F(TimeTests, test_asciitime) {
-  const std::time_t epoch = 1491518994;
-  const std::string expected = "Thu Apr  6 22:49:54 2017 UTC";
+TEST_F(TimeTests, test_asciitime)
+{
+       const std::time_t epoch = 1491518994;
+       const std::string expected = "Thu Apr  6 22:49:54 2017 UTC";
 
-  auto const result = std::gmtime(&epoch);
+       auto const result = std::gmtime(&epoch);
 
-  EXPECT_EQ(expected, toAsciiTime(result));
+       EXPECT_EQ(expected, toAsciiTime(result));
 }
 
-TEST_F(TimeTests, test_asciitimeutc) {
-  const std::time_t epoch = 1491518994;
-  const std::string expected = "Thu Apr  6 22:49:54 2017 UTC";
+TEST_F(TimeTests, test_asciitimeutc)
+{
+       const std::time_t epoch = 1491518994;
+       const std::string expected = "Thu Apr  6 22:49:54 2017 UTC";
 
-  auto const result = std::localtime(&epoch);
+       auto const result = std::localtime(&epoch);
 
-  EXPECT_EQ(expected, toAsciiTimeUTC(result));
+       EXPECT_EQ(expected, toAsciiTimeUTC(result));
 }
 }
index 73abaa26b09234fa54e7d2662838ce9c1cda08c7..f45ae5cc27c6a02dc321b21554e60cbdb57fe6a7 100644 (file)
 
 namespace osquery {
 
-std::string toAsciiTime(const struct tm* tm_time) {
-  if (tm_time == nullptr) {
-    return "";
-  }
-
-  auto time_str = platformAsctime(tm_time);
-  boost::algorithm::trim(time_str);
-  return time_str + " UTC";
+std::string toAsciiTime(const struct tm* tm_time)
+{
+       if (tm_time == nullptr) {
+               return "";
+       }
+
+       auto time_str = platformAsctime(tm_time);
+       boost::algorithm::trim(time_str);
+       return time_str + " UTC";
 }
 
-std::string toAsciiTimeUTC(const struct tm* tm_time) {
-  size_t epoch = toUnixTime(tm_time);
-  struct tm tptr;
+std::string toAsciiTimeUTC(const struct tm* tm_time)
+{
+       size_t epoch = toUnixTime(tm_time);
+       struct tm tptr;
 
-  std::memset(&tptr, 0, sizeof(tptr));
+       std::memset(&tptr, 0, sizeof(tptr));
 
-  if (epoch == (size_t)-1) {
-    return "";
-  }
+       if (epoch == (size_t) -1) {
+               return "";
+       }
 
 #ifdef OSQUERY_WINDOWS
-  _gmtime64_s(&tptr, (time_t*)&epoch);
+       _gmtime64_s(&tptr, (time_t*)&epoch);
 #else
-  gmtime_r((time_t*)&epoch, &tptr);
+       gmtime_r((time_t*)&epoch, &tptr);
 #endif
-  return toAsciiTime(&tptr);
+       return toAsciiTime(&tptr);
 }
 
-std::string getAsciiTime() {
-  auto result = std::time(nullptr);
+std::string getAsciiTime()
+{
+       auto result = std::time(nullptr);
 
-  struct tm now;
+       struct tm now;
 #ifdef OSQUERY_WINDOWS
-  _gmtime64_s(&now, &result);
+       _gmtime64_s(&now, &result);
 #else
-  gmtime_r(&result, &now);
+       gmtime_r(&result, &now);
 #endif
 
-  return toAsciiTime(&now);
+       return toAsciiTime(&now);
 }
 
-size_t toUnixTime(const struct tm* tm_time) {
-  struct tm result;
-  std::memset(&result, 0, sizeof(result));
+size_t toUnixTime(const struct tm* tm_time)
+{
+       struct tm result;
+       std::memset(&result, 0, sizeof(result));
 
-  std::memcpy(&result, tm_time, sizeof(result));
-  return mktime(&result);
+       std::memcpy(&result, tm_time, sizeof(result));
+       return mktime(&result);
 }
 
-size_t getUnixTime() {
-  std::time_t ut = std::time(nullptr);
-  return ut < 0 ? 0 : ut;
+size_t getUnixTime()
+{
+       std::time_t ut = std::time(nullptr);
+       return ut < 0 ? 0 : ut;
 }
 
 } // namespace osquery