Add android_createEmptyExt4Image()

This patch adds a new function to the emulator to create an
empty EXT4 partition image of a given size in bytes.

+ Basic unit test.

Change-Id: I5b709c5697fe4a57be76b4344413aff3447b616a
diff --git a/Makefile.android b/Makefile.android
index f4caf40..350b72f 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -334,6 +334,12 @@
   endif
 endif
 
+# Build libext4_utils and related modules/
+include $(LOCAL_PATH)/distrib/zlib-1.2.8/sources.make
+include $(LOCAL_PATH)/distrib/libsparse/sources.mk
+include $(LOCAL_PATH)/distrib/libselinux/sources.mk
+include $(LOCAL_PATH)/distrib/ext4_utils/sources.mk
+
 include $(LOCAL_PATH)/Makefile.common
 
 ifeq ($(HOST_OS),windows)
@@ -392,11 +398,6 @@
 
 include $(LOCAL_PATH)/Makefile.tests
 
-# Build libsparse and related executables.
-include $(LOCAL_PATH)/distrib/libsparse/sources.mk
-include $(LOCAL_PATH)/distrib/libselinux/sources.mk
-include $(LOCAL_PATH)/distrib/ext4_utils/sources.mk
-
 ##############################################################################
 ##############################################################################
 ###
diff --git a/Makefile.common b/Makefile.common
index 5844245..3dec971 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -88,8 +88,6 @@
 ###########################################################
 # Zlib sources
 #
-ZLIB_DIR := distrib/zlib-1.2.8
-include $(LOCAL_PATH)/$(ZLIB_DIR)/sources.make
 EMULATOR_COMMON_CFLAGS += -I$(ZLIB_INCLUDES)
 
 ###########################################################
@@ -153,6 +151,7 @@
 
 common_LOCAL_CFLAGS += $(EMULATOR_COMMON_CFLAGS)
 
+common_LOCAL_CFLAGS += -I$(LIBEXT4_UTILS_INCLUDES)
 
 ## one for 32-bit
 $(call start-emulator-library, emulator-common)
diff --git a/Makefile.target b/Makefile.target
index 229190c..ae5e1cd 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -364,6 +364,9 @@
     emulator-libjpeg \
     emulator-libelff \
     emulator-common \
+    emulator-libext4_utils \
+    emulator-libsparse \
+    emulator-libselinux \
     emulator-zlib \
     $(SDL_STATIC_LIBRARIES)
 
@@ -401,6 +404,9 @@
     emulator64-libjpeg \
     emulator64-libelff \
     emulator64-common \
+    emulator64-libext4_utils \
+    emulator64-libsparse \
+    emulator64-libselinux \
     emulator64-zlib \
     $(SDL_STATIC_LIBRARIES_64)
 
diff --git a/Makefile.tests b/Makefile.tests
index 5ff4c56..04373e6 100644
--- a/Makefile.tests
+++ b/Makefile.tests
@@ -36,7 +36,13 @@
 LOCAL_LDLIBS += $(EMULATOR_GTEST_LDLIBS)
 LOCAL_SRC_FILES := $(EMULATOR_UNITTESTS_SOURCES)
 LOCAL_CFLAGS += -O0
-LOCAL_STATIC_LIBRARIES += emulator-common emulator-libgtest
+LOCAL_STATIC_LIBRARIES += \
+    emulator-common \
+    emulator-libext4_utils \
+    emulator-libsparse \
+    emulator-libselinux \
+    emulator-zlib \
+    emulator-libgtest
 $(call end-emulator-program)
 
 
@@ -45,5 +51,11 @@
 LOCAL_LDLIBS += $(EMULATOR_GTEST_LDLIBS)
 LOCAL_SRC_FILES := $(EMULATOR_UNITTESTS_SOURCES)
 LOCAL_CFLAGS += -O0
-LOCAL_STATIC_LIBRARIES += emulator64-common emulator64-libgtest
+LOCAL_STATIC_LIBRARIES += \
+    emulator64-common \
+    emulator64-libext4_utils \
+    emulator64-libsparse \
+    emulator64-libselinux \
+    emulator64-zlib \
+    emulator64-libgtest
 $(call end-emulator-program)
diff --git a/android/filesystems/ext4_utils.cpp b/android/filesystems/ext4_utils.cpp
index 5d60c57..2c10646 100644
--- a/android/filesystems/ext4_utils.cpp
+++ b/android/filesystems/ext4_utils.cpp
@@ -14,6 +14,8 @@
 #include "android/base/Log.h"
 #include "android/base/files/ScopedStdioFile.h"
 
+#include "make_ext4fs.h"
+
 #include <stdint.h>
 #include <string.h>
 
@@ -65,3 +67,12 @@
     EXT4_LOG << "Not an Ext4 partition image: " << path;
     return false;
 }
+
+int android_createEmptyExt4Image(const char *filePath,
+                                 uint64_t size,
+                                 const char *mountpoint) {
+    int ret = ::make_ext4fs(filePath, size, mountpoint, NULL);
+    if (ret < 0)
+        EXT4_ERROR << "Failed to create ext4 image at: " << filePath;
+    return ret;
+}
diff --git a/android/filesystems/ext4_utils.h b/android/filesystems/ext4_utils.h
index e8dad10..e6db2f3 100644
--- a/android/filesystems/ext4_utils.h
+++ b/android/filesystems/ext4_utils.h
@@ -15,9 +15,18 @@
 #include "android/utils/compiler.h"
 
 #include <stdbool.h>
+#include <inttypes.h>
 
 ANDROID_BEGIN_HEADER
 
+// Create a new empty EXT4 partition image file at |filePath|
+// of |size| bytes. |mountPoint| is the name of the corresponding
+// mount point, e.g. 'cache' for the cache partition.
+// Returns 0 on success, or -errno on failure.
+int android_createEmptyExt4Image(const char *filePath,
+                                 uint64_t size,
+                                 const char *mountpoint);
+
 // Returns true iff the file at |filePath| is an actual EXT4 partition image.
 bool android_pathIsExt4PartitionImage(const char* filePath);
 
diff --git a/android/filesystems/ext4_utils_unittest.cpp b/android/filesystems/ext4_utils_unittest.cpp
index 94c6e57..646c93d 100644
--- a/android/filesystems/ext4_utils_unittest.cpp
+++ b/android/filesystems/ext4_utils_unittest.cpp
@@ -191,6 +191,13 @@
         return mTempFilePath.c_str();
     }
 
+    // Create the path of a temporary file, but do not create or
+    // populate it. The file is removed in the destructor.
+    const char* createTempPath() {
+        mTempFilePath = createTempFilePath();
+        return mTempFilePath.c_str();
+    }
+
     std::string mTempFilePath;
     char mImage[kExt4SystemImageSize * 2U];
 };
@@ -222,3 +229,11 @@
     const char* path = createTempFile(sizeof mImage);
     EXPECT_FALSE(android_pathIsExt4PartitionImage(path));
 }
+
+TEST_F(Ext4UtilsTest, android_createEmptyExt4Partition) {
+    const char* tempPath = createTempPath();
+    uint64_t kSize = 32 * 1024 * 1024;
+    int ret = android_createEmptyExt4Image(tempPath, kSize, "cache");
+    EXPECT_EQ(0, ret);
+    EXPECT_TRUE(android_pathIsExt4PartitionImage(tempPath));
+}