1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
//! Ext for unixes
use super::*;

use std::os::unix::fs::PermissionsExt as UnixPermsExt;

use std::borrow::Borrow;

pub trait PermissionsExt
{
    fn unix(&self) -> Permissions;
    fn set_unix(&mut self, perm: impl Borrow<Permissions>);
    fn from_unix(perm: impl Into<Permissions>) -> Self;
}

impl PermissionsExt for std::fs::Permissions
{
    #[inline] fn unix(&self) -> Permissions
    {
	self.mode().into()
    }
    #[inline] fn set_unix(&mut self, perm: impl Borrow<Permissions>)
    {
	self.set_mode(perm.borrow().mask());
    }
    #[inline] fn from_unix(perm: impl Into<Permissions>) -> Self
    {
	Self::from_mode(perm.into().into())
    }
}


#[cfg(feature="chmod")] 
mod chmod
{
    use libc::{
	fchmod,
	chmod,
    };

    use std::{
	path::Path,
	io::{
	    self,
	    ErrorKind,
	},
    };
    
    pub trait FChmodExt
    {
	fn chmod(&mut self, mode: impl Into<u32>) -> io::Result<()>;
    }

    impl<T> FChmodExt for T
	where T: std::os::unix::io::AsRawFd
    {
	
	/// Perform `chmod` on this file to `mode`.
	///
	/// Mode can be anything that implements `Into<u32>`. `Permissions` does this, you can also pass raw `mode_t` values.
	/// # Notes
	/// If you pass raw `mode_t` that is outside the range (0..=0o777), any extra bits are ignored.
	fn chmod(&mut self, mode: impl Into<u32>) -> io::Result<()>
	{
	    //use std::os::unix::io::*;
	    unsafe {
		if fchmod(self.as_raw_fd(), mode.into() & 0o777) == 0 {
		    Ok(())
		} else {
		    Err(io::Error::new(ErrorKind::Other, "fchmod failed"))
		}
	    }
	}
    }

    pub trait ChmodExt
    {
	fn chmod(&self, mode: impl Into<u32>) -> io::Result<()>;
    }

    impl<P> ChmodExt for P
    where P: AsRef<Path>
    {
	/// Perform `chmod` on this Path to `mode`.
	///
	/// Mode can be anything that implements `Into<u32>`. `Permissions` does this, you can also pass raw `mode_t` values.
	/// # Notes
	/// If you pass raw `mode_t` that is outside the range (0..=0o777), any extra bits are ignored.
	fn chmod(&self, mode: impl Into<u32>) -> io::Result<()>
	{
	    use std::os::unix::ffi::OsStrExt;
	    let bytes = self.as_ref().as_os_str().as_bytes();
	    unsafe {
		let path = std::ffi::CString::new(bytes).map_err(|_| io::Error::new(ErrorKind::Other, "invalid path"))?;
		if chmod(path.as_ptr(), mode.into() & 0o777) == 0 {
		    Ok(())
		} else {
		    Err(io::Error::new(ErrorKind::Other, "chmod failed"))
		}
	    }
	}
    }
}
#[cfg(feature="chmod")] 
pub use chmod::*;