diff --git a/Cargo.toml b/Cargo.toml index da29044..4c58537 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,9 @@ travis-ci = { repository = "serde-rs/serde" } errno = "0.2" libc = "0.2" +[build-dependencies] +bindgen = "0.58.1" + [dev-dependencies] tempfile = "3.1.0" lazy_static = "1.3.0" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..26eb038 --- /dev/null +++ b/build.rs @@ -0,0 +1,18 @@ +extern crate bindgen; + +use bindgen::Builder; +use std::{env::var, path::PathBuf}; + +fn main() { + let bindings = Builder::default() + .header_contents("wrapper.h", "#include ") + .derive_default(true) + .generate() + .expect("Could not generate bindings"); + + let mut bindings_path = PathBuf::from(var("OUT_DIR").unwrap()); + bindings_path.push("bindings.rs"); + bindings + .write_to_file(&bindings_path) + .expect("Could not write bindings to file"); +} diff --git a/src/lib.rs b/src/lib.rs index 9f8a9b7..4a8cfbb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,27 +18,29 @@ extern crate libc; -use std::fs::File; -use std::fs::OpenOptions; - +use bindings::{ + loop_info64, LOOP_CLR_FD, LOOP_CTL_GET_FREE, LOOP_SET_CAPACITY, LOOP_SET_FD, LOOP_SET_STATUS64, +}; use libc::{c_int, ioctl}; -use std::default::Default; -use std::io; -use std::os::unix::prelude::*; -use std::path::{Path, PathBuf}; - -// TODO support missing operations -const LOOP_SET_FD: u16 = 0x4C00; -const LOOP_CLR_FD: u16 = 0x4C01; -const LOOP_SET_STATUS64: u16 = 0x4C04; -//const LOOP_GET_STATUS64: u16 = 0x4C05; -const LOOP_SET_CAPACITY: u16 = 0x4C07; -//const LOOP_SET_DIRECT_IO: u16 = 0x4C08; -//const LOOP_SET_BLOCK_SIZE: u16 = 0x4C09; - -//const LOOP_CTL_ADD: u16 = 0x4C80; -//const LOOP_CTL_REMOVE: u16 = 0x4C81; -const LOOP_CTL_GET_FREE: u16 = 0x4C82; +use std::fs::{File, OpenOptions}; +use std::{ + default::Default, + io, + os::unix::prelude::*, + path::{Path, PathBuf}, +}; + +#[allow(non_camel_case_types)] +#[allow(dead_code)] +#[allow(non_snake_case)] +mod bindings { + include!(concat!(env!("OUT_DIR"), "/bindings.rs")); +} + +#[cfg(not(target_os = "android"))] +type IoctlRequest = libc::c_ulong; +#[cfg(target_os = "android")] +type IoctlRequest = libc::c_int; const LOOP_CONTROL: &str = "/dev/loop-control"; const LOOP_PREFIX: &str = "/dev/loop"; @@ -72,7 +74,10 @@ impl LoopControl { /// ``` pub fn next_free(&self) -> io::Result { let dev_num = ioctl_to_error(unsafe { - ioctl(self.dev_file.as_raw_fd() as c_int, LOOP_CTL_GET_FREE.into()) + ioctl( + self.dev_file.as_raw_fd() as c_int, + LOOP_CTL_GET_FREE as IoctlRequest, + ) })?; LoopDevice::open(&format!("{}{}", LOOP_PREFIX, dev_num)) } @@ -124,7 +129,7 @@ impl LoopDevice { note = "use `loop.with().offset(offset).attach(file)` instead" )] pub fn attach>(&self, backing_file: P, offset: u64) -> io::Result<()> { - let info = LoopInfo64 { + let info = loop_info64 { lo_offset: offset, ..Default::default() }; @@ -145,7 +150,7 @@ impl LoopDevice { /// # ld.detach().unwrap(); /// ``` pub fn attach_file>(&self, backing_file: P) -> io::Result<()> { - let info = LoopInfo64 { + let info = loop_info64 { ..Default::default() }; @@ -162,7 +167,7 @@ impl LoopDevice { backing_file: P, offset: u64, ) -> io::Result<()> { - let info = LoopInfo64 { + let info = loop_info64 { lo_offset: offset, ..Default::default() }; @@ -181,7 +186,7 @@ impl LoopDevice { offset: u64, size_limit: u64, ) -> io::Result<()> { - let info = LoopInfo64 { + let info = loop_info64 { lo_offset: offset, lo_sizelimit: size_limit, ..Default::default() @@ -190,11 +195,11 @@ impl LoopDevice { Self::attach_with_loop_info(self, backing_file, info) } - /// Attach the loop device to a file with loop_info. + /// Attach the loop device to a file with loop_info64. fn attach_with_loop_info( &self, // TODO should be mut? - but changing it is a breaking change backing_file: impl AsRef, - info: LoopInfo64, + info: loop_info64, ) -> io::Result<()> { let bf = OpenOptions::new() .read(true) @@ -205,7 +210,7 @@ impl LoopDevice { ioctl_to_error(unsafe { ioctl( self.device.as_raw_fd() as c_int, - LOOP_SET_FD.into(), + LOOP_SET_FD as IoctlRequest, bf.as_raw_fd() as c_int, ) })?; @@ -213,7 +218,7 @@ impl LoopDevice { if let Err(err) = ioctl_to_error(unsafe { ioctl( self.device.as_raw_fd() as c_int, - LOOP_SET_STATUS64.into(), + LOOP_SET_STATUS64 as IoctlRequest, &info, ) }) { @@ -252,7 +257,13 @@ impl LoopDevice { /// ld.detach().unwrap(); /// ``` pub fn detach(&self) -> io::Result<()> { - ioctl_to_error(unsafe { ioctl(self.device.as_raw_fd() as c_int, LOOP_CLR_FD.into(), 0) })?; + ioctl_to_error(unsafe { + ioctl( + self.device.as_raw_fd() as c_int, + LOOP_CLR_FD as IoctlRequest, + 0, + ) + })?; Ok(()) } @@ -262,7 +273,7 @@ impl LoopDevice { ioctl_to_error(unsafe { ioctl( self.device.as_raw_fd() as c_int, - LOOP_SET_CAPACITY.into(), + LOOP_SET_CAPACITY as IoctlRequest, 0, ) })?; @@ -300,7 +311,7 @@ impl LoopDevice { /// ``` pub struct AttachOptions<'d> { device: &'d mut LoopDevice, - info: LoopInfo64, + info: loop_info64, } impl AttachOptions<'_> { @@ -333,44 +344,6 @@ impl AttachOptions<'_> { } } -// https://man7.org/linux/man-pages/man4/loop.4.html -#[repr(C)] -struct LoopInfo64 { - pub lo_device: u64, // ioctl r/o - pub lo_inode: u64, // ioctl r/o - pub lo_rdevice: u64, // ioctl r/o - pub lo_offset: u64, // - pub lo_sizelimit: u64, // bytes, 0 == max available - pub lo_number: u32, // ioctl r/o - pub lo_encrypt_type: u32, // - pub lo_encrypt_key_size: u32, // ioctl w/o - pub lo_flags: u32, // ioctl r/w (r/o before Linux 2.6.25) - pub lo_file_name: [u8; 64], // - pub lo_crypt_name: [u8; 64], // - pub lo_encrypt_key: [u8; 32], // ioctl w/o - pub lo_init: [u64; 2], // -} - -impl Default for LoopInfo64 { - fn default() -> Self { - Self { - lo_device: 0, - lo_inode: 0, - lo_rdevice: 0, - lo_offset: 0, - lo_sizelimit: 0, - lo_number: 0, - lo_encrypt_type: 0, - lo_encrypt_key_size: 0, - lo_flags: 0, - lo_file_name: [0; 64], - lo_crypt_name: [0; 64], - lo_encrypt_key: [0; 32], - lo_init: [0; 2], - } - } -} - fn ioctl_to_error(ret: i32) -> io::Result { if ret < 0 { Err(io::Error::last_os_error()) diff --git a/tests/util/mod.rs b/tests/util/mod.rs index f7cbd80..f225cb9 100644 --- a/tests/util/mod.rs +++ b/tests/util/mod.rs @@ -1,9 +1,11 @@ use libc::fallocate; use serde::{Deserialize, Deserializer}; -use std::io; -use std::os::unix::io::AsRawFd; -use std::process::Command; -use std::sync::{Arc, Mutex, MutexGuard}; +use std::{ + io, + os::unix::io::AsRawFd, + process::Command, + sync::{Arc, Mutex, MutexGuard}, +}; use tempfile::{NamedTempFile, TempPath};