[thin_metadata_{pack/unpack}] Fix get_nr_blocks()

It didn't work with block devices.
This commit is contained in:
Joe Thornber
2020-06-10 14:38:42 +01:00
parent 821628b004
commit 380632565d
5 changed files with 101 additions and 6 deletions

View File

@@ -1,8 +1,72 @@
use std::fs;
use nix::sys::stat;
use nix::sys::stat::{FileStat, SFlag};
use std::io;
use std::fs::File;
use std::os::unix::io::AsRawFd;
//---------------------------------------
fn check_bits(mode: u32, flag: &SFlag) -> bool {
(mode & flag.bits()) != 0
}
pub fn is_file_or_blk(info: FileStat) -> bool {
check_bits(info.st_mode, &stat::SFlag::S_IFBLK) ||
check_bits(info.st_mode, &stat::SFlag::S_IFREG)
}
pub fn file_exists(path: &str) -> bool {
return match fs::metadata(path) {
Ok(_) => {true}
Err(_) => {false}
match stat::stat(path) {
Ok(info) => {
return is_file_or_blk(info);
}
_ => {
// FIXME: assuming all errors indicate the file doesn't
// exist.
eprintln!("couldn't stat '{}'", path);
return false;
}
}
}
//---------------------------------------
const BLKGETSIZE64_CODE: u8 = 0x12;
const BLKGETSIZE64_SEQ: u8 = 114;
ioctl_read!(ioctl_blkgetsize64, BLKGETSIZE64_CODE, BLKGETSIZE64_SEQ, u64);
pub fn fail<T>(msg: &str) -> io::Result<T> {
let e = io::Error::new(io::ErrorKind::Other, msg);
Err(e)
}
fn get_device_size(path: &str) -> io::Result<u64> {
let _file = File::open(path)?;
let fd = File::open(path).unwrap().as_raw_fd();
let mut cap = 0u64;
unsafe {
match ioctl_blkgetsize64(fd, &mut cap) {
Ok(_) => {return Ok(cap);}
_ => {return fail("BLKGETSIZE64 ioctl failed");}
}
}
}
pub fn file_size(path: &str) -> io::Result<u64> {
match stat::stat(path) {
Ok(info) => {
if check_bits(info.st_mode, &SFlag::S_IFREG) {
return Ok(info.st_size as u64);
} else if check_bits(info.st_mode, &SFlag::S_IFBLK) {
return get_device_size(path);
} else {
return fail("not a regular file or block device");
}
}
_ => {
return fail("stat failed");
}
}
}
//---------------------------------------

View File

@@ -4,6 +4,9 @@ extern crate flate2;
extern crate nom;
extern crate num_cpus;
#[macro_use]
extern crate nix;
#[cfg(test)]
extern crate quickcheck;
#[cfg(test)]

View File

@@ -19,6 +19,7 @@ use rand::prelude::*;
use std::sync::mpsc::{sync_channel, Receiver};
use crate::pack::node_encode::*;
use crate::file_utils;
const BLOCK_SIZE: u64 = 4096;
const MAGIC: u64 = 0xa537a0aa6309ef77;
@@ -192,8 +193,8 @@ where
}
fn get_nr_blocks(path: &str) -> io::Result<u64> {
let metadata = std::fs::metadata(path)?;
Ok(metadata.len() / (BLOCK_SIZE as u64))
let len = file_utils::file_size(path)?;
Ok(len / (BLOCK_SIZE as u64))
}
fn read_blocks<R>(rdr: &mut R, b: u64, count: u64) -> io::Result<Vec<u8>>