summaryrefslogtreecommitdiffstats
path: root/vendor/tempfile/src/file
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/tempfile/src/file')
-rw-r--r--vendor/tempfile/src/file/imp/other.rs4
-rw-r--r--vendor/tempfile/src/file/imp/unix.rs85
-rw-r--r--vendor/tempfile/src/file/imp/windows.rs13
-rw-r--r--vendor/tempfile/src/file/mod.rs151
4 files changed, 133 insertions, 120 deletions
diff --git a/vendor/tempfile/src/file/imp/other.rs b/vendor/tempfile/src/file/imp/other.rs
index d8a55a745..8721d2da6 100644
--- a/vendor/tempfile/src/file/imp/other.rs
+++ b/vendor/tempfile/src/file/imp/other.rs
@@ -9,7 +9,7 @@ fn not_supported<T>() -> io::Result<T> {
))
}
-pub fn create_named(_path: &Path, open_options: &mut OpenOptions) -> io::Result<File> {
+pub fn create_named(_path: &Path, _open_options: &mut OpenOptions) -> io::Result<File> {
not_supported()
}
@@ -25,6 +25,6 @@ pub fn persist(_old_path: &Path, _new_path: &Path, _overwrite: bool) -> io::Resu
not_supported()
}
-pub fn keep(path: &Path) -> io::Result<()> {
+pub fn keep(_path: &Path) -> io::Result<()> {
not_supported()
}
diff --git a/vendor/tempfile/src/file/imp/unix.rs b/vendor/tempfile/src/file/imp/unix.rs
index 480743cf7..c305ea95e 100644
--- a/vendor/tempfile/src/file/imp/unix.rs
+++ b/vendor/tempfile/src/file/imp/unix.rs
@@ -1,13 +1,11 @@
use std::env;
-use std::ffi::{CString, OsStr};
+use std::ffi::OsStr;
use std::fs::{self, File, OpenOptions};
use std::io;
cfg_if::cfg_if! {
if #[cfg(not(target_os = "wasi"))] {
- use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::{MetadataExt, OpenOptionsExt};
} else {
- use std::os::wasi::ffi::OsStrExt;
#[cfg(feature = "nightly")]
use std::os::wasi::fs::MetadataExt;
}
@@ -16,29 +14,7 @@ use crate::util;
use std::path::Path;
#[cfg(not(target_os = "redox"))]
-use libc::{c_char, c_int, link, rename, unlink};
-
-#[cfg(not(target_os = "redox"))]
-#[inline(always)]
-pub fn cvt_err(result: c_int) -> io::Result<c_int> {
- if result == -1 {
- Err(io::Error::last_os_error())
- } else {
- Ok(result)
- }
-}
-
-#[cfg(target_os = "redox")]
-#[inline(always)]
-pub fn cvt_err(result: Result<usize, syscall::Error>) -> io::Result<usize> {
- result.map_err(|err| io::Error::from_raw_os_error(err.errno))
-}
-
-// Stolen from std.
-pub fn cstr(path: &Path) -> io::Result<CString> {
- CString::new(path.as_os_str().as_bytes())
- .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "path contained a null"))
-}
+use rustix::fs::{cwd, linkat, renameat, unlinkat, AtFlags};
pub fn create_named(path: &Path, open_options: &mut OpenOptions) -> io::Result<File> {
open_options.read(true).write(true).create_new(true);
@@ -70,16 +46,18 @@ fn create_unlinked(path: &Path) -> io::Result<File> {
#[cfg(target_os = "linux")]
pub fn create(dir: &Path) -> io::Result<File> {
- use libc::{EISDIR, ENOENT, EOPNOTSUPP, O_TMPFILE};
+ use rustix::{fs::OFlags, io::Errno};
OpenOptions::new()
.read(true)
.write(true)
- .custom_flags(O_TMPFILE) // do not mix with `create_new(true)`
+ .custom_flags(OFlags::TMPFILE.bits() as i32) // do not mix with `create_new(true)`
.open(dir)
.or_else(|e| {
- match e.raw_os_error() {
+ match Errno::from_io_error(&e) {
// These are the three "not supported" error codes for O_TMPFILE.
- Some(EOPNOTSUPP) | Some(EISDIR) | Some(ENOENT) => create_unix(dir),
+ Some(Errno::OPNOTSUPP) | Some(Errno::ISDIR) | Some(Errno::NOENT) => {
+ create_unix(dir)
+ }
_ => Err(e),
}
})
@@ -124,29 +102,40 @@ pub fn reopen(_file: &File, _path: &Path) -> io::Result<File> {
#[cfg(not(target_os = "redox"))]
pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result<()> {
- unsafe {
- let old_path = cstr(old_path)?;
- let new_path = cstr(new_path)?;
- if overwrite {
- cvt_err(rename(
- old_path.as_ptr() as *const c_char,
- new_path.as_ptr() as *const c_char,
- ))?;
- } else {
- cvt_err(link(
- old_path.as_ptr() as *const c_char,
- new_path.as_ptr() as *const c_char,
- ))?;
- // Ignore unlink errors. Can we do better?
- // On recent linux, we can use renameat2 to do this atomically.
- let _ = unlink(old_path.as_ptr() as *const c_char);
+ if overwrite {
+ renameat(cwd(), old_path, cwd(), new_path)?;
+ } else {
+ // On Linux, use `renameat_with` to avoid overwriting an existing name,
+ // if the kernel and the filesystem support it.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ {
+ use rustix::fs::{renameat_with, RenameFlags};
+ use rustix::io::Errno;
+ use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
+
+ static NOSYS: AtomicBool = AtomicBool::new(false);
+ if !NOSYS.load(Relaxed) {
+ match renameat_with(cwd(), old_path, cwd(), new_path, RenameFlags::NOREPLACE) {
+ Ok(()) => return Ok(()),
+ Err(Errno::NOSYS) => NOSYS.store(true, Relaxed),
+ Err(Errno::INVAL) => {}
+ Err(e) => return Err(e.into()),
+ }
+ }
}
- Ok(())
+
+ // Otherwise use `linkat` to create the new filesystem name, which
+ // will fail if the name already exists, and then `unlinkat` to remove
+ // the old name.
+ linkat(cwd(), old_path, cwd(), new_path, AtFlags::empty())?;
+ // Ignore unlink errors. Can we do better?
+ let _ = unlinkat(cwd(), old_path, AtFlags::empty());
}
+ Ok(())
}
#[cfg(target_os = "redox")]
-pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result<()> {
+pub fn persist(_old_path: &Path, _new_path: &Path, _overwrite: bool) -> io::Result<()> {
// XXX implement when possible
Err(io::Error::from_raw_os_error(syscall::ENOSYS))
}
diff --git a/vendor/tempfile/src/file/imp/windows.rs b/vendor/tempfile/src/file/imp/windows.rs
index 71b474880..cb2673b5a 100644
--- a/vendor/tempfile/src/file/imp/windows.rs
+++ b/vendor/tempfile/src/file/imp/windows.rs
@@ -6,13 +6,12 @@ use std::os::windows::io::{AsRawHandle, FromRawHandle, RawHandle};
use std::path::Path;
use std::{io, iter};
-use winapi::um::fileapi::SetFileAttributesW;
-use winapi::um::handleapi::INVALID_HANDLE_VALUE;
-use winapi::um::winbase::{MoveFileExW, ReOpenFile};
-use winapi::um::winbase::{FILE_FLAG_DELETE_ON_CLOSE, MOVEFILE_REPLACE_EXISTING};
-use winapi::um::winnt::{FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_TEMPORARY};
-use winapi::um::winnt::{FILE_GENERIC_READ, FILE_GENERIC_WRITE, HANDLE};
-use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
+use windows_sys::Win32::Foundation::{HANDLE, INVALID_HANDLE_VALUE};
+use windows_sys::Win32::Storage::FileSystem::{
+ MoveFileExW, ReOpenFile, SetFileAttributesW, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_TEMPORARY,
+ FILE_FLAG_DELETE_ON_CLOSE, FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_SHARE_DELETE,
+ FILE_SHARE_READ, FILE_SHARE_WRITE, MOVEFILE_REPLACE_EXISTING,
+};
use crate::util;
diff --git a/vendor/tempfile/src/file/mod.rs b/vendor/tempfile/src/file/mod.rs
index b859ced79..023acd26a 100644
--- a/vendor/tempfile/src/file/mod.rs
+++ b/vendor/tempfile/src/file/mod.rs
@@ -52,7 +52,7 @@ mod imp;
///
/// [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html
pub fn tempfile() -> io::Result<File> {
- tempfile_in(&env::temp_dir())
+ tempfile_in(env::temp_dir())
}
/// Create a new temporary file in the specified directory.
@@ -467,29 +467,31 @@ impl AsRef<OsStr> for TempPath {
/// # Resource Leaking
///
/// If the program exits before the `NamedTempFile` destructor is
-/// run, such as via [`std::process::exit()`], by segfaulting, or by
-/// receiving a signal like `SIGINT`, then the temporary file
-/// will not be deleted.
+/// run, the temporary file will not be deleted. This can happen
+/// if the process exits using [`std::process::exit()`], a segfault occurs,
+/// receiving an interrupt signal like `SIGINT` that is not handled, or by using
+/// a statically declared `NamedTempFile` instance (like with [`lazy_static`]).
///
-/// Use the [`tempfile()`] function unless you absolutely need a named file.
+/// Use the [`tempfile()`] function unless you need a named file path.
///
/// [`tempfile()`]: fn.tempfile.html
/// [`NamedTempFile::new()`]: #method.new
/// [`NamedTempFile::new_in()`]: #method.new_in
/// [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html
/// [`std::process::exit()`]: http://doc.rust-lang.org/std/process/fn.exit.html
-pub struct NamedTempFile {
+/// [`lazy_static`]: https://github.com/rust-lang-nursery/lazy-static.rs/issues/62
+pub struct NamedTempFile<F = File> {
path: TempPath,
- file: File,
+ file: F,
}
-impl fmt::Debug for NamedTempFile {
+impl<F> fmt::Debug for NamedTempFile<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "NamedTempFile({:?})", self.path)
}
}
-impl AsRef<Path> for NamedTempFile {
+impl<F> AsRef<Path> for NamedTempFile<F> {
#[inline]
fn as_ref(&self) -> &Path {
self.path()
@@ -497,41 +499,46 @@ impl AsRef<Path> for NamedTempFile {
}
/// Error returned when persisting a temporary file fails.
-#[derive(Debug)]
-pub struct PersistError {
+pub struct PersistError<F = File> {
/// The underlying IO error.
pub error: io::Error,
/// The temporary file that couldn't be persisted.
- pub file: NamedTempFile,
+ pub file: NamedTempFile<F>,
+}
+
+impl<F> fmt::Debug for PersistError<F> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "PersistError({:?})", self.error)
+ }
}
-impl From<PersistError> for io::Error {
+impl<F> From<PersistError<F>> for io::Error {
#[inline]
- fn from(error: PersistError) -> io::Error {
+ fn from(error: PersistError<F>) -> io::Error {
error.error
}
}
-impl From<PersistError> for NamedTempFile {
+impl<F> From<PersistError<F>> for NamedTempFile<F> {
#[inline]
- fn from(error: PersistError) -> NamedTempFile {
+ fn from(error: PersistError<F>) -> NamedTempFile<F> {
error.file
}
}
-impl fmt::Display for PersistError {
+impl<F> fmt::Display for PersistError<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "failed to persist temporary file: {}", self.error)
}
}
-impl error::Error for PersistError {
+impl<F> error::Error for PersistError<F> {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
Some(&self.error)
}
}
-impl NamedTempFile {
+impl NamedTempFile<File> {
/// Create a new named temporary file.
///
/// See [`Builder`] for more configuration.
@@ -601,7 +608,9 @@ impl NamedTempFile {
pub fn new_in<P: AsRef<Path>>(dir: P) -> io::Result<NamedTempFile> {
Builder::new().tempfile_in(dir)
}
+}
+impl<F> NamedTempFile<F> {
/// Get the temporary file's path.
///
/// # Security
@@ -711,7 +720,7 @@ impl NamedTempFile {
/// ```
///
/// [`PersistError`]: struct.PersistError.html
- pub fn persist<P: AsRef<Path>>(self, new_path: P) -> Result<File, PersistError> {
+ pub fn persist<P: AsRef<Path>>(self, new_path: P) -> Result<F, PersistError<F>> {
let NamedTempFile { path, file } = self;
match path.persist(new_path) {
Ok(_) => Ok(file),
@@ -764,7 +773,7 @@ impl NamedTempFile {
/// # Ok(())
/// # }
/// ```
- pub fn persist_noclobber<P: AsRef<Path>>(self, new_path: P) -> Result<File, PersistError> {
+ pub fn persist_noclobber<P: AsRef<Path>>(self, new_path: P) -> Result<F, PersistError<F>> {
let NamedTempFile { path, file } = self;
match path.persist_noclobber(new_path) {
Ok(_) => Ok(file),
@@ -808,7 +817,7 @@ impl NamedTempFile {
/// ```
///
/// [`PathPersistError`]: struct.PathPersistError.html
- pub fn keep(self) -> Result<(File, PathBuf), PersistError> {
+ pub fn keep(self) -> Result<(F, PathBuf), PersistError<F>> {
let (file, path) = (self.file, self.path);
match path.keep() {
Ok(path) => Ok((file, path)),
@@ -819,6 +828,49 @@ impl NamedTempFile {
}
}
+ /// Get a reference to the underlying file.
+ pub fn as_file(&self) -> &F {
+ &self.file
+ }
+
+ /// Get a mutable reference to the underlying file.
+ pub fn as_file_mut(&mut self) -> &mut F {
+ &mut self.file
+ }
+
+ /// Convert the temporary file into a `std::fs::File`.
+ ///
+ /// The inner file will be deleted.
+ pub fn into_file(self) -> F {
+ self.file
+ }
+
+ /// Closes the file, leaving only the temporary file path.
+ ///
+ /// This is useful when another process must be able to open the temporary
+ /// file.
+ pub fn into_temp_path(self) -> TempPath {
+ self.path
+ }
+
+ /// Converts the named temporary file into its constituent parts.
+ ///
+ /// Note: When the path is dropped, the file is deleted but the file handle
+ /// is still usable.
+ pub fn into_parts(self) -> (F, TempPath) {
+ (self.file, self.path)
+ }
+
+ /// Creates a `NamedTempFile` from its constituent parts.
+ ///
+ /// This can be used with [`NamedTempFile::into_parts`] to reconstruct the
+ /// `NamedTempFile`.
+ pub fn from_parts(file: F, path: TempPath) -> Self {
+ Self { file, path }
+ }
+}
+
+impl NamedTempFile<File> {
/// Securely reopen the temporary file.
///
/// This function is useful when you need multiple independent handles to
@@ -858,54 +910,21 @@ impl NamedTempFile {
imp::reopen(self.as_file(), NamedTempFile::path(self))
.with_err_path(|| NamedTempFile::path(self))
}
-
- /// Get a reference to the underlying file.
- pub fn as_file(&self) -> &File {
- &self.file
- }
-
- /// Get a mutable reference to the underlying file.
- pub fn as_file_mut(&mut self) -> &mut File {
- &mut self.file
- }
-
- /// Convert the temporary file into a `std::fs::File`.
- ///
- /// The inner file will be deleted.
- pub fn into_file(self) -> File {
- self.file
- }
-
- /// Closes the file, leaving only the temporary file path.
- ///
- /// This is useful when another process must be able to open the temporary
- /// file.
- pub fn into_temp_path(self) -> TempPath {
- self.path
- }
-
- /// Converts the named temporary file into its constituent parts.
- ///
- /// Note: When the path is dropped, the file is deleted but the file handle
- /// is still usable.
- pub fn into_parts(self) -> (File, TempPath) {
- (self.file, self.path)
- }
}
-impl Read for NamedTempFile {
+impl<F: Read> Read for NamedTempFile<F> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.as_file_mut().read(buf).with_err_path(|| self.path())
}
}
-impl<'a> Read for &'a NamedTempFile {
+impl Read for &NamedTempFile<File> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.as_file().read(buf).with_err_path(|| self.path())
}
}
-impl Write for NamedTempFile {
+impl<F: Write> Write for NamedTempFile<F> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.as_file_mut().write(buf).with_err_path(|| self.path())
}
@@ -915,7 +934,7 @@ impl Write for NamedTempFile {
}
}
-impl<'a> Write for &'a NamedTempFile {
+impl Write for &NamedTempFile<File> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.as_file().write(buf).with_err_path(|| self.path())
}
@@ -925,20 +944,23 @@ impl<'a> Write for &'a NamedTempFile {
}
}
-impl Seek for NamedTempFile {
+impl<F: Seek> Seek for NamedTempFile<F> {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
self.as_file_mut().seek(pos).with_err_path(|| self.path())
}
}
-impl<'a> Seek for &'a NamedTempFile {
+impl Seek for &NamedTempFile<File> {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
self.as_file().seek(pos).with_err_path(|| self.path())
}
}
#[cfg(unix)]
-impl std::os::unix::io::AsRawFd for NamedTempFile {
+impl<F> std::os::unix::io::AsRawFd for NamedTempFile<F>
+where
+ F: std::os::unix::io::AsRawFd,
+{
#[inline]
fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
self.as_file().as_raw_fd()
@@ -946,7 +968,10 @@ impl std::os::unix::io::AsRawFd for NamedTempFile {
}
#[cfg(windows)]
-impl std::os::windows::io::AsRawHandle for NamedTempFile {
+impl<F> std::os::windows::io::AsRawHandle for NamedTempFile<F>
+where
+ F: std::os::windows::io::AsRawHandle,
+{
#[inline]
fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
self.as_file().as_raw_handle()