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