--- /dev/null
+#include "storage_backend_serialized.hpp"
+#include "print_content.hpp"
+#include "serialized_convert.hpp"
+#include "tslog.hpp"
+
+#include "include/fb_generated.h"
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <boost/tokenizer.hpp>
+
+#include <cerrno>
+#include <cstring>
+
+using namespace FB;
+
+namespace ldp_serialized {
+
+class StorageBackendSerialized::StorageBackendSerializedImpl {
+ int fd{-1};
+ uint8_t *mem{nullptr};
+ size_t length{0};
+ const FB::File *file;
+public:
+ void init(const char *filename);
+ void release();
+
+ void printContent() const;
+
+ template <typename T>
+ T *getPolicySet();
+};
+
+void StorageBackendSerialized::StorageBackendSerializedImpl::release() {
+ if (nullptr != mem) {
+ if (munmap(mem, length) != 0)
+ tslog::log("munmap(): ", strerror(errno), "\n");
+ mem = nullptr;
+ length = 0;
+ }
+
+ if (-1 != fd) {
+ if (close(fd) != 0)
+ tslog::log("close(): ", strerror(errno), "\n");
+ fd = -1;
+ }
+
+ file = nullptr;
+}
+
+void StorageBackendSerialized::StorageBackendSerializedImpl::init(const char *filename) {
+ auto err = [filename] (const char *what) {
+ tslog::log("Can't ", what, " ", filename, ": ", strerror(errno), "\n");
+ };
+
+ fd = open(filename, O_RDONLY);
+ if (-1 == fd) {
+ err("open");
+ return;
+ }
+
+ struct stat buf;
+
+ if (fstat(fd, &buf) == -1) {
+ err("stat");
+ close(fd);
+ return;
+ }
+
+ length = buf.st_size;
+
+ mem = reinterpret_cast<uint8_t*>(mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0));
+ if (MAP_FAILED == mem) {
+ err("mmap");
+ close(fd);
+ return;
+ }
+// for verification:
+//
+// if (!VerifyFileBuffer(Verifier(mem, length)))
+// bailout();
+//
+ file = GetFile(mem);
+}
+
+void StorageBackendSerialized::StorageBackendSerializedImpl::printContent() const {
+ std::cerr << *file;
+}
+
+/*************************************************/
+template <typename T>
+struct type_helper;
+
+#define TYPE_HELPER(T, t) \
+ template <> \
+ struct type_helper<const ldp_xml_parser::MatchItem##T> { \
+ typedef FB::T##Set policy_set_type; \
+ typedef FB::Policy##T policy_type; \
+ }; \
+ template <> \
+ auto StorageBackendSerialized::StorageBackendSerializedImpl::getPolicySet() \
+ -> const typename type_helper<const ldp_xml_parser::MatchItem##T>::policy_set_type * { \
+ assert(file); \
+ return file->m_##t##_set(); \
+ }
+
+TYPE_HELPER(Own, own)
+TYPE_HELPER(Send, send)
+TYPE_HELPER(Receive, receive)
+TYPE_HELPER(Access, access)
+
+void StorageBackendSerialized::init(const char *filename) {
+ pimpl->init(filename);
+}
+
+void StorageBackendSerialized::release() {
+ pimpl->release();
+}
+
+void StorageBackendSerialized::printContent() const {
+ pimpl->printContent();
+}
+
+template <typename T, typename I>
+bool match(const T &t, const I *i) {
+ // TODO!!!!
+ return true;
+}
+
+template <typename T, typename P = typename type_helper<T>::policy_type>
+ldp_xml_parser::DecisionItem getDecisionItem(const T &item, const P *policy) {
+ const auto *v = policy->items();
+ for (auto it = v->rbegin(); it != v->rend(); ++it) {
+ if (match(item, *it))
+ return makeDecisionItem((*it)->decision());
+ }
+ return ldp_xml_parser::Decision::ANY;
+}
+
+typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
+
+const DecisionItem *getDecisionItemFromTree(const FB::PolicyOwnNode *node,
+ tokenizer &tokens,
+ tokenizer::iterator &iterator) {
+ if (iterator == tokens.end()) {
+ if (node->decision_item()->decision() != Decision_ANY)
+ return node->decision_item();
+ else
+ return node->prefix_decision_item();
+ }
+
+ auto child = node->children()->LookupByKey(iterator->c_str());
+ if (nullptr == child)
+ return node->prefix_decision_item();
+
+ ++iterator;
+ const DecisionItem *child_decision = getDecisionItemFromTree(child, tokens, iterator);
+ if (child_decision->decision() == Decision_ANY)
+ return node->prefix_decision_item();
+
+ return child_decision;
+}
+
+template <> ldp_xml_parser::DecisionItem getDecisionItem(const ldp_xml_parser::MatchItemOwn &item,
+ const PolicyOwn *policy) {
+ if (item.getName().length() == 0)
+ return ldp_xml_parser::Decision::DENY;
+
+ boost::char_separator<char> separator(".");
+ tokenizer tokens(item.getName(), separator);
+
+ auto node = policy->tree();
+ if (nullptr == node)
+ return ldp_xml_parser::Decision::ANY;
+
+ auto iterator = tokens.begin();
+
+ return makeDecisionItem(getDecisionItemFromTree(node, tokens, iterator));
+}
+
+template <typename T, typename P = typename type_helper<T>::policy_type>
+ldp_xml_parser::DecisionItem getDecisionItemMaybeNull(const T &item, const P *policy) {
+ if (nullptr == policy)
+ return ldp_xml_parser::Decision::ANY;
+ return getDecisionItem(item, policy);
+}
+
+template <typename T>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextMandatory(const T &item) const {
+ return getDecisionItem(item, pimpl->getPolicySet<T>()->context_mandatory());
+}
+
+template <typename T>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextDefault(const T &item) const {
+ return getDecisionItem(item, pimpl->getPolicySet<T>()->context_default());
+}
+
+template <typename T>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemUser(uid_t uid, const T &item) const {
+ return getDecisionItemMaybeNull(item, pimpl->getPolicySet<T>()->user()->LookupByKey(uid));
+}
+
+template <typename T>
+ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemGroup(gid_t gid, const T &item) const {
+ return getDecisionItemMaybeNull(item, pimpl->getPolicySet<T>()->group()->LookupByKey(gid));
+}
+
+#define T_INSTANTIATION(T) \
+ template <> ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextMandatory(const ldp_xml_parser::MatchItem##T &item) const; \
+ template <> ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextDefault(const ldp_xml_parser::MatchItem##T &item) const;
+
+T_INSTANTIATION(Own)
+T_INSTANTIATION(Send)
+T_INSTANTIATION(Receive)
+T_INSTANTIATION(Access)
+
+#define T_INSTANTIATION2(T) \
+ template <> ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemUser(uid_t uid, const ldp_xml_parser::MatchItem##T &item) const; \
+ template <> ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemGroup(gid_t gid, const ldp_xml_parser::MatchItem##T &item) const;
+
+T_INSTANTIATION2(Own)
+T_INSTANTIATION2(Send)
+T_INSTANTIATION2(Receive)
+
+#undef T_INSTANTIATION
+#undef T_INSTANTIATION2
+
+StorageBackendSerialized::StorageBackendSerialized()
+ : pimpl{new StorageBackendSerializedImpl} {
+}
+
+StorageBackendSerialized::~StorageBackendSerialized() {
+ pimpl->release();
+}
+
+}