You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by al...@apache.org on 2018/07/03 17:08:45 UTC

nifi-minifi-cpp git commit: MINIFICPP-547: Add binary diff capability to agent updates.

Repository: nifi-minifi-cpp
Updated Branches:
  refs/heads/master fad26e57c -> 1f5ed4254


MINIFICPP-547: Add binary diff capability to agent updates.

This will enable partial updates via the C2 server.

This closes #367.

Signed-off-by: Aldrin Piri <al...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/commit/1f5ed425
Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/tree/1f5ed425
Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/diff/1f5ed425

Branch: refs/heads/master
Commit: 1f5ed4254318717618f674f51ba731ffd89116de
Parents: fad26e5
Author: Marc Parisi <ph...@apache.org>
Authored: Thu Jun 28 12:58:34 2018 -0400
Committer: Aldrin Piri <al...@apache.org>
Committed: Tue Jul 3 13:08:13 2018 -0400

----------------------------------------------------------------------
 CMakeLists.txt                                  |   6 +
 LICENSE                                         |  29 +-
 aptitude.sh                                     |   1 +
 cmake/BuildTests.cmake                          |   5 +
 darwin.sh                                       |   2 +-
 debian.sh                                       |   2 +-
 docker/Dockerfile                               |   1 +
 .../http-curl/tests/C2UpdateAgentTest.cpp       |   2 +-
 fedora.sh                                       |   2 +-
 libminifi/CMakeLists.txt                        |  10 +
 libminifi/include/c2/C2Agent.h                  |   2 +
 libminifi/include/utils/file/FileUtils.h        |  24 +-
 libminifi/src/c2/C2Agent.cpp                    |  16 +-
 rheldistro.sh                                   |   2 +-
 suse.sh                                         |   2 +-
 thirdparty/bsdiff/CMakeLists.txt                |  27 ++
 thirdparty/bsdiff/LICENSE                       |  24 +
 thirdparty/bsdiff/bsdiff.c                      | 477 +++++++++++++++++++
 thirdparty/bsdiff/bsdiff.h                      |  47 ++
 thirdparty/bsdiff/bspatch.c                     | 200 ++++++++
 thirdparty/bsdiff/bspatch.h                     |  47 ++
 21 files changed, 918 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c4f3e93..864f105 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -286,6 +286,12 @@ if (ENABLE_TENSORFLOW)
     createExtension(TENSORFLOW-EXTENSIONS "TENSORFLOW EXTENSIONS" "This enables TensorFlow support" "extensions/tensorflow" "${TEST_DIR}/tensorflow-tests")
 endif()
 
+
+find_package(bzip2)
+include_directories("thirdparty/bsdiff/")
+add_subdirectory("thirdparty/bsdiff")
+
+
 ## Bustache/template extensions
 option(ENABLE_BUSTACHE "Enables Bustache (ApplyTemplate) support." OFF)
 if (ENABLE_BUSTACHE)

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index 879a1d3..e89e620 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1399,4 +1399,31 @@ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product bundles 'bsdiff' which is available under a "2-clause BSD" license.
+
+	 Copyright 2003-2005 Colin Percival
+	 Copyright 2012 Matthew Endsley
+	 All rights reserved
+	
+	 Redistribution and use in source and binary forms, with or without
+	 modification, are permitted providing that the following conditions 
+	 are met:
+	 1. Redistributions of source code must retain the above copyright
+	    notice, this list of conditions and the following disclaimer.
+	 2. Redistributions in binary form must reproduce the above copyright
+	    notice, this list of conditions and the following disclaimer in the
+	    documentation and/or other materials provided with the distribution.
+	
+	 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+	 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+	 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+	 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+	 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+	 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+	 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+	 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 POSSIBILITY OF SUCH DAMAGE.

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/aptitude.sh
----------------------------------------------------------------------
diff --git a/aptitude.sh b/aptitude.sh
index 4867fa9..c9bb2ed 100644
--- a/aptitude.sh
+++ b/aptitude.sh
@@ -31,6 +31,7 @@ build_deps(){
   COMMAND="sudo apt-get -y install cmake gcc g++ zlib1g-dev libssl-dev uuid uuid-dev"
   export DEBIAN_FRONTEND=noninteractive
   INSTALLED=()
+  INSTALLED+=("libbz2-dev")
   sudo apt-get -y update
   for option in "${OPTIONS[@]}" ; do
     option_value="${!option}"

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/cmake/BuildTests.cmake
----------------------------------------------------------------------
diff --git a/cmake/BuildTests.cmake b/cmake/BuildTests.cmake
index 2a0277b..28ab029 100644
--- a/cmake/BuildTests.cmake
+++ b/cmake/BuildTests.cmake
@@ -53,6 +53,11 @@ function(createTests testName)
     target_include_directories(${testName} BEFORE PRIVATE "${CMAKE_SOURCE_DIR}/libminifi/include/utils")
     target_include_directories(${testName} BEFORE PRIVATE "${CMAKE_SOURCE_DIR}/libminifi/include/processors")
     target_include_directories(${testName} BEFORE PRIVATE "${CMAKE_SOURCE_DIR}/libminifi/include/provenance")
+
+	if (ENABLE_BINARY_DIFF)
+    	target_include_directories(${testName} BEFORE PRIVATE "${CMAKE_SOURCE_DIR}/thirdparty/bsdiff/")
+    endif(ENABLE_BINARY_DIFF)
+
     if (Boost_FOUND)
         target_include_directories(${testName} BEFORE PRIVATE "${Boost_INCLUDE_DIRS}")
     endif()

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/darwin.sh
----------------------------------------------------------------------
diff --git a/darwin.sh b/darwin.sh
index 2283d3b..2f9f5c6 100644
--- a/darwin.sh
+++ b/darwin.sh
@@ -47,6 +47,7 @@ build_deps(){
 
   COMMAND="brew install cmake"
   INSTALLED=()
+  INSTALLED+=("bzip2")
   for option in "${OPTIONS[@]}" ; do
     option_value="${!option}"
     if [ "$option_value" = "${TRUE}" ]; then
@@ -80,7 +81,6 @@ build_deps(){
           elif [ "$FOUND_VALUE" = "gpsd" ]; then
             INSTALLED+=("gpsd")
           elif [ "$FOUND_VALUE" = "libarchive" ]; then
-            INSTALLED+=("xz")
             INSTALLED+=("bzip2")
           fi
         fi

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/debian.sh
----------------------------------------------------------------------
diff --git a/debian.sh b/debian.sh
index 15672e9..758017f 100644
--- a/debian.sh
+++ b/debian.sh
@@ -37,6 +37,7 @@ build_deps(){
   COMMAND="sudo apt-get -y install cmake gcc g++ zlib1g-dev uuid uuid-dev"
   export DEBIAN_FRONTEND=noninteractive
   INSTALLED=()
+  INSTALLED+=("libbz2-dev")
   sudo apt-get -y update
   for option in "${OPTIONS[@]}" ; do
     option_value="${!option}"
@@ -71,7 +72,6 @@ build_deps(){
             INSTALLED+=("libgps-dev")
           elif [ "$FOUND_VALUE" = "libarchive" ]; then
             INSTALLED+=("liblzma-dev")
-            INSTALLED+=("libbz2-dev")
           fi
         fi
       done

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/docker/Dockerfile
----------------------------------------------------------------------
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 6d0097d..d1d608b 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -46,6 +46,7 @@ RUN apk --update --no-cache upgrade && apk --update --no-cache add gcc \
 	gpsd-dev \
 	libressl-dev \
 	zlib-dev \
+	bzip2-dev \
 	python-dev
 
 ENV USER minificpp

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/extensions/http-curl/tests/C2UpdateAgentTest.cpp
----------------------------------------------------------------------
diff --git a/extensions/http-curl/tests/C2UpdateAgentTest.cpp b/extensions/http-curl/tests/C2UpdateAgentTest.cpp
index 00b761b..8bb7b22 100644
--- a/extensions/http-curl/tests/C2UpdateAgentTest.cpp
+++ b/extensions/http-curl/tests/C2UpdateAgentTest.cpp
@@ -175,7 +175,7 @@ int main(int argc, char **argv) {
 
   auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(then - start).count();
   std::string logs = LogTestController::getInstance().log_output.str();
-  assert(logs.find("removing command") != std::string::npos);
+  assert(logs.find("removing file") != std::string::npos);
   LogTestController::getInstance().reset();
   rmdir("./content_repository");
   assert(h_ex.calls_ <= (milliseconds / 1000) + 1);

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/fedora.sh
----------------------------------------------------------------------
diff --git a/fedora.sh b/fedora.sh
index 9b2b859..99b9439 100644
--- a/fedora.sh
+++ b/fedora.sh
@@ -35,6 +35,7 @@ build_deps(){
 
   COMMAND="sudo yum -y install gcc gcc-c++ libuuid libuuid-devel"
   INSTALLED=()
+  INSTALLED+=("bzip2-devel")
   for option in "${OPTIONS[@]}" ; do
     option_value="${!option}"
     if [ "$option_value" = "${TRUE}" ]; then
@@ -68,7 +69,6 @@ build_deps(){
             INSTALLED+=("gpsd-devel")
           elif [ "$FOUND_VALUE" = "libarchive" ]; then
             INSTALLED+=("xz-devel")
-            INSTALLED+=("bzip2-devel")
           fi
         fi
       done

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/libminifi/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/libminifi/CMakeLists.txt b/libminifi/CMakeLists.txt
index 302b7f8..f7f3e93 100644
--- a/libminifi/CMakeLists.txt
+++ b/libminifi/CMakeLists.txt
@@ -36,6 +36,10 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-abi-version=2 -fobjc-arc -isysroot ${
 ELSE ()
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOPENSSL_SUPPORT -DYAML_SUPPORT")
 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DOPENSSL_SUPPORT -DYAML_SUPPORT")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBDIFF")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBDIFF")
+include_directories("../thirdparty/bsdiff/")
+
 ENDIF()
 
 
@@ -73,12 +77,17 @@ add_library(spdlog STATIC ${SPD_SOURCES})
 add_library(core-minifi STATIC ${SOURCES})
 target_link_libraries(core-minifi ${CMAKE_DL_LIBS} ${UUID_LIBRARIES} yaml-cpp)
 
+target_link_libraries(core-minifi  PRIVATE bsdiff )
+
 find_package(ZLIB REQUIRED)
 include_directories(${ZLIB_INCLUDE_DIRS})
 
 target_link_libraries(core-minifi minifi-expression-language-extensions)
 target_link_libraries (core-minifi ${ZLIB_LIBRARIES})
 
+
+
+
 # Include OpenSSL
 find_package (OpenSSL REQUIRED)
 if (OPENSSL_FOUND)
@@ -94,4 +103,5 @@ add_library(capi STATIC ${CAPI_SOURCES})
 target_link_libraries(minifi core-minifi)
 
 
+
 SET (LIBMINIFI core-minifi PARENT_SCOPE)

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/libminifi/include/c2/C2Agent.h
----------------------------------------------------------------------
diff --git a/libminifi/include/c2/C2Agent.h b/libminifi/include/c2/C2Agent.h
index 65f07b0..e9ff4e4 100644
--- a/libminifi/include/c2/C2Agent.h
+++ b/libminifi/include/c2/C2Agent.h
@@ -220,6 +220,8 @@ class C2Agent : public state::UpdateController, public state::response::Response
 
   std::string update_location_;
 
+  std::string bin_location_;
+
   std::shared_ptr<logging::Logger> logger_;
 }
 ;

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/libminifi/include/utils/file/FileUtils.h
----------------------------------------------------------------------
diff --git a/libminifi/include/utils/file/FileUtils.h b/libminifi/include/utils/file/FileUtils.h
index 796ee1a..767ede7 100644
--- a/libminifi/include/utils/file/FileUtils.h
+++ b/libminifi/include/utils/file/FileUtils.h
@@ -31,6 +31,20 @@
 #define stat _stat
 #endif
 
+#ifdef BDIFF
+
+extern "C"
+{
+#include "bsdiff.h"
+#include "bspatch.h"
+}
+#else
+int apply_bsdiff_patch(const char *oldfile, const char *newfile, const char *patch) {
+  return -1;
+}
+
+#endif
+
 namespace org {
 namespace apache {
 namespace nifi {
@@ -79,7 +93,7 @@ class FileUtils {
 #endif
     return -1;
   }
-  
+
   static int copy_file(const std::string &path_from, const std::string dest_path) {
     std::ifstream src(path_from, std::ios::binary);
     if (!src.is_open())
@@ -89,6 +103,14 @@ class FileUtils {
     return 0;
   }
 
+  static int apply_binary_diff(const char *file_original, const char *file_new, const char *result_file) {
+    return apply_bsdiff_patch(file_original, file_new, result_file);
+  }
+
+  static int binary_diff(const char *file_original, const char *file_other, const char *patchfile) {
+    return -1;
+  }
+
 };
 
 } /* namespace file */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/libminifi/src/c2/C2Agent.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/c2/C2Agent.cpp b/libminifi/src/c2/C2Agent.cpp
index 203b66d..c71283d 100644
--- a/libminifi/src/c2/C2Agent.cpp
+++ b/libminifi/src/c2/C2Agent.cpp
@@ -167,6 +167,9 @@ void C2Agent::configure(const std::shared_ptr<Configure> &configure, bool reconf
 
       copy_path << cwd << "/minifi.update";
     }
+
+    // if not defined we won't beable to update
+    configure->get("c2.agent.bin.location", bin_location_);
   }
   std::string heartbeat_reporters;
   if (configure->get("c2.agent.heartbeat.reporter.classes", heartbeat_reporters)) {
@@ -622,6 +625,11 @@ void C2Agent::handle_update(const C2ContentResponse &resp) {
   } else if (resp.name == "agent") {
     // we are upgrading the agent. therefore we must be given a location
     auto location = resp.operation_arguments.find("location");
+    auto isPartialStr = resp.operation_arguments.find("partial");
+    bool partial_update = false;
+    if (isPartialStr != std::end(resp.operation_arguments)) {
+      partial_update = utils::StringUtils::equalsIgnoreCase(isPartialStr->second.to_string(), "true") ? true : false;
+    }
     if (location != resp.operation_arguments.end()) {
       // we will not have a raw payload
       C2Payload payload(Operation::TRANSFER, false, true);
@@ -639,9 +647,13 @@ void C2Agent::handle_update(const C2ContentResponse &resp) {
       protocol_.load()->consumePayload(std::move(transfer_response));
 
       if (allow_updates_) {
-        utils::file::FileUtils::copy_file(file_path, update_location_);
+        if (partial_update && !bin_location_.empty()) {
+          utils::file::FileUtils::apply_binary_diff(bin_location_.c_str(), file_path.c_str(), update_location_.c_str());
+        } else {
+          utils::file::FileUtils::copy_file(file_path, update_location_);
+        }
         // remove the downloaded file.
-        logger_->log_trace("removing command %s", file_path);
+        logger_->log_trace("removing file %s", file_path);
         unlink(file_path.c_str());
         update_agent();
       }

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/rheldistro.sh
----------------------------------------------------------------------
diff --git a/rheldistro.sh b/rheldistro.sh
index 0b745d4..f4f1c0d 100644
--- a/rheldistro.sh
+++ b/rheldistro.sh
@@ -79,6 +79,7 @@ build_deps(){
 
   COMMAND="sudo yum install cmake3 gcc gcc-c++ libuuid libuuid-devel"
   INSTALLED=()
+  INSTALLED+=("bzip2-devel")
   for option in "${OPTIONS[@]}" ; do
     option_value="${!option}"
     if [ "$option_value" = "${TRUE}" ]; then
@@ -112,7 +113,6 @@ build_deps(){
             INSTALLED+=("gpsd-devel")
           elif [ "$FOUND_VALUE" = "libarchive" ]; then
             INSTALLED+=("xz-devel")
-            INSTALLED+=("bzip2-devel")
           fi
         fi
       done

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/suse.sh
----------------------------------------------------------------------
diff --git a/suse.sh b/suse.sh
index f70f69e..51fa005 100644
--- a/suse.sh
+++ b/suse.sh
@@ -70,6 +70,7 @@ build_deps(){
 
   COMMAND="sudo zypper in -y gcc gcc-c++ libuuid1 libuuid-devel"
   INSTALLED=()
+  INSTALLED+=("libbz2-devel")
   for option in "${OPTIONS[@]}" ; do
     option_value="${!option}"
     if [ "$option_value" = "${TRUE}" ]; then
@@ -103,7 +104,6 @@ build_deps(){
             INSTALLED+=("gpsd-devel")
           elif [ "$FOUND_VALUE" = "libarchive" ]; then
             INSTALLED+=("xz-devel")
-            INSTALLED+=("libbz2-devel")
           fi
         fi
       done

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/thirdparty/bsdiff/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/thirdparty/bsdiff/CMakeLists.txt b/thirdparty/bsdiff/CMakeLists.txt
new file mode 100644
index 0000000..4975f5b
--- /dev/null
+++ b/thirdparty/bsdiff/CMakeLists.txt
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+#
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+project(libbsdiff)
+
+set(CMAKE_C_STANDARD 99)
+
+set(SOURCES bsdiff.c bspatch.c)
+add_library(bsdiff STATIC ${SOURCES})
+
+target_link_libraries(bsdiff bz2)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/thirdparty/bsdiff/LICENSE
----------------------------------------------------------------------
diff --git a/thirdparty/bsdiff/LICENSE b/thirdparty/bsdiff/LICENSE
new file mode 100644
index 0000000..5d40665
--- /dev/null
+++ b/thirdparty/bsdiff/LICENSE
@@ -0,0 +1,24 @@
+ Copyright 2003-2005 Colin Percival
+ Copyright 2012 Matthew Endsley
+ All rights reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted providing that the following conditions 
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/thirdparty/bsdiff/bsdiff.c
----------------------------------------------------------------------
diff --git a/thirdparty/bsdiff/bsdiff.c b/thirdparty/bsdiff/bsdiff.c
new file mode 100644
index 0000000..1c8f367
--- /dev/null
+++ b/thirdparty/bsdiff/bsdiff.c
@@ -0,0 +1,477 @@
+/*-
+ * Copyright 2003-2005 Colin Percival
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "bsdiff.h"
+
+#include <limits.h>
+#include <string.h>
+
+#define MIN(x,y) (((x)<(y)) ? (x) : (y))
+#define MEDIAN3(a,b,c) (((a)<(b)) ? \
+	((b)<(c) ? (b) : ((a)<(c) ? (c) : (a))) : \
+	((b)>(c) ? (b) : ((a)>(c) ? (c) : (a))))
+
+static void split(int64_t *I,int64_t *V,int64_t start,int64_t len,int64_t h)
+{
+	int64_t i,j,k,x,y,z,tmp,jj,kk;
+
+	if(len<16) {
+		for(k=start;k<start+len;k+=j) {
+			j=1;x=V[I[k]+h];
+			for(i=1;k+i<start+len;i++) {
+				if(V[I[k+i]+h]<x) {
+					x=V[I[k+i]+h];
+					j=0;
+				};
+				if(V[I[k+i]+h]==x) {
+					tmp=I[k+j];I[k+j]=I[k+i];I[k+i]=tmp;
+					j++;
+				};
+			};
+			for(i=0;i<j;i++) V[I[k+i]]=k+j-1;
+			if(j==1) I[k]=-1;
+		};
+		return;
+	};
+
+	/* Select pivot, algorithm by Bentley & McIlroy */
+	j=start+len/2;
+	k=start+len-1;
+	x=V[I[j]+h];
+	y=V[I[start]+h];
+	z=V[I[k]+h];
+	if(len>40) {  /* Big array: Pseudomedian of 9 */
+		tmp=len/8;
+		x=MEDIAN3(x,V[I[j-tmp]+h],V[I[j+tmp]+h]);
+		y=MEDIAN3(y,V[I[start+tmp]+h],V[I[start+tmp+tmp]+h]);
+		z=MEDIAN3(z,V[I[k-tmp]+h],V[I[k-tmp-tmp]+h]);
+	};  /* Else medium array: Pseudomedian of 3 */
+	x=MEDIAN3(x,y,z);
+
+	jj=0;kk=0;
+	for(i=start;i<start+len;i++) {
+		if(V[I[i]+h]<x) jj++;
+		if(V[I[i]+h]==x) kk++;
+	};
+	jj+=start;kk+=jj;
+
+	i=start;j=0;k=0;
+	while(i<jj) {
+		if(V[I[i]+h]<x) {
+			i++;
+		} else if(V[I[i]+h]==x) {
+			tmp=I[i];I[i]=I[jj+j];I[jj+j]=tmp;
+			j++;
+		} else {
+			tmp=I[i];I[i]=I[kk+k];I[kk+k]=tmp;
+			k++;
+		};
+	};
+
+	while(jj+j<kk) {
+		if(V[I[jj+j]+h]==x) {
+			j++;
+		} else {
+			tmp=I[jj+j];I[jj+j]=I[kk+k];I[kk+k]=tmp;
+			k++;
+		};
+	};
+
+	if(jj>start) split(I,V,start,jj-start,h);
+
+	for(i=0;i<kk-jj;i++) V[I[jj+i]]=kk-1;
+	if(jj==kk-1) I[jj]=-1;
+
+	if(start+len>kk) split(I,V,kk,start+len-kk,h);
+}
+
+static void qsufsort(int64_t *I,int64_t *V,const uint8_t *old,int64_t oldsize)
+{
+	int64_t buckets[256];
+	int64_t i,h,len;
+
+	for(i=0;i<256;i++) buckets[i]=0;
+	for(i=0;i<oldsize;i++) buckets[old[i]]++;
+	for(i=1;i<256;i++) buckets[i]+=buckets[i-1];
+	for(i=255;i>0;i--) buckets[i]=buckets[i-1];
+	buckets[0]=0;
+
+	for(i=0;i<oldsize;i++) I[++buckets[old[i]]]=i;
+	I[0]=oldsize;
+	for(i=0;i<oldsize;i++) V[i]=buckets[old[i]];
+	V[oldsize]=0;
+	for(i=1;i<256;i++) if(buckets[i]==buckets[i-1]+1) I[buckets[i]]=-1;
+	I[0]=-1;
+
+	for(h=1;I[0]!=-(oldsize+1);h+=h) {
+		len=0;
+		for(i=0;i<oldsize+1;) {
+			if(I[i]<0) {
+				len-=I[i];
+				i-=I[i];
+			} else {
+				if(len) I[i-len]=-len;
+				len=V[I[i]]+1-i;
+				split(I,V,i,len,h);
+				i+=len;
+				len=0;
+			};
+		};
+		if(len) I[i-len]=-len;
+	};
+
+	for(i=0;i<oldsize+1;i++) I[V[i]]=i;
+}
+
+static int64_t matchlen(const uint8_t *old,int64_t oldsize,const uint8_t *new,int64_t newsize)
+{
+	int64_t i;
+
+	for(i=0;(i<oldsize)&&(i<newsize);i++)
+		if(old[i]!=new[i]) break;
+
+	return i;
+}
+
+static int64_t search(const int64_t *I,const uint8_t *old,int64_t oldsize,
+		const uint8_t *new,int64_t newsize,int64_t st,int64_t en,int64_t *pos)
+{
+	int64_t x,y;
+
+	if(en-st<2) {
+		x=matchlen(old+I[st],oldsize-I[st],new,newsize);
+		y=matchlen(old+I[en],oldsize-I[en],new,newsize);
+
+		if(x>y) {
+			*pos=I[st];
+			return x;
+		} else {
+			*pos=I[en];
+			return y;
+		}
+	};
+
+	x=st+(en-st)/2;
+	if(memcmp(old+I[x],new,MIN(oldsize-I[x],newsize))<0) {
+		return search(I,old,oldsize,new,newsize,x,en,pos);
+	} else {
+		return search(I,old,oldsize,new,newsize,st,x,pos);
+	};
+}
+
+static void offtout(int64_t x,uint8_t *buf)
+{
+	int64_t y;
+
+	if(x<0) y=-x; else y=x;
+
+	buf[0]=y%256;y-=buf[0];
+	y=y/256;buf[1]=y%256;y-=buf[1];
+	y=y/256;buf[2]=y%256;y-=buf[2];
+	y=y/256;buf[3]=y%256;y-=buf[3];
+	y=y/256;buf[4]=y%256;y-=buf[4];
+	y=y/256;buf[5]=y%256;y-=buf[5];
+	y=y/256;buf[6]=y%256;y-=buf[6];
+	y=y/256;buf[7]=y%256;
+
+	if(x<0) buf[7]|=0x80;
+}
+
+static int64_t writedata(struct bsdiff_stream* stream, const void* buffer, int64_t length)
+{
+	int64_t result = 0;
+
+	while (length > 0)
+	{
+		const int smallsize = (int)MIN(length, INT_MAX);
+		const int writeresult = stream->write(stream, buffer, smallsize);
+		if (writeresult == -1)
+		{
+			return -1;
+		}
+
+		result += writeresult;
+		length -= smallsize;
+		buffer = (uint8_t*)buffer + smallsize;
+	}
+
+	return result;
+}
+
+struct bsdiff_request
+{
+	const uint8_t* old;
+	int64_t oldsize;
+	const uint8_t* new;
+	int64_t newsize;
+	struct bsdiff_stream* stream;
+	int64_t *I;
+	uint8_t *buffer;
+};
+
+static int bsdiff_internal(const struct bsdiff_request req)
+{
+	int64_t *I,*V;
+	int64_t scan,pos,len;
+	int64_t lastscan,lastpos,lastoffset;
+	int64_t oldscore,scsc;
+	int64_t s,Sf,lenf,Sb,lenb;
+	int64_t overlap,Ss,lens;
+	int64_t i;
+	uint8_t *buffer;
+	uint8_t buf[8 * 3];
+
+	if((V=req.stream->malloc((req.oldsize+1)*sizeof(int64_t)))==NULL) return -1;
+	I = req.I;
+
+	qsufsort(I,V,req.old,req.oldsize);
+	req.stream->free(V);
+
+	buffer = req.buffer;
+
+	/* Compute the differences, writing ctrl as we go */
+	scan=0;len=0;pos=0;
+	lastscan=0;lastpos=0;lastoffset=0;
+	while(scan<req.newsize) {
+		oldscore=0;
+
+		for(scsc=scan+=len;scan<req.newsize;scan++) {
+			len=search(I,req.old,req.oldsize,req.new+scan,req.newsize-scan,
+					0,req.oldsize,&pos);
+
+			for(;scsc<scan+len;scsc++)
+			if((scsc+lastoffset<req.oldsize) &&
+				(req.old[scsc+lastoffset] == req.new[scsc]))
+				oldscore++;
+
+			if(((len==oldscore) && (len!=0)) ||
+				(len>oldscore+8)) break;
+
+			if((scan+lastoffset<req.oldsize) &&
+				(req.old[scan+lastoffset] == req.new[scan]))
+				oldscore--;
+		};
+
+		if((len!=oldscore) || (scan==req.newsize)) {
+			s=0;Sf=0;lenf=0;
+			for(i=0;(lastscan+i<scan)&&(lastpos+i<req.oldsize);) {
+				if(req.old[lastpos+i]==req.new[lastscan+i]) s++;
+				i++;
+				if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };
+			};
+
+			lenb=0;
+			if(scan<req.newsize) {
+				s=0;Sb=0;
+				for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) {
+					if(req.old[pos-i]==req.new[scan-i]) s++;
+					if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; };
+				};
+			};
+
+			if(lastscan+lenf>scan-lenb) {
+				overlap=(lastscan+lenf)-(scan-lenb);
+				s=0;Ss=0;lens=0;
+				for(i=0;i<overlap;i++) {
+					if(req.new[lastscan+lenf-overlap+i]==
+					   req.old[lastpos+lenf-overlap+i]) s++;
+					if(req.new[scan-lenb+i]==
+					   req.old[pos-lenb+i]) s--;
+					if(s>Ss) { Ss=s; lens=i+1; };
+				};
+
+				lenf+=lens-overlap;
+				lenb-=lens;
+			};
+
+			offtout(lenf,buf);
+			offtout((scan-lenb)-(lastscan+lenf),buf+8);
+			offtout((pos-lenb)-(lastpos+lenf),buf+16);
+
+			/* Write control data */
+			if (writedata(req.stream, buf, sizeof(buf)))
+				return -1;
+
+			/* Write diff data */
+			for(i=0;i<lenf;i++)
+				buffer[i]=req.new[lastscan+i]-req.old[lastpos+i];
+			if (writedata(req.stream, buffer, lenf))
+				return -1;
+
+			/* Write extra data */
+			for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)
+				buffer[i]=req.new[lastscan+lenf+i];
+			if (writedata(req.stream, buffer, (scan-lenb)-(lastscan+lenf)))
+				return -1;
+
+			lastscan=scan-lenb;
+			lastpos=pos-lenb;
+			lastoffset=pos-scan;
+		};
+	};
+
+	return 0;
+}
+
+int bsdiff(const uint8_t* old, int64_t oldsize, const uint8_t* newff, int64_t newsize, struct bsdiff_stream* stream)
+{
+	int result;
+	struct bsdiff_request req;
+
+	if((req.I=stream->malloc((oldsize+1)*sizeof(int64_t)))==NULL)
+		return -1;
+
+	if((req.buffer=stream->malloc(newsize+1))==NULL)
+	{
+		stream->free(req.I);
+		return -1;
+	}
+
+	req.old = old;
+	req.oldsize = oldsize;
+	req.new = newff;
+	req.newsize = newsize;
+	req.stream = stream;
+
+	result = bsdiff_internal(req);
+
+	stream->free(req.buffer);
+	stream->free(req.I);
+
+	return result;
+}
+
+#include <sys/types.h>
+
+#include <bzlib.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static int bz2_write(struct bsdiff_stream* stream, const void* buffer, int size)
+{
+	int bz2err;
+	BZFILE* bz2;
+
+	bz2 = (BZFILE*)stream->opaque;
+	BZ2_bzWrite(&bz2err, bz2, (void*)buffer, size);
+	if (bz2err != BZ_STREAM_END && bz2err != BZ_OK)
+		return -1;
+
+	return 0;
+}
+
+int bs_diff(const char *oldfile, const char *newfile, const char *patchfile)
+{
+	int fd;
+	int bz2err;
+	uint8_t *old,*new;
+	off_t oldsize,newsize;
+	uint8_t buf[8];
+	FILE * pf;
+	struct bsdiff_stream stream;
+	BZFILE* bz2;
+
+	memset(&bz2, 0, sizeof(bz2));
+	stream.malloc = malloc;
+	stream.free = free;
+	stream.write = bz2_write;
+
+	//if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
+
+	/* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
+		that we never try to malloc(0) and get a NULL pointer */
+	if(((fd=open(oldfile,O_RDONLY,0))<0) ||
+		((oldsize=lseek(fd,0,SEEK_END))==-1) ||
+		((old=malloc(oldsize+1))==NULL) ||
+		(lseek(fd,0,SEEK_SET)!=0) ||
+		(read(fd,old,oldsize)!=oldsize) ||
+		(close(fd)==-1)) {
+	    return -1;
+	    //err(1,"%s",argv[1]);
+	}
+
+
+	/* Allocate newsize+1 bytes instead of newsize bytes to ensure
+		that we never try to malloc(0) and get a NULL pointer */
+	if(((fd=open(newfile,O_RDONLY,0))<0) ||
+		((newsize=lseek(fd,0,SEEK_END))==-1) ||
+		((new=malloc(newsize+1))==NULL) ||
+		(lseek(fd,0,SEEK_SET)!=0) ||
+		(read(fd,new,newsize)!=newsize) ||
+		(close(fd)==-1)){
+	  return -2;
+	  //err(1,"%s",argv[2]);
+	}
+
+	/* Create the patch file */
+	if ((pf = fopen(patchfile, "w")) == NULL){
+	  return -3;
+	  //err(1, "%s", argv[3]);
+	}
+
+
+	/* Write header (signature+newsize) */
+	offtout(newsize, buf);
+	if (fwrite("ENDSLEY/BSDIFF43", 16, 1, pf) != 1 ||
+		fwrite(buf, sizeof(buf), 1, pf) != 1){
+	  return -4;
+		//err(1, "Failed to write header");
+	}
+
+
+	if (NULL == (bz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)))
+	{
+	  return -5;
+		//errx(1, "BZ2_bzWriteOpen, bz2err=%d", bz2err);
+	}
+
+	stream.opaque = bz2;
+	if (bsdiff(old, oldsize, new, newsize, &stream)){
+	  return -6;
+		//err(1, "bsdiff");
+	}
+
+	BZ2_bzWriteClose(&bz2err, bz2, 0, NULL, NULL);
+	if (bz2err != BZ_OK){
+	  return -7;
+		//err(1, "BZ2_bzWriteClose, bz2err=%d", bz2err);
+	}
+
+	if (fclose(pf)){
+	    return -8;
+		//err(1, "fclose");
+	}
+
+	/* Free the memory we used */
+	free(old);
+	free(new);
+
+	return 0;
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/thirdparty/bsdiff/bsdiff.h
----------------------------------------------------------------------
diff --git a/thirdparty/bsdiff/bsdiff.h b/thirdparty/bsdiff/bsdiff.h
new file mode 100644
index 0000000..9d15e06
--- /dev/null
+++ b/thirdparty/bsdiff/bsdiff.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright 2003-2005 Colin Percival
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions 
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BSDIFF_H
+# define BSDIFF_H
+
+# include <stddef.h>
+# include <stdint.h>
+
+struct bsdiff_stream
+{
+	void* opaque;
+
+	void* (*malloc)(size_t size);
+	void (*free)(void* ptr);
+	int (*write)(struct bsdiff_stream* stream, const void* buffer, int size);
+};
+
+int bsdiff(const uint8_t* old, int64_t oldsize, const uint8_t* newff, int64_t newsize, struct bsdiff_stream* stream);
+
+int bs_diff(const char *oldfile, const char *newfile, const char *patchfile);
+
+#endif

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/thirdparty/bsdiff/bspatch.c
----------------------------------------------------------------------
diff --git a/thirdparty/bsdiff/bspatch.c b/thirdparty/bsdiff/bspatch.c
new file mode 100644
index 0000000..b283323
--- /dev/null
+++ b/thirdparty/bsdiff/bspatch.c
@@ -0,0 +1,200 @@
+/*-
+ * Copyright 2003-2005 Colin Percival
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions 
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "bspatch.h"
+
+static int64_t offtin(uint8_t *buf)
+{
+	int64_t y;
+
+	y=buf[7]&0x7F;
+	y=y*256;y+=buf[6];
+	y=y*256;y+=buf[5];
+	y=y*256;y+=buf[4];
+	y=y*256;y+=buf[3];
+	y=y*256;y+=buf[2];
+	y=y*256;y+=buf[1];
+	y=y*256;y+=buf[0];
+
+	if(buf[7]&0x80) y=-y;
+
+	return y;
+}
+
+int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* newff, int64_t newsize, struct bspatch_stream* stream)
+{
+	uint8_t buf[8];
+	int64_t oldpos,newpos;
+	int64_t ctrl[3];
+	int64_t i;
+
+	oldpos=0;newpos=0;
+	while(newpos<newsize) {
+		/* Read control data */
+		for(i=0;i<=2;i++) {
+			if (stream->read(stream, buf, 8))
+				return -1;
+			ctrl[i]=offtin(buf);
+		};
+
+		/* Sanity-check */
+		if(newpos+ctrl[0]>newsize)
+			return -1;
+
+		/* Read diff string */
+		if (stream->read(stream, newff + newpos, ctrl[0]))
+			return -1;
+
+		/* Add old data to diff string */
+		for(i=0;i<ctrl[0];i++)
+			if((oldpos+i>=0) && (oldpos+i<oldsize))
+				newff[newpos+i]+=old[oldpos+i];
+
+		/* Adjust pointers */
+		newpos+=ctrl[0];
+		oldpos+=ctrl[0];
+
+		/* Sanity-check */
+		if(newpos+ctrl[1]>newsize)
+			return -1;
+
+		/* Read extra string */
+		if (stream->read(stream, newff + newpos, ctrl[1]))
+			return -1;
+
+		/* Adjust pointers */
+		newpos+=ctrl[1];
+		oldpos+=ctrl[2];
+	};
+
+	return 0;
+}
+
+
+#include <bzlib.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+int bz2_read(const struct bspatch_stream* stream, void* buffer, int length)
+{
+	int n;
+	int bz2err;
+	BZFILE* bz2;
+
+	bz2 = (BZFILE*)stream->opaque;
+	n = BZ2_bzRead(&bz2err, bz2, buffer, length);
+	if (n != length)
+		return -1;
+
+	return 0;
+}
+
+int apply_bsdiff_patch(const char *oldfile, const char *newfile, const char *patch)
+{
+	FILE * f;
+	int fd;
+	int bz2err;
+	uint8_t header[24];
+	uint8_t *old, *newff;
+	int64_t oldsize, newsize;
+	BZFILE* bz2;
+	struct bspatch_stream stream;
+	struct stat sb;
+
+	//if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
+
+	/* Open patch file */
+	if ((f = fopen(patch, "r")) == NULL){
+		//err(1, "fopen(%s)", patch);
+	  return -1;
+	}
+
+	/* Read header */
+	if (fread(header, 1, 24, f) != 24) {
+	  return -1;
+	  /*
+		if (feof(f))
+			errx(1, "Corrupt patch\n");
+		err(1, "fread(%s)", argv[3]);
+		*/
+	}
+
+	/* Check for appropriate magic */
+	if (memcmp(header, "ENDSLEY/BSDIFF43", 16) != 0)
+		errx(1, "Corrupt patch\n");
+
+	/* Read lengths from header */
+	newsize=offtin(header+16);
+	if(newsize<0)
+		errx(1,"Corrupt patch\n");
+
+	/* Close patch file and re-open it via libbzip2 at the right places */
+	if(((fd=open(oldfile,O_RDONLY,0))<0) ||
+		((oldsize=lseek(fd,0,SEEK_END))==-1) ||
+		((old=malloc(oldsize+1))==NULL) ||
+		(lseek(fd,0,SEEK_SET)!=0) ||
+		(read(fd,old,oldsize)!=oldsize) ||
+		(fstat(fd, &sb)) ||
+		(close(fd)==-1)) {
+	      return -2;
+	  //    err(1,"%s",argv[1]);
+	}
+	if((newff=malloc(newsize+1))==NULL) err(1,NULL);
+
+	if (NULL == (bz2 = BZ2_bzReadOpen(&bz2err, f, 0, 0, NULL, 0)))
+		errx(1, "BZ2_bzReadOpen, bz2err=%d", bz2err);
+
+	stream.read = bz2_read;
+	stream.opaque = bz2;
+	if (bspatch(old, oldsize, newff, newsize, &stream))
+		errx(1, "bspatch");
+
+	/* Clean up the bzip2 reads */
+	BZ2_bzReadClose(&bz2err, bz2);
+	fclose(f);
+
+	/* Write the new file */
+	if(((fd=open(newfile,O_CREAT|O_TRUNC|O_WRONLY,sb.st_mode))<0) ||
+		(write(fd,newff,newsize)!=newsize) || (close(fd)==-1))
+	{
+	  return -3;
+		//err(1,"%s",argv[2]);
+	}
+
+	free(newff);
+	free(old);
+
+	return 0;
+}
+

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/1f5ed425/thirdparty/bsdiff/bspatch.h
----------------------------------------------------------------------
diff --git a/thirdparty/bsdiff/bspatch.h b/thirdparty/bsdiff/bspatch.h
new file mode 100644
index 0000000..2037bb7
--- /dev/null
+++ b/thirdparty/bsdiff/bspatch.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright 2003-2005 Colin Percival
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions 
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BSPATCH_H
+#define BSPATCH_H
+
+# include <stdint.h>
+
+struct bspatch_stream
+{
+	void* opaque;
+	int (*read)(const struct bspatch_stream* stream, void* buffer, int length);
+};
+
+int bz2_read(const struct bspatch_stream* stream, void* buffer, int length);
+
+int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* newff, int64_t newsize, struct bspatch_stream* stream);
+
+
+int apply_bsdiff_patch(const char *oldfile, const char *newfile, const char *patch);
+
+#endif
+