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.
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.
11 //! Unix-specific extensions to primitives in the `std::fs` module.
13 #![stable(feature = "rust1", since = "1.0.0")]
15 use fs::{self, Permissions, OpenOptions};
20 use sys_common::{FromInner, AsInner, AsInnerMut};
21 use sys::platform::fs::MetadataExt as UnixMetadataExt;
23 /// Unix-specific extensions to `File`
24 #[unstable(feature = "file_offset", issue = "35918")]
26 /// Reads a number of bytes starting from a given offset.
28 /// Returns the number of bytes read.
30 /// The offset is relative to the start of the file and thus independent
31 /// from the current cursor.
33 /// The current file cursor is not affected by this function.
35 /// Note that similar to `File::read`, it is not an error to return with a
37 #[unstable(feature = "file_offset", issue = "35918")]
38 fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
40 /// Writes a number of bytes starting from a given offset.
42 /// Returns the number of bytes written.
44 /// The offset is relative to the start of the file and thus independent
45 /// from the current cursor.
47 /// The current file cursor is not affected by this function.
49 /// When writing beyond the end of the file, the file is appropiately
50 /// extended and the intermediate bytes are initialized with the value 0.
52 /// Note that similar to `File::write`, it is not an error to return a
54 #[unstable(feature = "file_offset", issue = "35918")]
55 fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
58 #[unstable(feature = "file_offset", issue = "35918")]
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)
63 fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
64 self.as_inner().write_at(buf, offset)
68 /// Unix-specific extensions to `Permissions`
69 #[stable(feature = "fs_ext", since = "1.1.0")]
70 pub trait PermissionsExt {
71 /// Returns the underlying raw `mode_t` bits that are the standard Unix
72 /// permissions for this file.
77 /// use std::fs::File;
78 /// use std::os::unix::fs::PermissionsExt;
80 /// let f = try!(File::create("foo.txt"));
81 /// let metadata = try!(f.metadata());
82 /// let permissions = metadata.permissions();
84 /// println!("permissions: {}", permissions.mode());
86 #[stable(feature = "fs_ext", since = "1.1.0")]
87 fn mode(&self) -> u32;
89 /// Sets the underlying raw bits for this set of permissions.
94 /// use std::fs::File;
95 /// use std::os::unix::fs::PermissionsExt;
97 /// let f = try!(File::create("foo.txt"));
98 /// let metadata = try!(f.metadata());
99 /// let mut permissions = metadata.permissions();
101 /// permissions.set_mode(0o644); // Read/write for owner and read for others.
102 /// assert_eq!(permissions.mode(), 0o644);
104 #[stable(feature = "fs_ext", since = "1.1.0")]
105 fn set_mode(&mut self, mode: u32);
107 /// Creates a new instance of `Permissions` from the given set of Unix
113 /// use std::fs::Permissions;
114 /// use std::os::unix::fs::PermissionsExt;
116 /// // Read/write for owner and read for others.
117 /// let permissions = Permissions::from_mode(0o644);
118 /// assert_eq!(permissions.mode(), 0o644);
120 #[stable(feature = "fs_ext", since = "1.1.0")]
121 fn from_mode(mode: u32) -> Self;
124 #[stable(feature = "fs_ext", since = "1.1.0")]
125 impl PermissionsExt for Permissions {
126 fn mode(&self) -> u32 {
127 self.as_inner().mode()
130 fn set_mode(&mut self, mode: u32) {
131 *self = Permissions::from_inner(FromInner::from_inner(mode));
134 fn from_mode(mode: u32) -> Permissions {
135 Permissions::from_inner(FromInner::from_inner(mode))
139 /// Unix-specific extensions to `OpenOptions`
140 #[stable(feature = "fs_ext", since = "1.1.0")]
141 pub trait OpenOptionsExt {
142 /// Sets the mode bits that a new file will be created with.
144 /// If a new file is created as part of a `File::open_opts` call then this
145 /// specified `mode` will be used as the permission bits for the new file.
146 /// If no `mode` is set, the default of `0o666` will be used.
147 /// The operating system masks out bits with the systems `umask`, to produce
148 /// the final permissions.
153 /// extern crate libc;
154 /// use std::fs::OpenOptions;
155 /// use std::os::unix::fs::OpenOptionsExt;
157 /// let mut options = OpenOptions::new();
158 /// options.mode(0o644); // Give read/write for owner and read for others.
159 /// let file = options.open("foo.txt");
161 #[stable(feature = "fs_ext", since = "1.1.0")]
162 fn mode(&mut self, mode: u32) -> &mut Self;
164 /// Pass custom flags to the `flags` agument of `open`.
166 /// The bits that define the access mode are masked out with `O_ACCMODE`, to
167 /// ensure they do not interfere with the access mode set by Rusts options.
169 /// Custom flags can only set flags, not remove flags set by Rusts options.
170 /// This options overwrites any previously set custom flags.
175 /// extern crate libc;
176 /// use std::fs::OpenOptions;
177 /// use std::os::unix::fs::OpenOptionsExt;
179 /// let mut options = OpenOptions::new();
180 /// options.write(true);
182 /// options.custom_flags(libc::O_NOFOLLOW);
184 /// let file = options.open("foo.txt");
186 #[stable(feature = "open_options_ext", since = "1.10.0")]
187 fn custom_flags(&mut self, flags: i32) -> &mut Self;
190 #[stable(feature = "fs_ext", since = "1.1.0")]
191 impl OpenOptionsExt for OpenOptions {
192 fn mode(&mut self, mode: u32) -> &mut OpenOptions {
193 self.as_inner_mut().mode(mode); self
196 fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
197 self.as_inner_mut().custom_flags(flags); self
201 // Hm, why are there casts here to the returned type, shouldn't the types always
202 // be the same? Right you are! Turns out, however, on android at least the types
203 // in the raw `stat` structure are not the same as the types being returned. Who
206 // As a result to make sure this compiles for all platforms we do the manual
207 // casts and rely on manual lowering to `stat` if the raw type is desired.
208 #[stable(feature = "metadata_ext", since = "1.1.0")]
209 pub trait MetadataExt {
210 #[stable(feature = "metadata_ext", since = "1.1.0")]
211 fn dev(&self) -> u64;
212 #[stable(feature = "metadata_ext", since = "1.1.0")]
213 fn ino(&self) -> u64;
214 #[stable(feature = "metadata_ext", since = "1.1.0")]
215 fn mode(&self) -> u32;
216 #[stable(feature = "metadata_ext", since = "1.1.0")]
217 fn nlink(&self) -> u64;
218 #[stable(feature = "metadata_ext", since = "1.1.0")]
219 fn uid(&self) -> u32;
220 #[stable(feature = "metadata_ext", since = "1.1.0")]
221 fn gid(&self) -> u32;
222 #[stable(feature = "metadata_ext", since = "1.1.0")]
223 fn rdev(&self) -> u64;
224 #[stable(feature = "metadata_ext", since = "1.1.0")]
225 fn size(&self) -> u64;
226 #[stable(feature = "metadata_ext", since = "1.1.0")]
227 fn atime(&self) -> i64;
228 #[stable(feature = "metadata_ext", since = "1.1.0")]
229 fn atime_nsec(&self) -> i64;
230 #[stable(feature = "metadata_ext", since = "1.1.0")]
231 fn mtime(&self) -> i64;
232 #[stable(feature = "metadata_ext", since = "1.1.0")]
233 fn mtime_nsec(&self) -> i64;
234 #[stable(feature = "metadata_ext", since = "1.1.0")]
235 fn ctime(&self) -> i64;
236 #[stable(feature = "metadata_ext", since = "1.1.0")]
237 fn ctime_nsec(&self) -> i64;
238 #[stable(feature = "metadata_ext", since = "1.1.0")]
239 fn blksize(&self) -> u64;
240 #[stable(feature = "metadata_ext", since = "1.1.0")]
241 fn blocks(&self) -> u64;
244 #[stable(feature = "metadata_ext", since = "1.1.0")]
245 impl MetadataExt for fs::Metadata {
246 fn dev(&self) -> u64 { self.st_dev() }
247 fn ino(&self) -> u64 { self.st_ino() }
248 fn mode(&self) -> u32 { self.st_mode() }
249 fn nlink(&self) -> u64 { self.st_nlink() }
250 fn uid(&self) -> u32 { self.st_uid() }
251 fn gid(&self) -> u32 { self.st_gid() }
252 fn rdev(&self) -> u64 { self.st_rdev() }
253 fn size(&self) -> u64 { self.st_size() }
254 fn atime(&self) -> i64 { self.st_atime() }
255 fn atime_nsec(&self) -> i64 { self.st_atime_nsec() }
256 fn mtime(&self) -> i64 { self.st_mtime() }
257 fn mtime_nsec(&self) -> i64 { self.st_mtime_nsec() }
258 fn ctime(&self) -> i64 { self.st_ctime() }
259 fn ctime_nsec(&self) -> i64 { self.st_ctime_nsec() }
260 fn blksize(&self) -> u64 { self.st_blksize() }
261 fn blocks(&self) -> u64 { self.st_blocks() }
264 /// Add special unix types (block/char device, fifo and socket)
265 #[stable(feature = "file_type_ext", since = "1.5.0")]
266 pub trait FileTypeExt {
267 /// Returns whether this file type is a block device.
268 #[stable(feature = "file_type_ext", since = "1.5.0")]
269 fn is_block_device(&self) -> bool;
270 /// Returns whether this file type is a char device.
271 #[stable(feature = "file_type_ext", since = "1.5.0")]
272 fn is_char_device(&self) -> bool;
273 /// Returns whether this file type is a fifo.
274 #[stable(feature = "file_type_ext", since = "1.5.0")]
275 fn is_fifo(&self) -> bool;
276 /// Returns whether this file type is a socket.
277 #[stable(feature = "file_type_ext", since = "1.5.0")]
278 fn is_socket(&self) -> bool;
281 #[stable(feature = "file_type_ext", since = "1.5.0")]
282 impl FileTypeExt for fs::FileType {
283 fn is_block_device(&self) -> bool { self.as_inner().is(libc::S_IFBLK) }
284 fn is_char_device(&self) -> bool { self.as_inner().is(libc::S_IFCHR) }
285 fn is_fifo(&self) -> bool { self.as_inner().is(libc::S_IFIFO) }
286 fn is_socket(&self) -> bool { self.as_inner().is(libc::S_IFSOCK) }
289 /// Unix-specific extension methods for `fs::DirEntry`
290 #[stable(feature = "dir_entry_ext", since = "1.1.0")]
291 pub trait DirEntryExt {
292 /// Returns the underlying `d_ino` field in the contained `dirent`
299 /// use std::os::unix::fs::DirEntryExt;
301 /// if let Ok(entries) = fs::read_dir(".") {
302 /// for entry in entries {
303 /// if let Ok(entry) = entry {
304 /// // Here, `entry` is a `DirEntry`.
305 /// println!("{:?}: {}", entry.file_name(), entry.ino());
310 #[stable(feature = "dir_entry_ext", since = "1.1.0")]
311 fn ino(&self) -> u64;
314 #[stable(feature = "dir_entry_ext", since = "1.1.0")]
315 impl DirEntryExt for fs::DirEntry {
316 fn ino(&self) -> u64 { self.as_inner().ino() }
319 /// Creates a new symbolic link on the filesystem.
321 /// The `dst` path will be a symbolic link pointing to the `src` path.
325 /// On Windows, you must specify whether a symbolic link points to a file
326 /// or directory. Use `os::windows::fs::symlink_file` to create a
327 /// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
328 /// symbolic link to a directory. Additionally, the process must have
329 /// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
335 /// use std::os::unix::fs;
337 /// # fn foo() -> std::io::Result<()> {
338 /// try!(fs::symlink("a.txt", "b.txt"));
342 #[stable(feature = "symlink", since = "1.1.0")]
343 pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
345 sys::fs::symlink(src.as_ref(), dst.as_ref())
348 #[stable(feature = "dir_builder", since = "1.6.0")]
349 /// An extension trait for `fs::DirBuilder` for unix-specific options.
350 pub trait DirBuilderExt {
351 /// Sets the mode to create new directories with. This option defaults to
357 /// use std::fs::DirBuilder;
358 /// use std::os::unix::fs::DirBuilderExt;
360 /// let mut builder = DirBuilder::new();
361 /// builder.mode(0o755);
363 #[stable(feature = "dir_builder", since = "1.6.0")]
364 fn mode(&mut self, mode: u32) -> &mut Self;
367 #[stable(feature = "dir_builder", since = "1.6.0")]
368 impl DirBuilderExt for fs::DirBuilder {
369 fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder {
370 self.as_inner_mut().set_mode(mode);