1macro_rules! impl_physical {
2 ( $($type:ident),+ ) => {
3 $(
4 impl Read for $type {
5 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
6 let sector_size = self.geometry.bytes_per_sector;
7 if buf.len() < sector_size as usize {
8 return Err(io::Error::new(
9 io::ErrorKind::InvalidInput,
10 format!("Could not read: buffer too small, must be at least {} bytes", sector_size)
11 ));
12 } else if (buf.len() % sector_size as usize) != 0 {
13 return Err(io::Error::new(
14 io::ErrorKind::InvalidInput,
15 format!(
16 "Could not read: buffer size must be a multiple of {} but is {}",
17 sector_size, buf.len()
18 )
19 ));
20 }
21
22 let mut bytes_read = 0u32;
23 let res = unsafe {
24 fs::ReadFile(
25 self.handle,
26 buf.as_mut_ptr() as *mut c_void,
27 (buf.len() as u32 / sector_size) * sector_size,
28 &mut bytes_read,
29 null_mut()
30 )
31 };
32 if res == 0 {
33 Err(io::Error::new(
34 io::ErrorKind::Other,
35 format!(
36 "Could not read: error code {:#08x}",
37 win32::last_error()
38 )
39 ))
40 } else {
41 Ok(bytes_read as usize)
42 }
43 }
44 }
45
46 impl Seek for $type {
47 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
48 fn check_pos(s: &$type, p: u64) -> io::Result<()> {
49 if p > i64::MAX as u64 {
50 Err(io::Error::new(
51 io::ErrorKind::InvalidInput,
52 format!("can only seek to pos <= {}", i64::MAX)
53 ))
54 } else if (p % s.geometry.bytes_per_sector as u64) != 0 {
55 Err(io::Error::new(
56 io::ErrorKind::InvalidInput,
57 format!("can only seek to multiples of {}", s.geometry.bytes_per_sector)
58 ))
59 } else {
60 Ok(())
61 }
62 }
63
64 let mut dist = LARGE_INTEGER::default();
65 let mut new_pos = LARGE_INTEGER::default();
66
67 let res = match pos {
68 SeekFrom::Start(p) => {
69 check_pos(self, p)?;
70 unsafe {
71 *dist.QuadPart_mut() = p as i64;
72 fs::SetFilePointerEx(self.handle, dist, &mut new_pos, FILE_BEGIN)
73 }
74 },
75 SeekFrom::Current(p) => {
76 unsafe {
77 *dist.QuadPart_mut() = p;
78 fs::SetFilePointerEx(self.handle, dist, &mut new_pos, FILE_CURRENT)
79 }
80 },
81 SeekFrom::End(p) => {
82 let p = min(0, p); return self.seek(SeekFrom::Start((self.size() as i128 + p as i128) as u64));
85 }
86 };
87
88 if res == 0 {
89 Err(io::Error::new(
90 io::ErrorKind::Other,
91 format!("Could not seek: error code {} (did you respect sector boundaries?)", win32::last_error())
92 ))
93 } else {
94 Ok(unsafe { *new_pos.QuadPart() } as u64)
95 }
96 }
97 }
98
99 impl Drop for $type {
100 fn drop(&mut self) {
101 unsafe {
102 CloseHandle(self.handle);
103 }
104 }
105 }
106 )+
107 }
108}
109
110macro_rules! impl_buffered {
111 ( $(($type:ident, $handle:ident)),+ ) => {
112 $(
113 impl $type {
114 fn go_to_sector(&mut self, sector_num: u64) -> io::Result<()> {
118 if sector_num == self.current_sector_num {
119 return Ok(());
120 }
121 let sector_num = min(sector_num, self.geometry.sectors());
122 let sector_size = self.$handle.geometry.bytes_per_sector as u64;
123 let sector_pos = sector_num * sector_size;
124 self.$handle.seek(SeekFrom::Start(sector_pos))?;
125
126 let max_pos = self.size();
128 let next_sector_len = min(sector_size, max_pos - sector_pos);
129 let mut sector = vec![0; next_sector_len as usize];
130 self.$handle.read_exact(&mut sector)?;
131
132 self.current_sector = Cursor::new(sector);
133 self.current_sector_num = sector_num;
134
135 Ok(())
136 }
137 }
138
139 impl Read for $type {
140 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
141 if self.current_sector.position() == self.geometry.bytes_per_sector as u64 {
142 self.go_to_sector(self.current_sector_num + 1)?;
143 }
144
145 self.current_sector.read(buf)
146 }
147 }
148
149 impl Seek for $type {
150 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
151 match pos {
152 SeekFrom::Start(p) => {
153 let sector = p / self.geometry.bytes_per_sector as u64;
154 self.go_to_sector(sector)?;
155 self.current_sector.seek(SeekFrom::Start(p % self.geometry.bytes_per_sector as u64))?;
156 },
157 SeekFrom::End(p) => {
158 let p = min(0, p); let end = self.size() as i128;
160 let sector = (end + p as i128) / self.geometry.bytes_per_sector as i128;
161 self.go_to_sector(sector as u64)?;
162
163 let target_pos = (end + p as i128) - sector * self.geometry.bytes_per_sector as i128;
164 self.current_sector.seek(SeekFrom::Start(target_pos as u64))?;
165 },
166 SeekFrom::Current(p) => {
167 let current = (self.current_sector_num * self.geometry.bytes_per_sector as u64 + self.current_sector.position()) as i128;
168 let sector = (current + p as i128) / self.geometry.bytes_per_sector as i128;
169 self.go_to_sector(sector as u64)?;
170
171 let target_pos = (current + p as i128) - sector * self.geometry.bytes_per_sector as i128;
172 self.current_sector.seek(SeekFrom::Start(target_pos as u64))?;
173 }
174 }
175
176 Ok(self.current_sector_num * self.geometry.bytes_per_sector as u64 + self.current_sector.position())
177 }
178 }
179 )+
180 }
181}