3 use std
::os
::windows
::ffi
::OsStrExt
;
4 use std
::os
::windows
::io
::{AsRawHandle, FromRawHandle, RawHandle}
;
8 use winapi
::shared
::minwindef
::DWORD
;
9 use winapi
::um
::fileapi
::{CreateFileW, SetFileAttributesW, CREATE_NEW}
;
10 use winapi
::um
::handleapi
::INVALID_HANDLE_VALUE
;
11 use winapi
::um
::winbase
::{FILE_FLAG_DELETE_ON_CLOSE, MOVEFILE_REPLACE_EXISTING}
;
12 use winapi
::um
::winbase
::{MoveFileExW, ReOpenFile}
;
13 use winapi
::um
::winnt
::{FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_TEMPORARY}
;
14 use winapi
::um
::winnt
::{FILE_GENERIC_READ, FILE_GENERIC_WRITE, HANDLE}
;
15 use winapi
::um
::winnt
::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE}
;
19 #[cfg_attr(irustfmt, rustfmt_skip)]
20 const ACCESS
: DWORD
= FILE_GENERIC_READ
22 #[cfg_attr(irustfmt, rustfmt_skip)]
23 const SHARE_MODE
: DWORD
= FILE_SHARE_DELETE
26 #[cfg_attr(irustfmt, rustfmt_skip)]
27 const FLAGS
: DWORD
= FILE_ATTRIBUTE_HIDDEN
28 | FILE_ATTRIBUTE_TEMPORARY
;
30 fn to_utf16(s
: &Path
) -> Vec
<u16> {
33 .chain(Some(0).into_iter())
43 ) -> io
::Result
<File
> {
44 let path
= to_utf16(path
);
56 if handle
== INVALID_HANDLE_VALUE
{
57 Err(io
::Error
::last_os_error())
59 Ok(unsafe { File::from_raw_handle(handle as RawHandle) }
)
63 pub fn create_named(path
: &Path
) -> io
::Result
<File
> {
64 win_create(path
, ACCESS
, SHARE_MODE
, CREATE_NEW
, FLAGS
)
67 pub fn create(dir
: &Path
) -> io
::Result
<File
> {
68 util
::create_helper(dir
, ".tmp", "", ::NUM_RAND_CHARS
, |path
| {
74 FLAGS
| FILE_FLAG_DELETE_ON_CLOSE
,
79 pub fn reopen(file
: &File
, _path
: &Path
) -> io
::Result
<File
> {
80 let handle
= file
.as_raw_handle();
82 let handle
= ReOpenFile(handle
as HANDLE
, ACCESS
, SHARE_MODE
, 0);
83 if handle
== INVALID_HANDLE_VALUE
{
84 Err(io
::Error
::last_os_error())
86 Ok(FromRawHandle
::from_raw_handle(handle
as RawHandle
))
91 pub fn persist(old_path
: &Path
, new_path
: &Path
, overwrite
: bool
) -> io
::Result
<()> {
92 // TODO: We should probably do this in one-shot using SetFileInformationByHandle but the API is
96 let old_path_w
= to_utf16(old_path
);
97 let new_path_w
= to_utf16(new_path
);
99 // Don't succeed if this fails. We don't want to claim to have successfully persisted a file
100 // still marked as temporary because this file won't have the same consistency guarantees.
101 if SetFileAttributesW(old_path_w
.as_ptr(), FILE_ATTRIBUTE_NORMAL
) == 0 {
102 return Err(io
::Error
::last_os_error());
108 flags
|= MOVEFILE_REPLACE_EXISTING
;
111 if MoveFileExW(old_path_w
.as_ptr(), new_path_w
.as_ptr(), flags
) == 0 {
112 let e
= io
::Error
::last_os_error();
113 // If this fails, the temporary file is now un-hidden and no longer marked temporary
114 // (slightly less efficient) but it will still work.
115 let _
= SetFileAttributesW(old_path_w
.as_ptr(), FLAGS
);