2014-09-15 20:37:20 +00:00
|
|
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
2014-07-31 00:35:19 +00:00
|
|
|
|
2014-09-10 01:54:53 +00:00
|
|
|
#pragma once
|
2014-07-31 00:35:19 +00:00
|
|
|
|
|
|
|
#include <functional>
|
|
|
|
#include <string>
|
|
|
|
#include <unordered_map>
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
#include <glog/logging.h>
|
|
|
|
|
|
|
|
#include "osquery/registry/init_registry.h"
|
|
|
|
#include "osquery/registry/singleton.h"
|
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
|
2014-09-16 07:28:23 +00:00
|
|
|
/**
|
|
|
|
* @brief A simple registry system for making values available by key across
|
|
|
|
* components.
|
2014-09-15 20:09:16 +00:00
|
|
|
*
|
2014-09-16 07:28:23 +00:00
|
|
|
* To use this registry, make a header like so:
|
2014-09-15 20:09:16 +00:00
|
|
|
*
|
2014-09-16 07:28:23 +00:00
|
|
|
* @code{.cpp}
|
|
|
|
* #include "osquery/registry.h"
|
2014-09-15 20:09:16 +00:00
|
|
|
*
|
2014-09-16 07:28:23 +00:00
|
|
|
* DECLARE_REGISTRY(MathFuncs, int, std::function<double(double)>)
|
|
|
|
* #define REGISTERED_MATH_FUNCS REGISTRY(MathFuncs)
|
|
|
|
* #define REGISTER_MATH_FUNC(id, func) \
|
|
|
|
* REGISTER(MathFuncs, id, func)
|
|
|
|
* @endcode
|
2014-09-15 20:09:16 +00:00
|
|
|
*
|
|
|
|
* Client code may then advertise an entry from a .cpp like so:
|
|
|
|
*
|
|
|
|
* @code{.cpp}
|
|
|
|
* #include "my/registry/header.h"
|
|
|
|
* REGISTER_MATH_FUNC(1, sqrt);
|
|
|
|
* @endcode
|
|
|
|
*
|
|
|
|
* Server code may then access the set of registered values by using
|
|
|
|
* `REGISTERED_MATH_FUNCS` as a map, which will be populated after
|
|
|
|
* `osquery::InitRegistry::get().run()` has been called.
|
|
|
|
*/
|
2014-08-15 07:25:30 +00:00
|
|
|
template <class Key, class Value>
|
2014-07-31 00:35:19 +00:00
|
|
|
class Registry : public std::unordered_map<Key, Value> {
|
|
|
|
public:
|
2014-09-16 07:28:23 +00:00
|
|
|
/**
|
|
|
|
* @brief Register a value in the global registry
|
2014-09-15 20:09:16 +00:00
|
|
|
*
|
2014-09-16 07:28:23 +00:00
|
|
|
* This is used internally by the `DECLARE_REGISTRY` registration workflow.
|
|
|
|
* If you're calling this method directly, you're probably doing something
|
|
|
|
* incorrectly.
|
2014-09-15 20:09:16 +00:00
|
|
|
*/
|
2014-08-15 07:25:30 +00:00
|
|
|
void registerValue(const Key& key,
|
|
|
|
const Value& value,
|
2014-07-31 00:35:19 +00:00
|
|
|
const char* displayName = "registry") {
|
|
|
|
if (this->insert(std::make_pair(key, value)).second) {
|
2014-08-15 07:25:30 +00:00
|
|
|
VLOG(1) << displayName << "[" << key << "]"
|
|
|
|
<< " registered";
|
2014-07-31 00:35:19 +00:00
|
|
|
} else {
|
2014-08-15 07:25:30 +00:00
|
|
|
LOG(ERROR) << displayName << "[" << key << "]"
|
|
|
|
<< " already registered";
|
2014-07-31 00:35:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2014-08-15 07:25:30 +00:00
|
|
|
#define DECLARE_REGISTRY(registryName, KeyType, ObjectType) \
|
|
|
|
namespace osquery { \
|
|
|
|
namespace registries { \
|
|
|
|
class registryName : public Registry<KeyType, ObjectType> {}; \
|
|
|
|
} \
|
2014-09-15 20:37:20 +00:00
|
|
|
}
|
2014-07-31 00:35:19 +00:00
|
|
|
|
|
|
|
#define REGISTRY(registryName) \
|
|
|
|
(osquery::Singleton<osquery::registries::registryName>::get())
|
|
|
|
|
|
|
|
#ifndef UNIQUE_VAR
|
|
|
|
#define UNIQUE_VAR_CONCAT(_name_, _line_) _name_##_line_
|
|
|
|
#define UNIQUE_VAR_LINENAME(_name_, _line_) UNIQUE_VAR_CONCAT(_name_, _line_)
|
|
|
|
#define UNIQUE_VAR(_name_) UNIQUE_VAR_LINENAME(_name_, __LINE__)
|
|
|
|
#endif
|
|
|
|
|
2014-08-15 07:25:30 +00:00
|
|
|
#define REGISTER(registryName, key, value) \
|
|
|
|
namespace {/* require global scope, don't pollute static namespace */ \
|
|
|
|
static osquery::RegisterInitFunc UNIQUE_VAR(registryName)([] { \
|
|
|
|
REGISTRY(registryName).registerValue((key), (value), #registryName); \
|
|
|
|
}); \
|
2014-07-31 00:35:19 +00:00
|
|
|
}
|