]>
Commit | Line | Data |
---|---|---|
476ff2be SL |
1 | // Copyright 2016 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! Unix-specific extensions to primitives in the `std::fs` module. | |
12 | ||
13 | #![stable(feature = "rust1", since = "1.0.0")] | |
14 | ||
15 | use fs::{self, Permissions, OpenOptions}; | |
16 | use io; | |
17 | use path::Path; | |
18 | use sys; | |
19 | use sys_common::{FromInner, AsInner, AsInnerMut}; | |
20 | ||
21 | /// Unix-specific extensions to `Permissions` | |
22 | #[stable(feature = "fs_ext", since = "1.1.0")] | |
23 | pub trait PermissionsExt { | |
24 | /// Returns the underlying raw `mode_t` bits that are the standard Unix | |
25 | /// permissions for this file. | |
26 | /// | |
27 | /// # Examples | |
28 | /// | |
29 | /// ```rust,ignore | |
30 | /// use std::fs::File; | |
31 | /// use std::os::unix::fs::PermissionsExt; | |
32 | /// | |
32a655c1 SL |
33 | /// let f = File::create("foo.txt")?; |
34 | /// let metadata = f.metadata()?; | |
476ff2be SL |
35 | /// let permissions = metadata.permissions(); |
36 | /// | |
37 | /// println!("permissions: {}", permissions.mode()); | |
38 | /// ``` | |
39 | #[stable(feature = "fs_ext", since = "1.1.0")] | |
40 | fn mode(&self) -> u32; | |
41 | ||
42 | /// Sets the underlying raw bits for this set of permissions. | |
43 | /// | |
44 | /// # Examples | |
45 | /// | |
46 | /// ```rust,ignore | |
47 | /// use std::fs::File; | |
48 | /// use std::os::unix::fs::PermissionsExt; | |
49 | /// | |
32a655c1 SL |
50 | /// let f = File::create("foo.txt")?; |
51 | /// let metadata = f.metadata()?; | |
476ff2be SL |
52 | /// let mut permissions = metadata.permissions(); |
53 | /// | |
54 | /// permissions.set_mode(0o644); // Read/write for owner and read for others. | |
55 | /// assert_eq!(permissions.mode(), 0o644); | |
56 | /// ``` | |
57 | #[stable(feature = "fs_ext", since = "1.1.0")] | |
58 | fn set_mode(&mut self, mode: u32); | |
59 | ||
60 | /// Creates a new instance of `Permissions` from the given set of Unix | |
61 | /// permission bits. | |
62 | /// | |
63 | /// # Examples | |
64 | /// | |
65 | /// ```rust,ignore | |
66 | /// use std::fs::Permissions; | |
67 | /// use std::os::unix::fs::PermissionsExt; | |
68 | /// | |
69 | /// // Read/write for owner and read for others. | |
70 | /// let permissions = Permissions::from_mode(0o644); | |
71 | /// assert_eq!(permissions.mode(), 0o644); | |
72 | /// ``` | |
73 | #[stable(feature = "fs_ext", since = "1.1.0")] | |
74 | fn from_mode(mode: u32) -> Self; | |
75 | } | |
76 | ||
77 | #[stable(feature = "fs_ext", since = "1.1.0")] | |
78 | impl PermissionsExt for Permissions { | |
79 | fn mode(&self) -> u32 { | |
80 | self.as_inner().mode() | |
81 | } | |
82 | ||
83 | fn set_mode(&mut self, mode: u32) { | |
84 | *self = Permissions::from_inner(FromInner::from_inner(mode)); | |
85 | } | |
86 | ||
87 | fn from_mode(mode: u32) -> Permissions { | |
88 | Permissions::from_inner(FromInner::from_inner(mode)) | |
89 | } | |
90 | } | |
91 | ||
92 | /// Unix-specific extensions to `OpenOptions` | |
93 | #[stable(feature = "fs_ext", since = "1.1.0")] | |
94 | pub trait OpenOptionsExt { | |
95 | /// Sets the mode bits that a new file will be created with. | |
96 | /// | |
97 | /// If a new file is created as part of a `File::open_opts` call then this | |
98 | /// specified `mode` will be used as the permission bits for the new file. | |
99 | /// If no `mode` is set, the default of `0o666` will be used. | |
100 | /// The operating system masks out bits with the systems `umask`, to produce | |
101 | /// the final permissions. | |
102 | /// | |
103 | /// # Examples | |
104 | /// | |
105 | /// ```rust,ignore | |
106 | /// extern crate libc; | |
107 | /// use std::fs::OpenOptions; | |
108 | /// use std::os::unix::fs::OpenOptionsExt; | |
109 | /// | |
110 | /// let mut options = OpenOptions::new(); | |
111 | /// options.mode(0o644); // Give read/write for owner and read for others. | |
112 | /// let file = options.open("foo.txt"); | |
113 | /// ``` | |
114 | #[stable(feature = "fs_ext", since = "1.1.0")] | |
115 | fn mode(&mut self, mode: u32) -> &mut Self; | |
116 | ||
117 | /// Pass custom flags to the `flags` agument of `open`. | |
118 | /// | |
119 | /// The bits that define the access mode are masked out with `O_ACCMODE`, to | |
120 | /// ensure they do not interfere with the access mode set by Rusts options. | |
121 | /// | |
122 | /// Custom flags can only set flags, not remove flags set by Rusts options. | |
123 | /// This options overwrites any previously set custom flags. | |
124 | /// | |
125 | /// # Examples | |
126 | /// | |
127 | /// ```rust,ignore | |
128 | /// extern crate libc; | |
129 | /// use std::fs::OpenOptions; | |
130 | /// use std::os::unix::fs::OpenOptionsExt; | |
131 | /// | |
132 | /// let mut options = OpenOptions::new(); | |
133 | /// options.write(true); | |
134 | /// if cfg!(unix) { | |
135 | /// options.custom_flags(libc::O_NOFOLLOW); | |
136 | /// } | |
137 | /// let file = options.open("foo.txt"); | |
138 | /// ``` | |
139 | #[stable(feature = "open_options_ext", since = "1.10.0")] | |
140 | fn custom_flags(&mut self, flags: i32) -> &mut Self; | |
141 | } | |
142 | ||
143 | #[stable(feature = "fs_ext", since = "1.1.0")] | |
144 | impl OpenOptionsExt for OpenOptions { | |
145 | fn mode(&mut self, mode: u32) -> &mut OpenOptions { | |
146 | self.as_inner_mut().mode(mode); self | |
147 | } | |
148 | ||
149 | fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions { | |
150 | self.as_inner_mut().custom_flags(flags); self | |
151 | } | |
152 | } | |
153 | ||
154 | // Hm, why are there casts here to the returned type, shouldn't the types always | |
155 | // be the same? Right you are! Turns out, however, on android at least the types | |
156 | // in the raw `stat` structure are not the same as the types being returned. Who | |
157 | // knew! | |
158 | // | |
159 | // As a result to make sure this compiles for all platforms we do the manual | |
160 | // casts and rely on manual lowering to `stat` if the raw type is desired. | |
161 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
162 | pub trait MetadataExt { | |
8bb4bdeb XL |
163 | #[stable(feature = "metadata_ext", since = "1.1.0")] |
164 | fn dev(&self) -> u64; | |
165 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
166 | fn ino(&self) -> u64; | |
476ff2be SL |
167 | #[stable(feature = "metadata_ext", since = "1.1.0")] |
168 | fn mode(&self) -> u32; | |
169 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
170 | fn uid(&self) -> u32; | |
171 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
172 | fn gid(&self) -> u32; | |
173 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
174 | fn size(&self) -> u64; | |
175 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
176 | fn atime(&self) -> i64; | |
177 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
178 | fn atime_nsec(&self) -> i64; | |
179 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
180 | fn mtime(&self) -> i64; | |
181 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
182 | fn mtime_nsec(&self) -> i64; | |
183 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
184 | fn ctime(&self) -> i64; | |
185 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
186 | fn ctime_nsec(&self) -> i64; | |
187 | } | |
188 | ||
189 | #[stable(feature = "metadata_ext", since = "1.1.0")] | |
190 | impl MetadataExt for fs::Metadata { | |
8bb4bdeb XL |
191 | fn dev(&self) -> u64 { |
192 | self.as_inner().as_inner().st_dev as u64 | |
193 | } | |
194 | fn ino(&self) -> u64 { | |
195 | self.as_inner().as_inner().st_ino as u64 | |
196 | } | |
476ff2be SL |
197 | fn mode(&self) -> u32 { |
198 | self.as_inner().as_inner().st_mode as u32 | |
199 | } | |
200 | fn uid(&self) -> u32 { | |
201 | self.as_inner().as_inner().st_uid as u32 | |
202 | } | |
203 | fn gid(&self) -> u32 { | |
204 | self.as_inner().as_inner().st_gid as u32 | |
205 | } | |
206 | fn size(&self) -> u64 { | |
207 | self.as_inner().as_inner().st_size as u64 | |
208 | } | |
209 | fn atime(&self) -> i64 { | |
210 | self.as_inner().as_inner().st_atime as i64 | |
211 | } | |
212 | fn atime_nsec(&self) -> i64 { | |
213 | self.as_inner().as_inner().st_atime_nsec as i64 | |
214 | } | |
215 | fn mtime(&self) -> i64 { | |
216 | self.as_inner().as_inner().st_mtime as i64 | |
217 | } | |
218 | fn mtime_nsec(&self) -> i64 { | |
219 | self.as_inner().as_inner().st_mtime_nsec as i64 | |
220 | } | |
221 | fn ctime(&self) -> i64 { | |
222 | self.as_inner().as_inner().st_ctime as i64 | |
223 | } | |
224 | fn ctime_nsec(&self) -> i64 { | |
225 | self.as_inner().as_inner().st_ctime_nsec as i64 | |
226 | } | |
227 | } | |
228 | ||
229 | /// Add special unix types (block/char device, fifo and socket) | |
230 | #[stable(feature = "file_type_ext", since = "1.5.0")] | |
231 | pub trait FileTypeExt { | |
232 | /// Returns whether this file type is a block device. | |
233 | #[stable(feature = "file_type_ext", since = "1.5.0")] | |
234 | fn is_block_device(&self) -> bool; | |
235 | /// Returns whether this file type is a char device. | |
236 | #[stable(feature = "file_type_ext", since = "1.5.0")] | |
237 | fn is_char_device(&self) -> bool; | |
238 | /// Returns whether this file type is a fifo. | |
239 | #[stable(feature = "file_type_ext", since = "1.5.0")] | |
240 | fn is_fifo(&self) -> bool; | |
241 | /// Returns whether this file type is a socket. | |
242 | #[stable(feature = "file_type_ext", since = "1.5.0")] | |
243 | fn is_socket(&self) -> bool; | |
244 | } | |
245 | ||
246 | #[stable(feature = "file_type_ext", since = "1.5.0")] | |
247 | impl FileTypeExt for fs::FileType { | |
248 | fn is_block_device(&self) -> bool { false /*FIXME: Implement block device mode*/ } | |
249 | fn is_char_device(&self) -> bool { false /*FIXME: Implement char device mode*/ } | |
250 | fn is_fifo(&self) -> bool { false /*FIXME: Implement fifo mode*/ } | |
251 | fn is_socket(&self) -> bool { false /*FIXME: Implement socket mode*/ } | |
252 | } | |
253 | ||
254 | /// Creates a new symbolic link on the filesystem. | |
255 | /// | |
256 | /// The `dst` path will be a symbolic link pointing to the `src` path. | |
257 | /// | |
258 | /// # Note | |
259 | /// | |
260 | /// On Windows, you must specify whether a symbolic link points to a file | |
261 | /// or directory. Use `os::windows::fs::symlink_file` to create a | |
262 | /// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a | |
263 | /// symbolic link to a directory. Additionally, the process must have | |
264 | /// `SeCreateSymbolicLinkPrivilege` in order to be able to create a | |
265 | /// symbolic link. | |
266 | /// | |
267 | /// # Examples | |
268 | /// | |
269 | /// ``` | |
270 | /// use std::os::unix::fs; | |
271 | /// | |
272 | /// # fn foo() -> std::io::Result<()> { | |
32a655c1 | 273 | /// fs::symlink("a.txt", "b.txt")?; |
476ff2be SL |
274 | /// # Ok(()) |
275 | /// # } | |
276 | /// ``` | |
277 | #[stable(feature = "symlink", since = "1.1.0")] | |
278 | pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> | |
279 | { | |
280 | sys::fs::symlink(src.as_ref(), dst.as_ref()) | |
281 | } | |
282 | ||
283 | #[stable(feature = "dir_builder", since = "1.6.0")] | |
284 | /// An extension trait for `fs::DirBuilder` for unix-specific options. | |
285 | pub trait DirBuilderExt { | |
286 | /// Sets the mode to create new directories with. This option defaults to | |
287 | /// 0o777. | |
288 | /// | |
289 | /// # Examples | |
290 | /// | |
291 | /// ```ignore | |
292 | /// use std::fs::DirBuilder; | |
293 | /// use std::os::unix::fs::DirBuilderExt; | |
294 | /// | |
295 | /// let mut builder = DirBuilder::new(); | |
296 | /// builder.mode(0o755); | |
297 | /// ``` | |
298 | #[stable(feature = "dir_builder", since = "1.6.0")] | |
299 | fn mode(&mut self, mode: u32) -> &mut Self; | |
300 | } | |
301 | ||
302 | #[stable(feature = "dir_builder", since = "1.6.0")] | |
303 | impl DirBuilderExt for fs::DirBuilder { | |
304 | fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder { | |
305 | self.as_inner_mut().set_mode(mode); | |
306 | self | |
307 | } | |
308 | } |