diff --git a/src/writer_process/ipc.rs b/src/writer_process/ipc.rs index 444c423..a0a730c 100644 --- a/src/writer_process/ipc.rs +++ b/src/writer_process/ipc.rs @@ -49,6 +49,7 @@ pub enum ErrorType { VerificationFailed, UnexpectedTermination, UnknownChildProcError(String), + FailedToUnmount { message: String, exit_code: i32 }, } impl From for ErrorType { @@ -75,6 +76,10 @@ impl Display for ErrorType { ErrorType::UnknownChildProcError(err) => { write!(f, "Unknown error occurred in child process: {err}") } + ErrorType::FailedToUnmount { message, exit_code } => write!( + f, + "Failed to unmount disk (exit code {exit_code})\n{message}" + ), } } } diff --git a/src/writer_process/mod.rs b/src/writer_process/mod.rs index 65e4576..a81f052 100644 --- a/src/writer_process/mod.rs +++ b/src/writer_process/mod.rs @@ -3,6 +3,8 @@ //! IT IS NOT TO BE USED DIRECTLY BY THE USER! ITS API HAS NO STABILITY GUARANTEES! use std::fs::OpenOptions; +use std::os::unix::process::ExitStatusExt; +use std::process::{Command, Stdio}; use std::{ fs::File, io::{self, Read, Seek, Write}, @@ -10,7 +12,7 @@ use std::{ use aligned_vec::avec_rt; use interprocess::local_socket::{prelude::*, GenericFilePath}; -use tracing::info; +use tracing::{debug, info}; use tracing_unwrap::ResultExt; use crate::childproc_common::child_init; @@ -60,6 +62,36 @@ pub fn main() { } fn run(mut tx: impl FnMut(StatusMessage), args: &WriterProcessConfig) -> Result<(), ErrorType> { + if cfg!(target_os = "macos") { + let mut command = Command::new("diskutil"); + command + .arg("unmountdisk") + .arg(&args.dest) + .stdin(Stdio::null()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); + + info!(?command, "spawning process to unmount disk"); + let mut child = command.spawn()?; + debug!("successfully ran diskutil, waiting on child process"); + + let exit = child.wait()?; + let mut stderr = String::new(); + child.stderr.take().unwrap().read_to_string(&mut stderr)?; + let mut stdout = String::new(); + child.stdout.take().unwrap().read_to_string(&mut stdout)?; + + debug!(?exit, ?stderr, "child exited"); + + let exit_code = exit.into_raw(); + if !exit.success() { + return Err(ErrorType::FailedToUnmount { + message: format!("stderr: {stderr}\nstdout: {stdout}"), + exit_code, + }); + } + } + info!("Opening file {}", args.src.to_string_lossy()); let mut file = File::open(&args.src).unwrap_or_log(); let size = file.seek(io::SeekFrom::End(0))?;