fastbootd: Add support for flashing logical partitions.

When flashing logical partitions, we read the "super" partition metadata
corresponding to the current slot. We then temporarily create a
device-mapper device for that partition, and immediately destroy the
device after all operations are complete. We do not mount partitions
ahead of time, or keep them mounted, because a fastboot operation may
change the layout of the logical partition table (or change which slot
is current).

Bug: 78793464
Test: fastboot flash a logical partition under "super"
Change-Id: Id2a61d3592decabeebfd283c4fd6e6cbe576a18c
diff --git a/fastboot/device/utility.h b/fastboot/device/utility.h
index 26f486b..0931fc3 100644
--- a/fastboot/device/utility.h
+++ b/fastboot/device/utility.h
@@ -29,6 +29,17 @@
   public:
     PartitionHandle() {}
     explicit PartitionHandle(const std::string& path) : path_(path) {}
+    PartitionHandle(const std::string& path, std::function<void()>&& closer)
+        : path_(path), closer_(std::move(closer)) {}
+    PartitionHandle(PartitionHandle&& other) = default;
+    PartitionHandle& operator=(PartitionHandle&& other) = default;
+    ~PartitionHandle() {
+        if (closer_) {
+            // Make sure the device is closed first.
+            fd_ = {};
+            closer_();
+        }
+    }
     const std::string& path() const { return path_; }
     int fd() const { return fd_.get(); }
     void set_fd(android::base::unique_fd&& fd) { fd_ = std::move(fd); }
@@ -36,11 +47,14 @@
   private:
     std::string path_;
     android::base::unique_fd fd_;
+    std::function<void()> closer_;
 };
 
 class FastbootDevice;
 
 std::optional<std::string> FindPhysicalPartition(const std::string& name);
+bool LogicalPartitionExists(const std::string& name, const std::string& slot_suffix,
+                            bool* is_zero_length = nullptr);
 bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHandle* handle);
 
 bool GetSlotNumber(const std::string& slot, android::hardware::boot::V1_0::Slot* number);