diff --git a/Cargo.lock b/Cargo.lock index 5a48f05..0ca6d78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,6 +54,11 @@ name = "byteorder" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cc" +version = "1.0.54" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cfg-if" version = "0.1.9" @@ -168,6 +173,18 @@ dependencies = [ "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nix" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.54 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -368,6 +385,7 @@ dependencies = [ "crc32c 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "nom 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -405,6 +423,11 @@ name = "version_check" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -438,6 +461,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +"checksum cc 1.0.54 (registry+https://github.com/rust-lang/crates.io-index)" = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" "checksum crc32c 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77ba37ef26c12988c1cee882d522d65e1d5d2ad8c3864665b88ee92767ed84c5" @@ -452,6 +476,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" "checksum miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" +"checksum nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum nom 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6" "checksum num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c8b15b261814f992e33760b1fca9fe8b693d8a65299f20c9901688636cfb746" @@ -481,6 +506,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" "checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" diff --git a/Cargo.toml b/Cargo.toml index c07e97c..e1e1c7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ clap = "2.33" crc32c = "0.4" flate2 = "1.0" libc = "0.2.71" +nix = "0.17" nom = "5.1" num_cpus = "1.13" rand = "0.7" diff --git a/src/file_utils.rs b/src/file_utils.rs index 9768bb8..a63469d 100644 --- a/src/file_utils.rs +++ b/src/file_utils.rs @@ -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(msg: &str) -> io::Result { + let e = io::Error::new(io::ErrorKind::Other, msg); + Err(e) +} + +fn get_device_size(path: &str) -> io::Result { + let file = File::open(path)?; + let fd = file.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 { + 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"); + } + } +} + +//--------------------------------------- diff --git a/src/lib.rs b/src/lib.rs index 9a193e1..cf410c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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)] diff --git a/src/pack/pack.rs b/src/pack/pack.rs index b4afa15..cff11e9 100644 --- a/src/pack/pack.rs +++ b/src/pack/pack.rs @@ -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 { - 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(rdr: &mut R, b: u64, count: u64) -> io::Result>