android/filesystems/partition_types.h: new header

This patch introduces a new header to handle several types of
partition images through a simple common interface. This will be
used in a future patch to rework the way these images are setup
in vl-android.c

+ Move test support stuff to android/filesystems/testing/
+ Add unit tests.

Change-Id: Icc1c32258e37731283079adf0e5407fa2e48f661
diff --git a/Makefile.common b/Makefile.common
index 3dec971..17f886e 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -123,6 +123,7 @@
 	android/base/StringView.cpp \
 	android/emulation/CpuAccelerator.cpp \
 	android/filesystems/ext4_utils.cpp \
+	android/filesystems/partition_types.cpp \
 	android/kernel/kernel_utils.cpp \
 	android/utils/assert.c \
 	android/utils/bufprint.c \
diff --git a/Makefile.tests b/Makefile.tests
index 04373e6..b9a5a28 100644
--- a/Makefile.tests
+++ b/Makefile.tests
@@ -23,6 +23,8 @@
   android/base/StringView_unittest.cpp \
   android/emulation/CpuAccelerator_unittest.cpp \
   android/filesystems/ext4_utils_unittest.cpp \
+  android/filesystems/partition_types_unittest.cpp \
+  android/filesystems/testing/TestSupport.cpp \
   android/kernel/kernel_utils_unittest.cpp \
 
 ifeq (windows,$(HOST_OS))
diff --git a/android/filesystems/ext4_utils_unittest.cpp b/android/filesystems/ext4_utils_unittest.cpp
index 646c93d..66cc4a7 100644
--- a/android/filesystems/ext4_utils_unittest.cpp
+++ b/android/filesystems/ext4_utils_unittest.cpp
@@ -14,6 +14,8 @@
 #include "android/base/EintrWrapper.h"
 #include "android/base/Log.h"
 #include "android/base/files/ScopedStdioFile.h"
+#include "android/filesystems/testing/TestExt4ImageHeader.h"
+#include "android/filesystems/testing/TestSupport.h"
 
 #include <gtest/gtest.h>
 
@@ -28,144 +30,13 @@
 #endif
 
 using android::base::ScopedStdioFile;
-
-// These are the first 1082 bytes of an EXT4 system.img file
-// It was generated with:
-//
-//    dd -if=$SDK/system-images/android-19/armeabi-v7a/system.img
-//       -of=/tmp/ext4-system.img
-//       -bs=1082 -count=1
-//
-//    xxd -i /tmp/ext4-system.img
-//
-// The two last bytes must be 0x53 / 0xef, i.e. the EXT4 magic bytes.
-//
-static const unsigned char kExt4SystemImage[] = {
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0x89, 0x00, 0x00, 0x00, 0x26, 0x02, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x15, 0x19, 0x01, 0x00, 0xd6, 0x85, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x1b, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
-  0x53, 0xef
-};
-
-static const size_t kExt4SystemImageSize = sizeof(kExt4SystemImage);
-
-
-// TODO(digit): Move that to a test-support class.
-static std::string createTempFilePath() {
-#ifdef _WIN32
-    char tempDir[MAX_PATH];
-    DWORD ret = GetTempPath(MAX_PATH, tempDir);
-    CHECK(ret > 0 && ret < MAX_PATH)
-            << "Could not get temporary directory path";
-
-    std::string result;
-    result.resize(MAX_PATH);
-    UINT ret2 = GetTempFileName(tempDir, "emulator-test-", 0,  &result[0]);
-    CHECK(ret2 != ERROR_BUFFER_OVERFLOW) << "Could not create temporary file name";
-    result.resize(::strlen(result.c_str()));
-    return result;
-#else
-    std::string result("/tmp/emulator-test.XXXXXX");
-    int ret = HANDLE_EINTR(mkstemp(&result[0]));
-    PCHECK(ret >= 0) << "Could not create temporary filepath";
-    ::close(ret);
-    return result;
-#endif
-}
-
+using android::testing::CreateTempFilePath;
 
 class Ext4UtilsTest : public ::testing::Test {
 public:
     Ext4UtilsTest() : mTempFilePath() {
         ::memset(mImage, 0, sizeof mImage);
-        ::memcpy(mImage, kExt4SystemImage, kExt4SystemImageSize);
+        ::memcpy(mImage, kTestExt4ImageHeader, kTestExt4ImageHeaderSize);
     }
 
     ~Ext4UtilsTest() {
@@ -181,7 +52,7 @@
     const char* createTempFile(size_t maxBytes) {
         CHECK(maxBytes <= sizeof mImage);
         // TODO(digit): Replace with something else.
-        mTempFilePath = createTempFilePath();
+        mTempFilePath = CreateTempFilePath();
         ScopedStdioFile file(fopen(mTempFilePath.c_str(), "wb"));
         PCHECK(file.get()) << "Could not create temporary file!";
         PCHECK(::fwrite(mImage, maxBytes, 1, file.get()) == 1)
@@ -194,21 +65,21 @@
     // 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();
+        mTempFilePath = CreateTempFilePath();
         return mTempFilePath.c_str();
     }
 
     std::string mTempFilePath;
-    char mImage[kExt4SystemImageSize * 2U];
+    char mImage[kTestExt4ImageHeaderSize * 2U];
 };
 
 TEST_F(Ext4UtilsTest, android_pathIsExt4PartitionImage) {
-    const char* path = createTempFile(kExt4SystemImageSize);
+    const char* path = createTempFile(kTestExt4ImageHeaderSize);
     EXPECT_TRUE(android_pathIsExt4PartitionImage(path));
 }
 
 TEST_F(Ext4UtilsTest, android_pathIsExt4PartitionImageTruncated) {
-    const char* path = createTempFile(kExt4SystemImageSize - 2U);
+    const char* path = createTempFile(kTestExt4ImageHeaderSize - 2U);
     EXPECT_FALSE(android_pathIsExt4PartitionImage(path));
 }
 
@@ -219,13 +90,13 @@
 }
 
 TEST_F(Ext4UtilsTest, android_pathIsExt4PartitionImageBadMagic1) {
-    mImage[kExt4SystemImageSize - 1] = 0;
+    mImage[kTestExt4ImageHeaderSize - 1] = 0;
     const char* path = createTempFile(sizeof mImage);
     EXPECT_FALSE(android_pathIsExt4PartitionImage(path));
 }
 
 TEST_F(Ext4UtilsTest, android_pathIsExt4PartitionImageBadMagic2) {
-    mImage[kExt4SystemImageSize - 2] = 0;
+    mImage[kTestExt4ImageHeaderSize - 2] = 0;
     const char* path = createTempFile(sizeof mImage);
     EXPECT_FALSE(android_pathIsExt4PartitionImage(path));
 }
diff --git a/android/filesystems/partition_types.cpp b/android/filesystems/partition_types.cpp
new file mode 100644
index 0000000..f0dfba7
--- /dev/null
+++ b/android/filesystems/partition_types.cpp
@@ -0,0 +1,65 @@
+// Copyright 2014 The Android Open Source Project
+//
+// This software is licensed under the terms of the GNU General Public
+// License version 2, as published by the Free Software Foundation, and
+// may be copied, distributed, and modified under those terms.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+#include "android/filesystems/partition_types.h"
+
+#include "android/filesystems/ext4_utils.h"
+#include "android/utils/panic.h"
+#include "android/utils/path.h"
+
+#include <errno.h>
+
+const char* androidPartitionType_toString(AndroidPartitionType part_type) {
+    switch (part_type) {
+        case ANDROID_PARTITION_TYPE_UNKNOWN:
+            return "unknown";
+        case ANDROID_PARTITION_TYPE_YAFFS2:
+            return "yaffs2";
+        case ANDROID_PARTITION_TYPE_EXT4:
+            return "ext4";
+        default:
+            APANIC("Invalid partition type value %d", part_type);
+    }
+}
+
+
+AndroidPartitionType androidPartitionType_probeFile(const char* image_file) {
+    if (!path_exists(image_file)) {
+        return ANDROID_PARTITION_TYPE_UNKNOWN;
+    }
+    if (android_pathIsExt4PartitionImage(image_file)) {
+        return ANDROID_PARTITION_TYPE_EXT4;
+    }
+    // Assume YAFFS2, since there is little way to be sure for now.
+    // NOTE: An empty file is a valid Yaffs2 file!
+    return ANDROID_PARTITION_TYPE_YAFFS2;
+}
+
+
+int androidPartitionType_makeEmptyFile(AndroidPartitionType part_type,
+                                       uint64_t part_size,
+                                       const char* part_file) {
+    switch (part_type) {
+        case ANDROID_PARTITION_TYPE_YAFFS2:
+            // Any empty file is a valid YAFFS2 partition, |part_size|
+            // can be ignored here.
+            if (path_empty_file(part_file) < 0) {
+                return -errno;
+            }
+            return 0;
+
+        case ANDROID_PARTITION_TYPE_EXT4:
+            return android_createEmptyExt4Image(part_file, part_size, NULL);
+
+        default:
+            return -EINVAL;
+    }
+}
diff --git a/android/filesystems/partition_types.h b/android/filesystems/partition_types.h
new file mode 100644
index 0000000..9bbdcf4
--- /dev/null
+++ b/android/filesystems/partition_types.h
@@ -0,0 +1,46 @@
+// Copyright 2014 The Android Open Source Project
+//
+// This software is licensed under the terms of the GNU General Public
+// License version 2, as published by the Free Software Foundation, and
+// may be copied, distributed, and modified under those terms.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+#ifndef ANDROID_FILESYSTEMS_PARTITION_TYPES_H
+#define ANDROID_FILESYSTEMS_PARTITION_TYPES_H
+
+#include "android/utils/compiler.h"
+
+#include <inttypes.h>
+
+ANDROID_BEGIN_HEADER
+
+// List of supported Android partition image types.
+typedef enum {
+    ANDROID_PARTITION_TYPE_UNKNOWN = 0,
+    ANDROID_PARTITION_TYPE_YAFFS2 = 1,
+    ANDROID_PARTITION_TYPE_EXT4 = 2,
+} AndroidPartitionType;
+
+// Return a string describing the partition type to the caller.
+// Note: this will panic if |part_type| is an invalid value.
+const char* androidPartitionType_toString(AndroidPartitionType part_type);
+
+// Probe a given image file and return its partition image type.
+// Note: this returns ANDROID_PARTITION_TYPE_UNKNOWN if the file does
+// not exist or cannot be read.
+AndroidPartitionType androidPartitionType_probeFile(const char* image_file);
+
+// Create or reset the file at |image_file| to be an empty partition of type
+// |part_type| and size |part_size|. Returns 0 on success, or -errno on
+// failure.
+int androidPartitionType_makeEmptyFile(AndroidPartitionType part_type,
+                                       uint64_t part_size,
+                                       const char* image_file);
+
+ANDROID_END_HEADER
+
+#endif  // ANDROID_FILESYSTEMS_PARTITION_TYPES_H
diff --git a/android/filesystems/partition_types_unittest.cpp b/android/filesystems/partition_types_unittest.cpp
new file mode 100644
index 0000000..5bdddd9
--- /dev/null
+++ b/android/filesystems/partition_types_unittest.cpp
@@ -0,0 +1,102 @@
+// Copyright 2014 The Android Open Source Project
+//
+// This software is licensed under the terms of the GNU General Public
+// License version 2, as published by the Free Software Foundation, and
+// may be copied, distributed, and modified under those terms.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+#include "android/filesystems/partition_types.h"
+
+#include "android/base/EintrWrapper.h"
+#include "android/base/files/ScopedStdioFile.h"
+#include "android/filesystems/ext4_utils.h"
+#include "android/filesystems/testing/TestExt4ImageHeader.h"
+#include "android/filesystems/testing/TestSupport.h"
+
+#include "android/utils/path.h"
+
+#include <gtest/gtest.h>
+
+#include <stdio.h>
+#include <string>
+#include <unistd.h>
+
+namespace {
+
+using android::base::ScopedStdioFile;
+
+class TempPartition {
+public:
+    TempPartition() {
+        mPath = android::testing::CreateTempFilePath();
+    }
+
+    ~TempPartition() {
+        if (!mPath.empty()) {
+            HANDLE_EINTR(::unlink(mPath.c_str()));
+        }
+    }
+
+    const char* GetPath() const {
+        return mPath.c_str();
+    }
+
+protected:
+    std::string mPath;
+};
+
+}  // namespace
+
+TEST(AndroidPartitionType, ToString) {
+    EXPECT_STREQ("unknown", androidPartitionType_toString(ANDROID_PARTITION_TYPE_UNKNOWN));
+    EXPECT_STREQ("yaffs2", androidPartitionType_toString(ANDROID_PARTITION_TYPE_YAFFS2));
+    EXPECT_STREQ("ext4", androidPartitionType_toString(ANDROID_PARTITION_TYPE_EXT4));
+}
+
+TEST(AndroidPartitionType, ProbeFileYaffs2) {
+    TempPartition part;
+
+    // An empty partition is a valid YAFFS2 one.
+    ::path_empty_file(part.GetPath());
+
+    EXPECT_EQ(ANDROID_PARTITION_TYPE_YAFFS2,
+              androidPartitionType_probeFile(part.GetPath()));
+}
+
+
+TEST(AndroidPartitionType, ProbeFileExt4) {
+    TempPartition part;
+
+    android_createEmptyExt4Image(part.GetPath(), 16*1024*1024, "cache");
+
+    EXPECT_EQ(ANDROID_PARTITION_TYPE_EXT4,
+              androidPartitionType_probeFile(part.GetPath()));
+}
+
+TEST(AndroidPartitionType, MakeEmptyFileYaffs2) {
+    TempPartition part;
+
+    EXPECT_EQ(0, androidPartitionType_makeEmptyFile(
+            ANDROID_PARTITION_TYPE_YAFFS2,
+            8 * 1024 * 1024,
+            part.GetPath())) << "Could not create Yaffs2 partition image";
+
+    EXPECT_EQ(ANDROID_PARTITION_TYPE_YAFFS2,
+              androidPartitionType_probeFile(part.GetPath()));
+}
+
+TEST(AndroidPartitionType, MakeEmptyFileExt4) {
+    TempPartition part;
+
+    EXPECT_EQ(0, androidPartitionType_makeEmptyFile(
+            ANDROID_PARTITION_TYPE_EXT4,
+            8 * 1024 * 1024,
+            part.GetPath())) << "Could not create EXT4 partition image";
+
+    EXPECT_EQ(ANDROID_PARTITION_TYPE_EXT4,
+              androidPartitionType_probeFile(part.GetPath()));
+}
diff --git a/android/filesystems/testing/TestExt4ImageHeader.h b/android/filesystems/testing/TestExt4ImageHeader.h
new file mode 100644
index 0000000..13d41e2
--- /dev/null
+++ b/android/filesystems/testing/TestExt4ImageHeader.h
@@ -0,0 +1,122 @@
+// Copyright 2014 The Android Open Source Project
+//
+// This software is licensed under the terms of the GNU General Public
+// License version 2, as published by the Free Software Foundation, and
+// may be copied, distributed, and modified under those terms.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+#ifndef ANDROID_FILESYSTEMS_TESTING_TEST_EXT4_IMAGE_HEADER_H
+#define ANDROID_FILESYSTEMS_TESTING_TEST_EXT4_IMAGE_HEADER_H
+
+// These are the first 1082 bytes of an EXT4 system.img file
+// It was generated with:
+//
+//    dd -if=$SDK/system-images/android-19/armeabi-v7a/system.img
+//       -of=/tmp/ext4-system.img
+//       -bs=1082 -count=1
+//
+//    xxd -i /tmp/ext4-system.img
+//
+// The two last bytes must be 0x53 / 0xef, i.e. the EXT4 magic bytes.
+//
+static const unsigned char kTestExt4ImageHeader[] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x89, 0x00, 0x00, 0x00, 0x26, 0x02, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x15, 0x19, 0x01, 0x00, 0xd6, 0x85, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x1b, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+  0x53, 0xef
+};
+
+static const size_t kTestExt4ImageHeaderSize = sizeof(kTestExt4ImageHeader);
+
+#endif  // ANDROID_FILESYSTEMS_TESTING_TEST_EXT4_IMAGE_HEADER_H
diff --git a/android/filesystems/testing/TestSupport.cpp b/android/filesystems/testing/TestSupport.cpp
new file mode 100644
index 0000000..f084306
--- /dev/null
+++ b/android/filesystems/testing/TestSupport.cpp
@@ -0,0 +1,49 @@
+// Copyright 2014 The Android Open Source Project
+//
+// This software is licensed under the terms of the GNU General Public
+// License version 2, as published by the Free Software Foundation, and
+// may be copied, distributed, and modified under those terms.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+#include "android/filesystems/testing/TestSupport.h"
+
+#include "android/base/EintrWrapper.h"
+#include "android/base/Log.h"
+
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+namespace android {
+namespace testing {
+
+std::string CreateTempFilePath() {
+#ifdef _WIN32
+    char tempDir[MAX_PATH];
+    DWORD ret = GetTempPath(MAX_PATH, tempDir);
+    CHECK(ret > 0 && ret < MAX_PATH)
+            << "Could not get temporary directory path";
+
+    std::string result;
+    result.resize(MAX_PATH);
+    UINT ret2 = GetTempFileName(tempDir, "emulator-test-", 0,  &result[0]);
+    CHECK(ret2 != ERROR_BUFFER_OVERFLOW) << "Could not create temporary file name";
+    result.resize(::strlen(result.c_str()));
+    return result;
+#else
+    std::string result("/tmp/emulator-test.XXXXXX");
+    int ret = HANDLE_EINTR(mkstemp(&result[0]));
+    PCHECK(ret >= 0) << "Could not create temporary filepath";
+    ::close(ret);
+    return result;
+#endif
+}
+
+}  // namespace testing
+}  // namespace android
diff --git a/android/filesystems/testing/TestSupport.h b/android/filesystems/testing/TestSupport.h
new file mode 100644
index 0000000..b2285b5
--- /dev/null
+++ b/android/filesystems/testing/TestSupport.h
@@ -0,0 +1,25 @@
+// Copyright 2014 The Android Open Source Project
+//
+// This software is licensed under the terms of the GNU General Public
+// License version 2, as published by the Free Software Foundation, and
+// may be copied, distributed, and modified under those terms.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+#ifndef ANDROID_FILESYSTEMS_TESTING_TEST_SUPPORT_H
+#define ANDROID_FILESYSTEMS_TESTING_TEST_SUPPORT_H
+
+#include <string>
+
+namespace android {
+namespace testing {
+
+std::string CreateTempFilePath();
+
+}  // namespace testing
+}  // namespace android
+
+#endif  // ANDROID_FILESYSTEMS_TESTING_TEST_SUPPORT_H