Merge "Remove LOCAL_CLANG"
diff --git a/otautil/DirUtil.cpp b/otautil/DirUtil.cpp
index e08e360..ad344de 100644
--- a/otautil/DirUtil.cpp
+++ b/otautil/DirUtil.cpp
@@ -160,59 +160,3 @@
     }
     return 0;
 }
-
-int
-dirUnlinkHierarchy(const char *path)
-{
-    struct stat st;
-    DIR *dir;
-    struct dirent *de;
-    int fail = 0;
-
-    /* is it a file or directory? */
-    if (lstat(path, &st) < 0) {
-        return -1;
-    }
-
-    /* a file, so unlink it */
-    if (!S_ISDIR(st.st_mode)) {
-        return unlink(path);
-    }
-
-    /* a directory, so open handle */
-    dir = opendir(path);
-    if (dir == NULL) {
-        return -1;
-    }
-
-    /* recurse over components */
-    errno = 0;
-    while ((de = readdir(dir)) != NULL) {
-        //TODO: don't blow the stack
-        char dn[PATH_MAX];
-        if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, ".")) {
-            continue;
-        }
-        snprintf(dn, sizeof(dn), "%s/%s", path, de->d_name);
-        if (dirUnlinkHierarchy(dn) < 0) {
-            fail = 1;
-            break;
-        }
-        errno = 0;
-    }
-    /* in case readdir or unlink_recursive failed */
-    if (fail || errno < 0) {
-        int save = errno;
-        closedir(dir);
-        errno = save;
-        return -1;
-    }
-
-    /* close directory handle */
-    if (closedir(dir) < 0) {
-        return -1;
-    }
-
-    /* delete target directory */
-    return rmdir(path);
-}
diff --git a/otautil/DirUtil.h b/otautil/DirUtil.h
index 85b83c3..beecc10 100644
--- a/otautil/DirUtil.h
+++ b/otautil/DirUtil.h
@@ -17,13 +17,8 @@
 #ifndef MINZIP_DIRUTIL_H_
 #define MINZIP_DIRUTIL_H_
 
-#include <stdbool.h>
 #include <utime.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 struct selabel_handle;
 
 /* Like "mkdir -p", try to guarantee that all directories
@@ -43,12 +38,4 @@
         const struct utimbuf *timestamp, bool stripFileName,
         struct selabel_handle* sehnd);
 
-/* rm -rf <path>
- */
-int dirUnlinkHierarchy(const char *path);
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif  // MINZIP_DIRUTIL_H_
diff --git a/recovery.cpp b/recovery.cpp
index 55b12d5..8f3e9bd 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -1594,15 +1594,14 @@
             ui->Print("Rebooting automatically.\n");
         }
     } else if (!just_exit) {
-        status = INSTALL_NONE;  // No command specified
-        ui->SetBackground(RecoveryUI::NO_COMMAND);
-
-        // http://b/17489952
-        // If this is an eng or userdebug build, automatically turn on the
-        // text display if no command is specified.
-        if (is_ro_debuggable()) {
-            ui->ShowText(true);
-        }
+      // If this is an eng or userdebug build, automatically turn on the text display if no command
+      // is specified. Note that this should be called before setting the background to avoid
+      // flickering the background image.
+      if (is_ro_debuggable()) {
+        ui->ShowText(true);
+      }
+      status = INSTALL_NONE;  // No command specified
+      ui->SetBackground(RecoveryUI::NO_COMMAND);
     }
 
     if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) {
diff --git a/roots.cpp b/roots.cpp
index 0360bde..46e5c1b 100644
--- a/roots.cpp
+++ b/roots.cpp
@@ -28,6 +28,7 @@
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
 #include <cryptfs.h>
 #include <ext4_utils/wipe.h>
 #include <fs_mgr.h>
@@ -165,6 +166,23 @@
     return WEXITSTATUS(status);
 }
 
+static ssize_t get_file_size(int fd, uint64_t reserve_len) {
+  struct stat buf;
+  int ret = fstat(fd, &buf);
+  if (ret) return 0;
+
+  ssize_t computed_size;
+  if (S_ISREG(buf.st_mode)) {
+    computed_size = buf.st_size - reserve_len;
+  } else if (S_ISBLK(buf.st_mode)) {
+    computed_size = get_block_device_size(fd) - reserve_len;
+  } else {
+    computed_size = 0;
+  }
+
+  return computed_size;
+}
+
 int format_volume(const char* volume, const char* directory) {
     Volume* v = volume_for_path(volume);
     if (v == NULL) {
@@ -204,7 +222,16 @@
         if (v->length != 0) {
             length = v->length;
         } else if (v->key_loc != NULL && strcmp(v->key_loc, "footer") == 0) {
-            length = -CRYPT_FOOTER_OFFSET;
+          android::base::unique_fd fd(open(v->blk_device, O_RDONLY));
+          if (fd < 0) {
+            PLOG(ERROR) << "get_file_size: failed to open " << v->blk_device;
+            return -1;
+          }
+          length = get_file_size(fd.get(), CRYPT_FOOTER_OFFSET);
+          if (length <= 0) {
+            LOG(ERROR) << "get_file_size: invalid size " << length << " for " << v->blk_device;
+            return -1;
+          }
         }
         int result;
         if (strcmp(v->fs_type, "ext4") == 0) {
@@ -262,16 +289,6 @@
             result = exec_cmd(e2fsdroid_argv[0], const_cast<char**>(e2fsdroid_argv));
           }
         } else {   /* Has to be f2fs because we checked earlier. */
-            if (v->key_loc != NULL && strcmp(v->key_loc, "footer") == 0 && length < 0) {
-                LOG(ERROR) << "format_volume: crypt footer + negative length (" << length
-                           << ") not supported on " << v->fs_type;
-                return -1;
-            }
-            if (length < 0) {
-                LOG(ERROR) << "format_volume: negative length (" << length
-                           << ") not supported on " << v->fs_type;
-                return -1;
-            }
             char *num_sectors = nullptr;
             if (length >= 512 && asprintf(&num_sectors, "%zd", length / 512) <= 0) {
                 LOG(ERROR) << "format_volume: failed to create " << v->fs_type
diff --git a/tests/unit/dirutil_test.cpp b/tests/unit/dirutil_test.cpp
index 5e2ae4f..e62032c 100644
--- a/tests/unit/dirutil_test.cpp
+++ b/tests/unit/dirutil_test.cpp
@@ -116,35 +116,3 @@
   ASSERT_EQ(0, rmdir((prefix + "/a/b").c_str()));
   ASSERT_EQ(0, rmdir((prefix + "/a").c_str()));
 }
-
-TEST(DirUtilTest, unlink_invalid) {
-  // File doesn't exist.
-  ASSERT_EQ(-1, dirUnlinkHierarchy("doesntexist"));
-
-  // Nonexistent directory.
-  TemporaryDir td;
-  std::string path(td.path);
-  ASSERT_EQ(-1, dirUnlinkHierarchy((path + "/a").c_str()));
-  ASSERT_EQ(ENOENT, errno);
-}
-
-TEST(DirUtilTest, unlink_smoke) {
-  // Unlink a file.
-  TemporaryFile tf;
-  ASSERT_EQ(0, dirUnlinkHierarchy(tf.path));
-  ASSERT_EQ(-1, access(tf.path, F_OK));
-
-  TemporaryDir td;
-  std::string path(td.path);
-  constexpr mode_t mode = 0700;
-  ASSERT_EQ(0, mkdir((path + "/a").c_str(), mode));
-  ASSERT_EQ(0, mkdir((path + "/a/b").c_str(), mode));
-  ASSERT_EQ(0, mkdir((path + "/a/b/c").c_str(), mode));
-  ASSERT_EQ(0, mkdir((path + "/a/d").c_str(), mode));
-
-  // Remove "../a" recursively.
-  ASSERT_EQ(0, dirUnlinkHierarchy((path + "/a").c_str()));
-
-  // Verify it's gone.
-  ASSERT_EQ(-1, access((path + "/a").c_str(), F_OK));
-}
diff --git a/updater/install.cpp b/updater/install.cpp
index bfe91e7..8e54c2e 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -95,34 +95,6 @@
   uiPrint(state, error_msg);
 }
 
-static bool is_dir(const std::string& dirpath) {
-  struct stat st;
-  return stat(dirpath.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
-}
-
-// Create all parent directories of name, if necessary.
-static bool make_parents(const std::string& name) {
-  size_t prev_end = 0;
-  while (prev_end < name.size()) {
-    size_t next_end = name.find('/', prev_end + 1);
-    if (next_end == std::string::npos) {
-      break;
-    }
-    std::string dir_path = name.substr(0, next_end);
-    if (!is_dir(dir_path)) {
-      int result = mkdir(dir_path.c_str(), 0700);
-      if (result != 0) {
-        PLOG(ERROR) << "failed to mkdir " << dir_path << " when make parents for " << name;
-        return false;
-      }
-
-      LOG(INFO) << "created [" << dir_path << "]";
-    }
-    prev_end = next_end;
-  }
-  return true;
-}
-
 // mount(fs_type, partition_type, location, mount_point)
 // mount(fs_type, partition_type, location, mount_point, mount_options)