xref: /aosp_15_r20/external/crosvm/src/main.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker //! Runs a virtual machine
6*bb4ee6a4SAndroid Build Coastguard Worker //!
7*bb4ee6a4SAndroid Build Coastguard Worker //! ## Feature flags
8*bb4ee6a4SAndroid Build Coastguard Worker #![cfg_attr(feature = "document-features", doc = document_features::document_features!())]
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(feature = "composite-disk", feature = "qcow"))]
11*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::OpenOptions;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
13*bb4ee6a4SAndroid Build Coastguard Worker 
14*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow;
15*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
16*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Result;
17*bb4ee6a4SAndroid Build Coastguard Worker use argh::FromArgs;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::debug;
19*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
20*bb4ee6a4SAndroid Build Coastguard Worker use base::info;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::set_thread_name;
22*bb4ee6a4SAndroid Build Coastguard Worker use base::syslog;
23*bb4ee6a4SAndroid Build Coastguard Worker use base::syslog::LogArgs;
24*bb4ee6a4SAndroid Build Coastguard Worker use base::syslog::LogConfig;
25*bb4ee6a4SAndroid Build Coastguard Worker use cmdline::RunCommand;
26*bb4ee6a4SAndroid Build Coastguard Worker mod crosvm;
27*bb4ee6a4SAndroid Build Coastguard Worker use crosvm::cmdline;
28*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "plugin")]
29*bb4ee6a4SAndroid Build Coastguard Worker use crosvm::config::executable_is_plugin;
30*bb4ee6a4SAndroid Build Coastguard Worker use crosvm::config::Config;
31*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::vhost::user::device::run_block_device;
32*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
33*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::vhost::user::device::run_gpu_device;
34*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "net")]
35*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::vhost::user::device::run_net_device;
36*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "audio")]
37*bb4ee6a4SAndroid Build Coastguard Worker use devices::virtio::vhost::user::device::run_snd_device;
38*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "composite-disk")]
39*bb4ee6a4SAndroid Build Coastguard Worker use disk::create_composite_disk;
40*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "composite-disk")]
41*bb4ee6a4SAndroid Build Coastguard Worker use disk::create_zero_filler;
42*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "composite-disk")]
43*bb4ee6a4SAndroid Build Coastguard Worker use disk::open_disk_file;
44*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(feature = "composite-disk", feature = "qcow"))]
45*bb4ee6a4SAndroid Build Coastguard Worker use disk::DiskFileParams;
46*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "composite-disk")]
47*bb4ee6a4SAndroid Build Coastguard Worker use disk::ImagePartitionType;
48*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "composite-disk")]
49*bb4ee6a4SAndroid Build Coastguard Worker use disk::PartitionInfo;
50*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "qcow")]
51*bb4ee6a4SAndroid Build Coastguard Worker use disk::QcowFile;
52*bb4ee6a4SAndroid Build Coastguard Worker mod sys;
53*bb4ee6a4SAndroid Build Coastguard Worker use crosvm::cmdline::Command;
54*bb4ee6a4SAndroid Build Coastguard Worker use crosvm::cmdline::CrossPlatformCommands;
55*bb4ee6a4SAndroid Build Coastguard Worker use crosvm::cmdline::CrossPlatformDevicesCommands;
56*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
57*bb4ee6a4SAndroid Build Coastguard Worker use sys::windows::setup_metrics_reporting;
58*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "composite-disk")]
59*bb4ee6a4SAndroid Build Coastguard Worker use uuid::Uuid;
60*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
61*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::do_gpu_display_add;
62*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
63*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::do_gpu_display_list;
64*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
65*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::do_gpu_display_remove;
66*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
67*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::do_gpu_set_display_mouse_mode;
68*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::do_modify_battery;
69*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pci-hotplug")]
70*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::do_net_add;
71*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pci-hotplug")]
72*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::do_net_remove;
73*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::do_security_key_attach;
74*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::do_swap_status;
75*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::do_usb_attach;
76*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::do_usb_detach;
77*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::do_usb_list;
78*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")]
79*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::handle_request;
80*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::vms_request;
81*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
82*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::ModifyGpuResult;
83*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::client::ModifyUsbResult;
84*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")]
85*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::BalloonControlCommand;
86*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::DiskControlCommand;
87*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::HotPlugDeviceInfo;
88*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::HotPlugDeviceType;
89*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::SnapshotCommand;
90*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::SwapCommand;
91*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::UsbControlResult;
92*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmRequest;
93*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")]
94*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmResponse;
95*bb4ee6a4SAndroid Build Coastguard Worker 
96*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::error_to_exit_code;
97*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::init_log;
98*bb4ee6a4SAndroid Build Coastguard Worker 
99*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "scudo")]
100*bb4ee6a4SAndroid Build Coastguard Worker #[global_allocator]
101*bb4ee6a4SAndroid Build Coastguard Worker static ALLOCATOR: scudo::GlobalScudoAllocator = scudo::GlobalScudoAllocator;
102*bb4ee6a4SAndroid Build Coastguard Worker 
103*bb4ee6a4SAndroid Build Coastguard Worker #[repr(i32)]
104*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Debug, PartialEq, Eq)]
105*bb4ee6a4SAndroid Build Coastguard Worker /// Exit code from crosvm,
106*bb4ee6a4SAndroid Build Coastguard Worker enum CommandStatus {
107*bb4ee6a4SAndroid Build Coastguard Worker     /// Exit with success. Also used to mean VM stopped successfully.
108*bb4ee6a4SAndroid Build Coastguard Worker     SuccessOrVmStop = 0,
109*bb4ee6a4SAndroid Build Coastguard Worker     /// VM requested reset.
110*bb4ee6a4SAndroid Build Coastguard Worker     VmReset = 32,
111*bb4ee6a4SAndroid Build Coastguard Worker     /// VM crashed.
112*bb4ee6a4SAndroid Build Coastguard Worker     VmCrash = 33,
113*bb4ee6a4SAndroid Build Coastguard Worker     /// VM exit due to kernel panic in guest.
114*bb4ee6a4SAndroid Build Coastguard Worker     GuestPanic = 34,
115*bb4ee6a4SAndroid Build Coastguard Worker     /// Invalid argument was given to crosvm.
116*bb4ee6a4SAndroid Build Coastguard Worker     InvalidArgs = 35,
117*bb4ee6a4SAndroid Build Coastguard Worker     /// VM exit due to vcpu stall detection.
118*bb4ee6a4SAndroid Build Coastguard Worker     WatchdogReset = 36,
119*bb4ee6a4SAndroid Build Coastguard Worker }
120*bb4ee6a4SAndroid Build Coastguard Worker 
121*bb4ee6a4SAndroid Build Coastguard Worker impl CommandStatus {
message(&self) -> &'static str122*bb4ee6a4SAndroid Build Coastguard Worker     fn message(&self) -> &'static str {
123*bb4ee6a4SAndroid Build Coastguard Worker         match self {
124*bb4ee6a4SAndroid Build Coastguard Worker             Self::SuccessOrVmStop => "exiting with success",
125*bb4ee6a4SAndroid Build Coastguard Worker             Self::VmReset => "exiting with reset",
126*bb4ee6a4SAndroid Build Coastguard Worker             Self::VmCrash => "exiting with crash",
127*bb4ee6a4SAndroid Build Coastguard Worker             Self::GuestPanic => "exiting with guest panic",
128*bb4ee6a4SAndroid Build Coastguard Worker             Self::InvalidArgs => "invalid argument",
129*bb4ee6a4SAndroid Build Coastguard Worker             Self::WatchdogReset => "exiting with watchdog reset",
130*bb4ee6a4SAndroid Build Coastguard Worker         }
131*bb4ee6a4SAndroid Build Coastguard Worker     }
132*bb4ee6a4SAndroid Build Coastguard Worker }
133*bb4ee6a4SAndroid Build Coastguard Worker 
134*bb4ee6a4SAndroid Build Coastguard Worker impl From<sys::ExitState> for CommandStatus {
from(result: sys::ExitState) -> CommandStatus135*bb4ee6a4SAndroid Build Coastguard Worker     fn from(result: sys::ExitState) -> CommandStatus {
136*bb4ee6a4SAndroid Build Coastguard Worker         match result {
137*bb4ee6a4SAndroid Build Coastguard Worker             sys::ExitState::Stop => CommandStatus::SuccessOrVmStop,
138*bb4ee6a4SAndroid Build Coastguard Worker             sys::ExitState::Reset => CommandStatus::VmReset,
139*bb4ee6a4SAndroid Build Coastguard Worker             sys::ExitState::Crash => CommandStatus::VmCrash,
140*bb4ee6a4SAndroid Build Coastguard Worker             sys::ExitState::GuestPanic => CommandStatus::GuestPanic,
141*bb4ee6a4SAndroid Build Coastguard Worker             sys::ExitState::WatchdogReset => CommandStatus::WatchdogReset,
142*bb4ee6a4SAndroid Build Coastguard Worker         }
143*bb4ee6a4SAndroid Build Coastguard Worker     }
144*bb4ee6a4SAndroid Build Coastguard Worker }
145*bb4ee6a4SAndroid Build Coastguard Worker 
run_vm(cmd: RunCommand, log_config: LogConfig) -> Result<CommandStatus>146*bb4ee6a4SAndroid Build Coastguard Worker fn run_vm(cmd: RunCommand, log_config: LogConfig) -> Result<CommandStatus> {
147*bb4ee6a4SAndroid Build Coastguard Worker     let cfg = match TryInto::<Config>::try_into(cmd) {
148*bb4ee6a4SAndroid Build Coastguard Worker         Ok(cfg) => cfg,
149*bb4ee6a4SAndroid Build Coastguard Worker         Err(e) => {
150*bb4ee6a4SAndroid Build Coastguard Worker             eprintln!("{}", e);
151*bb4ee6a4SAndroid Build Coastguard Worker             return Err(anyhow!("{}", e));
152*bb4ee6a4SAndroid Build Coastguard Worker         }
153*bb4ee6a4SAndroid Build Coastguard Worker     };
154*bb4ee6a4SAndroid Build Coastguard Worker 
155*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(ref name) = cfg.name {
156*bb4ee6a4SAndroid Build Coastguard Worker         set_thread_name(name).context("Failed to set the name")?;
157*bb4ee6a4SAndroid Build Coastguard Worker     }
158*bb4ee6a4SAndroid Build Coastguard Worker 
159*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "plugin")]
160*bb4ee6a4SAndroid Build Coastguard Worker     if executable_is_plugin(&cfg.executable_path) {
161*bb4ee6a4SAndroid Build Coastguard Worker         let res = match crosvm::plugin::run_config(cfg) {
162*bb4ee6a4SAndroid Build Coastguard Worker             Ok(_) => {
163*bb4ee6a4SAndroid Build Coastguard Worker                 info!("crosvm and plugin have exited normally");
164*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(CommandStatus::SuccessOrVmStop)
165*bb4ee6a4SAndroid Build Coastguard Worker             }
166*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
167*bb4ee6a4SAndroid Build Coastguard Worker                 eprintln!("{:#}", e);
168*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e)
169*bb4ee6a4SAndroid Build Coastguard Worker             }
170*bb4ee6a4SAndroid Build Coastguard Worker         };
171*bb4ee6a4SAndroid Build Coastguard Worker         return res;
172*bb4ee6a4SAndroid Build Coastguard Worker     }
173*bb4ee6a4SAndroid Build Coastguard Worker 
174*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "crash-report")]
175*bb4ee6a4SAndroid Build Coastguard Worker     crosvm::sys::setup_emulator_crash_reporting(&cfg)?;
176*bb4ee6a4SAndroid Build Coastguard Worker 
177*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(windows)]
178*bb4ee6a4SAndroid Build Coastguard Worker     setup_metrics_reporting()?;
179*bb4ee6a4SAndroid Build Coastguard Worker 
180*bb4ee6a4SAndroid Build Coastguard Worker     init_log(log_config, &cfg)?;
181*bb4ee6a4SAndroid Build Coastguard Worker     cros_tracing::init();
182*bb4ee6a4SAndroid Build Coastguard Worker 
183*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(async_executor) = cfg.async_executor {
184*bb4ee6a4SAndroid Build Coastguard Worker         cros_async::Executor::set_default_executor_kind(async_executor)
185*bb4ee6a4SAndroid Build Coastguard Worker             .context("Failed to set the default async executor")?;
186*bb4ee6a4SAndroid Build Coastguard Worker     }
187*bb4ee6a4SAndroid Build Coastguard Worker 
188*bb4ee6a4SAndroid Build Coastguard Worker     let exit_state = crate::sys::run_config(cfg)?;
189*bb4ee6a4SAndroid Build Coastguard Worker     Ok(CommandStatus::from(exit_state))
190*bb4ee6a4SAndroid Build Coastguard Worker }
191*bb4ee6a4SAndroid Build Coastguard Worker 
stop_vms(cmd: cmdline::StopCommand) -> std::result::Result<(), ()>192*bb4ee6a4SAndroid Build Coastguard Worker fn stop_vms(cmd: cmdline::StopCommand) -> std::result::Result<(), ()> {
193*bb4ee6a4SAndroid Build Coastguard Worker     vms_request(&VmRequest::Exit, cmd.socket_path)
194*bb4ee6a4SAndroid Build Coastguard Worker }
195*bb4ee6a4SAndroid Build Coastguard Worker 
suspend_vms(cmd: cmdline::SuspendCommand) -> std::result::Result<(), ()>196*bb4ee6a4SAndroid Build Coastguard Worker fn suspend_vms(cmd: cmdline::SuspendCommand) -> std::result::Result<(), ()> {
197*bb4ee6a4SAndroid Build Coastguard Worker     if cmd.full {
198*bb4ee6a4SAndroid Build Coastguard Worker         vms_request(&VmRequest::SuspendVm, cmd.socket_path)
199*bb4ee6a4SAndroid Build Coastguard Worker     } else {
200*bb4ee6a4SAndroid Build Coastguard Worker         vms_request(&VmRequest::SuspendVcpus, cmd.socket_path)
201*bb4ee6a4SAndroid Build Coastguard Worker     }
202*bb4ee6a4SAndroid Build Coastguard Worker }
203*bb4ee6a4SAndroid Build Coastguard Worker 
swap_vms(cmd: cmdline::SwapCommand) -> std::result::Result<(), ()>204*bb4ee6a4SAndroid Build Coastguard Worker fn swap_vms(cmd: cmdline::SwapCommand) -> std::result::Result<(), ()> {
205*bb4ee6a4SAndroid Build Coastguard Worker     use cmdline::SwapSubcommands::*;
206*bb4ee6a4SAndroid Build Coastguard Worker     let (req, path) = match &cmd.nested {
207*bb4ee6a4SAndroid Build Coastguard Worker         Enable(params) => (VmRequest::Swap(SwapCommand::Enable), &params.socket_path),
208*bb4ee6a4SAndroid Build Coastguard Worker         Trim(params) => (VmRequest::Swap(SwapCommand::Trim), &params.socket_path),
209*bb4ee6a4SAndroid Build Coastguard Worker         SwapOut(params) => (VmRequest::Swap(SwapCommand::SwapOut), &params.socket_path),
210*bb4ee6a4SAndroid Build Coastguard Worker         Disable(params) => (
211*bb4ee6a4SAndroid Build Coastguard Worker             VmRequest::Swap(SwapCommand::Disable {
212*bb4ee6a4SAndroid Build Coastguard Worker                 slow_file_cleanup: params.slow_file_cleanup,
213*bb4ee6a4SAndroid Build Coastguard Worker             }),
214*bb4ee6a4SAndroid Build Coastguard Worker             &params.socket_path,
215*bb4ee6a4SAndroid Build Coastguard Worker         ),
216*bb4ee6a4SAndroid Build Coastguard Worker         Status(params) => (VmRequest::Swap(SwapCommand::Status), &params.socket_path),
217*bb4ee6a4SAndroid Build Coastguard Worker     };
218*bb4ee6a4SAndroid Build Coastguard Worker     if let VmRequest::Swap(SwapCommand::Status) = req {
219*bb4ee6a4SAndroid Build Coastguard Worker         do_swap_status(path)
220*bb4ee6a4SAndroid Build Coastguard Worker     } else {
221*bb4ee6a4SAndroid Build Coastguard Worker         vms_request(&req, path)
222*bb4ee6a4SAndroid Build Coastguard Worker     }
223*bb4ee6a4SAndroid Build Coastguard Worker }
224*bb4ee6a4SAndroid Build Coastguard Worker 
resume_vms(cmd: cmdline::ResumeCommand) -> std::result::Result<(), ()>225*bb4ee6a4SAndroid Build Coastguard Worker fn resume_vms(cmd: cmdline::ResumeCommand) -> std::result::Result<(), ()> {
226*bb4ee6a4SAndroid Build Coastguard Worker     if cmd.full {
227*bb4ee6a4SAndroid Build Coastguard Worker         vms_request(&VmRequest::ResumeVm, cmd.socket_path)
228*bb4ee6a4SAndroid Build Coastguard Worker     } else {
229*bb4ee6a4SAndroid Build Coastguard Worker         vms_request(&VmRequest::ResumeVcpus, cmd.socket_path)
230*bb4ee6a4SAndroid Build Coastguard Worker     }
231*bb4ee6a4SAndroid Build Coastguard Worker }
232*bb4ee6a4SAndroid Build Coastguard Worker 
powerbtn_vms(cmd: cmdline::PowerbtnCommand) -> std::result::Result<(), ()>233*bb4ee6a4SAndroid Build Coastguard Worker fn powerbtn_vms(cmd: cmdline::PowerbtnCommand) -> std::result::Result<(), ()> {
234*bb4ee6a4SAndroid Build Coastguard Worker     vms_request(&VmRequest::Powerbtn, cmd.socket_path)
235*bb4ee6a4SAndroid Build Coastguard Worker }
236*bb4ee6a4SAndroid Build Coastguard Worker 
sleepbtn_vms(cmd: cmdline::SleepCommand) -> std::result::Result<(), ()>237*bb4ee6a4SAndroid Build Coastguard Worker fn sleepbtn_vms(cmd: cmdline::SleepCommand) -> std::result::Result<(), ()> {
238*bb4ee6a4SAndroid Build Coastguard Worker     vms_request(&VmRequest::Sleepbtn, cmd.socket_path)
239*bb4ee6a4SAndroid Build Coastguard Worker }
240*bb4ee6a4SAndroid Build Coastguard Worker 
inject_gpe(cmd: cmdline::GpeCommand) -> std::result::Result<(), ()>241*bb4ee6a4SAndroid Build Coastguard Worker fn inject_gpe(cmd: cmdline::GpeCommand) -> std::result::Result<(), ()> {
242*bb4ee6a4SAndroid Build Coastguard Worker     vms_request(
243*bb4ee6a4SAndroid Build Coastguard Worker         &VmRequest::Gpe {
244*bb4ee6a4SAndroid Build Coastguard Worker             gpe: cmd.gpe,
245*bb4ee6a4SAndroid Build Coastguard Worker             clear_evt: None,
246*bb4ee6a4SAndroid Build Coastguard Worker         },
247*bb4ee6a4SAndroid Build Coastguard Worker         cmd.socket_path,
248*bb4ee6a4SAndroid Build Coastguard Worker     )
249*bb4ee6a4SAndroid Build Coastguard Worker }
250*bb4ee6a4SAndroid Build Coastguard Worker 
251*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")]
balloon_vms(cmd: cmdline::BalloonCommand) -> std::result::Result<(), ()>252*bb4ee6a4SAndroid Build Coastguard Worker fn balloon_vms(cmd: cmdline::BalloonCommand) -> std::result::Result<(), ()> {
253*bb4ee6a4SAndroid Build Coastguard Worker     let command = BalloonControlCommand::Adjust {
254*bb4ee6a4SAndroid Build Coastguard Worker         num_bytes: cmd.num_bytes,
255*bb4ee6a4SAndroid Build Coastguard Worker         wait_for_success: cmd.wait,
256*bb4ee6a4SAndroid Build Coastguard Worker     };
257*bb4ee6a4SAndroid Build Coastguard Worker     vms_request(&VmRequest::BalloonCommand(command), cmd.socket_path)
258*bb4ee6a4SAndroid Build Coastguard Worker }
259*bb4ee6a4SAndroid Build Coastguard Worker 
260*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")]
balloon_stats(cmd: cmdline::BalloonStatsCommand) -> std::result::Result<(), ()>261*bb4ee6a4SAndroid Build Coastguard Worker fn balloon_stats(cmd: cmdline::BalloonStatsCommand) -> std::result::Result<(), ()> {
262*bb4ee6a4SAndroid Build Coastguard Worker     let command = BalloonControlCommand::Stats {};
263*bb4ee6a4SAndroid Build Coastguard Worker     let request = &VmRequest::BalloonCommand(command);
264*bb4ee6a4SAndroid Build Coastguard Worker     let response = handle_request(request, cmd.socket_path)?;
265*bb4ee6a4SAndroid Build Coastguard Worker     match serde_json::to_string_pretty(&response) {
266*bb4ee6a4SAndroid Build Coastguard Worker         Ok(response_json) => println!("{}", response_json),
267*bb4ee6a4SAndroid Build Coastguard Worker         Err(e) => {
268*bb4ee6a4SAndroid Build Coastguard Worker             error!("Failed to serialize into JSON: {}", e);
269*bb4ee6a4SAndroid Build Coastguard Worker             return Err(());
270*bb4ee6a4SAndroid Build Coastguard Worker         }
271*bb4ee6a4SAndroid Build Coastguard Worker     }
272*bb4ee6a4SAndroid Build Coastguard Worker     match response {
273*bb4ee6a4SAndroid Build Coastguard Worker         VmResponse::BalloonStats { .. } => Ok(()),
274*bb4ee6a4SAndroid Build Coastguard Worker         _ => Err(()),
275*bb4ee6a4SAndroid Build Coastguard Worker     }
276*bb4ee6a4SAndroid Build Coastguard Worker }
277*bb4ee6a4SAndroid Build Coastguard Worker 
278*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "balloon")]
balloon_ws(cmd: cmdline::BalloonWsCommand) -> std::result::Result<(), ()>279*bb4ee6a4SAndroid Build Coastguard Worker fn balloon_ws(cmd: cmdline::BalloonWsCommand) -> std::result::Result<(), ()> {
280*bb4ee6a4SAndroid Build Coastguard Worker     let command = BalloonControlCommand::WorkingSet {};
281*bb4ee6a4SAndroid Build Coastguard Worker     let request = &VmRequest::BalloonCommand(command);
282*bb4ee6a4SAndroid Build Coastguard Worker     let response = handle_request(request, cmd.socket_path)?;
283*bb4ee6a4SAndroid Build Coastguard Worker     match serde_json::to_string_pretty(&response) {
284*bb4ee6a4SAndroid Build Coastguard Worker         Ok(response_json) => println!("{response_json}"),
285*bb4ee6a4SAndroid Build Coastguard Worker         Err(e) => {
286*bb4ee6a4SAndroid Build Coastguard Worker             error!("Failed to serialize into JSON: {e}");
287*bb4ee6a4SAndroid Build Coastguard Worker             return Err(());
288*bb4ee6a4SAndroid Build Coastguard Worker         }
289*bb4ee6a4SAndroid Build Coastguard Worker     }
290*bb4ee6a4SAndroid Build Coastguard Worker     match response {
291*bb4ee6a4SAndroid Build Coastguard Worker         VmResponse::BalloonWS { .. } => Ok(()),
292*bb4ee6a4SAndroid Build Coastguard Worker         _ => Err(()),
293*bb4ee6a4SAndroid Build Coastguard Worker     }
294*bb4ee6a4SAndroid Build Coastguard Worker }
295*bb4ee6a4SAndroid Build Coastguard Worker 
modify_battery(cmd: cmdline::BatteryCommand) -> std::result::Result<(), ()>296*bb4ee6a4SAndroid Build Coastguard Worker fn modify_battery(cmd: cmdline::BatteryCommand) -> std::result::Result<(), ()> {
297*bb4ee6a4SAndroid Build Coastguard Worker     do_modify_battery(
298*bb4ee6a4SAndroid Build Coastguard Worker         cmd.socket_path,
299*bb4ee6a4SAndroid Build Coastguard Worker         &cmd.battery_type,
300*bb4ee6a4SAndroid Build Coastguard Worker         &cmd.property,
301*bb4ee6a4SAndroid Build Coastguard Worker         &cmd.target,
302*bb4ee6a4SAndroid Build Coastguard Worker     )
303*bb4ee6a4SAndroid Build Coastguard Worker }
304*bb4ee6a4SAndroid Build Coastguard Worker 
modify_vfio(cmd: cmdline::VfioCrosvmCommand) -> std::result::Result<(), ()>305*bb4ee6a4SAndroid Build Coastguard Worker fn modify_vfio(cmd: cmdline::VfioCrosvmCommand) -> std::result::Result<(), ()> {
306*bb4ee6a4SAndroid Build Coastguard Worker     let (request, socket_path, vfio_path) = match cmd.command {
307*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::VfioSubCommand::Add(c) => {
308*bb4ee6a4SAndroid Build Coastguard Worker             let request = VmRequest::HotPlugVfioCommand {
309*bb4ee6a4SAndroid Build Coastguard Worker                 device: HotPlugDeviceInfo {
310*bb4ee6a4SAndroid Build Coastguard Worker                     device_type: HotPlugDeviceType::EndPoint,
311*bb4ee6a4SAndroid Build Coastguard Worker                     path: c.vfio_path.clone(),
312*bb4ee6a4SAndroid Build Coastguard Worker                     hp_interrupt: true,
313*bb4ee6a4SAndroid Build Coastguard Worker                 },
314*bb4ee6a4SAndroid Build Coastguard Worker                 add: true,
315*bb4ee6a4SAndroid Build Coastguard Worker             };
316*bb4ee6a4SAndroid Build Coastguard Worker             (request, c.socket_path, c.vfio_path)
317*bb4ee6a4SAndroid Build Coastguard Worker         }
318*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::VfioSubCommand::Remove(c) => {
319*bb4ee6a4SAndroid Build Coastguard Worker             let request = VmRequest::HotPlugVfioCommand {
320*bb4ee6a4SAndroid Build Coastguard Worker                 device: HotPlugDeviceInfo {
321*bb4ee6a4SAndroid Build Coastguard Worker                     device_type: HotPlugDeviceType::EndPoint,
322*bb4ee6a4SAndroid Build Coastguard Worker                     path: c.vfio_path.clone(),
323*bb4ee6a4SAndroid Build Coastguard Worker                     hp_interrupt: false,
324*bb4ee6a4SAndroid Build Coastguard Worker                 },
325*bb4ee6a4SAndroid Build Coastguard Worker                 add: false,
326*bb4ee6a4SAndroid Build Coastguard Worker             };
327*bb4ee6a4SAndroid Build Coastguard Worker             (request, c.socket_path, c.vfio_path)
328*bb4ee6a4SAndroid Build Coastguard Worker         }
329*bb4ee6a4SAndroid Build Coastguard Worker     };
330*bb4ee6a4SAndroid Build Coastguard Worker     if !vfio_path.exists() || !vfio_path.is_dir() {
331*bb4ee6a4SAndroid Build Coastguard Worker         error!("Invalid host sysfs path: {:?}", vfio_path);
332*bb4ee6a4SAndroid Build Coastguard Worker         return Err(());
333*bb4ee6a4SAndroid Build Coastguard Worker     }
334*bb4ee6a4SAndroid Build Coastguard Worker 
335*bb4ee6a4SAndroid Build Coastguard Worker     vms_request(&request, socket_path)?;
336*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
337*bb4ee6a4SAndroid Build Coastguard Worker }
338*bb4ee6a4SAndroid Build Coastguard Worker 
339*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "pci-hotplug")]
modify_virtio_net(cmd: cmdline::VirtioNetCommand) -> std::result::Result<(), ()>340*bb4ee6a4SAndroid Build Coastguard Worker fn modify_virtio_net(cmd: cmdline::VirtioNetCommand) -> std::result::Result<(), ()> {
341*bb4ee6a4SAndroid Build Coastguard Worker     match cmd.command {
342*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::VirtioNetSubCommand::AddTap(c) => {
343*bb4ee6a4SAndroid Build Coastguard Worker             let bus_num = do_net_add(&c.tap_name, c.socket_path).map_err(|e| {
344*bb4ee6a4SAndroid Build Coastguard Worker                 error!("{}", &e);
345*bb4ee6a4SAndroid Build Coastguard Worker             })?;
346*bb4ee6a4SAndroid Build Coastguard Worker             info!("Tap device {} plugged to PCI bus {}", &c.tap_name, bus_num);
347*bb4ee6a4SAndroid Build Coastguard Worker         }
348*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::VirtioNetSubCommand::RemoveTap(c) => {
349*bb4ee6a4SAndroid Build Coastguard Worker             do_net_remove(c.bus, &c.socket_path).map_err(|e| {
350*bb4ee6a4SAndroid Build Coastguard Worker                 error!("Tap device remove failed: {:?}", &e);
351*bb4ee6a4SAndroid Build Coastguard Worker             })?;
352*bb4ee6a4SAndroid Build Coastguard Worker             info!("Tap device removed from PCI bus {}", &c.bus);
353*bb4ee6a4SAndroid Build Coastguard Worker         }
354*bb4ee6a4SAndroid Build Coastguard Worker     };
355*bb4ee6a4SAndroid Build Coastguard Worker 
356*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
357*bb4ee6a4SAndroid Build Coastguard Worker }
358*bb4ee6a4SAndroid Build Coastguard Worker 
359*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "composite-disk")]
parse_composite_partition_arg( partition_arg: &str, ) -> std::result::Result<(String, String, bool, Option<Uuid>), ()>360*bb4ee6a4SAndroid Build Coastguard Worker fn parse_composite_partition_arg(
361*bb4ee6a4SAndroid Build Coastguard Worker     partition_arg: &str,
362*bb4ee6a4SAndroid Build Coastguard Worker ) -> std::result::Result<(String, String, bool, Option<Uuid>), ()> {
363*bb4ee6a4SAndroid Build Coastguard Worker     let mut partition_fields = partition_arg.split(":");
364*bb4ee6a4SAndroid Build Coastguard Worker 
365*bb4ee6a4SAndroid Build Coastguard Worker     let label = partition_fields.next();
366*bb4ee6a4SAndroid Build Coastguard Worker     let path = partition_fields.next();
367*bb4ee6a4SAndroid Build Coastguard Worker     let opt = partition_fields.next();
368*bb4ee6a4SAndroid Build Coastguard Worker     let part_guid = partition_fields.next();
369*bb4ee6a4SAndroid Build Coastguard Worker 
370*bb4ee6a4SAndroid Build Coastguard Worker     if let (Some(label), Some(path)) = (label, path) {
371*bb4ee6a4SAndroid Build Coastguard Worker         // By default, composite disk is read-only
372*bb4ee6a4SAndroid Build Coastguard Worker         let writable = match opt {
373*bb4ee6a4SAndroid Build Coastguard Worker             None => false,
374*bb4ee6a4SAndroid Build Coastguard Worker             Some("") => false,
375*bb4ee6a4SAndroid Build Coastguard Worker             Some("writable") => true,
376*bb4ee6a4SAndroid Build Coastguard Worker             Some(value) => {
377*bb4ee6a4SAndroid Build Coastguard Worker                 error!(
378*bb4ee6a4SAndroid Build Coastguard Worker                     "Unrecognized option '{}'. Expected 'writable' or nothing.",
379*bb4ee6a4SAndroid Build Coastguard Worker                     value
380*bb4ee6a4SAndroid Build Coastguard Worker                 );
381*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(());
382*bb4ee6a4SAndroid Build Coastguard Worker             }
383*bb4ee6a4SAndroid Build Coastguard Worker         };
384*bb4ee6a4SAndroid Build Coastguard Worker 
385*bb4ee6a4SAndroid Build Coastguard Worker         let part_guid = part_guid
386*bb4ee6a4SAndroid Build Coastguard Worker             .map(Uuid::parse_str)
387*bb4ee6a4SAndroid Build Coastguard Worker             .transpose()
388*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|e| error!("Invalid partition GUID: {}", e))?;
389*bb4ee6a4SAndroid Build Coastguard Worker 
390*bb4ee6a4SAndroid Build Coastguard Worker         Ok((label.to_owned(), path.to_owned(), writable, part_guid))
391*bb4ee6a4SAndroid Build Coastguard Worker     } else {
392*bb4ee6a4SAndroid Build Coastguard Worker         error!(
393*bb4ee6a4SAndroid Build Coastguard Worker             "Must specify label and path for partition '{}', like LABEL:PARTITION",
394*bb4ee6a4SAndroid Build Coastguard Worker             partition_arg
395*bb4ee6a4SAndroid Build Coastguard Worker         );
396*bb4ee6a4SAndroid Build Coastguard Worker         Err(())
397*bb4ee6a4SAndroid Build Coastguard Worker     }
398*bb4ee6a4SAndroid Build Coastguard Worker }
399*bb4ee6a4SAndroid Build Coastguard Worker 
400*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "composite-disk")]
create_composite(cmd: cmdline::CreateCompositeCommand) -> std::result::Result<(), ()>401*bb4ee6a4SAndroid Build Coastguard Worker fn create_composite(cmd: cmdline::CreateCompositeCommand) -> std::result::Result<(), ()> {
402*bb4ee6a4SAndroid Build Coastguard Worker     use std::path::PathBuf;
403*bb4ee6a4SAndroid Build Coastguard Worker 
404*bb4ee6a4SAndroid Build Coastguard Worker     let composite_image_path = &cmd.path;
405*bb4ee6a4SAndroid Build Coastguard Worker     let zero_filler_path = format!("{}.filler", composite_image_path);
406*bb4ee6a4SAndroid Build Coastguard Worker     let header_path = format!("{}.header", composite_image_path);
407*bb4ee6a4SAndroid Build Coastguard Worker     let footer_path = format!("{}.footer", composite_image_path);
408*bb4ee6a4SAndroid Build Coastguard Worker 
409*bb4ee6a4SAndroid Build Coastguard Worker     let mut composite_image_file = OpenOptions::new()
410*bb4ee6a4SAndroid Build Coastguard Worker         .create(true)
411*bb4ee6a4SAndroid Build Coastguard Worker         .read(true)
412*bb4ee6a4SAndroid Build Coastguard Worker         .write(true)
413*bb4ee6a4SAndroid Build Coastguard Worker         .truncate(true)
414*bb4ee6a4SAndroid Build Coastguard Worker         .open(composite_image_path)
415*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|e| {
416*bb4ee6a4SAndroid Build Coastguard Worker             error!(
417*bb4ee6a4SAndroid Build Coastguard Worker                 "Failed opening composite disk image file at '{}': {}",
418*bb4ee6a4SAndroid Build Coastguard Worker                 composite_image_path, e
419*bb4ee6a4SAndroid Build Coastguard Worker             );
420*bb4ee6a4SAndroid Build Coastguard Worker         })?;
421*bb4ee6a4SAndroid Build Coastguard Worker     create_zero_filler(&zero_filler_path).map_err(|e| {
422*bb4ee6a4SAndroid Build Coastguard Worker         error!(
423*bb4ee6a4SAndroid Build Coastguard Worker             "Failed to create zero filler file at '{}': {}",
424*bb4ee6a4SAndroid Build Coastguard Worker             &zero_filler_path, e
425*bb4ee6a4SAndroid Build Coastguard Worker         );
426*bb4ee6a4SAndroid Build Coastguard Worker     })?;
427*bb4ee6a4SAndroid Build Coastguard Worker     let mut header_file = OpenOptions::new()
428*bb4ee6a4SAndroid Build Coastguard Worker         .create(true)
429*bb4ee6a4SAndroid Build Coastguard Worker         .read(true)
430*bb4ee6a4SAndroid Build Coastguard Worker         .write(true)
431*bb4ee6a4SAndroid Build Coastguard Worker         .truncate(true)
432*bb4ee6a4SAndroid Build Coastguard Worker         .open(&header_path)
433*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|e| {
434*bb4ee6a4SAndroid Build Coastguard Worker             error!(
435*bb4ee6a4SAndroid Build Coastguard Worker                 "Failed opening header image file at '{}': {}",
436*bb4ee6a4SAndroid Build Coastguard Worker                 header_path, e
437*bb4ee6a4SAndroid Build Coastguard Worker             );
438*bb4ee6a4SAndroid Build Coastguard Worker         })?;
439*bb4ee6a4SAndroid Build Coastguard Worker     let mut footer_file = OpenOptions::new()
440*bb4ee6a4SAndroid Build Coastguard Worker         .create(true)
441*bb4ee6a4SAndroid Build Coastguard Worker         .read(true)
442*bb4ee6a4SAndroid Build Coastguard Worker         .write(true)
443*bb4ee6a4SAndroid Build Coastguard Worker         .truncate(true)
444*bb4ee6a4SAndroid Build Coastguard Worker         .open(&footer_path)
445*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|e| {
446*bb4ee6a4SAndroid Build Coastguard Worker             error!(
447*bb4ee6a4SAndroid Build Coastguard Worker                 "Failed opening footer image file at '{}': {}",
448*bb4ee6a4SAndroid Build Coastguard Worker                 footer_path, e
449*bb4ee6a4SAndroid Build Coastguard Worker             );
450*bb4ee6a4SAndroid Build Coastguard Worker         })?;
451*bb4ee6a4SAndroid Build Coastguard Worker 
452*bb4ee6a4SAndroid Build Coastguard Worker     let partitions = cmd
453*bb4ee6a4SAndroid Build Coastguard Worker         .partitions
454*bb4ee6a4SAndroid Build Coastguard Worker         .into_iter()
455*bb4ee6a4SAndroid Build Coastguard Worker         .map(|partition_arg| {
456*bb4ee6a4SAndroid Build Coastguard Worker             let (label, path, writable, part_guid) = parse_composite_partition_arg(&partition_arg)?;
457*bb4ee6a4SAndroid Build Coastguard Worker 
458*bb4ee6a4SAndroid Build Coastguard Worker             // Sparseness for composite disks is not user provided on Linux
459*bb4ee6a4SAndroid Build Coastguard Worker             // (e.g. via an option), and it has no runtime effect.
460*bb4ee6a4SAndroid Build Coastguard Worker             let size = open_disk_file(DiskFileParams {
461*bb4ee6a4SAndroid Build Coastguard Worker                 path: PathBuf::from(&path),
462*bb4ee6a4SAndroid Build Coastguard Worker                 is_read_only: !writable,
463*bb4ee6a4SAndroid Build Coastguard Worker                 is_sparse_file: true,
464*bb4ee6a4SAndroid Build Coastguard Worker                 is_overlapped: false,
465*bb4ee6a4SAndroid Build Coastguard Worker                 is_direct: false,
466*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
467*bb4ee6a4SAndroid Build Coastguard Worker                 depth: 0,
468*bb4ee6a4SAndroid Build Coastguard Worker             })
469*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|e| error!("Failed to create DiskFile instance: {}", e))?
470*bb4ee6a4SAndroid Build Coastguard Worker             .get_len()
471*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|e| error!("Failed to get length of partition image: {}", e))?;
472*bb4ee6a4SAndroid Build Coastguard Worker 
473*bb4ee6a4SAndroid Build Coastguard Worker             Ok(PartitionInfo {
474*bb4ee6a4SAndroid Build Coastguard Worker                 label,
475*bb4ee6a4SAndroid Build Coastguard Worker                 path: Path::new(&path).to_owned(),
476*bb4ee6a4SAndroid Build Coastguard Worker                 partition_type: ImagePartitionType::LinuxFilesystem,
477*bb4ee6a4SAndroid Build Coastguard Worker                 writable,
478*bb4ee6a4SAndroid Build Coastguard Worker                 size,
479*bb4ee6a4SAndroid Build Coastguard Worker                 part_guid,
480*bb4ee6a4SAndroid Build Coastguard Worker             })
481*bb4ee6a4SAndroid Build Coastguard Worker         })
482*bb4ee6a4SAndroid Build Coastguard Worker         .collect::<Result<Vec<PartitionInfo>, ()>>()?;
483*bb4ee6a4SAndroid Build Coastguard Worker 
484*bb4ee6a4SAndroid Build Coastguard Worker     create_composite_disk(
485*bb4ee6a4SAndroid Build Coastguard Worker         &partitions,
486*bb4ee6a4SAndroid Build Coastguard Worker         &PathBuf::from(zero_filler_path),
487*bb4ee6a4SAndroid Build Coastguard Worker         &PathBuf::from(header_path),
488*bb4ee6a4SAndroid Build Coastguard Worker         &mut header_file,
489*bb4ee6a4SAndroid Build Coastguard Worker         &PathBuf::from(footer_path),
490*bb4ee6a4SAndroid Build Coastguard Worker         &mut footer_file,
491*bb4ee6a4SAndroid Build Coastguard Worker         &mut composite_image_file,
492*bb4ee6a4SAndroid Build Coastguard Worker     )
493*bb4ee6a4SAndroid Build Coastguard Worker     .map_err(|e| {
494*bb4ee6a4SAndroid Build Coastguard Worker         error!(
495*bb4ee6a4SAndroid Build Coastguard Worker             "Failed to create composite disk image at '{}': {}",
496*bb4ee6a4SAndroid Build Coastguard Worker             composite_image_path, e
497*bb4ee6a4SAndroid Build Coastguard Worker         );
498*bb4ee6a4SAndroid Build Coastguard Worker     })?;
499*bb4ee6a4SAndroid Build Coastguard Worker 
500*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
501*bb4ee6a4SAndroid Build Coastguard Worker }
502*bb4ee6a4SAndroid Build Coastguard Worker 
503*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "qcow")]
create_qcow2(cmd: cmdline::CreateQcow2Command) -> std::result::Result<(), ()>504*bb4ee6a4SAndroid Build Coastguard Worker fn create_qcow2(cmd: cmdline::CreateQcow2Command) -> std::result::Result<(), ()> {
505*bb4ee6a4SAndroid Build Coastguard Worker     use std::path::PathBuf;
506*bb4ee6a4SAndroid Build Coastguard Worker 
507*bb4ee6a4SAndroid Build Coastguard Worker     if !(cmd.size.is_some() ^ cmd.backing_file.is_some()) {
508*bb4ee6a4SAndroid Build Coastguard Worker         println!(
509*bb4ee6a4SAndroid Build Coastguard Worker             "Create a new QCOW2 image at `PATH` of either the specified `SIZE` in bytes or
510*bb4ee6a4SAndroid Build Coastguard Worker     with a '--backing_file'."
511*bb4ee6a4SAndroid Build Coastguard Worker         );
512*bb4ee6a4SAndroid Build Coastguard Worker         return Err(());
513*bb4ee6a4SAndroid Build Coastguard Worker     }
514*bb4ee6a4SAndroid Build Coastguard Worker 
515*bb4ee6a4SAndroid Build Coastguard Worker     let file = OpenOptions::new()
516*bb4ee6a4SAndroid Build Coastguard Worker         .create(true)
517*bb4ee6a4SAndroid Build Coastguard Worker         .read(true)
518*bb4ee6a4SAndroid Build Coastguard Worker         .write(true)
519*bb4ee6a4SAndroid Build Coastguard Worker         .truncate(true)
520*bb4ee6a4SAndroid Build Coastguard Worker         .open(&cmd.file_path)
521*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|e| {
522*bb4ee6a4SAndroid Build Coastguard Worker             error!("Failed opening qcow file at '{}': {}", cmd.file_path, e);
523*bb4ee6a4SAndroid Build Coastguard Worker         })?;
524*bb4ee6a4SAndroid Build Coastguard Worker 
525*bb4ee6a4SAndroid Build Coastguard Worker     let params = DiskFileParams {
526*bb4ee6a4SAndroid Build Coastguard Worker         path: PathBuf::from(&cmd.file_path),
527*bb4ee6a4SAndroid Build Coastguard Worker         is_read_only: false,
528*bb4ee6a4SAndroid Build Coastguard Worker         is_sparse_file: false,
529*bb4ee6a4SAndroid Build Coastguard Worker         is_overlapped: false,
530*bb4ee6a4SAndroid Build Coastguard Worker         is_direct: false,
531*bb4ee6a4SAndroid Build Coastguard Worker         lock: true,
532*bb4ee6a4SAndroid Build Coastguard Worker         depth: 0,
533*bb4ee6a4SAndroid Build Coastguard Worker     };
534*bb4ee6a4SAndroid Build Coastguard Worker     match (cmd.size, cmd.backing_file) {
535*bb4ee6a4SAndroid Build Coastguard Worker         (Some(size), None) => QcowFile::new(file, params, size).map_err(|e| {
536*bb4ee6a4SAndroid Build Coastguard Worker             error!("Failed to create qcow file at '{}': {}", cmd.file_path, e);
537*bb4ee6a4SAndroid Build Coastguard Worker         })?,
538*bb4ee6a4SAndroid Build Coastguard Worker         (None, Some(backing_file)) => QcowFile::new_from_backing(file, params, &backing_file)
539*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|e| {
540*bb4ee6a4SAndroid Build Coastguard Worker                 error!("Failed to create qcow file at '{}': {}", cmd.file_path, e);
541*bb4ee6a4SAndroid Build Coastguard Worker             })?,
542*bb4ee6a4SAndroid Build Coastguard Worker         _ => unreachable!(),
543*bb4ee6a4SAndroid Build Coastguard Worker     };
544*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
545*bb4ee6a4SAndroid Build Coastguard Worker }
546*bb4ee6a4SAndroid Build Coastguard Worker 
start_device(opts: cmdline::DeviceCommand) -> std::result::Result<(), ()>547*bb4ee6a4SAndroid Build Coastguard Worker fn start_device(opts: cmdline::DeviceCommand) -> std::result::Result<(), ()> {
548*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(async_executor) = opts.async_executor {
549*bb4ee6a4SAndroid Build Coastguard Worker         cros_async::Executor::set_default_executor_kind(async_executor)
550*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|e| error!("Failed to set the default async executor: {:#}", e))?;
551*bb4ee6a4SAndroid Build Coastguard Worker     }
552*bb4ee6a4SAndroid Build Coastguard Worker 
553*bb4ee6a4SAndroid Build Coastguard Worker     let result = match opts.command {
554*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::DeviceSubcommand::CrossPlatform(command) => match command {
555*bb4ee6a4SAndroid Build Coastguard Worker             CrossPlatformDevicesCommands::Block(cfg) => run_block_device(cfg),
556*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "gpu")]
557*bb4ee6a4SAndroid Build Coastguard Worker             CrossPlatformDevicesCommands::Gpu(cfg) => run_gpu_device(cfg),
558*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "net")]
559*bb4ee6a4SAndroid Build Coastguard Worker             CrossPlatformDevicesCommands::Net(cfg) => run_net_device(cfg),
560*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "audio")]
561*bb4ee6a4SAndroid Build Coastguard Worker             CrossPlatformDevicesCommands::Snd(cfg) => run_snd_device(cfg),
562*bb4ee6a4SAndroid Build Coastguard Worker         },
563*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::DeviceSubcommand::Sys(command) => sys::start_device(command),
564*bb4ee6a4SAndroid Build Coastguard Worker     };
565*bb4ee6a4SAndroid Build Coastguard Worker 
566*bb4ee6a4SAndroid Build Coastguard Worker     result.map_err(|e| {
567*bb4ee6a4SAndroid Build Coastguard Worker         error!("Failed to run device: {:#}", e);
568*bb4ee6a4SAndroid Build Coastguard Worker     })
569*bb4ee6a4SAndroid Build Coastguard Worker }
570*bb4ee6a4SAndroid Build Coastguard Worker 
disk_cmd(cmd: cmdline::DiskCommand) -> std::result::Result<(), ()>571*bb4ee6a4SAndroid Build Coastguard Worker fn disk_cmd(cmd: cmdline::DiskCommand) -> std::result::Result<(), ()> {
572*bb4ee6a4SAndroid Build Coastguard Worker     match cmd.command {
573*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::DiskSubcommand::Resize(cmd) => {
574*bb4ee6a4SAndroid Build Coastguard Worker             let request = VmRequest::DiskCommand {
575*bb4ee6a4SAndroid Build Coastguard Worker                 disk_index: cmd.disk_index,
576*bb4ee6a4SAndroid Build Coastguard Worker                 command: DiskControlCommand::Resize {
577*bb4ee6a4SAndroid Build Coastguard Worker                     new_size: cmd.disk_size,
578*bb4ee6a4SAndroid Build Coastguard Worker                 },
579*bb4ee6a4SAndroid Build Coastguard Worker             };
580*bb4ee6a4SAndroid Build Coastguard Worker             vms_request(&request, cmd.socket_path)
581*bb4ee6a4SAndroid Build Coastguard Worker         }
582*bb4ee6a4SAndroid Build Coastguard Worker     }
583*bb4ee6a4SAndroid Build Coastguard Worker }
584*bb4ee6a4SAndroid Build Coastguard Worker 
make_rt(cmd: cmdline::MakeRTCommand) -> std::result::Result<(), ()>585*bb4ee6a4SAndroid Build Coastguard Worker fn make_rt(cmd: cmdline::MakeRTCommand) -> std::result::Result<(), ()> {
586*bb4ee6a4SAndroid Build Coastguard Worker     vms_request(&VmRequest::MakeRT, cmd.socket_path)
587*bb4ee6a4SAndroid Build Coastguard Worker }
588*bb4ee6a4SAndroid Build Coastguard Worker 
589*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
gpu_display_add(cmd: cmdline::GpuAddDisplaysCommand) -> ModifyGpuResult590*bb4ee6a4SAndroid Build Coastguard Worker fn gpu_display_add(cmd: cmdline::GpuAddDisplaysCommand) -> ModifyGpuResult {
591*bb4ee6a4SAndroid Build Coastguard Worker     do_gpu_display_add(cmd.socket_path, cmd.gpu_display)
592*bb4ee6a4SAndroid Build Coastguard Worker }
593*bb4ee6a4SAndroid Build Coastguard Worker 
594*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
gpu_display_list(cmd: cmdline::GpuListDisplaysCommand) -> ModifyGpuResult595*bb4ee6a4SAndroid Build Coastguard Worker fn gpu_display_list(cmd: cmdline::GpuListDisplaysCommand) -> ModifyGpuResult {
596*bb4ee6a4SAndroid Build Coastguard Worker     do_gpu_display_list(cmd.socket_path)
597*bb4ee6a4SAndroid Build Coastguard Worker }
598*bb4ee6a4SAndroid Build Coastguard Worker 
599*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
gpu_display_remove(cmd: cmdline::GpuRemoveDisplaysCommand) -> ModifyGpuResult600*bb4ee6a4SAndroid Build Coastguard Worker fn gpu_display_remove(cmd: cmdline::GpuRemoveDisplaysCommand) -> ModifyGpuResult {
601*bb4ee6a4SAndroid Build Coastguard Worker     do_gpu_display_remove(cmd.socket_path, cmd.display_id)
602*bb4ee6a4SAndroid Build Coastguard Worker }
603*bb4ee6a4SAndroid Build Coastguard Worker 
604*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
gpu_set_display_mouse_mode(cmd: cmdline::GpuSetDisplayMouseModeCommand) -> ModifyGpuResult605*bb4ee6a4SAndroid Build Coastguard Worker fn gpu_set_display_mouse_mode(cmd: cmdline::GpuSetDisplayMouseModeCommand) -> ModifyGpuResult {
606*bb4ee6a4SAndroid Build Coastguard Worker     do_gpu_set_display_mouse_mode(cmd.socket_path, cmd.display_id, cmd.mouse_mode)
607*bb4ee6a4SAndroid Build Coastguard Worker }
608*bb4ee6a4SAndroid Build Coastguard Worker 
609*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
modify_gpu(cmd: cmdline::GpuCommand) -> std::result::Result<(), ()>610*bb4ee6a4SAndroid Build Coastguard Worker fn modify_gpu(cmd: cmdline::GpuCommand) -> std::result::Result<(), ()> {
611*bb4ee6a4SAndroid Build Coastguard Worker     let result = match cmd.command {
612*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::GpuSubCommand::AddDisplays(cmd) => gpu_display_add(cmd),
613*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::GpuSubCommand::ListDisplays(cmd) => gpu_display_list(cmd),
614*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::GpuSubCommand::RemoveDisplays(cmd) => gpu_display_remove(cmd),
615*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::GpuSubCommand::SetDisplayMouseMode(cmd) => gpu_set_display_mouse_mode(cmd),
616*bb4ee6a4SAndroid Build Coastguard Worker     };
617*bb4ee6a4SAndroid Build Coastguard Worker     match result {
618*bb4ee6a4SAndroid Build Coastguard Worker         Ok(response) => {
619*bb4ee6a4SAndroid Build Coastguard Worker             println!("{}", response);
620*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
621*bb4ee6a4SAndroid Build Coastguard Worker         }
622*bb4ee6a4SAndroid Build Coastguard Worker         Err(e) => {
623*bb4ee6a4SAndroid Build Coastguard Worker             println!("error {}", e);
624*bb4ee6a4SAndroid Build Coastguard Worker             Err(())
625*bb4ee6a4SAndroid Build Coastguard Worker         }
626*bb4ee6a4SAndroid Build Coastguard Worker     }
627*bb4ee6a4SAndroid Build Coastguard Worker }
628*bb4ee6a4SAndroid Build Coastguard Worker 
usb_attach(cmd: cmdline::UsbAttachCommand) -> ModifyUsbResult<UsbControlResult>629*bb4ee6a4SAndroid Build Coastguard Worker fn usb_attach(cmd: cmdline::UsbAttachCommand) -> ModifyUsbResult<UsbControlResult> {
630*bb4ee6a4SAndroid Build Coastguard Worker     let dev_path = Path::new(&cmd.dev_path);
631*bb4ee6a4SAndroid Build Coastguard Worker 
632*bb4ee6a4SAndroid Build Coastguard Worker     do_usb_attach(cmd.socket_path, dev_path)
633*bb4ee6a4SAndroid Build Coastguard Worker }
634*bb4ee6a4SAndroid Build Coastguard Worker 
security_key_attach(cmd: cmdline::UsbAttachKeyCommand) -> ModifyUsbResult<UsbControlResult>635*bb4ee6a4SAndroid Build Coastguard Worker fn security_key_attach(cmd: cmdline::UsbAttachKeyCommand) -> ModifyUsbResult<UsbControlResult> {
636*bb4ee6a4SAndroid Build Coastguard Worker     let dev_path = Path::new(&cmd.dev_path);
637*bb4ee6a4SAndroid Build Coastguard Worker 
638*bb4ee6a4SAndroid Build Coastguard Worker     do_security_key_attach(cmd.socket_path, dev_path)
639*bb4ee6a4SAndroid Build Coastguard Worker }
640*bb4ee6a4SAndroid Build Coastguard Worker 
usb_detach(cmd: cmdline::UsbDetachCommand) -> ModifyUsbResult<UsbControlResult>641*bb4ee6a4SAndroid Build Coastguard Worker fn usb_detach(cmd: cmdline::UsbDetachCommand) -> ModifyUsbResult<UsbControlResult> {
642*bb4ee6a4SAndroid Build Coastguard Worker     do_usb_detach(cmd.socket_path, cmd.port)
643*bb4ee6a4SAndroid Build Coastguard Worker }
644*bb4ee6a4SAndroid Build Coastguard Worker 
usb_list(cmd: cmdline::UsbListCommand) -> ModifyUsbResult<UsbControlResult>645*bb4ee6a4SAndroid Build Coastguard Worker fn usb_list(cmd: cmdline::UsbListCommand) -> ModifyUsbResult<UsbControlResult> {
646*bb4ee6a4SAndroid Build Coastguard Worker     do_usb_list(cmd.socket_path)
647*bb4ee6a4SAndroid Build Coastguard Worker }
648*bb4ee6a4SAndroid Build Coastguard Worker 
modify_usb(cmd: cmdline::UsbCommand) -> std::result::Result<(), ()>649*bb4ee6a4SAndroid Build Coastguard Worker fn modify_usb(cmd: cmdline::UsbCommand) -> std::result::Result<(), ()> {
650*bb4ee6a4SAndroid Build Coastguard Worker     let result = match cmd.command {
651*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::UsbSubCommand::Attach(cmd) => usb_attach(cmd),
652*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::UsbSubCommand::SecurityKeyAttach(cmd) => security_key_attach(cmd),
653*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::UsbSubCommand::Detach(cmd) => usb_detach(cmd),
654*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::UsbSubCommand::List(cmd) => usb_list(cmd),
655*bb4ee6a4SAndroid Build Coastguard Worker     };
656*bb4ee6a4SAndroid Build Coastguard Worker     match result {
657*bb4ee6a4SAndroid Build Coastguard Worker         Ok(response) => {
658*bb4ee6a4SAndroid Build Coastguard Worker             println!("{}", response);
659*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
660*bb4ee6a4SAndroid Build Coastguard Worker         }
661*bb4ee6a4SAndroid Build Coastguard Worker         Err(e) => {
662*bb4ee6a4SAndroid Build Coastguard Worker             println!("error {}", e);
663*bb4ee6a4SAndroid Build Coastguard Worker             Err(())
664*bb4ee6a4SAndroid Build Coastguard Worker         }
665*bb4ee6a4SAndroid Build Coastguard Worker     }
666*bb4ee6a4SAndroid Build Coastguard Worker }
667*bb4ee6a4SAndroid Build Coastguard Worker 
snapshot_vm(cmd: cmdline::SnapshotCommand) -> std::result::Result<(), ()>668*bb4ee6a4SAndroid Build Coastguard Worker fn snapshot_vm(cmd: cmdline::SnapshotCommand) -> std::result::Result<(), ()> {
669*bb4ee6a4SAndroid Build Coastguard Worker     use cmdline::SnapshotSubCommands::*;
670*bb4ee6a4SAndroid Build Coastguard Worker     let (socket_path, request) = match cmd.snapshot_command {
671*bb4ee6a4SAndroid Build Coastguard Worker         Take(take_cmd) => {
672*bb4ee6a4SAndroid Build Coastguard Worker             let req = VmRequest::Snapshot(SnapshotCommand::Take {
673*bb4ee6a4SAndroid Build Coastguard Worker                 snapshot_path: take_cmd.snapshot_path,
674*bb4ee6a4SAndroid Build Coastguard Worker                 compress_memory: take_cmd.compress_memory,
675*bb4ee6a4SAndroid Build Coastguard Worker                 encrypt: take_cmd.encrypt,
676*bb4ee6a4SAndroid Build Coastguard Worker             });
677*bb4ee6a4SAndroid Build Coastguard Worker             (take_cmd.socket_path, req)
678*bb4ee6a4SAndroid Build Coastguard Worker         }
679*bb4ee6a4SAndroid Build Coastguard Worker     };
680*bb4ee6a4SAndroid Build Coastguard Worker     let socket_path = Path::new(&socket_path);
681*bb4ee6a4SAndroid Build Coastguard Worker     vms_request(&request, socket_path)
682*bb4ee6a4SAndroid Build Coastguard Worker }
683*bb4ee6a4SAndroid Build Coastguard Worker 
684*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::unnecessary_wraps)]
pkg_version() -> std::result::Result<(), ()>685*bb4ee6a4SAndroid Build Coastguard Worker fn pkg_version() -> std::result::Result<(), ()> {
686*bb4ee6a4SAndroid Build Coastguard Worker     const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");
687*bb4ee6a4SAndroid Build Coastguard Worker     const PKG_VERSION: Option<&'static str> = option_env!("PKG_VERSION");
688*bb4ee6a4SAndroid Build Coastguard Worker 
689*bb4ee6a4SAndroid Build Coastguard Worker     print!("crosvm {}", VERSION.unwrap_or("UNKNOWN"));
690*bb4ee6a4SAndroid Build Coastguard Worker     match PKG_VERSION {
691*bb4ee6a4SAndroid Build Coastguard Worker         Some(v) => println!("-{}", v),
692*bb4ee6a4SAndroid Build Coastguard Worker         None => println!(),
693*bb4ee6a4SAndroid Build Coastguard Worker     }
694*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
695*bb4ee6a4SAndroid Build Coastguard Worker }
696*bb4ee6a4SAndroid Build Coastguard Worker 
697*bb4ee6a4SAndroid Build Coastguard Worker // Returns true if the argument is a flag (e.g. `-s` or `--long`).
698*bb4ee6a4SAndroid Build Coastguard Worker //
699*bb4ee6a4SAndroid Build Coastguard Worker // As a special case, `-` is not treated as a flag, since it is typically used to represent
700*bb4ee6a4SAndroid Build Coastguard Worker // `stdin`/`stdout`.
is_flag(arg: &str) -> bool701*bb4ee6a4SAndroid Build Coastguard Worker fn is_flag(arg: &str) -> bool {
702*bb4ee6a4SAndroid Build Coastguard Worker     arg.len() > 1 && arg.starts_with('-')
703*bb4ee6a4SAndroid Build Coastguard Worker }
704*bb4ee6a4SAndroid Build Coastguard Worker 
705*bb4ee6a4SAndroid Build Coastguard Worker // Perform transformations on `args_iter` to produce arguments suitable for parsing by `argh`.
prepare_argh_args<I: IntoIterator<Item = String>>(args_iter: I) -> Vec<String>706*bb4ee6a4SAndroid Build Coastguard Worker fn prepare_argh_args<I: IntoIterator<Item = String>>(args_iter: I) -> Vec<String> {
707*bb4ee6a4SAndroid Build Coastguard Worker     let mut args: Vec<String> = Vec::default();
708*bb4ee6a4SAndroid Build Coastguard Worker     // http://b/235882579
709*bb4ee6a4SAndroid Build Coastguard Worker     for arg in args_iter {
710*bb4ee6a4SAndroid Build Coastguard Worker         match arg.as_str() {
711*bb4ee6a4SAndroid Build Coastguard Worker             "--host_ip" => {
712*bb4ee6a4SAndroid Build Coastguard Worker                 eprintln!("`--host_ip` option is deprecated!");
713*bb4ee6a4SAndroid Build Coastguard Worker                 eprintln!("Please use `--host-ip` instead");
714*bb4ee6a4SAndroid Build Coastguard Worker                 args.push("--host-ip".to_string());
715*bb4ee6a4SAndroid Build Coastguard Worker             }
716*bb4ee6a4SAndroid Build Coastguard Worker             "-h" => args.push("--help".to_string()),
717*bb4ee6a4SAndroid Build Coastguard Worker             arg if is_flag(arg) => {
718*bb4ee6a4SAndroid Build Coastguard Worker                 // Split `--arg=val` into `--arg val`, since argh doesn't support the former.
719*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some((key, value)) = arg.split_once("=") {
720*bb4ee6a4SAndroid Build Coastguard Worker                     args.push(key.to_string());
721*bb4ee6a4SAndroid Build Coastguard Worker                     args.push(value.to_string());
722*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
723*bb4ee6a4SAndroid Build Coastguard Worker                     args.push(arg.to_string());
724*bb4ee6a4SAndroid Build Coastguard Worker                 }
725*bb4ee6a4SAndroid Build Coastguard Worker             }
726*bb4ee6a4SAndroid Build Coastguard Worker             arg => args.push(arg.to_string()),
727*bb4ee6a4SAndroid Build Coastguard Worker         }
728*bb4ee6a4SAndroid Build Coastguard Worker     }
729*bb4ee6a4SAndroid Build Coastguard Worker 
730*bb4ee6a4SAndroid Build Coastguard Worker     args
731*bb4ee6a4SAndroid Build Coastguard Worker }
732*bb4ee6a4SAndroid Build Coastguard Worker 
shorten_usage(help: &str) -> String733*bb4ee6a4SAndroid Build Coastguard Worker fn shorten_usage(help: &str) -> String {
734*bb4ee6a4SAndroid Build Coastguard Worker     let mut lines = help.lines().collect::<Vec<_>>();
735*bb4ee6a4SAndroid Build Coastguard Worker     let first_line = lines[0].split(char::is_whitespace).collect::<Vec<_>>();
736*bb4ee6a4SAndroid Build Coastguard Worker 
737*bb4ee6a4SAndroid Build Coastguard Worker     // Shorten the usage line if it's for `crovm run` command that has so many options.
738*bb4ee6a4SAndroid Build Coastguard Worker     let run_usage = format!("Usage: {} run <options> KERNEL", first_line[1]);
739*bb4ee6a4SAndroid Build Coastguard Worker     if first_line[0] == "Usage:" && first_line[2] == "run" {
740*bb4ee6a4SAndroid Build Coastguard Worker         lines[0] = &run_usage;
741*bb4ee6a4SAndroid Build Coastguard Worker     }
742*bb4ee6a4SAndroid Build Coastguard Worker 
743*bb4ee6a4SAndroid Build Coastguard Worker     lines.join("\n")
744*bb4ee6a4SAndroid Build Coastguard Worker }
745*bb4ee6a4SAndroid Build Coastguard Worker 
crosvm_main<I: IntoIterator<Item = String>>(args: I) -> Result<CommandStatus>746*bb4ee6a4SAndroid Build Coastguard Worker fn crosvm_main<I: IntoIterator<Item = String>>(args: I) -> Result<CommandStatus> {
747*bb4ee6a4SAndroid Build Coastguard Worker     let _library_watcher = sys::get_library_watcher();
748*bb4ee6a4SAndroid Build Coastguard Worker 
749*bb4ee6a4SAndroid Build Coastguard Worker     // The following panic hook will stop our crashpad hook on windows.
750*bb4ee6a4SAndroid Build Coastguard Worker     // Only initialize when the crash-pad feature is off.
751*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(not(feature = "crash-report"))]
752*bb4ee6a4SAndroid Build Coastguard Worker     sys::set_panic_hook();
753*bb4ee6a4SAndroid Build Coastguard Worker 
754*bb4ee6a4SAndroid Build Coastguard Worker     // Ensure all processes detach from metrics on exit.
755*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(windows)]
756*bb4ee6a4SAndroid Build Coastguard Worker     let _metrics_destructor = metrics::get_destructor();
757*bb4ee6a4SAndroid Build Coastguard Worker 
758*bb4ee6a4SAndroid Build Coastguard Worker     let args = prepare_argh_args(args);
759*bb4ee6a4SAndroid Build Coastguard Worker     let args = args.iter().map(|s| s.as_str()).collect::<Vec<_>>();
760*bb4ee6a4SAndroid Build Coastguard Worker     let args = match crosvm::cmdline::CrosvmCmdlineArgs::from_args(&args[..1], &args[1..]) {
761*bb4ee6a4SAndroid Build Coastguard Worker         Ok(args) => args,
762*bb4ee6a4SAndroid Build Coastguard Worker         Err(e) if e.status.is_ok() => {
763*bb4ee6a4SAndroid Build Coastguard Worker             // If parsing succeeded and the user requested --help, print the usage message to stdout
764*bb4ee6a4SAndroid Build Coastguard Worker             // and exit with success.
765*bb4ee6a4SAndroid Build Coastguard Worker             let help = shorten_usage(&e.output);
766*bb4ee6a4SAndroid Build Coastguard Worker             println!("{help}");
767*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(CommandStatus::SuccessOrVmStop);
768*bb4ee6a4SAndroid Build Coastguard Worker         }
769*bb4ee6a4SAndroid Build Coastguard Worker         Err(e) => {
770*bb4ee6a4SAndroid Build Coastguard Worker             error!("arg parsing failed: {}", e.output);
771*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(CommandStatus::InvalidArgs);
772*bb4ee6a4SAndroid Build Coastguard Worker         }
773*bb4ee6a4SAndroid Build Coastguard Worker     };
774*bb4ee6a4SAndroid Build Coastguard Worker     let extended_status = args.extended_status;
775*bb4ee6a4SAndroid Build Coastguard Worker 
776*bb4ee6a4SAndroid Build Coastguard Worker     debug!("CLI arguments parsed.");
777*bb4ee6a4SAndroid Build Coastguard Worker 
778*bb4ee6a4SAndroid Build Coastguard Worker     let mut log_config = LogConfig {
779*bb4ee6a4SAndroid Build Coastguard Worker         log_args: LogArgs {
780*bb4ee6a4SAndroid Build Coastguard Worker             filter: args.log_level,
781*bb4ee6a4SAndroid Build Coastguard Worker             proc_name: args.syslog_tag.unwrap_or("crosvm".to_string()),
782*bb4ee6a4SAndroid Build Coastguard Worker             syslog: !args.no_syslog,
783*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
784*bb4ee6a4SAndroid Build Coastguard Worker         },
785*bb4ee6a4SAndroid Build Coastguard Worker 
786*bb4ee6a4SAndroid Build Coastguard Worker         ..Default::default()
787*bb4ee6a4SAndroid Build Coastguard Worker     };
788*bb4ee6a4SAndroid Build Coastguard Worker 
789*bb4ee6a4SAndroid Build Coastguard Worker     let ret = match args.command {
790*bb4ee6a4SAndroid Build Coastguard Worker         Command::CrossPlatform(command) => {
791*bb4ee6a4SAndroid Build Coastguard Worker             // Past this point, usage of exit is in danger of leaking zombie processes.
792*bb4ee6a4SAndroid Build Coastguard Worker             if let CrossPlatformCommands::Run(cmd) = command {
793*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some(syslog_tag) = &cmd.syslog_tag {
794*bb4ee6a4SAndroid Build Coastguard Worker                     base::warn!(
795*bb4ee6a4SAndroid Build Coastguard Worker                         "`crosvm run --syslog-tag` is deprecated; please use \
796*bb4ee6a4SAndroid Build Coastguard Worker                          `crosvm --syslog-tag=\"{}\" run` instead",
797*bb4ee6a4SAndroid Build Coastguard Worker                         syslog_tag
798*bb4ee6a4SAndroid Build Coastguard Worker                     );
799*bb4ee6a4SAndroid Build Coastguard Worker                     log_config.log_args.proc_name.clone_from(syslog_tag);
800*bb4ee6a4SAndroid Build Coastguard Worker                 }
801*bb4ee6a4SAndroid Build Coastguard Worker                 // We handle run_vm separately because it does not simply signal success/error
802*bb4ee6a4SAndroid Build Coastguard Worker                 // but also indicates whether the guest requested reset or stop.
803*bb4ee6a4SAndroid Build Coastguard Worker                 run_vm(cmd, log_config)
804*bb4ee6a4SAndroid Build Coastguard Worker             } else if let CrossPlatformCommands::Device(cmd) = command {
805*bb4ee6a4SAndroid Build Coastguard Worker                 // On windows, the device command handles its own logging setup, so we can't handle
806*bb4ee6a4SAndroid Build Coastguard Worker                 // it below otherwise logging will double init.
807*bb4ee6a4SAndroid Build Coastguard Worker                 if cfg!(unix) {
808*bb4ee6a4SAndroid Build Coastguard Worker                     syslog::init_with(log_config).context("failed to initialize syslog")?;
809*bb4ee6a4SAndroid Build Coastguard Worker                 }
810*bb4ee6a4SAndroid Build Coastguard Worker                 start_device(cmd)
811*bb4ee6a4SAndroid Build Coastguard Worker                     .map_err(|_| anyhow!("start_device subcommand failed"))
812*bb4ee6a4SAndroid Build Coastguard Worker                     .map(|_| CommandStatus::SuccessOrVmStop)
813*bb4ee6a4SAndroid Build Coastguard Worker             } else {
814*bb4ee6a4SAndroid Build Coastguard Worker                 syslog::init_with(log_config).context("failed to initialize syslog")?;
815*bb4ee6a4SAndroid Build Coastguard Worker 
816*bb4ee6a4SAndroid Build Coastguard Worker                 match command {
817*bb4ee6a4SAndroid Build Coastguard Worker                     #[cfg(feature = "balloon")]
818*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Balloon(cmd) => {
819*bb4ee6a4SAndroid Build Coastguard Worker                         balloon_vms(cmd).map_err(|_| anyhow!("balloon subcommand failed"))
820*bb4ee6a4SAndroid Build Coastguard Worker                     }
821*bb4ee6a4SAndroid Build Coastguard Worker                     #[cfg(feature = "balloon")]
822*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::BalloonStats(cmd) => {
823*bb4ee6a4SAndroid Build Coastguard Worker                         balloon_stats(cmd).map_err(|_| anyhow!("balloon_stats subcommand failed"))
824*bb4ee6a4SAndroid Build Coastguard Worker                     }
825*bb4ee6a4SAndroid Build Coastguard Worker                     #[cfg(feature = "balloon")]
826*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::BalloonWs(cmd) => {
827*bb4ee6a4SAndroid Build Coastguard Worker                         balloon_ws(cmd).map_err(|_| anyhow!("balloon_ws subcommand failed"))
828*bb4ee6a4SAndroid Build Coastguard Worker                     }
829*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Battery(cmd) => {
830*bb4ee6a4SAndroid Build Coastguard Worker                         modify_battery(cmd).map_err(|_| anyhow!("battery subcommand failed"))
831*bb4ee6a4SAndroid Build Coastguard Worker                     }
832*bb4ee6a4SAndroid Build Coastguard Worker                     #[cfg(feature = "composite-disk")]
833*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::CreateComposite(cmd) => create_composite(cmd)
834*bb4ee6a4SAndroid Build Coastguard Worker                         .map_err(|_| anyhow!("create_composite subcommand failed")),
835*bb4ee6a4SAndroid Build Coastguard Worker                     #[cfg(feature = "qcow")]
836*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::CreateQcow2(cmd) => {
837*bb4ee6a4SAndroid Build Coastguard Worker                         create_qcow2(cmd).map_err(|_| anyhow!("create_qcow2 subcommand failed"))
838*bb4ee6a4SAndroid Build Coastguard Worker                     }
839*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Device(_) => unreachable!(),
840*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Disk(cmd) => {
841*bb4ee6a4SAndroid Build Coastguard Worker                         disk_cmd(cmd).map_err(|_| anyhow!("disk subcommand failed"))
842*bb4ee6a4SAndroid Build Coastguard Worker                     }
843*bb4ee6a4SAndroid Build Coastguard Worker                     #[cfg(feature = "gpu")]
844*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Gpu(cmd) => {
845*bb4ee6a4SAndroid Build Coastguard Worker                         modify_gpu(cmd).map_err(|_| anyhow!("gpu subcommand failed"))
846*bb4ee6a4SAndroid Build Coastguard Worker                     }
847*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::MakeRT(cmd) => {
848*bb4ee6a4SAndroid Build Coastguard Worker                         make_rt(cmd).map_err(|_| anyhow!("make_rt subcommand failed"))
849*bb4ee6a4SAndroid Build Coastguard Worker                     }
850*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Resume(cmd) => {
851*bb4ee6a4SAndroid Build Coastguard Worker                         resume_vms(cmd).map_err(|_| anyhow!("resume subcommand failed"))
852*bb4ee6a4SAndroid Build Coastguard Worker                     }
853*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Run(_) => unreachable!(),
854*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Stop(cmd) => {
855*bb4ee6a4SAndroid Build Coastguard Worker                         stop_vms(cmd).map_err(|_| anyhow!("stop subcommand failed"))
856*bb4ee6a4SAndroid Build Coastguard Worker                     }
857*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Suspend(cmd) => {
858*bb4ee6a4SAndroid Build Coastguard Worker                         suspend_vms(cmd).map_err(|_| anyhow!("suspend subcommand failed"))
859*bb4ee6a4SAndroid Build Coastguard Worker                     }
860*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Swap(cmd) => {
861*bb4ee6a4SAndroid Build Coastguard Worker                         swap_vms(cmd).map_err(|_| anyhow!("swap subcommand failed"))
862*bb4ee6a4SAndroid Build Coastguard Worker                     }
863*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Powerbtn(cmd) => {
864*bb4ee6a4SAndroid Build Coastguard Worker                         powerbtn_vms(cmd).map_err(|_| anyhow!("powerbtn subcommand failed"))
865*bb4ee6a4SAndroid Build Coastguard Worker                     }
866*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Sleepbtn(cmd) => {
867*bb4ee6a4SAndroid Build Coastguard Worker                         sleepbtn_vms(cmd).map_err(|_| anyhow!("sleepbtn subcommand failed"))
868*bb4ee6a4SAndroid Build Coastguard Worker                     }
869*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Gpe(cmd) => {
870*bb4ee6a4SAndroid Build Coastguard Worker                         inject_gpe(cmd).map_err(|_| anyhow!("gpe subcommand failed"))
871*bb4ee6a4SAndroid Build Coastguard Worker                     }
872*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Usb(cmd) => {
873*bb4ee6a4SAndroid Build Coastguard Worker                         modify_usb(cmd).map_err(|_| anyhow!("usb subcommand failed"))
874*bb4ee6a4SAndroid Build Coastguard Worker                     }
875*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Version(_) => {
876*bb4ee6a4SAndroid Build Coastguard Worker                         pkg_version().map_err(|_| anyhow!("version subcommand failed"))
877*bb4ee6a4SAndroid Build Coastguard Worker                     }
878*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Vfio(cmd) => {
879*bb4ee6a4SAndroid Build Coastguard Worker                         modify_vfio(cmd).map_err(|_| anyhow!("vfio subcommand failed"))
880*bb4ee6a4SAndroid Build Coastguard Worker                     }
881*bb4ee6a4SAndroid Build Coastguard Worker                     #[cfg(feature = "pci-hotplug")]
882*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::VirtioNet(cmd) => {
883*bb4ee6a4SAndroid Build Coastguard Worker                         modify_virtio_net(cmd).map_err(|_| anyhow!("virtio subcommand failed"))
884*bb4ee6a4SAndroid Build Coastguard Worker                     }
885*bb4ee6a4SAndroid Build Coastguard Worker                     CrossPlatformCommands::Snapshot(cmd) => {
886*bb4ee6a4SAndroid Build Coastguard Worker                         snapshot_vm(cmd).map_err(|_| anyhow!("snapshot subcommand failed"))
887*bb4ee6a4SAndroid Build Coastguard Worker                     }
888*bb4ee6a4SAndroid Build Coastguard Worker                 }
889*bb4ee6a4SAndroid Build Coastguard Worker                 .map(|_| CommandStatus::SuccessOrVmStop)
890*bb4ee6a4SAndroid Build Coastguard Worker             }
891*bb4ee6a4SAndroid Build Coastguard Worker         }
892*bb4ee6a4SAndroid Build Coastguard Worker         cmdline::Command::Sys(command) => {
893*bb4ee6a4SAndroid Build Coastguard Worker             let log_args = log_config.log_args.clone();
894*bb4ee6a4SAndroid Build Coastguard Worker             // On windows, the sys commands handle their own logging setup, so we can't handle it
895*bb4ee6a4SAndroid Build Coastguard Worker             // below otherwise logging will double init.
896*bb4ee6a4SAndroid Build Coastguard Worker             if cfg!(unix) {
897*bb4ee6a4SAndroid Build Coastguard Worker                 syslog::init_with(log_config).context("failed to initialize syslog")?;
898*bb4ee6a4SAndroid Build Coastguard Worker             }
899*bb4ee6a4SAndroid Build Coastguard Worker             sys::run_command(command, log_args).map(|_| CommandStatus::SuccessOrVmStop)
900*bb4ee6a4SAndroid Build Coastguard Worker         }
901*bb4ee6a4SAndroid Build Coastguard Worker     };
902*bb4ee6a4SAndroid Build Coastguard Worker 
903*bb4ee6a4SAndroid Build Coastguard Worker     sys::cleanup();
904*bb4ee6a4SAndroid Build Coastguard Worker 
905*bb4ee6a4SAndroid Build Coastguard Worker     // WARNING: Any code added after this point is not guaranteed to run
906*bb4ee6a4SAndroid Build Coastguard Worker     // since we may forcibly kill this process (and its children) above.
907*bb4ee6a4SAndroid Build Coastguard Worker     ret.map(|s| {
908*bb4ee6a4SAndroid Build Coastguard Worker         if extended_status {
909*bb4ee6a4SAndroid Build Coastguard Worker             s
910*bb4ee6a4SAndroid Build Coastguard Worker         } else {
911*bb4ee6a4SAndroid Build Coastguard Worker             CommandStatus::SuccessOrVmStop
912*bb4ee6a4SAndroid Build Coastguard Worker         }
913*bb4ee6a4SAndroid Build Coastguard Worker     })
914*bb4ee6a4SAndroid Build Coastguard Worker }
915*bb4ee6a4SAndroid Build Coastguard Worker 
main()916*bb4ee6a4SAndroid Build Coastguard Worker fn main() {
917*bb4ee6a4SAndroid Build Coastguard Worker     syslog::early_init();
918*bb4ee6a4SAndroid Build Coastguard Worker     debug!("crosvm started.");
919*bb4ee6a4SAndroid Build Coastguard Worker     let res = crosvm_main(std::env::args());
920*bb4ee6a4SAndroid Build Coastguard Worker 
921*bb4ee6a4SAndroid Build Coastguard Worker     let exit_code = match &res {
922*bb4ee6a4SAndroid Build Coastguard Worker         Ok(code) => {
923*bb4ee6a4SAndroid Build Coastguard Worker             info!("{}", code.message());
924*bb4ee6a4SAndroid Build Coastguard Worker             *code as i32
925*bb4ee6a4SAndroid Build Coastguard Worker         }
926*bb4ee6a4SAndroid Build Coastguard Worker         Err(e) => {
927*bb4ee6a4SAndroid Build Coastguard Worker             let exit_code = error_to_exit_code(&res);
928*bb4ee6a4SAndroid Build Coastguard Worker             error!("exiting with error {}: {:?}", exit_code, e);
929*bb4ee6a4SAndroid Build Coastguard Worker             exit_code
930*bb4ee6a4SAndroid Build Coastguard Worker         }
931*bb4ee6a4SAndroid Build Coastguard Worker     };
932*bb4ee6a4SAndroid Build Coastguard Worker     std::process::exit(exit_code);
933*bb4ee6a4SAndroid Build Coastguard Worker }
934*bb4ee6a4SAndroid Build Coastguard Worker 
935*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
936*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
937*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
938*bb4ee6a4SAndroid Build Coastguard Worker 
939*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
args_is_flag()940*bb4ee6a4SAndroid Build Coastguard Worker     fn args_is_flag() {
941*bb4ee6a4SAndroid Build Coastguard Worker         assert!(is_flag("--test"));
942*bb4ee6a4SAndroid Build Coastguard Worker         assert!(is_flag("-s"));
943*bb4ee6a4SAndroid Build Coastguard Worker 
944*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!is_flag("-"));
945*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!is_flag("no-leading-dash"));
946*bb4ee6a4SAndroid Build Coastguard Worker     }
947*bb4ee6a4SAndroid Build Coastguard Worker 
948*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
args_split_long()949*bb4ee6a4SAndroid Build Coastguard Worker     fn args_split_long() {
950*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
951*bb4ee6a4SAndroid Build Coastguard Worker             prepare_argh_args(
952*bb4ee6a4SAndroid Build Coastguard Worker                 ["crosvm", "run", "--something=options", "vm_kernel"].map(|x| x.to_string())
953*bb4ee6a4SAndroid Build Coastguard Worker             ),
954*bb4ee6a4SAndroid Build Coastguard Worker             ["crosvm", "run", "--something", "options", "vm_kernel"]
955*bb4ee6a4SAndroid Build Coastguard Worker         );
956*bb4ee6a4SAndroid Build Coastguard Worker     }
957*bb4ee6a4SAndroid Build Coastguard Worker 
958*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
args_split_short()959*bb4ee6a4SAndroid Build Coastguard Worker     fn args_split_short() {
960*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
961*bb4ee6a4SAndroid Build Coastguard Worker             prepare_argh_args(
962*bb4ee6a4SAndroid Build Coastguard Worker                 ["crosvm", "run", "-p=init=/bin/bash", "vm_kernel"].map(|x| x.to_string())
963*bb4ee6a4SAndroid Build Coastguard Worker             ),
964*bb4ee6a4SAndroid Build Coastguard Worker             ["crosvm", "run", "-p", "init=/bin/bash", "vm_kernel"]
965*bb4ee6a4SAndroid Build Coastguard Worker         );
966*bb4ee6a4SAndroid Build Coastguard Worker     }
967*bb4ee6a4SAndroid Build Coastguard Worker 
968*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
args_host_ip()969*bb4ee6a4SAndroid Build Coastguard Worker     fn args_host_ip() {
970*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
971*bb4ee6a4SAndroid Build Coastguard Worker             prepare_argh_args(
972*bb4ee6a4SAndroid Build Coastguard Worker                 ["crosvm", "run", "--host_ip", "1.2.3.4", "vm_kernel"].map(|x| x.to_string())
973*bb4ee6a4SAndroid Build Coastguard Worker             ),
974*bb4ee6a4SAndroid Build Coastguard Worker             ["crosvm", "run", "--host-ip", "1.2.3.4", "vm_kernel"]
975*bb4ee6a4SAndroid Build Coastguard Worker         );
976*bb4ee6a4SAndroid Build Coastguard Worker     }
977*bb4ee6a4SAndroid Build Coastguard Worker 
978*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
args_h()979*bb4ee6a4SAndroid Build Coastguard Worker     fn args_h() {
980*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
981*bb4ee6a4SAndroid Build Coastguard Worker             prepare_argh_args(["crosvm", "run", "-h"].map(|x| x.to_string())),
982*bb4ee6a4SAndroid Build Coastguard Worker             ["crosvm", "run", "--help"]
983*bb4ee6a4SAndroid Build Coastguard Worker         );
984*bb4ee6a4SAndroid Build Coastguard Worker     }
985*bb4ee6a4SAndroid Build Coastguard Worker 
986*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
args_battery_option()987*bb4ee6a4SAndroid Build Coastguard Worker     fn args_battery_option() {
988*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
989*bb4ee6a4SAndroid Build Coastguard Worker             prepare_argh_args(
990*bb4ee6a4SAndroid Build Coastguard Worker                 [
991*bb4ee6a4SAndroid Build Coastguard Worker                     "crosvm",
992*bb4ee6a4SAndroid Build Coastguard Worker                     "run",
993*bb4ee6a4SAndroid Build Coastguard Worker                     "--battery",
994*bb4ee6a4SAndroid Build Coastguard Worker                     "type=goldfish",
995*bb4ee6a4SAndroid Build Coastguard Worker                     "-p",
996*bb4ee6a4SAndroid Build Coastguard Worker                     "init=/bin/bash",
997*bb4ee6a4SAndroid Build Coastguard Worker                     "vm_kernel"
998*bb4ee6a4SAndroid Build Coastguard Worker                 ]
999*bb4ee6a4SAndroid Build Coastguard Worker                 .map(|x| x.to_string())
1000*bb4ee6a4SAndroid Build Coastguard Worker             ),
1001*bb4ee6a4SAndroid Build Coastguard Worker             [
1002*bb4ee6a4SAndroid Build Coastguard Worker                 "crosvm",
1003*bb4ee6a4SAndroid Build Coastguard Worker                 "run",
1004*bb4ee6a4SAndroid Build Coastguard Worker                 "--battery",
1005*bb4ee6a4SAndroid Build Coastguard Worker                 "type=goldfish",
1006*bb4ee6a4SAndroid Build Coastguard Worker                 "-p",
1007*bb4ee6a4SAndroid Build Coastguard Worker                 "init=/bin/bash",
1008*bb4ee6a4SAndroid Build Coastguard Worker                 "vm_kernel"
1009*bb4ee6a4SAndroid Build Coastguard Worker             ]
1010*bb4ee6a4SAndroid Build Coastguard Worker         );
1011*bb4ee6a4SAndroid Build Coastguard Worker     }
1012*bb4ee6a4SAndroid Build Coastguard Worker 
1013*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
help_success()1014*bb4ee6a4SAndroid Build Coastguard Worker     fn help_success() {
1015*bb4ee6a4SAndroid Build Coastguard Worker         let args = ["crosvm", "--help"];
1016*bb4ee6a4SAndroid Build Coastguard Worker         let res = crosvm_main(args.iter().map(|s| s.to_string()));
1017*bb4ee6a4SAndroid Build Coastguard Worker         let status = res.expect("arg parsing should succeed");
1018*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(status, CommandStatus::SuccessOrVmStop);
1019*bb4ee6a4SAndroid Build Coastguard Worker     }
1020*bb4ee6a4SAndroid Build Coastguard Worker 
1021*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
invalid_arg_failure()1022*bb4ee6a4SAndroid Build Coastguard Worker     fn invalid_arg_failure() {
1023*bb4ee6a4SAndroid Build Coastguard Worker         let args = ["crosvm", "--heeeelp"];
1024*bb4ee6a4SAndroid Build Coastguard Worker         let res = crosvm_main(args.iter().map(|s| s.to_string()));
1025*bb4ee6a4SAndroid Build Coastguard Worker         let status = res.expect("arg parsing should succeed");
1026*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(status, CommandStatus::InvalidArgs);
1027*bb4ee6a4SAndroid Build Coastguard Worker     }
1028*bb4ee6a4SAndroid Build Coastguard Worker 
1029*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
1030*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "composite-disk")]
parse_composite_disk_arg()1031*bb4ee6a4SAndroid Build Coastguard Worker     fn parse_composite_disk_arg() {
1032*bb4ee6a4SAndroid Build Coastguard Worker         let arg1 = String::from("LABEL1:/partition1.img:writable");
1033*bb4ee6a4SAndroid Build Coastguard Worker         let res1 = parse_composite_partition_arg(&arg1);
1034*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1035*bb4ee6a4SAndroid Build Coastguard Worker             res1,
1036*bb4ee6a4SAndroid Build Coastguard Worker             Ok((
1037*bb4ee6a4SAndroid Build Coastguard Worker                 String::from("LABEL1"),
1038*bb4ee6a4SAndroid Build Coastguard Worker                 String::from("/partition1.img"),
1039*bb4ee6a4SAndroid Build Coastguard Worker                 true,
1040*bb4ee6a4SAndroid Build Coastguard Worker                 None
1041*bb4ee6a4SAndroid Build Coastguard Worker             ))
1042*bb4ee6a4SAndroid Build Coastguard Worker         );
1043*bb4ee6a4SAndroid Build Coastguard Worker 
1044*bb4ee6a4SAndroid Build Coastguard Worker         let arg2 = String::from("LABEL2:/partition2.img");
1045*bb4ee6a4SAndroid Build Coastguard Worker         let res2 = parse_composite_partition_arg(&arg2);
1046*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1047*bb4ee6a4SAndroid Build Coastguard Worker             res2,
1048*bb4ee6a4SAndroid Build Coastguard Worker             Ok((
1049*bb4ee6a4SAndroid Build Coastguard Worker                 String::from("LABEL2"),
1050*bb4ee6a4SAndroid Build Coastguard Worker                 String::from("/partition2.img"),
1051*bb4ee6a4SAndroid Build Coastguard Worker                 false,
1052*bb4ee6a4SAndroid Build Coastguard Worker                 None
1053*bb4ee6a4SAndroid Build Coastguard Worker             ))
1054*bb4ee6a4SAndroid Build Coastguard Worker         );
1055*bb4ee6a4SAndroid Build Coastguard Worker 
1056*bb4ee6a4SAndroid Build Coastguard Worker         let arg3 =
1057*bb4ee6a4SAndroid Build Coastguard Worker             String::from("LABEL3:/partition3.img:writable:4049C8DC-6C2B-C740-A95A-BDAA629D4378");
1058*bb4ee6a4SAndroid Build Coastguard Worker         let res3 = parse_composite_partition_arg(&arg3);
1059*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1060*bb4ee6a4SAndroid Build Coastguard Worker             res3,
1061*bb4ee6a4SAndroid Build Coastguard Worker             Ok((
1062*bb4ee6a4SAndroid Build Coastguard Worker                 String::from("LABEL3"),
1063*bb4ee6a4SAndroid Build Coastguard Worker                 String::from("/partition3.img"),
1064*bb4ee6a4SAndroid Build Coastguard Worker                 true,
1065*bb4ee6a4SAndroid Build Coastguard Worker                 Some(Uuid::from_u128(0x4049C8DC_6C2B_C740_A95A_BDAA629D4378))
1066*bb4ee6a4SAndroid Build Coastguard Worker             ))
1067*bb4ee6a4SAndroid Build Coastguard Worker         );
1068*bb4ee6a4SAndroid Build Coastguard Worker 
1069*bb4ee6a4SAndroid Build Coastguard Worker         // third argument is an empty string. writable: false.
1070*bb4ee6a4SAndroid Build Coastguard Worker         let arg4 = String::from("LABEL4:/partition4.img::4049C8DC-6C2B-C740-A95A-BDAA629D4378");
1071*bb4ee6a4SAndroid Build Coastguard Worker         let res4 = parse_composite_partition_arg(&arg4);
1072*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1073*bb4ee6a4SAndroid Build Coastguard Worker             res4,
1074*bb4ee6a4SAndroid Build Coastguard Worker             Ok((
1075*bb4ee6a4SAndroid Build Coastguard Worker                 String::from("LABEL4"),
1076*bb4ee6a4SAndroid Build Coastguard Worker                 String::from("/partition4.img"),
1077*bb4ee6a4SAndroid Build Coastguard Worker                 false,
1078*bb4ee6a4SAndroid Build Coastguard Worker                 Some(Uuid::from_u128(0x4049C8DC_6C2B_C740_A95A_BDAA629D4378))
1079*bb4ee6a4SAndroid Build Coastguard Worker             ))
1080*bb4ee6a4SAndroid Build Coastguard Worker         );
1081*bb4ee6a4SAndroid Build Coastguard Worker 
1082*bb4ee6a4SAndroid Build Coastguard Worker         // third argument is not "writable" or an empty string
1083*bb4ee6a4SAndroid Build Coastguard Worker         let arg5 = String::from("LABEL5:/partition5.img:4049C8DC-6C2B-C740-A95A-BDAA629D4378");
1084*bb4ee6a4SAndroid Build Coastguard Worker         let res5 = parse_composite_partition_arg(&arg5);
1085*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(res5, Err(()));
1086*bb4ee6a4SAndroid Build Coastguard Worker     }
1087*bb4ee6a4SAndroid Build Coastguard Worker 
1088*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
test_shorten_run_usage()1089*bb4ee6a4SAndroid Build Coastguard Worker     fn test_shorten_run_usage() {
1090*bb4ee6a4SAndroid Build Coastguard Worker         let help = r"Usage: crosvm run [<KERNEL>] [options] <very long line>...
1091*bb4ee6a4SAndroid Build Coastguard Worker 
1092*bb4ee6a4SAndroid Build Coastguard Worker Start a new crosvm instance";
1093*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1094*bb4ee6a4SAndroid Build Coastguard Worker             shorten_usage(help),
1095*bb4ee6a4SAndroid Build Coastguard Worker             r"Usage: crosvm run <options> KERNEL
1096*bb4ee6a4SAndroid Build Coastguard Worker 
1097*bb4ee6a4SAndroid Build Coastguard Worker Start a new crosvm instance"
1098*bb4ee6a4SAndroid Build Coastguard Worker         );
1099*bb4ee6a4SAndroid Build Coastguard Worker     }
1100*bb4ee6a4SAndroid Build Coastguard Worker }
1101