]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/windows/handle.rs
Implement reading and writing atomically at certain offsets
[rust.git] / src / libstd / sys / windows / handle.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![unstable(issue = "0", feature = "windows_handle")]
12
13 use cmp;
14 use io::{ErrorKind, Read};
15 use io;
16 use mem;
17 use ops::Deref;
18 use ptr;
19 use sys::c;
20 use sys::cvt;
21 use sys_common::io::read_to_end_uninitialized;
22 use u32;
23
24 /// An owned container for `HANDLE` object, closing them on Drop.
25 ///
26 /// All methods are inherited through a `Deref` impl to `RawHandle`
27 pub struct Handle(RawHandle);
28
29 /// A wrapper type for `HANDLE` objects to give them proper Send/Sync inference
30 /// as well as Rust-y methods.
31 ///
32 /// This does **not** drop the handle when it goes out of scope, use `Handle`
33 /// instead for that.
34 #[derive(Copy, Clone)]
35 pub struct RawHandle(c::HANDLE);
36
37 unsafe impl Send for RawHandle {}
38 unsafe impl Sync for RawHandle {}
39
40 impl Handle {
41     pub fn new(handle: c::HANDLE) -> Handle {
42         Handle(RawHandle::new(handle))
43     }
44
45     pub fn new_event(manual: bool, init: bool) -> io::Result<Handle> {
46         unsafe {
47             let event = c::CreateEventW(ptr::null_mut(),
48                                         manual as c::BOOL,
49                                         init as c::BOOL,
50                                         ptr::null());
51             if event.is_null() {
52                 Err(io::Error::last_os_error())
53             } else {
54                 Ok(Handle::new(event))
55             }
56         }
57     }
58
59     pub fn into_raw(self) -> c::HANDLE {
60         let ret = self.raw();
61         mem::forget(self);
62         return ret;
63     }
64 }
65
66 impl Deref for Handle {
67     type Target = RawHandle;
68     fn deref(&self) -> &RawHandle { &self.0 }
69 }
70
71 impl Drop for Handle {
72     fn drop(&mut self) {
73         unsafe { let _ = c::CloseHandle(self.raw()); }
74     }
75 }
76
77 impl RawHandle {
78     pub fn new(handle: c::HANDLE) -> RawHandle {
79         RawHandle(handle)
80     }
81
82     pub fn raw(&self) -> c::HANDLE { self.0 }
83
84     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
85         let mut read = 0;
86         // ReadFile takes a DWORD (u32) for the length so it only supports
87         // reading u32::MAX bytes at a time.
88         let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
89         let res = cvt(unsafe {
90             c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
91                         len, &mut read, ptr::null_mut())
92         });
93
94         match res {
95             Ok(_) => Ok(read as usize),
96
97             // The special treatment of BrokenPipe is to deal with Windows
98             // pipe semantics, which yields this error when *reading* from
99             // a pipe after the other end has closed; we interpret that as
100             // EOF on the pipe.
101             Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(0),
102
103             Err(e) => Err(e)
104         }
105     }
106
107     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
108         let mut read = 0;
109         let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
110         let res = unsafe {
111             let mut overlapped: c::OVERLAPPED = mem::zeroed();
112             overlapped.Offset = offset as u32;
113             overlapped.OffsetHigh = (offset >> 32) as u32;
114             cvt(c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
115                             len, &mut read, &mut overlapped))
116         };
117         match res {
118             Ok(_) => Ok(read as usize),
119             Err(ref e) if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) => Ok(0),
120             Err(e) => Err(e),
121         }
122     }
123
124     pub unsafe fn read_overlapped(&self,
125                                   buf: &mut [u8],
126                                   overlapped: *mut c::OVERLAPPED)
127                                   -> io::Result<Option<usize>> {
128         let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
129         let mut amt = 0;
130         let res = cvt({
131             c::ReadFile(self.0, buf.as_ptr() as c::LPVOID,
132                         len, &mut amt, overlapped)
133         });
134         match res {
135             Ok(_) => Ok(Some(amt as usize)),
136             Err(e) => {
137                 if e.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) {
138                     Ok(None)
139                 } else if e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) {
140                     Ok(Some(0))
141                 } else {
142                     Err(e)
143                 }
144             }
145         }
146     }
147
148     pub fn overlapped_result(&self,
149                              overlapped: *mut c::OVERLAPPED,
150                              wait: bool) -> io::Result<usize> {
151         unsafe {
152             let mut bytes = 0;
153             let wait = if wait {c::TRUE} else {c::FALSE};
154             let res = cvt({
155                 c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait)
156             });
157             match res {
158                 Ok(_) => Ok(bytes as usize),
159                 Err(e) => {
160                     if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) ||
161                        e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) {
162                         Ok(0)
163                     } else {
164                         Err(e)
165                     }
166                 }
167             }
168         }
169     }
170
171     pub fn cancel_io(&self) -> io::Result<()> {
172         unsafe {
173             cvt(c::CancelIo(self.raw())).map(|_| ())
174         }
175     }
176
177     pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
178         let mut me = self;
179         (&mut me).read_to_end(buf)
180     }
181
182     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
183         let mut amt = 0;
184         // WriteFile takes a DWORD (u32) for the length so it only supports
185         // writing u32::MAX bytes at a time.
186         let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
187         cvt(unsafe {
188             c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
189                          len, &mut amt, ptr::null_mut())
190         })?;
191         Ok(amt as usize)
192     }
193
194     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
195         let mut written = 0;
196         let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
197         unsafe {
198             let mut overlapped: c::OVERLAPPED = mem::zeroed();
199             overlapped.Offset = offset as u32;
200             overlapped.OffsetHigh = (offset >> 32) as u32;
201             cvt(c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
202                              len, &mut written, &mut overlapped))?;
203         }
204         Ok(written as usize)
205     }
206
207     pub fn duplicate(&self, access: c::DWORD, inherit: bool,
208                      options: c::DWORD) -> io::Result<Handle> {
209         let mut ret = 0 as c::HANDLE;
210         cvt(unsafe {
211             let cur_proc = c::GetCurrentProcess();
212             c::DuplicateHandle(cur_proc, self.0, cur_proc, &mut ret,
213                             access, inherit as c::BOOL,
214                             options)
215         })?;
216         Ok(Handle::new(ret))
217     }
218 }
219
220 impl<'a> Read for &'a RawHandle {
221     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
222         (**self).read(buf)
223     }
224
225     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
226         unsafe { read_to_end_uninitialized(self, buf) }
227     }
228 }