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