cap_primitives/fs/
file.rs1use std::io;
2
3#[cfg(unix)]
5pub trait FileExt {
6 fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
8
9 #[cfg(unix_file_vectored_at)]
11 fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
12 default_read_vectored(|b| self.read_at(b, offset), bufs)
13 }
14
15 fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
17 while !buf.is_empty() {
18 match self.read_at(buf, offset) {
19 Ok(0) => break,
20 Ok(n) => {
21 let tmp = buf;
22 buf = &mut tmp[n..];
23 offset += n as u64;
24 }
25 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
26 Err(e) => return Err(e),
27 }
28 }
29 if !buf.is_empty() {
30 Err(io::Error::new(
31 io::ErrorKind::UnexpectedEof,
32 "failed to fill whole buffer",
33 ))
34 } else {
35 Ok(())
36 }
37 }
38
39 fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
41
42 #[cfg(unix_file_vectored_at)]
44 fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
45 default_write_vectored(|b| self.write_at(b, offset), bufs)
46 }
47
48 fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
50 while !buf.is_empty() {
51 match self.write_at(buf, offset) {
52 Ok(0) => {
53 return Err(io::Error::new(
54 io::ErrorKind::WriteZero,
55 "failed to write whole buffer",
56 ));
57 }
58 Ok(n) => {
59 buf = &buf[n..];
60 offset += n as u64
61 }
62 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
63 Err(e) => return Err(e),
64 }
65 }
66 Ok(())
67 }
68}
69
70#[cfg(unix_file_vectored_at)]
71fn default_read_vectored<F>(read: F, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize>
72where
73 F: FnOnce(&mut [u8]) -> io::Result<usize>,
74{
75 let buf = bufs
76 .iter_mut()
77 .find(|b| !b.is_empty())
78 .map_or(&mut [][..], |b| &mut **b);
79 read(buf)
80}
81
82#[cfg(unix_file_vectored_at)]
83fn default_write_vectored<F>(write: F, bufs: &[io::IoSlice<'_>]) -> io::Result<usize>
84where
85 F: FnOnce(&[u8]) -> io::Result<usize>,
86{
87 let buf = bufs
88 .iter()
89 .find(|b| !b.is_empty())
90 .map_or(&[][..], |b| &**b);
91 write(buf)
92}
93
94#[cfg(target_os = "wasi")]
96pub trait FileExt {
97 fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
99 let bufs = &mut [io::IoSliceMut::new(buf)];
100 self.read_vectored_at(bufs, offset)
101 }
102
103 fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize>;
105
106 fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
108 while !buf.is_empty() {
109 match self.read_at(buf, offset) {
110 Ok(0) => break,
111 Ok(n) => {
112 let tmp = buf;
113 buf = &mut tmp[n..];
114 offset += n as u64;
115 }
116 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
117 Err(e) => return Err(e),
118 }
119 }
120 if !buf.is_empty() {
121 Err(io::Error::new(
122 io::ErrorKind::UnexpectedEof,
123 "failed to fill whole buffer",
124 ))
125 } else {
126 Ok(())
127 }
128 }
129
130 fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
132 let bufs = &[io::IoSlice::new(buf)];
133 self.write_vectored_at(bufs, offset)
134 }
135
136 fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize>;
138
139 fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
141 while !buf.is_empty() {
142 match self.write_at(buf, offset) {
143 Ok(0) => {
144 return Err(io::Error::new(
145 io::ErrorKind::WriteZero,
146 "failed to write whole buffer",
147 ));
148 }
149 Ok(n) => {
150 buf = &buf[n..];
151 offset += n as u64
152 }
153 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
154 Err(e) => return Err(e),
155 }
156 }
157 Ok(())
158 }
159
160 fn tell(&self) -> io::Result<u64>;
162
163 fn fdstat_set_flags(&self, flags: u16) -> io::Result<()>;
165
166 fn fdstat_set_rights(&self, rights: u64, inheriting: u64) -> io::Result<()>;
168
169 fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()>;
171
172 fn allocate(&self, offset: u64, len: u64) -> io::Result<()>;
174
175 fn create_directory<P: AsRef<std::path::Path>>(&self, dir: P) -> io::Result<()>;
177
178 fn read_link<P: AsRef<std::path::Path>>(&self, path: P) -> io::Result<std::path::PathBuf>;
180
181 fn metadata_at<P: AsRef<std::path::Path>>(
183 &self,
184 lookup_flags: u32,
185 path: P,
186 ) -> io::Result<std::fs::Metadata>;
187
188 fn remove_file<P: AsRef<std::path::Path>>(&self, path: P) -> io::Result<()>;
190
191 fn remove_directory<P: AsRef<std::path::Path>>(&self, path: P) -> io::Result<()>;
193}
194
195#[cfg(windows)]
197pub trait FileExt {
198 fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
200
201 fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
203}