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