1use crate::bitmap::BitmapSlice;
7use crate::volatile_memory::copy_slice_impl::{copy_from_volatile_slice, copy_to_volatile_slice};
8use crate::{VolatileMemoryError, VolatileSlice};
9use std::io::{Cursor, ErrorKind};
10
11#[cfg(feature = "rawfd")]
12use std::io::Stdout;
13
14#[cfg(feature = "rawfd")]
15use std::os::fd::{AsFd, AsRawFd, BorrowedFd};
16
17macro_rules! retry_eintr {
18 ($io_call: expr) => {
19 loop {
20 let r = $io_call;
21
22 if let Err(crate::VolatileMemoryError::IOError(ref err)) = r {
23 if err.kind() == std::io::ErrorKind::Interrupted {
24 continue;
25 }
26 }
27
28 break r;
29 }
30 };
31}
32
33pub(crate) use retry_eintr;
34
35pub trait ReadVolatile {
43 fn read_volatile<B: BitmapSlice>(
48 &mut self,
49 buf: &mut VolatileSlice<B>,
50 ) -> Result<usize, VolatileMemoryError>;
51
52 fn read_exact_volatile<B: BitmapSlice>(
57 &mut self,
58 buf: &mut VolatileSlice<B>,
59 ) -> Result<(), VolatileMemoryError> {
60 let mut partial_buf = buf.offset(0)?;
63
64 while !partial_buf.is_empty() {
65 match retry_eintr!(self.read_volatile(&mut partial_buf)) {
66 Ok(0) => {
67 return Err(VolatileMemoryError::IOError(std::io::Error::new(
68 ErrorKind::UnexpectedEof,
69 "failed to fill whole buffer",
70 )))
71 }
72 Ok(bytes_read) => partial_buf = partial_buf.offset(bytes_read)?,
73 Err(err) => return Err(err),
74 }
75 }
76
77 Ok(())
78 }
79}
80
81pub trait WriteVolatile {
89 fn write_volatile<B: BitmapSlice>(
94 &mut self,
95 buf: &VolatileSlice<B>,
96 ) -> Result<usize, VolatileMemoryError>;
97
98 fn write_all_volatile<B: BitmapSlice>(
103 &mut self,
104 buf: &VolatileSlice<B>,
105 ) -> Result<(), VolatileMemoryError> {
106 let mut partial_buf = buf.offset(0)?;
109
110 while !partial_buf.is_empty() {
111 match retry_eintr!(self.write_volatile(&partial_buf)) {
112 Ok(0) => {
113 return Err(VolatileMemoryError::IOError(std::io::Error::new(
114 ErrorKind::WriteZero,
115 "failed to write whole buffer",
116 )))
117 }
118 Ok(bytes_written) => partial_buf = partial_buf.offset(bytes_written)?,
119 Err(err) => return Err(err),
120 }
121 }
122
123 Ok(())
124 }
125}
126
127macro_rules! impl_read_write_volatile_for_raw_fd {
133 ($raw_fd_ty:ty) => {
134 #[cfg(feature = "rawfd")]
135 impl ReadVolatile for $raw_fd_ty {
136 fn read_volatile<B: BitmapSlice>(
137 &mut self,
138 buf: &mut VolatileSlice<B>,
139 ) -> Result<usize, VolatileMemoryError> {
140 read_volatile_raw_fd(self.as_fd(), buf)
141 }
142 }
143
144 #[cfg(feature = "rawfd")]
145 impl ReadVolatile for &$raw_fd_ty {
146 fn read_volatile<B: BitmapSlice>(
147 &mut self,
148 buf: &mut VolatileSlice<B>,
149 ) -> Result<usize, VolatileMemoryError> {
150 read_volatile_raw_fd(self.as_fd(), buf)
151 }
152 }
153
154 #[cfg(feature = "rawfd")]
155 impl ReadVolatile for &mut $raw_fd_ty {
156 fn read_volatile<B: BitmapSlice>(
157 &mut self,
158 buf: &mut VolatileSlice<B>,
159 ) -> Result<usize, VolatileMemoryError> {
160 read_volatile_raw_fd(self.as_fd(), buf)
161 }
162 }
163
164 #[cfg(feature = "rawfd")]
165 impl WriteVolatile for $raw_fd_ty {
166 fn write_volatile<B: BitmapSlice>(
167 &mut self,
168 buf: &VolatileSlice<B>,
169 ) -> Result<usize, VolatileMemoryError> {
170 write_volatile_raw_fd(self.as_fd(), buf)
171 }
172 }
173
174 #[cfg(feature = "rawfd")]
175 impl WriteVolatile for &$raw_fd_ty {
176 fn write_volatile<B: BitmapSlice>(
177 &mut self,
178 buf: &VolatileSlice<B>,
179 ) -> Result<usize, VolatileMemoryError> {
180 write_volatile_raw_fd(self.as_fd(), buf)
181 }
182 }
183
184 #[cfg(feature = "rawfd")]
185 impl WriteVolatile for &mut $raw_fd_ty {
186 fn write_volatile<B: BitmapSlice>(
187 &mut self,
188 buf: &VolatileSlice<B>,
189 ) -> Result<usize, VolatileMemoryError> {
190 write_volatile_raw_fd(self.as_fd(), buf)
191 }
192 }
193 };
194}
195
196#[cfg(feature = "rawfd")]
197impl WriteVolatile for Stdout {
198 fn write_volatile<B: BitmapSlice>(
199 &mut self,
200 buf: &VolatileSlice<B>,
201 ) -> Result<usize, VolatileMemoryError> {
202 write_volatile_raw_fd(self.as_fd(), buf)
203 }
204}
205
206#[cfg(feature = "rawfd")]
207impl WriteVolatile for &Stdout {
208 fn write_volatile<B: BitmapSlice>(
209 &mut self,
210 buf: &VolatileSlice<B>,
211 ) -> Result<usize, VolatileMemoryError> {
212 write_volatile_raw_fd(self.as_fd(), buf)
213 }
214}
215
216impl_read_write_volatile_for_raw_fd!(std::fs::File);
217impl_read_write_volatile_for_raw_fd!(std::net::TcpStream);
218impl_read_write_volatile_for_raw_fd!(std::os::unix::net::UnixStream);
219impl_read_write_volatile_for_raw_fd!(std::os::fd::OwnedFd);
220impl_read_write_volatile_for_raw_fd!(std::os::fd::BorrowedFd<'_>);
221
222#[cfg(feature = "rawfd")]
227fn read_volatile_raw_fd(
228 raw_fd: BorrowedFd<'_>,
229 buf: &mut VolatileSlice<impl BitmapSlice>,
230) -> Result<usize, VolatileMemoryError> {
231 let fd = raw_fd.as_raw_fd();
232 let guard = buf.ptr_guard_mut();
233
234 let dst = guard.as_ptr().cast::<libc::c_void>();
235
236 let bytes_read = unsafe { libc::read(fd, dst, buf.len()) };
240
241 if bytes_read < 0 {
242 buf.bitmap().mark_dirty(0, buf.len());
244
245 Err(VolatileMemoryError::IOError(std::io::Error::last_os_error()))
246 } else {
247 let bytes_read = bytes_read.try_into().unwrap();
248 buf.bitmap().mark_dirty(0, bytes_read);
249 Ok(bytes_read)
250 }
251}
252
253#[cfg(feature = "rawfd")]
258fn write_volatile_raw_fd(
259 raw_fd: BorrowedFd<'_>,
260 buf: &VolatileSlice<impl BitmapSlice>,
261) -> Result<usize, VolatileMemoryError> {
262 let fd = raw_fd.as_raw_fd();
263 let guard = buf.ptr_guard();
264
265 let src = guard.as_ptr().cast::<libc::c_void>();
266
267 let bytes_written = unsafe { libc::write(fd, src, buf.len()) };
271
272 if bytes_written < 0 {
273 Err(VolatileMemoryError::IOError(std::io::Error::last_os_error()))
274 } else {
275 Ok(bytes_written.try_into().unwrap())
276 }
277}
278
279impl WriteVolatile for &mut [u8] {
280 fn write_volatile<B: BitmapSlice>(
281 &mut self,
282 buf: &VolatileSlice<B>,
283 ) -> Result<usize, VolatileMemoryError> {
284 let total = buf.len().min(self.len());
285
286 let written = unsafe { copy_from_volatile_slice(self.as_mut_ptr(), buf, total) };
295
296 *self = std::mem::take(self).split_at_mut(written).1;
298
299 Ok(written)
300 }
301
302 fn write_all_volatile<B: BitmapSlice>(
303 &mut self,
304 buf: &VolatileSlice<B>,
305 ) -> Result<(), VolatileMemoryError> {
306 if self.write_volatile(buf)? == buf.len() {
308 Ok(())
309 } else {
310 Err(VolatileMemoryError::IOError(std::io::Error::new(
311 ErrorKind::WriteZero,
312 "failed to write whole buffer",
313 )))
314 }
315 }
316}
317
318impl ReadVolatile for &[u8] {
319 fn read_volatile<B: BitmapSlice>(
320 &mut self,
321 buf: &mut VolatileSlice<B>,
322 ) -> Result<usize, VolatileMemoryError> {
323 let total = buf.len().min(self.len());
324
325 let read = unsafe { copy_to_volatile_slice(buf, self.as_ptr(), total) };
334
335 *self = self.split_at(read).1;
337
338 Ok(read)
339 }
340
341 fn read_exact_volatile<B: BitmapSlice>(
342 &mut self,
343 buf: &mut VolatileSlice<B>,
344 ) -> Result<(), VolatileMemoryError> {
345 if buf.len() > self.len() {
347 return Err(VolatileMemoryError::IOError(std::io::Error::new(
348 ErrorKind::UnexpectedEof,
349 "failed to fill whole buffer",
350 )));
351 }
352
353 self.read_volatile(buf).map(|_| ())
354 }
355}
356
357impl WriteVolatile for Vec<u8> {
360 fn write_volatile<B: BitmapSlice>(
361 &mut self,
362 buf: &VolatileSlice<B>,
363 ) -> Result<usize, VolatileMemoryError> {
364 let count = buf.len();
365 self.reserve(count);
366 let len = self.len();
367
368 unsafe {
379 let copied_len = copy_from_volatile_slice(self.as_mut_ptr().add(len), buf, count);
380
381 assert_eq!(copied_len, count);
382 self.set_len(len + count);
383 }
384 Ok(count)
385 }
386}
387
388impl<T> ReadVolatile for Cursor<T>
391where
392 T: AsRef<[u8]>,
393{
394 fn read_volatile<B: BitmapSlice>(
395 &mut self,
396 buf: &mut VolatileSlice<B>,
397 ) -> Result<usize, VolatileMemoryError> {
398 let inner = self.get_ref().as_ref();
399 let len = self.position().min(inner.len() as u64);
400 let n = ReadVolatile::read_volatile(&mut &inner[(len as usize)..], buf)?;
401 self.set_position(self.position() + n as u64);
402 Ok(n)
403 }
404
405 fn read_exact_volatile<B: BitmapSlice>(
406 &mut self,
407 buf: &mut VolatileSlice<B>,
408 ) -> Result<(), VolatileMemoryError> {
409 let inner = self.get_ref().as_ref();
410 let n = buf.len();
411 let len = self.position().min(inner.len() as u64);
412 ReadVolatile::read_exact_volatile(&mut &inner[(len as usize)..], buf)?;
413 self.set_position(self.position() + n as u64);
414 Ok(())
415 }
416}
417
418impl WriteVolatile for Cursor<&mut [u8]> {
419 fn write_volatile<B: BitmapSlice>(
420 &mut self,
421 buf: &VolatileSlice<B>,
422 ) -> Result<usize, VolatileMemoryError> {
423 let pos = self.position().min(self.get_ref().len() as u64);
424 let n = WriteVolatile::write_volatile(&mut &mut self.get_mut()[(pos as usize)..], buf)?;
425 self.set_position(self.position() + n as u64);
426 Ok(n)
427 }
428
429 }
432
433#[cfg(test)]
434mod tests {
435 use crate::io::{ReadVolatile, WriteVolatile};
436 use crate::{VolatileMemoryError, VolatileSlice};
437 use std::io::{Cursor, ErrorKind};
438 #[cfg(feature = "rawfd")]
439 use std::io::{Read, Seek, Write};
440 #[cfg(feature = "rawfd")]
441 use vmm_sys_util::tempfile::TempFile;
442
443 fn read_4_bytes_to_5_byte_memory(source: Vec<u8>, expected_output: [u8; 5]) {
445 let mut memory = vec![0u8; 5];
447
448 assert_eq!(
449 (&source[..])
450 .read_volatile(&mut VolatileSlice::from(&mut memory[..4]))
451 .unwrap(),
452 source.len().min(4)
453 );
454 assert_eq!(&memory, &expected_output);
455
456 let mut memory = vec![0u8; 5];
458 let result = (&source[..]).read_exact_volatile(&mut VolatileSlice::from(&mut memory[..4]));
459
460 if source.len() < 4 {
463 match result.unwrap_err() {
464 VolatileMemoryError::IOError(ioe) => {
465 assert_eq!(ioe.kind(), ErrorKind::UnexpectedEof)
466 }
467 err => panic!("{:?}", err),
468 }
469 assert_eq!(memory, vec![0u8; 5]);
470 } else {
471 result.unwrap();
472 assert_eq!(&memory, &expected_output);
473 }
474 }
475
476 #[cfg(all(feature = "rawfd", not(miri)))]
478 fn read_4_bytes_from_file(source: Vec<u8>, expected_output: [u8; 5]) {
479 let mut temp_file = TempFile::new().unwrap().into_file();
480 temp_file.write_all(source.as_ref()).unwrap();
481 temp_file.rewind().unwrap();
482
483 let mut memory = vec![0u8; 5];
485
486 assert_eq!(
487 temp_file
488 .read_volatile(&mut VolatileSlice::from(&mut memory[..4]))
489 .unwrap(),
490 source.len().min(4)
491 );
492 assert_eq!(&memory, &expected_output);
493
494 temp_file.rewind().unwrap();
495
496 let mut memory = vec![0u8; 5];
498
499 let read_exact_result =
500 temp_file.read_exact_volatile(&mut VolatileSlice::from(&mut memory[..4]));
501
502 if source.len() < 4 {
503 read_exact_result.unwrap_err();
504 } else {
505 read_exact_result.unwrap();
506 }
507 assert_eq!(&memory, &expected_output);
508 }
509
510 #[test]
511 fn test_read_volatile() {
512 let test_cases = [
513 (vec![1u8, 2], [1u8, 2, 0, 0, 0]),
514 (vec![1, 2, 3, 4], [1, 2, 3, 4, 0]),
515 (vec![5, 6, 7, 8, 9], [5, 6, 7, 8, 0]),
517 ];
518
519 for (input, output) in test_cases {
520 read_4_bytes_to_5_byte_memory(input.clone(), output);
521 #[cfg(all(feature = "rawfd", not(miri)))]
522 read_4_bytes_from_file(input, output);
523 }
524 }
525
526 fn write_4_bytes_to_5_byte_vec(mut source: Vec<u8>, expected_result: [u8; 5]) {
528 let mut memory = vec![0u8; 5];
529
530 assert_eq!(
532 (&mut memory[..4])
533 .write_volatile(&VolatileSlice::from(source.as_mut_slice()))
534 .unwrap(),
535 source.len().min(4)
536 );
537 assert_eq!(&memory, &expected_result);
538
539 let mut memory = vec![0u8; 5];
541
542 let result =
543 (&mut memory[..4]).write_all_volatile(&VolatileSlice::from(source.as_mut_slice()));
544
545 if source.len() > 4 {
546 match result.unwrap_err() {
547 VolatileMemoryError::IOError(ioe) => {
548 assert_eq!(ioe.kind(), ErrorKind::WriteZero)
549 }
550 err => panic!("{:?}", err),
551 }
552 assert_eq!(&memory, &expected_result);
555 } else {
556 result.unwrap();
557 assert_eq!(&memory, &expected_result);
558 }
559 }
560
561 #[cfg(all(feature = "rawfd", not(miri)))]
563 fn write_5_bytes_to_file(mut source: Vec<u8>) {
564 let mut temp_file = TempFile::new().unwrap().into_file();
566
567 temp_file
568 .write_volatile(&VolatileSlice::from(source.as_mut_slice()))
569 .unwrap();
570 temp_file.rewind().unwrap();
571
572 let mut written = vec![0u8; source.len()];
573 temp_file.read_exact(written.as_mut_slice()).unwrap();
574
575 assert_eq!(source, written);
576 assert_eq!(temp_file.read(&mut [0u8]).unwrap(), 0);
578
579 let mut temp_file = TempFile::new().unwrap().into_file();
581
582 temp_file
583 .write_all_volatile(&VolatileSlice::from(source.as_mut_slice()))
584 .unwrap();
585 temp_file.rewind().unwrap();
586
587 let mut written = vec![0u8; source.len()];
588 temp_file.read_exact(written.as_mut_slice()).unwrap();
589
590 assert_eq!(source, written);
591 assert_eq!(temp_file.read(&mut [0u8]).unwrap(), 0);
593 }
594
595 #[test]
596 fn test_write_volatile() {
597 let test_cases = [
598 (vec![1u8, 2], [1u8, 2, 0, 0, 0]),
599 (vec![1, 2, 3, 4], [1, 2, 3, 4, 0]),
600 (vec![5, 6, 7, 8, 9], [5, 6, 7, 8, 0]),
602 ];
603
604 for (input, output) in test_cases {
605 write_4_bytes_to_5_byte_vec(input.clone(), output);
606 #[cfg(all(feature = "rawfd", not(miri)))]
607 write_5_bytes_to_file(input);
608 }
609 }
610
611 #[test]
612 fn test_read_volatile_for_cursor() {
613 let read_buffer = [1, 2, 3, 4, 5, 6, 7];
614 let mut output = vec![0u8; 5];
615
616 let mut cursor = Cursor::new(read_buffer);
617
618 assert_eq!(
620 cursor
621 .read_volatile(&mut VolatileSlice::from(&mut output[..4]))
622 .unwrap(),
623 4
624 );
625 assert_eq!(output, vec![1, 2, 3, 4, 0]);
626
627 assert_eq!(
629 cursor
630 .read_volatile(&mut VolatileSlice::from(&mut output[..4]))
631 .unwrap(),
632 3
633 );
634 assert_eq!(output, vec![5, 6, 7, 4, 0]);
635
636 cursor.set_position(0);
637 cursor
639 .read_exact_volatile(&mut VolatileSlice::from(&mut output[..4]))
640 .unwrap();
641 assert_eq!(output, vec![1, 2, 3, 4, 0]);
642
643 assert!(cursor
646 .read_exact_volatile(&mut VolatileSlice::from(&mut output[..4]))
647 .is_err());
648 assert_eq!(output, vec![1, 2, 3, 4, 0]);
649 }
650
651 #[test]
652 fn test_write_volatile_for_cursor() {
653 let mut write_buffer = vec![0u8; 7];
654 let mut input = [1, 2, 3, 4];
655
656 let mut cursor = Cursor::new(write_buffer.as_mut_slice());
657
658 assert_eq!(
660 cursor
661 .write_volatile(&VolatileSlice::from(input.as_mut_slice()))
662 .unwrap(),
663 4
664 );
665 assert_eq!(cursor.get_ref(), &[1, 2, 3, 4, 0, 0, 0]);
666
667 assert_eq!(
669 cursor
670 .write_volatile(&VolatileSlice::from(input.as_mut_slice()))
671 .unwrap(),
672 3
673 );
674 assert_eq!(cursor.get_ref(), &[1, 2, 3, 4, 1, 2, 3]);
675 }
676
677 #[test]
678 fn test_write_volatile_for_vec() {
679 let mut write_buffer = Vec::new();
680 let mut input = [1, 2, 3, 4];
681
682 assert_eq!(
683 write_buffer
684 .write_volatile(&VolatileSlice::from(input.as_mut_slice()))
685 .unwrap(),
686 4
687 );
688
689 assert_eq!(&write_buffer, &input);
690 }
691}