Skip to content

Commit e256ee2

Browse files
committed
Replace unwrap/panic with proper error propagation
All IO backend new() functions (sync, tokio, uring) now return Qcow2Result instead of panicking on file open failures. Both setup macros propagate these errors with ?. check_cluster now returns Err on non-allocated clusters instead of silently printing a warning and returning Ok. main() exits with code 1 on error instead of panicking via unwrap.
1 parent 57a11d4 commit e256ee2

6 files changed

Lines changed: 45 additions & 43 deletions

File tree

src/dev.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2753,18 +2753,20 @@ impl<T: Qcow2IoOps> Qcow2Dev<T> {
27532753
async fn check_cluster(&self, virt_off: u64, cluster: Option<u64>) -> Qcow2Result<()> {
27542754
match cluster {
27552755
None => Ok(()),
2756-
Some(host_cluster) => {
2757-
match self.cluster_is_allocated(host_cluster).await? {
2758-
false => {
2759-
eprintln!(
2760-
"virt_offset {:x} pointed to non-allocated cluster {:x}",
2761-
virt_off, host_cluster
2762-
);
2763-
}
2764-
true => {}
2756+
Some(host_cluster) => match self.cluster_is_allocated(host_cluster).await? {
2757+
true => Ok(()),
2758+
false => {
2759+
eprintln!(
2760+
"virt_offset {:x} pointed to non-allocated cluster {:x}",
2761+
virt_off, host_cluster
2762+
);
2763+
Err(format!(
2764+
"check: virt_offset {:x} pointed to non-allocated cluster {:x}",
2765+
virt_off, host_cluster
2766+
)
2767+
.into())
27652768
}
2766-
Ok(())
2767-
}
2769+
},
27682770
}
27692771
}
27702772

src/main.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -543,12 +543,10 @@ fn check_qcow2(args: CheckArgs) -> Qcow2Result<()> {
543543

544544
rt.block_on(async move {
545545
let p = qcow2_rs::qcow2_default_params!(false, false);
546-
let dev = qcow2_setup_dev_tokio(&args.file, &p).await.unwrap();
547-
548-
dev.check().await.expect("check failed");
549-
});
546+
let dev = qcow2_setup_dev_tokio(&args.file, &p).await?;
550547

551-
Ok(())
548+
dev.check().await
549+
})
552550
}
553551

554552
async fn copy_from_qcow2<T: Qcow2IoOps>(
@@ -725,12 +723,17 @@ fn main() {
725723
.format_timestamp(None)
726724
.init();
727725

728-
match cli.command {
729-
Commands::Dump(arg) => dump_qcow2(arg).unwrap(),
730-
Commands::Format(arg) => format_qcow2(arg).unwrap(),
731-
Commands::Map(arg) => map_qcow2(arg).unwrap(),
732-
Commands::Info(arg) => info_qcow2(arg).unwrap(),
733-
Commands::Check(arg) => check_qcow2(arg).unwrap(),
734-
Commands::Convert(arg) => convert_qcow2(arg).unwrap(),
726+
let result = match cli.command {
727+
Commands::Dump(arg) => dump_qcow2(arg),
728+
Commands::Format(arg) => format_qcow2(arg),
729+
Commands::Map(arg) => map_qcow2(arg),
730+
Commands::Info(arg) => info_qcow2(arg),
731+
Commands::Check(arg) => check_qcow2(arg),
732+
Commands::Convert(arg) => convert_qcow2(arg),
735733
};
734+
735+
if let Err(e) = result {
736+
eprintln!("error: {}", e);
737+
std::process::exit(1);
738+
}
736739
}

src/sync_io.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub struct Qcow2IoSync {
1616
}
1717

1818
impl Qcow2IoSync {
19-
pub fn new(path: &Path, ro: bool, dio: bool) -> Qcow2IoSync {
19+
pub fn new(path: &Path, ro: bool, dio: bool) -> Qcow2Result<Qcow2IoSync> {
2020
#[cfg(target_os = "macos")]
2121
fn set_dio(_file: &File) {}
2222

@@ -27,17 +27,17 @@ impl Qcow2IoSync {
2727
}
2828
}
2929

30-
let file = OpenOptions::new().read(true).write(!ro).open(path).unwrap();
30+
let file = OpenOptions::new().read(true).write(!ro).open(path)?;
3131

3232
if dio {
3333
set_dio(&file);
3434
}
3535

3636
let fd = file.as_raw_fd();
37-
Qcow2IoSync {
37+
Ok(Qcow2IoSync {
3838
_file: RefCell::new(file),
3939
fd,
40-
}
40+
})
4141
}
4242

4343
#[inline(always)]

src/tokio_io.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,37 +26,35 @@ pub struct Qcow2IoTokio {
2626

2727
impl Qcow2IoTokio {
2828
#[cfg(target_os = "linux")]
29-
pub async fn new(path: &Path, ro: bool, dio: bool) -> Qcow2IoTokio {
29+
pub async fn new(path: &Path, ro: bool, dio: bool) -> Qcow2Result<Qcow2IoTokio> {
3030
let file = OpenOptions::new()
3131
.read(true)
3232
.write(!ro)
3333
.open(path.to_path_buf())
34-
.await
35-
.unwrap();
34+
.await?;
3635

3736
assert!(!dio);
3837

3938
let fd = file.as_raw_fd();
40-
Qcow2IoTokio {
39+
Ok(Qcow2IoTokio {
4140
file: tokio::sync::Mutex::new(file),
4241
fd,
43-
}
42+
})
4443
}
4544

4645
#[cfg(not(target_os = "linux"))]
47-
pub async fn new(path: &Path, ro: bool, dio: bool) -> Qcow2IoTokio {
46+
pub async fn new(path: &Path, ro: bool, dio: bool) -> Qcow2Result<Qcow2IoTokio> {
4847
let file = OpenOptions::new()
4948
.read(true)
5049
.write(!ro)
5150
.open(path.to_path_buf())
52-
.await
53-
.unwrap();
51+
.await?;
5452

5553
assert!(!dio);
5654

57-
Qcow2IoTokio {
55+
Ok(Qcow2IoTokio {
5856
file: tokio::sync::Mutex::new(file),
59-
}
57+
})
6058
}
6159

6260
async fn write_at(&self, offset: u64, buf: &[u8]) -> Qcow2Result<()> {

src/uring.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,19 @@ pub struct Qcow2IoUring {
8181
}
8282

8383
impl Qcow2IoUring {
84-
pub async fn new(path: &Path, ro: bool, dio: bool) -> Qcow2IoUring {
84+
pub async fn new(path: &Path, ro: bool, dio: bool) -> Qcow2Result<Qcow2IoUring> {
8585
let file = OpenOptions::new()
8686
.read(true)
8787
.write(!ro)
8888
.open(path.to_path_buf())
89-
.await
90-
.unwrap();
89+
.await?;
9190

9291
if dio {
9392
unsafe {
9493
libc::fcntl(file.as_raw_fd(), libc::F_SETFL, libc::O_DIRECT);
9594
}
9695
}
97-
Qcow2IoUring { file }
96+
Ok(Qcow2IoUring { file })
9897
}
9998
}
10099

src/utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ macro_rules! qcow2_setup_dev_fn {
9494
path: &Path,
9595
params: &Qcow2DevParams,
9696
) -> Qcow2Result<Qcow2Dev<$type>> {
97-
let io = <$type>::new(path, params.is_read_only(), params.is_direct_io()).await;
97+
let io = <$type>::new(path, params.is_read_only(), params.is_direct_io()).await?;
9898
let (mut dev, backing) = qcow2_alloc_dev(&path, io, params).await?;
9999
match backing {
100100
Some(back_path) => {
@@ -124,7 +124,7 @@ qcow2_setup_dev_fn!(crate::tokio_io::Qcow2IoTokio, qcow2_setup_dev_tokio);
124124
macro_rules! qcow2_setup_dev_fn_sync {
125125
($type:ty, $fn_name: ident) => {
126126
pub fn $fn_name(path: &Path, params: &Qcow2DevParams) -> Qcow2Result<Qcow2Dev<$type>> {
127-
let io = <$type>::new(path, params.is_read_only(), params.is_direct_io());
127+
let io = <$type>::new(path, params.is_read_only(), params.is_direct_io())?;
128128
let (mut dev, backing) = qcow2_alloc_dev_sync(&path, io, params)?;
129129
match backing {
130130
Some(back_path) => {

0 commit comments

Comments
 (0)