DO NOT MERGE: Build a static bspatch for recovery. am: 2eea58f169
am: fb97da5a93  -s ours

Change-Id: Ia8374b9a7fa8ac750620827e1fdfbd0d5fa89bd0
diff --git a/Android.mk b/Android.mk
index 4341eef..12ee3e8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -26,9 +26,10 @@
     libbz
 
 # "bsdiff" program.
-bsdiff_shared_libs := \
+bsdiff_static_libs := \
     libdivsufsort64 \
-    libdivsufsort
+    libdivsufsort \
+    $(bsdiff_common_static_libs)
 
 bsdiff_src_files := \
     bsdiff.cc
@@ -49,17 +50,54 @@
     extents_unittest.cc \
     test_utils.cc
 
+# Target static libraries.
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbspatch
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_SRC_FILES := $(bspatch_src_files)
+LOCAL_CFLAGS := $(bsdiff_common_cflags)
+LOCAL_STATIC_LIBRARIES := $(bsdiff_common_static_libs)
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbsdiff
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_SRC_FILES := $(bsdiff_src_files)
+LOCAL_CFLAGS := $(bsdiff_common_cflags)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+LOCAL_STATIC_LIBRARIES := $(bsdiff_static_libs)
+include $(BUILD_STATIC_LIBRARY)
+
+# Host static libraries.
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbspatch
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_SRC_FILES := $(bspatch_src_files)
+LOCAL_CFLAGS := $(bsdiff_common_cflags)
+LOCAL_STATIC_LIBRARIES := $(bsdiff_common_static_libs)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbsdiff
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_SRC_FILES := $(bsdiff_src_files)
+LOCAL_CFLAGS := $(bsdiff_common_cflags)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+LOCAL_STATIC_LIBRARIES := $(bsdiff_static_libs)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
 # Target executables.
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := bspatch
 LOCAL_CPP_EXTENSION := .cc
-LOCAL_SRC_FILES := \
-    $(bspatch_src_files) \
-    bspatch_main.cc
+LOCAL_SRC_FILES := bspatch_main.cc
 LOCAL_CFLAGS := $(bsdiff_common_cflags)
-LOCAL_C_INCLUDES += external/bzip2
-LOCAL_STATIC_LIBRARIES := $(bsdiff_common_static_libs)
+LOCAL_STATIC_LIBRARIES := \
+    libbspatch \
+    $(bsdiff_common_static_libs)
 include $(BUILD_EXECUTABLE)
 
 # bspatch used in recovery by update_engine_sideload.
@@ -69,11 +107,10 @@
 LOCAL_FORCE_STATIC_EXECUTABLE := true
 LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
 LOCAL_CPP_EXTENSION := .cc
-LOCAL_SRC_FILES := \
-    $(bspatch_src_files) \
-    bspatch_main.cc
+LOCAL_SRC_FILES := bspatch_main.cc
 LOCAL_CFLAGS := $(bsdiff_common_cflags)
 LOCAL_STATIC_LIBRARIES := \
+    libbspatch \
     $(bsdiff_common_static_libs)
 include $(BUILD_EXECUTABLE)
 
@@ -82,40 +119,36 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := bsdiff
 LOCAL_CPP_EXTENSION := .cc
-LOCAL_SRC_FILES := \
-    $(bsdiff_src_files) \
-    bsdiff_main.cc
+LOCAL_SRC_FILES := bsdiff_main.cc
 LOCAL_CFLAGS := $(bsdiff_common_cflags)
-LOCAL_C_INCLUDES += external/bzip2
-LOCAL_STATIC_LIBRARIES := $(bsdiff_common_static_libs)
-LOCAL_SHARED_LIBRARIES := $(bsdiff_shared_libs)
+LOCAL_STATIC_LIBRARIES := \
+    libbsdiff \
+    $(bsdiff_static_libs)
 include $(BUILD_HOST_EXECUTABLE)
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := bspatch
 LOCAL_CPP_EXTENSION := .cc
-LOCAL_SRC_FILES := \
-    $(bspatch_src_files) \
-    bspatch_main.cc
+LOCAL_SRC_FILES := bspatch_main.cc
 LOCAL_CFLAGS := $(bsdiff_common_cflags)
-LOCAL_C_INCLUDES += external/bzip2
-LOCAL_STATIC_LIBRARIES := $(bsdiff_common_static_libs)
+LOCAL_STATIC_LIBRARIES := \
+    libbspatch \
+    $(bsdiff_common_static_libs)
 include $(BUILD_HOST_EXECUTABLE)
 
+# Unit tests.
+
 include $(CLEAR_VARS)
 LOCAL_MODULE := bsdiff_unittest
 LOCAL_MODULE_TAGS := debug tests
 LOCAL_CPP_EXTENSION := .cc
-LOCAL_SRC_FILES := \
-    $(bsdiff_src_files) \
-    $(bspatch_src_files) \
-    $(bsdiff_common_unittests) \
+LOCAL_SRC_FILES := $(bsdiff_common_unittests) \
     testrunner.cc
-LOCAL_CFLAGS := $(bsdiff_common_cflags)
-LOCAL_C_INCLUDES += external/bzip2
+LOCAL_CFLAGS := $(bsdiff_common_cflags) \
+    -DBSDIFF_TARGET_UNITTEST
 LOCAL_STATIC_LIBRARIES := \
-    $(bsdiff_common_static_libs) \
-    libgtest_host \
-    libgmock_host
-LOCAL_SHARED_LIBRARIES := $(bsdiff_shared_libs)
-include $(BUILD_HOST_EXECUTABLE)
+    libbsdiff \
+    libbspatch \
+    libgmock \
+    $(bsdiff_static_libs)
+include $(BUILD_NATIVE_TEST)
diff --git a/bsdiff.cc b/bsdiff.cc
index dab0d82..669a1e5 100644
--- a/bsdiff.cc
+++ b/bsdiff.cc
@@ -28,6 +28,8 @@
 __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bsdiff/bsdiff.c,v 1.1 2005/08/06 01:59:05 cperciva Exp $");
 #endif
 
+#include "bsdiff.h"
+
 #include <sys/types.h>
 
 #include <bzlib.h>
@@ -50,7 +52,7 @@
 
 namespace bsdiff {
 
-static off_t matchlen(u_char *old, off_t oldsize, u_char *new_buf,
+static off_t matchlen(const u_char* old, off_t oldsize, const u_char* new_buf,
                       off_t newsize) {
 	off_t i;
 
@@ -60,9 +62,14 @@
 	return i;
 }
 
-static off_t search(saidx_t *I,u_char *old,off_t oldsize,
-		u_char *new_buf,off_t newsize,off_t st,off_t en,off_t *pos)
-{
+// This is a binary search of the string |new_buf| of size |newsize| (or a
+// prefix of it) in the |old| string with size |oldsize| using the suffix array
+// |I|. |st| and |en| is the start and end of the search range (inclusive).
+// Returns the length of the longest prefix found and stores the position of the
+// string found in |*pos|.
+static off_t search(saidx_t* I, const u_char* old, off_t oldsize,
+                    const u_char* new_buf, off_t newsize, off_t st, off_t en,
+                    off_t* pos) {
 	off_t x,y;
 
 	if(en-st<2) {
@@ -109,6 +116,35 @@
 	int fd;
 	u_char *old_buf,*new_buf;
 	off_t oldsize,newsize;
+
+	/* 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(old_filename,O_RDONLY,0))<0) ||
+		((oldsize=lseek(fd,0,SEEK_END))==-1) ||
+		((old_buf=static_cast<u_char*>(malloc(oldsize+1)))==NULL) ||
+		(lseek(fd,0,SEEK_SET)!=0) ||
+		(read(fd,old_buf,oldsize)!=oldsize) ||
+		(close(fd)==-1)) err(1,"%s",old_filename);
+
+	/* 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(new_filename,O_RDONLY,0))<0) ||
+		((newsize=lseek(fd,0,SEEK_END))==-1) ||
+		((new_buf = static_cast<u_char*>(malloc(newsize+1)))==NULL) ||
+		(lseek(fd,0,SEEK_SET)!=0) ||
+		(read(fd,new_buf,newsize)!=newsize) ||
+		(close(fd)==-1)) err(1,"%s",new_filename);
+
+	int ret = bsdiff(old_buf, oldsize, new_buf, newsize, patch_filename);
+
+	free(old_buf);
+	free(new_buf);
+
+	return ret;
+}
+
+int bsdiff(const u_char* old_buf, off_t oldsize, const u_char* new_buf,
+           off_t newsize, const char* patch_filename) {
 	saidx_t *I;
 	off_t scan,pos=0,len;
 	off_t lastscan,lastpos,lastoffset;
@@ -124,29 +160,11 @@
 	BZFILE * pfbz2;
 	int bz2err;
 
-	/* 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(old_filename,O_RDONLY,0))<0) ||
-		((oldsize=lseek(fd,0,SEEK_END))==-1) ||
-		((old_buf=static_cast<u_char*>(malloc(oldsize+1)))==NULL) ||
-		(lseek(fd,0,SEEK_SET)!=0) ||
-		(read(fd,old_buf,oldsize)!=oldsize) ||
-		(close(fd)==-1)) err(1,"%s",old_filename);
-
 	if((I=static_cast<saidx_t*>(malloc((oldsize+1)*sizeof(saidx_t))))==NULL)
 		err(1,NULL);
 
 	if(divsufsort(old_buf, I, oldsize)) err(1, "divsufsort");
 
-	/* 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(new_filename,O_RDONLY,0))<0) ||
-		((newsize=lseek(fd,0,SEEK_END))==-1) ||
-		((new_buf = static_cast<u_char*>(malloc(newsize+1)))==NULL) ||
-		(lseek(fd,0,SEEK_SET)!=0) ||
-		(read(fd,new_buf,newsize)!=newsize) ||
-		(close(fd)==-1)) err(1,"%s",new_filename);
-
 	if(((db=static_cast<u_char*>(malloc(newsize+1)))==NULL) ||
 		((eb=static_cast<u_char*>(malloc(newsize+1)))==NULL)) err(1,NULL);
 	dblen=0;
@@ -193,7 +211,7 @@
 			prev_pos=pos;
 
 			len=search(I,old_buf,oldsize,new_buf+scan,newsize-scan,
-					0,oldsize,&pos);
+					0,oldsize-1,&pos);
 
 			for(;scsc<scan+len;scsc++)
 			if((scsc+lastoffset<oldsize) &&
@@ -325,8 +343,6 @@
 	free(db);
 	free(eb);
 	free(I);
-	free(old_buf);
-	free(new_buf);
 
 	return 0;
 }
diff --git a/bsdiff.h b/bsdiff.h
index c86b6f8..370ee03 100644
--- a/bsdiff.h
+++ b/bsdiff.h
@@ -5,12 +5,20 @@
 #ifndef _BSDIFF_BSDIFF_H_
 #define _BSDIFF_BSDIFF_H_
 
+#include <sys/types.h>
+
 namespace bsdiff {
 
 int bsdiff(const char* old_filename,
            const char* new_filename,
            const char* patch_filename);
 
+int bsdiff(const u_char* old_buf,
+           off_t oldsize,
+           const u_char* new_buf,
+           off_t newsize,
+           const char* patch_filename);
+
 }  // namespace bsdiff
 
 #endif  // _BSDIFF_BSDIFF_H_
diff --git a/file.h b/file.h
index e9659c7..ad1fd2f 100644
--- a/file.h
+++ b/file.h
@@ -29,7 +29,7 @@
  private:
   // Creates the File instance for the |fd|. Takes ownership of the file
   // descriptor.
-  File(int fd);
+  explicit File(int fd);
 
   int fd_;
 };
diff --git a/test_utils.cc b/test_utils.cc
index 2ad8fc8..f369f80 100644
--- a/test_utils.cc
+++ b/test_utils.cc
@@ -7,6 +7,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
 #include <gtest/gtest.h>
@@ -51,6 +52,16 @@
 
 namespace test_utils {
 
+void BsdiffTestEnvironment::SetUp() {
+#ifdef BSDIFF_TARGET_UNITTEST
+#define BSDIFF_TARGET_TMP_BASE "/data/tmp"
+      if (access(BSDIFF_TARGET_TMP_BASE, F_OK) == -1) {
+        mkdir(BSDIFF_TARGET_TMP_BASE, S_IRWXU | S_IRWXG | S_IROTH | S_IWOTH);
+      }
+      setenv("TMPDIR", BSDIFF_TARGET_TMP_BASE, 1);
+#endif // defined (BSDIFF_TARGET_UNITTEST)
+}
+
 bool ReadFile(const string& path, vector<uint8_t>* out) {
   FILE* fp = fopen(path.c_str(), "r");
   if (!fp)
@@ -101,13 +112,15 @@
   memcpy(&diff_len, contents.data() + 16, sizeof(diff_len));
   memcpy(&new_file_len, contents.data() + 24, sizeof(new_file_len));
 
-  TEST_AND_RETURN_FALSE(file_size >= kHeaderSize + ctrl_len + diff_len);
-  extra_len = file_size - kHeaderSize - ctrl_len - diff_len;
-
   // Sanity check before we attempt to parse the bz2 streams.
   TEST_AND_RETURN_FALSE(ctrl_len >= 0);
   TEST_AND_RETURN_FALSE(diff_len >= 0);
 
+  // The cast is safe since ctrl_len and diff_len are both positive.
+  TEST_AND_RETURN_FALSE(file_size >=
+        static_cast<uint64_t>(kHeaderSize + ctrl_len + diff_len));
+  extra_len = file_size - kHeaderSize - ctrl_len - diff_len;
+
   uint8_t* ptr = contents.data() + kHeaderSize;
   bz2_ctrl = vector<uint8_t>(ptr, ptr + ctrl_len);
   ptr += ctrl_len;
diff --git a/test_utils.h b/test_utils.h
index 186d9e6..7132fe5 100644
--- a/test_utils.h
+++ b/test_utils.h
@@ -5,6 +5,7 @@
 #ifndef _BSDIFF_TEST_UTILS_H_
 #define _BSDIFF_TEST_UTILS_H_
 
+#include <gtest/gtest.h>
 #include <string>
 #include <vector>
 
@@ -18,6 +19,11 @@
 
 namespace test_utils {
 
+class BsdiffTestEnvironment : public ::testing::Environment {
+  public:
+    virtual void SetUp();
+};
+
 // Reads all the contents of the file |path| into |out|. Returns whether it
 // read up to the end of file.
 bool ReadFile(const std::string& path, std::vector<uint8_t>* out);
diff --git a/testrunner.cc b/testrunner.cc
index 44f0b5e..8b598e2 100644
--- a/testrunner.cc
+++ b/testrunner.cc
@@ -2,9 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "test_utils.h"
+
 #include <gtest/gtest.h>
 
 int main(int argc, char** argv) {
   ::testing::InitGoogleTest(&argc, argv);
+  ::testing::AddGlobalTestEnvironment(new test_utils::BsdiffTestEnvironment);
   return RUN_ALL_TESTS();
 }