Skip to content

Commit

Permalink
Clean up and fix file_length_impl for blockdevs on linux
Browse files Browse the repository at this point in the history
Only try BLKGETSIZE on blockdevs,
use BLKGETSIZE64 instead of BLKGETSIZE,
store BLKGETSIZE64 a u64 and then "as _" at point-of-use (musl).

Closes: #155
  • Loading branch information
nabijaczleweli committed Sep 4, 2023
1 parent 7e39628 commit 9e6fcd1
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 26 deletions.
11 changes: 3 additions & 8 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ BLKGETSIZE
/// Replace `{}` with the `BLKGETSIZE` expression from `IOCTL_CHECK_SOURCE`
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
static IOCTL_INCLUDE_SKELETON: &str = r#"
/// Return `device size / 512` (`long *` arg)
static BLKGETSIZE: {type} = {expr} as {type};
/// Return size of blockdev (`u64 *` arg)
static BLKGETSIZE64: u64 = {expr} as _;
"#;


Expand All @@ -51,14 +51,9 @@ fn get_ioctl_data() {
let ioctl_preprocessed = String::from_utf8(cc::Build::new().file(ioctl_source).expand()).unwrap();
let blkgetsize_expr = ioctl_preprocessed.lines().next_back().unwrap().replace("U", "");

let ioctl_request_type = match &env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV")[..] {
"musl" => "libc::c_int",
_ => "libc::c_ulong",
};

let ioctl_include = ioctl_dir.join("ioctl.rs");
File::create(&ioctl_include)
.unwrap()
.write_all(IOCTL_INCLUDE_SKELETON.replace("{type}", ioctl_request_type).replace("{expr}", &blkgetsize_expr).as_bytes())
.write_all(IOCTL_INCLUDE_SKELETON.replace("{expr}", &blkgetsize_expr).as_bytes())
.unwrap();
}
26 changes: 8 additions & 18 deletions src/util/os/non_windows_non_macos.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::os::unix::fs::{PermissionsExt, FileTypeExt};
use libc::{O_RDONLY, c_ulong, close, ioctl, open};
use libc::{O_CLOEXEC, O_RDONLY, close, ioctl, open};
use std::os::unix::ffi::OsStrExt;
use std::fs::{FileType, Metadata};
use std::ffi::CString;
Expand All @@ -9,15 +9,6 @@ use std::path::Path;
include!(concat!(env!("OUT_DIR"), "/ioctl-data/ioctl.rs"));


// Stolen from https://unix.superglobalmegacorp.com/Net2/newsrc/sys/stat.h.html
/// X for owner
const S_IXUSR: u32 = 0o000100;
/// X for group
const S_IXGRP: u32 = 0o000010;
/// X for other
const S_IXOTH: u32 = 0o000001;


/// OS-specific check for fileness
pub fn is_device(tp: &FileType) -> bool {
tp.is_block_device() || tp.is_char_device() || tp.is_fifo() || tp.is_socket()
Expand All @@ -30,17 +21,16 @@ pub fn file_length<P: AsRef<Path>>(meta: &Metadata, path: &P) -> u64 {
}

fn file_length_impl(meta: &Metadata, path: &Path) -> u64 {
if is_device(&meta.file_type()) {
let mut block_count: c_ulong = 0;

if meta.file_type().is_block_device() {
let path_c = CString::new(path.as_os_str().as_bytes()).unwrap();
let dev_file = unsafe { open(path_c.as_ptr(), O_RDONLY) };
if dev_file >= 0 {
let ok = unsafe { ioctl(dev_file, BLKGETSIZE, &mut block_count as *mut c_ulong) } == 0;
let dev_file = unsafe { open(path_c.as_ptr(), O_RDONLY | O_CLOEXEC) };
if dev_file != -1 {
let mut size: u64 = 0;
let ok = unsafe { ioctl(dev_file, BLKGETSIZE64 as _, &mut size as *mut _) } == 0;
unsafe { close(dev_file) };

if ok {
return block_count as u64 * 512;
return size;
}
}
}
Expand All @@ -50,5 +40,5 @@ fn file_length_impl(meta: &Metadata, path: &Path) -> u64 {

/// Check if file is marked executable
pub fn file_executable(meta: &Metadata) -> bool {
(meta.permissions().mode() & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0
(meta.permissions().mode() & 0o111) != 0
}

0 comments on commit 9e6fcd1

Please sign in to comment.