Skip to content

add accessors for the underlying stat data #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/filetype.rs
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@ use std::fs::Metadata;
/// this simplified enum that works for many appalications.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SimpleType {
/// Entry is of unknown type
Unknown,
/// Entry is a symlink
Symlink,
/// Entry is a directory
105 changes: 103 additions & 2 deletions src/metadata.rs
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ use std::fs::Permissions;
use std::os::unix::fs::PermissionsExt;

use libc;
use std::time::{Duration, SystemTime, UNIX_EPOCH};

use crate::SimpleType;

@@ -17,11 +18,11 @@ pub struct Metadata {
impl Metadata {
/// Returns simplified type of the directory entry
pub fn simple_type(&self) -> SimpleType {
let typ = self.stat.st_mode & libc::S_IFMT;
match typ {
match self.file_type().unwrap_or(0) as libc::mode_t {
libc::S_IFREG => SimpleType::File,
libc::S_IFDIR => SimpleType::Dir,
libc::S_IFLNK => SimpleType::Symlink,
0 => SimpleType::Unknown,
_ => SimpleType::Other,
}
}
@@ -45,12 +46,112 @@ impl Metadata {
pub fn len(&self) -> u64 {
self.stat.st_size as u64
}
/// Return low level file type, if available
pub fn file_type(&self) -> Option<libc::mode_t> {
Some(self.stat.st_mode & libc::S_IFMT)
}
/// Return device node, if available
pub fn ino(&self) -> Option<libc::ino_t> {
Some(self.stat.st_ino)
}
/// Return device node major of the file, if available
pub fn dev_major(&self) -> Option<u32> {
Some(major(self.stat.st_dev))
}
/// Return device node minor of the file, if available
pub fn dev_minor(&self) -> Option<u32> {
Some(minor(self.stat.st_dev))
}
/// Return device node major of an device descriptor, if available
pub fn rdev_major(&self) -> Option<u32> {
match self.file_type()? as libc::mode_t {
libc::S_IFBLK | libc::S_IFCHR => Some(major(self.stat.st_rdev)),
_ => None,
}
}
/// Return device node minor of an device descriptor, if available
pub fn rdev_minor(&self) -> Option<u32> {
match self.file_type()? as libc::mode_t {
libc::S_IFBLK | libc::S_IFCHR => Some(minor(self.stat.st_rdev)),
_ => None,
}
}
/// Return preferered I/O Blocksize, if available
pub fn blksize(&self) -> Option<libc::blksize_t> {
Some(self.stat.st_blksize)
}
/// Return the number of 512 bytes blocks, if available
pub fn blocks(&self) -> Option<libc::blkcnt_t> {
Some(self.stat.st_blocks)
}
/// Returns file size (same as len() but Option), if available
pub fn size(&self) -> Option<libc::off_t> {
Some(self.stat.st_size)
}
/// Returns number of hard-links, if available
pub fn nlink(&self) -> Option<libc::nlink_t> {
Some(self.stat.st_nlink)
}
/// Returns user id, if available
pub fn uid(&self) -> Option<libc::uid_t> {
Some(self.stat.st_uid)
}
/// Returns group id, if available
pub fn gid(&self) -> Option<libc::gid_t> {
Some(self.stat.st_gid)
}
/// Returns mode bits, if available
pub fn file_mode(&self) -> Option<libc::mode_t> {
Some(self.stat.st_mode & 0o7777)
}
/// Returns last access time, if available
pub fn atime(&self) -> Option<SystemTime> {
Some(unix_systemtime(self.stat.st_atime, self.stat.st_atime_nsec))
}
/// Returns creation, if available
pub fn btime(&self) -> Option<SystemTime> {
None
}
/// Returns last status change time, if available
pub fn ctime(&self) -> Option<SystemTime> {
Some(unix_systemtime(self.stat.st_ctime, self.stat.st_ctime_nsec))
}
/// Returns last modification time, if available
pub fn mtime(&self) -> Option<SystemTime> {
Some(unix_systemtime(self.stat.st_mtime, self.stat.st_mtime_nsec))
}
}

pub fn new(stat: libc::stat) -> Metadata {
Metadata { stat: stat }
}

fn unix_systemtime(sec: libc::time_t, nsec: i64) -> SystemTime {
UNIX_EPOCH + Duration::from_secs(sec as u64) + Duration::from_nanos(nsec as u64)
}

#[cfg(not(target_os = "macos"))]
pub fn major(dev: libc::dev_t) -> u32 {
unsafe { libc::major(dev) }
}

#[cfg(not(target_os = "macos"))]
pub fn minor(dev: libc::dev_t) -> u32 {
unsafe { libc::minor(dev) }
}

// major/minor are not in rust's darwin libc (why)
// see https://github.com/apple/darwin-xnu/blob/main/bsd/sys/types.h
#[cfg(target_os = "macos")]
pub fn major(dev: libc::dev_t) -> u32 {
(dev as u32 >> 24) & 0xff
}

#[cfg(target_os = "macos")]
pub fn minor(dev: libc::dev_t) -> u32 {
dev as u32 & 0xffffff
}

#[cfg(test)]
mod test {
use super::*;