Add method to create empty writable partition.

For now this is just a sparse file to be used as raw image, but in
future it will be a QCOW2 image.

Bug: 190503448
Test: vm create-partition /data/local/tmp/blah 1000000
Change-Id: Ic07cd96b1a05bfaade1fa48d75d1ed3167d32795
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index c295388..7b63917 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -30,7 +30,9 @@
 };
 use command_fds::FdMapping;
 use log::{debug, error, warn};
+use std::convert::TryInto;
 use std::fs::{File, create_dir};
+use std::io::{Seek, SeekFrom, Write};
 use std::os::unix::io::AsRawFd;
 use std::path::{Path, PathBuf};
 use std::sync::{Arc, Mutex, Weak};
@@ -131,6 +133,36 @@
         Ok(VirtualMachine::create(instance))
     }
 
+    /// Initialise an empty partition image of the given size to be used as a writable partition.
+    fn initializeWritablePartition(
+        &self,
+        image_fd: &ParcelFileDescriptor,
+        size: i64,
+    ) -> binder::Result<()> {
+        let size: u64 = size.try_into().map_err(|e| {
+            error!("Invalid size {}: {}", size, e);
+            StatusCode::BAD_VALUE
+        })?;
+        let mut image = clone_file(image_fd)?;
+
+        // TODO: create a QCOW2 image instead, like `crosvm create_qcow2`, once `mk_cdisk` supports
+        // it (b/189211641).
+        if size > 0 {
+            // Extend the file to the given size by seeking to the size we want and writing a single
+            // 0 byte there.
+            image.seek(SeekFrom::Start(size - 1)).map_err(|e| {
+                error!("Failed to seek to desired size of image file ({}): {}.", size, e);
+                StatusCode::UNKNOWN_ERROR
+            })?;
+            image.write_all(&[0]).map_err(|e| {
+                error!("Failed to write 0 to image file: {}.", e);
+                StatusCode::UNKNOWN_ERROR
+            })?;
+        }
+
+        Ok(())
+    }
+
     /// Get a list of all currently running VMs. This method is only intended for debug purposes,
     /// and as such is only permitted from the shell user.
     fn debugListVms(&self) -> binder::Result<Vec<VirtualMachineDebugInfo>> {