Add real UUID support to ext4_utils.

For some unknown reason, we've always been generating the same UUID
for every single ext4 partition that we formatted.  Yikes.

Add a flag to request that a real UUID be generated when creating
filesystem.

Bug: 19993667
Change-Id: I6f3f6aa373021cb8b6779e5354ac36436c4d98d3
diff --git a/ext4_utils/Android.mk b/ext4_utils/Android.mk
index 9f56cca..352e742 100644
--- a/ext4_utils/Android.mk
+++ b/ext4_utils/Android.mk
@@ -10,7 +10,6 @@
     contents.c \
     extent.c \
     indirect.c \
-    uuid.c \
     sha1.c \
     wipe.c \
     crc16.c \
@@ -66,9 +65,11 @@
 LOCAL_C_INCLUDES += system/core/logwrapper/include
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
+    libext2_uuid \
     libselinux \
     libsparse \
     libz
+LOCAL_CFLAGS := -DREAL_UUID
 include $(BUILD_SHARED_LIBRARY)
 
 
@@ -86,9 +87,11 @@
 LOCAL_MODULE := make_ext4fs
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
+    libext2_uuid \
     libext4_utils \
     libselinux \
     libz
+LOCAL_CFLAGS := -DREAL_UUID
 include $(BUILD_EXECUTABLE)
 
 
diff --git a/ext4_utils/ext4_utils.c b/ext4_utils/ext4_utils.c
index ad0491f..3b22b81 100644
--- a/ext4_utils/ext4_utils.c
+++ b/ext4_utils/ext4_utils.c
@@ -15,12 +15,15 @@
  */
 
 #include "ext4_utils.h"
-#include "uuid.h"
 #include "allocate.h"
 #include "indirect.h"
 #include "extent.h"
+#include "sha1.h"
 
 #include <sparse/sparse.h>
+#ifdef REAL_UUID
+#include <uuid.h>
+#endif
 
 #include <fcntl.h>
 #include <inttypes.h>
@@ -49,6 +52,44 @@
 
 jmp_buf setjmp_env;
 
+/* Definition from RFC-4122 */
+struct uuid {
+    u32 time_low;
+    u16 time_mid;
+    u16 time_hi_and_version;
+    u8 clk_seq_hi_res;
+    u8 clk_seq_low;
+    u16 node0_1;
+    u32 node2_5;
+};
+
+static void sha1_hash(const char *namespace, const char *name,
+    unsigned char sha1[SHA1_DIGEST_LENGTH])
+{
+    SHA1_CTX ctx;
+    SHA1Init(&ctx);
+    SHA1Update(&ctx, (const u8*)namespace, strlen(namespace));
+    SHA1Update(&ctx, (const u8*)name, strlen(name));
+    SHA1Final(sha1, &ctx);
+}
+
+static void generate_sha1_uuid(const char *namespace, const char *name, u8 result[16])
+{
+    unsigned char sha1[SHA1_DIGEST_LENGTH];
+    struct uuid *uuid = (struct uuid *)result;
+
+    sha1_hash(namespace, name, (unsigned char*)sha1);
+    memcpy(uuid, sha1, sizeof(struct uuid));
+
+    uuid->time_low = ntohl(uuid->time_low);
+    uuid->time_mid = ntohs(uuid->time_mid);
+    uuid->time_hi_and_version = ntohs(uuid->time_hi_and_version);
+    uuid->time_hi_and_version &= 0x0FFF;
+    uuid->time_hi_and_version |= (5 << 12);
+    uuid->clk_seq_hi_res &= ~(1 << 6);
+    uuid->clk_seq_hi_res |= 1 << 7;
+}
+
 /* returns 1 if a is a power of b */
 static int is_power_of(int a, int b)
 {
@@ -188,7 +229,7 @@
 }
 
 /* Fill in the superblock memory buffer based on the filesystem parameters */
-void ext4_fill_in_sb()
+void ext4_fill_in_sb(int real_uuid)
 {
 	unsigned int i;
 	struct ext4_super_block *sb = aux_info.sb;
@@ -225,7 +266,16 @@
 	sb->s_feature_compat = info.feat_compat;
 	sb->s_feature_incompat = info.feat_incompat;
 	sb->s_feature_ro_compat = info.feat_ro_compat;
-	generate_uuid("extandroid/make_ext4fs", info.label, sb->s_uuid);
+	if (real_uuid == 1) {
+#ifdef REAL_UUID
+	    uuid_generate(sb->s_uuid);
+#else
+	    fprintf(stderr, "Not compiled with real UUID support\n");
+	    abort();
+#endif
+	} else {
+	    generate_sha1_uuid("extandroid/make_ext4fs", info.label, sb->s_uuid);
+	}
 	memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name));
 	strncpy(sb->s_volume_name, info.label, sizeof(sb->s_volume_name));
 	memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted));
diff --git a/ext4_utils/ext4_utils.h b/ext4_utils/ext4_utils.h
index 499753f..ea95446 100644
--- a/ext4_utils/ext4_utils.h
+++ b/ext4_utils/ext4_utils.h
@@ -138,7 +138,7 @@
 void write_ext4_image(int fd, int gz, int sparse, int crc);
 void ext4_create_fs_aux_info(void);
 void ext4_free_fs_aux_info(void);
-void ext4_fill_in_sb(void);
+void ext4_fill_in_sb(int real_uuid);
 void ext4_create_resize_inode(void);
 void ext4_create_journal_inode(void);
 void ext4_update_free(void);
@@ -157,7 +157,7 @@
 
 int make_ext4fs_internal(int fd, const char *directory,
 						 const char *mountpoint, fs_config_func_t fs_config_func, int gzip,
-						 int sparse, int crc, int wipe,
+						 int sparse, int crc, int wipe, int real_uuid,
 						 struct selabel_handle *sehnd, int verbose, time_t fixed_time,
 						 FILE* block_list_file);
 
diff --git a/ext4_utils/make_ext4fs.c b/ext4_utils/make_ext4fs.c
index 62a3f1a..5c9e208 100644
--- a/ext4_utils/make_ext4fs.c
+++ b/ext4_utils/make_ext4fs.c
@@ -18,7 +18,6 @@
 #include "ext4_utils.h"
 #include "allocate.h"
 #include "contents.h"
-#include "uuid.h"
 #include "wipe.h"
 
 #include <sparse/sparse.h>
@@ -406,7 +405,7 @@
 	reset_ext4fs_info();
 	info.len = len;
 
-	return make_ext4fs_internal(fd, NULL, mountpoint, NULL, 0, 1, 0, 0, sehnd, 0, -1, NULL);
+	return make_ext4fs_internal(fd, NULL, mountpoint, NULL, 0, 1, 0, 0, 0, sehnd, 0, -1, NULL);
 }
 
 int make_ext4fs(const char *filename, long long len,
@@ -424,7 +423,7 @@
 		return EXIT_FAILURE;
 	}
 
-	status = make_ext4fs_internal(fd, NULL, mountpoint, NULL, 0, 0, 0, 1, sehnd, 0, -1, NULL);
+	status = make_ext4fs_internal(fd, NULL, mountpoint, NULL, 0, 0, 0, 1, 0, sehnd, 0, -1, NULL);
 	close(fd);
 
 	return status;
@@ -492,7 +491,7 @@
 
 int make_ext4fs_internal(int fd, const char *_directory,
 						 const char *_mountpoint, fs_config_func_t fs_config_func, int gzip,
-						 int sparse, int crc, int wipe,
+						 int sparse, int crc, int wipe, int real_uuid,
 						 struct selabel_handle *sehnd, int verbose, time_t fixed_time,
 						 FILE* block_list_file)
 {
@@ -585,7 +584,7 @@
 
 	block_allocator_init();
 
-	ext4_fill_in_sb();
+	ext4_fill_in_sb(real_uuid);
 
 	if (reserve_inodes(0, 10) == EXT4_ALLOCATE_FAILED)
 		error("failed to reserve first 10 inodes");
diff --git a/ext4_utils/make_ext4fs_main.c b/ext4_utils/make_ext4fs_main.c
index a6c5f61..0e2ef5e 100644
--- a/ext4_utils/make_ext4fs_main.c
+++ b/ext4_utils/make_ext4fs_main.c
@@ -52,7 +52,7 @@
 {
 	fprintf(stderr, "%s [ -l <len> ] [ -j <journal size> ] [ -b <block_size> ]\n", basename(path));
 	fprintf(stderr, "    [ -g <blocks per group> ] [ -i <inodes> ] [ -I <inode size> ]\n");
-	fprintf(stderr, "    [ -L <label> ] [ -f ] [ -a <android mountpoint> ]\n");
+	fprintf(stderr, "    [ -L <label> ] [ -f ] [ -a <android mountpoint> ] [ -u ]\n");
 	fprintf(stderr, "    [ -S file_contexts ] [ -C fs_config ] [ -T timestamp ]\n");
 	fprintf(stderr, "    [ -z | -s ] [ -w ] [ -c ] [ -J ] [ -v ] [ -B <block_list_file> ]\n");
 	fprintf(stderr, "    <filename> [<directory>]\n");
@@ -70,6 +70,7 @@
 	int sparse = 0;
 	int crc = 0;
 	int wipe = 0;
+	int real_uuid = 0;
 	int fd;
 	int exitcode;
 	int verbose = 0;
@@ -80,7 +81,7 @@
 	struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "" } };
 #endif
 
-	while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:S:T:C:B:fwzJsctv")) != -1) {
+	while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:S:T:C:B:fwzJsctvu")) != -1) {
 		switch (opt) {
 		case 'l':
 			info.len = parse_num(optarg);
@@ -118,6 +119,9 @@
 		case 'w':
 			wipe = 1;
 			break;
+		case 'u':
+			real_uuid = 1;
+			break;
 		case 'z':
 			gzip = 1;
 			break;
@@ -227,7 +231,7 @@
 	}
 
 	exitcode = make_ext4fs_internal(fd, directory, mountpoint, fs_config_func, gzip,
-		sparse, crc, wipe, sehnd, verbose, fixed_time, block_list_file);
+		sparse, crc, wipe, real_uuid, sehnd, verbose, fixed_time, block_list_file);
 	close(fd);
 	if (block_list_file)
 		fclose(block_list_file);
diff --git a/ext4_utils/uuid.c b/ext4_utils/uuid.c
deleted file mode 100644
index 33d2494..0000000
--- a/ext4_utils/uuid.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed 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.
- */
-
-#include <string.h>
-
-#ifdef USE_MINGW
-#include <winsock2.h>
-#else
-#include <arpa/inet.h>
-#endif
-
-#include "ext4_utils.h"
-#include "sha1.h"
-#include "uuid.h"
-
-/* Definition from RFC-4122 */
-struct uuid {
-	u32 time_low;
-	u16 time_mid;
-	u16 time_hi_and_version;
-	u8 clk_seq_hi_res;
-	u8 clk_seq_low;
-	u16 node0_1;
-	u32 node2_5;
-};
-
-static void sha1_hash(const char *namespace, const char *name,
-	unsigned char sha1[SHA1_DIGEST_LENGTH])
-{
-	SHA1_CTX ctx;
-	SHA1Init(&ctx);
-	SHA1Update(&ctx, (const u8*)namespace, strlen(namespace));
-	SHA1Update(&ctx, (const u8*)name, strlen(name));
-	SHA1Final(sha1, &ctx);
-}
-
-void generate_uuid(const char *namespace, const char *name, u8 result[16])
-{
-	unsigned char sha1[SHA1_DIGEST_LENGTH];
-	struct uuid *uuid = (struct uuid *)result;
-
-	sha1_hash(namespace, name, (unsigned char*)sha1);
-	memcpy(uuid, sha1, sizeof(struct uuid));
-
-	uuid->time_low = ntohl(uuid->time_low);
-	uuid->time_mid = ntohs(uuid->time_mid);
-	uuid->time_hi_and_version = ntohs(uuid->time_hi_and_version);
-	uuid->time_hi_and_version &= 0x0FFF;
-	uuid->time_hi_and_version |= (5 << 12);
-	uuid->clk_seq_hi_res &= ~(1 << 6);
-	uuid->clk_seq_hi_res |= 1 << 7;
-}
diff --git a/ext4_utils/uuid.h b/ext4_utils/uuid.h
deleted file mode 100644
index ff1b438..0000000
--- a/ext4_utils/uuid.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed 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.
- */
-
-#ifndef _UUID_H_
-#define _UUID_H_
-
-#include "ext4_utils.h"
-
-void generate_uuid(const char *namespace, const char *name, u8 result[16]);
-
-#endif