storage_stress_test_utils/
io.rs1use fidl_fuchsia_io as fio;
6use fuchsia_fs::directory::*;
7use fuchsia_fs::file::*;
8use fuchsia_fs::node::OpenError;
9use log::debug;
10use std::path::Path;
11use zx::{Event, Status};
12
13pub struct Directory {
16 proxy: fio::DirectoryProxy,
17}
18
19impl Directory {
20 pub fn from_namespace(path: impl AsRef<Path>, flags: fio::Flags) -> Result<Directory, Status> {
22 let path = path.as_ref().to_str().unwrap();
23 match fuchsia_fs::directory::open_in_namespace(path, flags) {
24 Ok(proxy) => Ok(Directory { proxy }),
25 Err(OpenError::OpenError(s)) => {
26 debug!(path:%, status:% = s; "from_namespace failed");
27 Err(s)
28 }
29 Err(OpenError::SendOpenRequest(e)) => {
30 if e.is_closed() {
31 Err(Status::PEER_CLOSED)
32 } else {
33 panic!("Unexpected FIDL error during open: {}", e);
34 }
35 }
36 Err(OpenError::OnOpenEventStreamClosed) => Err(Status::PEER_CLOSED),
37 Err(OpenError::Namespace(s)) => Err(s),
38 Err(e) => panic!("Unexpected error during open: {}", e),
39 }
40 }
41
42 pub async fn open_directory(
44 &self,
45 filename: &str,
46 flags: fio::Flags,
47 ) -> Result<Directory, Status> {
48 match fuchsia_fs::directory::open_directory(&self.proxy, filename, flags).await {
49 Ok(proxy) => Ok(Directory { proxy }),
50 Err(OpenError::OpenError(s)) => {
51 debug!(filename:%, flags:?, status:% = s; "open_directory failed");
52 Err(s)
53 }
54 Err(OpenError::SendOpenRequest(e)) => {
55 if e.is_closed() {
56 Err(Status::PEER_CLOSED)
57 } else {
58 panic!("Unexpected FIDL error during open: {}", e);
59 }
60 }
61 Err(OpenError::OnOpenEventStreamClosed) => Err(Status::PEER_CLOSED),
62 Err(e) => panic!("Unexpected error during open: {}", e),
63 }
64 }
65
66 pub async fn open_file(&self, filename: &str, flags: fio::Flags) -> Result<File, Status> {
68 match fuchsia_fs::directory::open_file(&self.proxy, filename, flags).await {
69 Ok(proxy) => Ok(File { proxy }),
70 Err(OpenError::OpenError(s)) => {
71 debug!(filename:%, flags:?, status:% = s; "open_file failed");
72 Err(s)
73 }
74 Err(OpenError::SendOpenRequest(e)) => {
75 if e.is_closed() {
76 Err(Status::PEER_CLOSED)
77 } else {
78 panic!("Unexpected FIDL error during open: {}", e);
79 }
80 }
81 Err(OpenError::OnOpenEventStreamClosed) => Err(Status::PEER_CLOSED),
82 Err(e) => panic!("Unexpected error during open: {}", e),
83 }
84 }
85
86 pub async fn create_directory(
88 &self,
89 filename: &str,
90 flags: fio::Flags,
91 ) -> Result<Directory, Status> {
92 match fuchsia_fs::directory::create_directory(&self.proxy, filename, flags).await {
93 Ok(proxy) => Ok(Directory { proxy }),
94 Err(OpenError::OpenError(s)) => {
95 debug!(filename:%, flags:?, status:% = s; "create_directory failed");
96 Err(s)
97 }
98 Err(OpenError::SendOpenRequest(e)) => {
99 if e.is_closed() {
100 Err(Status::PEER_CLOSED)
101 } else {
102 panic!("Unexpected FIDL error during create: {}", e);
103 }
104 }
105 Err(OpenError::OnOpenEventStreamClosed) => Err(Status::PEER_CLOSED),
106 Err(e) => panic!("Unexpected error during create: {}", e),
107 }
108 }
109
110 pub async fn sync_directory(&self) -> Result<(), Status> {
112 match self.proxy.sync().await {
113 Ok(_) => Ok(()),
114 Err(e) => {
115 if e.is_closed() {
116 Err(Status::PEER_CLOSED)
117 } else {
118 panic!("Unexpected FIDL error during sync: {}", e);
119 }
120 }
121 }
122 }
123
124 pub async fn remove(&self, filename: &str) -> Result<(), Status> {
126 match self.proxy.unlink(filename, &fio::UnlinkOptions::default()).await {
127 Ok(result) => Status::ok(match result {
128 Ok(()) => 0,
129 Err(status) => status,
130 }),
131 Err(e) => {
132 if e.is_closed() {
133 Err(Status::PEER_CLOSED)
134 } else {
135 panic!("Unexpected FIDL error during remove: {}", e);
136 }
137 }
138 }
139 }
140
141 pub async fn rename(
144 &self,
145 src_name: &str,
146 dst_parent: &Directory,
147 dst_name: &str,
148 ) -> Result<(), Status> {
149 let dst_token = match dst_parent.proxy.get_token().await {
150 Ok((_raw_status_code, Some(handle))) => Ok(handle),
151 Ok((_raw_status_code, None)) => {
152 panic!("No handle");
153 }
154 Err(e) => {
155 if e.is_closed() {
156 Err(Status::PEER_CLOSED)
157 } else {
158 panic!("Unexpected FIDL error during rename: {}", e);
159 }
160 }
161 }?;
162 match self.proxy.rename(src_name, Event::from(dst_token), dst_name).await {
163 Ok(_) => Ok(()),
164 Err(e) => {
165 if e.is_closed() {
166 Err(Status::PEER_CLOSED)
167 } else {
168 panic!("Unexpected FIDL error during rename: {}", e);
169 }
170 }
171 }
172 }
173
174 pub async fn entries(&self) -> Result<Vec<String>, Status> {
176 match fuchsia_fs::directory::readdir(&self.proxy).await {
177 Ok(entries) => Ok(entries.iter().map(|entry| entry.name.clone()).collect()),
178 Err(fuchsia_fs::directory::EnumerateError::Fidl(_, e)) => {
179 if e.is_closed() {
180 Err(Status::PEER_CLOSED)
181 } else {
182 panic!("Unexpected FIDL error reading dirents: {}", e);
183 }
184 }
185 Err(fuchsia_fs::directory::EnumerateError::ReadDirents(s)) => Err(s),
186 Err(e) => {
187 panic!("Unexpected error reading dirents: {}", e);
188 }
189 }
190 }
191}
192
193#[derive(Debug)]
196pub struct File {
197 proxy: fio::FileProxy,
198}
199
200impl File {
201 pub async fn truncate(&self, length: u64) -> Result<(), Status> {
203 match self.proxy.resize(length).await {
204 Ok(result) => result.map_err(Status::from_raw),
205 Err(e) => {
206 if e.is_closed() {
207 Err(Status::PEER_CLOSED)
208 } else {
209 panic!("Unexpected FIDL error during truncate: {}", e);
210 }
211 }
212 }
213 }
214
215 pub async fn write(&self, data: &[u8]) -> Result<(), Status> {
217 match write(&self.proxy, data).await {
218 Ok(()) => Ok(()),
219 Err(WriteError::Fidl(e)) => {
220 if e.is_closed() {
221 Err(Status::PEER_CLOSED)
222 } else {
223 panic!("Unexpected FIDL error during write: {}", e);
224 }
225 }
226 Err(WriteError::WriteError(s)) => Err(s),
227 Err(e) => panic!("Unexpected error during write: {:?}", e),
228 }
229 }
230
231 pub async fn size_on_disk(&self) -> Result<u64, Status> {
233 match self.proxy.get_attr().await {
234 Ok((raw_status_code, attr)) => {
235 Status::ok(raw_status_code)?;
236 Ok(attr.storage_size)
237 }
238 Err(e) => {
239 if e.is_closed() {
240 Err(Status::PEER_CLOSED)
241 } else {
242 panic!("Unexpected FIDL error during size_on_disk: {}", e)
243 }
244 }
245 }
246 }
247
248 pub async fn uncompressed_size(&self) -> Result<u64, Status> {
250 match self.proxy.get_attr().await {
251 Ok((raw_status_code, attr)) => {
252 Status::ok(raw_status_code)?;
253 Ok(attr.content_size)
254 }
255 Err(e) => {
256 if e.is_closed() {
257 Err(Status::PEER_CLOSED)
258 } else {
259 panic!("Unexpected FIDL error during size_on_disk: {}", e)
260 }
261 }
262 }
263 }
264
265 pub async fn read_num_bytes(&self, num_bytes: u64) -> Result<Vec<u8>, Status> {
268 match read_num_bytes(&self.proxy, num_bytes).await {
269 Ok(data) => Ok(data),
270 Err(ReadError::Fidl(e)) => {
271 if e.is_closed() {
272 Err(Status::PEER_CLOSED)
273 } else {
274 panic!("Unexpected FIDL error during read_exact_num_bytes: {}", e);
275 }
276 }
277 Err(ReadError::ReadError(s)) => Err(s),
278 Err(e) => panic!("Unexpected error during read: {:?}", e),
279 }
280 }
281
282 pub async fn read_until_eof(&self) -> Result<Vec<u8>, Status> {
284 match read(&self.proxy).await {
285 Ok(data) => Ok(data),
286 Err(ReadError::Fidl(e)) => {
287 if e.is_closed() {
288 Err(Status::PEER_CLOSED)
289 } else {
290 panic!("Unexpected FIDL error during read_until_eof: {}", e);
291 }
292 }
293 Err(ReadError::ReadError(s)) => Err(s),
294 Err(e) => panic!("Unexpected error during read_until_eof: {:?}", e),
295 }
296 }
297
298 pub async fn seek(&self, origin: fio::SeekOrigin, offset: u64) -> Result<(), Status> {
300 match self.proxy.seek(origin, offset as i64).await {
301 Ok(result) => result.map_err(Status::from_raw).map(|_: u64| ()),
302 Err(e) => {
303 if e.is_closed() {
304 Err(Status::PEER_CLOSED)
305 } else {
306 panic!("Unexpected FIDL error during seek: {}", e);
307 }
308 }
309 }
310 }
311
312 pub async fn close(self) -> Result<(), Status> {
314 match self.proxy.close().await {
315 Ok(result) => result.map_err(Status::from_raw),
316 Err(e) => {
317 if e.is_closed() {
318 Err(Status::PEER_CLOSED)
319 } else {
320 panic!("Unexpected FIDL error during close: {}", e);
321 }
322 }
323 }
324 }
325}
326
327impl Clone for Directory {
328 fn clone(&self) -> Self {
329 let new_proxy = clone(&self.proxy).unwrap();
330 Self { proxy: new_proxy }
331 }
332}