Skip to content

Commit

Permalink
df: linux support
Browse files Browse the repository at this point in the history
  • Loading branch information
jgarzik committed Mar 9, 2024
1 parent e9063c9 commit 297d7ea
Showing 1 changed file with 51 additions and 5 deletions.
56 changes: 51 additions & 5 deletions fs/src/df.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ use plib::PROJECT_NAME;
use std::ffi::{CStr, CString};
use std::io;

#[cfg(target_os = "linux")]
const _PATH_MOUNTED: &'static str = "/etc/mtab";

/// df - report free storage space
#[derive(Parser, Debug)]
#[command(author, version, about, long_about)]
Expand All @@ -37,6 +40,7 @@ struct Args {
files: Vec<String>,
}

#[cfg(target_os = "macos")]
fn to_cstr(array: &[libc::c_char]) -> &CStr {
unsafe {
// Assuming the array is null-terminated, as it should be for C strings.
Expand All @@ -53,15 +57,16 @@ fn stat(filename_str: &str) -> io::Result<libc::stat> {
if rc == 0 {
Ok(st)
} else {
Err(io::Error::from_raw_os_error(rc))
let errno = std::io::Error::last_os_error().raw_os_error().unwrap();
Err(io::Error::from_raw_os_error(errno))
}
}
}

struct Mount {
devname: String,
dir: String,
dev: libc::dev_t,
dev: i64,
masked: bool,
cached_statfs: libc::statfs,
}
Expand Down Expand Up @@ -95,9 +100,9 @@ impl MountList {
fn push(&mut self, fsstat: &libc::statfs, devname: &CStr, dirname: &CStr) {
let dev = {
if let Ok(st) = stat(devname.to_str().unwrap()) {
st.st_rdev
st.st_rdev as i64
} else if let Ok(st) = stat(dirname.to_str().unwrap()) {
st.st_dev
st.st_dev as i64
} else {
-1
}
Expand All @@ -113,6 +118,7 @@ impl MountList {
}
}

#[cfg(target_os = "macos")]
fn read_mount_info() -> io::Result<MountList> {
let mut info = MountList::new();

Expand All @@ -134,6 +140,46 @@ fn read_mount_info() -> io::Result<MountList> {
Ok(info)
}

#[cfg(target_os = "linux")]
fn read_mount_info() -> io::Result<MountList> {
let mut info = MountList::new();

unsafe {
let path_mnt = CString::new(_PATH_MOUNTED).unwrap();
let mnt_mode = CString::new("r").unwrap();
let f = libc::setmntent(path_mnt.as_ptr(), mnt_mode.as_ptr());
if f.is_null() {
let errno = std::io::Error::last_os_error().raw_os_error().unwrap();
return Err(io::Error::from_raw_os_error(errno));
}

loop {
let me = libc::getmntent(f);
if me.is_null() {
break;
}

let me_devname = (*me).mnt_fsname;
let me_dirname = (*me).mnt_dir;
let devname = CStr::from_ptr(me_devname);
let dirname = CStr::from_ptr(me_dirname);

let mut mount: libc::statfs = std::mem::zeroed();
let rc = libc::statfs(dirname.as_ptr(), &mut mount);
if rc < 0 {
let errno = std::io::Error::last_os_error().raw_os_error().unwrap();
return Err(io::Error::from_raw_os_error(errno));
}

info.push(&mount, devname, dirname);
}

libc::endmntent(f);
}

Ok(info)
}

fn mask_fs_by_file(info: &mut MountList, filename: &str) -> io::Result<()> {
let stat_res = stat(filename);
if let Err(e) = stat_res {
Expand All @@ -143,7 +189,7 @@ fn mask_fs_by_file(info: &mut MountList, filename: &str) -> io::Result<()> {
let stat = stat_res.unwrap();

for mount in &mut info.mounts {
if stat.st_dev == mount.dev {
if stat.st_dev as i64 == mount.dev {
info.has_masks = true;
mount.masked = true;
}
Expand Down

0 comments on commit 297d7ea

Please sign in to comment.