std\sys\fs\windows/
dir.rs1use crate::os::windows::io::{
2 AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, HandleOrInvalid, IntoRawHandle,
3 OwnedHandle, RawHandle,
4};
5use crate::path::Path;
6use crate::sys::api::{UnicodeStrRef, WinError};
7use crate::sys::fs::windows::debug_path_handle;
8use crate::sys::fs::{File, FileAttr, OpenOptions};
9use crate::sys::handle::Handle;
10use crate::sys::path::{WCStr, with_native_path};
11use crate::sys::{AsInner, FromInner, IntoInner, IoResult, c, to_u16s};
12use crate::{fmt, fs, io, ptr};
13
14pub struct Dir {
15 handle: Handle,
16}
17
18unsafe fn nt_create_file(
22 opts: &OpenOptions,
23 object_attributes: &c::OBJECT_ATTRIBUTES,
24 create_options: c::NTCREATEFILE_CREATE_OPTIONS,
25) -> io::Result<Handle> {
26 let mut handle = ptr::null_mut();
27 let mut io_status = c::IO_STATUS_BLOCK::PENDING;
28 let access = opts.get_access_mode()? | c::SYNCHRONIZE;
30 let options = create_options | c::FILE_SYNCHRONOUS_IO_NONALERT;
32 let status = unsafe {
33 c::NtCreateFile(
34 &mut handle,
35 access,
36 object_attributes,
37 &mut io_status,
38 ptr::null(),
39 c::FILE_ATTRIBUTE_NORMAL,
40 opts.share_mode,
41 opts.get_disposition()?,
42 options,
43 ptr::null(),
44 0,
45 )
46 };
47 if c::nt_success(status) {
48 unsafe { Ok(Handle::from_raw_handle(handle)) }
50 } else {
51 Err(WinError::new(unsafe { c::RtlNtStatusToDosError(status) })).io_result()
52 }
53}
54
55impl Dir {
56 pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<Self> {
57 with_native_path(path, &|path| Self::open_with_native(path, opts))
58 }
59
60 pub fn open_file(&self, path: &Path, opts: &OpenOptions) -> io::Result<File> {
61 if path.is_absolute() {
63 return File::open(path, opts);
64 }
65 let path = to_u16s(path)?;
66 let path = &path[..path.len() - 1]; self.open_file_native(&path, opts).map(|handle| File { handle })
68 }
69
70 fn open_with_native(path: &WCStr, opts: &OpenOptions) -> io::Result<Self> {
71 let creation = opts.get_creation_mode()?;
72 let sa = c::SECURITY_ATTRIBUTES {
73 nLength: size_of::<c::SECURITY_ATTRIBUTES>() as u32,
74 lpSecurityDescriptor: ptr::null_mut(),
75 bInheritHandle: opts.inherit_handle as c::BOOL,
76 };
77 let handle = unsafe {
78 c::CreateFileW(
79 path.as_ptr(),
80 opts.get_access_mode()?,
81 opts.share_mode,
82 &raw const sa,
83 creation,
84 opts.get_flags_and_attributes() | c::FILE_FLAG_BACKUP_SEMANTICS,
86 ptr::null_mut(),
87 )
88 };
89 match OwnedHandle::try_from(unsafe { HandleOrInvalid::from_raw_handle(handle) }) {
90 Ok(handle) => Ok(Self { handle: Handle::from_inner(handle) }),
91 Err(_) => Err(io::Error::last_os_error()),
92 }
93 }
94
95 fn open_file_native(&self, path: &[u16], opts: &OpenOptions) -> io::Result<Handle> {
96 let name = UnicodeStrRef::from_slice(path);
97 let object_attributes = c::OBJECT_ATTRIBUTES {
98 RootDirectory: self.handle.as_raw_handle(),
99 ObjectName: name.as_ptr(),
100 ..c::OBJECT_ATTRIBUTES::with_length()
101 };
102 unsafe { nt_create_file(opts, &object_attributes, c::FILE_NON_DIRECTORY_FILE) }
103 }
104
105 pub fn metadata(&self) -> io::Result<FileAttr> {
106 let handle = self.handle.as_raw_handle();
108 let f = core::mem::ManuallyDrop::new(File {
109 handle: unsafe { Handle::from_raw_handle(handle) },
111 });
112 f.file_attr()
113 }
114}
115
116impl fmt::Debug for Dir {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 let mut b = debug_path_handle(self.handle.as_handle(), f, "Dir");
119 b.finish()
120 }
121}
122
123#[unstable(feature = "dirfd", issue = "120426")]
124impl AsRawHandle for fs::Dir {
125 fn as_raw_handle(&self) -> RawHandle {
126 self.as_inner().handle.as_raw_handle()
127 }
128}
129
130#[unstable(feature = "dirhandle", issue = "120426")]
131impl IntoRawHandle for fs::Dir {
132 fn into_raw_handle(self) -> RawHandle {
133 self.into_inner().handle.into_raw_handle()
134 }
135}
136
137#[unstable(feature = "dirhandle", issue = "120426")]
138impl FromRawHandle for fs::Dir {
139 unsafe fn from_raw_handle(handle: RawHandle) -> Self {
140 Self::from_inner(Dir { handle: unsafe { FromRawHandle::from_raw_handle(handle) } })
141 }
142}
143
144#[unstable(feature = "dirhandle", issue = "120426")]
145impl AsHandle for fs::Dir {
146 fn as_handle(&self) -> BorrowedHandle<'_> {
147 self.as_inner().handle.as_handle()
148 }
149}
150
151#[unstable(feature = "dirhandle", issue = "120426")]
152impl From<fs::Dir> for OwnedHandle {
153 fn from(value: fs::Dir) -> Self {
154 value.into_inner().handle.into_inner()
155 }
156}
157
158#[unstable(feature = "dirhandle", issue = "120426")]
159impl From<OwnedHandle> for fs::Dir {
160 fn from(value: OwnedHandle) -> Self {
161 Self::from_inner(Dir { handle: Handle::from_inner(value) })
162 }
163}