Merge changes from topic "fastbootd-flashall"

* changes:
  fastbootd: Support flashall with logical partitions.
  fastboot: Use _WIN32 instead of WIN32.
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index a679143..7da0a9f 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -64,6 +64,7 @@
 LOCAL_C_INCLUDES_windows := development/host/windows/usb/api
 LOCAL_CFLAGS := $(fastboot_cflags)
 LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin)
+LOCAL_CPP_STD := c++17
 LOCAL_CXX_STL := $(fastboot_stl)
 LOCAL_HEADER_LIBRARIES := bootimg_headers
 LOCAL_LDLIBS_darwin := $(fastboot_ldlibs_darwin)
@@ -82,7 +83,6 @@
 
 LOCAL_CFLAGS := $(fastboot_cflags)
 LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin)
-LOCAL_CPP_STD := c++17
 LOCAL_CXX_STL := $(fastboot_stl)
 LOCAL_HEADER_LIBRARIES := bootimg_headers
 LOCAL_LDLIBS_darwin := $(fastboot_ldlibs_darwin)
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index db6d5d6..20c3359 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -104,9 +104,10 @@
     void* data;
     int64_t sz;
     int fd;
+    int64_t image_size;
 };
 
-static struct {
+struct Image {
     const char* nickname;
     const char* img_name;
     const char* sig_name;
@@ -114,7 +115,9 @@
     bool optional_if_no_image;
     bool optional_if_no_partition;
     bool IsSecondary() const { return nickname == nullptr; }
-} images[] = {
+};
+
+static Image images[] = {
         // clang-format off
     { "boot",     "boot.img",         "boot.sig",     "boot",     false, false },
     { nullptr,    "boot_other.img",   "boot.sig",     "boot",     true,  false },
@@ -128,7 +131,6 @@
                                                       "product_services",
                                                                   true,  true  },
     { "recovery", "recovery.img",     "recovery.sig", "recovery", true,  false },
-    { "super",    "super.img",        "super.sig",    "super",    true,  true  },
     { "system",   "system.img",       "system.sig",   "system",   false, true  },
     { nullptr,    "system_other.img", "system.sig",   "system",   true,  false },
     { "vbmeta",   "vbmeta.img",       "vbmeta.sig",   "vbmeta",   true,  false },
@@ -773,6 +775,13 @@
         return false;
     }
 
+    if (sparse_file* s = sparse_file_import_auto(fd, false, false)) {
+        buf->image_size = sparse_file_len(s, false, false);
+        sparse_file_destroy(s);
+    } else {
+        buf->image_size = sz;
+    }
+
     lseek64(fd, 0, SEEK_SET);
     int64_t limit = get_sparse_limit(sz);
     if (limit) {
@@ -1044,6 +1053,11 @@
     }
 }
 
+static bool is_userspace_fastboot() {
+    std::string value;
+    return fb_getvar("is-userspace", &value) && value == "yes";
+}
+
 static bool if_partition_exists(const std::string& partition, const std::string& slot) {
     std::string has_slot;
     std::string partition_name = partition;
@@ -1158,7 +1172,42 @@
     fb_queue_command("signature", "installing signature");
 }
 
-static void do_flashall(const std::string& slot_override, bool skip_secondary) {
+static bool is_logical(const std::string& partition) {
+    std::string value;
+    return fb_getvar("is-logical:" + partition, &value) && value == "yes";
+}
+
+static void update_super_partition(bool force_wipe) {
+    if (!if_partition_exists("super", "")) {
+        return;
+    }
+    std::string image = find_item_given_name("super_empty.img");
+    if (access(image.c_str(), R_OK) < 0) {
+        return;
+    }
+
+    if (!is_userspace_fastboot()) {
+        die("Must have userspace fastboot to flash logical partitions");
+    }
+
+    int fd = open(image.c_str(), O_RDONLY);
+    if (fd < 0) {
+        die("could not open '%s': %s", image.c_str(), strerror(errno));
+    }
+    fb_queue_download_fd("super", fd, get_file_size(fd));
+
+    std::string command = "update-super:super";
+    if (force_wipe) {
+        command += ":wipe";
+    }
+    fb_queue_command(command, "Updating super partition");
+
+    // We need these commands to have finished before proceeding, since
+    // otherwise "getvar is-logical" may not return a correct answer below.
+    fb_execute_queue();
+}
+
+static void do_flashall(const std::string& slot_override, bool skip_secondary, bool wipe) {
     std::string fname;
     queue_info_dump();
 
@@ -1188,6 +1237,10 @@
         }
     }
 
+    update_super_partition(wipe);
+
+    // List of partitions to flash and their slots.
+    std::vector<std::pair<const Image*, std::string>> entries;
     for (size_t i = 0; i < arraysize(images); i++) {
         const char* slot = NULL;
         if (images[i].IsSecondary()) {
@@ -1196,21 +1249,38 @@
             slot = slot_override.c_str();
         }
         if (!slot) continue;
-        fname = find_item_given_name(images[i].img_name);
+        entries.emplace_back(&images[i], slot);
+
+        // Resize any logical partition to 0, so each partition is reset to 0
+        // extents, and will achieve more optimal allocation.
+        auto resize_partition = [](const std::string& partition) -> void {
+            if (is_logical(partition)) {
+                fb_queue_resize_partition(partition, "0");
+            }
+        };
+        do_for_partitions(images[i].part_name, slot, resize_partition, false);
+    }
+
+    // Flash each partition in the list if it has a corresponding image.
+    for (const auto& [image, slot] : entries) {
+        fname = find_item_given_name(image->img_name);
         fastboot_buffer buf;
         if (!load_buf(fname.c_str(), &buf)) {
-            if (images[i].optional_if_no_image) continue;
-            die("could not load '%s': %s", images[i].img_name, strerror(errno));
+            if (image->optional_if_no_image) continue;
+            die("could not load '%s': %s", image->img_name, strerror(errno));
         }
-        if (images[i].optional_if_no_partition &&
-            !if_partition_exists(images[i].part_name, slot)) {
+        if (image->optional_if_no_partition &&
+            !if_partition_exists(image->part_name, slot)) {
             continue;
         }
         auto flashall = [&](const std::string &partition) {
             do_send_signature(fname.c_str());
+            if (is_logical(partition)) {
+                fb_queue_resize_partition(partition, std::to_string(buf.image_size));
+            }
             flash_buf(partition.c_str(), &buf);
         };
-        do_for_partitions(images[i].part_name, slot, flashall, false);
+        do_for_partitions(image->part_name, slot, flashall, false);
     }
 
     if (slot_override == "all") {
@@ -1648,9 +1718,9 @@
         } else if (command == "flashall") {
             if (slot_override == "all") {
                 fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
-                do_flashall(slot_override, true);
+                do_flashall(slot_override, true, wants_wipe);
             } else {
-                do_flashall(slot_override, skip_secondary);
+                do_flashall(slot_override, skip_secondary, wants_wipe);
             }
             wants_reboot = true;
         } else if (command == "update") {
diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp
index b0ac2ef..fc6a16b 100644
--- a/fastboot/fs.cpp
+++ b/fastboot/fs.cpp
@@ -8,7 +8,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#ifndef WIN32
+#ifndef _WIN32
 #include <sys/wait.h>
 #else
 #include <tchar.h>
@@ -27,7 +27,7 @@
 using android::base::StringPrintf;
 using android::base::unique_fd;
 
-#ifdef WIN32
+#ifdef _WIN32
 static int exec_cmd(const char* path, const char** argv, const char** envp) {
     std::string cmd;
     int i = 0;