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
105
106
107
108
109
use crate::*;
#[man("Uses readlinkat(2) on (`fd`, `path`) and appends the result to `buf`")]
pub fn read_link_to_ustring<'a>(
fd: c::c_int,
path: impl IntoUstr<'a>,
buf: &mut Ustring,
) -> Result<usize> {
let path = path.into_ustr();
let stat = fstatat(fd, &path, c::AT_SYMLINK_NOFOLLOW)?;
if stat.st_mode & c::S_IFLNK == 0 {
return Err(Errno(c::EINVAL));
}
let mut size = stat.st_size as usize + 1;
if size == 1 {
size = 128;
}
loop {
buf.reserve_exact(size);
let mut retry = false;
let res = unsafe {
buf.with_unused(|buf| {
let buf_len = buf.len();
match readlinkat(fd, &path, buf) {
Ok(n) if n.len() == buf_len => {
retry = true;
Err(Errno(c::ENAMETOOLONG))
}
r => r.map(|r| r.len()),
}
})
};
if retry && size < c::PATH_MAX as usize {
size *= 2;
} else {
return res;
}
}
}
pub fn read_link_to_new_ustring<'a>(
fd: c::c_int,
path: impl IntoUstr<'a>,
) -> Result<Ustring> {
let mut s = Ustring::new();
read_link_to_ustring(fd, path, &mut s).map(|_| s)
}
extern "C" {
fn uapi_black_box(ptr: *const u8) -> *mut u8;
}
pub(crate) fn black_box<T: ?Sized>(ptr: *const T) {
unsafe {
uapi_black_box(ptr as *const _);
}
}
pub(crate) fn black_box_id<T>(ptr: *const T) -> *mut T {
unsafe { uapi_black_box(ptr as *const _) as *mut _ }
}
pub(crate) const fn einval<T>() -> Result<T> {
Err(Errno(c::EINVAL))
}
pub(crate) trait Integer: Copy {
const MAX_VALUE: Self;
}
macro_rules! imv {
($t:ty) => {
impl Integer for $t {
const MAX_VALUE: Self = <$t>::max_value();
}
};
}
imv!(i8);
imv!(i16);
imv!(i32);
imv!(i64);
imv!(i128);
imv!(isize);
imv!(u8);
imv!(u16);
imv!(u32);
imv!(u64);
imv!(u128);
imv!(usize);