1use crate::{
2 c_str::CStr,
3 error::{Errno, ResultExt},
4 header::{
5 fcntl::O_CREAT,
6 sys_stat::stat,
7 unistd::{SEEK_CUR, SEEK_END, SEEK_SET},
8 },
9 io,
10 out::Out,
11 platform::{Pal, Sys, types::*},
12};
13use core::ops::Deref;
14
15pub struct File {
16 pub fd: c_int,
17 pub reference: bool,
20}
21
22impl File {
23 pub fn new(fd: c_int) -> Self {
24 Self {
25 fd,
26 reference: false,
27 }
28 }
29
30 pub fn open(path: CStr, oflag: c_int) -> Result<Self, Errno> {
31 Sys::open(path, oflag, 0)
32 .map(Self::new)
33 .map_err(Errno::sync)
34 }
35
36 pub fn openat(dirfd: c_int, path: CStr, oflag: c_int) -> Result<Self, Errno> {
37 Sys::openat(dirfd, path, oflag, 0)
38 .map(Self::new)
39 .map_err(Errno::sync)
40 }
41
42 pub fn create(path: CStr, oflag: c_int, mode: mode_t) -> Result<Self, Errno> {
43 Sys::open(path, oflag | O_CREAT, mode)
44 .map(Self::new)
45 .map_err(Errno::sync)
46 }
47
48 pub fn createat(dirfd: c_int, path: CStr, oflag: c_int, mode: mode_t) -> Result<Self, Errno> {
49 Sys::openat(dirfd, path, oflag | O_CREAT, mode)
50 .map(Self::new)
51 .map_err(Errno::sync)
52 }
53
54 pub fn sync_all(&self) -> Result<(), Errno> {
55 Sys::fsync(self.fd).map_err(Errno::sync)
56 }
57
58 pub fn set_len(&self, size: u64) -> Result<(), Errno> {
59 Sys::ftruncate(self.fd, size as off_t).map_err(Errno::sync)
60 }
61
62 pub fn fstat(&self) -> Result<stat, Errno> {
63 let mut file_st = stat::default();
64 Sys::fstat(self.fd, Out::from_mut(&mut file_st)).map_err(Errno::sync)?;
65 Ok(file_st)
66 }
67
68 pub fn try_clone(&self) -> io::Result<Self> {
69 Ok(Self::new(Sys::dup(self.fd)?))
70 }
71
72 pub unsafe fn get_ref(&self) -> Self {
76 Self {
77 fd: self.fd,
78 reference: true,
79 }
80 }
81}
82
83impl io::Read for &File {
84 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
85 match Sys::read(self.fd, buf).map(|read| read as ssize_t).or_minus_one_errno() {
86 -1 => Err(io::last_os_error()),
87 ok => Ok(ok as usize),
88 }
89 }
90}
91
92impl io::Write for &File {
93 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
94 match Sys::write(self.fd, buf)
95 .map(|read| read as ssize_t)
96 .or_minus_one_errno()
97 {
98 -1 => Err(io::last_os_error()),
99 ok => Ok(ok as usize),
100 }
101 }
102
103 fn flush(&mut self) -> io::Result<()> {
104 Ok(())
105 }
106}
107
108impl io::Seek for &File {
109 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
110 let (offset, whence) = match pos {
111 io::SeekFrom::Start(start) => (start as off_t, SEEK_SET),
112 io::SeekFrom::Current(current) => (current as off_t, SEEK_CUR),
113 io::SeekFrom::End(end) => (end as off_t, SEEK_END),
114 };
115
116 Ok(Sys::lseek(self.fd, offset, whence)? as u64)
117 }
118}
119
120impl io::Read for File {
121 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
122 (&mut &*self).read(buf)
123 }
124}
125
126impl io::Write for File {
127 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
128 (&mut &*self).write(buf)
129 }
130
131 fn flush(&mut self) -> io::Result<()> {
132 (&mut &*self).flush()
133 }
134}
135
136impl io::Seek for File {
137 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
138 (&mut &*self).seek(pos)
139 }
140}
141
142impl Deref for File {
143 type Target = c_int;
144
145 fn deref(&self) -> &Self::Target {
146 &self.fd
147 }
148}
149
150impl Drop for File {
151 fn drop(&mut self) {
152 if !self.reference {
153 let _ = Sys::close(self.fd);
154 }
155 }
156}