| 1 | //! Filesystem manipulation operations. |
| 2 | //! |
| 3 | //! This module contains basic methods to manipulate the contents of the local |
| 4 | //! filesystem. All methods in this module represent cross-platform filesystem |
| 5 | //! operations. Extra platform-specific functionality can be found in the |
| 6 | //! extension traits of `std::os::$platform`. |
| 7 | |
| 8 | #![stable (feature = "rust1" , since = "1.0.0" )] |
| 9 | #![deny (unsafe_op_in_unsafe_fn)] |
| 10 | |
| 11 | #[cfg (all( |
| 12 | test, |
| 13 | not(any( |
| 14 | target_os = "emscripten" , |
| 15 | target_os = "wasi" , |
| 16 | target_env = "sgx" , |
| 17 | target_os = "xous" , |
| 18 | target_os = "trusty" , |
| 19 | )) |
| 20 | ))] |
| 21 | mod tests; |
| 22 | |
| 23 | use crate::ffi::OsString; |
| 24 | use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; |
| 25 | use crate::path::{Path, PathBuf}; |
| 26 | use crate::sealed::Sealed; |
| 27 | use crate::sync::Arc; |
| 28 | use crate::sys::fs as fs_imp; |
| 29 | use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; |
| 30 | use crate::time::SystemTime; |
| 31 | use crate::{error, fmt}; |
| 32 | |
| 33 | /// An object providing access to an open file on the filesystem. |
| 34 | /// |
| 35 | /// An instance of a `File` can be read and/or written depending on what options |
| 36 | /// it was opened with. Files also implement [`Seek`] to alter the logical cursor |
| 37 | /// that the file contains internally. |
| 38 | /// |
| 39 | /// Files are automatically closed when they go out of scope. Errors detected |
| 40 | /// on closing are ignored by the implementation of `Drop`. Use the method |
| 41 | /// [`sync_all`] if these errors must be manually handled. |
| 42 | /// |
| 43 | /// `File` does not buffer reads and writes. For efficiency, consider wrapping the |
| 44 | /// file in a [`BufReader`] or [`BufWriter`] when performing many small [`read`] |
| 45 | /// or [`write`] calls, unless unbuffered reads and writes are required. |
| 46 | /// |
| 47 | /// # Examples |
| 48 | /// |
| 49 | /// Creates a new file and write bytes to it (you can also use [`write`]): |
| 50 | /// |
| 51 | /// ```no_run |
| 52 | /// use std::fs::File; |
| 53 | /// use std::io::prelude::*; |
| 54 | /// |
| 55 | /// fn main() -> std::io::Result<()> { |
| 56 | /// let mut file = File::create("foo.txt" )?; |
| 57 | /// file.write_all(b"Hello, world!" )?; |
| 58 | /// Ok(()) |
| 59 | /// } |
| 60 | /// ``` |
| 61 | /// |
| 62 | /// Reads the contents of a file into a [`String`] (you can also use [`read`]): |
| 63 | /// |
| 64 | /// ```no_run |
| 65 | /// use std::fs::File; |
| 66 | /// use std::io::prelude::*; |
| 67 | /// |
| 68 | /// fn main() -> std::io::Result<()> { |
| 69 | /// let mut file = File::open("foo.txt" )?; |
| 70 | /// let mut contents = String::new(); |
| 71 | /// file.read_to_string(&mut contents)?; |
| 72 | /// assert_eq!(contents, "Hello, world!" ); |
| 73 | /// Ok(()) |
| 74 | /// } |
| 75 | /// ``` |
| 76 | /// |
| 77 | /// Using a buffered [`Read`]er: |
| 78 | /// |
| 79 | /// ```no_run |
| 80 | /// use std::fs::File; |
| 81 | /// use std::io::BufReader; |
| 82 | /// use std::io::prelude::*; |
| 83 | /// |
| 84 | /// fn main() -> std::io::Result<()> { |
| 85 | /// let file = File::open("foo.txt" )?; |
| 86 | /// let mut buf_reader = BufReader::new(file); |
| 87 | /// let mut contents = String::new(); |
| 88 | /// buf_reader.read_to_string(&mut contents)?; |
| 89 | /// assert_eq!(contents, "Hello, world!" ); |
| 90 | /// Ok(()) |
| 91 | /// } |
| 92 | /// ``` |
| 93 | /// |
| 94 | /// Note that, although read and write methods require a `&mut File`, because |
| 95 | /// of the interfaces for [`Read`] and [`Write`], the holder of a `&File` can |
| 96 | /// still modify the file, either through methods that take `&File` or by |
| 97 | /// retrieving the underlying OS object and modifying the file that way. |
| 98 | /// Additionally, many operating systems allow concurrent modification of files |
| 99 | /// by different processes. Avoid assuming that holding a `&File` means that the |
| 100 | /// file will not change. |
| 101 | /// |
| 102 | /// # Platform-specific behavior |
| 103 | /// |
| 104 | /// On Windows, the implementation of [`Read`] and [`Write`] traits for `File` |
| 105 | /// perform synchronous I/O operations. Therefore the underlying file must not |
| 106 | /// have been opened for asynchronous I/O (e.g. by using `FILE_FLAG_OVERLAPPED`). |
| 107 | /// |
| 108 | /// [`BufReader`]: io::BufReader |
| 109 | /// [`BufWriter`]: io::BufWriter |
| 110 | /// [`sync_all`]: File::sync_all |
| 111 | /// [`write`]: File::write |
| 112 | /// [`read`]: File::read |
| 113 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 114 | #[cfg_attr (not(test), rustc_diagnostic_item = "File" )] |
| 115 | pub struct File { |
| 116 | inner: fs_imp::File, |
| 117 | } |
| 118 | |
| 119 | /// An enumeration of possible errors which can occur while trying to acquire a lock |
| 120 | /// from the [`try_lock`] method and [`try_lock_shared`] method on a [`File`]. |
| 121 | /// |
| 122 | /// [`try_lock`]: File::try_lock |
| 123 | /// [`try_lock_shared`]: File::try_lock_shared |
| 124 | #[unstable (feature = "file_lock" , issue = "130994" )] |
| 125 | pub enum TryLockError { |
| 126 | /// The lock could not be acquired due to an I/O error on the file. The standard library will |
| 127 | /// not return an [`ErrorKind::WouldBlock`] error inside [`TryLockError::Error`] |
| 128 | /// |
| 129 | /// [`ErrorKind::WouldBlock`]: io::ErrorKind::WouldBlock |
| 130 | Error(io::Error), |
| 131 | /// The lock could not be acquired at this time because it is held by another handle/process. |
| 132 | WouldBlock, |
| 133 | } |
| 134 | |
| 135 | /// Metadata information about a file. |
| 136 | /// |
| 137 | /// This structure is returned from the [`metadata`] or |
| 138 | /// [`symlink_metadata`] function or method and represents known |
| 139 | /// metadata about a file such as its permissions, size, modification |
| 140 | /// times, etc. |
| 141 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 142 | #[derive (Clone)] |
| 143 | pub struct Metadata(fs_imp::FileAttr); |
| 144 | |
| 145 | /// Iterator over the entries in a directory. |
| 146 | /// |
| 147 | /// This iterator is returned from the [`read_dir`] function of this module and |
| 148 | /// will yield instances of <code>[io::Result]<[DirEntry]></code>. Through a [`DirEntry`] |
| 149 | /// information like the entry's path and possibly other metadata can be |
| 150 | /// learned. |
| 151 | /// |
| 152 | /// The order in which this iterator returns entries is platform and filesystem |
| 153 | /// dependent. |
| 154 | /// |
| 155 | /// # Errors |
| 156 | /// |
| 157 | /// This [`io::Result`] will be an [`Err`] if there's some sort of intermittent |
| 158 | /// IO error during iteration. |
| 159 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 160 | #[derive (Debug)] |
| 161 | pub struct ReadDir(fs_imp::ReadDir); |
| 162 | |
| 163 | /// Entries returned by the [`ReadDir`] iterator. |
| 164 | /// |
| 165 | /// An instance of `DirEntry` represents an entry inside of a directory on the |
| 166 | /// filesystem. Each entry can be inspected via methods to learn about the full |
| 167 | /// path or possibly other metadata through per-platform extension traits. |
| 168 | /// |
| 169 | /// # Platform-specific behavior |
| 170 | /// |
| 171 | /// On Unix, the `DirEntry` struct contains an internal reference to the open |
| 172 | /// directory. Holding `DirEntry` objects will consume a file handle even |
| 173 | /// after the `ReadDir` iterator is dropped. |
| 174 | /// |
| 175 | /// Note that this [may change in the future][changes]. |
| 176 | /// |
| 177 | /// [changes]: io#platform-specific-behavior |
| 178 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 179 | pub struct DirEntry(fs_imp::DirEntry); |
| 180 | |
| 181 | /// Options and flags which can be used to configure how a file is opened. |
| 182 | /// |
| 183 | /// This builder exposes the ability to configure how a [`File`] is opened and |
| 184 | /// what operations are permitted on the open file. The [`File::open`] and |
| 185 | /// [`File::create`] methods are aliases for commonly used options using this |
| 186 | /// builder. |
| 187 | /// |
| 188 | /// Generally speaking, when using `OpenOptions`, you'll first call |
| 189 | /// [`OpenOptions::new`], then chain calls to methods to set each option, then |
| 190 | /// call [`OpenOptions::open`], passing the path of the file you're trying to |
| 191 | /// open. This will give you a [`io::Result`] with a [`File`] inside that you |
| 192 | /// can further operate on. |
| 193 | /// |
| 194 | /// # Examples |
| 195 | /// |
| 196 | /// Opening a file to read: |
| 197 | /// |
| 198 | /// ```no_run |
| 199 | /// use std::fs::OpenOptions; |
| 200 | /// |
| 201 | /// let file = OpenOptions::new().read(true).open("foo.txt" ); |
| 202 | /// ``` |
| 203 | /// |
| 204 | /// Opening a file for both reading and writing, as well as creating it if it |
| 205 | /// doesn't exist: |
| 206 | /// |
| 207 | /// ```no_run |
| 208 | /// use std::fs::OpenOptions; |
| 209 | /// |
| 210 | /// let file = OpenOptions::new() |
| 211 | /// .read(true) |
| 212 | /// .write(true) |
| 213 | /// .create(true) |
| 214 | /// .open("foo.txt" ); |
| 215 | /// ``` |
| 216 | #[derive (Clone, Debug)] |
| 217 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 218 | #[cfg_attr (not(test), rustc_diagnostic_item = "FsOpenOptions" )] |
| 219 | pub struct OpenOptions(fs_imp::OpenOptions); |
| 220 | |
| 221 | /// Representation of the various timestamps on a file. |
| 222 | #[derive (Copy, Clone, Debug, Default)] |
| 223 | #[stable (feature = "file_set_times" , since = "1.75.0" )] |
| 224 | pub struct FileTimes(fs_imp::FileTimes); |
| 225 | |
| 226 | /// Representation of the various permissions on a file. |
| 227 | /// |
| 228 | /// This module only currently provides one bit of information, |
| 229 | /// [`Permissions::readonly`], which is exposed on all currently supported |
| 230 | /// platforms. Unix-specific functionality, such as mode bits, is available |
| 231 | /// through the [`PermissionsExt`] trait. |
| 232 | /// |
| 233 | /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt |
| 234 | #[derive (Clone, PartialEq, Eq, Debug)] |
| 235 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 236 | #[cfg_attr (not(test), rustc_diagnostic_item = "FsPermissions" )] |
| 237 | pub struct Permissions(fs_imp::FilePermissions); |
| 238 | |
| 239 | /// A structure representing a type of file with accessors for each file type. |
| 240 | /// It is returned by [`Metadata::file_type`] method. |
| 241 | #[stable (feature = "file_type" , since = "1.1.0" )] |
| 242 | #[derive (Copy, Clone, PartialEq, Eq, Hash)] |
| 243 | #[cfg_attr (not(test), rustc_diagnostic_item = "FileType" )] |
| 244 | pub struct FileType(fs_imp::FileType); |
| 245 | |
| 246 | /// A builder used to create directories in various manners. |
| 247 | /// |
| 248 | /// This builder also supports platform-specific options. |
| 249 | #[stable (feature = "dir_builder" , since = "1.6.0" )] |
| 250 | #[cfg_attr (not(test), rustc_diagnostic_item = "DirBuilder" )] |
| 251 | #[derive (Debug)] |
| 252 | pub struct DirBuilder { |
| 253 | inner: fs_imp::DirBuilder, |
| 254 | recursive: bool, |
| 255 | } |
| 256 | |
| 257 | /// Reads the entire contents of a file into a bytes vector. |
| 258 | /// |
| 259 | /// This is a convenience function for using [`File::open`] and [`read_to_end`] |
| 260 | /// with fewer imports and without an intermediate variable. |
| 261 | /// |
| 262 | /// [`read_to_end`]: Read::read_to_end |
| 263 | /// |
| 264 | /// # Errors |
| 265 | /// |
| 266 | /// This function will return an error if `path` does not already exist. |
| 267 | /// Other errors may also be returned according to [`OpenOptions::open`]. |
| 268 | /// |
| 269 | /// While reading from the file, this function handles [`io::ErrorKind::Interrupted`] |
| 270 | /// with automatic retries. See [io::Read] documentation for details. |
| 271 | /// |
| 272 | /// # Examples |
| 273 | /// |
| 274 | /// ```no_run |
| 275 | /// use std::fs; |
| 276 | /// |
| 277 | /// fn main() -> Result<(), Box<dyn std::error::Error + 'static>> { |
| 278 | /// let data: Vec<u8> = fs::read("image.jpg" )?; |
| 279 | /// assert_eq!(data[0..3], [0xFF, 0xD8, 0xFF]); |
| 280 | /// Ok(()) |
| 281 | /// } |
| 282 | /// ``` |
| 283 | #[stable (feature = "fs_read_write_bytes" , since = "1.26.0" )] |
| 284 | pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> { |
| 285 | fn inner(path: &Path) -> io::Result<Vec<u8>> { |
| 286 | let mut file: File = File::open(path)?; |
| 287 | let size: Option = file.metadata().map(|m: Metadata| m.len() as usize).ok(); |
| 288 | let mut bytes: Vec = Vec::try_with_capacity(size.unwrap_or(default:0))?; |
| 289 | io::default_read_to_end(&mut file, &mut bytes, size)?; |
| 290 | Ok(bytes) |
| 291 | } |
| 292 | inner(path.as_ref()) |
| 293 | } |
| 294 | |
| 295 | /// Reads the entire contents of a file into a string. |
| 296 | /// |
| 297 | /// This is a convenience function for using [`File::open`] and [`read_to_string`] |
| 298 | /// with fewer imports and without an intermediate variable. |
| 299 | /// |
| 300 | /// [`read_to_string`]: Read::read_to_string |
| 301 | /// |
| 302 | /// # Errors |
| 303 | /// |
| 304 | /// This function will return an error if `path` does not already exist. |
| 305 | /// Other errors may also be returned according to [`OpenOptions::open`]. |
| 306 | /// |
| 307 | /// If the contents of the file are not valid UTF-8, then an error will also be |
| 308 | /// returned. |
| 309 | /// |
| 310 | /// While reading from the file, this function handles [`io::ErrorKind::Interrupted`] |
| 311 | /// with automatic retries. See [io::Read] documentation for details. |
| 312 | /// |
| 313 | /// # Examples |
| 314 | /// |
| 315 | /// ```no_run |
| 316 | /// use std::fs; |
| 317 | /// use std::error::Error; |
| 318 | /// |
| 319 | /// fn main() -> Result<(), Box<dyn Error>> { |
| 320 | /// let message: String = fs::read_to_string("message.txt" )?; |
| 321 | /// println!("{}" , message); |
| 322 | /// Ok(()) |
| 323 | /// } |
| 324 | /// ``` |
| 325 | #[stable (feature = "fs_read_write" , since = "1.26.0" )] |
| 326 | pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> { |
| 327 | fn inner(path: &Path) -> io::Result<String> { |
| 328 | let mut file: File = File::open(path)?; |
| 329 | let size: Option = file.metadata().map(|m: Metadata| m.len() as usize).ok(); |
| 330 | let mut string: String = String::new(); |
| 331 | string.try_reserve_exact(additional:size.unwrap_or(default:0))?; |
| 332 | io::default_read_to_string(&mut file, &mut string, size)?; |
| 333 | Ok(string) |
| 334 | } |
| 335 | inner(path.as_ref()) |
| 336 | } |
| 337 | |
| 338 | /// Writes a slice as the entire contents of a file. |
| 339 | /// |
| 340 | /// This function will create a file if it does not exist, |
| 341 | /// and will entirely replace its contents if it does. |
| 342 | /// |
| 343 | /// Depending on the platform, this function may fail if the |
| 344 | /// full directory path does not exist. |
| 345 | /// |
| 346 | /// This is a convenience function for using [`File::create`] and [`write_all`] |
| 347 | /// with fewer imports. |
| 348 | /// |
| 349 | /// [`write_all`]: Write::write_all |
| 350 | /// |
| 351 | /// # Examples |
| 352 | /// |
| 353 | /// ```no_run |
| 354 | /// use std::fs; |
| 355 | /// |
| 356 | /// fn main() -> std::io::Result<()> { |
| 357 | /// fs::write("foo.txt" , b"Lorem ipsum" )?; |
| 358 | /// fs::write("bar.txt" , "dolor sit" )?; |
| 359 | /// Ok(()) |
| 360 | /// } |
| 361 | /// ``` |
| 362 | #[stable (feature = "fs_read_write_bytes" , since = "1.26.0" )] |
| 363 | pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { |
| 364 | fn inner(path: &Path, contents: &[u8]) -> io::Result<()> { |
| 365 | File::create(path)?.write_all(buf:contents) |
| 366 | } |
| 367 | inner(path.as_ref(), contents.as_ref()) |
| 368 | } |
| 369 | |
| 370 | #[unstable (feature = "file_lock" , issue = "130994" )] |
| 371 | impl error::Error for TryLockError {} |
| 372 | |
| 373 | #[unstable (feature = "file_lock" , issue = "130994" )] |
| 374 | impl fmt::Debug for TryLockError { |
| 375 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 376 | match self { |
| 377 | TryLockError::Error(err: &Error) => err.fmt(f), |
| 378 | TryLockError::WouldBlock => "WouldBlock" .fmt(f), |
| 379 | } |
| 380 | } |
| 381 | } |
| 382 | |
| 383 | #[unstable (feature = "file_lock" , issue = "130994" )] |
| 384 | impl fmt::Display for TryLockError { |
| 385 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 386 | match&'static str self { |
| 387 | TryLockError::Error(_) => "lock acquisition failed due to I/O error" , |
| 388 | TryLockError::WouldBlock => "lock acquisition failed because the operation would block" , |
| 389 | } |
| 390 | .fmt(f) |
| 391 | } |
| 392 | } |
| 393 | |
| 394 | #[unstable (feature = "file_lock" , issue = "130994" )] |
| 395 | impl From<TryLockError> for io::Error { |
| 396 | fn from(err: TryLockError) -> io::Error { |
| 397 | match err { |
| 398 | TryLockError::Error(err: Error) => err, |
| 399 | TryLockError::WouldBlock => io::ErrorKind::WouldBlock.into(), |
| 400 | } |
| 401 | } |
| 402 | } |
| 403 | |
| 404 | impl File { |
| 405 | /// Attempts to open a file in read-only mode. |
| 406 | /// |
| 407 | /// See the [`OpenOptions::open`] method for more details. |
| 408 | /// |
| 409 | /// If you only need to read the entire file contents, |
| 410 | /// consider [`std::fs::read()`][self::read] or |
| 411 | /// [`std::fs::read_to_string()`][self::read_to_string] instead. |
| 412 | /// |
| 413 | /// # Errors |
| 414 | /// |
| 415 | /// This function will return an error if `path` does not already exist. |
| 416 | /// Other errors may also be returned according to [`OpenOptions::open`]. |
| 417 | /// |
| 418 | /// # Examples |
| 419 | /// |
| 420 | /// ```no_run |
| 421 | /// use std::fs::File; |
| 422 | /// use std::io::Read; |
| 423 | /// |
| 424 | /// fn main() -> std::io::Result<()> { |
| 425 | /// let mut f = File::open("foo.txt" )?; |
| 426 | /// let mut data = vec![]; |
| 427 | /// f.read_to_end(&mut data)?; |
| 428 | /// Ok(()) |
| 429 | /// } |
| 430 | /// ``` |
| 431 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 432 | pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> { |
| 433 | OpenOptions::new().read(true).open(path.as_ref()) |
| 434 | } |
| 435 | |
| 436 | /// Attempts to open a file in read-only mode with buffering. |
| 437 | /// |
| 438 | /// See the [`OpenOptions::open`] method, the [`BufReader`][io::BufReader] type, |
| 439 | /// and the [`BufRead`][io::BufRead] trait for more details. |
| 440 | /// |
| 441 | /// If you only need to read the entire file contents, |
| 442 | /// consider [`std::fs::read()`][self::read] or |
| 443 | /// [`std::fs::read_to_string()`][self::read_to_string] instead. |
| 444 | /// |
| 445 | /// # Errors |
| 446 | /// |
| 447 | /// This function will return an error if `path` does not already exist, |
| 448 | /// or if memory allocation fails for the new buffer. |
| 449 | /// Other errors may also be returned according to [`OpenOptions::open`]. |
| 450 | /// |
| 451 | /// # Examples |
| 452 | /// |
| 453 | /// ```no_run |
| 454 | /// #![feature(file_buffered)] |
| 455 | /// use std::fs::File; |
| 456 | /// use std::io::BufRead; |
| 457 | /// |
| 458 | /// fn main() -> std::io::Result<()> { |
| 459 | /// let mut f = File::open_buffered("foo.txt" )?; |
| 460 | /// assert!(f.capacity() > 0); |
| 461 | /// for (line, i) in f.lines().zip(1..) { |
| 462 | /// println!("{i:6}: {}" , line?); |
| 463 | /// } |
| 464 | /// Ok(()) |
| 465 | /// } |
| 466 | /// ``` |
| 467 | #[unstable (feature = "file_buffered" , issue = "130804" )] |
| 468 | pub fn open_buffered<P: AsRef<Path>>(path: P) -> io::Result<io::BufReader<File>> { |
| 469 | // Allocate the buffer *first* so we don't affect the filesystem otherwise. |
| 470 | let buffer = io::BufReader::<Self>::try_new_buffer()?; |
| 471 | let file = File::open(path)?; |
| 472 | Ok(io::BufReader::with_buffer(file, buffer)) |
| 473 | } |
| 474 | |
| 475 | /// Opens a file in write-only mode. |
| 476 | /// |
| 477 | /// This function will create a file if it does not exist, |
| 478 | /// and will truncate it if it does. |
| 479 | /// |
| 480 | /// Depending on the platform, this function may fail if the |
| 481 | /// full directory path does not exist. |
| 482 | /// See the [`OpenOptions::open`] function for more details. |
| 483 | /// |
| 484 | /// See also [`std::fs::write()`][self::write] for a simple function to |
| 485 | /// create a file with some given data. |
| 486 | /// |
| 487 | /// # Examples |
| 488 | /// |
| 489 | /// ```no_run |
| 490 | /// use std::fs::File; |
| 491 | /// use std::io::Write; |
| 492 | /// |
| 493 | /// fn main() -> std::io::Result<()> { |
| 494 | /// let mut f = File::create("foo.txt" )?; |
| 495 | /// f.write_all(&1234_u32.to_be_bytes())?; |
| 496 | /// Ok(()) |
| 497 | /// } |
| 498 | /// ``` |
| 499 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 500 | pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> { |
| 501 | OpenOptions::new().write(true).create(true).truncate(true).open(path.as_ref()) |
| 502 | } |
| 503 | |
| 504 | /// Opens a file in write-only mode with buffering. |
| 505 | /// |
| 506 | /// This function will create a file if it does not exist, |
| 507 | /// and will truncate it if it does. |
| 508 | /// |
| 509 | /// Depending on the platform, this function may fail if the |
| 510 | /// full directory path does not exist. |
| 511 | /// |
| 512 | /// See the [`OpenOptions::open`] method and the |
| 513 | /// [`BufWriter`][io::BufWriter] type for more details. |
| 514 | /// |
| 515 | /// See also [`std::fs::write()`][self::write] for a simple function to |
| 516 | /// create a file with some given data. |
| 517 | /// |
| 518 | /// # Examples |
| 519 | /// |
| 520 | /// ```no_run |
| 521 | /// #![feature(file_buffered)] |
| 522 | /// use std::fs::File; |
| 523 | /// use std::io::Write; |
| 524 | /// |
| 525 | /// fn main() -> std::io::Result<()> { |
| 526 | /// let mut f = File::create_buffered("foo.txt" )?; |
| 527 | /// assert!(f.capacity() > 0); |
| 528 | /// for i in 0..100 { |
| 529 | /// writeln!(&mut f, "{i}" )?; |
| 530 | /// } |
| 531 | /// f.flush()?; |
| 532 | /// Ok(()) |
| 533 | /// } |
| 534 | /// ``` |
| 535 | #[unstable (feature = "file_buffered" , issue = "130804" )] |
| 536 | pub fn create_buffered<P: AsRef<Path>>(path: P) -> io::Result<io::BufWriter<File>> { |
| 537 | // Allocate the buffer *first* so we don't affect the filesystem otherwise. |
| 538 | let buffer = io::BufWriter::<Self>::try_new_buffer()?; |
| 539 | let file = File::create(path)?; |
| 540 | Ok(io::BufWriter::with_buffer(file, buffer)) |
| 541 | } |
| 542 | |
| 543 | /// Creates a new file in read-write mode; error if the file exists. |
| 544 | /// |
| 545 | /// This function will create a file if it does not exist, or return an error if it does. This |
| 546 | /// way, if the call succeeds, the file returned is guaranteed to be new. |
| 547 | /// If a file exists at the target location, creating a new file will fail with [`AlreadyExists`] |
| 548 | /// or another error based on the situation. See [`OpenOptions::open`] for a |
| 549 | /// non-exhaustive list of likely errors. |
| 550 | /// |
| 551 | /// This option is useful because it is atomic. Otherwise between checking whether a file |
| 552 | /// exists and creating a new one, the file may have been created by another process (a TOCTOU |
| 553 | /// race condition / attack). |
| 554 | /// |
| 555 | /// This can also be written using |
| 556 | /// `File::options().read(true).write(true).create_new(true).open(...)`. |
| 557 | /// |
| 558 | /// [`AlreadyExists`]: crate::io::ErrorKind::AlreadyExists |
| 559 | /// |
| 560 | /// # Examples |
| 561 | /// |
| 562 | /// ```no_run |
| 563 | /// use std::fs::File; |
| 564 | /// use std::io::Write; |
| 565 | /// |
| 566 | /// fn main() -> std::io::Result<()> { |
| 567 | /// let mut f = File::create_new("foo.txt" )?; |
| 568 | /// f.write_all("Hello, world!" .as_bytes())?; |
| 569 | /// Ok(()) |
| 570 | /// } |
| 571 | /// ``` |
| 572 | #[stable (feature = "file_create_new" , since = "1.77.0" )] |
| 573 | pub fn create_new<P: AsRef<Path>>(path: P) -> io::Result<File> { |
| 574 | OpenOptions::new().read(true).write(true).create_new(true).open(path.as_ref()) |
| 575 | } |
| 576 | |
| 577 | /// Returns a new OpenOptions object. |
| 578 | /// |
| 579 | /// This function returns a new OpenOptions object that you can use to |
| 580 | /// open or create a file with specific options if `open()` or `create()` |
| 581 | /// are not appropriate. |
| 582 | /// |
| 583 | /// It is equivalent to `OpenOptions::new()`, but allows you to write more |
| 584 | /// readable code. Instead of |
| 585 | /// `OpenOptions::new().append(true).open("example.log")`, |
| 586 | /// you can write `File::options().append(true).open("example.log")`. This |
| 587 | /// also avoids the need to import `OpenOptions`. |
| 588 | /// |
| 589 | /// See the [`OpenOptions::new`] function for more details. |
| 590 | /// |
| 591 | /// # Examples |
| 592 | /// |
| 593 | /// ```no_run |
| 594 | /// use std::fs::File; |
| 595 | /// use std::io::Write; |
| 596 | /// |
| 597 | /// fn main() -> std::io::Result<()> { |
| 598 | /// let mut f = File::options().append(true).open("example.log" )?; |
| 599 | /// writeln!(&mut f, "new line" )?; |
| 600 | /// Ok(()) |
| 601 | /// } |
| 602 | /// ``` |
| 603 | #[must_use ] |
| 604 | #[stable (feature = "with_options" , since = "1.58.0" )] |
| 605 | #[cfg_attr (not(test), rustc_diagnostic_item = "file_options" )] |
| 606 | pub fn options() -> OpenOptions { |
| 607 | OpenOptions::new() |
| 608 | } |
| 609 | |
| 610 | /// Attempts to sync all OS-internal file content and metadata to disk. |
| 611 | /// |
| 612 | /// This function will attempt to ensure that all in-memory data reaches the |
| 613 | /// filesystem before returning. |
| 614 | /// |
| 615 | /// This can be used to handle errors that would otherwise only be caught |
| 616 | /// when the `File` is closed, as dropping a `File` will ignore all errors. |
| 617 | /// Note, however, that `sync_all` is generally more expensive than closing |
| 618 | /// a file by dropping it, because the latter is not required to block until |
| 619 | /// the data has been written to the filesystem. |
| 620 | /// |
| 621 | /// If synchronizing the metadata is not required, use [`sync_data`] instead. |
| 622 | /// |
| 623 | /// [`sync_data`]: File::sync_data |
| 624 | /// |
| 625 | /// # Examples |
| 626 | /// |
| 627 | /// ```no_run |
| 628 | /// use std::fs::File; |
| 629 | /// use std::io::prelude::*; |
| 630 | /// |
| 631 | /// fn main() -> std::io::Result<()> { |
| 632 | /// let mut f = File::create("foo.txt" )?; |
| 633 | /// f.write_all(b"Hello, world!" )?; |
| 634 | /// |
| 635 | /// f.sync_all()?; |
| 636 | /// Ok(()) |
| 637 | /// } |
| 638 | /// ``` |
| 639 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 640 | #[doc (alias = "fsync" )] |
| 641 | pub fn sync_all(&self) -> io::Result<()> { |
| 642 | self.inner.fsync() |
| 643 | } |
| 644 | |
| 645 | /// This function is similar to [`sync_all`], except that it might not |
| 646 | /// synchronize file metadata to the filesystem. |
| 647 | /// |
| 648 | /// This is intended for use cases that must synchronize content, but don't |
| 649 | /// need the metadata on disk. The goal of this method is to reduce disk |
| 650 | /// operations. |
| 651 | /// |
| 652 | /// Note that some platforms may simply implement this in terms of |
| 653 | /// [`sync_all`]. |
| 654 | /// |
| 655 | /// [`sync_all`]: File::sync_all |
| 656 | /// |
| 657 | /// # Examples |
| 658 | /// |
| 659 | /// ```no_run |
| 660 | /// use std::fs::File; |
| 661 | /// use std::io::prelude::*; |
| 662 | /// |
| 663 | /// fn main() -> std::io::Result<()> { |
| 664 | /// let mut f = File::create("foo.txt" )?; |
| 665 | /// f.write_all(b"Hello, world!" )?; |
| 666 | /// |
| 667 | /// f.sync_data()?; |
| 668 | /// Ok(()) |
| 669 | /// } |
| 670 | /// ``` |
| 671 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 672 | #[doc (alias = "fdatasync" )] |
| 673 | pub fn sync_data(&self) -> io::Result<()> { |
| 674 | self.inner.datasync() |
| 675 | } |
| 676 | |
| 677 | /// Acquire an exclusive lock on the file. Blocks until the lock can be acquired. |
| 678 | /// |
| 679 | /// This acquires an exclusive lock; no other file handle to this file may acquire another lock. |
| 680 | /// |
| 681 | /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], |
| 682 | /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with |
| 683 | /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not |
| 684 | /// cause non-lockholders to block. |
| 685 | /// |
| 686 | /// If this file handle/descriptor, or a clone of it, already holds an lock the exact behavior |
| 687 | /// is unspecified and platform dependent, including the possibility that it will deadlock. |
| 688 | /// However, if this method returns, then an exclusive lock is held. |
| 689 | /// |
| 690 | /// If the file not open for writing, it is unspecified whether this function returns an error. |
| 691 | /// |
| 692 | /// The lock will be released when this file (along with any other file descriptors/handles |
| 693 | /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called. |
| 694 | /// |
| 695 | /// # Platform-specific behavior |
| 696 | /// |
| 697 | /// This function currently corresponds to the `flock` function on Unix with the `LOCK_EX` flag, |
| 698 | /// and the `LockFileEx` function on Windows with the `LOCKFILE_EXCLUSIVE_LOCK` flag. Note that, |
| 699 | /// this [may change in the future][changes]. |
| 700 | /// |
| 701 | /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, |
| 702 | /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`. |
| 703 | /// |
| 704 | /// [changes]: io#platform-specific-behavior |
| 705 | /// |
| 706 | /// [`lock`]: File::lock |
| 707 | /// [`lock_shared`]: File::lock_shared |
| 708 | /// [`try_lock`]: File::try_lock |
| 709 | /// [`try_lock_shared`]: File::try_lock_shared |
| 710 | /// [`unlock`]: File::unlock |
| 711 | /// [`read`]: Read::read |
| 712 | /// [`write`]: Write::write |
| 713 | /// |
| 714 | /// # Examples |
| 715 | /// |
| 716 | /// ```no_run |
| 717 | /// #![feature(file_lock)] |
| 718 | /// use std::fs::File; |
| 719 | /// |
| 720 | /// fn main() -> std::io::Result<()> { |
| 721 | /// let f = File::create("foo.txt" )?; |
| 722 | /// f.lock()?; |
| 723 | /// Ok(()) |
| 724 | /// } |
| 725 | /// ``` |
| 726 | #[unstable (feature = "file_lock" , issue = "130994" )] |
| 727 | pub fn lock(&self) -> io::Result<()> { |
| 728 | self.inner.lock() |
| 729 | } |
| 730 | |
| 731 | /// Acquire a shared (non-exclusive) lock on the file. Blocks until the lock can be acquired. |
| 732 | /// |
| 733 | /// This acquires a shared lock; more than one file handle may hold a shared lock, but none may |
| 734 | /// hold an exclusive lock at the same time. |
| 735 | /// |
| 736 | /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], |
| 737 | /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with |
| 738 | /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not |
| 739 | /// cause non-lockholders to block. |
| 740 | /// |
| 741 | /// If this file handle/descriptor, or a clone of it, already holds an lock, the exact behavior |
| 742 | /// is unspecified and platform dependent, including the possibility that it will deadlock. |
| 743 | /// However, if this method returns, then a shared lock is held. |
| 744 | /// |
| 745 | /// The lock will be released when this file (along with any other file descriptors/handles |
| 746 | /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called. |
| 747 | /// |
| 748 | /// # Platform-specific behavior |
| 749 | /// |
| 750 | /// This function currently corresponds to the `flock` function on Unix with the `LOCK_SH` flag, |
| 751 | /// and the `LockFileEx` function on Windows. Note that, this |
| 752 | /// [may change in the future][changes]. |
| 753 | /// |
| 754 | /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, |
| 755 | /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`. |
| 756 | /// |
| 757 | /// [changes]: io#platform-specific-behavior |
| 758 | /// |
| 759 | /// [`lock`]: File::lock |
| 760 | /// [`lock_shared`]: File::lock_shared |
| 761 | /// [`try_lock`]: File::try_lock |
| 762 | /// [`try_lock_shared`]: File::try_lock_shared |
| 763 | /// [`unlock`]: File::unlock |
| 764 | /// [`read`]: Read::read |
| 765 | /// [`write`]: Write::write |
| 766 | /// |
| 767 | /// # Examples |
| 768 | /// |
| 769 | /// ```no_run |
| 770 | /// #![feature(file_lock)] |
| 771 | /// use std::fs::File; |
| 772 | /// |
| 773 | /// fn main() -> std::io::Result<()> { |
| 774 | /// let f = File::open("foo.txt" )?; |
| 775 | /// f.lock_shared()?; |
| 776 | /// Ok(()) |
| 777 | /// } |
| 778 | /// ``` |
| 779 | #[unstable (feature = "file_lock" , issue = "130994" )] |
| 780 | pub fn lock_shared(&self) -> io::Result<()> { |
| 781 | self.inner.lock_shared() |
| 782 | } |
| 783 | |
| 784 | /// Try to acquire an exclusive lock on the file. |
| 785 | /// |
| 786 | /// Returns `Err(TryLockError::WouldBlock)` if a different lock is already held on this file |
| 787 | /// (via another handle/descriptor). |
| 788 | /// |
| 789 | /// This acquires an exclusive lock; no other file handle to this file may acquire another lock. |
| 790 | /// |
| 791 | /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], |
| 792 | /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with |
| 793 | /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not |
| 794 | /// cause non-lockholders to block. |
| 795 | /// |
| 796 | /// If this file handle/descriptor, or a clone of it, already holds an lock, the exact behavior |
| 797 | /// is unspecified and platform dependent, including the possibility that it will deadlock. |
| 798 | /// However, if this method returns `Ok(true)`, then it has acquired an exclusive lock. |
| 799 | /// |
| 800 | /// If the file not open for writing, it is unspecified whether this function returns an error. |
| 801 | /// |
| 802 | /// The lock will be released when this file (along with any other file descriptors/handles |
| 803 | /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called. |
| 804 | /// |
| 805 | /// # Platform-specific behavior |
| 806 | /// |
| 807 | /// This function currently corresponds to the `flock` function on Unix with the `LOCK_EX` and |
| 808 | /// `LOCK_NB` flags, and the `LockFileEx` function on Windows with the `LOCKFILE_EXCLUSIVE_LOCK` |
| 809 | /// and `LOCKFILE_FAIL_IMMEDIATELY` flags. Note that, this |
| 810 | /// [may change in the future][changes]. |
| 811 | /// |
| 812 | /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, |
| 813 | /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`. |
| 814 | /// |
| 815 | /// [changes]: io#platform-specific-behavior |
| 816 | /// |
| 817 | /// [`lock`]: File::lock |
| 818 | /// [`lock_shared`]: File::lock_shared |
| 819 | /// [`try_lock`]: File::try_lock |
| 820 | /// [`try_lock_shared`]: File::try_lock_shared |
| 821 | /// [`unlock`]: File::unlock |
| 822 | /// [`read`]: Read::read |
| 823 | /// [`write`]: Write::write |
| 824 | /// |
| 825 | /// # Examples |
| 826 | /// |
| 827 | /// ```no_run |
| 828 | /// #![feature(file_lock)] |
| 829 | /// use std::fs::{File, TryLockError}; |
| 830 | /// |
| 831 | /// fn main() -> std::io::Result<()> { |
| 832 | /// let f = File::create("foo.txt" )?; |
| 833 | /// // Explicit handling of the WouldBlock error |
| 834 | /// match f.try_lock() { |
| 835 | /// Ok(_) => (), |
| 836 | /// Err(TryLockError::WouldBlock) => (), // Lock not acquired |
| 837 | /// Err(TryLockError::Error(err)) => return Err(err), |
| 838 | /// } |
| 839 | /// // Alternately, propagate the error as an io::Error |
| 840 | /// f.try_lock()?; |
| 841 | /// Ok(()) |
| 842 | /// } |
| 843 | /// ``` |
| 844 | #[unstable (feature = "file_lock" , issue = "130994" )] |
| 845 | pub fn try_lock(&self) -> Result<(), TryLockError> { |
| 846 | self.inner.try_lock() |
| 847 | } |
| 848 | |
| 849 | /// Try to acquire a shared (non-exclusive) lock on the file. |
| 850 | /// |
| 851 | /// Returns `Err(TryLockError::WouldBlock)` if a different lock is already held on this file |
| 852 | /// (via another handle/descriptor). |
| 853 | /// |
| 854 | /// This acquires a shared lock; more than one file handle may hold a shared lock, but none may |
| 855 | /// hold an exclusive lock at the same time. |
| 856 | /// |
| 857 | /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], |
| 858 | /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with |
| 859 | /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not |
| 860 | /// cause non-lockholders to block. |
| 861 | /// |
| 862 | /// If this file handle, or a clone of it, already holds an lock, the exact behavior is |
| 863 | /// unspecified and platform dependent, including the possibility that it will deadlock. |
| 864 | /// However, if this method returns `Ok(true)`, then it has acquired a shared lock. |
| 865 | /// |
| 866 | /// The lock will be released when this file (along with any other file descriptors/handles |
| 867 | /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called. |
| 868 | /// |
| 869 | /// # Platform-specific behavior |
| 870 | /// |
| 871 | /// This function currently corresponds to the `flock` function on Unix with the `LOCK_SH` and |
| 872 | /// `LOCK_NB` flags, and the `LockFileEx` function on Windows with the |
| 873 | /// `LOCKFILE_FAIL_IMMEDIATELY` flag. Note that, this |
| 874 | /// [may change in the future][changes]. |
| 875 | /// |
| 876 | /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, |
| 877 | /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`. |
| 878 | /// |
| 879 | /// [changes]: io#platform-specific-behavior |
| 880 | /// |
| 881 | /// [`lock`]: File::lock |
| 882 | /// [`lock_shared`]: File::lock_shared |
| 883 | /// [`try_lock`]: File::try_lock |
| 884 | /// [`try_lock_shared`]: File::try_lock_shared |
| 885 | /// [`unlock`]: File::unlock |
| 886 | /// [`read`]: Read::read |
| 887 | /// [`write`]: Write::write |
| 888 | /// |
| 889 | /// # Examples |
| 890 | /// |
| 891 | /// ```no_run |
| 892 | /// #![feature(file_lock)] |
| 893 | /// use std::fs::{File, TryLockError}; |
| 894 | /// |
| 895 | /// fn main() -> std::io::Result<()> { |
| 896 | /// let f = File::open("foo.txt" )?; |
| 897 | /// // Explicit handling of the WouldBlock error |
| 898 | /// match f.try_lock_shared() { |
| 899 | /// Ok(_) => (), |
| 900 | /// Err(TryLockError::WouldBlock) => (), // Lock not acquired |
| 901 | /// Err(TryLockError::Error(err)) => return Err(err), |
| 902 | /// } |
| 903 | /// // Alternately, propagate the error as an io::Error |
| 904 | /// f.try_lock_shared()?; |
| 905 | /// |
| 906 | /// Ok(()) |
| 907 | /// } |
| 908 | /// ``` |
| 909 | #[unstable (feature = "file_lock" , issue = "130994" )] |
| 910 | pub fn try_lock_shared(&self) -> Result<(), TryLockError> { |
| 911 | self.inner.try_lock_shared() |
| 912 | } |
| 913 | |
| 914 | /// Release all locks on the file. |
| 915 | /// |
| 916 | /// All locks are released when the file (along with any other file descriptors/handles |
| 917 | /// duplicated or inherited from it) is closed. This method allows releasing locks without |
| 918 | /// closing the file. |
| 919 | /// |
| 920 | /// If no lock is currently held via this file descriptor/handle, this method may return an |
| 921 | /// error, or may return successfully without taking any action. |
| 922 | /// |
| 923 | /// # Platform-specific behavior |
| 924 | /// |
| 925 | /// This function currently corresponds to the `flock` function on Unix with the `LOCK_UN` flag, |
| 926 | /// and the `UnlockFile` function on Windows. Note that, this |
| 927 | /// [may change in the future][changes]. |
| 928 | /// |
| 929 | /// On Windows, locking a file will fail if the file is opened only for append. To lock a file, |
| 930 | /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`. |
| 931 | /// |
| 932 | /// [changes]: io#platform-specific-behavior |
| 933 | /// |
| 934 | /// # Examples |
| 935 | /// |
| 936 | /// ```no_run |
| 937 | /// #![feature(file_lock)] |
| 938 | /// use std::fs::File; |
| 939 | /// |
| 940 | /// fn main() -> std::io::Result<()> { |
| 941 | /// let f = File::open("foo.txt" )?; |
| 942 | /// f.lock()?; |
| 943 | /// f.unlock()?; |
| 944 | /// Ok(()) |
| 945 | /// } |
| 946 | /// ``` |
| 947 | #[unstable (feature = "file_lock" , issue = "130994" )] |
| 948 | pub fn unlock(&self) -> io::Result<()> { |
| 949 | self.inner.unlock() |
| 950 | } |
| 951 | |
| 952 | /// Truncates or extends the underlying file, updating the size of |
| 953 | /// this file to become `size`. |
| 954 | /// |
| 955 | /// If the `size` is less than the current file's size, then the file will |
| 956 | /// be shrunk. If it is greater than the current file's size, then the file |
| 957 | /// will be extended to `size` and have all of the intermediate data filled |
| 958 | /// in with 0s. |
| 959 | /// |
| 960 | /// The file's cursor isn't changed. In particular, if the cursor was at the |
| 961 | /// end and the file is shrunk using this operation, the cursor will now be |
| 962 | /// past the end. |
| 963 | /// |
| 964 | /// # Errors |
| 965 | /// |
| 966 | /// This function will return an error if the file is not opened for writing. |
| 967 | /// Also, [`std::io::ErrorKind::InvalidInput`](crate::io::ErrorKind::InvalidInput) |
| 968 | /// will be returned if the desired length would cause an overflow due to |
| 969 | /// the implementation specifics. |
| 970 | /// |
| 971 | /// # Examples |
| 972 | /// |
| 973 | /// ```no_run |
| 974 | /// use std::fs::File; |
| 975 | /// |
| 976 | /// fn main() -> std::io::Result<()> { |
| 977 | /// let mut f = File::create("foo.txt" )?; |
| 978 | /// f.set_len(10)?; |
| 979 | /// Ok(()) |
| 980 | /// } |
| 981 | /// ``` |
| 982 | /// |
| 983 | /// Note that this method alters the content of the underlying file, even |
| 984 | /// though it takes `&self` rather than `&mut self`. |
| 985 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 986 | pub fn set_len(&self, size: u64) -> io::Result<()> { |
| 987 | self.inner.truncate(size) |
| 988 | } |
| 989 | |
| 990 | /// Queries metadata about the underlying file. |
| 991 | /// |
| 992 | /// # Examples |
| 993 | /// |
| 994 | /// ```no_run |
| 995 | /// use std::fs::File; |
| 996 | /// |
| 997 | /// fn main() -> std::io::Result<()> { |
| 998 | /// let mut f = File::open("foo.txt" )?; |
| 999 | /// let metadata = f.metadata()?; |
| 1000 | /// Ok(()) |
| 1001 | /// } |
| 1002 | /// ``` |
| 1003 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1004 | pub fn metadata(&self) -> io::Result<Metadata> { |
| 1005 | self.inner.file_attr().map(Metadata) |
| 1006 | } |
| 1007 | |
| 1008 | /// Creates a new `File` instance that shares the same underlying file handle |
| 1009 | /// as the existing `File` instance. Reads, writes, and seeks will affect |
| 1010 | /// both `File` instances simultaneously. |
| 1011 | /// |
| 1012 | /// # Examples |
| 1013 | /// |
| 1014 | /// Creates two handles for a file named `foo.txt`: |
| 1015 | /// |
| 1016 | /// ```no_run |
| 1017 | /// use std::fs::File; |
| 1018 | /// |
| 1019 | /// fn main() -> std::io::Result<()> { |
| 1020 | /// let mut file = File::open("foo.txt" )?; |
| 1021 | /// let file_copy = file.try_clone()?; |
| 1022 | /// Ok(()) |
| 1023 | /// } |
| 1024 | /// ``` |
| 1025 | /// |
| 1026 | /// Assuming there’s a file named `foo.txt` with contents `abcdef\n`, create |
| 1027 | /// two handles, seek one of them, and read the remaining bytes from the |
| 1028 | /// other handle: |
| 1029 | /// |
| 1030 | /// ```no_run |
| 1031 | /// use std::fs::File; |
| 1032 | /// use std::io::SeekFrom; |
| 1033 | /// use std::io::prelude::*; |
| 1034 | /// |
| 1035 | /// fn main() -> std::io::Result<()> { |
| 1036 | /// let mut file = File::open("foo.txt" )?; |
| 1037 | /// let mut file_copy = file.try_clone()?; |
| 1038 | /// |
| 1039 | /// file.seek(SeekFrom::Start(3))?; |
| 1040 | /// |
| 1041 | /// let mut contents = vec![]; |
| 1042 | /// file_copy.read_to_end(&mut contents)?; |
| 1043 | /// assert_eq!(contents, b"def \n" ); |
| 1044 | /// Ok(()) |
| 1045 | /// } |
| 1046 | /// ``` |
| 1047 | #[stable (feature = "file_try_clone" , since = "1.9.0" )] |
| 1048 | pub fn try_clone(&self) -> io::Result<File> { |
| 1049 | Ok(File { inner: self.inner.duplicate()? }) |
| 1050 | } |
| 1051 | |
| 1052 | /// Changes the permissions on the underlying file. |
| 1053 | /// |
| 1054 | /// # Platform-specific behavior |
| 1055 | /// |
| 1056 | /// This function currently corresponds to the `fchmod` function on Unix and |
| 1057 | /// the `SetFileInformationByHandle` function on Windows. Note that, this |
| 1058 | /// [may change in the future][changes]. |
| 1059 | /// |
| 1060 | /// [changes]: io#platform-specific-behavior |
| 1061 | /// |
| 1062 | /// # Errors |
| 1063 | /// |
| 1064 | /// This function will return an error if the user lacks permission change |
| 1065 | /// attributes on the underlying file. It may also return an error in other |
| 1066 | /// os-specific unspecified cases. |
| 1067 | /// |
| 1068 | /// # Examples |
| 1069 | /// |
| 1070 | /// ```no_run |
| 1071 | /// fn main() -> std::io::Result<()> { |
| 1072 | /// use std::fs::File; |
| 1073 | /// |
| 1074 | /// let file = File::open("foo.txt" )?; |
| 1075 | /// let mut perms = file.metadata()?.permissions(); |
| 1076 | /// perms.set_readonly(true); |
| 1077 | /// file.set_permissions(perms)?; |
| 1078 | /// Ok(()) |
| 1079 | /// } |
| 1080 | /// ``` |
| 1081 | /// |
| 1082 | /// Note that this method alters the permissions of the underlying file, |
| 1083 | /// even though it takes `&self` rather than `&mut self`. |
| 1084 | #[doc (alias = "fchmod" , alias = "SetFileInformationByHandle" )] |
| 1085 | #[stable (feature = "set_permissions_atomic" , since = "1.16.0" )] |
| 1086 | pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> { |
| 1087 | self.inner.set_permissions(perm.0) |
| 1088 | } |
| 1089 | |
| 1090 | /// Changes the timestamps of the underlying file. |
| 1091 | /// |
| 1092 | /// # Platform-specific behavior |
| 1093 | /// |
| 1094 | /// This function currently corresponds to the `futimens` function on Unix (falling back to |
| 1095 | /// `futimes` on macOS before 10.13) and the `SetFileTime` function on Windows. Note that this |
| 1096 | /// [may change in the future][changes]. |
| 1097 | /// |
| 1098 | /// [changes]: io#platform-specific-behavior |
| 1099 | /// |
| 1100 | /// # Errors |
| 1101 | /// |
| 1102 | /// This function will return an error if the user lacks permission to change timestamps on the |
| 1103 | /// underlying file. It may also return an error in other os-specific unspecified cases. |
| 1104 | /// |
| 1105 | /// This function may return an error if the operating system lacks support to change one or |
| 1106 | /// more of the timestamps set in the `FileTimes` structure. |
| 1107 | /// |
| 1108 | /// # Examples |
| 1109 | /// |
| 1110 | /// ```no_run |
| 1111 | /// fn main() -> std::io::Result<()> { |
| 1112 | /// use std::fs::{self, File, FileTimes}; |
| 1113 | /// |
| 1114 | /// let src = fs::metadata("src" )?; |
| 1115 | /// let dest = File::options().write(true).open("dest" )?; |
| 1116 | /// let times = FileTimes::new() |
| 1117 | /// .set_accessed(src.accessed()?) |
| 1118 | /// .set_modified(src.modified()?); |
| 1119 | /// dest.set_times(times)?; |
| 1120 | /// Ok(()) |
| 1121 | /// } |
| 1122 | /// ``` |
| 1123 | #[stable (feature = "file_set_times" , since = "1.75.0" )] |
| 1124 | #[doc (alias = "futimens" )] |
| 1125 | #[doc (alias = "futimes" )] |
| 1126 | #[doc (alias = "SetFileTime" )] |
| 1127 | pub fn set_times(&self, times: FileTimes) -> io::Result<()> { |
| 1128 | self.inner.set_times(times.0) |
| 1129 | } |
| 1130 | |
| 1131 | /// Changes the modification time of the underlying file. |
| 1132 | /// |
| 1133 | /// This is an alias for `set_times(FileTimes::new().set_modified(time))`. |
| 1134 | #[stable (feature = "file_set_times" , since = "1.75.0" )] |
| 1135 | #[inline ] |
| 1136 | pub fn set_modified(&self, time: SystemTime) -> io::Result<()> { |
| 1137 | self.set_times(FileTimes::new().set_modified(time)) |
| 1138 | } |
| 1139 | } |
| 1140 | |
| 1141 | // In addition to the `impl`s here, `File` also has `impl`s for |
| 1142 | // `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and |
| 1143 | // `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and |
| 1144 | // `AsHandle`/`From<OwnedHandle>`/`Into<OwnedHandle>` and |
| 1145 | // `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows. |
| 1146 | |
| 1147 | impl AsInner<fs_imp::File> for File { |
| 1148 | #[inline ] |
| 1149 | fn as_inner(&self) -> &fs_imp::File { |
| 1150 | &self.inner |
| 1151 | } |
| 1152 | } |
| 1153 | impl FromInner<fs_imp::File> for File { |
| 1154 | fn from_inner(f: fs_imp::File) -> File { |
| 1155 | File { inner: f } |
| 1156 | } |
| 1157 | } |
| 1158 | impl IntoInner<fs_imp::File> for File { |
| 1159 | fn into_inner(self) -> fs_imp::File { |
| 1160 | self.inner |
| 1161 | } |
| 1162 | } |
| 1163 | |
| 1164 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1165 | impl fmt::Debug for File { |
| 1166 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 1167 | self.inner.fmt(f) |
| 1168 | } |
| 1169 | } |
| 1170 | |
| 1171 | /// Indicates how much extra capacity is needed to read the rest of the file. |
| 1172 | fn buffer_capacity_required(mut file: &File) -> Option<usize> { |
| 1173 | let size: u64 = file.metadata().map(|m: Metadata| m.len()).ok()?; |
| 1174 | let pos: u64 = file.stream_position().ok()?; |
| 1175 | // Don't worry about `usize` overflow because reading will fail regardless |
| 1176 | // in that case. |
| 1177 | Some(size.saturating_sub(pos) as usize) |
| 1178 | } |
| 1179 | |
| 1180 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1181 | impl Read for &File { |
| 1182 | /// Reads some bytes from the file. |
| 1183 | /// |
| 1184 | /// See [`Read::read`] docs for more info. |
| 1185 | /// |
| 1186 | /// # Platform-specific behavior |
| 1187 | /// |
| 1188 | /// This function currently corresponds to the `read` function on Unix and |
| 1189 | /// the `NtReadFile` function on Windows. Note that this [may change in |
| 1190 | /// the future][changes]. |
| 1191 | /// |
| 1192 | /// [changes]: io#platform-specific-behavior |
| 1193 | #[inline ] |
| 1194 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
| 1195 | self.inner.read(buf) |
| 1196 | } |
| 1197 | |
| 1198 | /// Like `read`, except that it reads into a slice of buffers. |
| 1199 | /// |
| 1200 | /// See [`Read::read_vectored`] docs for more info. |
| 1201 | /// |
| 1202 | /// # Platform-specific behavior |
| 1203 | /// |
| 1204 | /// This function currently corresponds to the `readv` function on Unix and |
| 1205 | /// falls back to the `read` implementation on Windows. Note that this |
| 1206 | /// [may change in the future][changes]. |
| 1207 | /// |
| 1208 | /// [changes]: io#platform-specific-behavior |
| 1209 | #[inline ] |
| 1210 | fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
| 1211 | self.inner.read_vectored(bufs) |
| 1212 | } |
| 1213 | |
| 1214 | #[inline ] |
| 1215 | fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { |
| 1216 | self.inner.read_buf(cursor) |
| 1217 | } |
| 1218 | |
| 1219 | /// Determines if `File` has an efficient `read_vectored` implementation. |
| 1220 | /// |
| 1221 | /// See [`Read::is_read_vectored`] docs for more info. |
| 1222 | /// |
| 1223 | /// # Platform-specific behavior |
| 1224 | /// |
| 1225 | /// This function currently returns `true` on Unix an `false` on Windows. |
| 1226 | /// Note that this [may change in the future][changes]. |
| 1227 | /// |
| 1228 | /// [changes]: io#platform-specific-behavior |
| 1229 | #[inline ] |
| 1230 | fn is_read_vectored(&self) -> bool { |
| 1231 | self.inner.is_read_vectored() |
| 1232 | } |
| 1233 | |
| 1234 | // Reserves space in the buffer based on the file size when available. |
| 1235 | fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { |
| 1236 | let size = buffer_capacity_required(self); |
| 1237 | buf.try_reserve(size.unwrap_or(0))?; |
| 1238 | io::default_read_to_end(self, buf, size) |
| 1239 | } |
| 1240 | |
| 1241 | // Reserves space in the buffer based on the file size when available. |
| 1242 | fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { |
| 1243 | let size = buffer_capacity_required(self); |
| 1244 | buf.try_reserve(size.unwrap_or(0))?; |
| 1245 | io::default_read_to_string(self, buf, size) |
| 1246 | } |
| 1247 | } |
| 1248 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1249 | impl Write for &File { |
| 1250 | /// Writes some bytes to the file. |
| 1251 | /// |
| 1252 | /// See [`Write::write`] docs for more info. |
| 1253 | /// |
| 1254 | /// # Platform-specific behavior |
| 1255 | /// |
| 1256 | /// This function currently corresponds to the `write` function on Unix and |
| 1257 | /// the `NtWriteFile` function on Windows. Note that this [may change in |
| 1258 | /// the future][changes]. |
| 1259 | /// |
| 1260 | /// [changes]: io#platform-specific-behavior |
| 1261 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
| 1262 | self.inner.write(buf) |
| 1263 | } |
| 1264 | |
| 1265 | /// Like `write`, except that it writes into a slice of buffers. |
| 1266 | /// |
| 1267 | /// See [`Write::write_vectored`] docs for more info. |
| 1268 | /// |
| 1269 | /// # Platform-specific behavior |
| 1270 | /// |
| 1271 | /// This function currently corresponds to the `writev` function on Unix |
| 1272 | /// and falls back to the `write` implementation on Windows. Note that this |
| 1273 | /// [may change in the future][changes]. |
| 1274 | /// |
| 1275 | /// [changes]: io#platform-specific-behavior |
| 1276 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
| 1277 | self.inner.write_vectored(bufs) |
| 1278 | } |
| 1279 | |
| 1280 | /// Determines if `File` has an efficient `write_vectored` implementation. |
| 1281 | /// |
| 1282 | /// See [`Write::is_write_vectored`] docs for more info. |
| 1283 | /// |
| 1284 | /// # Platform-specific behavior |
| 1285 | /// |
| 1286 | /// This function currently returns `true` on Unix an `false` on Windows. |
| 1287 | /// Note that this [may change in the future][changes]. |
| 1288 | /// |
| 1289 | /// [changes]: io#platform-specific-behavior |
| 1290 | #[inline ] |
| 1291 | fn is_write_vectored(&self) -> bool { |
| 1292 | self.inner.is_write_vectored() |
| 1293 | } |
| 1294 | |
| 1295 | /// Flushes the file, ensuring that all intermediately buffered contents |
| 1296 | /// reach their destination. |
| 1297 | /// |
| 1298 | /// See [`Write::flush`] docs for more info. |
| 1299 | /// |
| 1300 | /// # Platform-specific behavior |
| 1301 | /// |
| 1302 | /// Since a `File` structure doesn't contain any buffers, this function is |
| 1303 | /// currently a no-op on Unix and Windows. Note that this [may change in |
| 1304 | /// the future][changes]. |
| 1305 | /// |
| 1306 | /// [changes]: io#platform-specific-behavior |
| 1307 | #[inline ] |
| 1308 | fn flush(&mut self) -> io::Result<()> { |
| 1309 | self.inner.flush() |
| 1310 | } |
| 1311 | } |
| 1312 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1313 | impl Seek for &File { |
| 1314 | /// Seek to an offset, in bytes in a file. |
| 1315 | /// |
| 1316 | /// See [`Seek::seek`] docs for more info. |
| 1317 | /// |
| 1318 | /// # Platform-specific behavior |
| 1319 | /// |
| 1320 | /// This function currently corresponds to the `lseek64` function on Unix |
| 1321 | /// and the `SetFilePointerEx` function on Windows. Note that this [may |
| 1322 | /// change in the future][changes]. |
| 1323 | /// |
| 1324 | /// [changes]: io#platform-specific-behavior |
| 1325 | fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { |
| 1326 | self.inner.seek(pos) |
| 1327 | } |
| 1328 | |
| 1329 | /// Returns the length of this file (in bytes). |
| 1330 | /// |
| 1331 | /// See [`Seek::stream_len`] docs for more info. |
| 1332 | /// |
| 1333 | /// # Platform-specific behavior |
| 1334 | /// |
| 1335 | /// This function currently corresponds to the `statx` function on Linux |
| 1336 | /// (with fallbacks) and the `GetFileSizeEx` function on Windows. Note that |
| 1337 | /// this [may change in the future][changes]. |
| 1338 | /// |
| 1339 | /// [changes]: io#platform-specific-behavior |
| 1340 | fn stream_len(&mut self) -> io::Result<u64> { |
| 1341 | if let Some(result) = self.inner.size() { |
| 1342 | return result; |
| 1343 | } |
| 1344 | io::stream_len_default(self) |
| 1345 | } |
| 1346 | |
| 1347 | fn stream_position(&mut self) -> io::Result<u64> { |
| 1348 | self.inner.tell() |
| 1349 | } |
| 1350 | } |
| 1351 | |
| 1352 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1353 | impl Read for File { |
| 1354 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
| 1355 | (&*self).read(buf) |
| 1356 | } |
| 1357 | fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
| 1358 | (&*self).read_vectored(bufs) |
| 1359 | } |
| 1360 | fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { |
| 1361 | (&*self).read_buf(cursor) |
| 1362 | } |
| 1363 | #[inline ] |
| 1364 | fn is_read_vectored(&self) -> bool { |
| 1365 | (&&*self).is_read_vectored() |
| 1366 | } |
| 1367 | fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { |
| 1368 | (&*self).read_to_end(buf) |
| 1369 | } |
| 1370 | fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { |
| 1371 | (&*self).read_to_string(buf) |
| 1372 | } |
| 1373 | } |
| 1374 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1375 | impl Write for File { |
| 1376 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
| 1377 | (&*self).write(buf) |
| 1378 | } |
| 1379 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
| 1380 | (&*self).write_vectored(bufs) |
| 1381 | } |
| 1382 | #[inline ] |
| 1383 | fn is_write_vectored(&self) -> bool { |
| 1384 | (&&*self).is_write_vectored() |
| 1385 | } |
| 1386 | #[inline ] |
| 1387 | fn flush(&mut self) -> io::Result<()> { |
| 1388 | (&*self).flush() |
| 1389 | } |
| 1390 | } |
| 1391 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1392 | impl Seek for File { |
| 1393 | fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { |
| 1394 | (&*self).seek(pos) |
| 1395 | } |
| 1396 | fn stream_len(&mut self) -> io::Result<u64> { |
| 1397 | (&*self).stream_len() |
| 1398 | } |
| 1399 | fn stream_position(&mut self) -> io::Result<u64> { |
| 1400 | (&*self).stream_position() |
| 1401 | } |
| 1402 | } |
| 1403 | |
| 1404 | #[stable (feature = "io_traits_arc" , since = "1.73.0" )] |
| 1405 | impl Read for Arc<File> { |
| 1406 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
| 1407 | (&**self).read(buf) |
| 1408 | } |
| 1409 | fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
| 1410 | (&**self).read_vectored(bufs) |
| 1411 | } |
| 1412 | fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { |
| 1413 | (&**self).read_buf(cursor) |
| 1414 | } |
| 1415 | #[inline ] |
| 1416 | fn is_read_vectored(&self) -> bool { |
| 1417 | (&**self).is_read_vectored() |
| 1418 | } |
| 1419 | fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { |
| 1420 | (&**self).read_to_end(buf) |
| 1421 | } |
| 1422 | fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { |
| 1423 | (&**self).read_to_string(buf) |
| 1424 | } |
| 1425 | } |
| 1426 | #[stable (feature = "io_traits_arc" , since = "1.73.0" )] |
| 1427 | impl Write for Arc<File> { |
| 1428 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
| 1429 | (&**self).write(buf) |
| 1430 | } |
| 1431 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
| 1432 | (&**self).write_vectored(bufs) |
| 1433 | } |
| 1434 | #[inline ] |
| 1435 | fn is_write_vectored(&self) -> bool { |
| 1436 | (&**self).is_write_vectored() |
| 1437 | } |
| 1438 | #[inline ] |
| 1439 | fn flush(&mut self) -> io::Result<()> { |
| 1440 | (&**self).flush() |
| 1441 | } |
| 1442 | } |
| 1443 | #[stable (feature = "io_traits_arc" , since = "1.73.0" )] |
| 1444 | impl Seek for Arc<File> { |
| 1445 | fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { |
| 1446 | (&**self).seek(pos) |
| 1447 | } |
| 1448 | fn stream_len(&mut self) -> io::Result<u64> { |
| 1449 | (&**self).stream_len() |
| 1450 | } |
| 1451 | fn stream_position(&mut self) -> io::Result<u64> { |
| 1452 | (&**self).stream_position() |
| 1453 | } |
| 1454 | } |
| 1455 | |
| 1456 | impl OpenOptions { |
| 1457 | /// Creates a blank new set of options ready for configuration. |
| 1458 | /// |
| 1459 | /// All options are initially set to `false`. |
| 1460 | /// |
| 1461 | /// # Examples |
| 1462 | /// |
| 1463 | /// ```no_run |
| 1464 | /// use std::fs::OpenOptions; |
| 1465 | /// |
| 1466 | /// let mut options = OpenOptions::new(); |
| 1467 | /// let file = options.read(true).open("foo.txt" ); |
| 1468 | /// ``` |
| 1469 | #[cfg_attr (not(test), rustc_diagnostic_item = "open_options_new" )] |
| 1470 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1471 | #[must_use ] |
| 1472 | pub fn new() -> Self { |
| 1473 | OpenOptions(fs_imp::OpenOptions::new()) |
| 1474 | } |
| 1475 | |
| 1476 | /// Sets the option for read access. |
| 1477 | /// |
| 1478 | /// This option, when true, will indicate that the file should be |
| 1479 | /// `read`-able if opened. |
| 1480 | /// |
| 1481 | /// # Examples |
| 1482 | /// |
| 1483 | /// ```no_run |
| 1484 | /// use std::fs::OpenOptions; |
| 1485 | /// |
| 1486 | /// let file = OpenOptions::new().read(true).open("foo.txt" ); |
| 1487 | /// ``` |
| 1488 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1489 | pub fn read(&mut self, read: bool) -> &mut Self { |
| 1490 | self.0.read(read); |
| 1491 | self |
| 1492 | } |
| 1493 | |
| 1494 | /// Sets the option for write access. |
| 1495 | /// |
| 1496 | /// This option, when true, will indicate that the file should be |
| 1497 | /// `write`-able if opened. |
| 1498 | /// |
| 1499 | /// If the file already exists, any write calls on it will overwrite its |
| 1500 | /// contents, without truncating it. |
| 1501 | /// |
| 1502 | /// # Examples |
| 1503 | /// |
| 1504 | /// ```no_run |
| 1505 | /// use std::fs::OpenOptions; |
| 1506 | /// |
| 1507 | /// let file = OpenOptions::new().write(true).open("foo.txt" ); |
| 1508 | /// ``` |
| 1509 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1510 | pub fn write(&mut self, write: bool) -> &mut Self { |
| 1511 | self.0.write(write); |
| 1512 | self |
| 1513 | } |
| 1514 | |
| 1515 | /// Sets the option for the append mode. |
| 1516 | /// |
| 1517 | /// This option, when true, means that writes will append to a file instead |
| 1518 | /// of overwriting previous contents. |
| 1519 | /// Note that setting `.write(true).append(true)` has the same effect as |
| 1520 | /// setting only `.append(true)`. |
| 1521 | /// |
| 1522 | /// Append mode guarantees that writes will be positioned at the current end of file, |
| 1523 | /// even when there are other processes or threads appending to the same file. This is |
| 1524 | /// unlike <code>[seek]\([SeekFrom]::[End]\(0))</code> followed by `write()`, which |
| 1525 | /// has a race between seeking and writing during which another writer can write, with |
| 1526 | /// our `write()` overwriting their data. |
| 1527 | /// |
| 1528 | /// Keep in mind that this does not necessarily guarantee that data appended by |
| 1529 | /// different processes or threads does not interleave. The amount of data accepted a |
| 1530 | /// single `write()` call depends on the operating system and file system. A |
| 1531 | /// successful `write()` is allowed to write only part of the given data, so even if |
| 1532 | /// you're careful to provide the whole message in a single call to `write()`, there |
| 1533 | /// is no guarantee that it will be written out in full. If you rely on the filesystem |
| 1534 | /// accepting the message in a single write, make sure that all data that belongs |
| 1535 | /// together is written in one operation. This can be done by concatenating strings |
| 1536 | /// before passing them to [`write()`]. |
| 1537 | /// |
| 1538 | /// If a file is opened with both read and append access, beware that after |
| 1539 | /// opening, and after every write, the position for reading may be set at the |
| 1540 | /// end of the file. So, before writing, save the current position (using |
| 1541 | /// <code>[Seek]::[stream_position]</code>), and restore it before the next read. |
| 1542 | /// |
| 1543 | /// ## Note |
| 1544 | /// |
| 1545 | /// This function doesn't create the file if it doesn't exist. Use the |
| 1546 | /// [`OpenOptions::create`] method to do so. |
| 1547 | /// |
| 1548 | /// [`write()`]: Write::write "io::Write::write" |
| 1549 | /// [`flush()`]: Write::flush "io::Write::flush" |
| 1550 | /// [stream_position]: Seek::stream_position "io::Seek::stream_position" |
| 1551 | /// [seek]: Seek::seek "io::Seek::seek" |
| 1552 | /// [Current]: SeekFrom::Current "io::SeekFrom::Current" |
| 1553 | /// [End]: SeekFrom::End "io::SeekFrom::End" |
| 1554 | /// |
| 1555 | /// # Examples |
| 1556 | /// |
| 1557 | /// ```no_run |
| 1558 | /// use std::fs::OpenOptions; |
| 1559 | /// |
| 1560 | /// let file = OpenOptions::new().append(true).open("foo.txt" ); |
| 1561 | /// ``` |
| 1562 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1563 | pub fn append(&mut self, append: bool) -> &mut Self { |
| 1564 | self.0.append(append); |
| 1565 | self |
| 1566 | } |
| 1567 | |
| 1568 | /// Sets the option for truncating a previous file. |
| 1569 | /// |
| 1570 | /// If a file is successfully opened with this option set to true, it will truncate |
| 1571 | /// the file to 0 length if it already exists. |
| 1572 | /// |
| 1573 | /// The file must be opened with write access for truncate to work. |
| 1574 | /// |
| 1575 | /// # Examples |
| 1576 | /// |
| 1577 | /// ```no_run |
| 1578 | /// use std::fs::OpenOptions; |
| 1579 | /// |
| 1580 | /// let file = OpenOptions::new().write(true).truncate(true).open("foo.txt" ); |
| 1581 | /// ``` |
| 1582 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1583 | pub fn truncate(&mut self, truncate: bool) -> &mut Self { |
| 1584 | self.0.truncate(truncate); |
| 1585 | self |
| 1586 | } |
| 1587 | |
| 1588 | /// Sets the option to create a new file, or open it if it already exists. |
| 1589 | /// |
| 1590 | /// In order for the file to be created, [`OpenOptions::write`] or |
| 1591 | /// [`OpenOptions::append`] access must be used. |
| 1592 | /// |
| 1593 | /// See also [`std::fs::write()`][self::write] for a simple function to |
| 1594 | /// create a file with some given data. |
| 1595 | /// |
| 1596 | /// # Examples |
| 1597 | /// |
| 1598 | /// ```no_run |
| 1599 | /// use std::fs::OpenOptions; |
| 1600 | /// |
| 1601 | /// let file = OpenOptions::new().write(true).create(true).open("foo.txt" ); |
| 1602 | /// ``` |
| 1603 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1604 | pub fn create(&mut self, create: bool) -> &mut Self { |
| 1605 | self.0.create(create); |
| 1606 | self |
| 1607 | } |
| 1608 | |
| 1609 | /// Sets the option to create a new file, failing if it already exists. |
| 1610 | /// |
| 1611 | /// No file is allowed to exist at the target location, also no (dangling) symlink. In this |
| 1612 | /// way, if the call succeeds, the file returned is guaranteed to be new. |
| 1613 | /// If a file exists at the target location, creating a new file will fail with [`AlreadyExists`] |
| 1614 | /// or another error based on the situation. See [`OpenOptions::open`] for a |
| 1615 | /// non-exhaustive list of likely errors. |
| 1616 | /// |
| 1617 | /// This option is useful because it is atomic. Otherwise between checking |
| 1618 | /// whether a file exists and creating a new one, the file may have been |
| 1619 | /// created by another process (a TOCTOU race condition / attack). |
| 1620 | /// |
| 1621 | /// If `.create_new(true)` is set, [`.create()`] and [`.truncate()`] are |
| 1622 | /// ignored. |
| 1623 | /// |
| 1624 | /// The file must be opened with write or append access in order to create |
| 1625 | /// a new file. |
| 1626 | /// |
| 1627 | /// [`.create()`]: OpenOptions::create |
| 1628 | /// [`.truncate()`]: OpenOptions::truncate |
| 1629 | /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists |
| 1630 | /// |
| 1631 | /// # Examples |
| 1632 | /// |
| 1633 | /// ```no_run |
| 1634 | /// use std::fs::OpenOptions; |
| 1635 | /// |
| 1636 | /// let file = OpenOptions::new().write(true) |
| 1637 | /// .create_new(true) |
| 1638 | /// .open("foo.txt" ); |
| 1639 | /// ``` |
| 1640 | #[stable (feature = "expand_open_options2" , since = "1.9.0" )] |
| 1641 | pub fn create_new(&mut self, create_new: bool) -> &mut Self { |
| 1642 | self.0.create_new(create_new); |
| 1643 | self |
| 1644 | } |
| 1645 | |
| 1646 | /// Opens a file at `path` with the options specified by `self`. |
| 1647 | /// |
| 1648 | /// # Errors |
| 1649 | /// |
| 1650 | /// This function will return an error under a number of different |
| 1651 | /// circumstances. Some of these error conditions are listed here, together |
| 1652 | /// with their [`io::ErrorKind`]. The mapping to [`io::ErrorKind`]s is not |
| 1653 | /// part of the compatibility contract of the function. |
| 1654 | /// |
| 1655 | /// * [`NotFound`]: The specified file does not exist and neither `create` |
| 1656 | /// or `create_new` is set. |
| 1657 | /// * [`NotFound`]: One of the directory components of the file path does |
| 1658 | /// not exist. |
| 1659 | /// * [`PermissionDenied`]: The user lacks permission to get the specified |
| 1660 | /// access rights for the file. |
| 1661 | /// * [`PermissionDenied`]: The user lacks permission to open one of the |
| 1662 | /// directory components of the specified path. |
| 1663 | /// * [`AlreadyExists`]: `create_new` was specified and the file already |
| 1664 | /// exists. |
| 1665 | /// * [`InvalidInput`]: Invalid combinations of open options (truncate |
| 1666 | /// without write access, no access mode set, etc.). |
| 1667 | /// |
| 1668 | /// The following errors don't match any existing [`io::ErrorKind`] at the moment: |
| 1669 | /// * One of the directory components of the specified file path |
| 1670 | /// was not, in fact, a directory. |
| 1671 | /// * Filesystem-level errors: full disk, write permission |
| 1672 | /// requested on a read-only file system, exceeded disk quota, too many |
| 1673 | /// open files, too long filename, too many symbolic links in the |
| 1674 | /// specified path (Unix-like systems only), etc. |
| 1675 | /// |
| 1676 | /// # Examples |
| 1677 | /// |
| 1678 | /// ```no_run |
| 1679 | /// use std::fs::OpenOptions; |
| 1680 | /// |
| 1681 | /// let file = OpenOptions::new().read(true).open("foo.txt" ); |
| 1682 | /// ``` |
| 1683 | /// |
| 1684 | /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists |
| 1685 | /// [`InvalidInput`]: io::ErrorKind::InvalidInput |
| 1686 | /// [`NotFound`]: io::ErrorKind::NotFound |
| 1687 | /// [`PermissionDenied`]: io::ErrorKind::PermissionDenied |
| 1688 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1689 | pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> { |
| 1690 | self._open(path.as_ref()) |
| 1691 | } |
| 1692 | |
| 1693 | fn _open(&self, path: &Path) -> io::Result<File> { |
| 1694 | fs_imp::File::open(path, &self.0).map(|inner| File { inner }) |
| 1695 | } |
| 1696 | } |
| 1697 | |
| 1698 | impl AsInner<fs_imp::OpenOptions> for OpenOptions { |
| 1699 | #[inline ] |
| 1700 | fn as_inner(&self) -> &fs_imp::OpenOptions { |
| 1701 | &self.0 |
| 1702 | } |
| 1703 | } |
| 1704 | |
| 1705 | impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions { |
| 1706 | #[inline ] |
| 1707 | fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { |
| 1708 | &mut self.0 |
| 1709 | } |
| 1710 | } |
| 1711 | |
| 1712 | impl Metadata { |
| 1713 | /// Returns the file type for this metadata. |
| 1714 | /// |
| 1715 | /// # Examples |
| 1716 | /// |
| 1717 | /// ```no_run |
| 1718 | /// fn main() -> std::io::Result<()> { |
| 1719 | /// use std::fs; |
| 1720 | /// |
| 1721 | /// let metadata = fs::metadata("foo.txt" )?; |
| 1722 | /// |
| 1723 | /// println!("{:?}" , metadata.file_type()); |
| 1724 | /// Ok(()) |
| 1725 | /// } |
| 1726 | /// ``` |
| 1727 | #[must_use ] |
| 1728 | #[stable (feature = "file_type" , since = "1.1.0" )] |
| 1729 | pub fn file_type(&self) -> FileType { |
| 1730 | FileType(self.0.file_type()) |
| 1731 | } |
| 1732 | |
| 1733 | /// Returns `true` if this metadata is for a directory. The |
| 1734 | /// result is mutually exclusive to the result of |
| 1735 | /// [`Metadata::is_file`], and will be false for symlink metadata |
| 1736 | /// obtained from [`symlink_metadata`]. |
| 1737 | /// |
| 1738 | /// # Examples |
| 1739 | /// |
| 1740 | /// ```no_run |
| 1741 | /// fn main() -> std::io::Result<()> { |
| 1742 | /// use std::fs; |
| 1743 | /// |
| 1744 | /// let metadata = fs::metadata("foo.txt" )?; |
| 1745 | /// |
| 1746 | /// assert!(!metadata.is_dir()); |
| 1747 | /// Ok(()) |
| 1748 | /// } |
| 1749 | /// ``` |
| 1750 | #[must_use ] |
| 1751 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1752 | pub fn is_dir(&self) -> bool { |
| 1753 | self.file_type().is_dir() |
| 1754 | } |
| 1755 | |
| 1756 | /// Returns `true` if this metadata is for a regular file. The |
| 1757 | /// result is mutually exclusive to the result of |
| 1758 | /// [`Metadata::is_dir`], and will be false for symlink metadata |
| 1759 | /// obtained from [`symlink_metadata`]. |
| 1760 | /// |
| 1761 | /// When the goal is simply to read from (or write to) the source, the most |
| 1762 | /// reliable way to test the source can be read (or written to) is to open |
| 1763 | /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on |
| 1764 | /// a Unix-like system for example. See [`File::open`] or |
| 1765 | /// [`OpenOptions::open`] for more information. |
| 1766 | /// |
| 1767 | /// # Examples |
| 1768 | /// |
| 1769 | /// ```no_run |
| 1770 | /// use std::fs; |
| 1771 | /// |
| 1772 | /// fn main() -> std::io::Result<()> { |
| 1773 | /// let metadata = fs::metadata("foo.txt" )?; |
| 1774 | /// |
| 1775 | /// assert!(metadata.is_file()); |
| 1776 | /// Ok(()) |
| 1777 | /// } |
| 1778 | /// ``` |
| 1779 | #[must_use ] |
| 1780 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1781 | pub fn is_file(&self) -> bool { |
| 1782 | self.file_type().is_file() |
| 1783 | } |
| 1784 | |
| 1785 | /// Returns `true` if this metadata is for a symbolic link. |
| 1786 | /// |
| 1787 | /// # Examples |
| 1788 | /// |
| 1789 | #[cfg_attr (unix, doc = "```no_run" )] |
| 1790 | #[cfg_attr (not(unix), doc = "```ignore" )] |
| 1791 | /// use std::fs; |
| 1792 | /// use std::path::Path; |
| 1793 | /// use std::os::unix::fs::symlink; |
| 1794 | /// |
| 1795 | /// fn main() -> std::io::Result<()> { |
| 1796 | /// let link_path = Path::new("link" ); |
| 1797 | /// symlink("/origin_does_not_exist/" , link_path)?; |
| 1798 | /// |
| 1799 | /// let metadata = fs::symlink_metadata(link_path)?; |
| 1800 | /// |
| 1801 | /// assert!(metadata.is_symlink()); |
| 1802 | /// Ok(()) |
| 1803 | /// } |
| 1804 | /// ``` |
| 1805 | #[must_use ] |
| 1806 | #[stable (feature = "is_symlink" , since = "1.58.0" )] |
| 1807 | pub fn is_symlink(&self) -> bool { |
| 1808 | self.file_type().is_symlink() |
| 1809 | } |
| 1810 | |
| 1811 | /// Returns the size of the file, in bytes, this metadata is for. |
| 1812 | /// |
| 1813 | /// # Examples |
| 1814 | /// |
| 1815 | /// ```no_run |
| 1816 | /// use std::fs; |
| 1817 | /// |
| 1818 | /// fn main() -> std::io::Result<()> { |
| 1819 | /// let metadata = fs::metadata("foo.txt" )?; |
| 1820 | /// |
| 1821 | /// assert_eq!(0, metadata.len()); |
| 1822 | /// Ok(()) |
| 1823 | /// } |
| 1824 | /// ``` |
| 1825 | #[must_use ] |
| 1826 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1827 | pub fn len(&self) -> u64 { |
| 1828 | self.0.size() |
| 1829 | } |
| 1830 | |
| 1831 | /// Returns the permissions of the file this metadata is for. |
| 1832 | /// |
| 1833 | /// # Examples |
| 1834 | /// |
| 1835 | /// ```no_run |
| 1836 | /// use std::fs; |
| 1837 | /// |
| 1838 | /// fn main() -> std::io::Result<()> { |
| 1839 | /// let metadata = fs::metadata("foo.txt" )?; |
| 1840 | /// |
| 1841 | /// assert!(!metadata.permissions().readonly()); |
| 1842 | /// Ok(()) |
| 1843 | /// } |
| 1844 | /// ``` |
| 1845 | #[must_use ] |
| 1846 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 1847 | pub fn permissions(&self) -> Permissions { |
| 1848 | Permissions(self.0.perm()) |
| 1849 | } |
| 1850 | |
| 1851 | /// Returns the last modification time listed in this metadata. |
| 1852 | /// |
| 1853 | /// The returned value corresponds to the `mtime` field of `stat` on Unix |
| 1854 | /// platforms and the `ftLastWriteTime` field on Windows platforms. |
| 1855 | /// |
| 1856 | /// # Errors |
| 1857 | /// |
| 1858 | /// This field might not be available on all platforms, and will return an |
| 1859 | /// `Err` on platforms where it is not available. |
| 1860 | /// |
| 1861 | /// # Examples |
| 1862 | /// |
| 1863 | /// ```no_run |
| 1864 | /// use std::fs; |
| 1865 | /// |
| 1866 | /// fn main() -> std::io::Result<()> { |
| 1867 | /// let metadata = fs::metadata("foo.txt" )?; |
| 1868 | /// |
| 1869 | /// if let Ok(time) = metadata.modified() { |
| 1870 | /// println!("{time:?}" ); |
| 1871 | /// } else { |
| 1872 | /// println!("Not supported on this platform" ); |
| 1873 | /// } |
| 1874 | /// Ok(()) |
| 1875 | /// } |
| 1876 | /// ``` |
| 1877 | #[doc (alias = "mtime" , alias = "ftLastWriteTime" )] |
| 1878 | #[stable (feature = "fs_time" , since = "1.10.0" )] |
| 1879 | pub fn modified(&self) -> io::Result<SystemTime> { |
| 1880 | self.0.modified().map(FromInner::from_inner) |
| 1881 | } |
| 1882 | |
| 1883 | /// Returns the last access time of this metadata. |
| 1884 | /// |
| 1885 | /// The returned value corresponds to the `atime` field of `stat` on Unix |
| 1886 | /// platforms and the `ftLastAccessTime` field on Windows platforms. |
| 1887 | /// |
| 1888 | /// Note that not all platforms will keep this field update in a file's |
| 1889 | /// metadata, for example Windows has an option to disable updating this |
| 1890 | /// time when files are accessed and Linux similarly has `noatime`. |
| 1891 | /// |
| 1892 | /// # Errors |
| 1893 | /// |
| 1894 | /// This field might not be available on all platforms, and will return an |
| 1895 | /// `Err` on platforms where it is not available. |
| 1896 | /// |
| 1897 | /// # Examples |
| 1898 | /// |
| 1899 | /// ```no_run |
| 1900 | /// use std::fs; |
| 1901 | /// |
| 1902 | /// fn main() -> std::io::Result<()> { |
| 1903 | /// let metadata = fs::metadata("foo.txt" )?; |
| 1904 | /// |
| 1905 | /// if let Ok(time) = metadata.accessed() { |
| 1906 | /// println!("{time:?}" ); |
| 1907 | /// } else { |
| 1908 | /// println!("Not supported on this platform" ); |
| 1909 | /// } |
| 1910 | /// Ok(()) |
| 1911 | /// } |
| 1912 | /// ``` |
| 1913 | #[doc (alias = "atime" , alias = "ftLastAccessTime" )] |
| 1914 | #[stable (feature = "fs_time" , since = "1.10.0" )] |
| 1915 | pub fn accessed(&self) -> io::Result<SystemTime> { |
| 1916 | self.0.accessed().map(FromInner::from_inner) |
| 1917 | } |
| 1918 | |
| 1919 | /// Returns the creation time listed in this metadata. |
| 1920 | /// |
| 1921 | /// The returned value corresponds to the `btime` field of `statx` on |
| 1922 | /// Linux kernel starting from to 4.11, the `birthtime` field of `stat` on other |
| 1923 | /// Unix platforms, and the `ftCreationTime` field on Windows platforms. |
| 1924 | /// |
| 1925 | /// # Errors |
| 1926 | /// |
| 1927 | /// This field might not be available on all platforms, and will return an |
| 1928 | /// `Err` on platforms or filesystems where it is not available. |
| 1929 | /// |
| 1930 | /// # Examples |
| 1931 | /// |
| 1932 | /// ```no_run |
| 1933 | /// use std::fs; |
| 1934 | /// |
| 1935 | /// fn main() -> std::io::Result<()> { |
| 1936 | /// let metadata = fs::metadata("foo.txt" )?; |
| 1937 | /// |
| 1938 | /// if let Ok(time) = metadata.created() { |
| 1939 | /// println!("{time:?}" ); |
| 1940 | /// } else { |
| 1941 | /// println!("Not supported on this platform or filesystem" ); |
| 1942 | /// } |
| 1943 | /// Ok(()) |
| 1944 | /// } |
| 1945 | /// ``` |
| 1946 | #[doc (alias = "btime" , alias = "birthtime" , alias = "ftCreationTime" )] |
| 1947 | #[stable (feature = "fs_time" , since = "1.10.0" )] |
| 1948 | pub fn created(&self) -> io::Result<SystemTime> { |
| 1949 | self.0.created().map(FromInner::from_inner) |
| 1950 | } |
| 1951 | } |
| 1952 | |
| 1953 | #[stable (feature = "std_debug" , since = "1.16.0" )] |
| 1954 | impl fmt::Debug for Metadata { |
| 1955 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 1956 | let mut debug: DebugStruct<'_, '_> = f.debug_struct(name:"Metadata" ); |
| 1957 | debug.field(name:"file_type" , &self.file_type()); |
| 1958 | debug.field(name:"permissions" , &self.permissions()); |
| 1959 | debug.field(name:"len" , &self.len()); |
| 1960 | if let Ok(modified: SystemTime) = self.modified() { |
| 1961 | debug.field(name:"modified" , &modified); |
| 1962 | } |
| 1963 | if let Ok(accessed: SystemTime) = self.accessed() { |
| 1964 | debug.field(name:"accessed" , &accessed); |
| 1965 | } |
| 1966 | if let Ok(created: SystemTime) = self.created() { |
| 1967 | debug.field(name:"created" , &created); |
| 1968 | } |
| 1969 | debug.finish_non_exhaustive() |
| 1970 | } |
| 1971 | } |
| 1972 | |
| 1973 | impl AsInner<fs_imp::FileAttr> for Metadata { |
| 1974 | #[inline ] |
| 1975 | fn as_inner(&self) -> &fs_imp::FileAttr { |
| 1976 | &self.0 |
| 1977 | } |
| 1978 | } |
| 1979 | |
| 1980 | impl FromInner<fs_imp::FileAttr> for Metadata { |
| 1981 | fn from_inner(attr: fs_imp::FileAttr) -> Metadata { |
| 1982 | Metadata(attr) |
| 1983 | } |
| 1984 | } |
| 1985 | |
| 1986 | impl FileTimes { |
| 1987 | /// Creates a new `FileTimes` with no times set. |
| 1988 | /// |
| 1989 | /// Using the resulting `FileTimes` in [`File::set_times`] will not modify any timestamps. |
| 1990 | #[stable (feature = "file_set_times" , since = "1.75.0" )] |
| 1991 | pub fn new() -> Self { |
| 1992 | Self::default() |
| 1993 | } |
| 1994 | |
| 1995 | /// Set the last access time of a file. |
| 1996 | #[stable (feature = "file_set_times" , since = "1.75.0" )] |
| 1997 | pub fn set_accessed(mut self, t: SystemTime) -> Self { |
| 1998 | self.0.set_accessed(t.into_inner()); |
| 1999 | self |
| 2000 | } |
| 2001 | |
| 2002 | /// Set the last modified time of a file. |
| 2003 | #[stable (feature = "file_set_times" , since = "1.75.0" )] |
| 2004 | pub fn set_modified(mut self, t: SystemTime) -> Self { |
| 2005 | self.0.set_modified(t.into_inner()); |
| 2006 | self |
| 2007 | } |
| 2008 | } |
| 2009 | |
| 2010 | impl AsInnerMut<fs_imp::FileTimes> for FileTimes { |
| 2011 | fn as_inner_mut(&mut self) -> &mut fs_imp::FileTimes { |
| 2012 | &mut self.0 |
| 2013 | } |
| 2014 | } |
| 2015 | |
| 2016 | // For implementing OS extension traits in `std::os` |
| 2017 | #[stable (feature = "file_set_times" , since = "1.75.0" )] |
| 2018 | impl Sealed for FileTimes {} |
| 2019 | |
| 2020 | impl Permissions { |
| 2021 | /// Returns `true` if these permissions describe a readonly (unwritable) file. |
| 2022 | /// |
| 2023 | /// # Note |
| 2024 | /// |
| 2025 | /// This function does not take Access Control Lists (ACLs), Unix group |
| 2026 | /// membership and other nuances into account. |
| 2027 | /// Therefore the return value of this function cannot be relied upon |
| 2028 | /// to predict whether attempts to read or write the file will actually succeed. |
| 2029 | /// |
| 2030 | /// # Windows |
| 2031 | /// |
| 2032 | /// On Windows this returns [`FILE_ATTRIBUTE_READONLY`](https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants). |
| 2033 | /// If `FILE_ATTRIBUTE_READONLY` is set then writes to the file will fail |
| 2034 | /// but the user may still have permission to change this flag. If |
| 2035 | /// `FILE_ATTRIBUTE_READONLY` is *not* set then writes may still fail due |
| 2036 | /// to lack of write permission. |
| 2037 | /// The behavior of this attribute for directories depends on the Windows |
| 2038 | /// version. |
| 2039 | /// |
| 2040 | /// # Unix (including macOS) |
| 2041 | /// |
| 2042 | /// On Unix-based platforms this checks if *any* of the owner, group or others |
| 2043 | /// write permission bits are set. It does not consider anything else, including: |
| 2044 | /// |
| 2045 | /// * Whether the current user is in the file's assigned group. |
| 2046 | /// * Permissions granted by ACL. |
| 2047 | /// * That `root` user can write to files that do not have any write bits set. |
| 2048 | /// * Writable files on a filesystem that is mounted read-only. |
| 2049 | /// |
| 2050 | /// The [`PermissionsExt`] trait gives direct access to the permission bits but |
| 2051 | /// also does not read ACLs. |
| 2052 | /// |
| 2053 | /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt |
| 2054 | /// |
| 2055 | /// # Examples |
| 2056 | /// |
| 2057 | /// ```no_run |
| 2058 | /// use std::fs::File; |
| 2059 | /// |
| 2060 | /// fn main() -> std::io::Result<()> { |
| 2061 | /// let mut f = File::create("foo.txt" )?; |
| 2062 | /// let metadata = f.metadata()?; |
| 2063 | /// |
| 2064 | /// assert_eq!(false, metadata.permissions().readonly()); |
| 2065 | /// Ok(()) |
| 2066 | /// } |
| 2067 | /// ``` |
| 2068 | #[must_use = "call `set_readonly` to modify the readonly flag" ] |
| 2069 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2070 | pub fn readonly(&self) -> bool { |
| 2071 | self.0.readonly() |
| 2072 | } |
| 2073 | |
| 2074 | /// Modifies the readonly flag for this set of permissions. If the |
| 2075 | /// `readonly` argument is `true`, using the resulting `Permission` will |
| 2076 | /// update file permissions to forbid writing. Conversely, if it's `false`, |
| 2077 | /// using the resulting `Permission` will update file permissions to allow |
| 2078 | /// writing. |
| 2079 | /// |
| 2080 | /// This operation does **not** modify the files attributes. This only |
| 2081 | /// changes the in-memory value of these attributes for this `Permissions` |
| 2082 | /// instance. To modify the files attributes use the [`set_permissions`] |
| 2083 | /// function which commits these attribute changes to the file. |
| 2084 | /// |
| 2085 | /// # Note |
| 2086 | /// |
| 2087 | /// `set_readonly(false)` makes the file *world-writable* on Unix. |
| 2088 | /// You can use the [`PermissionsExt`] trait on Unix to avoid this issue. |
| 2089 | /// |
| 2090 | /// It also does not take Access Control Lists (ACLs) or Unix group |
| 2091 | /// membership into account. |
| 2092 | /// |
| 2093 | /// # Windows |
| 2094 | /// |
| 2095 | /// On Windows this sets or clears [`FILE_ATTRIBUTE_READONLY`](https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants). |
| 2096 | /// If `FILE_ATTRIBUTE_READONLY` is set then writes to the file will fail |
| 2097 | /// but the user may still have permission to change this flag. If |
| 2098 | /// `FILE_ATTRIBUTE_READONLY` is *not* set then the write may still fail if |
| 2099 | /// the user does not have permission to write to the file. |
| 2100 | /// |
| 2101 | /// In Windows 7 and earlier this attribute prevents deleting empty |
| 2102 | /// directories. It does not prevent modifying the directory contents. |
| 2103 | /// On later versions of Windows this attribute is ignored for directories. |
| 2104 | /// |
| 2105 | /// # Unix (including macOS) |
| 2106 | /// |
| 2107 | /// On Unix-based platforms this sets or clears the write access bit for |
| 2108 | /// the owner, group *and* others, equivalent to `chmod a+w <file>` |
| 2109 | /// or `chmod a-w <file>` respectively. The latter will grant write access |
| 2110 | /// to all users! You can use the [`PermissionsExt`] trait on Unix |
| 2111 | /// to avoid this issue. |
| 2112 | /// |
| 2113 | /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt |
| 2114 | /// |
| 2115 | /// # Examples |
| 2116 | /// |
| 2117 | /// ```no_run |
| 2118 | /// use std::fs::File; |
| 2119 | /// |
| 2120 | /// fn main() -> std::io::Result<()> { |
| 2121 | /// let f = File::create("foo.txt" )?; |
| 2122 | /// let metadata = f.metadata()?; |
| 2123 | /// let mut permissions = metadata.permissions(); |
| 2124 | /// |
| 2125 | /// permissions.set_readonly(true); |
| 2126 | /// |
| 2127 | /// // filesystem doesn't change, only the in memory state of the |
| 2128 | /// // readonly permission |
| 2129 | /// assert_eq!(false, metadata.permissions().readonly()); |
| 2130 | /// |
| 2131 | /// // just this particular `permissions`. |
| 2132 | /// assert_eq!(true, permissions.readonly()); |
| 2133 | /// Ok(()) |
| 2134 | /// } |
| 2135 | /// ``` |
| 2136 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2137 | pub fn set_readonly(&mut self, readonly: bool) { |
| 2138 | self.0.set_readonly(readonly) |
| 2139 | } |
| 2140 | } |
| 2141 | |
| 2142 | impl FileType { |
| 2143 | /// Tests whether this file type represents a directory. The |
| 2144 | /// result is mutually exclusive to the results of |
| 2145 | /// [`is_file`] and [`is_symlink`]; only zero or one of these |
| 2146 | /// tests may pass. |
| 2147 | /// |
| 2148 | /// [`is_file`]: FileType::is_file |
| 2149 | /// [`is_symlink`]: FileType::is_symlink |
| 2150 | /// |
| 2151 | /// # Examples |
| 2152 | /// |
| 2153 | /// ```no_run |
| 2154 | /// fn main() -> std::io::Result<()> { |
| 2155 | /// use std::fs; |
| 2156 | /// |
| 2157 | /// let metadata = fs::metadata("foo.txt" )?; |
| 2158 | /// let file_type = metadata.file_type(); |
| 2159 | /// |
| 2160 | /// assert_eq!(file_type.is_dir(), false); |
| 2161 | /// Ok(()) |
| 2162 | /// } |
| 2163 | /// ``` |
| 2164 | #[must_use ] |
| 2165 | #[stable (feature = "file_type" , since = "1.1.0" )] |
| 2166 | pub fn is_dir(&self) -> bool { |
| 2167 | self.0.is_dir() |
| 2168 | } |
| 2169 | |
| 2170 | /// Tests whether this file type represents a regular file. |
| 2171 | /// The result is mutually exclusive to the results of |
| 2172 | /// [`is_dir`] and [`is_symlink`]; only zero or one of these |
| 2173 | /// tests may pass. |
| 2174 | /// |
| 2175 | /// When the goal is simply to read from (or write to) the source, the most |
| 2176 | /// reliable way to test the source can be read (or written to) is to open |
| 2177 | /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on |
| 2178 | /// a Unix-like system for example. See [`File::open`] or |
| 2179 | /// [`OpenOptions::open`] for more information. |
| 2180 | /// |
| 2181 | /// [`is_dir`]: FileType::is_dir |
| 2182 | /// [`is_symlink`]: FileType::is_symlink |
| 2183 | /// |
| 2184 | /// # Examples |
| 2185 | /// |
| 2186 | /// ```no_run |
| 2187 | /// fn main() -> std::io::Result<()> { |
| 2188 | /// use std::fs; |
| 2189 | /// |
| 2190 | /// let metadata = fs::metadata("foo.txt" )?; |
| 2191 | /// let file_type = metadata.file_type(); |
| 2192 | /// |
| 2193 | /// assert_eq!(file_type.is_file(), true); |
| 2194 | /// Ok(()) |
| 2195 | /// } |
| 2196 | /// ``` |
| 2197 | #[must_use ] |
| 2198 | #[stable (feature = "file_type" , since = "1.1.0" )] |
| 2199 | pub fn is_file(&self) -> bool { |
| 2200 | self.0.is_file() |
| 2201 | } |
| 2202 | |
| 2203 | /// Tests whether this file type represents a symbolic link. |
| 2204 | /// The result is mutually exclusive to the results of |
| 2205 | /// [`is_dir`] and [`is_file`]; only zero or one of these |
| 2206 | /// tests may pass. |
| 2207 | /// |
| 2208 | /// The underlying [`Metadata`] struct needs to be retrieved |
| 2209 | /// with the [`fs::symlink_metadata`] function and not the |
| 2210 | /// [`fs::metadata`] function. The [`fs::metadata`] function |
| 2211 | /// follows symbolic links, so [`is_symlink`] would always |
| 2212 | /// return `false` for the target file. |
| 2213 | /// |
| 2214 | /// [`fs::metadata`]: metadata |
| 2215 | /// [`fs::symlink_metadata`]: symlink_metadata |
| 2216 | /// [`is_dir`]: FileType::is_dir |
| 2217 | /// [`is_file`]: FileType::is_file |
| 2218 | /// [`is_symlink`]: FileType::is_symlink |
| 2219 | /// |
| 2220 | /// # Examples |
| 2221 | /// |
| 2222 | /// ```no_run |
| 2223 | /// use std::fs; |
| 2224 | /// |
| 2225 | /// fn main() -> std::io::Result<()> { |
| 2226 | /// let metadata = fs::symlink_metadata("foo.txt" )?; |
| 2227 | /// let file_type = metadata.file_type(); |
| 2228 | /// |
| 2229 | /// assert_eq!(file_type.is_symlink(), false); |
| 2230 | /// Ok(()) |
| 2231 | /// } |
| 2232 | /// ``` |
| 2233 | #[must_use ] |
| 2234 | #[stable (feature = "file_type" , since = "1.1.0" )] |
| 2235 | pub fn is_symlink(&self) -> bool { |
| 2236 | self.0.is_symlink() |
| 2237 | } |
| 2238 | } |
| 2239 | |
| 2240 | #[stable (feature = "std_debug" , since = "1.16.0" )] |
| 2241 | impl fmt::Debug for FileType { |
| 2242 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 2243 | f&mut DebugStruct<'_, '_>.debug_struct("FileType" ) |
| 2244 | .field("is_file" , &self.is_file()) |
| 2245 | .field("is_dir" , &self.is_dir()) |
| 2246 | .field(name:"is_symlink" , &self.is_symlink()) |
| 2247 | .finish_non_exhaustive() |
| 2248 | } |
| 2249 | } |
| 2250 | |
| 2251 | impl AsInner<fs_imp::FileType> for FileType { |
| 2252 | #[inline ] |
| 2253 | fn as_inner(&self) -> &fs_imp::FileType { |
| 2254 | &self.0 |
| 2255 | } |
| 2256 | } |
| 2257 | |
| 2258 | impl FromInner<fs_imp::FilePermissions> for Permissions { |
| 2259 | fn from_inner(f: fs_imp::FilePermissions) -> Permissions { |
| 2260 | Permissions(f) |
| 2261 | } |
| 2262 | } |
| 2263 | |
| 2264 | impl AsInner<fs_imp::FilePermissions> for Permissions { |
| 2265 | #[inline ] |
| 2266 | fn as_inner(&self) -> &fs_imp::FilePermissions { |
| 2267 | &self.0 |
| 2268 | } |
| 2269 | } |
| 2270 | |
| 2271 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2272 | impl Iterator for ReadDir { |
| 2273 | type Item = io::Result<DirEntry>; |
| 2274 | |
| 2275 | fn next(&mut self) -> Option<io::Result<DirEntry>> { |
| 2276 | self.0.next().map(|entry: Result| entry.map(op:DirEntry)) |
| 2277 | } |
| 2278 | } |
| 2279 | |
| 2280 | impl DirEntry { |
| 2281 | /// Returns the full path to the file that this entry represents. |
| 2282 | /// |
| 2283 | /// The full path is created by joining the original path to `read_dir` |
| 2284 | /// with the filename of this entry. |
| 2285 | /// |
| 2286 | /// # Examples |
| 2287 | /// |
| 2288 | /// ```no_run |
| 2289 | /// use std::fs; |
| 2290 | /// |
| 2291 | /// fn main() -> std::io::Result<()> { |
| 2292 | /// for entry in fs::read_dir("." )? { |
| 2293 | /// let dir = entry?; |
| 2294 | /// println!("{:?}" , dir.path()); |
| 2295 | /// } |
| 2296 | /// Ok(()) |
| 2297 | /// } |
| 2298 | /// ``` |
| 2299 | /// |
| 2300 | /// This prints output like: |
| 2301 | /// |
| 2302 | /// ```text |
| 2303 | /// "./whatever.txt" |
| 2304 | /// "./foo.html" |
| 2305 | /// "./hello_world.rs" |
| 2306 | /// ``` |
| 2307 | /// |
| 2308 | /// The exact text, of course, depends on what files you have in `.`. |
| 2309 | #[must_use ] |
| 2310 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2311 | pub fn path(&self) -> PathBuf { |
| 2312 | self.0.path() |
| 2313 | } |
| 2314 | |
| 2315 | /// Returns the metadata for the file that this entry points at. |
| 2316 | /// |
| 2317 | /// This function will not traverse symlinks if this entry points at a |
| 2318 | /// symlink. To traverse symlinks use [`fs::metadata`] or [`fs::File::metadata`]. |
| 2319 | /// |
| 2320 | /// [`fs::metadata`]: metadata |
| 2321 | /// [`fs::File::metadata`]: File::metadata |
| 2322 | /// |
| 2323 | /// # Platform-specific behavior |
| 2324 | /// |
| 2325 | /// On Windows this function is cheap to call (no extra system calls |
| 2326 | /// needed), but on Unix platforms this function is the equivalent of |
| 2327 | /// calling `symlink_metadata` on the path. |
| 2328 | /// |
| 2329 | /// # Examples |
| 2330 | /// |
| 2331 | /// ``` |
| 2332 | /// use std::fs; |
| 2333 | /// |
| 2334 | /// if let Ok(entries) = fs::read_dir("." ) { |
| 2335 | /// for entry in entries { |
| 2336 | /// if let Ok(entry) = entry { |
| 2337 | /// // Here, `entry` is a `DirEntry`. |
| 2338 | /// if let Ok(metadata) = entry.metadata() { |
| 2339 | /// // Now let's show our entry's permissions! |
| 2340 | /// println!("{:?}: {:?}" , entry.path(), metadata.permissions()); |
| 2341 | /// } else { |
| 2342 | /// println!("Couldn't get metadata for {:?}" , entry.path()); |
| 2343 | /// } |
| 2344 | /// } |
| 2345 | /// } |
| 2346 | /// } |
| 2347 | /// ``` |
| 2348 | #[stable (feature = "dir_entry_ext" , since = "1.1.0" )] |
| 2349 | pub fn metadata(&self) -> io::Result<Metadata> { |
| 2350 | self.0.metadata().map(Metadata) |
| 2351 | } |
| 2352 | |
| 2353 | /// Returns the file type for the file that this entry points at. |
| 2354 | /// |
| 2355 | /// This function will not traverse symlinks if this entry points at a |
| 2356 | /// symlink. |
| 2357 | /// |
| 2358 | /// # Platform-specific behavior |
| 2359 | /// |
| 2360 | /// On Windows and most Unix platforms this function is free (no extra |
| 2361 | /// system calls needed), but some Unix platforms may require the equivalent |
| 2362 | /// call to `symlink_metadata` to learn about the target file type. |
| 2363 | /// |
| 2364 | /// # Examples |
| 2365 | /// |
| 2366 | /// ``` |
| 2367 | /// use std::fs; |
| 2368 | /// |
| 2369 | /// if let Ok(entries) = fs::read_dir("." ) { |
| 2370 | /// for entry in entries { |
| 2371 | /// if let Ok(entry) = entry { |
| 2372 | /// // Here, `entry` is a `DirEntry`. |
| 2373 | /// if let Ok(file_type) = entry.file_type() { |
| 2374 | /// // Now let's show our entry's file type! |
| 2375 | /// println!("{:?}: {:?}" , entry.path(), file_type); |
| 2376 | /// } else { |
| 2377 | /// println!("Couldn't get file type for {:?}" , entry.path()); |
| 2378 | /// } |
| 2379 | /// } |
| 2380 | /// } |
| 2381 | /// } |
| 2382 | /// ``` |
| 2383 | #[stable (feature = "dir_entry_ext" , since = "1.1.0" )] |
| 2384 | pub fn file_type(&self) -> io::Result<FileType> { |
| 2385 | self.0.file_type().map(FileType) |
| 2386 | } |
| 2387 | |
| 2388 | /// Returns the file name of this directory entry without any |
| 2389 | /// leading path component(s). |
| 2390 | /// |
| 2391 | /// As an example, |
| 2392 | /// the output of the function will result in "foo" for all the following paths: |
| 2393 | /// - "./foo" |
| 2394 | /// - "/the/foo" |
| 2395 | /// - "../../foo" |
| 2396 | /// |
| 2397 | /// # Examples |
| 2398 | /// |
| 2399 | /// ``` |
| 2400 | /// use std::fs; |
| 2401 | /// |
| 2402 | /// if let Ok(entries) = fs::read_dir("." ) { |
| 2403 | /// for entry in entries { |
| 2404 | /// if let Ok(entry) = entry { |
| 2405 | /// // Here, `entry` is a `DirEntry`. |
| 2406 | /// println!("{:?}" , entry.file_name()); |
| 2407 | /// } |
| 2408 | /// } |
| 2409 | /// } |
| 2410 | /// ``` |
| 2411 | #[must_use ] |
| 2412 | #[stable (feature = "dir_entry_ext" , since = "1.1.0" )] |
| 2413 | pub fn file_name(&self) -> OsString { |
| 2414 | self.0.file_name() |
| 2415 | } |
| 2416 | } |
| 2417 | |
| 2418 | #[stable (feature = "dir_entry_debug" , since = "1.13.0" )] |
| 2419 | impl fmt::Debug for DirEntry { |
| 2420 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 2421 | f.debug_tuple(name:"DirEntry" ).field(&self.path()).finish() |
| 2422 | } |
| 2423 | } |
| 2424 | |
| 2425 | impl AsInner<fs_imp::DirEntry> for DirEntry { |
| 2426 | #[inline ] |
| 2427 | fn as_inner(&self) -> &fs_imp::DirEntry { |
| 2428 | &self.0 |
| 2429 | } |
| 2430 | } |
| 2431 | |
| 2432 | /// Removes a file from the filesystem. |
| 2433 | /// |
| 2434 | /// Note that there is no |
| 2435 | /// guarantee that the file is immediately deleted (e.g., depending on |
| 2436 | /// platform, other open file descriptors may prevent immediate removal). |
| 2437 | /// |
| 2438 | /// # Platform-specific behavior |
| 2439 | /// |
| 2440 | /// This function currently corresponds to the `unlink` function on Unix. |
| 2441 | /// On Windows, `DeleteFile` is used or `CreateFileW` and `SetInformationByHandle` for readonly files. |
| 2442 | /// Note that, this [may change in the future][changes]. |
| 2443 | /// |
| 2444 | /// [changes]: io#platform-specific-behavior |
| 2445 | /// |
| 2446 | /// # Errors |
| 2447 | /// |
| 2448 | /// This function will return an error in the following situations, but is not |
| 2449 | /// limited to just these cases: |
| 2450 | /// |
| 2451 | /// * `path` points to a directory. |
| 2452 | /// * The file doesn't exist. |
| 2453 | /// * The user lacks permissions to remove the file. |
| 2454 | /// |
| 2455 | /// This function will only ever return an error of kind `NotFound` if the given |
| 2456 | /// path does not exist. Note that the inverse is not true, |
| 2457 | /// ie. if a path does not exist, its removal may fail for a number of reasons, |
| 2458 | /// such as insufficient permissions. |
| 2459 | /// |
| 2460 | /// # Examples |
| 2461 | /// |
| 2462 | /// ```no_run |
| 2463 | /// use std::fs; |
| 2464 | /// |
| 2465 | /// fn main() -> std::io::Result<()> { |
| 2466 | /// fs::remove_file("a.txt" )?; |
| 2467 | /// Ok(()) |
| 2468 | /// } |
| 2469 | /// ``` |
| 2470 | #[doc (alias = "rm" , alias = "unlink" , alias = "DeleteFile" )] |
| 2471 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2472 | pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> { |
| 2473 | fs_imp::remove_file(path.as_ref()) |
| 2474 | } |
| 2475 | |
| 2476 | /// Given a path, queries the file system to get information about a file, |
| 2477 | /// directory, etc. |
| 2478 | /// |
| 2479 | /// This function will traverse symbolic links to query information about the |
| 2480 | /// destination file. |
| 2481 | /// |
| 2482 | /// # Platform-specific behavior |
| 2483 | /// |
| 2484 | /// This function currently corresponds to the `stat` function on Unix |
| 2485 | /// and the `GetFileInformationByHandle` function on Windows. |
| 2486 | /// Note that, this [may change in the future][changes]. |
| 2487 | /// |
| 2488 | /// [changes]: io#platform-specific-behavior |
| 2489 | /// |
| 2490 | /// # Errors |
| 2491 | /// |
| 2492 | /// This function will return an error in the following situations, but is not |
| 2493 | /// limited to just these cases: |
| 2494 | /// |
| 2495 | /// * The user lacks permissions to perform `metadata` call on `path`. |
| 2496 | /// * `path` does not exist. |
| 2497 | /// |
| 2498 | /// # Examples |
| 2499 | /// |
| 2500 | /// ```rust,no_run |
| 2501 | /// use std::fs; |
| 2502 | /// |
| 2503 | /// fn main() -> std::io::Result<()> { |
| 2504 | /// let attr = fs::metadata("/some/file/path.txt" )?; |
| 2505 | /// // inspect attr ... |
| 2506 | /// Ok(()) |
| 2507 | /// } |
| 2508 | /// ``` |
| 2509 | #[doc (alias = "stat" )] |
| 2510 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2511 | pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> { |
| 2512 | fs_imp::metadata(path.as_ref()).map(op:Metadata) |
| 2513 | } |
| 2514 | |
| 2515 | /// Queries the metadata about a file without following symlinks. |
| 2516 | /// |
| 2517 | /// # Platform-specific behavior |
| 2518 | /// |
| 2519 | /// This function currently corresponds to the `lstat` function on Unix |
| 2520 | /// and the `GetFileInformationByHandle` function on Windows. |
| 2521 | /// Note that, this [may change in the future][changes]. |
| 2522 | /// |
| 2523 | /// [changes]: io#platform-specific-behavior |
| 2524 | /// |
| 2525 | /// # Errors |
| 2526 | /// |
| 2527 | /// This function will return an error in the following situations, but is not |
| 2528 | /// limited to just these cases: |
| 2529 | /// |
| 2530 | /// * The user lacks permissions to perform `metadata` call on `path`. |
| 2531 | /// * `path` does not exist. |
| 2532 | /// |
| 2533 | /// # Examples |
| 2534 | /// |
| 2535 | /// ```rust,no_run |
| 2536 | /// use std::fs; |
| 2537 | /// |
| 2538 | /// fn main() -> std::io::Result<()> { |
| 2539 | /// let attr = fs::symlink_metadata("/some/file/path.txt" )?; |
| 2540 | /// // inspect attr ... |
| 2541 | /// Ok(()) |
| 2542 | /// } |
| 2543 | /// ``` |
| 2544 | #[doc (alias = "lstat" )] |
| 2545 | #[stable (feature = "symlink_metadata" , since = "1.1.0" )] |
| 2546 | pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> { |
| 2547 | fs_imp::symlink_metadata(path.as_ref()).map(op:Metadata) |
| 2548 | } |
| 2549 | |
| 2550 | /// Renames a file or directory to a new name, replacing the original file if |
| 2551 | /// `to` already exists. |
| 2552 | /// |
| 2553 | /// This will not work if the new name is on a different mount point. |
| 2554 | /// |
| 2555 | /// # Platform-specific behavior |
| 2556 | /// |
| 2557 | /// This function currently corresponds to the `rename` function on Unix |
| 2558 | /// and the `MoveFileExW` or `SetFileInformationByHandle` function on Windows. |
| 2559 | /// |
| 2560 | /// Because of this, the behavior when both `from` and `to` exist differs. On |
| 2561 | /// Unix, if `from` is a directory, `to` must also be an (empty) directory. If |
| 2562 | /// `from` is not a directory, `to` must also be not a directory. The behavior |
| 2563 | /// on Windows is the same on Windows 10 1607 and higher if `FileRenameInfoEx` |
| 2564 | /// is supported by the filesystem; otherwise, `from` can be anything, but |
| 2565 | /// `to` must *not* be a directory. |
| 2566 | /// |
| 2567 | /// Note that, this [may change in the future][changes]. |
| 2568 | /// |
| 2569 | /// [changes]: io#platform-specific-behavior |
| 2570 | /// |
| 2571 | /// # Errors |
| 2572 | /// |
| 2573 | /// This function will return an error in the following situations, but is not |
| 2574 | /// limited to just these cases: |
| 2575 | /// |
| 2576 | /// * `from` does not exist. |
| 2577 | /// * The user lacks permissions to view contents. |
| 2578 | /// * `from` and `to` are on separate filesystems. |
| 2579 | /// |
| 2580 | /// # Examples |
| 2581 | /// |
| 2582 | /// ```no_run |
| 2583 | /// use std::fs; |
| 2584 | /// |
| 2585 | /// fn main() -> std::io::Result<()> { |
| 2586 | /// fs::rename("a.txt" , "b.txt" )?; // Rename a.txt to b.txt |
| 2587 | /// Ok(()) |
| 2588 | /// } |
| 2589 | /// ``` |
| 2590 | #[doc (alias = "mv" , alias = "MoveFile" , alias = "MoveFileEx" )] |
| 2591 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2592 | pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> { |
| 2593 | fs_imp::rename(old:from.as_ref(), new:to.as_ref()) |
| 2594 | } |
| 2595 | |
| 2596 | /// Copies the contents of one file to another. This function will also |
| 2597 | /// copy the permission bits of the original file to the destination file. |
| 2598 | /// |
| 2599 | /// This function will **overwrite** the contents of `to`. |
| 2600 | /// |
| 2601 | /// Note that if `from` and `to` both point to the same file, then the file |
| 2602 | /// will likely get truncated by this operation. |
| 2603 | /// |
| 2604 | /// On success, the total number of bytes copied is returned and it is equal to |
| 2605 | /// the length of the `to` file as reported by `metadata`. |
| 2606 | /// |
| 2607 | /// If you want to copy the contents of one file to another and you’re |
| 2608 | /// working with [`File`]s, see the [`io::copy`](io::copy()) function. |
| 2609 | /// |
| 2610 | /// # Platform-specific behavior |
| 2611 | /// |
| 2612 | /// This function currently corresponds to the `open` function in Unix |
| 2613 | /// with `O_RDONLY` for `from` and `O_WRONLY`, `O_CREAT`, and `O_TRUNC` for `to`. |
| 2614 | /// `O_CLOEXEC` is set for returned file descriptors. |
| 2615 | /// |
| 2616 | /// On Linux (including Android), this function attempts to use `copy_file_range(2)`, |
| 2617 | /// and falls back to reading and writing if that is not possible. |
| 2618 | /// |
| 2619 | /// On Windows, this function currently corresponds to `CopyFileEx`. Alternate |
| 2620 | /// NTFS streams are copied but only the size of the main stream is returned by |
| 2621 | /// this function. |
| 2622 | /// |
| 2623 | /// On MacOS, this function corresponds to `fclonefileat` and `fcopyfile`. |
| 2624 | /// |
| 2625 | /// Note that platform-specific behavior [may change in the future][changes]. |
| 2626 | /// |
| 2627 | /// [changes]: io#platform-specific-behavior |
| 2628 | /// |
| 2629 | /// # Errors |
| 2630 | /// |
| 2631 | /// This function will return an error in the following situations, but is not |
| 2632 | /// limited to just these cases: |
| 2633 | /// |
| 2634 | /// * `from` is neither a regular file nor a symlink to a regular file. |
| 2635 | /// * `from` does not exist. |
| 2636 | /// * The current process does not have the permission rights to read |
| 2637 | /// `from` or write `to`. |
| 2638 | /// * The parent directory of `to` doesn't exist. |
| 2639 | /// |
| 2640 | /// # Examples |
| 2641 | /// |
| 2642 | /// ```no_run |
| 2643 | /// use std::fs; |
| 2644 | /// |
| 2645 | /// fn main() -> std::io::Result<()> { |
| 2646 | /// fs::copy("foo.txt" , "bar.txt" )?; // Copy foo.txt to bar.txt |
| 2647 | /// Ok(()) |
| 2648 | /// } |
| 2649 | /// ``` |
| 2650 | #[doc (alias = "cp" )] |
| 2651 | #[doc (alias = "CopyFile" , alias = "CopyFileEx" )] |
| 2652 | #[doc (alias = "fclonefileat" , alias = "fcopyfile" )] |
| 2653 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2654 | pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> { |
| 2655 | fs_imp::copy(from.as_ref(), to.as_ref()) |
| 2656 | } |
| 2657 | |
| 2658 | /// Creates a new hard link on the filesystem. |
| 2659 | /// |
| 2660 | /// The `link` path will be a link pointing to the `original` path. Note that |
| 2661 | /// systems often require these two paths to both be located on the same |
| 2662 | /// filesystem. |
| 2663 | /// |
| 2664 | /// If `original` names a symbolic link, it is platform-specific whether the |
| 2665 | /// symbolic link is followed. On platforms where it's possible to not follow |
| 2666 | /// it, it is not followed, and the created hard link points to the symbolic |
| 2667 | /// link itself. |
| 2668 | /// |
| 2669 | /// # Platform-specific behavior |
| 2670 | /// |
| 2671 | /// This function currently corresponds the `CreateHardLink` function on Windows. |
| 2672 | /// On most Unix systems, it corresponds to the `linkat` function with no flags. |
| 2673 | /// On Android, VxWorks, and Redox, it instead corresponds to the `link` function. |
| 2674 | /// On MacOS, it uses the `linkat` function if it is available, but on very old |
| 2675 | /// systems where `linkat` is not available, `link` is selected at runtime instead. |
| 2676 | /// Note that, this [may change in the future][changes]. |
| 2677 | /// |
| 2678 | /// [changes]: io#platform-specific-behavior |
| 2679 | /// |
| 2680 | /// # Errors |
| 2681 | /// |
| 2682 | /// This function will return an error in the following situations, but is not |
| 2683 | /// limited to just these cases: |
| 2684 | /// |
| 2685 | /// * The `original` path is not a file or doesn't exist. |
| 2686 | /// * The 'link' path already exists. |
| 2687 | /// |
| 2688 | /// # Examples |
| 2689 | /// |
| 2690 | /// ```no_run |
| 2691 | /// use std::fs; |
| 2692 | /// |
| 2693 | /// fn main() -> std::io::Result<()> { |
| 2694 | /// fs::hard_link("a.txt" , "b.txt" )?; // Hard link a.txt to b.txt |
| 2695 | /// Ok(()) |
| 2696 | /// } |
| 2697 | /// ``` |
| 2698 | #[doc (alias = "CreateHardLink" , alias = "linkat" )] |
| 2699 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2700 | pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> { |
| 2701 | fs_imp::hard_link(original.as_ref(), link.as_ref()) |
| 2702 | } |
| 2703 | |
| 2704 | /// Creates a new symbolic link on the filesystem. |
| 2705 | /// |
| 2706 | /// The `link` path will be a symbolic link pointing to the `original` path. |
| 2707 | /// On Windows, this will be a file symlink, not a directory symlink; |
| 2708 | /// for this reason, the platform-specific [`std::os::unix::fs::symlink`] |
| 2709 | /// and [`std::os::windows::fs::symlink_file`] or [`symlink_dir`] should be |
| 2710 | /// used instead to make the intent explicit. |
| 2711 | /// |
| 2712 | /// [`std::os::unix::fs::symlink`]: crate::os::unix::fs::symlink |
| 2713 | /// [`std::os::windows::fs::symlink_file`]: crate::os::windows::fs::symlink_file |
| 2714 | /// [`symlink_dir`]: crate::os::windows::fs::symlink_dir |
| 2715 | /// |
| 2716 | /// # Examples |
| 2717 | /// |
| 2718 | /// ```no_run |
| 2719 | /// use std::fs; |
| 2720 | /// |
| 2721 | /// fn main() -> std::io::Result<()> { |
| 2722 | /// fs::soft_link("a.txt" , "b.txt" )?; |
| 2723 | /// Ok(()) |
| 2724 | /// } |
| 2725 | /// ``` |
| 2726 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2727 | #[deprecated ( |
| 2728 | since = "1.1.0" , |
| 2729 | note = "replaced with std::os::unix::fs::symlink and \ |
| 2730 | std::os::windows::fs::{symlink_file, symlink_dir}" |
| 2731 | )] |
| 2732 | pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> { |
| 2733 | fs_imp::symlink(original.as_ref(), link.as_ref()) |
| 2734 | } |
| 2735 | |
| 2736 | /// Reads a symbolic link, returning the file that the link points to. |
| 2737 | /// |
| 2738 | /// # Platform-specific behavior |
| 2739 | /// |
| 2740 | /// This function currently corresponds to the `readlink` function on Unix |
| 2741 | /// and the `CreateFile` function with `FILE_FLAG_OPEN_REPARSE_POINT` and |
| 2742 | /// `FILE_FLAG_BACKUP_SEMANTICS` flags on Windows. |
| 2743 | /// Note that, this [may change in the future][changes]. |
| 2744 | /// |
| 2745 | /// [changes]: io#platform-specific-behavior |
| 2746 | /// |
| 2747 | /// # Errors |
| 2748 | /// |
| 2749 | /// This function will return an error in the following situations, but is not |
| 2750 | /// limited to just these cases: |
| 2751 | /// |
| 2752 | /// * `path` is not a symbolic link. |
| 2753 | /// * `path` does not exist. |
| 2754 | /// |
| 2755 | /// # Examples |
| 2756 | /// |
| 2757 | /// ```no_run |
| 2758 | /// use std::fs; |
| 2759 | /// |
| 2760 | /// fn main() -> std::io::Result<()> { |
| 2761 | /// let path = fs::read_link("a.txt" )?; |
| 2762 | /// Ok(()) |
| 2763 | /// } |
| 2764 | /// ``` |
| 2765 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2766 | pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> { |
| 2767 | fs_imp::read_link(path.as_ref()) |
| 2768 | } |
| 2769 | |
| 2770 | /// Returns the canonical, absolute form of a path with all intermediate |
| 2771 | /// components normalized and symbolic links resolved. |
| 2772 | /// |
| 2773 | /// # Platform-specific behavior |
| 2774 | /// |
| 2775 | /// This function currently corresponds to the `realpath` function on Unix |
| 2776 | /// and the `CreateFile` and `GetFinalPathNameByHandle` functions on Windows. |
| 2777 | /// Note that this [may change in the future][changes]. |
| 2778 | /// |
| 2779 | /// On Windows, this converts the path to use [extended length path][path] |
| 2780 | /// syntax, which allows your program to use longer path names, but means you |
| 2781 | /// can only join backslash-delimited paths to it, and it may be incompatible |
| 2782 | /// with other applications (if passed to the application on the command-line, |
| 2783 | /// or written to a file another application may read). |
| 2784 | /// |
| 2785 | /// [changes]: io#platform-specific-behavior |
| 2786 | /// [path]: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file |
| 2787 | /// |
| 2788 | /// # Errors |
| 2789 | /// |
| 2790 | /// This function will return an error in the following situations, but is not |
| 2791 | /// limited to just these cases: |
| 2792 | /// |
| 2793 | /// * `path` does not exist. |
| 2794 | /// * A non-final component in path is not a directory. |
| 2795 | /// |
| 2796 | /// # Examples |
| 2797 | /// |
| 2798 | /// ```no_run |
| 2799 | /// use std::fs; |
| 2800 | /// |
| 2801 | /// fn main() -> std::io::Result<()> { |
| 2802 | /// let path = fs::canonicalize("../a/../foo.txt" )?; |
| 2803 | /// Ok(()) |
| 2804 | /// } |
| 2805 | /// ``` |
| 2806 | #[doc (alias = "realpath" )] |
| 2807 | #[doc (alias = "GetFinalPathNameByHandle" )] |
| 2808 | #[stable (feature = "fs_canonicalize" , since = "1.5.0" )] |
| 2809 | pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> { |
| 2810 | fs_imp::canonicalize(path.as_ref()) |
| 2811 | } |
| 2812 | |
| 2813 | /// Creates a new, empty directory at the provided path |
| 2814 | /// |
| 2815 | /// # Platform-specific behavior |
| 2816 | /// |
| 2817 | /// This function currently corresponds to the `mkdir` function on Unix |
| 2818 | /// and the `CreateDirectoryW` function on Windows. |
| 2819 | /// Note that, this [may change in the future][changes]. |
| 2820 | /// |
| 2821 | /// [changes]: io#platform-specific-behavior |
| 2822 | /// |
| 2823 | /// **NOTE**: If a parent of the given path doesn't exist, this function will |
| 2824 | /// return an error. To create a directory and all its missing parents at the |
| 2825 | /// same time, use the [`create_dir_all`] function. |
| 2826 | /// |
| 2827 | /// # Errors |
| 2828 | /// |
| 2829 | /// This function will return an error in the following situations, but is not |
| 2830 | /// limited to just these cases: |
| 2831 | /// |
| 2832 | /// * User lacks permissions to create directory at `path`. |
| 2833 | /// * A parent of the given path doesn't exist. (To create a directory and all |
| 2834 | /// its missing parents at the same time, use the [`create_dir_all`] |
| 2835 | /// function.) |
| 2836 | /// * `path` already exists. |
| 2837 | /// |
| 2838 | /// # Examples |
| 2839 | /// |
| 2840 | /// ```no_run |
| 2841 | /// use std::fs; |
| 2842 | /// |
| 2843 | /// fn main() -> std::io::Result<()> { |
| 2844 | /// fs::create_dir("/some/dir" )?; |
| 2845 | /// Ok(()) |
| 2846 | /// } |
| 2847 | /// ``` |
| 2848 | #[doc (alias = "mkdir" , alias = "CreateDirectory" )] |
| 2849 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2850 | #[cfg_attr (not(test), rustc_diagnostic_item = "fs_create_dir" )] |
| 2851 | pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { |
| 2852 | DirBuilder::new().create(path.as_ref()) |
| 2853 | } |
| 2854 | |
| 2855 | /// Recursively create a directory and all of its parent components if they |
| 2856 | /// are missing. |
| 2857 | /// |
| 2858 | /// This function is not atomic. If it returns an error, any parent components it was able to create |
| 2859 | /// will remain. |
| 2860 | /// |
| 2861 | /// If the empty path is passed to this function, it always succeeds without |
| 2862 | /// creating any directories. |
| 2863 | /// |
| 2864 | /// # Platform-specific behavior |
| 2865 | /// |
| 2866 | /// This function currently corresponds to multiple calls to the `mkdir` |
| 2867 | /// function on Unix and the `CreateDirectoryW` function on Windows. |
| 2868 | /// |
| 2869 | /// Note that, this [may change in the future][changes]. |
| 2870 | /// |
| 2871 | /// [changes]: io#platform-specific-behavior |
| 2872 | /// |
| 2873 | /// # Errors |
| 2874 | /// |
| 2875 | /// The function will return an error if any directory specified in path does not exist and |
| 2876 | /// could not be created. There may be other error conditions; see [`fs::create_dir`] for specifics. |
| 2877 | /// |
| 2878 | /// Notable exception is made for situations where any of the directories |
| 2879 | /// specified in the `path` could not be created as it was being created concurrently. |
| 2880 | /// Such cases are considered to be successful. That is, calling `create_dir_all` |
| 2881 | /// concurrently from multiple threads or processes is guaranteed not to fail |
| 2882 | /// due to a race condition with itself. |
| 2883 | /// |
| 2884 | /// [`fs::create_dir`]: create_dir |
| 2885 | /// |
| 2886 | /// # Examples |
| 2887 | /// |
| 2888 | /// ```no_run |
| 2889 | /// use std::fs; |
| 2890 | /// |
| 2891 | /// fn main() -> std::io::Result<()> { |
| 2892 | /// fs::create_dir_all("/some/dir" )?; |
| 2893 | /// Ok(()) |
| 2894 | /// } |
| 2895 | /// ``` |
| 2896 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2897 | pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> { |
| 2898 | DirBuilder::new().recursive(true).create(path.as_ref()) |
| 2899 | } |
| 2900 | |
| 2901 | /// Removes an empty directory. |
| 2902 | /// |
| 2903 | /// If you want to remove a directory that is not empty, as well as all |
| 2904 | /// of its contents recursively, consider using [`remove_dir_all`] |
| 2905 | /// instead. |
| 2906 | /// |
| 2907 | /// # Platform-specific behavior |
| 2908 | /// |
| 2909 | /// This function currently corresponds to the `rmdir` function on Unix |
| 2910 | /// and the `RemoveDirectory` function on Windows. |
| 2911 | /// Note that, this [may change in the future][changes]. |
| 2912 | /// |
| 2913 | /// [changes]: io#platform-specific-behavior |
| 2914 | /// |
| 2915 | /// # Errors |
| 2916 | /// |
| 2917 | /// This function will return an error in the following situations, but is not |
| 2918 | /// limited to just these cases: |
| 2919 | /// |
| 2920 | /// * `path` doesn't exist. |
| 2921 | /// * `path` isn't a directory. |
| 2922 | /// * The user lacks permissions to remove the directory at the provided `path`. |
| 2923 | /// * The directory isn't empty. |
| 2924 | /// |
| 2925 | /// This function will only ever return an error of kind `NotFound` if the given |
| 2926 | /// path does not exist. Note that the inverse is not true, |
| 2927 | /// ie. if a path does not exist, its removal may fail for a number of reasons, |
| 2928 | /// such as insufficient permissions. |
| 2929 | /// |
| 2930 | /// # Examples |
| 2931 | /// |
| 2932 | /// ```no_run |
| 2933 | /// use std::fs; |
| 2934 | /// |
| 2935 | /// fn main() -> std::io::Result<()> { |
| 2936 | /// fs::remove_dir("/some/dir" )?; |
| 2937 | /// Ok(()) |
| 2938 | /// } |
| 2939 | /// ``` |
| 2940 | #[doc (alias = "rmdir" , alias = "RemoveDirectory" )] |
| 2941 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 2942 | pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { |
| 2943 | fs_imp::remove_dir(path.as_ref()) |
| 2944 | } |
| 2945 | |
| 2946 | /// Removes a directory at this path, after removing all its contents. Use |
| 2947 | /// carefully! |
| 2948 | /// |
| 2949 | /// This function does **not** follow symbolic links and it will simply remove the |
| 2950 | /// symbolic link itself. |
| 2951 | /// |
| 2952 | /// # Platform-specific behavior |
| 2953 | /// |
| 2954 | /// These implementation details [may change in the future][changes]. |
| 2955 | /// |
| 2956 | /// - "Unix-like": By default, this function currently corresponds to |
| 2957 | /// `openat`, `fdopendir`, `unlinkat` and `lstat` |
| 2958 | /// on Unix-family platforms, except where noted otherwise. |
| 2959 | /// - "Windows": This function currently corresponds to `CreateFileW`, |
| 2960 | /// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtCreateFile`. |
| 2961 | /// |
| 2962 | /// ## Time-of-check to time-of-use (TOCTOU) race conditions |
| 2963 | /// On a few platforms there is no way to remove a directory's contents without following symlinks |
| 2964 | /// unless you perform a check and then operate on paths based on that directory. |
| 2965 | /// This allows concurrently-running code to replace the directory with a symlink after the check, |
| 2966 | /// causing a removal to instead operate on a path based on the symlink. This is a TOCTOU race. |
| 2967 | /// By default, `fs::remove_dir_all` protects against a symlink TOCTOU race on all platforms |
| 2968 | /// except the following. It should not be used in security-sensitive contexts on these platforms: |
| 2969 | /// - Miri: Even when emulating targets where the underlying implementation will protect against |
| 2970 | /// TOCTOU races, Miri will not do so. |
| 2971 | /// - Redox OS: This function does not protect against TOCTOU races, as Redox does not implement |
| 2972 | /// the required platform support to do so. |
| 2973 | /// |
| 2974 | /// [changes]: io#platform-specific-behavior |
| 2975 | /// |
| 2976 | /// # Errors |
| 2977 | /// |
| 2978 | /// See [`fs::remove_file`] and [`fs::remove_dir`]. |
| 2979 | /// |
| 2980 | /// [`remove_dir_all`] will fail if [`remove_dir`] or [`remove_file`] fail on *any* constituent |
| 2981 | /// paths, *including* the root `path`. Consequently, |
| 2982 | /// |
| 2983 | /// - The directory you are deleting *must* exist, meaning that this function is *not idempotent*. |
| 2984 | /// - [`remove_dir_all`] will fail if the `path` is *not* a directory. |
| 2985 | /// |
| 2986 | /// Consider ignoring the error if validating the removal is not required for your use case. |
| 2987 | /// |
| 2988 | /// This function may return [`io::ErrorKind::DirectoryNotEmpty`] if the directory is concurrently |
| 2989 | /// written into, which typically indicates some contents were removed but not all. |
| 2990 | /// [`io::ErrorKind::NotFound`] is only returned if no removal occurs. |
| 2991 | /// |
| 2992 | /// [`fs::remove_file`]: remove_file |
| 2993 | /// [`fs::remove_dir`]: remove_dir |
| 2994 | /// |
| 2995 | /// # Examples |
| 2996 | /// |
| 2997 | /// ```no_run |
| 2998 | /// use std::fs; |
| 2999 | /// |
| 3000 | /// fn main() -> std::io::Result<()> { |
| 3001 | /// fs::remove_dir_all("/some/dir" )?; |
| 3002 | /// Ok(()) |
| 3003 | /// } |
| 3004 | /// ``` |
| 3005 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 3006 | pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> { |
| 3007 | fs_imp::remove_dir_all(path.as_ref()) |
| 3008 | } |
| 3009 | |
| 3010 | /// Returns an iterator over the entries within a directory. |
| 3011 | /// |
| 3012 | /// The iterator will yield instances of <code>[io::Result]<[DirEntry]></code>. |
| 3013 | /// New errors may be encountered after an iterator is initially constructed. |
| 3014 | /// Entries for the current and parent directories (typically `.` and `..`) are |
| 3015 | /// skipped. |
| 3016 | /// |
| 3017 | /// # Platform-specific behavior |
| 3018 | /// |
| 3019 | /// This function currently corresponds to the `opendir` function on Unix |
| 3020 | /// and the `FindFirstFileEx` function on Windows. Advancing the iterator |
| 3021 | /// currently corresponds to `readdir` on Unix and `FindNextFile` on Windows. |
| 3022 | /// Note that, this [may change in the future][changes]. |
| 3023 | /// |
| 3024 | /// [changes]: io#platform-specific-behavior |
| 3025 | /// |
| 3026 | /// The order in which this iterator returns entries is platform and filesystem |
| 3027 | /// dependent. |
| 3028 | /// |
| 3029 | /// # Errors |
| 3030 | /// |
| 3031 | /// This function will return an error in the following situations, but is not |
| 3032 | /// limited to just these cases: |
| 3033 | /// |
| 3034 | /// * The provided `path` doesn't exist. |
| 3035 | /// * The process lacks permissions to view the contents. |
| 3036 | /// * The `path` points at a non-directory file. |
| 3037 | /// |
| 3038 | /// # Examples |
| 3039 | /// |
| 3040 | /// ``` |
| 3041 | /// use std::io; |
| 3042 | /// use std::fs::{self, DirEntry}; |
| 3043 | /// use std::path::Path; |
| 3044 | /// |
| 3045 | /// // one possible implementation of walking a directory only visiting files |
| 3046 | /// fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry)) -> io::Result<()> { |
| 3047 | /// if dir.is_dir() { |
| 3048 | /// for entry in fs::read_dir(dir)? { |
| 3049 | /// let entry = entry?; |
| 3050 | /// let path = entry.path(); |
| 3051 | /// if path.is_dir() { |
| 3052 | /// visit_dirs(&path, cb)?; |
| 3053 | /// } else { |
| 3054 | /// cb(&entry); |
| 3055 | /// } |
| 3056 | /// } |
| 3057 | /// } |
| 3058 | /// Ok(()) |
| 3059 | /// } |
| 3060 | /// ``` |
| 3061 | /// |
| 3062 | /// ```rust,no_run |
| 3063 | /// use std::{fs, io}; |
| 3064 | /// |
| 3065 | /// fn main() -> io::Result<()> { |
| 3066 | /// let mut entries = fs::read_dir("." )? |
| 3067 | /// .map(|res| res.map(|e| e.path())) |
| 3068 | /// .collect::<Result<Vec<_>, io::Error>>()?; |
| 3069 | /// |
| 3070 | /// // The order in which `read_dir` returns entries is not guaranteed. If reproducible |
| 3071 | /// // ordering is required the entries should be explicitly sorted. |
| 3072 | /// |
| 3073 | /// entries.sort(); |
| 3074 | /// |
| 3075 | /// // The entries have now been sorted by their path. |
| 3076 | /// |
| 3077 | /// Ok(()) |
| 3078 | /// } |
| 3079 | /// ``` |
| 3080 | #[doc (alias = "ls" , alias = "opendir" , alias = "FindFirstFile" , alias = "FindNextFile" )] |
| 3081 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 3082 | pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> { |
| 3083 | fs_imp::read_dir(path.as_ref()).map(op:ReadDir) |
| 3084 | } |
| 3085 | |
| 3086 | /// Changes the permissions found on a file or a directory. |
| 3087 | /// |
| 3088 | /// # Platform-specific behavior |
| 3089 | /// |
| 3090 | /// This function currently corresponds to the `chmod` function on Unix |
| 3091 | /// and the `SetFileAttributes` function on Windows. |
| 3092 | /// Note that, this [may change in the future][changes]. |
| 3093 | /// |
| 3094 | /// [changes]: io#platform-specific-behavior |
| 3095 | /// |
| 3096 | /// ## Symlinks |
| 3097 | /// On UNIX-like systems, this function will update the permission bits |
| 3098 | /// of the file pointed to by the symlink. |
| 3099 | /// |
| 3100 | /// Note that this behavior can lead to privalage escalation vulnerabilites, |
| 3101 | /// where the ability to create a symlink in one directory allows you to |
| 3102 | /// cause the permissions of another file or directory to be modified. |
| 3103 | /// |
| 3104 | /// For this reason, using this function with symlinks should be avoided. |
| 3105 | /// When possible, permissions should be set at creation time instead. |
| 3106 | /// |
| 3107 | /// # Rationale |
| 3108 | /// POSIX does not specify an `lchmod` function, |
| 3109 | /// and symlinks can be followed regardless of what permission bits are set. |
| 3110 | /// |
| 3111 | /// # Errors |
| 3112 | /// |
| 3113 | /// This function will return an error in the following situations, but is not |
| 3114 | /// limited to just these cases: |
| 3115 | /// |
| 3116 | /// * `path` does not exist. |
| 3117 | /// * The user lacks the permission to change attributes of the file. |
| 3118 | /// |
| 3119 | /// # Examples |
| 3120 | /// |
| 3121 | /// ```no_run |
| 3122 | /// use std::fs; |
| 3123 | /// |
| 3124 | /// fn main() -> std::io::Result<()> { |
| 3125 | /// let mut perms = fs::metadata("foo.txt" )?.permissions(); |
| 3126 | /// perms.set_readonly(true); |
| 3127 | /// fs::set_permissions("foo.txt" , perms)?; |
| 3128 | /// Ok(()) |
| 3129 | /// } |
| 3130 | /// ``` |
| 3131 | #[doc (alias = "chmod" , alias = "SetFileAttributes" )] |
| 3132 | #[stable (feature = "set_permissions" , since = "1.1.0" )] |
| 3133 | pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> { |
| 3134 | fs_imp::set_permissions(path.as_ref(), perm.0) |
| 3135 | } |
| 3136 | |
| 3137 | impl DirBuilder { |
| 3138 | /// Creates a new set of options with default mode/security settings for all |
| 3139 | /// platforms and also non-recursive. |
| 3140 | /// |
| 3141 | /// # Examples |
| 3142 | /// |
| 3143 | /// ``` |
| 3144 | /// use std::fs::DirBuilder; |
| 3145 | /// |
| 3146 | /// let builder = DirBuilder::new(); |
| 3147 | /// ``` |
| 3148 | #[stable (feature = "dir_builder" , since = "1.6.0" )] |
| 3149 | #[must_use ] |
| 3150 | pub fn new() -> DirBuilder { |
| 3151 | DirBuilder { inner: fs_imp::DirBuilder::new(), recursive: false } |
| 3152 | } |
| 3153 | |
| 3154 | /// Indicates that directories should be created recursively, creating all |
| 3155 | /// parent directories. Parents that do not exist are created with the same |
| 3156 | /// security and permissions settings. |
| 3157 | /// |
| 3158 | /// This option defaults to `false`. |
| 3159 | /// |
| 3160 | /// # Examples |
| 3161 | /// |
| 3162 | /// ``` |
| 3163 | /// use std::fs::DirBuilder; |
| 3164 | /// |
| 3165 | /// let mut builder = DirBuilder::new(); |
| 3166 | /// builder.recursive(true); |
| 3167 | /// ``` |
| 3168 | #[stable (feature = "dir_builder" , since = "1.6.0" )] |
| 3169 | pub fn recursive(&mut self, recursive: bool) -> &mut Self { |
| 3170 | self.recursive = recursive; |
| 3171 | self |
| 3172 | } |
| 3173 | |
| 3174 | /// Creates the specified directory with the options configured in this |
| 3175 | /// builder. |
| 3176 | /// |
| 3177 | /// It is considered an error if the directory already exists unless |
| 3178 | /// recursive mode is enabled. |
| 3179 | /// |
| 3180 | /// # Examples |
| 3181 | /// |
| 3182 | /// ```no_run |
| 3183 | /// use std::fs::{self, DirBuilder}; |
| 3184 | /// |
| 3185 | /// let path = "/tmp/foo/bar/baz" ; |
| 3186 | /// DirBuilder::new() |
| 3187 | /// .recursive(true) |
| 3188 | /// .create(path).unwrap(); |
| 3189 | /// |
| 3190 | /// assert!(fs::metadata(path).unwrap().is_dir()); |
| 3191 | /// ``` |
| 3192 | #[stable (feature = "dir_builder" , since = "1.6.0" )] |
| 3193 | pub fn create<P: AsRef<Path>>(&self, path: P) -> io::Result<()> { |
| 3194 | self._create(path.as_ref()) |
| 3195 | } |
| 3196 | |
| 3197 | fn _create(&self, path: &Path) -> io::Result<()> { |
| 3198 | if self.recursive { self.create_dir_all(path) } else { self.inner.mkdir(path) } |
| 3199 | } |
| 3200 | |
| 3201 | fn create_dir_all(&self, path: &Path) -> io::Result<()> { |
| 3202 | if path == Path::new("" ) { |
| 3203 | return Ok(()); |
| 3204 | } |
| 3205 | |
| 3206 | match self.inner.mkdir(path) { |
| 3207 | Ok(()) => return Ok(()), |
| 3208 | Err(ref e) if e.kind() == io::ErrorKind::NotFound => {} |
| 3209 | Err(_) if path.is_dir() => return Ok(()), |
| 3210 | Err(e) => return Err(e), |
| 3211 | } |
| 3212 | match path.parent() { |
| 3213 | Some(p) => self.create_dir_all(p)?, |
| 3214 | None => { |
| 3215 | return Err(io::const_error!( |
| 3216 | io::ErrorKind::Uncategorized, |
| 3217 | "failed to create whole tree" , |
| 3218 | )); |
| 3219 | } |
| 3220 | } |
| 3221 | match self.inner.mkdir(path) { |
| 3222 | Ok(()) => Ok(()), |
| 3223 | Err(_) if path.is_dir() => Ok(()), |
| 3224 | Err(e) => Err(e), |
| 3225 | } |
| 3226 | } |
| 3227 | } |
| 3228 | |
| 3229 | impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder { |
| 3230 | #[inline ] |
| 3231 | fn as_inner_mut(&mut self) -> &mut fs_imp::DirBuilder { |
| 3232 | &mut self.inner |
| 3233 | } |
| 3234 | } |
| 3235 | |
| 3236 | /// Returns `Ok(true)` if the path points at an existing entity. |
| 3237 | /// |
| 3238 | /// This function will traverse symbolic links to query information about the |
| 3239 | /// destination file. In case of broken symbolic links this will return `Ok(false)`. |
| 3240 | /// |
| 3241 | /// As opposed to the [`Path::exists`] method, this will only return `Ok(true)` or `Ok(false)` |
| 3242 | /// if the path was _verified_ to exist or not exist. If its existence can neither be confirmed |
| 3243 | /// nor denied, an `Err(_)` will be propagated instead. This can be the case if e.g. listing |
| 3244 | /// permission is denied on one of the parent directories. |
| 3245 | /// |
| 3246 | /// Note that while this avoids some pitfalls of the `exists()` method, it still can not |
| 3247 | /// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios |
| 3248 | /// where those bugs are not an issue. |
| 3249 | /// |
| 3250 | /// # Examples |
| 3251 | /// |
| 3252 | /// ```no_run |
| 3253 | /// use std::fs; |
| 3254 | /// |
| 3255 | /// assert!(!fs::exists("does_not_exist.txt" ).expect("Can't check existence of file does_not_exist.txt" )); |
| 3256 | /// assert!(fs::exists("/root/secret_file.txt" ).is_err()); |
| 3257 | /// ``` |
| 3258 | /// |
| 3259 | /// [`Path::exists`]: crate::path::Path::exists |
| 3260 | #[stable (feature = "fs_try_exists" , since = "1.81.0" )] |
| 3261 | #[inline ] |
| 3262 | pub fn exists<P: AsRef<Path>>(path: P) -> io::Result<bool> { |
| 3263 | fs_imp::exists(path.as_ref()) |
| 3264 | } |
| 3265 | |