From 10241c20ea1c5d6fa5553ee9ebc3a93440d6dca3 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Tue, 28 May 2019 09:35:08 +0200 Subject: [PATCH] src/tools.rs: implement image_size helper --- src/tools.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/tools.rs b/src/tools.rs index 3c1e8cd6..9046a532 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -4,6 +4,7 @@ use failure::*; use nix::unistd; use nix::sys::stat; +use nix::{convert_ioctl_res, request_code_read, ioc}; use lazy_static::lazy_static; @@ -754,3 +755,33 @@ pub trait AsAny { impl AsAny for T { fn as_any(&self) -> &Any { self } } + + +// /usr/include/linux/fs.h: #define BLKGETSIZE64 _IOR(0x12,114,size_t) +// return device size in bytes (u64 *arg) +nix::ioctl_read!(blkgetsize64, 0x12, 114, u64); + +/// Return file or block device size +pub fn image_size(path: &Path) -> Result { + + use std::os::unix::io::AsRawFd; + use std::os::unix::fs::FileTypeExt; + + let file = std::fs::File::open(path)?; + let metadata = file.metadata()?; + let file_type = metadata.file_type(); + + if file_type.is_block_device() { + let mut size : u64 = 0; + let res = unsafe { blkgetsize64(file.as_raw_fd(), &mut size) }; + + if let Err(err) = res { + bail!("blkgetsize64 failed for {:?} - {}", path, err); + } + Ok(size) + } else if file_type.is_file() { + Ok(metadata.len()) + } else { + bail!("image size failed - got unexpected file type {:?}", file_type); + } +}