1use fidl_fuchsia_io as fio;
8
9pub mod directory;
10pub mod file;
11pub mod node;
12
13pub use fio::{Flags, OpenFlags, PERM_EXECUTABLE, PERM_READABLE, PERM_WRITABLE};
16
17pub fn canonicalize_path(path: &str) -> &str {
20 if path == "/" {
21 return ".";
22 }
23 if path.starts_with('/') {
24 return &path[1..];
25 }
26 path
27}
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32 use std::fs;
33 use std::path::Path;
34 use tempfile::TempDir;
35 use vfs::file::vmo::read_only;
36 use vfs::pseudo_directory;
37 use vfs::remote::remote_dir;
38 use {fuchsia_async as fasync, zx_status};
39
40 #[fasync::run_singlethreaded(test)]
41 async fn open_and_read_file_test() {
42 let tempdir = TempDir::new().expect("failed to create tmp dir");
43 let data = "abc".repeat(10000);
44 fs::write(tempdir.path().join("myfile"), &data).expect("failed writing file");
45
46 let dir = crate::directory::open_in_namespace(
47 tempdir.path().to_str().unwrap(),
48 fio::PERM_READABLE,
49 )
50 .expect("could not open tmp dir");
51 let file = directory::open_file_async(&dir, "myfile", fio::PERM_READABLE)
52 .expect("could not open file");
53 let contents = file::read_to_string(&file).await.expect("could not read file");
54 assert_eq!(&contents, &data, "File contents did not match");
55 }
56
57 #[fasync::run_singlethreaded(test)]
58 async fn open_and_write_file_test() {
59 let tempdir = TempDir::new().expect("failed to create tmp dir");
61 let dir = crate::directory::open_in_namespace(
62 tempdir.path().to_str().unwrap(),
63 fio::PERM_READABLE | fio::PERM_WRITABLE,
64 )
65 .expect("could not open tmp dir");
66
67 let file_name = Path::new("myfile");
69 let data = "abc".repeat(10000);
70 let file = directory::open_file_async(
71 &dir,
72 file_name.to_str().unwrap(),
73 fio::Flags::FLAG_MAYBE_CREATE | fio::PERM_WRITABLE,
74 )
75 .expect("could not open file");
76 file::write(&file, &data).await.expect("could not write file");
77
78 let contents = std::fs::read_to_string(tempdir.path().join(file_name)).unwrap();
80 assert_eq!(&contents, &data, "File contents did not match");
81 }
82
83 #[test]
84 fn test_canonicalize_path() {
85 assert_eq!(canonicalize_path("/"), ".");
86 assert_eq!(canonicalize_path("/foo"), "foo");
87 assert_eq!(canonicalize_path("/foo/bar/"), "foo/bar/");
88
89 assert_eq!(canonicalize_path("."), ".");
90 assert_eq!(canonicalize_path("./"), "./");
91 assert_eq!(canonicalize_path("foo/bar/"), "foo/bar/");
92 }
93
94 #[fasync::run_singlethreaded(test)]
95 async fn flags_test() {
96 let tempdir = TempDir::new().expect("failed to create tmp dir");
97 std::fs::write(tempdir.path().join("read_write"), "rw/read_write")
98 .expect("failed to write file");
99 let dir = crate::directory::open_in_namespace(
100 tempdir.path().to_str().unwrap(),
101 fio::PERM_READABLE | fio::PERM_WRITABLE,
102 )
103 .expect("could not open tmp dir");
104 let example_dir = pseudo_directory! {
105 "ro" => pseudo_directory! {
106 "read_only" => read_only("ro/read_only"),
107 },
108 "rw" => remote_dir(dir)
109 };
110 let example_dir_proxy =
111 vfs::directory::serve(example_dir, fio::PERM_READABLE | fio::PERM_WRITABLE);
112
113 for (file_name, flags, should_succeed) in vec![
114 ("ro/read_only", fio::PERM_READABLE, true),
115 ("ro/read_only", fio::PERM_READABLE | fio::PERM_WRITABLE, false),
116 ("ro/read_only", fio::PERM_WRITABLE, false),
117 ("rw/read_write", fio::PERM_READABLE, true),
118 ("rw/read_write", fio::PERM_READABLE | fio::PERM_WRITABLE, true),
119 ("rw/read_write", fio::PERM_WRITABLE, true),
120 ] {
121 let file_proxy =
122 directory::open_file_async(&example_dir_proxy, file_name, flags).unwrap();
123 match (should_succeed, file_proxy.query().await) {
124 (true, Ok(_)) => (),
125 (false, Err(_)) => continue,
126 (true, Err(e)) => {
127 panic!("failed to open when expected success, couldn't describe: {:?}", e)
128 }
129 (false, Ok(d)) => {
130 panic!("successfully opened when expected failure, could describe: {:?}", d)
131 }
132 }
133 if flags.intersects(fio::Flags::PERM_READ) {
134 assert_eq!(
135 file_name,
136 file::read_to_string(&file_proxy).await.expect("failed to read file")
137 );
138 }
139 if flags.intersects(fio::Flags::PERM_WRITE) {
140 let _: u64 = file_proxy
141 .write(b"write_only")
142 .await
143 .expect("write failed")
144 .map_err(zx_status::Status::from_raw)
145 .expect("write error");
146 }
147 assert_eq!(file_proxy.close().await.unwrap(), Ok(()));
148 }
149 }
150}