|
1 | 1 | // Copyright (c) 2022-present INESC-ID. |
2 | 2 | // Distributed under the MIT license that can be found in the LICENSE file. |
3 | 3 |
|
4 | | -use crate::{AsPointer, Ptr, Value}; |
| 4 | +use crate::{AnyPtr, AsPointer, Ptr, Value}; |
5 | 5 | use std::cell::{RefCell, UnsafeCell}; |
6 | 6 | use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; |
7 | 7 | use std::rc::Rc; |
@@ -58,3 +58,83 @@ pub unsafe fn cout_unsafe() -> *mut std::fs::File { |
58 | 58 | pub unsafe fn cerr_unsafe() -> *mut std::fs::File { |
59 | 59 | UNSAFE_STDERR.with(UnsafeCell::get) |
60 | 60 | } |
| 61 | + |
| 62 | +pub fn fread_refcount(a0: AnyPtr, a1: u64, a2: u64, a3: Ptr<::std::fs::File>) -> u64 { |
| 63 | + let total = a1.saturating_mul(a2) as usize; |
| 64 | + let mut dst = a0 |
| 65 | + .cast::<u8>() |
| 66 | + .expect("fread: only supporting u8 pointers") |
| 67 | + .clone(); |
| 68 | + |
| 69 | + let f = (*a3.upgrade().deref()) |
| 70 | + .try_clone() |
| 71 | + .expect("try_clone failed"); |
| 72 | + let mut reader = std::io::BufReader::with_capacity(64 * 1024, f); |
| 73 | + |
| 74 | + let mut read_bytes: usize = 0; |
| 75 | + let mut buffer: [u8; 8192] = [0; 8192]; |
| 76 | + |
| 77 | + while read_bytes < total { |
| 78 | + let remaining = total - read_bytes; |
| 79 | + let to_read = std::cmp::min(buffer.len(), remaining); |
| 80 | + |
| 81 | + let n = match std::io::Read::read(&mut reader, &mut buffer[..to_read]) { |
| 82 | + Ok(0) => break, |
| 83 | + Ok(n) => n, |
| 84 | + Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue, |
| 85 | + Err(e) => panic!("Unhandled error in fread: {e}"), |
| 86 | + }; |
| 87 | + |
| 88 | + for &byte in &buffer[..n] { |
| 89 | + dst.write(byte); |
| 90 | + dst = dst.offset(1); |
| 91 | + } |
| 92 | + |
| 93 | + read_bytes += n; |
| 94 | + } |
| 95 | + |
| 96 | + (read_bytes / a1 as usize) as u64 |
| 97 | +} |
| 98 | + |
| 99 | +/// # Safety |
| 100 | +/// |
| 101 | +/// `a0` must point to a writable buffer of at least `a1 * a2` bytes, and `a3` |
| 102 | +/// must point to a valid, open `std::fs::File`. |
| 103 | +pub unsafe fn fread_unsafe( |
| 104 | + a0: *mut ::std::ffi::c_void, |
| 105 | + a1: u64, |
| 106 | + a2: u64, |
| 107 | + a3: *mut ::std::fs::File, |
| 108 | +) -> u64 { |
| 109 | + let total = a1.saturating_mul(a2) as usize; |
| 110 | + let mut dst = a0 as *mut u8; |
| 111 | + |
| 112 | + let f = unsafe { (*a3).try_clone().expect("try_clone failed") }; |
| 113 | + let mut reader = std::io::BufReader::with_capacity(64 * 1024, f); |
| 114 | + |
| 115 | + let mut read_bytes: usize = 0; |
| 116 | + let mut buffer: [u8; 8192] = [0; 8192]; |
| 117 | + |
| 118 | + while read_bytes < total { |
| 119 | + let remaining = total - read_bytes; |
| 120 | + let to_read = std::cmp::min(buffer.len(), remaining); |
| 121 | + |
| 122 | + let n = match std::io::Read::read(&mut reader, &mut buffer[..to_read]) { |
| 123 | + Ok(0) => break, |
| 124 | + Ok(n) => n, |
| 125 | + Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue, |
| 126 | + Err(e) => panic!("Unhandled error in fread: {e}"), |
| 127 | + }; |
| 128 | + |
| 129 | + for &byte in &buffer[..n] { |
| 130 | + unsafe { |
| 131 | + *dst = byte; |
| 132 | + dst = dst.offset(1); |
| 133 | + } |
| 134 | + } |
| 135 | + |
| 136 | + read_bytes += n; |
| 137 | + } |
| 138 | + |
| 139 | + (read_bytes / a1 as usize) as u64 |
| 140 | +} |
0 commit comments