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
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
{
fn chmod(&mut self, mode: impl Into<u32>) -> io::Result<()>
{
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>
{
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::*;