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