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