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