Initial commit of binary store handler.

Implement a dummy interface with TODOs.

Signed-off-by: Kun Yi <kunyi@google.com>
Change-Id: Ie58b3aa58d209063fe2af7402086a72da999fb5a
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..ea71ad6
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,99 @@
+---
+Language:        Cpp
+# BasedOnStyle:  LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: false
+AlignOperands:   true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+  AfterClass:      true
+  AfterControlStatement: true
+  AfterEnum:       true
+  AfterFunction:   true
+  AfterNamespace:  true
+  AfterObjCDeclaration: true
+  AfterStruct:     true
+  AfterUnion:      true
+  BeforeCatch:     true
+  BeforeElse:      true
+  IndentBraces:    false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: AfterColon
+ColumnLimit:     80
+CommentPragmas:  '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+PointerAlignment: Left
+DisableFormat:   false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros:   [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeBlocks: Regroup
+IncludeCategories:
+  - Regex:           '^[<"](gtest|gmock)'
+    Priority:        5
+  - Regex:           '^"config.h"'
+    Priority:        -1
+  - Regex:           '^".*\.hpp"'
+    Priority:        1
+  - Regex:           '^<.*\.h>'
+    Priority:        2
+  - Regex:           '^<.*'
+    Priority:        3
+  - Regex:           '.*'
+    Priority:        4
+IndentCaseLabels: true
+IndentWidth:     4
+IndentWrappedFunctionNames: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd:   ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+ReflowComments:  true
+SortIncludes:    true
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles:  false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard:        Cpp11
+TabWidth:        4
+UseTab:          Never
+...
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..dad7ab4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,65 @@
+# Template from:
+# https://github.com/github/gitignore/blob/master/Autotools.gitignore
+
+# http://www.gnu.org/software/automake
+
+Makefile.in
+/ar-lib
+/mdate-sh
+/py-compile
+/test-driver
+/ylwrap
+
+# http://www.gnu.org/software/autoconf
+
+/autom4te.cache
+/autoscan.log
+/autoscan-*.log
+/aclocal.m4
+/compile
+/config.guess
+/config.h.in
+/config.sub
+/configure
+/configure.scan
+/depcomp
+/install-sh
+/missing
+/stamp-h1
+/m4
+
+# https://www.gnu.org/software/libtool/
+
+/ltmain.sh
+
+# http://www.gnu.org/software/texinfo
+
+/texinfo.tex
+
+# Repo Specific Items
+*.o
+*.lo
+/config.h
+/config.h.in~
+/config.log
+/config.status
+Makefile
+.deps
+.dirstamp
+/lib*
+.libs/
+/*-libtool
+.project
+/test/*_unittest
+/test/*.log
+/test/*.trs
+
+# ignore vim swap files
+.*.sw*
+# failures from patch
+*.orig
+*.rej
+# backup files from some editors
+*~
+.cscope/
+build/
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..676eceb
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,12 @@
+AM_DEFAULT_SOURCE_EXT = .cpp
+
+libbinarystoredir = ${libdir}/ipmid-providers
+libbinarystore_LTLIBRARIES = libbinarystore.la
+libbinarystore_la_SOURCES = main.cpp \
+			    handler.cpp
+libbinarystore_la_LDFLAGS = $(PHOSPHOR_LOGGING_LIBS) \
+			    -version-info 0:0:0 -shared
+libbinarystore_la_CXXFLAGS = $(PHOSPHOR_LOGGING_CFLAGS) \
+			     -flto
+
+SUBDIRS = . test
diff --git a/bootstrap.sh b/bootstrap.sh
new file mode 100755
index 0000000..50b75b7
--- /dev/null
+++ b/bootstrap.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+AUTOCONF_FILES="Makefile.in aclocal.m4 ar-lib autom4te.cache compile \
+        config.guess config.h.in config.sub configure depcomp install-sh \
+        ltmain.sh missing *libtool test-driver"
+
+case $1 in
+    clean)
+        test -f Makefile && make maintainer-clean
+        for file in ${AUTOCONF_FILES}; do
+            find -name "$file" | xargs -r rm -rf
+        done
+        exit 0
+        ;;
+esac
+
+autoreconf -i
+echo 'Run "./configure ${CONFIGURE_FLAGS} && make"'
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..c856762
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,57 @@
+# Initialization
+AC_PREREQ([2.69])
+AC_INIT([phosphor-ipmi-blobs-binarystore], [1.0], [https://github.com/openbmc/phosphor-ipmi-blobs-binarystore/issues])
+AC_LANG([C++])
+AC_CONFIG_HEADERS([config.h])
+AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror foreign dist-xz])
+AM_SILENT_RULES([yes])
+
+# Checks for programs.
+AC_PROG_CXX
+AM_PROG_AR
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+
+# Checks for typedefs, structures, and compiler characteristics.
+AX_CXX_COMPILE_STDCXX_17([noext])
+AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS])
+
+# Checks for library functions.
+LT_INIT # Required for systemd linking
+
+# Checks for libraries.
+PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging],, [AC_MSG_ERROR([Could not find phosphor-logging...openbmc/phosphor-logging package required])])
+AC_CHECK_HEADER([blobs-ipmid], [AC_MSG_ERROR(["phosphor-ipmi-blobs required and not found."])])
+
+# Check/set gtest specific functions.
+PKG_CHECK_MODULES([GTEST], [gtest], [], [AC_MSG_NOTICE([gtest not found, tests will not build])])
+PKG_CHECK_MODULES([GMOCK], [gmock], [], [AC_MSG_NOTICE([gmock not found, tests will not build])])
+PKG_CHECK_MODULES([GTEST_MAIN], [gtest_main], [], [AC_MSG_NOTICE([gtest_main not found, tests will not build])])
+
+# Add --enable-oe-sdk flag to configure script
+AC_ARG_ENABLE([oe-sdk],
+    AS_HELP_STRING([--enable-oe-sdk], [Link testcases absolutely against OE SDK so they can be ran within it.])
+)
+
+# Check for OECORE_TARGET_SYSROOT in the environment.
+AC_ARG_VAR(OECORE_TARGET_SYSROOT,
+    [Path to the OE SDK SYSROOT])
+
+# Configure OESDK_TESTCASE_FLAGS environment variable, which will be later
+# used in test/Makefile.am
+AS_IF([test "x$enable_oe_sdk" == "xyes"],
+    AS_IF([test "x$OECORE_TARGET_SYSROOT" == "x"],
+          AC_MSG_ERROR([OECORE_TARGET_SYSROOT must be set with --enable-oe-sdk])
+    )
+    AC_MSG_NOTICE([Enabling OE-SDK at $OECORE_TARGET_SYSROOT])
+    [
+        testcase_flags="-Wl,-rpath,\${OECORE_TARGET_SYSROOT}/lib"
+        testcase_flags="${testcase_flags} -Wl,-rpath,\${OECORE_TARGET_SYSROOT}/usr/lib"
+        testcase_flags="${testcase_flags} -Wl,-dynamic-linker,`find \${OECORE_TARGET_SYSROOT}/lib/ld-*.so | sort -r -n | head -n1`"
+    ]
+    AC_SUBST([OESDK_TESTCASE_FLAGS], [$testcase_flags])
+)
+
+# Create configured output
+AC_CONFIG_FILES([Makefile test/Makefile])
+AC_OUTPUT
diff --git a/handler.cpp b/handler.cpp
new file mode 100644
index 0000000..967a8c2
--- /dev/null
+++ b/handler.cpp
@@ -0,0 +1,87 @@
+#include "handler.hpp"
+
+namespace blobs
+{
+
+bool BinaryStoreBlobHandler::canHandleBlob(const std::string& path)
+{
+    // TODO: implement
+    return false;
+}
+
+std::vector<std::string> BinaryStoreBlobHandler::getBlobIds()
+{
+    // TODO: implement
+    std::vector<std::string> result;
+    return result;
+}
+
+bool BinaryStoreBlobHandler::deleteBlob(const std::string& path)
+{
+    // TODO: implement
+    return false;
+}
+
+bool BinaryStoreBlobHandler::stat(const std::string& path,
+                                  struct BlobMeta* meta)
+{
+    // TODO: implement
+    return false;
+}
+
+bool BinaryStoreBlobHandler::open(uint16_t session, uint16_t flags,
+                                  const std::string& path)
+{
+    // TODO: implement
+    return false;
+}
+
+std::vector<uint8_t> BinaryStoreBlobHandler::read(uint16_t session,
+                                                  uint32_t offset,
+                                                  uint32_t requestedSize)
+{
+    // TODO: implement
+    std::vector<uint8_t> result;
+    return result;
+}
+
+bool BinaryStoreBlobHandler::write(uint16_t session, uint32_t offset,
+                                   const std::vector<uint8_t>& data)
+{
+    // TODO: implement
+    return false;
+}
+
+bool BinaryStoreBlobHandler::writeMeta(uint16_t session, uint32_t offset,
+                                       const std::vector<uint8_t>& data)
+{
+    /* Binary store handler doesn't support write meta */
+    return false;
+}
+
+bool BinaryStoreBlobHandler::commit(uint16_t session,
+                                    const std::vector<uint8_t>& data)
+{
+    // TODO: implement
+    return false;
+}
+
+bool BinaryStoreBlobHandler::close(uint16_t session)
+{
+    // TODO: implement
+    return false;
+}
+
+bool BinaryStoreBlobHandler::stat(uint16_t session, struct BlobMeta* meta)
+{
+    // TODO: implement
+    return false;
+}
+
+bool BinaryStoreBlobHandler::expire(uint16_t session)
+{
+    /* Binary store handler doesn't support expire */
+    return false;
+}
+
+} // namespace blobs
diff --git a/handler.hpp b/handler.hpp
new file mode 100644
index 0000000..dcc17b4
--- /dev/null
+++ b/handler.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <blobs-ipmid/blobs.hpp>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+using std::size_t;
+using std::uint16_t;
+using std::uint32_t;
+using std::uint64_t;
+using std::uint8_t;
+
+namespace blobs
+{
+
+class BinaryStoreBlobHandler : public GenericBlobInterface
+{
+  public:
+    BinaryStoreBlobHandler() = default;
+    ~BinaryStoreBlobHandler() = default;
+    BinaryStoreBlobHandler(const BinaryStoreBlobHandler&) = delete;
+    BinaryStoreBlobHandler& operator=(const BinaryStoreBlobHandler&) = delete;
+    BinaryStoreBlobHandler(BinaryStoreBlobHandler&&) = default;
+    BinaryStoreBlobHandler& operator=(BinaryStoreBlobHandler&&) = default;
+
+    bool canHandleBlob(const std::string& path) override;
+    std::vector<std::string> getBlobIds() override;
+    bool deleteBlob(const std::string& path) override;
+    bool stat(const std::string& path, struct BlobMeta* meta) override;
+    bool open(uint16_t session, uint16_t flags,
+              const std::string& path) override;
+    std::vector<uint8_t> read(uint16_t session, uint32_t offset,
+                              uint32_t requestedSize) override;
+    bool write(uint16_t session, uint32_t offset,
+               const std::vector<uint8_t>& data) override;
+    bool writeMeta(uint16_t session, uint32_t offset,
+                   const std::vector<uint8_t>& data) override;
+    bool commit(uint16_t session, const std::vector<uint8_t>& data) override;
+    bool close(uint16_t session) override;
+    bool stat(uint16_t session, struct BlobMeta* meta) override;
+    bool expire(uint16_t session) override;
+};
+
+} // namespace blobs
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..97b3aa9
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,23 @@
+#include "handler.hpp"
+
+#include <blobs-ipmid/blobs.hpp>
+#include <memory>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This is required by the blob manager.
+ * TODO: move the declaration to blobs.hpp since all handlers need it
+ */
+std::unique_ptr<blobs::GenericBlobInterface> createHandler();
+
+#ifdef __cplusplus
+}
+#endif
+
+std::unique_ptr<blobs::GenericBlobInterface> createHandler()
+{
+    return std::make_unique<blobs::BinaryStoreBlobHandler>();
+}
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..b80b6d2
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,19 @@
+AM_CPPFLAGS = -I$(top_srcdir)/ \
+	$(GTEST_CFLAGS) \
+	$(GMOCK_CFLAGS)
+AM_CXXFLAGS = \
+	$(GTEST_MAIN_CFLAGS)
+AM_LDFLAGS = \
+	$(GMOCK_LIBS) \
+	$(GTEST_MAIN_LIBS) \
+	$(OESDK_TESTCASE_FLAGS)
+
+# Run all 'check' test programs
+check_PROGRAMS = \
+	handler_unittest
+TESTS = $(check_PROGRAMS)
+
+handler_unittest_SOURCES = handler_unittest.cpp
+handler_unittest_LDADD = $(PHOSPHOR_LOGGING_LIBS) \
+	$(top_builddir)/handler.o
+handler_unittest_CXXFLAGS = $(PHOSPHOR_LOGGING_CFLAGS)
diff --git a/test/handler_unittest.cpp b/test/handler_unittest.cpp
new file mode 100644
index 0000000..124a3ff
--- /dev/null
+++ b/test/handler_unittest.cpp
@@ -0,0 +1,12 @@
+#include "handler_unittest.hpp"
+
+namespace blobs
+{
+
+TEST_F(BinaryStoreBlobHandlerBasicTest, CanHandleBlobChecksNameInvalid)
+{
+    // Verify canHandleBlob checks and returns false on an invalid name.
+    EXPECT_FALSE(bstore.canHandleBlob("asdf"));
+}
+
+} // namespace blobs
diff --git a/test/handler_unittest.hpp b/test/handler_unittest.hpp
new file mode 100644
index 0000000..fd93de4
--- /dev/null
+++ b/test/handler_unittest.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "handler.hpp"
+
+#include <gtest/gtest.h>
+
+namespace blobs
+{
+
+class BinaryStoreBlobHandlerTest : public ::testing::Test
+{
+  protected:
+    BinaryStoreBlobHandlerTest() = default;
+
+    BinaryStoreBlobHandler bstore;
+};
+
+class BinaryStoreBlobHandlerBasicTest : public BinaryStoreBlobHandlerTest
+{
+};
+
+} // namespace blobs