1use std::env;
2use std::ffi::OsString;
3use std::fs::{self, File, OpenOptions, Permissions};
4use std::io::{Read, Result, Write};
5#[cfg(unix)]
6use std::os::unix::fs::PermissionsExt;
7use std::path::{Path, PathBuf};
8
9#[cfg(feature = "temp")]
10use tempdir;
11
12#[cfg(unix)]
13use UnixFileSystem;
14use {DirEntry, FileSystem, ReadDir};
15#[cfg(feature = "temp")]
16use {TempDir, TempFileSystem};
17
18#[cfg(feature = "temp")]
24#[derive(Debug)]
25pub struct OsTempDir(tempdir::TempDir);
26
27#[cfg(feature = "temp")]
28impl TempDir for OsTempDir {
29 fn path(&self) -> &Path {
30 self.0.path()
31 }
32}
33
34#[derive(Clone, Debug, Default)]
40pub struct OsFileSystem {}
41
42impl OsFileSystem {
43 pub fn new() -> Self {
44 OsFileSystem {}
45 }
46}
47
48impl FileSystem for OsFileSystem {
49 type DirEntry = fs::DirEntry;
50 type ReadDir = fs::ReadDir;
51
52 fn current_dir(&self) -> Result<PathBuf> {
53 env::current_dir()
54 }
55
56 fn set_current_dir<P: AsRef<Path>>(&self, path: P) -> Result<()> {
57 env::set_current_dir(path)
58 }
59
60 fn is_dir<P: AsRef<Path>>(&self, path: P) -> bool {
61 path.as_ref().is_dir()
62 }
63
64 fn is_file<P: AsRef<Path>>(&self, path: P) -> bool {
65 path.as_ref().is_file()
66 }
67
68 fn create_dir<P: AsRef<Path>>(&self, path: P) -> Result<()> {
69 fs::create_dir(path)
70 }
71
72 fn create_dir_all<P: AsRef<Path>>(&self, path: P) -> Result<()> {
73 fs::create_dir_all(path)
74 }
75
76 fn remove_dir<P: AsRef<Path>>(&self, path: P) -> Result<()> {
77 fs::remove_dir(path)
78 }
79
80 fn remove_dir_all<P: AsRef<Path>>(&self, path: P) -> Result<()> {
81 fs::remove_dir_all(path)
82 }
83
84 fn read_dir<P: AsRef<Path>>(&self, path: P) -> Result<Self::ReadDir> {
85 fs::read_dir(path)
86 }
87
88 fn write_file<P, B>(&self, path: P, buf: B) -> Result<()>
89 where
90 P: AsRef<Path>,
91 B: AsRef<[u8]>,
92 {
93 let mut file = File::create(path)?;
94 file.write_all(buf.as_ref())
95 }
96
97 fn overwrite_file<P, B>(&self, path: P, buf: B) -> Result<()>
98 where
99 P: AsRef<Path>,
100 B: AsRef<[u8]>,
101 {
102 let mut file = OpenOptions::new().write(true).truncate(true).open(path)?;
103 file.write_all(buf.as_ref())
104 }
105
106 fn read_file<P: AsRef<Path>>(&self, path: P) -> Result<Vec<u8>> {
107 let mut contents = Vec::<u8>::new();
108 let mut file = File::open(path)?;
109
110 file.read_to_end(&mut contents)?;
111
112 Ok(contents)
113 }
114
115 fn read_file_into<P, B>(&self, path: P, mut buf: B) -> Result<usize>
116 where
117 P: AsRef<Path>,
118 B: AsMut<Vec<u8>>,
119 {
120 let mut file = File::open(path)?;
121 file.read_to_end(buf.as_mut())
122 }
123
124 fn read_file_to_string<P: AsRef<Path>>(&self, path: P) -> Result<String> {
125 let mut contents = String::new();
126 let mut file = File::open(path)?;
127
128 file.read_to_string(&mut contents)?;
129
130 Ok(contents)
131 }
132
133 fn create_file<P, B>(&self, path: P, buf: B) -> Result<()>
134 where
135 P: AsRef<Path>,
136 B: AsRef<[u8]>,
137 {
138 let mut file = OpenOptions::new().write(true).create_new(true).open(path)?;
139
140 file.write_all(buf.as_ref())
141 }
142
143 fn remove_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
144 fs::remove_file(path)
145 }
146
147 fn copy_file<P, Q>(&self, from: P, to: Q) -> Result<()>
148 where
149 P: AsRef<Path>,
150 Q: AsRef<Path>,
151 {
152 fs::copy(from, to).and(Ok(()))
153 }
154
155 fn rename<P, Q>(&self, from: P, to: Q) -> Result<()>
156 where
157 P: AsRef<Path>,
158 Q: AsRef<Path>,
159 {
160 fs::rename(from, to)
161 }
162
163 fn readonly<P: AsRef<Path>>(&self, path: P) -> Result<bool> {
164 permissions(path.as_ref()).map(|p| p.readonly())
165 }
166
167 fn set_readonly<P: AsRef<Path>>(&self, path: P, readonly: bool) -> Result<()> {
168 let mut permissions = permissions(path.as_ref())?;
169
170 permissions.set_readonly(readonly);
171
172 fs::set_permissions(path, permissions)
173 }
174
175 fn len<P: AsRef<Path>>(&self, path: P) -> u64 {
176 fs::metadata(path.as_ref()).map(|md| md.len()).unwrap_or(0)
177 }
178}
179
180#[cfg(unix)]
181impl UnixFileSystem for OsFileSystem {
182 fn mode<P: AsRef<Path>>(&self, path: P) -> Result<u32> {
183 permissions(path.as_ref()).map(|p| p.mode())
184 }
185
186 fn set_mode<P: AsRef<Path>>(&self, path: P, mode: u32) -> Result<()> {
187 let mut permissions = permissions(path.as_ref())?;
188
189 permissions.set_mode(mode);
190
191 fs::set_permissions(path, permissions)
192 }
193}
194
195#[cfg(feature = "temp")]
196impl TempFileSystem for OsFileSystem {
197 type TempDir = OsTempDir;
198
199 fn temp_dir<S: AsRef<str>>(&self, prefix: S) -> Result<Self::TempDir> {
200 tempdir::TempDir::new(prefix.as_ref()).map(OsTempDir)
201 }
202}
203
204impl DirEntry for fs::DirEntry {
205 fn file_name(&self) -> OsString {
206 self.file_name()
207 }
208
209 fn path(&self) -> PathBuf {
210 self.path()
211 }
212}
213
214impl ReadDir<fs::DirEntry> for fs::ReadDir {}
215
216fn permissions(path: &Path) -> Result<Permissions> {
217 let metadata = fs::metadata(path)?;
218
219 Ok(metadata.permissions())
220}