1use super::*;
3
4pub const STDIN_FILENO: RawFd = libc::STDIN_FILENO;
6pub const STDOUT_FILENO: RawFd = libc::STDOUT_FILENO;
8pub const STDERR_FILENO: RawFd = libc::STDERR_FILENO;
10
11mod raw;
12use raw::*;
13
14mod managed;
15mod unmanaged;
16
17pub use self::{
18 managed::*,
19 unmanaged::*,
20};
21
22pub mod memory;
23
24#[derive(Debug)]
25enum MaybeMappedInner<T>
26{
27 Raw(T),
28 Copied(memory::MemoryFile),
29}
30
31impl<T: AsRawFd + io::Read> MaybeMappedInner<T>
32{
33 pub fn from_stat(mut file: T) -> io::Result<(Self, u64)>
34 {
35 use libc::fstat;
36 let fd = file.as_raw_fd();
37 let sz = unsafe {
38 let mut stat = std::mem::MaybeUninit::uninit();
39 if fstat(fd, stat.as_mut_ptr()) != 0 {
40 let mut mem = memory::MemoryFile::new()?;
41 let count = std::io::copy(&mut file, &mut mem)?;
42 return Ok((Self::Copied(mem), count));
43 }
44 stat.assume_init().st_size & i64::MAX
45 } as u64;
46 Ok((Self::Raw(file), sz))
47 }
48}
49
50impl<T: IntoRawFd> MaybeMappedInner<T>
51{
52 #[inline]
53 pub unsafe fn into_file(self) -> std::fs::File
54 {
55 let fd = match self {
56 Self::Raw(r) => r.into_raw_fd(),
57 Self::Copied(c) => c.into_raw_fd(),
58 };
59
60 FromRawFd::from_raw_fd(fd)
61 }
62}
63
64impl<T> AsRawFd for MaybeMappedInner<T>
65where T: AsRawFd
66{
67 #[inline]
68 fn as_raw_fd(&self) -> RawFd {
69 match self {
70 Self::Copied(c) => c.as_raw_fd(),
71 Self::Raw(r) => r.as_raw_fd(),
72 }
73 }
74}
75
76pub fn try_map_or_cloned<F: io::Read + AsRawFd + IntoRawFd>(file: F, perm: Perm, flags: impl MapFlags) -> io::Result<MappedFile<std::fs::File>>
81{
82 let (len, file) = {
83 let (file, size) = MaybeMappedInner::from_stat(file)?;
84 let size = usize::try_from(size).map_err(|_| io::Error::new(io::ErrorKind::Unsupported, "File size exceeds pointer word width"))?;
85 (size, unsafe {
86 file.into_file()
87 })
88 };
89 MappedFile::new(file, len, perm, flags)
90}
91
92#[cfg(test)]
93mod tests
94{
95 use super::*;
96
97 #[test]
98 fn std_in_out_err_fileno()
99 {
100 #[inline(always)]
101 fn test_fileno<const EXPECTED: RawFd>(expected_name: &'static str, got: RawFd)
102 {
103 assert_eq!(EXPECTED, got, "{expected_name} invalid: expected: {EXPECTED}, got {got}");
104 }
105
106 test_fileno::<STDIN_FILENO>("STDIN_FILENO", std::io::stdin().as_raw_fd());
107 test_fileno::<STDOUT_FILENO>("STDOUT_FILENO", std::io::stdout().as_raw_fd());
108 test_fileno::<STDERR_FILENO>("STDERR_FILENO", std::io::stderr().as_raw_fd());
109 }
110
111 #[test]
112 fn test_readwrite()
113 {
114 let mut input = ManagedFD::from(memory::MemoryFile::new().unwrap());
115 let mut output = memory::MemoryFile::new().unwrap();
116 assert_eq!(std::io::copy(&mut input, &mut output).unwrap(), 0, "Bad read");
117
118 }
119}